ethertap.c (3334B)
1 /* 2 * ethertap: tap device ethernet driver 3 * copyright © 2008 erik quanstrom 4 * copyright © 2010 Tully Gray 5 * copyright © 2010 Jesus Galan Lopez 6 */ 7 8 #include "u.h" 9 #include "lib.h" 10 #include "mem.h" 11 #include "dat.h" 12 #include "fns.h" 13 #include "io.h" 14 #include "error.h" 15 #include "netif.h" 16 #include "etherif.h" 17 #include "vether.h" 18 19 #if defined(__APPLE__) 20 #include <sys/socket.h> 21 #endif 22 #include <net/if.h> 23 #include <sys/ioctl.h> 24 25 #ifdef linux 26 #include <netpacket/packet.h> 27 #include <linux/if_tun.h> 28 #elif defined(__FreeBSD__) 29 #include <net/if_tun.h> 30 #endif 31 32 typedef struct Ctlr Ctlr; 33 struct Ctlr { 34 int fd; 35 int txerrs; 36 uchar ea[Eaddrlen]; 37 }; 38 39 static uchar anyea[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}; 40 41 #ifdef linux 42 static int 43 opentap(char *dev) 44 { 45 int fd; 46 char *tap0 = "tap0"; 47 struct ifreq ifr; 48 49 if(dev == nil) 50 dev = tap0; 51 if((fd = open("/dev/net/tun", O_RDWR)) < 0) 52 return -1; 53 memset(&ifr, 0, sizeof ifr); 54 strncpy(ifr.ifr_name, dev, sizeof ifr.ifr_name); 55 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 56 if(ioctl(fd, TUNSETIFF, &ifr) < 0){ 57 close(fd); 58 return -1; 59 } 60 return fd; 61 } 62 #elif defined(__FreeBSD__) 63 static int 64 opentap(char *dev) 65 { 66 int fd; 67 struct stat s; 68 69 if((fd = open("/dev/tap", O_RDWR)) < 0) 70 return -1; 71 return fd; 72 } 73 #elif defined(__APPLE__) 74 static int 75 opentap(char *dev) 76 { 77 int fd; 78 char *tap0 = "/dev/tap0"; 79 80 if(dev == nil) 81 dev = tap0; 82 if((fd = open(dev, O_RDWR)) < 0) { 83 iprint("tap: open failed with: %d\n", errno); 84 return -1; 85 } 86 return fd; 87 } 88 #endif 89 90 static int 91 setup(char *dev) 92 { 93 return opentap(dev); 94 } 95 96 Block* 97 tappkt(Ctlr *c) 98 { 99 int n; 100 Block *b; 101 102 b = allocb(1514); 103 for(;;){ 104 n = read(c->fd, b->rp, BALLOC(b)); 105 if(n <= 0) 106 panic("fd %d read %d", c->fd, n); 107 if(memcmp(b->rp + 0, anyea, 6) == 0 108 || memcmp(b->rp + 0, c->ea, 6) == 0) 109 break; 110 } 111 b->wp += n; 112 b->flag |= Btcpck|Budpck|Bpktck; 113 return b; 114 } 115 116 static void 117 taprecvkproc(void *v) 118 { 119 Block *b; 120 Ether *e; 121 122 e = v; 123 while((b = tappkt(e->ctlr))) 124 etheriq(e, b, 1); 125 pexit("read fail", 1); 126 } 127 128 static void 129 taptransmit(Ether* e) 130 { 131 Block *b, *h; 132 Ctlr *c; 133 134 c = e->ctlr; 135 while ((b = qget(e->oq)) != nil) { 136 if(memcmp(b->rp + 6, anyea, 6) == 0 || 137 memcmp(b->rp + 0, c->ea, 6) == 0){ 138 h = allocb(BLEN(b)); 139 memcpy(h->rp, b->wp, BLEN(b)); 140 h->wp += BLEN(b); 141 h->flag |= Btcpck|Budpck|Bpktck; 142 etheriq(e, h, 1); 143 } 144 if(write(c->fd, b->rp, BLEN(b)) == -1) 145 c->txerrs++; 146 freeb(b); 147 } 148 } 149 150 static long 151 tapifstat(Ether *e, void *a, long n, ulong offset) 152 { 153 char buf[128]; 154 Ctlr *c; 155 156 c = a; 157 snprint(buf, sizeof buf, "txerrors: %lud\n", c->txerrs); 158 return readstr(offset, a, n, buf); 159 } 160 161 static void 162 tapattach(Ether* e) 163 { 164 kproc("taprecv", taprecvkproc, e); 165 } 166 167 static int 168 tappnp(Ether* e) 169 { 170 Ctlr c; 171 static int cve = 0; 172 173 while(cve < MaxEther && ve[cve].tap == 0) 174 cve++; 175 if(cve == MaxEther || ve[cve].dev == nil) 176 return -1; 177 178 memset(&c, 0, sizeof c); 179 c.fd = setup(ve[cve].dev); 180 memcpy(c.ea, ve[cve].ea, Eaddrlen); 181 if(c.fd== -1){ 182 iprint("ve: tap failed to initialize\n"); 183 cve++; 184 return -1; 185 } 186 e->ctlr = malloc(sizeof c); 187 memcpy(e->ctlr, &c, sizeof c); 188 e->tbdf = BUSUNKNOWN; 189 memcpy(e->ea, ve[cve].ea, Eaddrlen); 190 e->attach = tapattach; 191 e->transmit = taptransmit; 192 e->ifstat = tapifstat; 193 e->ni.arg = e; 194 e->ni.link = 1; 195 cve++; 196 return 0; 197 } 198 199 void 200 ethertaplink(void) 201 { 202 addethercard("tap", tappnp); 203 }