etherpcap.c (3312B)
1 /* 2 * etherpcap - portable Virtual Ethernet driver for 9vx. 3 * 4 * Copyright (c) 2008 Devon H. O'Dell 5 * copyright © 2008 erik quanstrom 6 * copyright © 2010 Jesus Galan Lopez 7 * 8 * Released under 2-clause BSD license. 9 */ 10 11 #include "u.h" 12 13 #include "lib.h" 14 #include "mem.h" 15 #include "dat.h" 16 #include "fns.h" 17 #include "io.h" 18 #include "error.h" 19 #include "netif.h" 20 #include "etherif.h" 21 #include "vether.h" 22 23 #include <pcap.h> 24 25 static uvlong txerrs; 26 27 extern int eafrom(char *ma, uchar ea[6]); 28 29 typedef struct Ctlr Ctlr; 30 struct Ctlr { 31 pcap_t *pd; 32 }; 33 34 static void * 35 veerror(char* err) 36 { 37 iprint("ve: %s\n", err); 38 return nil; 39 } 40 41 static pcap_t * 42 setup(char *dev, uchar *ea) 43 { 44 char filter[30]; 45 char errbuf[PCAP_ERRBUF_SIZE]; 46 pcap_t *pd; 47 struct bpf_program prog; 48 bpf_u_int32 net; 49 bpf_u_int32 mask; 50 51 if(sprint(filter, "ether dst %2.2ux:%2.2ux:%2.2ux:%2.2ux:%2.2ux:%2.2ux", 52 ea[0], ea[1], ea[2],ea[3], ea[4], ea[5]) == -1) 53 return veerror("cannot create pcap filter"); 54 55 if ((pd = pcap_open_live(dev, 65000, 1, 1, errbuf)) == nil){ 56 // try to find a device 57 if ((dev = pcap_lookupdev(errbuf)) == nil) 58 return veerror("cannot find network device"); 59 if ((pd = pcap_open_live(dev, 65000, 1, 1, errbuf)) == nil) 60 return nil; 61 } 62 63 pcap_lookupnet(dev, &net, &mask, errbuf); 64 pcap_compile(pd, &prog, filter, 0, net); 65 66 if (pcap_setfilter(pd, &prog) == -1) 67 return nil; 68 69 pcap_freecode(&prog); 70 71 return pd; 72 } 73 74 static Block * 75 pcappkt(Ctlr *c) 76 { 77 struct pcap_pkthdr hdr; 78 uchar *p; 79 Block *b; 80 81 while ((p = pcap_next(c->pd, &hdr)) == nil); 82 83 b = allocb(hdr.caplen); 84 memcpy(b->rp, p, hdr.caplen); 85 b->wp += hdr.caplen; 86 b->flag |= Btcpck|Budpck|Bpktck; 87 88 /* 89 iprint("+++++++++++ packet %d (len %d):\n", ++fn, hdr.caplen); 90 int i=0; uchar* u; 91 static int fn=0; 92 93 for(u=b->rp; u<b->wp; u++){ 94 if (i%16 == 0) iprint("%.4ux", i); 95 if (i%8 == 0) iprint(" "); 96 iprint("%2.2ux ", *u); 97 if (++i%16 == 0) iprint("\n"); 98 } 99 iprint("\n-------------\n"); 100 */ 101 102 return b; 103 104 } 105 106 static void 107 pcaprecvkproc(void *v) 108 { 109 Ether *e; 110 Block *b; 111 112 e = v; 113 while ((b = pcappkt(e->ctlr))) 114 if (b != nil) 115 etheriq(e, b, 1); 116 } 117 118 static void 119 pcaptransmit(Ether* e) 120 { 121 const u_char *u; 122 Block *b; 123 Ctlr *c; 124 125 c = e->ctlr; 126 while ((b = qget(e->oq)) != nil) { 127 int wlen; 128 129 u = (const u_char*)b->rp; 130 131 wlen = pcap_inject(c->pd, u, BLEN(b)); 132 // iprint("injected packet len %d\n", wlen); 133 if (wlen == -1) 134 txerrs++; 135 136 freeb(b); 137 } 138 } 139 140 static long 141 pcapifstat(Ether *e, void *a, long n, ulong offset) 142 { 143 char buf[128]; 144 145 snprint(buf, sizeof buf, "txerrors: %lud\n", txerrs); 146 return readstr(offset, a, n, buf); 147 } 148 149 static void 150 pcapattach(Ether* e) 151 { 152 kproc("pcaprecv", pcaprecvkproc, e); 153 } 154 155 static int 156 pcappnp(Ether* e) 157 { 158 Ctlr c; 159 static int cve = 0; 160 161 while(cve < MaxEther && ve[cve].tap == 1) 162 cve++; 163 if(cve == MaxEther || ve[cve].dev == nil) 164 return -1; 165 166 memset(&c, 0, sizeof(c)); 167 c.pd = setup(ve[cve].dev, ve[cve].ea); 168 if (c.pd == nil) { 169 iprint("ve: pcap failed to initialize\n"); 170 cve++; 171 return -1; 172 } 173 e->ctlr = malloc(sizeof(c)); 174 memcpy(e->ctlr, &c, sizeof(c)); 175 e->tbdf = BUSUNKNOWN; 176 memcpy(e->ea, ve[cve].ea, Eaddrlen); 177 e->attach = pcapattach; 178 e->transmit = pcaptransmit; 179 e->ifstat = pcapifstat; 180 e->ni.arg = e; 181 e->ni.link = 1; 182 cve++; 183 return 0; 184 } 185 186 void 187 etherpcaplink(void) 188 { 189 addethercard("pcap", pcappnp); 190 }