aboutsummaryrefslogtreecommitdiff
path: root/src/dns/gnunet-helper-dns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dns/gnunet-helper-dns.c')
-rw-r--r--src/dns/gnunet-helper-dns.c1373
1 files changed, 680 insertions, 693 deletions
diff --git a/src/dns/gnunet-helper-dns.c b/src/dns/gnunet-helper-dns.c
index e837d81c6..eceb278d2 100644
--- a/src/dns/gnunet-helper-dns.c
+++ b/src/dns/gnunet-helper-dns.c
@@ -83,11 +83,12 @@
83 */ 83 */
84#define MAX_SIZE 65536 84#define MAX_SIZE 65536
85 85
86#if !HAVE_DECL_STRUCT_IN6_IFREQ 86#if ! HAVE_DECL_STRUCT_IN6_IFREQ
87/** 87/**
88 * This is in linux/include/net/ipv6.h, but not always exported... 88 * This is in linux/include/net/ipv6.h, but not always exported...
89 */ 89 */
90struct in6_ifreq { 90struct in6_ifreq
91{
91 struct in6_addr ifr6_addr; 92 struct in6_addr ifr6_addr;
92 uint32_t ifr6_prefixlen; 93 uint32_t ifr6_prefixlen;
93 unsigned int ifr6_ifindex; 94 unsigned int ifr6_ifindex;
@@ -151,11 +152,11 @@ static int cpipe[2];
151 * @param signal signal number of the signal (not used) 152 * @param signal signal number of the signal (not used)
152 */ 153 */
153static void 154static void
154signal_handler(int signal) 155signal_handler (int signal)
155{ 156{
156 /* ignore return value, as the signal handler could theoretically 157 /* ignore return value, as the signal handler could theoretically
157 be called many times before the shutdown can actually happen */ 158 be called many times before the shutdown can actually happen */
158 (void)write(cpipe[1], "K", 1); 159 (void) write (cpipe[1], "K", 1);
159} 160}
160 161
161 162
@@ -167,22 +168,22 @@ signal_handler(int signal)
167 * @param flags open flags (O_RDONLY, O_WRONLY) 168 * @param flags open flags (O_RDONLY, O_WRONLY)
168 */ 169 */
169static void 170static void
170open_dev_null(int target_fd, 171open_dev_null (int target_fd,
171 int flags) 172 int flags)
172{ 173{
173 int fd; 174 int fd;
174 175
175 fd = open("/dev/null", flags); 176 fd = open ("/dev/null", flags);
176 if (-1 == fd) 177 if (-1 == fd)
177 abort(); 178 abort ();
178 if (fd == target_fd) 179 if (fd == target_fd)
179 return; 180 return;
180 if (-1 == dup2(fd, target_fd)) 181 if (-1 == dup2 (fd, target_fd))
181 { 182 {
182 (void)close(fd); 183 (void) close (fd);
183 abort(); 184 abort ();
184 } 185 }
185 (void)close(fd); 186 (void) close (fd);
186} 187}
187 188
188 189
@@ -194,50 +195,50 @@ open_dev_null(int target_fd,
194 * @return 0 on success, 1 on any error 195 * @return 0 on success, 1 on any error
195 */ 196 */
196static int 197static int
197fork_and_exec(const char *file, 198fork_and_exec (const char *file,
198 char *const cmd[]) 199 char *const cmd[])
199{ 200{
200 int status; 201 int status;
201 pid_t pid; 202 pid_t pid;
202 pid_t ret; 203 pid_t ret;
203 204
204 pid = fork(); 205 pid = fork ();
205 if (-1 == pid) 206 if (-1 == pid)
206 { 207 {
207 fprintf(stderr, 208 fprintf (stderr,
208 "fork failed: %s\n", 209 "fork failed: %s\n",
209 strerror(errno)); 210 strerror (errno));
210 return 1; 211 return 1;
211 } 212 }
212 if (0 == pid) 213 if (0 == pid)
213 { 214 {
214 /* we are the child process */ 215 /* we are the child process */
215 /* close stdin/stdout to not cause interference 216 /* close stdin/stdout to not cause interference
216 with the helper's main protocol! */ 217 with the helper's main protocol! */
217 (void)close(0); 218 (void) close (0);
218 open_dev_null(0, O_RDONLY); 219 open_dev_null (0, O_RDONLY);
219 (void)close(1); 220 (void) close (1);
220 open_dev_null(1, O_WRONLY); 221 open_dev_null (1, O_WRONLY);
221 (void)execv(file, cmd); 222 (void) execv (file, cmd);
222 /* can only get here on error */ 223 /* can only get here on error */
223 fprintf(stderr, 224 fprintf (stderr,
224 "exec `%s' failed: %s\n", 225 "exec `%s' failed: %s\n",
225 file, 226 file,
226 strerror(errno)); 227 strerror (errno));
227 _exit(1); 228 _exit (1);
228 } 229 }
229 /* keep running waitpid as long as the only error we get is 'EINTR' */ 230 /* keep running waitpid as long as the only error we get is 'EINTR' */
230 while ((-1 == (ret = waitpid(pid, &status, 0))) && 231 while ((-1 == (ret = waitpid (pid, &status, 0))) &&
231 (errno == EINTR)) 232 (errno == EINTR))
232 ; 233 ;
233 if (-1 == ret) 234 if (-1 == ret)
234 { 235 {
235 fprintf(stderr, 236 fprintf (stderr,
236 "waitpid failed: %s\n", 237 "waitpid failed: %s\n",
237 strerror(errno)); 238 strerror (errno));
238 return 1; 239 return 1;
239 } 240 }
240 if (!(WIFEXITED(status) && (0 == WEXITSTATUS(status)))) 241 if (! (WIFEXITED (status) && (0 == WEXITSTATUS (status))))
241 return 1; 242 return 1;
242 /* child process completed and returned success, we're happy */ 243 /* child process completed and returned success, we're happy */
243 return 0; 244 return 0;
@@ -252,45 +253,45 @@ fork_and_exec(const char *file,
252 * @return the fd to the tun or -1 on error 253 * @return the fd to the tun or -1 on error
253 */ 254 */
254static int 255static int
255init_tun(char *dev) 256init_tun (char *dev)
256{ 257{
257 struct ifreq ifr; 258 struct ifreq ifr;
258 int fd; 259 int fd;
259 260
260 if (NULL == dev) 261 if (NULL == dev)
261 { 262 {
262 errno = EINVAL; 263 errno = EINVAL;
263 return -1; 264 return -1;
264 } 265 }
265 266
266 if (-1 == (fd = open("/dev/net/tun", O_RDWR))) 267 if (-1 == (fd = open ("/dev/net/tun", O_RDWR)))
267 { 268 {
268 fprintf(stderr, "Error opening `%s': %s\n", "/dev/net/tun", 269 fprintf (stderr, "Error opening `%s': %s\n", "/dev/net/tun",
269 strerror(errno)); 270 strerror (errno));
270 return -1; 271 return -1;
271 } 272 }
272 273
273 if (fd >= FD_SETSIZE) 274 if (fd >= FD_SETSIZE)
274 { 275 {
275 fprintf(stderr, "File descriptor to large: %d", fd); 276 fprintf (stderr, "File descriptor to large: %d", fd);
276 (void)close(fd); 277 (void) close (fd);
277 return -1; 278 return -1;
278 } 279 }
279 280
280 memset(&ifr, 0, sizeof(ifr)); 281 memset (&ifr, 0, sizeof(ifr));
281 ifr.ifr_flags = IFF_TUN; 282 ifr.ifr_flags = IFF_TUN;
282 283
283 if ('\0' != *dev) 284 if ('\0' != *dev)
284 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 285 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
285 286
286 if (-1 == ioctl(fd, TUNSETIFF, (void *)&ifr)) 287 if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr))
287 { 288 {
288 fprintf(stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun", 289 fprintf (stderr, "Error with ioctl on `%s': %s\n", "/dev/net/tun",
289 strerror(errno)); 290 strerror (errno));
290 (void)close(fd); 291 (void) close (fd);
291 return -1; 292 return -1;
292 } 293 }
293 strcpy(dev, ifr.ifr_name); 294 strcpy (dev, ifr.ifr_name);
294 return fd; 295 return fd;
295} 296}
296 297
@@ -303,7 +304,7 @@ init_tun(char *dev)
303 * @param prefix_len the length of the network-prefix 304 * @param prefix_len the length of the network-prefix
304 */ 305 */
305static void 306static void
306set_address6(const char *dev, const char *address, unsigned long prefix_len) 307set_address6 (const char *dev, const char *address, unsigned long prefix_len)
307{ 308{
308 struct ifreq ifr; 309 struct ifreq ifr;
309 struct in6_ifreq ifr6; 310 struct in6_ifreq ifr6;
@@ -313,39 +314,39 @@ set_address6(const char *dev, const char *address, unsigned long prefix_len)
313 /* 314 /*
314 * parse the new address 315 * parse the new address
315 */ 316 */
316 memset(&sa6, 0, sizeof(struct sockaddr_in6)); 317 memset (&sa6, 0, sizeof(struct sockaddr_in6));
317 sa6.sin6_family = AF_INET6; 318 sa6.sin6_family = AF_INET6;
318 if (1 != inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr)) 319 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
319 { 320 {
320 fprintf(stderr, 321 fprintf (stderr,
321 "Failed to parse IPv6 address `%s': %s\n", 322 "Failed to parse IPv6 address `%s': %s\n",
322 address, 323 address,
323 strerror(errno)); 324 strerror (errno));
324 exit(1); 325 exit (1);
325 } 326 }
326 327
327 if (-1 == (fd = socket(PF_INET6, SOCK_DGRAM, 0))) 328 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
328 { 329 {
329 fprintf(stderr, 330 fprintf (stderr,
330 "Error creating IPv6 socket: %s (ignored)\n", 331 "Error creating IPv6 socket: %s (ignored)\n",
331 strerror(errno)); 332 strerror (errno));
332 /* ignore error, maybe only IPv4 works on this system! */ 333 /* ignore error, maybe only IPv4 works on this system! */
333 return; 334 return;
334 } 335 }
335 336
336 memset(&ifr, 0, sizeof(struct ifreq)); 337 memset (&ifr, 0, sizeof(struct ifreq));
337 /* 338 /*
338 * Get the index of the if 339 * Get the index of the if
339 */ 340 */
340 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 341 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
341 if (-1 == ioctl(fd, SIOGIFINDEX, &ifr)) 342 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
342 { 343 {
343 fprintf(stderr, "ioctl failed at %d: %s\n", __LINE__, strerror(errno)); 344 fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
344 (void)close(fd); 345 (void) close (fd);
345 exit(1); 346 exit (1);
346 } 347 }
347 348
348 memset(&ifr6, 0, sizeof(struct in6_ifreq)); 349 memset (&ifr6, 0, sizeof(struct in6_ifreq));
349 ifr6.ifr6_addr = sa6.sin6_addr; 350 ifr6.ifr6_addr = sa6.sin6_addr;
350 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 351 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
351 ifr6.ifr6_prefixlen = prefix_len; 352 ifr6.ifr6_prefixlen = prefix_len;
@@ -353,42 +354,42 @@ set_address6(const char *dev, const char *address, unsigned long prefix_len)
353 /* 354 /*
354 * Set the address 355 * Set the address
355 */ 356 */
356 if (-1 == ioctl(fd, SIOCSIFADDR, &ifr6)) 357 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
357 { 358 {
358 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 359 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
359 strerror(errno)); 360 strerror (errno));
360 (void)close(fd); 361 (void) close (fd);
361 exit(1); 362 exit (1);
362 } 363 }
363 364
364 /* 365 /*
365 * Get the flags 366 * Get the flags
366 */ 367 */
367 if (-1 == ioctl(fd, SIOCGIFFLAGS, &ifr)) 368 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
368 { 369 {
369 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 370 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
370 strerror(errno)); 371 strerror (errno));
371 (void)close(fd); 372 (void) close (fd);
372 exit(1); 373 exit (1);
373 } 374 }
374 375
375 /* 376 /*
376 * Add the UP and RUNNING flags 377 * Add the UP and RUNNING flags
377 */ 378 */
378 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 379 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
379 if (-1 == ioctl(fd, SIOCSIFFLAGS, &ifr)) 380 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
380 { 381 {
381 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 382 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
382 strerror(errno)); 383 strerror (errno));
383 (void)close(fd); 384 (void) close (fd);
384 exit(1); 385 exit (1);
385 } 386 }
386 387
387 if (0 != close(fd)) 388 if (0 != close (fd))
388 { 389 {
389 fprintf(stderr, "close failed: %s\n", strerror(errno)); 390 fprintf (stderr, "close failed: %s\n", strerror (errno));
390 exit(1); 391 exit (1);
391 } 392 }
392} 393}
393 394
394 395
@@ -400,100 +401,100 @@ set_address6(const char *dev, const char *address, unsigned long prefix_len)
400 * @param mask the netmask 401 * @param mask the netmask
401 */ 402 */
402static void 403static void
403set_address4(const char *dev, const char *address, const char *mask) 404set_address4 (const char *dev, const char *address, const char *mask)
404{ 405{
405 int fd; 406 int fd;
406 struct sockaddr_in *addr; 407 struct sockaddr_in *addr;
407 struct ifreq ifr; 408 struct ifreq ifr;
408 409
409 memset(&ifr, 0, sizeof(struct ifreq)); 410 memset (&ifr, 0, sizeof(struct ifreq));
410 addr = (struct sockaddr_in *)&(ifr.ifr_addr); 411 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
411 addr->sin_family = AF_INET; 412 addr->sin_family = AF_INET;
412 413
413 /* 414 /*
414 * Parse the address 415 * Parse the address
415 */ 416 */
416 if (1 != inet_pton(AF_INET, address, &addr->sin_addr.s_addr)) 417 if (1 != inet_pton (AF_INET, address, &addr->sin_addr.s_addr))
417 { 418 {
418 fprintf(stderr, 419 fprintf (stderr,
419 "Failed to parse IPv4 address `%s': %s\n", 420 "Failed to parse IPv4 address `%s': %s\n",
420 address, 421 address,
421 strerror(errno)); 422 strerror (errno));
422 exit(1); 423 exit (1);
423 } 424 }
424 425
425 if (-1 == (fd = socket(PF_INET, SOCK_DGRAM, 0))) 426 if (-1 == (fd = socket (PF_INET, SOCK_DGRAM, 0)))
426 { 427 {
427 fprintf(stderr, 428 fprintf (stderr,
428 "Error creating IPv4 socket: %s\n", 429 "Error creating IPv4 socket: %s\n",
429 strerror(errno)); 430 strerror (errno));
430 exit(1); 431 exit (1);
431 } 432 }
432 433
433 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 434 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
434 435
435 /* 436 /*
436 * Set the address 437 * Set the address
437 */ 438 */
438 if (-1 == ioctl(fd, SIOCSIFADDR, &ifr)) 439 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr))
439 { 440 {
440 fprintf(stderr, "ioctl failed at %d: %s\n", __LINE__, strerror(errno)); 441 fprintf (stderr, "ioctl failed at %d: %s\n", __LINE__, strerror (errno));
441 (void)close(fd); 442 (void) close (fd);
442 exit(1); 443 exit (1);
443 } 444 }
444 445
445 /* 446 /*
446 * Parse the netmask 447 * Parse the netmask
447 */ 448 */
448 addr = (struct sockaddr_in *)&(ifr.ifr_netmask); 449 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
449 if (1 != inet_pton(AF_INET, mask, &addr->sin_addr.s_addr)) 450 if (1 != inet_pton (AF_INET, mask, &addr->sin_addr.s_addr))
450 { 451 {
451 fprintf(stderr, "Failed to parse address `%s': %s\n", mask, 452 fprintf (stderr, "Failed to parse address `%s': %s\n", mask,
452 strerror(errno)); 453 strerror (errno));
453 (void)close(fd); 454 (void) close (fd);
454 exit(1); 455 exit (1);
455 } 456 }
456 457
457 /* 458 /*
458 * Set the netmask 459 * Set the netmask
459 */ 460 */
460 if (-1 == ioctl(fd, SIOCSIFNETMASK, &ifr)) 461 if (-1 == ioctl (fd, SIOCSIFNETMASK, &ifr))
461 { 462 {
462 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 463 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
463 strerror(errno)); 464 strerror (errno));
464 (void)close(fd); 465 (void) close (fd);
465 exit(1); 466 exit (1);
466 } 467 }
467 468
468 /* 469 /*
469 * Get the flags 470 * Get the flags
470 */ 471 */
471 if (-1 == ioctl(fd, SIOCGIFFLAGS, &ifr)) 472 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
472 { 473 {
473 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 474 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
474 strerror(errno)); 475 strerror (errno));
475 (void)close(fd); 476 (void) close (fd);
476 exit(1); 477 exit (1);
477 } 478 }
478 479
479 /* 480 /*
480 * Add the UP and RUNNING flags 481 * Add the UP and RUNNING flags
481 */ 482 */
482 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 483 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
483 if (-1 == ioctl(fd, SIOCSIFFLAGS, &ifr)) 484 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
484 { 485 {
485 fprintf(stderr, "ioctl failed at line %d: %s\n", __LINE__, 486 fprintf (stderr, "ioctl failed at line %d: %s\n", __LINE__,
486 strerror(errno)); 487 strerror (errno));
487 (void)close(fd); 488 (void) close (fd);
488 exit(1); 489 exit (1);
489 } 490 }
490 491
491 if (0 != close(fd)) 492 if (0 != close (fd))
492 { 493 {
493 fprintf(stderr, "close failed: %s\n", strerror(errno)); 494 fprintf (stderr, "close failed: %s\n", strerror (errno));
494 (void)close(fd); 495 (void) close (fd);
495 exit(1); 496 exit (1);
496 } 497 }
497} 498}
498 499
499 500
@@ -505,7 +506,7 @@ set_address4(const char *dev, const char *address, const char *mask)
505 * @param fd_tun tunnel FD 506 * @param fd_tun tunnel FD
506 */ 507 */
507static void 508static void
508run(int fd_tun) 509run (int fd_tun)
509{ 510{
510 /* 511 /*
511 * The buffer filled by reading from fd_tun 512 * The buffer filled by reading from fd_tun
@@ -526,176 +527,176 @@ run(int fd_tun)
526 int max; 527 int max;
527 528
528 while (1) 529 while (1)
530 {
531 FD_ZERO (&fds_w);
532 FD_ZERO (&fds_r);
533
534 /*
535 * We are supposed to read and the buffer is empty
536 * -> select on read from tun
537 */
538 if (0 == buftun_size)
539 FD_SET (fd_tun, &fds_r);
540
541 /*
542 * We are supposed to read and the buffer is not empty
543 * -> select on write to stdout
544 */
545 if (0 < buftun_size)
546 FD_SET (1, &fds_w);
547
548 /*
549 * We are supposed to write and the buffer is empty
550 * -> select on read from stdin
551 */
552 if (NULL == bufin_read)
553 FD_SET (0, &fds_r);
554
555 /*
556 * We are supposed to write and the buffer is not empty
557 * -> select on write to tun
558 */
559 if (NULL != bufin_read)
560 FD_SET (fd_tun, &fds_w);
561
562 FD_SET (cpipe[0], &fds_r);
563 max = (fd_tun > cpipe[0]) ? fd_tun : cpipe[0];
564
565 int r = select (max + 1, &fds_r, &fds_w, NULL, NULL);
566
567 if (-1 == r)
568 {
569 if (EINTR == errno)
570 continue;
571 fprintf (stderr, "select failed: %s\n", strerror (errno));
572 return;
573 }
574
575 if (r > 0)
529 { 576 {
530 FD_ZERO(&fds_w); 577 if (FD_ISSET (cpipe[0], &fds_r))
531 FD_ZERO(&fds_r); 578 return; /* aborted by signal */
532 579
533 /* 580 if (FD_ISSET (fd_tun, &fds_r))
534 * We are supposed to read and the buffer is empty 581 {
535 * -> select on read from tun 582 buftun_size =
536 */ 583 read (fd_tun, buftun + sizeof(struct GNUNET_MessageHeader),
537 if (0 == buftun_size) 584 MAX_SIZE - sizeof(struct GNUNET_MessageHeader));
538 FD_SET(fd_tun, &fds_r); 585 if (-1 == buftun_size)
539 586 {
540 /* 587 if ((errno == EINTR) ||
541 * We are supposed to read and the buffer is not empty 588 (errno == EAGAIN))
542 * -> select on write to stdout 589 {
543 */ 590 buftun_size = 0;
544 if (0 < buftun_size) 591 continue;
545 FD_SET(1, &fds_w); 592 }
546 593 fprintf (stderr, "read-error: %s\n", strerror (errno));
547 /* 594 return;
548 * We are supposed to write and the buffer is empty 595 }
549 * -> select on read from stdin 596 if (0 == buftun_size)
550 */ 597 {
551 if (NULL == bufin_read) 598 fprintf (stderr, "EOF on tun\n");
552 FD_SET(0, &fds_r); 599 return;
553 600 }
554 /* 601 buftun_read = buftun;
555 * We are supposed to write and the buffer is not empty
556 * -> select on write to tun
557 */
558 if (NULL != bufin_read)
559 FD_SET(fd_tun, &fds_w);
560
561 FD_SET(cpipe[0], &fds_r);
562 max = (fd_tun > cpipe[0]) ? fd_tun : cpipe[0];
563
564 int r = select(max + 1, &fds_r, &fds_w, NULL, NULL);
565
566 if (-1 == r)
567 { 602 {
568 if (EINTR == errno) 603 struct GNUNET_MessageHeader *hdr =
604 (struct GNUNET_MessageHeader *) buftun;
605 buftun_size += sizeof(struct GNUNET_MessageHeader);
606 hdr->type = htons (GNUNET_MESSAGE_TYPE_DNS_HELPER);
607 hdr->size = htons (buftun_size);
608 }
609 }
610 else if (FD_ISSET (1, &fds_w))
611 {
612 ssize_t written = write (1, buftun_read, buftun_size);
613
614 if (-1 == written)
615 {
616 if ((errno == EINTR) ||
617 (errno == EAGAIN))
569 continue; 618 continue;
570 fprintf(stderr, "select failed: %s\n", strerror(errno)); 619 fprintf (stderr, "write-error to stdout: %s\n", strerror (errno));
571 return; 620 return;
572 } 621 }
622 if (0 == written)
623 {
624 fprintf (stderr, "write returned 0\n");
625 return;
626 }
627 buftun_size -= written;
628 buftun_read += written;
629 }
573 630
574 if (r > 0) 631 if (FD_ISSET (0, &fds_r))
632 {
633 bufin_size = read (0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
634 if (-1 == bufin_size)
635 {
636 bufin_read = NULL;
637 if ((errno == EINTR) ||
638 (errno == EAGAIN))
639 continue;
640 fprintf (stderr, "read-error: %s\n", strerror (errno));
641 return;
642 }
643 if (0 == bufin_size)
644 {
645 bufin_read = NULL;
646 fprintf (stderr, "EOF on stdin\n");
647 return;
648 }
575 { 649 {
576 if (FD_ISSET(cpipe[0], &fds_r)) 650 struct GNUNET_MessageHeader *hdr;
577 return; /* aborted by signal */
578
579 if (FD_ISSET(fd_tun, &fds_r))
580 {
581 buftun_size =
582 read(fd_tun, buftun + sizeof(struct GNUNET_MessageHeader),
583 MAX_SIZE - sizeof(struct GNUNET_MessageHeader));
584 if (-1 == buftun_size)
585 {
586 if ((errno == EINTR) ||
587 (errno == EAGAIN))
588 {
589 buftun_size = 0;
590 continue;
591 }
592 fprintf(stderr, "read-error: %s\n", strerror(errno));
593 return;
594 }
595 if (0 == buftun_size)
596 {
597 fprintf(stderr, "EOF on tun\n");
598 return;
599 }
600 buftun_read = buftun;
601 {
602 struct GNUNET_MessageHeader *hdr =
603 (struct GNUNET_MessageHeader *)buftun;
604 buftun_size += sizeof(struct GNUNET_MessageHeader);
605 hdr->type = htons(GNUNET_MESSAGE_TYPE_DNS_HELPER);
606 hdr->size = htons(buftun_size);
607 }
608 }
609 else if (FD_ISSET(1, &fds_w))
610 {
611 ssize_t written = write(1, buftun_read, buftun_size);
612
613 if (-1 == written)
614 {
615 if ((errno == EINTR) ||
616 (errno == EAGAIN))
617 continue;
618 fprintf(stderr, "write-error to stdout: %s\n", strerror(errno));
619 return;
620 }
621 if (0 == written)
622 {
623 fprintf(stderr, "write returned 0\n");
624 return;
625 }
626 buftun_size -= written;
627 buftun_read += written;
628 }
629
630 if (FD_ISSET(0, &fds_r))
631 {
632 bufin_size = read(0, bufin + bufin_rpos, MAX_SIZE - bufin_rpos);
633 if (-1 == bufin_size)
634 {
635 bufin_read = NULL;
636 if ((errno == EINTR) ||
637 (errno == EAGAIN))
638 continue;
639 fprintf(stderr, "read-error: %s\n", strerror(errno));
640 return;
641 }
642 if (0 == bufin_size)
643 {
644 bufin_read = NULL;
645 fprintf(stderr, "EOF on stdin\n");
646 return;
647 }
648 {
649 struct GNUNET_MessageHeader *hdr;
650 651
651PROCESS_BUFFER: 652PROCESS_BUFFER:
652 bufin_rpos += bufin_size; 653 bufin_rpos += bufin_size;
653 if (bufin_rpos < sizeof(struct GNUNET_MessageHeader)) 654 if (bufin_rpos < sizeof(struct GNUNET_MessageHeader))
654 continue; 655 continue;
655 hdr = (struct GNUNET_MessageHeader *)bufin; 656 hdr = (struct GNUNET_MessageHeader *) bufin;
656 if (ntohs(hdr->type) != GNUNET_MESSAGE_TYPE_DNS_HELPER) 657 if (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_DNS_HELPER)
657 { 658 {
658 fprintf(stderr, "protocol violation!\n"); 659 fprintf (stderr, "protocol violation!\n");
659 return; 660 return;
660 } 661 }
661 if (ntohs(hdr->size) > bufin_rpos) 662 if (ntohs (hdr->size) > bufin_rpos)
662 continue; 663 continue;
663 bufin_read = bufin + sizeof(struct GNUNET_MessageHeader); 664 bufin_read = bufin + sizeof(struct GNUNET_MessageHeader);
664 bufin_size = ntohs(hdr->size) - sizeof(struct GNUNET_MessageHeader); 665 bufin_size = ntohs (hdr->size) - sizeof(struct GNUNET_MessageHeader);
665 bufin_rpos -= bufin_size + sizeof(struct GNUNET_MessageHeader); 666 bufin_rpos -= bufin_size + sizeof(struct GNUNET_MessageHeader);
666 }
667 }
668 else if (FD_ISSET(fd_tun, &fds_w))
669 {
670 ssize_t written = write(fd_tun, bufin_read, bufin_size);
671
672 if (-1 == written)
673 {
674 if ((errno == EINTR) ||
675 (errno == EAGAIN))
676 continue;
677 fprintf(stderr, "write-error to tun: %s\n", strerror(errno));
678 return;
679 }
680 if (0 == written)
681 {
682 fprintf(stderr, "write returned 0\n");
683 return;
684 }
685 {
686 bufin_size -= written;
687 bufin_read += written;
688 if (0 == bufin_size)
689 {
690 memmove(bufin, bufin_read, bufin_rpos);
691 bufin_read = NULL; /* start reading again */
692 bufin_size = 0;
693 goto PROCESS_BUFFER;
694 }
695 }
696 }
697 } 667 }
668 }
669 else if (FD_ISSET (fd_tun, &fds_w))
670 {
671 ssize_t written = write (fd_tun, bufin_read, bufin_size);
672
673 if (-1 == written)
674 {
675 if ((errno == EINTR) ||
676 (errno == EAGAIN))
677 continue;
678 fprintf (stderr, "write-error to tun: %s\n", strerror (errno));
679 return;
680 }
681 if (0 == written)
682 {
683 fprintf (stderr, "write returned 0\n");
684 return;
685 }
686 {
687 bufin_size -= written;
688 bufin_read += written;
689 if (0 == bufin_size)
690 {
691 memmove (bufin, bufin_read, bufin_rpos);
692 bufin_read = NULL; /* start reading again */
693 bufin_size = 0;
694 goto PROCESS_BUFFER;
695 }
696 }
697 }
698 } 698 }
699 }
699} 700}
700 701
701 702
@@ -732,7 +733,7 @@ PROCESS_BUFFER:
732 * 255 failed to handle kill signal properly 733 * 255 failed to handle kill signal properly
733 */ 734 */
734int 735int
735main(int argc, char *const*argv) 736main (int argc, char *const*argv)
736{ 737{
737 int r; 738 int r;
738 char dev[IFNAMSIZ]; 739 char dev[IFNAMSIZ];
@@ -742,224 +743,225 @@ main(int argc, char *const*argv)
742 int nortsetup = 0; 743 int nortsetup = 0;
743 744
744 if (7 != argc) 745 if (7 != argc)
745 { 746 {
746 fprintf(stderr, "Fatal: must supply 6 arguments!\n"); 747 fprintf (stderr, "Fatal: must supply 6 arguments!\n");
747 return 1; 748 return 1;
748 } 749 }
749 750
750 /* assert privs so we can modify the firewall rules! */ 751 /* assert privs so we can modify the firewall rules! */
751 uid = getuid(); 752 uid = getuid ();
752#ifdef HAVE_SETRESUID 753#ifdef HAVE_SETRESUID
753 if (0 != setresuid(uid, 0, 0)) 754 if (0 != setresuid (uid, 0, 0))
754 { 755 {
755 fprintf(stderr, "Failed to setresuid to root: %s\n", strerror(errno)); 756 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
756 return 254; 757 return 254;
757 } 758 }
758#else 759#else
759 if (0 != seteuid(0)) 760 if (0 != seteuid (0))
760 { 761 {
761 fprintf(stderr, "Failed to seteuid back to root: %s\n", strerror(errno)); 762 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
762 return 254; 763 return 254;
763 } 764 }
764#endif 765#endif
765 if (0 == strncmp(argv[6], "1", 2)) 766 if (0 == strncmp (argv[6], "1", 2))
766 nortsetup = 1; 767 nortsetup = 1;
767 768
768 if (0 == nortsetup) 769 if (0 == nortsetup)
769 { 770 {
770 /* verify that the binaries we care about are executable */ 771 /* verify that the binaries we care about are executable */
771#ifdef IPTABLES 772#ifdef IPTABLES
772 if (0 == access(IPTABLES, X_OK)) 773 if (0 == access (IPTABLES, X_OK))
773 sbin_iptables = IPTABLES; 774 sbin_iptables = IPTABLES;
774 else 775 else
775#endif 776#endif
776 if (0 == access("/sbin/iptables", X_OK)) 777 if (0 == access ("/sbin/iptables", X_OK))
777 sbin_iptables = "/sbin/iptables"; 778 sbin_iptables = "/sbin/iptables";
778 else if (0 == access("/usr/sbin/iptables", X_OK)) 779 else if (0 == access ("/usr/sbin/iptables", X_OK))
779 sbin_iptables = "/usr/sbin/iptables"; 780 sbin_iptables = "/usr/sbin/iptables";
780 else 781 else
781 { 782 {
782 fprintf(stderr, 783 fprintf (stderr,
783 "Fatal: executable iptables not found in approved directories: %s\n", 784 "Fatal: executable iptables not found in approved directories: %s\n",
784 strerror(errno)); 785 strerror (errno));
785 return 3; 786 return 3;
786 } 787 }
787#ifdef IP6TABLES 788#ifdef IP6TABLES
788 if (0 == access(IP6TABLES, X_OK)) 789 if (0 == access (IP6TABLES, X_OK))
789 sbin_ip6tables = IP6TABLES; 790 sbin_ip6tables = IP6TABLES;
790 else 791 else
791#endif 792#endif
792 if (0 == access("/sbin/ip6tables", X_OK)) 793 if (0 == access ("/sbin/ip6tables", X_OK))
793 sbin_ip6tables = "/sbin/ip6tables"; 794 sbin_ip6tables = "/sbin/ip6tables";
794 else if (0 == access("/usr/sbin/ip6tables", X_OK)) 795 else if (0 == access ("/usr/sbin/ip6tables", X_OK))
795 sbin_ip6tables = "/usr/sbin/ip6tables"; 796 sbin_ip6tables = "/usr/sbin/ip6tables";
796 else 797 else
797 { 798 {
798 fprintf(stderr, 799 fprintf (stderr,
799 "Fatal: executable ip6tables not found in approved directories: %s\n", 800 "Fatal: executable ip6tables not found in approved directories: %s\n",
800 strerror(errno)); 801 strerror (errno));
801 return 3; 802 return 3;
802 } 803 }
803#ifdef PATH_TO_IP 804#ifdef PATH_TO_IP
804 if (0 == access(PATH_TO_IP, X_OK)) 805 if (0 == access (PATH_TO_IP, X_OK))
805 sbin_ip = PATH_TO_IP; 806 sbin_ip = PATH_TO_IP;
806 else 807 else
807#endif 808#endif
808 if (0 == access("/sbin/ip", X_OK)) 809 if (0 == access ("/sbin/ip", X_OK))
809 sbin_ip = "/sbin/ip"; 810 sbin_ip = "/sbin/ip";
810 else if (0 == access("/usr/sbin/ip", X_OK)) 811 else if (0 == access ("/usr/sbin/ip", X_OK))
811 sbin_ip = "/usr/sbin/ip"; 812 sbin_ip = "/usr/sbin/ip";
812 else if (0 == access("/bin/ip", X_OK)) /* gentoo has it there */ 813 else if (0 == access ("/bin/ip", X_OK)) /* gentoo has it there */
813 sbin_ip = "/bin/ip"; 814 sbin_ip = "/bin/ip";
814 else 815 else
815 { 816 {
816 fprintf(stderr, 817 fprintf (stderr,
817 "Fatal: executable ip not found in approved directories: %s\n", 818 "Fatal: executable ip not found in approved directories: %s\n",
818 strerror(errno)); 819 strerror (errno));
819 return 4; 820 return 4;
820 } 821 }
821#ifdef SYSCTL 822#ifdef SYSCTL
822 if (0 == access(SYSCTL, X_OK)) 823 if (0 == access (SYSCTL, X_OK))
823 sbin_sysctl = SYSCTL; 824 sbin_sysctl = SYSCTL;
824 else 825 else
825#endif 826#endif
826 if (0 == access("/sbin/sysctl", X_OK)) 827 if (0 == access ("/sbin/sysctl", X_OK))
827 sbin_sysctl = "/sbin/sysctl"; 828 sbin_sysctl = "/sbin/sysctl";
828 else if (0 == access("/usr/sbin/sysctl", X_OK)) 829 else if (0 == access ("/usr/sbin/sysctl", X_OK))
829 sbin_sysctl = "/usr/sbin/sysctl"; 830 sbin_sysctl = "/usr/sbin/sysctl";
830 else 831 else
831 { 832 {
832 fprintf(stderr, 833 fprintf (stderr,
833 "Fatal: executable sysctl not found in approved directories: %s\n", 834 "Fatal: executable sysctl not found in approved directories: %s\n",
834 strerror(errno)); 835 strerror (errno));
835 return 5; 836 return 5;
836 }
837 } 837 }
838 }
838 839
839 /* setup 'mygid' string */ 840 /* setup 'mygid' string */
840 snprintf(mygid, sizeof(mygid), "%d", (int)getegid()); 841 snprintf (mygid, sizeof(mygid), "%d", (int) getegid ());
841 842
842 /* do not die on SIGPIPE */ 843 /* do not die on SIGPIPE */
843 if (SIG_ERR == signal(SIGPIPE, SIG_IGN)) 844 if (SIG_ERR == signal (SIGPIPE, SIG_IGN))
844 { 845 {
845 fprintf(stderr, "Failed to protect against SIGPIPE: %s\n", 846 fprintf (stderr, "Failed to protect against SIGPIPE: %s\n",
846 strerror(errno)); 847 strerror (errno));
847 return 7; 848 return 7;
848 } 849 }
849 850
850 /* setup pipe to shutdown nicely on SIGINT */ 851 /* setup pipe to shutdown nicely on SIGINT */
851 if (0 != pipe(cpipe)) 852 if (0 != pipe (cpipe))
852 { 853 {
853 fprintf(stderr, 854 fprintf (stderr,
854 "Fatal: could not setup control pipe: %s\n", 855 "Fatal: could not setup control pipe: %s\n",
855 strerror(errno)); 856 strerror (errno));
856 return 6; 857 return 6;
857 } 858 }
858 if (cpipe[0] >= FD_SETSIZE) 859 if (cpipe[0] >= FD_SETSIZE)
859 { 860 {
860 fprintf(stderr, "Pipe file descriptor to large: %d", cpipe[0]); 861 fprintf (stderr, "Pipe file descriptor to large: %d", cpipe[0]);
861 (void)close(cpipe[0]); 862 (void) close (cpipe[0]);
862 (void)close(cpipe[1]); 863 (void) close (cpipe[1]);
863 return 6; 864 return 6;
864 } 865 }
865 { 866 {
866 /* make pipe non-blocking, as we theoretically could otherwise block 867 /* make pipe non-blocking, as we theoretically could otherwise block
867 in the signal handler */ 868 in the signal handler */
868 int flags = fcntl(cpipe[1], F_GETFL); 869 int flags = fcntl (cpipe[1], F_GETFL);
869 if (-1 == flags) 870 if (-1 == flags)
870 { 871 {
871 fprintf(stderr, "Failed to read flags for pipe: %s", strerror(errno)); 872 fprintf (stderr, "Failed to read flags for pipe: %s", strerror (errno));
872 (void)close(cpipe[0]); 873 (void) close (cpipe[0]);
873 (void)close(cpipe[1]); 874 (void) close (cpipe[1]);
874 return 6; 875 return 6;
875 } 876 }
876 flags |= O_NONBLOCK; 877 flags |= O_NONBLOCK;
877 if (0 != fcntl(cpipe[1], F_SETFL, flags)) 878 if (0 != fcntl (cpipe[1], F_SETFL, flags))
878 { 879 {
879 fprintf(stderr, "Failed to make pipe non-blocking: %s", strerror(errno)); 880 fprintf (stderr, "Failed to make pipe non-blocking: %s", strerror (
880 (void)close(cpipe[0]); 881 errno));
881 (void)close(cpipe[1]); 882 (void) close (cpipe[0]);
882 return 6; 883 (void) close (cpipe[1]);
883 } 884 return 6;
885 }
884 } 886 }
885 if ((SIG_ERR == signal(SIGTERM, &signal_handler)) || 887 if ((SIG_ERR == signal (SIGTERM, &signal_handler)) ||
886#if (SIGTERM != GNUNET_TERM_SIG) 888#if (SIGTERM != GNUNET_TERM_SIG)
887 (SIG_ERR == signal(GNUNET_TERM_SIG, &signal_handler)) || 889 (SIG_ERR == signal (GNUNET_TERM_SIG, &signal_handler)) ||
888#endif 890#endif
889 (SIG_ERR == signal(SIGINT, &signal_handler)) || 891 (SIG_ERR == signal (SIGINT, &signal_handler)) ||
890 (SIG_ERR == signal(SIGHUP, &signal_handler))) 892 (SIG_ERR == signal (SIGHUP, &signal_handler)))
891 { 893 {
892 fprintf(stderr, 894 fprintf (stderr,
893 "Fatal: could not initialize signal handler: %s\n", 895 "Fatal: could not initialize signal handler: %s\n",
894 strerror(errno)); 896 strerror (errno));
895 (void)close(cpipe[0]); 897 (void) close (cpipe[0]);
896 (void)close(cpipe[1]); 898 (void) close (cpipe[1]);
897 return 7; 899 return 7;
898 } 900 }
899 901
900 902
901 /* get interface name */ 903 /* get interface name */
902 strncpy(dev, argv[1], IFNAMSIZ); 904 strncpy (dev, argv[1], IFNAMSIZ);
903 dev[IFNAMSIZ - 1] = '\0'; 905 dev[IFNAMSIZ - 1] = '\0';
904 906
905 /* Disable rp filtering */ 907 /* Disable rp filtering */
906 if (0 == nortsetup) 908 if (0 == nortsetup)
909 {
910 char *const sysctl_args[] = { "sysctl", "-w",
911 "net.ipv4.conf.all.rp_filter=0", NULL };
912 char *const sysctl_args2[] = { "sysctl", "-w",
913 "net.ipv4.conf.default.rp_filter=0", NULL };
914 if ((0 != fork_and_exec (sbin_sysctl, sysctl_args)) ||
915 (0 != fork_and_exec (sbin_sysctl, sysctl_args2)))
907 { 916 {
908 char *const sysctl_args[] = { "sysctl", "-w", 917 fprintf (stderr,
909 "net.ipv4.conf.all.rp_filter=0", NULL }; 918 "Failed to disable rp filtering.\n");
910 char *const sysctl_args2[] = { "sysctl", "-w", 919 return 5;
911 "net.ipv4.conf.default.rp_filter=0", NULL };
912 if ((0 != fork_and_exec(sbin_sysctl, sysctl_args)) ||
913 (0 != fork_and_exec(sbin_sysctl, sysctl_args2)))
914 {
915 fprintf(stderr,
916 "Failed to disable rp filtering.\n");
917 return 5;
918 }
919 } 920 }
921 }
920 922
921 923
922 /* now open virtual interface (first part that requires root) */ 924 /* now open virtual interface (first part that requires root) */
923 if (-1 == (fd_tun = init_tun(dev))) 925 if (-1 == (fd_tun = init_tun (dev)))
924 { 926 {
925 fprintf(stderr, "Fatal: could not initialize tun-interface\n"); 927 fprintf (stderr, "Fatal: could not initialize tun-interface\n");
926 (void)signal(SIGTERM, SIG_IGN); 928 (void) signal (SIGTERM, SIG_IGN);
927#if (SIGTERM != GNUNET_TERM_SIG) 929#if (SIGTERM != GNUNET_TERM_SIG)
928 (void)signal(GNUNET_TERM_SIG, SIG_IGN); 930 (void) signal (GNUNET_TERM_SIG, SIG_IGN);
929#endif 931#endif
930 (void)signal(SIGINT, SIG_IGN); 932 (void) signal (SIGINT, SIG_IGN);
931 (void)signal(SIGHUP, SIG_IGN); 933 (void) signal (SIGHUP, SIG_IGN);
932 (void)close(cpipe[0]); 934 (void) close (cpipe[0]);
933 (void)close(cpipe[1]); 935 (void) close (cpipe[1]);
934 return 5; 936 return 5;
935 } 937 }
936 938
937 /* now set interface addresses */ 939 /* now set interface addresses */
938 { 940 {
939 const char *address = argv[2]; 941 const char *address = argv[2];
940 long prefix_len = atol(argv[3]); 942 long prefix_len = atol (argv[3]);
941 943
942 if ((prefix_len < 1) || (prefix_len > 127)) 944 if ((prefix_len < 1) || (prefix_len > 127))
943 { 945 {
944 fprintf(stderr, "Fatal: prefix_len out of range\n"); 946 fprintf (stderr, "Fatal: prefix_len out of range\n");
945 (void)signal(SIGTERM, SIG_IGN); 947 (void) signal (SIGTERM, SIG_IGN);
946#if (SIGTERM != GNUNET_TERM_SIG) 948#if (SIGTERM != GNUNET_TERM_SIG)
947 (void)signal(GNUNET_TERM_SIG, SIG_IGN); 949 (void) signal (GNUNET_TERM_SIG, SIG_IGN);
948#endif 950#endif
949 (void)signal(SIGINT, SIG_IGN); 951 (void) signal (SIGINT, SIG_IGN);
950 (void)signal(SIGHUP, SIG_IGN); 952 (void) signal (SIGHUP, SIG_IGN);
951 (void)close(cpipe[0]); 953 (void) close (cpipe[0]);
952 (void)close(cpipe[1]); 954 (void) close (cpipe[1]);
953 return 2; 955 return 2;
954 } 956 }
955 set_address6(dev, address, prefix_len); 957 set_address6 (dev, address, prefix_len);
956 } 958 }
957 959
958 { 960 {
959 const char *address = argv[4]; 961 const char *address = argv[4];
960 const char *mask = argv[5]; 962 const char *mask = argv[5];
961 963
962 set_address4(dev, address, mask); 964 set_address4 (dev, address, mask);
963 } 965 }
964 966
965 967
@@ -968,237 +970,222 @@ main(int argc, char *const*argv)
968 by the 'gnunet-service-dns') and with destination 970 by the 'gnunet-service-dns') and with destination
969 to port 53 on UDP, without hijacking */ 971 to port 53 on UDP, without hijacking */
970 if (0 == nortsetup) 972 if (0 == nortsetup)
973 {
974 r = 8; /* failed to fully setup routing table */
971 { 975 {
972 r = 8; /* failed to fully setup routing table */ 976 char *const mangle_args[] = {
973 { 977 "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
974 char *const mangle_args[] = 978 "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
975 { 979 "ACCEPT", NULL
976 "iptables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p", 980 };
977 "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j", 981 if (0 != fork_and_exec (sbin_iptables, mangle_args))
978 "ACCEPT", NULL 982 goto cleanup_rest;
979 };
980 if (0 != fork_and_exec(sbin_iptables, mangle_args))
981 goto cleanup_rest;
982 }
983 {
984 char *const mangle_args[] =
985 {
986 "ip6tables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
987 "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
988 "ACCEPT", NULL
989 };
990 if (0 != fork_and_exec(sbin_ip6tables, mangle_args))
991 goto cleanup_mangle_1b;
992 }
993 /* Mark all of the other DNS traffic using our mark DNS_MARK,
994 unless it is on a link-local IPv6 address, which we cannot support. */
995 {
996 char *const mark_args[] =
997 {
998 "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
999 "udp", "--dport", DNS_PORT,
1000 "-j", "MARK", "--set-mark", DNS_MARK,
1001 NULL
1002 };
1003 if (0 != fork_and_exec(sbin_iptables, mark_args))
1004 goto cleanup_mangle_1;
1005 }
1006 {
1007 char *const mark_args[] =
1008 {
1009 "ip6tables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
1010 "udp", "--dport", DNS_PORT,
1011 "!", "-s", "fe80::/10", /* this line excludes link-local traffic */
1012 "-j", "MARK", "--set-mark", DNS_MARK,
1013 NULL
1014 };
1015 if (0 != fork_and_exec(sbin_ip6tables, mark_args))
1016 goto cleanup_mark_2b;
1017 }
1018 /* Forward all marked DNS traffic to our DNS_TABLE */
1019 {
1020 char *const forward_args[] =
1021 {
1022 "ip", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1023 };
1024 if (0 != fork_and_exec(sbin_ip, forward_args))
1025 goto cleanup_mark_2;
1026 }
1027 {
1028 char *const forward_args[] =
1029 {
1030 "ip", "-6", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1031 };
1032 if (0 != fork_and_exec(sbin_ip, forward_args))
1033 goto cleanup_forward_3b;
1034 }
1035 /* Finally, add rule in our forwarding table to pass to our virtual interface */
1036 {
1037 char *const route_args[] =
1038 {
1039 "ip", "route", "add", "default", "dev", dev,
1040 "table", DNS_TABLE, NULL
1041 };
1042 if (0 != fork_and_exec(sbin_ip, route_args))
1043 goto cleanup_forward_3;
1044 }
1045 {
1046 char *const route_args[] =
1047 {
1048 "ip", "-6", "route", "add", "default", "dev", dev,
1049 "table", DNS_TABLE, NULL
1050 };
1051 if (0 != fork_and_exec(sbin_ip, route_args))
1052 goto cleanup_route_4b;
1053 }
1054 } 983 }
984 {
985 char *const mangle_args[] = {
986 "ip6tables", "-m", "owner", "-t", "mangle", "-I", "OUTPUT", "1", "-p",
987 "udp", "--gid-owner", mygid, "--dport", DNS_PORT, "-j",
988 "ACCEPT", NULL
989 };
990 if (0 != fork_and_exec (sbin_ip6tables, mangle_args))
991 goto cleanup_mangle_1b;
992 }
993 /* Mark all of the other DNS traffic using our mark DNS_MARK,
994 unless it is on a link-local IPv6 address, which we cannot support. */
995 {
996 char *const mark_args[] = {
997 "iptables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
998 "udp", "--dport", DNS_PORT,
999 "-j", "MARK", "--set-mark", DNS_MARK,
1000 NULL
1001 };
1002 if (0 != fork_and_exec (sbin_iptables, mark_args))
1003 goto cleanup_mangle_1;
1004 }
1005 {
1006 char *const mark_args[] = {
1007 "ip6tables", "-t", "mangle", "-I", "OUTPUT", "2", "-p",
1008 "udp", "--dport", DNS_PORT,
1009 "!", "-s", "fe80::/10", /* this line excludes link-local traffic */
1010 "-j", "MARK", "--set-mark", DNS_MARK,
1011 NULL
1012 };
1013 if (0 != fork_and_exec (sbin_ip6tables, mark_args))
1014 goto cleanup_mark_2b;
1015 }
1016 /* Forward all marked DNS traffic to our DNS_TABLE */
1017 {
1018 char *const forward_args[] = {
1019 "ip", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1020 };
1021 if (0 != fork_and_exec (sbin_ip, forward_args))
1022 goto cleanup_mark_2;
1023 }
1024 {
1025 char *const forward_args[] = {
1026 "ip", "-6", "rule", "add", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1027 };
1028 if (0 != fork_and_exec (sbin_ip, forward_args))
1029 goto cleanup_forward_3b;
1030 }
1031 /* Finally, add rule in our forwarding table to pass to our virtual interface */
1032 {
1033 char *const route_args[] = {
1034 "ip", "route", "add", "default", "dev", dev,
1035 "table", DNS_TABLE, NULL
1036 };
1037 if (0 != fork_and_exec (sbin_ip, route_args))
1038 goto cleanup_forward_3;
1039 }
1040 {
1041 char *const route_args[] = {
1042 "ip", "-6", "route", "add", "default", "dev", dev,
1043 "table", DNS_TABLE, NULL
1044 };
1045 if (0 != fork_and_exec (sbin_ip, route_args))
1046 goto cleanup_route_4b;
1047 }
1048 }
1055 1049
1056 /* drop privs *except* for the saved UID; this is not perfect, but better 1050 /* drop privs *except* for the saved UID; this is not perfect, but better
1057 than doing nothing */ 1051 than doing nothing */
1058#ifdef HAVE_SETRESUID 1052#ifdef HAVE_SETRESUID
1059 if (0 != setresuid(uid, uid, 0)) 1053 if (0 != setresuid (uid, uid, 0))
1060 { 1054 {
1061 fprintf(stderr, "Failed to setresuid: %s\n", strerror(errno)); 1055 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
1062 r = 24; 1056 r = 24;
1063 goto cleanup_route_4; 1057 goto cleanup_route_4;
1064 } 1058 }
1065#else 1059#else
1066 /* Note: no 'setuid' here as we must keep our saved UID as root */ 1060 /* Note: no 'setuid' here as we must keep our saved UID as root */
1067 if (0 != seteuid(uid)) 1061 if (0 != seteuid (uid))
1068 { 1062 {
1069 fprintf(stderr, "Failed to seteuid: %s\n", strerror(errno)); 1063 fprintf (stderr, "Failed to seteuid: %s\n", strerror (errno));
1070 r = 24; 1064 r = 24;
1071 goto cleanup_route_4; 1065 goto cleanup_route_4;
1072 } 1066 }
1073#endif 1067#endif
1074 1068
1075 r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */ 1069 r = 0; /* did fully setup routing table (if nothing else happens, we were successful!) */
1076 1070
1077 /* now forward until we hit a problem */ 1071 /* now forward until we hit a problem */
1078 run(fd_tun); 1072 run (fd_tun);
1079 1073
1080 /* now need to regain privs so we can remove the firewall rules we added! */ 1074 /* now need to regain privs so we can remove the firewall rules we added! */
1081#ifdef HAVE_SETRESUID 1075#ifdef HAVE_SETRESUID
1082 if (0 != setresuid(uid, 0, 0)) 1076 if (0 != setresuid (uid, 0, 0))
1083 { 1077 {
1084 fprintf(stderr, "Failed to setresuid back to root: %s\n", strerror(errno)); 1078 fprintf (stderr, "Failed to setresuid back to root: %s\n", strerror (
1085 r = 40; 1079 errno));
1086 goto cleanup_route_4; 1080 r = 40;
1087 } 1081 goto cleanup_route_4;
1082 }
1088#else 1083#else
1089 if (0 != seteuid(0)) 1084 if (0 != seteuid (0))
1090 { 1085 {
1091 fprintf(stderr, "Failed to seteuid back to root: %s\n", strerror(errno)); 1086 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
1092 r = 40; 1087 r = 40;
1093 goto cleanup_route_4; 1088 goto cleanup_route_4;
1094 } 1089 }
1095#endif 1090#endif
1096 1091
1097 /* update routing tables again -- this is why we could not fully drop privs */ 1092 /* update routing tables again -- this is why we could not fully drop privs */
1098 /* now undo updating of routing tables; normal exit or clean-up-on-error case */ 1093 /* now undo updating of routing tables; normal exit or clean-up-on-error case */
1099cleanup_route_4: 1094cleanup_route_4:
1100 if (0 == nortsetup) 1095 if (0 == nortsetup)
1101 { 1096 {
1102 char *const route_clean_args[] = 1097 char *const route_clean_args[] = {
1103 { 1098 "ip", "-6", "route", "del", "default", "dev", dev,
1104 "ip", "-6", "route", "del", "default", "dev", dev, 1099 "table", DNS_TABLE, NULL
1105 "table", DNS_TABLE, NULL 1100 };
1106 }; 1101 if (0 != fork_and_exec (sbin_ip, route_clean_args))
1107 if (0 != fork_and_exec(sbin_ip, route_clean_args)) 1102 r += 1;
1108 r += 1; 1103 }
1109 }
1110cleanup_route_4b: 1104cleanup_route_4b:
1111 if (0 == nortsetup) 1105 if (0 == nortsetup)
1112 { 1106 {
1113 char *const route_clean_args[] = 1107 char *const route_clean_args[] = {
1114 { 1108 "ip", "route", "del", "default", "dev", dev,
1115 "ip", "route", "del", "default", "dev", dev, 1109 "table", DNS_TABLE, NULL
1116 "table", DNS_TABLE, NULL 1110 };
1117 }; 1111 if (0 != fork_and_exec (sbin_ip, route_clean_args))
1118 if (0 != fork_and_exec(sbin_ip, route_clean_args)) 1112 r += 1;
1119 r += 1; 1113 }
1120 }
1121cleanup_forward_3: 1114cleanup_forward_3:
1122 if (0 == nortsetup) 1115 if (0 == nortsetup)
1123 { 1116 {
1124 char *const forward_clean_args[] = 1117 char *const forward_clean_args[] = {
1125 { 1118 "ip", "-6", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1126 "ip", "-6", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL 1119 };
1127 }; 1120 if (0 != fork_and_exec (sbin_ip, forward_clean_args))
1128 if (0 != fork_and_exec(sbin_ip, forward_clean_args)) 1121 r += 2;
1129 r += 2; 1122 }
1130 }
1131cleanup_forward_3b: 1123cleanup_forward_3b:
1132 if (0 == nortsetup) 1124 if (0 == nortsetup)
1133 { 1125 {
1134 char *const forward_clean_args[] = 1126 char *const forward_clean_args[] = {
1135 { 1127 "ip", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL
1136 "ip", "rule", "del", "fwmark", DNS_MARK, "table", DNS_TABLE, NULL 1128 };
1137 }; 1129 if (0 != fork_and_exec (sbin_ip, forward_clean_args))
1138 if (0 != fork_and_exec(sbin_ip, forward_clean_args)) 1130 r += 2;
1139 r += 2; 1131 }
1140 }
1141cleanup_mark_2: 1132cleanup_mark_2:
1142 if (0 == nortsetup) 1133 if (0 == nortsetup)
1143 { 1134 {
1144 char *const mark_clean_args[] = 1135 char *const mark_clean_args[] = {
1145 { 1136 "ip6tables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1146 "ip6tables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", 1137 "--dport", DNS_PORT,
1147 "--dport", DNS_PORT, 1138 "!", "-s", "fe80::/10", /* this line excludes link-local traffic */
1148 "!", "-s", "fe80::/10", /* this line excludes link-local traffic */ 1139 "-j", "MARK", "--set-mark", DNS_MARK, NULL
1149 "-j", "MARK", "--set-mark", DNS_MARK, NULL 1140 };
1150 }; 1141 if (0 != fork_and_exec (sbin_ip6tables, mark_clean_args))
1151 if (0 != fork_and_exec(sbin_ip6tables, mark_clean_args)) 1142 r += 4;
1152 r += 4; 1143 }
1153 }
1154cleanup_mark_2b: 1144cleanup_mark_2b:
1155 if (0 == nortsetup) 1145 if (0 == nortsetup)
1156 { 1146 {
1157 char *const mark_clean_args[] = 1147 char *const mark_clean_args[] = {
1158 { 1148 "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1159 "iptables", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", 1149 "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL
1160 "--dport", DNS_PORT, "-j", "MARK", "--set-mark", DNS_MARK, NULL 1150 };
1161 }; 1151 if (0 != fork_and_exec (sbin_iptables, mark_clean_args))
1162 if (0 != fork_and_exec(sbin_iptables, mark_clean_args)) 1152 r += 4;
1163 r += 4; 1153 }
1164 }
1165cleanup_mangle_1: 1154cleanup_mangle_1:
1166 if (0 == nortsetup) 1155 if (0 == nortsetup)
1167 { 1156 {
1168 char *const mangle_clean_args[] = 1157 char *const mangle_clean_args[] = {
1169 { 1158 "ip6tables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1170 "ip6tables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", 1159 "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
1171 "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", 1160 NULL
1172 NULL 1161 };
1173 }; 1162 if (0 != fork_and_exec (sbin_ip6tables, mangle_clean_args))
1174 if (0 != fork_and_exec(sbin_ip6tables, mangle_clean_args)) 1163 r += 8;
1175 r += 8; 1164 }
1176 }
1177cleanup_mangle_1b: 1165cleanup_mangle_1b:
1178 if (0 == nortsetup) 1166 if (0 == nortsetup)
1179 { 1167 {
1180 char *const mangle_clean_args[] = 1168 char *const mangle_clean_args[] = {
1181 { 1169 "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp",
1182 "iptables", "-m", "owner", "-t", "mangle", "-D", "OUTPUT", "-p", "udp", 1170 "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT",
1183 "--gid-owner", mygid, "--dport", DNS_PORT, "-j", "ACCEPT", 1171 NULL
1184 NULL 1172 };
1185 }; 1173 if (0 != fork_and_exec (sbin_iptables, mangle_clean_args))
1186 if (0 != fork_and_exec(sbin_iptables, mangle_clean_args)) 1174 r += 8;
1187 r += 8; 1175 }
1188 }
1189 1176
1190cleanup_rest: 1177cleanup_rest:
1191 /* close virtual interface */ 1178 /* close virtual interface */
1192 (void)close(fd_tun); 1179 (void) close (fd_tun);
1193 /* remove signal handler so we can close the pipes */ 1180 /* remove signal handler so we can close the pipes */
1194 (void)signal(SIGTERM, SIG_IGN); 1181 (void) signal (SIGTERM, SIG_IGN);
1195#if (SIGTERM != GNUNET_TERM_SIG) 1182#if (SIGTERM != GNUNET_TERM_SIG)
1196 (void)signal(GNUNET_TERM_SIG, SIG_IGN); 1183 (void) signal (GNUNET_TERM_SIG, SIG_IGN);
1197#endif 1184#endif
1198 (void)signal(SIGINT, SIG_IGN); 1185 (void) signal (SIGINT, SIG_IGN);
1199 (void)signal(SIGHUP, SIG_IGN); 1186 (void) signal (SIGHUP, SIG_IGN);
1200 (void)close(cpipe[0]); 1187 (void) close (cpipe[0]);
1201 (void)close(cpipe[1]); 1188 (void) close (cpipe[1]);
1202 return r; 1189 return r;
1203} 1190}
1204 1191