aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn.c
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2011-01-26 13:15:22 +0000
committerPhilipp Tölke <toelke@in.tum.de>2011-01-26 13:15:22 +0000
commit62c64f683cce5f7521a9a49e6a1055b22da82091 (patch)
tree64072a06170ab68716322a2a294ca3b6b3647e9b /src/vpn/gnunet-helper-vpn.c
parentac6f62af65ec1d509efe6ba958ea61c6eacd5f99 (diff)
downloadgnunet-62c64f683cce5f7521a9a49e6a1055b22da82091.tar.gz
gnunet-62c64f683cce5f7521a9a49e6a1055b22da82091.zip
Documented, cleaned and indented gnunet-helper-vpn
Diffstat (limited to 'src/vpn/gnunet-helper-vpn.c')
-rw-r--r--src/vpn/gnunet-helper-vpn.c371
1 files changed, 219 insertions, 152 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c
index 1cee01c71..00eb15c6a 100644
--- a/src/vpn/gnunet-helper-vpn.c
+++ b/src/vpn/gnunet-helper-vpn.c
@@ -47,7 +47,7 @@
47/** 47/**
48 * This is in linux/include/net/ipv6.h, but not always exported... 48 * This is in linux/include/net/ipv6.h, but not always exported...
49 */ 49 */
50struct in6_ifreq 50struct in6_ifreq
51{ 51{
52 struct in6_addr ifr6_addr; 52 struct in6_addr ifr6_addr;
53 uint32_t ifr6_prefixlen; 53 uint32_t ifr6_prefixlen;
@@ -55,50 +55,52 @@ struct in6_ifreq
55}; 55};
56#endif 56#endif
57 57
58
59/** 58/**
60 * Creates a tun-interface called dev; 59 * Creates a tun-interface called dev;
61 * @param dev is asumed to point to a char[IFNAMSIZ] 60 * @param dev is asumed to point to a char[IFNAMSIZ]
62 * if *dev == '\\0', uses the name supplied by the kernel 61 * if *dev == '\\0', uses the name supplied by the kernel
63 * @return the fd to the tun or -1 on error 62 * @return the fd to the tun or -1 on error
64 */ 63 */
65static int 64static int
66init_tun (char *dev) 65init_tun (char *dev)
67{ 66{
68 struct ifreq ifr; 67 struct ifreq ifr;
69 int fd; 68 int fd;
70 69
71 if (NULL == dev) 70 if (NULL == dev)
72 { 71 {
73 errno = EINVAL; 72 errno = EINVAL;
74 return -1; 73 return -1;
75 } 74 }
76 75
77 if (-1 == (fd = open("/dev/net/tun", O_RDWR))) 76 if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
77 {
78 fprintf (stderr,
79 "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno));
80 return -1;
81 }
82
83 if (fd >= FD_SETSIZE)
78 { 84 {
79 fprintf (stderr, 85 fprintf (stderr, "Filedescriptor to large: %d", fd);
80 "Error opening `%s': %s\n",
81 "/dev/net/tun",
82 strerror(errno));
83 return -1; 86 return -1;
84 } 87 }
85 88
86 memset(&ifr, 0, sizeof(ifr)); 89 memset (&ifr, 0, sizeof (ifr));
87 ifr.ifr_flags = IFF_TUN; 90 ifr.ifr_flags = IFF_TUN;
88 91
89 if ('\0' == *dev) 92 if ('\0' == *dev)
90 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 93 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
91 94
92 if (-1 == ioctl(fd, TUNSETIFF, (void *) &ifr)) 95 if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
93 { 96 {
94 fprintf (stderr, 97 fprintf (stderr,
95 "Error with ioctl on `%s': %s\n", 98 "Error with ioctl on `%s': %s\n",
96 "/dev/net/tun", 99 "/dev/net/tun", strerror (errno));
97 strerror(errno));
98 close (fd); 100 close (fd);
99 return -1; 101 return -1;
100 } 102 }
101 strcpy(dev, ifr.ifr_name); 103 strcpy (dev, ifr.ifr_name);
102 return fd; 104 return fd;
103} 105}
104 106
@@ -111,10 +113,8 @@ init_tun (char *dev)
111 * @param prefix_len the length of the network-prefix 113 * @param prefix_len the length of the network-prefix
112 */ 114 */
113static void 115static void
114set_address6 (const char *dev, 116set_address6 (const char *dev, const char *address, unsigned long prefix_len)
115 const char *address, 117{
116 unsigned long prefix_len)
117{
118 struct ifreq ifr; 118 struct ifreq ifr;
119 struct in6_ifreq ifr6; 119 struct in6_ifreq ifr6;
120 struct sockaddr_in6 sa6; 120 struct sockaddr_in6 sa6;
@@ -122,70 +122,73 @@ set_address6 (const char *dev,
122 122
123 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) 123 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
124 { 124 {
125 fprintf (stderr, 125 fprintf (stderr, "Error creating socket: %s\n", strerror (errno));
126 "Error creating socket: %s\n",
127 strerror (errno));
128 exit (1); 126 exit (1);
129 } 127 }
130 memset (&sa6, 0, sizeof (struct sockaddr_in6)); 128 memset (&sa6, 0, sizeof (struct sockaddr_in6));
131 sa6.sin6_family = AF_INET6; 129 sa6.sin6_family = AF_INET6;
132 130
131 /*
132 * parse the new address
133 */
133 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) 134 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
134 { 135 {
135 fprintf (stderr, 136 fprintf (stderr,
136 "Failed to parse address `%s': %s\n", 137 "Failed to parse address `%s': %s\n",
137 address, 138 address, strerror (errno));
138 strerror (errno));
139 exit (1); 139 exit (1);
140 } 140 }
141 memcpy (&ifr6.ifr6_addr, &sa6.sin6_addr, sizeof (struct in6_addr));
142
141 143
142 memcpy (&ifr6.ifr6_addr, 144 /*
143 &sa6.sin6_addr, 145 * Get the index of the if
144 sizeof (struct in6_addr)); 146 */
145 strncpy (ifr.ifr_name, dev, IFNAMSIZ); 147 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
146 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) 148 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
147 { 149 {
148 fprintf (stderr, 150 fprintf (stderr,
149 "ioctl failed at %d: %s\n", 151 "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
150 __LINE__,
151 strerror (errno));
152 exit (1); 152 exit (1);
153 } 153 }
154
155 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 154 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
155
156 ifr6.ifr6_prefixlen = prefix_len; 156 ifr6.ifr6_prefixlen = prefix_len;
157
158 /*
159 * Set the address
160 */
157 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) 161 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
158 { 162 {
159 fprintf (stderr, 163 fprintf (stderr,
160 "ioctl failed at line %d: %s\n", 164 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
161 __LINE__,
162 strerror (errno));
163 exit (1); 165 exit (1);
164 } 166 }
165 167
168 /*
169 * Get the flags
170 */
166 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) 171 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
167 { 172 {
168 fprintf (stderr, 173 fprintf (stderr,
169 "ioctl failed at line %d: %s\n", 174 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
170 __LINE__,
171 strerror (errno));
172 exit (1); 175 exit (1);
173 } 176 }
177
178 /*
179 * Add the UP and RUNNING flags
180 */
174 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 181 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
175 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) 182 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
176 { 183 {
177 fprintf (stderr, 184 fprintf (stderr,
178 "ioctl failed at line %d: %s\n", 185 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
179 __LINE__,
180 strerror (errno));
181 exit (1); 186 exit (1);
182 } 187 }
183 188
184 if (0 != close (fd)) 189 if (0 != close (fd))
185 { 190 {
186 fprintf (stderr, 191 fprintf (stderr, "close failed: %s\n", strerror (errno));
187 "close failed: %s\n",
188 strerror (errno));
189 exit (1); 192 exit (1);
190 } 193 }
191} 194}
@@ -211,6 +214,9 @@ set_address4 (char *dev, char *address, char *mask)
211 addr->sin_family = AF_INET; 214 addr->sin_family = AF_INET;
212 addr->sin_addr.s_addr = inet_addr (address); 215 addr->sin_addr.s_addr = inet_addr (address);
213 216
217 /*
218 * Parse the address
219 */
214 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr); 220 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
215 if (r < 0) 221 if (r < 0)
216 { 222 {
@@ -227,6 +233,9 @@ set_address4 (char *dev, char *address, char *mask)
227 233
228 strncpy (ifr.ifr_name, dev, IFNAMSIZ); 234 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
229 235
236 /*
237 * Set the address
238 */
230 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0) 239 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
231 { 240 {
232 perror ("SIOCSIFADDR"); 241 perror ("SIOCSIFADDR");
@@ -234,6 +243,9 @@ set_address4 (char *dev, char *address, char *mask)
234 return; 243 return;
235 } 244 }
236 245
246 /*
247 * Parse the netmask
248 */
237 addr = (struct sockaddr_in *) &(ifr.ifr_netmask); 249 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
238 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr); 250 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
239 if (r < 0) 251 if (r < 0)
@@ -242,6 +254,9 @@ set_address4 (char *dev, char *address, char *mask)
242 exit (1); 254 exit (1);
243 } 255 }
244 256
257 /*
258 * Set the netmask
259 */
245 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0) 260 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
246 { 261 {
247 perror ("SIOCSIFNETMASK"); 262 perror ("SIOCSIFNETMASK");
@@ -249,156 +264,211 @@ set_address4 (char *dev, char *address, char *mask)
249 return; 264 return;
250 } 265 }
251 266
252 (void) ioctl (fd, SIOCGIFFLAGS, &ifr); 267 /*
268 * Get the flags
269 */
270 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
271 {
272 fprintf (stderr,
273 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
274 exit (1);
275 }
276
277 /*
278 * Add the UP and RUNNING flags
279 */
253 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 280 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
254 (void) ioctl (fd, SIOCSIFFLAGS, &ifr); 281 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
255 close (fd); 282 {
283 fprintf (stderr,
284 "ioctl failed at line %d: %s\n", __LINE__, strerror (errno));
285 exit (1);
286 }
287
288 if (0 != close (fd))
289 {
290 fprintf (stderr, "close failed: %s\n", strerror (errno));
291 exit (1);
292 }
256} 293}
257 294
258 295
259static void 296static void
260run (int fd_tun) 297run (int fd_tun)
261{ 298{
262 unsigned char buf[MAX_SIZE]; 299 /*
300 * The buffer filled by reading from fd_tun
301 */
302 unsigned char buftun[MAX_SIZE];
303 ssize_t buftun_size = 0;
304 unsigned char *buftun_read;
305
306 /*
307 * The buffer filled by reading from stdin
308 */
309 unsigned char bufin[MAX_SIZE];
310 ssize_t bufin_size = 0;
311 unsigned char *bufin_write;
312
263 fd_set fds_w; 313 fd_set fds_w;
264 fd_set fds_r; 314 fd_set fds_r;
315
265 int rea = 1; 316 int rea = 1;
266 int wri = 1; 317 int wri = 1;
267 int write_fd_possible = 0; 318
268 int write_stdout_possible = 0;
269 ssize_t tin;
270outer:
271 while ((1 == rea) || (1 == wri)) 319 while ((1 == rea) || (1 == wri))
272 { 320 {
273 FD_ZERO (&fds_w); 321 FD_ZERO (&fds_w);
274 FD_ZERO (&fds_r); 322 FD_ZERO (&fds_r);
275 323
276 if (rea) 324 /*
325 * We are supposed to read and the buffer is empty
326 * -> select on read from tun
327 */
328 if (rea && (0 == buftun_size))
277 { 329 {
278 FD_SET (fd_tun, &fds_r); 330 FD_SET (fd_tun, &fds_r);
279 if (!write_stdout_possible)
280 FD_SET (1, &fds_w);
281 } 331 }
282 332
283 if (wri) 333 /*
334 * We are supposed to read and the buffer is not empty
335 * -> select on write to stdout
336 */
337 if (rea && (0 != buftun_size))
338 {
339 FD_SET (1, &fds_w);
340 }
341
342 /*
343 * We are supposed to write and the buffer is empty
344 * -> select on read from stdin
345 */
346 if (wri && (0 == bufin_size))
284 { 347 {
285 FD_SET (0, &fds_r); 348 FD_SET (0, &fds_r);
286 if (!write_fd_possible) 349 }
287 FD_SET (fd_tun, &fds_w); 350
351 /*
352 * We are supposed to write and the buffer is not empty
353 * -> select on write to tun
354 */
355 if (wri && (0 != bufin_size))
356 {
357 FD_SET (fd_tun, &fds_w);
288 } 358 }
289 359
290 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); 360 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
291 /* FIXME: if error... */ 361 if (-1 == r)
292 if (r > 0)
293 { 362 {
294 if (FD_ISSET (fd_tun, &fds_w)) 363 fprintf (stderr, "select failed: %s\n", strerror (errno));
295 write_fd_possible = 1; 364 exit (1);
296 if (FD_ISSET (1, &fds_w)) 365 }
297 write_stdout_possible = 1;
298 366
299 if (FD_ISSET (0, &fds_r) && write_fd_possible) 367 if (r > 0)
368 {
369 if (FD_ISSET (fd_tun, &fds_r))
300 { 370 {
301 write_fd_possible = 0; 371 buftun_size =
302 struct GNUNET_MessageHeader *pkt = ( struct GNUNET_MessageHeader *) buf; 372 read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader),
303 tin = read (0, buf, sizeof (struct GNUNET_MessageHeader)); 373 MAX_SIZE - sizeof (struct GNUNET_MessageHeader)) +
304 if (tin <= 0) 374 sizeof (struct GNUNET_MessageHeader);
375 if (-1 == buftun_size)
305 { 376 {
306 fprintf (stderr, "read-error: %s\n", strerror (errno)); 377 fprintf (stderr, "read-error: %s\n", strerror (errno));
307 shutdown (fd_tun, SHUT_WR); 378 shutdown (fd_tun, SHUT_RD);
308 shutdown (0, SHUT_RD); 379 shutdown (1, SHUT_WR);
309 wri = 0; 380 rea = 0;
310 goto outer; 381 buftun_size = 0;
311 } 382 }
312 if (pkt->type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) 383 else if (0 == buftun_size)
313 abort ();
314 while (tin < ntohs (pkt->size))
315 { 384 {
316 ssize_t t = read (0, buf + tin, ntohs (pkt->size) - tin); 385 fprintf (stderr, "eof on tun\n");
317 if (t <= 0) 386 shutdown (fd_tun, SHUT_RD);
318 { 387 shutdown (1, SHUT_WR);
319 fprintf (stderr, "read-error: %s\n", strerror (errno)); 388 rea = 0;
320 shutdown (fd_tun, SHUT_WR); 389 buftun_size = 0;
321 shutdown (0, SHUT_RD);
322 wri = 0;
323 goto outer;
324 }
325 tin += t;
326 } 390 }
327 tin = 0; 391 else
328 while (tin <
329 ntohs (pkt->size) -
330 sizeof (struct GNUNET_MessageHeader))
331 { 392 {
332 ssize_t t = write (fd_tun, &pkt[1], 393 buftun_read = buftun;
333 ntohs (pkt->size) - 394 struct GNUNET_MessageHeader *hdr =
334 sizeof (struct GNUNET_MessageHeader) - tin); 395 (struct GNUNET_MessageHeader *) buftun;
335 if (t <= 0) 396 hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER);
336 { 397 hdr->size = htons (buftun_size);
337 fprintf (stderr, "write-error 3: %s\n",
338 strerror (errno));
339 shutdown (fd_tun, SHUT_WR);
340 shutdown (0, SHUT_RD);
341 wri = 0;
342 goto outer;
343 }
344 tin += t;
345 } 398 }
346 } 399 }
347 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) 400 else if (FD_ISSET (1, &fds_w))
348 { 401 {
349 write_stdout_possible = 0; 402 ssize_t written = write (1, buftun_read, buftun_size);
350 tin = read (fd_tun, buf, MAX_SIZE); 403 if (-1 == written)
351 if (tin <= 0)
352 { 404 {
353 fprintf (stderr, "read-error: %s\n", strerror (errno)); 405 fprintf (stderr, "write-error to stdout: %s\n",
406 strerror (errno));
354 shutdown (fd_tun, SHUT_RD); 407 shutdown (fd_tun, SHUT_RD);
355 shutdown (1, SHUT_WR); 408 shutdown (1, SHUT_WR);
356 rea = 0; 409 rea = 0;
357 goto outer; 410 buftun_size = 0;
411 }
412 buftun_size -= written;
413 buftun_read += written;
414 }
415
416 if (FD_ISSET (0, &fds_r))
417 {
418 bufin_size = read (0, bufin, MAX_SIZE);
419 if (-1 == bufin_size)
420 {
421 fprintf (stderr, "read-error: %s\n", strerror (errno));
422 shutdown (0, SHUT_RD);
423 shutdown (fd_tun, SHUT_WR);
424 wri = 0;
425 bufin_size = 0;
358 } 426 }
359 struct GNUNET_MessageHeader hdr = {.size = 427 else if (0 == bufin_size)
360 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
361 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
362 };
363 tin = 0;
364 while (tin < sizeof (struct GNUNET_MessageHeader))
365 { 428 {
366 ssize_t t = 429 fprintf (stderr, "eof on stdin\n");
367 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - tin); 430 shutdown (0, SHUT_RD);
368 if (t < 0) 431 shutdown (fd_tun, SHUT_WR);
369 { 432 wri = 0;
370 fprintf (stderr, "write-error 2: %s\n", 433 bufin_size = 0;
371 strerror (errno));
372 shutdown (fd_tun, SHUT_RD);
373 shutdown (1, SHUT_WR);
374 rea = 0;
375 goto outer;
376 }
377 tin += t;
378 } 434 }
379 while (tin < ntohs (hdr.size)) 435 else
380 { 436 {
381 size_t t = write (1, buf, ntohs (hdr.size) - tin); 437 struct GNUNET_MessageHeader *hdr =
382 if (t < 0) 438 (struct GNUNET_MessageHeader *) bufin;
439 if ((bufin_size < sizeof (struct GNUNET_MessageHeader))
440 || (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER)
441 || (ntohs (hdr->size) != bufin_size))
383 { 442 {
384 fprintf (stderr, "write-error 1: %s, written %d/%d\n", 443 fprintf (stderr, "protocol violation!\n");
385 strerror (errno), r, ntohs (hdr.size)); 444 exit (1);
386 shutdown (fd_tun, SHUT_RD);
387 shutdown (1, SHUT_WR);
388 rea = 0;
389 goto outer;
390 } 445 }
391 tin += t; 446 bufin_write = bufin + sizeof (struct GNUNET_MessageHeader);
447 bufin_size -= sizeof (struct GNUNET_MessageHeader);
448 }
449 }
450 else if (FD_ISSET (fd_tun, &fds_w))
451 {
452 ssize_t written = write (fd_tun, bufin_write, bufin_size);
453 if (-1 == written)
454 {
455 fprintf (stderr, "write-error to tun: %s\n",
456 strerror (errno));
457 shutdown (0, SHUT_RD);
458 shutdown (fd_tun, SHUT_WR);
459 wri = 0;
460 bufin_size = 0;
392 } 461 }
462 bufin_size -= written;
463 bufin_write += written;
393 } 464 }
394 } 465 }
395 } 466 }
396} 467}
397 468
398 469
399int 470int
400main (int argc, 471main (int argc, char **argv)
401 char** argv)
402{ 472{
403 char dev[IFNAMSIZ]; 473 char dev[IFNAMSIZ];
404 int fd_tun; 474 int fd_tun;
@@ -406,8 +476,7 @@ main (int argc,
406 memset (dev, 0, IFNAMSIZ); 476 memset (dev, 0, IFNAMSIZ);
407 if (-1 == (fd_tun = init_tun (dev))) 477 if (-1 == (fd_tun = init_tun (dev)))
408 { 478 {
409 fprintf (stderr, 479 fprintf (stderr, "Fatal: could not initialize tun-interface\n");
410 "Fatal: could not initialize tun-interface\n");
411 return 1; 480 return 1;
412 } 481 }
413 482
@@ -428,9 +497,7 @@ main (int argc,
428 497
429 uid_t uid = getuid (); 498 uid_t uid = getuid ();
430 if (0 != setresuid (uid, uid, uid)) 499 if (0 != setresuid (uid, uid, uid))
431 fprintf (stderr, 500 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
432 "Failed to setresuid: %s\n",
433 strerror (errno));
434 run (fd_tun); 501 run (fd_tun);
435 close (fd_tun); 502 close (fd_tun);
436 return 0; 503 return 0;