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 }