etherpcap.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
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 }