Mercurial > hg > index.cgi
comparison src/lwwire-packet.c @ 12:f8226a33698d
Add PACKET extension
author | Brett Gordon <beretta42@gmail.com> |
---|---|
date | Fri, 18 Nov 2016 19:51:43 -0700 |
parents | |
children | e4d98cbf95eb |
comparison
equal
deleted
inserted
replaced
11:38184ef1296d | 12:f8226a33698d |
---|---|
1 /* | |
2 Packet extension for lwwire | |
3 | |
4 Talks Layer 2, Ethernet Frames, sends them to a Linux TAP/TUN device. | |
5 | |
6 TODO: | |
7 * better (any) RXMTU and TXMTU, Queue Length handling | |
8 | |
9 */ | |
10 | |
11 #include <stdio.h> | |
12 #include "lwwire.h" | |
13 | |
14 #include <unistd.h> | |
15 #include <string.h> | |
16 #include <ctype.h> | |
17 #include <sys/ioctl.h> | |
18 #include <sys/types.h> | |
19 #include <sys/stat.h> | |
20 #include <fcntl.h> | |
21 #include <sys/socket.h> | |
22 #include <linux/if.h> | |
23 #include <linux/if_tun.h> | |
24 | |
25 | |
26 #define MAX_FRAME 1526 | |
27 static int tunfd = -1; | |
28 static char tundev[10]; | |
29 static unsigned char opacket[MAX_FRAME]; | |
30 static unsigned char packet[MAX_FRAME]; | |
31 static int tunz = -1; | |
32 static unsigned char *packet_ptr; | |
33 static int csize = 511; | |
34 static int rxmtu = 1500; | |
35 static int txmtu = 1500; | |
36 static int qlen = 10; | |
37 | |
38 /* | |
39 | |
40 NOTE: the __attribute__((used)) tags are there to prevent the functions | |
41 from being optimized out as would often be the case with functions declared | |
42 static. This could be avoided by removing the static declarations. However, | |
43 by declaring everything static except for the lwwire_register() function, | |
44 we avoid polluting the global namespace and possibly having conflicts with | |
45 other extensions. | |
46 */ | |
47 | |
48 | |
49 /* Allocate (open) a new tap device | |
50 Take symbolic name of device and tap/tun flags. Returns fd, or < 0 on | |
51 error. | |
52 */ | |
53 static int tun_alloc(char *dev, int flags) | |
54 { | |
55 struct ifreq ifr; | |
56 int fd, err; | |
57 char *clonedev = "/dev/net/tun"; | |
58 | |
59 /* open the clone device */ | |
60 if ((fd = open(clonedev, O_RDWR)) < 0) | |
61 { | |
62 perror("tun_alloc"); | |
63 return fd; | |
64 } | |
65 /* preparation of the struct ifr, of type "struct ifreq" */ | |
66 memset(&ifr, 0, sizeof(ifr)); | |
67 ifr.ifr_flags = flags; | |
68 if (*dev) | |
69 { | |
70 strncpy(ifr.ifr_name, dev, IFNAMSIZ); | |
71 } | |
72 /* try to create the device */ | |
73 if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) | |
74 { | |
75 perror("tun_alloc"); | |
76 close(fd); | |
77 return err; | |
78 } | |
79 /* write acquired tap device name back to struct */ | |
80 strcpy(dev, ifr.ifr_name); | |
81 | |
82 nonblock(fd); | |
83 return fd; | |
84 } | |
85 | |
86 | |
87 /* Tell client how many bytes to expect for the next read. */ | |
88 static int tun_proto_poll() | |
89 { | |
90 unsigned char buf[2]; | |
91 while (1) | |
92 { | |
93 if (tunz < 1) | |
94 tunz = read(tunfd, packet, MAX_FRAME); | |
95 if (tunz < rxmtu) | |
96 break; | |
97 else | |
98 tunz = 0; | |
99 } | |
100 buf[0] = (unsigned char)(tunz >> 8); | |
101 buf[1] = (unsigned char)(tunz & 0xff); | |
102 lwwire_write(buf,2); | |
103 packet_ptr = packet; | |
104 return 0; | |
105 } | |
106 | |
107 /* Drop the current packet */ | |
108 static int tun_proto_drop() | |
109 { | |
110 tunz = 0; | |
111 return 0; | |
112 } | |
113 | |
114 | |
115 /* receive *entire* frame */ | |
116 static int tun_proto_recv() | |
117 { | |
118 if (tunz < 1) | |
119 return -1; | |
120 lwwire_write(packet, tunz); | |
121 tunz = 0; | |
122 return 0; | |
123 } | |
124 | |
125 /* receive next chunk (upto 511 bytes) of frame */ | |
126 static int tun_proto_recv_chunk() | |
127 { | |
128 int s; | |
129 if (csize < tunz) | |
130 s = csize; | |
131 else | |
132 s = tunz; | |
133 lwwire_write(packet_ptr, s); | |
134 packet_ptr += s; | |
135 tunz -= s; | |
136 return 0; | |
137 } | |
138 | |
139 /* send a frame */ | |
140 static int tun_proto_send() | |
141 { | |
142 int len; | |
143 unsigned char buf[2]; | |
144 if (lwwire_read(buf, 2) < 0) | |
145 return -1; | |
146 len = (buf[0]<<8) + buf[1]; | |
147 if (lwwire_read(opacket, len) < 0) | |
148 return -1; | |
149 if (write(tunfd, opacket, len) < 0) | |
150 return -1; | |
151 return 0; | |
152 } | |
153 | |
154 | |
155 /* set/return receive mtu */ | |
156 static int tun_proto_setrxmtu() | |
157 { | |
158 unsigned char buf[2]; | |
159 if (lwwire_read(buf, 2) < 0) | |
160 return -1; | |
161 rxmtu = (buf[0]<<8) + buf[1]; | |
162 lwwire_write(buf, 2); | |
163 return 0; | |
164 } | |
165 | |
166 /* set/return transmit mtu */ | |
167 static int tun_proto_settxmtu() | |
168 { | |
169 unsigned char buf[2]; | |
170 if (lwwire_read(buf, 2) < 0) | |
171 return -1; | |
172 txmtu = (buf[0]<<8) + buf[1]; | |
173 lwwire_write(buf, 2); | |
174 return 0; | |
175 } | |
176 | |
177 /* set/return receive mtu */ | |
178 static int tun_proto_setqlen() | |
179 { | |
180 unsigned char buf[1]; | |
181 if (lwwire_read(buf, 1) < 0) | |
182 return -1; | |
183 qlen = buf[0]; | |
184 lwwire_write(buf, 1); | |
185 return 0; | |
186 } | |
187 | |
188 | |
189 | |
190 // this is called to handle an operation for this extension | |
191 // it should return nonzero if the operation code (op) is not | |
192 // supported. Otherwise, it should implement the operation codes. | |
193 __attribute__((used)) static int packet_handler(int op) | |
194 { | |
195 switch (op) | |
196 { | |
197 case 0: | |
198 return tun_proto_poll(); | |
199 case 1: | |
200 return tun_proto_recv(); | |
201 case 2: | |
202 return tun_proto_send(); | |
203 case 3: | |
204 return tun_proto_drop(); | |
205 case 4: | |
206 return tun_proto_setrxmtu(); | |
207 case 5: | |
208 return tun_proto_setqlen(); | |
209 case 6: | |
210 return tun_proto_settxmtu(); | |
211 case 7: | |
212 return tun_proto_recv_chunk(); | |
213 default: | |
214 return -1; | |
215 } | |
216 return 0; | |
217 } | |
218 | |
219 // this will be called when the extension is enabled | |
220 // return nonzero if enabling the extension cannot happen for some reason | |
221 __attribute__((used)) static int packet_enable(void) | |
222 { | |
223 if (tunfd < 0) | |
224 { | |
225 strcpy(tundev, "tap0"); | |
226 tunfd = tun_alloc(tundev, IFF_TAP | IFF_NO_PI); | |
227 if (tunfd < 0) return -1; | |
228 tunz = -1; | |
229 } | |
230 return 0; | |
231 } | |
232 | |
233 // this will be called when an extension is disabled | |
234 // if this extension cannot be disabled after it is enabled, it should return | |
235 // nonzero; otherwise, this MUST succeed | |
236 __attribute__((used)) static int packet_disable(void) | |
237 { | |
238 close(tunfd); | |
239 tunfd = -1; | |
240 return 0; | |
241 } | |
242 | |
243 // this call should do anything needed to disable the extension | |
244 // and anything special that might be needed on a protocol reset | |
245 // it will only be called if the extension is enabled when the | |
246 // reset occurs. Even if the extension isn't disablable, this call | |
247 // MUST disable it and reset things as if the extension was never | |
248 // enabled. | |
249 __attribute__((used)) static void packet_reset(void) | |
250 { | |
251 packet_disable(); | |
252 } | |
253 | |
254 int lwwire_register(void) | |
255 { | |
256 fprintf(stderr, "Registering PACKET extension\n"); | |
257 return lwwire_register_extension(0x01, packet_handler, packet_enable, packet_disable, packet_reset); | |
258 } |