| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: inetd.c,v 1.133 2021/09/03 19:33:51 rillig Exp $ */ | | 1 | /* $NetBSD: inetd.c,v 1.134 2021/09/03 20:24:28 rillig Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, |
9 | * NASA Ames Research Center and by Matthias Scheler. | | 9 | * NASA Ames Research Center and by Matthias Scheler. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -56,27 +56,27 @@ | | | @@ -56,27 +56,27 @@ |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
59 | * SUCH DAMAGE. | | 59 | * SUCH DAMAGE. |
60 | */ | | 60 | */ |
61 | | | 61 | |
62 | #include <sys/cdefs.h> | | 62 | #include <sys/cdefs.h> |
63 | #ifndef lint | | 63 | #ifndef lint |
64 | __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\ | | 64 | __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\ |
65 | The Regents of the University of California. All rights reserved."); | | 65 | The Regents of the University of California. All rights reserved."); |
66 | #if 0 | | 66 | #if 0 |
67 | static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; | | 67 | static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; |
68 | #else | | 68 | #else |
69 | __RCSID("$NetBSD: inetd.c,v 1.133 2021/09/03 19:33:51 rillig Exp $"); | | 69 | __RCSID("$NetBSD: inetd.c,v 1.134 2021/09/03 20:24:28 rillig Exp $"); |
70 | #endif | | 70 | #endif |
71 | #endif /* not lint */ | | 71 | #endif /* not lint */ |
72 | | | 72 | |
73 | /* | | 73 | /* |
74 | * Inetd - Internet super-server | | 74 | * Inetd - Internet super-server |
75 | * | | 75 | * |
76 | * This program invokes all internet services as needed. Connection-oriented | | 76 | * This program invokes all internet services as needed. Connection-oriented |
77 | * services are invoked each time a connection is made, by creating a process. | | 77 | * services are invoked each time a connection is made, by creating a process. |
78 | * This process is passed the connection as file descriptor 0 and is expected | | 78 | * This process is passed the connection as file descriptor 0 and is expected |
79 | * to do a getpeername to find out the source host and port. | | 79 | * to do a getpeername to find out the source host and port. |
80 | * | | 80 | * |
81 | * Datagram oriented services are invoked when a datagram | | 81 | * Datagram oriented services are invoked when a datagram |
82 | * arrives; a process is created and passed a pending message | | 82 | * arrives; a process is created and passed a pending message |
| @@ -327,48 +327,48 @@ static void clear_ip_list(struct servtab | | | @@ -327,48 +327,48 @@ static void clear_ip_list(struct servtab |
327 | static time_t rl_time(void); | | 327 | static time_t rl_time(void); |
328 | static void rl_get_name(struct servtab *, int, char *); | | 328 | static void rl_get_name(struct servtab *, int, char *); |
329 | static void rl_drop_connection(struct servtab *, int); | | 329 | static void rl_drop_connection(struct servtab *, int); |
330 | | | 330 | |
331 | struct biltin { | | 331 | struct biltin { |
332 | const char *bi_service; /* internally provided service name */ | | 332 | const char *bi_service; /* internally provided service name */ |
333 | int bi_socktype; /* type of socket supported */ | | 333 | int bi_socktype; /* type of socket supported */ |
334 | short bi_fork; /* 1 if should fork before call */ | | 334 | short bi_fork; /* 1 if should fork before call */ |
335 | short bi_wait; /* 1 if should wait for child */ | | 335 | short bi_wait; /* 1 if should wait for child */ |
336 | void (*bi_fn)(int, struct servtab *); | | 336 | void (*bi_fn)(int, struct servtab *); |
337 | /* function which performs it */ | | 337 | /* function which performs it */ |
338 | } biltins[] = { | | 338 | } biltins[] = { |
339 | /* Echo received data */ | | 339 | /* Echo received data */ |
340 | { "echo", SOCK_STREAM, 1, 0, echo_stream }, | | 340 | { "echo", SOCK_STREAM, true, false, echo_stream }, |
341 | { "echo", SOCK_DGRAM, 0, 0, echo_dg }, | | 341 | { "echo", SOCK_DGRAM, false, false, echo_dg }, |
342 | | | 342 | |
343 | /* Internet /dev/null */ | | 343 | /* Internet /dev/null */ |
344 | { "discard", SOCK_STREAM, 1, 0, discard_stream }, | | 344 | { "discard", SOCK_STREAM, true, false, discard_stream }, |
345 | { "discard", SOCK_DGRAM, 0, 0, discard_dg }, | | 345 | { "discard", SOCK_DGRAM, false, false, discard_dg }, |
346 | | | 346 | |
347 | /* Return 32 bit time since 1970 */ | | 347 | /* Return 32 bit time since 1970 */ |
348 | { "time", SOCK_STREAM, 0, 0, machtime_stream }, | | 348 | { "time", SOCK_STREAM, false, false, machtime_stream }, |
349 | { "time", SOCK_DGRAM, 0, 0, machtime_dg }, | | 349 | { "time", SOCK_DGRAM, false, false, machtime_dg }, |
350 | | | 350 | |
351 | /* Return human-readable time */ | | 351 | /* Return human-readable time */ |
352 | { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, | | 352 | { "daytime", SOCK_STREAM, false, false, daytime_stream }, |
353 | { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, | | 353 | { "daytime", SOCK_DGRAM, false, false, daytime_dg }, |
354 | | | 354 | |
355 | /* Familiar character generator */ | | 355 | /* Familiar character generator */ |
356 | { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, | | 356 | { "chargen", SOCK_STREAM, true, false, chargen_stream }, |
357 | { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, | | 357 | { "chargen", SOCK_DGRAM, false, false, chargen_dg }, |
358 | | | 358 | |
359 | { "tcpmux", SOCK_STREAM, 1, 0, tcpmux }, | | 359 | { "tcpmux", SOCK_STREAM, true, false, tcpmux }, |
360 | | | 360 | |
361 | { NULL, 0, 0, 0, NULL } | | 361 | { NULL, 0, false, false, NULL } |
362 | }; | | 362 | }; |
363 | | | 363 | |
364 | /* list of "bad" ports. I.e. ports that are most obviously used for | | 364 | /* list of "bad" ports. I.e. ports that are most obviously used for |
365 | * "cycling packets" denial of service attacks. See /etc/services. | | 365 | * "cycling packets" denial of service attacks. See /etc/services. |
366 | * List must end with port number "0". | | 366 | * List must end with port number "0". |
367 | */ | | 367 | */ |
368 | | | 368 | |
369 | u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 }; | | 369 | u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 }; |
370 | | | 370 | |
371 | | | 371 | |
372 | #define NUMINT (sizeof(intab) / sizeof(struct inent)) | | 372 | #define NUMINT (sizeof(intab) / sizeof(struct inent)) |
373 | const char *CONFIG = _PATH_INETDCONF; | | 373 | const char *CONFIG = _PATH_INETDCONF; |
374 | | | 374 | |
| @@ -379,32 +379,32 @@ int | | | @@ -379,32 +379,32 @@ int |
379 | main(int argc, char *argv[]) | | 379 | main(int argc, char *argv[]) |
380 | { | | 380 | { |
381 | int ch, n, reload = 1; | | 381 | int ch, n, reload = 1; |
382 | | | 382 | |
383 | while ((ch = getopt(argc, argv, | | 383 | while ((ch = getopt(argc, argv, |
384 | #ifdef LIBWRAP | | 384 | #ifdef LIBWRAP |
385 | "dl" | | 385 | "dl" |
386 | #else | | 386 | #else |
387 | "d" | | 387 | "d" |
388 | #endif | | 388 | #endif |
389 | )) != -1) | | 389 | )) != -1) |
390 | switch(ch) { | | 390 | switch(ch) { |
391 | case 'd': | | 391 | case 'd': |
392 | debug = 1; | | 392 | debug = true; |
393 | options |= SO_DEBUG; | | 393 | options |= SO_DEBUG; |
394 | break; | | 394 | break; |
395 | #ifdef LIBWRAP | | 395 | #ifdef LIBWRAP |
396 | case 'l': | | 396 | case 'l': |
397 | lflag = 1; | | 397 | lflag = true; |
398 | break; | | 398 | break; |
399 | #endif | | 399 | #endif |
400 | case '?': | | 400 | case '?': |
401 | default: | | 401 | default: |
402 | usage(); | | 402 | usage(); |
403 | } | | 403 | } |
404 | argc -= optind; | | 404 | argc -= optind; |
405 | argv += optind; | | 405 | argv += optind; |
406 | | | 406 | |
407 | if (argc > 0) | | 407 | if (argc > 0) |
408 | CONFIG = argv[0]; | | 408 | CONFIG = argv[0]; |
409 | | | 409 | |
410 | if (!debug) | | 410 | if (!debug) |
| @@ -438,220 +438,220 @@ main(int argc, char *argv[]) | | | @@ -438,220 +438,220 @@ main(int argc, char *argv[]) |
438 | | | 438 | |
439 | ev = allocchange(); | | 439 | ev = allocchange(); |
440 | EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, | | 440 | EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, |
441 | 0, 0, 0); | | 441 | 0, 0, 0); |
442 | } | | 442 | } |
443 | } | | 443 | } |
444 | | | 444 | |
445 | for (;;) { | | 445 | for (;;) { |
446 | int ctrl; | | 446 | int ctrl; |
447 | struct kevent eventbuf[64], *ev; | | 447 | struct kevent eventbuf[64], *ev; |
448 | struct servtab *sep; | | 448 | struct servtab *sep; |
449 | | | 449 | |
450 | if (reload) { | | 450 | if (reload) { |
451 | reload = 0; | | 451 | reload = false; |
452 | config_root(); | | 452 | config_root(); |
453 | } | | 453 | } |
454 | | | 454 | |
455 | n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf)); | | 455 | n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf)); |
456 | changes = 0; | | 456 | changes = 0; |
457 | | | 457 | |
458 | for (ev = eventbuf; n > 0; ev++, n--) { | | 458 | for (ev = eventbuf; n > 0; ev++, n--) { |
459 | if (ev->filter == EVFILT_SIGNAL) { | | 459 | if (ev->filter == EVFILT_SIGNAL) { |
460 | switch (ev->ident) { | | 460 | switch (ev->ident) { |
461 | case SIGALRM: | | 461 | case SIGALRM: |
462 | retry(); | | 462 | retry(); |
463 | break; | | 463 | break; |
464 | case SIGCHLD: | | 464 | case SIGCHLD: |
465 | reapchild(); | | 465 | reapchild(); |
466 | break; | | 466 | break; |
467 | case SIGTERM: | | 467 | case SIGTERM: |
468 | case SIGINT: | | 468 | case SIGINT: |
469 | goaway(); | | 469 | goaway(); |
470 | break; | | 470 | break; |
471 | case SIGHUP: | | 471 | case SIGHUP: |
472 | reload = 1; | | 472 | reload = true; |
473 | break; | | 473 | break; |
474 | } | | 474 | } |
475 | continue; | | 475 | continue; |
476 | } | | 476 | } |
477 | if (ev->filter != EVFILT_READ) | | 477 | if (ev->filter != EVFILT_READ) |
478 | continue; | | 478 | continue; |
479 | sep = (struct servtab *)ev->udata; | | 479 | sep = (struct servtab *)ev->udata; |
480 | /* Paranoia */ | | 480 | /* Paranoia */ |
481 | if ((int)ev->ident != sep->se_fd) | | 481 | if ((int)ev->ident != sep->se_fd) |
482 | continue; | | 482 | continue; |
483 | DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep)); | | 483 | DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep)); |
484 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { | | 484 | if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { |
485 | /* XXX here do the libwrap check-before-accept*/ | | 485 | /* XXX here do the libwrap check-before-accept*/ |
486 | ctrl = accept(sep->se_fd, NULL, NULL); | | 486 | ctrl = accept(sep->se_fd, NULL, NULL); |
487 | DPRINTF(SERV_FMT ": accept, ctrl fd %d", | | 487 | DPRINTF(SERV_FMT ": accept, ctrl fd %d", |
488 | SERV_PARAMS(sep), ctrl); | | 488 | SERV_PARAMS(sep), ctrl); |
489 | if (ctrl < 0) { | | 489 | if (ctrl < 0) { |
490 | if (errno != EINTR) | | 490 | if (errno != EINTR) |
491 | syslog(LOG_WARNING, | | 491 | syslog(LOG_WARNING, |
492 | SERV_FMT ": accept: %m", | | 492 | SERV_FMT ": accept: %m", |
493 | SERV_PARAMS(sep)); | | 493 | SERV_PARAMS(sep)); |
494 | continue; | | 494 | continue; |
495 | } | | 495 | } |
496 | } else | | 496 | } else |
497 | ctrl = sep->se_fd; | | 497 | ctrl = sep->se_fd; |
498 | spawn(sep, ctrl); | | 498 | spawn(sep, ctrl); |
499 | } | | 499 | } |
500 | } | | 500 | } |
501 | } | | 501 | } |
502 | | | 502 | |
503 | static void | | 503 | static void |
504 | spawn(struct servtab *sep, int ctrl) | | 504 | spawn(struct servtab *sep, int ctrl) |
505 | { | | 505 | { |
506 | int dofork; | | 506 | int dofork; |
507 | pid_t pid; | | 507 | pid_t pid; |
508 | | | 508 | |
509 | pid = 0; | | 509 | pid = 0; |
510 | #ifdef LIBWRAP_INTERNAL | | 510 | #ifdef LIBWRAP_INTERNAL |
511 | dofork = 1; | | 511 | dofork = true; |
512 | #else | | 512 | #else |
513 | dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); | | 513 | dofork = (sep->se_bi == NULL || sep->se_bi->bi_fork); |
514 | #endif | | 514 | #endif |
515 | if (dofork) { | | 515 | if (dofork) { |
516 | if (rl_process(sep, ctrl)) { | | 516 | if (rl_process(sep, ctrl)) { |
517 | return; | | 517 | return; |
518 | } | | 518 | } |
519 | pid = fork(); | | 519 | pid = fork(); |
520 | if (pid < 0) { | | 520 | if (pid < 0) { |
521 | syslog(LOG_ERR, "fork: %m"); | | 521 | syslog(LOG_ERR, "fork: %m"); |
522 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | | 522 | if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) |
523 | close(ctrl); | | 523 | close(ctrl); |
524 | sleep(1); | | 524 | sleep(1); |
525 | return; | | 525 | return; |
526 | } | | 526 | } |
527 | if (pid != 0 && sep->se_wait) { | | 527 | if (pid != 0 && sep->se_wait != 0) { |
528 | struct kevent *ev; | | 528 | struct kevent *ev; |
529 | | | 529 | |
530 | sep->se_wait = pid; | | 530 | sep->se_wait = pid; |
531 | ev = allocchange(); | | 531 | ev = allocchange(); |
532 | EV_SET(ev, sep->se_fd, EVFILT_READ, | | 532 | EV_SET(ev, sep->se_fd, EVFILT_READ, |
533 | EV_DELETE, 0, 0, 0); | | 533 | EV_DELETE, 0, 0, 0); |
534 | } | | 534 | } |
535 | if (pid == 0) { | | 535 | if (pid == 0) { |
536 | size_t n; | | 536 | size_t n; |
537 | | | 537 | |
538 | for (n = 0; n < __arraycount(my_signals); n++) | | 538 | for (n = 0; n < __arraycount(my_signals); n++) |
539 | (void) signal(my_signals[n], SIG_DFL); | | 539 | (void) signal(my_signals[n], SIG_DFL); |
540 | if (debug) | | 540 | if (debug) |
541 | setsid(); | | 541 | setsid(); |
542 | } | | 542 | } |
543 | } | | 543 | } |
544 | if (pid == 0) { | | 544 | if (pid == 0) { |
545 | run_service(ctrl, sep, dofork); | | 545 | run_service(ctrl, sep, dofork); |
546 | if (dofork) | | 546 | if (dofork) |
547 | exit(0); | | 547 | exit(0); |
548 | } | | 548 | } |
549 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | | 549 | if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) |
550 | close(ctrl); | | 550 | close(ctrl); |
551 | } | | 551 | } |
552 | | | 552 | |
553 | static void | | 553 | static void |
554 | run_service(int ctrl, struct servtab *sep, int didfork) | | 554 | run_service(int ctrl, struct servtab *sep, int didfork) |
555 | { | | 555 | { |
556 | struct passwd *pwd; | | 556 | struct passwd *pwd; |
557 | struct group *grp = NULL; /* XXX gcc */ | | 557 | struct group *grp = NULL; /* XXX gcc */ |
558 | char buf[NI_MAXSERV]; | | 558 | char buf[NI_MAXSERV]; |
559 | struct servtab *s; | | 559 | struct servtab *s; |
560 | #ifdef LIBWRAP | | 560 | #ifdef LIBWRAP |
561 | char abuf[BUFSIZ]; | | 561 | char abuf[BUFSIZ]; |
562 | struct request_info req; | | 562 | struct request_info req; |
563 | int denied; | | 563 | int denied; |
564 | char *service = NULL; /* XXX gcc */ | | 564 | char *service = NULL; /* XXX gcc */ |
565 | #endif | | 565 | #endif |
566 | | | 566 | |
567 | #ifdef LIBWRAP | | 567 | #ifdef LIBWRAP |
568 | #ifndef LIBWRAP_INTERNAL | | 568 | #ifndef LIBWRAP_INTERNAL |
569 | if (sep->se_bi == 0) | | 569 | if (sep->se_bi == 0) |
570 | #endif | | 570 | #endif |
571 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { | | 571 | if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { |
572 | request_init(&req, RQ_DAEMON, sep->se_argv[0] ? | | 572 | request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ? |
573 | sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); | | 573 | sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); |
574 | fromhost(&req); | | 574 | fromhost(&req); |
575 | denied = !hosts_access(&req); | | 575 | denied = hosts_access(&req) == 0; |
576 | if (denied || lflag) { | | 576 | if (denied || lflag) { |
577 | if (getnameinfo(&sep->se_ctrladdr, | | 577 | if (getnameinfo(&sep->se_ctrladdr, |
578 | (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0, | | 578 | (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0, |
579 | buf, sizeof(buf), 0) != 0) { | | 579 | buf, sizeof(buf), 0) != 0) { |
580 | /* shouldn't happen */ | | 580 | /* shouldn't happen */ |
581 | (void)snprintf(buf, sizeof buf, "%d", | | 581 | (void)snprintf(buf, sizeof buf, "%d", |
582 | ntohs(sep->se_ctrladdr_in.sin_port)); | | 582 | ntohs(sep->se_ctrladdr_in.sin_port)); |
583 | } | | 583 | } |
584 | service = buf; | | 584 | service = buf; |
585 | if (req.client->sin) { | | 585 | if (req.client->sin != NULL) { |
586 | sockaddr_snprintf(abuf, sizeof(abuf), "%a", | | 586 | sockaddr_snprintf(abuf, sizeof(abuf), "%a", |
587 | req.client->sin); | | 587 | req.client->sin); |
588 | } else { | | 588 | } else { |
589 | strcpy(abuf, "(null)"); | | 589 | strcpy(abuf, "(null)"); |
590 | } | | 590 | } |
591 | } | | 591 | } |
592 | if (denied) { | | 592 | if (denied) { |
593 | syslog(deny_severity, | | 593 | syslog(deny_severity, |
594 | "refused connection from %.500s(%s), service %s (%s)", | | 594 | "refused connection from %.500s(%s), service %s (%s)", |
595 | eval_client(&req), abuf, service, sep->se_proto); | | 595 | eval_client(&req), abuf, service, sep->se_proto); |
596 | goto reject; | | 596 | goto reject; |
597 | } | | 597 | } |
598 | if (lflag) { | | 598 | if (lflag) { |
599 | syslog(allow_severity, | | 599 | syslog(allow_severity, |
600 | "connection from %.500s(%s), service %s (%s)", | | 600 | "connection from %.500s(%s), service %s (%s)", |
601 | eval_client(&req), abuf, service, sep->se_proto); | | 601 | eval_client(&req), abuf, service, sep->se_proto); |
602 | } | | 602 | } |
603 | } | | 603 | } |
604 | #endif /* LIBWRAP */ | | 604 | #endif /* LIBWRAP */ |
605 | | | 605 | |
606 | if (sep->se_bi) { | | 606 | if (sep->se_bi != NULL) { |
607 | if (didfork) { | | 607 | if (didfork) { |
608 | for (s = servtab; s; s = s->se_next) | | 608 | for (s = servtab; s != NULL; s = s->se_next) |
609 | if (s->se_fd != -1 && s->se_fd != ctrl) { | | 609 | if (s->se_fd != -1 && s->se_fd != ctrl) { |
610 | close(s->se_fd); | | 610 | close(s->se_fd); |
611 | s->se_fd = -1; | | 611 | s->se_fd = -1; |
612 | } | | 612 | } |
613 | } | | 613 | } |
614 | (*sep->se_bi->bi_fn)(ctrl, sep); | | 614 | (*sep->se_bi->bi_fn)(ctrl, sep); |
615 | } else { | | 615 | } else { |
616 | if ((pwd = getpwnam(sep->se_user)) == NULL) { | | 616 | if ((pwd = getpwnam(sep->se_user)) == NULL) { |
617 | syslog(LOG_ERR, "%s/%s: %s: No such user", | | 617 | syslog(LOG_ERR, "%s/%s: %s: No such user", |
618 | sep->se_service, sep->se_proto, sep->se_user); | | 618 | sep->se_service, sep->se_proto, sep->se_user); |
619 | goto reject; | | 619 | goto reject; |
620 | } | | 620 | } |
621 | if (sep->se_group && | | 621 | if (sep->se_group != NULL && |
622 | (grp = getgrnam(sep->se_group)) == NULL) { | | 622 | (grp = getgrnam(sep->se_group)) == NULL) { |
623 | syslog(LOG_ERR, "%s/%s: %s: No such group", | | 623 | syslog(LOG_ERR, "%s/%s: %s: No such group", |
624 | sep->se_service, sep->se_proto, sep->se_group); | | 624 | sep->se_service, sep->se_proto, sep->se_group); |
625 | goto reject; | | 625 | goto reject; |
626 | } | | 626 | } |
627 | if (pwd->pw_uid) { | | 627 | if (pwd->pw_uid != 0) { |
628 | if (sep->se_group) | | 628 | if (sep->se_group != NULL) |
629 | pwd->pw_gid = grp->gr_gid; | | 629 | pwd->pw_gid = grp->gr_gid; |
630 | if (setgid(pwd->pw_gid) < 0) { | | 630 | if (setgid(pwd->pw_gid) < 0) { |
631 | syslog(LOG_ERR, | | 631 | syslog(LOG_ERR, |
632 | "%s/%s: can't set gid %d: %m", sep->se_service, | | 632 | "%s/%s: can't set gid %d: %m", sep->se_service, |
633 | sep->se_proto, pwd->pw_gid); | | 633 | sep->se_proto, pwd->pw_gid); |
634 | goto reject; | | 634 | goto reject; |
635 | } | | 635 | } |
636 | (void) initgroups(pwd->pw_name, | | 636 | (void) initgroups(pwd->pw_name, |
637 | pwd->pw_gid); | | 637 | pwd->pw_gid); |
638 | if (setuid(pwd->pw_uid) < 0) { | | 638 | if (setuid(pwd->pw_uid) < 0) { |
639 | syslog(LOG_ERR, | | 639 | syslog(LOG_ERR, |
640 | "%s/%s: can't set uid %d: %m", sep->se_service, | | 640 | "%s/%s: can't set uid %d: %m", sep->se_service, |
641 | sep->se_proto, pwd->pw_uid); | | 641 | sep->se_proto, pwd->pw_uid); |
642 | goto reject; | | 642 | goto reject; |
643 | } | | 643 | } |
644 | } else if (sep->se_group) { | | 644 | } else if (sep->se_group != NULL) { |
645 | (void) setgid((gid_t)grp->gr_gid); | | 645 | (void) setgid((gid_t)grp->gr_gid); |
646 | } | | 646 | } |
647 | DPRINTF("%d execl %s", | | 647 | DPRINTF("%d execl %s", |
648 | getpid(), sep->se_server); | | 648 | getpid(), sep->se_server); |
649 | /* Set our control descriptor to not close-on-exec... */ | | 649 | /* Set our control descriptor to not close-on-exec... */ |
650 | if (fcntl(ctrl, F_SETFD, 0) < 0) | | 650 | if (fcntl(ctrl, F_SETFD, 0) < 0) |
651 | syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl); | | 651 | syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl); |
652 | /* ...and dup it to stdin, stdout, and stderr. */ | | 652 | /* ...and dup it to stdin, stdout, and stderr. */ |
653 | if (ctrl != 0) { | | 653 | if (ctrl != 0) { |
654 | dup2(ctrl, 0); | | 654 | dup2(ctrl, 0); |
655 | close(ctrl); | | 655 | close(ctrl); |
656 | ctrl = 0; | | 656 | ctrl = 0; |
657 | } | | 657 | } |
| @@ -816,90 +816,90 @@ config(void) | | | @@ -816,90 +816,90 @@ config(void) |
816 | char *host; | | 816 | char *host; |
817 | const char *port; | | 817 | const char *port; |
818 | int error; | | 818 | int error; |
819 | int s; | | 819 | int s; |
820 | | | 820 | |
821 | /* check if the family is supported */ | | 821 | /* check if the family is supported */ |
822 | s = socket(sep->se_family, SOCK_DGRAM, 0); | | 822 | s = socket(sep->se_family, SOCK_DGRAM, 0); |
823 | if (s < 0) { | | 823 | if (s < 0) { |
824 | syslog(LOG_WARNING, | | 824 | syslog(LOG_WARNING, |
825 | "%s/%s: %s: the address family is not " | | 825 | "%s/%s: %s: the address family is not " |
826 | "supported by the kernel", | | 826 | "supported by the kernel", |
827 | sep->se_service, sep->se_proto, | | 827 | sep->se_service, sep->se_proto, |
828 | sep->se_hostaddr); | | 828 | sep->se_hostaddr); |
829 | sep->se_checked = 0; | | 829 | sep->se_checked = false; |
830 | continue; | | 830 | continue; |
831 | } | | 831 | } |
832 | close(s); | | 832 | close(s); |
833 | | | 833 | |
834 | memset(&hints, 0, sizeof(hints)); | | 834 | memset(&hints, 0, sizeof(hints)); |
835 | hints.ai_family = sep->se_family; | | 835 | hints.ai_family = sep->se_family; |
836 | hints.ai_socktype = sep->se_socktype; | | 836 | hints.ai_socktype = sep->se_socktype; |
837 | hints.ai_flags = AI_PASSIVE; | | 837 | hints.ai_flags = AI_PASSIVE; |
838 | if (!strcmp(sep->se_hostaddr, "*")) | | 838 | if (strcmp(sep->se_hostaddr, "*") == 0) |
839 | host = NULL; | | 839 | host = NULL; |
840 | else | | 840 | else |
841 | host = sep->se_hostaddr; | | 841 | host = sep->se_hostaddr; |
842 | if (isrpcservice(sep) || ISMUX(sep)) | | 842 | if (isrpcservice(sep) || ISMUX(sep)) |
843 | port = "0"; | | 843 | port = "0"; |
844 | else | | 844 | else |
845 | port = sep->se_service; | | 845 | port = sep->se_service; |
846 | error = getaddrinfo(host, port, &hints, &res); | | 846 | error = getaddrinfo(host, port, &hints, &res); |
847 | if (error) { | | 847 | if (error != 0) { |
848 | if (error == EAI_SERVICE) { | | 848 | if (error == EAI_SERVICE) { |
849 | /* gai_strerror not friendly enough */ | | 849 | /* gai_strerror not friendly enough */ |
850 | syslog(LOG_WARNING, SERV_FMT ": " | | 850 | syslog(LOG_WARNING, SERV_FMT ": " |
851 | "unknown service", | | 851 | "unknown service", |
852 | SERV_PARAMS(sep)); | | 852 | SERV_PARAMS(sep)); |
853 | } else { | | 853 | } else { |
854 | syslog(LOG_ERR, SERV_FMT ": %s: %s", | | 854 | syslog(LOG_ERR, SERV_FMT ": %s: %s", |
855 | SERV_PARAMS(sep), | | 855 | SERV_PARAMS(sep), |
856 | sep->se_hostaddr, | | 856 | sep->se_hostaddr, |
857 | gai_strerror(error)); | | 857 | gai_strerror(error)); |
858 | } | | 858 | } |
859 | sep->se_checked = 0; | | 859 | sep->se_checked = false; |
860 | continue; | | 860 | continue; |
861 | } | | 861 | } |
862 | if (res->ai_next) { | | 862 | if (res->ai_next != NULL) { |
863 | syslog(LOG_ERR, | | 863 | syslog(LOG_ERR, |
864 | SERV_FMT ": %s: resolved to multiple addr", | | 864 | SERV_FMT ": %s: resolved to multiple addr", |
865 | SERV_PARAMS(sep), | | 865 | SERV_PARAMS(sep), |
866 | sep->se_hostaddr); | | 866 | sep->se_hostaddr); |
867 | sep->se_checked = 0; | | 867 | sep->se_checked = false; |
868 | freeaddrinfo(res); | | 868 | freeaddrinfo(res); |
869 | continue; | | 869 | continue; |
870 | } | | 870 | } |
871 | memcpy(&sep->se_ctrladdr, res->ai_addr, | | 871 | memcpy(&sep->se_ctrladdr, res->ai_addr, |
872 | res->ai_addrlen); | | 872 | res->ai_addrlen); |
873 | if (ISMUX(sep)) { | | 873 | if (ISMUX(sep)) { |
874 | sep->se_fd = -1; | | 874 | sep->se_fd = -1; |
875 | freeaddrinfo(res); | | 875 | freeaddrinfo(res); |
876 | continue; | | 876 | continue; |
877 | } | | 877 | } |
878 | sep->se_ctrladdr_size = res->ai_addrlen; | | 878 | sep->se_ctrladdr_size = res->ai_addrlen; |
879 | freeaddrinfo(res); | | 879 | freeaddrinfo(res); |
880 | #ifdef RPC | | 880 | #ifdef RPC |
881 | if (isrpcservice(sep)) { | | 881 | if (isrpcservice(sep)) { |
882 | struct rpcent *rp; | | 882 | struct rpcent *rp; |
883 | | | 883 | |
884 | sep->se_rpcprog = atoi(sep->se_service); | | 884 | sep->se_rpcprog = atoi(sep->se_service); |
885 | if (sep->se_rpcprog == 0) { | | 885 | if (sep->se_rpcprog == 0) { |
886 | rp = getrpcbyname(sep->se_service); | | 886 | rp = getrpcbyname(sep->se_service); |
887 | if (rp == 0) { | | 887 | if (rp == 0) { |
888 | syslog(LOG_ERR, | | 888 | syslog(LOG_ERR, |
889 | SERV_FMT | | 889 | SERV_FMT |
890 | ": unknown service", | | 890 | ": unknown service", |
891 | SERV_PARAMS(sep)); | | 891 | SERV_PARAMS(sep)); |
892 | sep->se_checked = 0; | | 892 | sep->se_checked = false; |
893 | continue; | | 893 | continue; |
894 | } | | 894 | } |
895 | sep->se_rpcprog = rp->r_number; | | 895 | sep->se_rpcprog = rp->r_number; |
896 | } | | 896 | } |
897 | if (sep->se_fd == -1 && !ISMUX(sep)) | | 897 | if (sep->se_fd == -1 && !ISMUX(sep)) |
898 | setup(sep); | | 898 | setup(sep); |
899 | if (sep->se_fd != -1) | | 899 | if (sep->se_fd != -1) |
900 | register_rpc(sep); | | 900 | register_rpc(sep); |
901 | } else | | 901 | } else |
902 | #endif | | 902 | #endif |
903 | { | | 903 | { |
904 | if (sep->se_fd >= 0) | | 904 | if (sep->se_fd >= 0) |
905 | close_sep(sep); | | 905 | close_sep(sep); |
| @@ -907,27 +907,27 @@ config(void) | | | @@ -907,27 +907,27 @@ config(void) |
907 | setup(sep); | | 907 | setup(sep); |
908 | } | | 908 | } |
909 | } | | 909 | } |
910 | } | | 910 | } |
911 | } | | 911 | } |
912 | endconfig(); | | 912 | endconfig(); |
913 | } | | 913 | } |
914 | | | 914 | |
915 | static void | | 915 | static void |
916 | retry(void) | | 916 | retry(void) |
917 | { | | 917 | { |
918 | struct servtab *sep; | | 918 | struct servtab *sep; |
919 | | | 919 | |
920 | timingout = 0; | | 920 | timingout = false; |
921 | for (sep = servtab; sep != NULL; sep = sep->se_next) { | | 921 | for (sep = servtab; sep != NULL; sep = sep->se_next) { |
922 | if (sep->se_fd == -1 && !ISMUX(sep)) { | | 922 | if (sep->se_fd == -1 && !ISMUX(sep)) { |
923 | switch (sep->se_family) { | | 923 | switch (sep->se_family) { |
924 | case AF_LOCAL: | | 924 | case AF_LOCAL: |
925 | case AF_INET: | | 925 | case AF_INET: |
926 | #ifdef INET6 | | 926 | #ifdef INET6 |
927 | case AF_INET6: | | 927 | case AF_INET6: |
928 | #endif | | 928 | #endif |
929 | setup(sep); | | 929 | setup(sep); |
930 | if (sep->se_fd >= 0 && isrpcservice(sep)) | | 930 | if (sep->se_fd >= 0 && isrpcservice(sep)) |
931 | register_rpc(sep); | | 931 | register_rpc(sep); |
932 | break; | | 932 | break; |
933 | } | | 933 | } |
| @@ -1026,27 +1026,27 @@ setsockopt(fd, SOL_SOCKET, opt, &on, (so | | | @@ -1026,27 +1026,27 @@ setsockopt(fd, SOL_SOCKET, opt, &on, (so |
1026 | return; | | 1026 | return; |
1027 | } | | 1027 | } |
1028 | } | | 1028 | } |
1029 | #endif | | 1029 | #endif |
1030 | | | 1030 | |
1031 | if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { | | 1031 | if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { |
1032 | DPRINTF(SERV_FMT ": bind failed: %s", | | 1032 | DPRINTF(SERV_FMT ": bind failed: %s", |
1033 | SERV_PARAMS(sep), strerror(errno)); | | 1033 | SERV_PARAMS(sep), strerror(errno)); |
1034 | syslog(LOG_ERR, SERV_FMT ": bind: %m", | | 1034 | syslog(LOG_ERR, SERV_FMT ": bind: %m", |
1035 | SERV_PARAMS(sep)); | | 1035 | SERV_PARAMS(sep)); |
1036 | (void) close(sep->se_fd); | | 1036 | (void) close(sep->se_fd); |
1037 | sep->se_fd = -1; | | 1037 | sep->se_fd = -1; |
1038 | if (!timingout) { | | 1038 | if (!timingout) { |
1039 | timingout = 1; | | 1039 | timingout = true; |
1040 | alarm(RETRYTIME); | | 1040 | alarm(RETRYTIME); |
1041 | } | | 1041 | } |
1042 | return; | | 1042 | return; |
1043 | } | | 1043 | } |
1044 | if (sep->se_socktype == SOCK_STREAM) | | 1044 | if (sep->se_socktype == SOCK_STREAM) |
1045 | listen(sep->se_fd, 10); | | 1045 | listen(sep->se_fd, 10); |
1046 | | | 1046 | |
1047 | /* Set the accept filter, if specified. To be done after listen.*/ | | 1047 | /* Set the accept filter, if specified. To be done after listen.*/ |
1048 | if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET, | | 1048 | if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET, |
1049 | SO_ACCEPTFILTER, &sep->se_accf, | | 1049 | SO_ACCEPTFILTER, &sep->se_accf, |
1050 | (socklen_t)sizeof(sep->se_accf)) < 0) | | 1050 | (socklen_t)sizeof(sep->se_accf)) < 0) |
1051 | syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m", | | 1051 | syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m", |
1052 | sep->se_accf.af_name); | | 1052 | sep->se_accf.af_name); |
| @@ -1099,51 +1099,51 @@ register_rpc(struct servtab *sep) | | | @@ -1099,51 +1099,51 @@ register_rpc(struct servtab *sep) |
1099 | syslog(LOG_ERR, SERV_FMT ": getsockname: %m", | | 1099 | syslog(LOG_ERR, SERV_FMT ": getsockname: %m", |
1100 | SERV_PARAMS(sep)); | | 1100 | SERV_PARAMS(sep)); |
1101 | return; | | 1101 | return; |
1102 | } | | 1102 | } |
1103 | | | 1103 | |
1104 | nbuf.buf = &ss; | | 1104 | nbuf.buf = &ss; |
1105 | nbuf.len = ss.ss_len; | | 1105 | nbuf.len = ss.ss_len; |
1106 | nbuf.maxlen = sizeof (struct sockaddr_storage); | | 1106 | nbuf.maxlen = sizeof (struct sockaddr_storage); |
1107 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { | | 1107 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { |
1108 | DPRINTF("rpcb_set: %u %d %s %s", | | 1108 | DPRINTF("rpcb_set: %u %d %s %s", |
1109 | sep->se_rpcprog, n, nconf->nc_netid, | | 1109 | sep->se_rpcprog, n, nconf->nc_netid, |
1110 | taddr2uaddr(nconf, &nbuf)); | | 1110 | taddr2uaddr(nconf, &nbuf)); |
1111 | (void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf); | | 1111 | (void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf); |
1112 | if (!rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf)) | | 1112 | if (rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf) == 0) |
1113 | syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s", | | 1113 | syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s", |
1114 | sep->se_rpcprog, n, nconf->nc_netid, | | 1114 | sep->se_rpcprog, n, nconf->nc_netid, |
1115 | taddr2uaddr(nconf, &nbuf), clnt_spcreateerror("")); | | 1115 | taddr2uaddr(nconf, &nbuf), clnt_spcreateerror("")); |
1116 | } | | 1116 | } |
1117 | #endif /* RPC */ | | 1117 | #endif /* RPC */ |
1118 | } | | 1118 | } |
1119 | | | 1119 | |
1120 | static void | | 1120 | static void |
1121 | unregister_rpc(struct servtab *sep) | | 1121 | unregister_rpc(struct servtab *sep) |
1122 | { | | 1122 | { |
1123 | #ifdef RPC | | 1123 | #ifdef RPC |
1124 | int n; | | 1124 | int n; |
1125 | struct netconfig *nconf; | | 1125 | struct netconfig *nconf; |
1126 | | | 1126 | |
1127 | if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { | | 1127 | if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { |
1128 | syslog(LOG_ERR, "%s: getnetconfigent failed", | | 1128 | syslog(LOG_ERR, "%s: getnetconfigent failed", |
1129 | sep->se_proto); | | 1129 | sep->se_proto); |
1130 | return; | | 1130 | return; |
1131 | } | | 1131 | } |
1132 | | | 1132 | |
1133 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { | | 1133 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { |
1134 | DPRINTF("rpcb_unset(%u, %d, %s)", | | 1134 | DPRINTF("rpcb_unset(%u, %d, %s)", |
1135 | sep->se_rpcprog, n, nconf->nc_netid); | | 1135 | sep->se_rpcprog, n, nconf->nc_netid); |
1136 | if (!rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf)) | | 1136 | if (rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf) == 0) |
1137 | syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n", | | 1137 | syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n", |
1138 | sep->se_rpcprog, n, nconf->nc_netid); | | 1138 | sep->se_rpcprog, n, nconf->nc_netid); |
1139 | } | | 1139 | } |
1140 | #endif /* RPC */ | | 1140 | #endif /* RPC */ |
1141 | } | | 1141 | } |
1142 | | | 1142 | |
1143 | | | 1143 | |
1144 | static struct servtab * | | 1144 | static struct servtab * |
1145 | enter(struct servtab *cp) | | 1145 | enter(struct servtab *cp) |
1146 | { | | 1146 | { |
1147 | struct servtab *sep; | | 1147 | struct servtab *sep; |
1148 | | | 1148 | |
1149 | sep = malloc(sizeof (*sep)); | | 1149 | sep = malloc(sizeof (*sep)); |
| @@ -1279,27 +1279,27 @@ more: | | | @@ -1279,27 +1279,27 @@ more: |
1279 | include_configs(arg); | | 1279 | include_configs(arg); |
1280 | goto more; | | 1280 | goto more; |
1281 | } else { | | 1281 | } else { |
1282 | ERR("Unknown directive '%s'", &arg[1]); | | 1282 | ERR("Unknown directive '%s'", &arg[1]); |
1283 | goto more; | | 1283 | goto more; |
1284 | } | | 1284 | } |
1285 | } | | 1285 | } |
1286 | | | 1286 | |
1287 | /* After this point, we might need to store data in a servtab */ | | 1287 | /* After this point, we might need to store data in a servtab */ |
1288 | *sep = init_servtab(); | | 1288 | *sep = init_servtab(); |
1289 | | | 1289 | |
1290 | /* Check for a host name. */ | | 1290 | /* Check for a host name. */ |
1291 | hostdelim = strrchr(arg, ':'); | | 1291 | hostdelim = strrchr(arg, ':'); |
1292 | if (hostdelim) { | | 1292 | if (hostdelim != NULL) { |
1293 | *hostdelim = '\0'; | | 1293 | *hostdelim = '\0'; |
1294 | if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { | | 1294 | if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { |
1295 | hostdelim[-1] = '\0'; | | 1295 | hostdelim[-1] = '\0'; |
1296 | sep->se_hostaddr = newstr(arg + 1); | | 1296 | sep->se_hostaddr = newstr(arg + 1); |
1297 | } else | | 1297 | } else |
1298 | sep->se_hostaddr = newstr(arg); | | 1298 | sep->se_hostaddr = newstr(arg); |
1299 | arg = hostdelim + 1; | | 1299 | arg = hostdelim + 1; |
1300 | /* | | 1300 | /* |
1301 | * If the line is of the form `host:', then just change the | | 1301 | * If the line is of the form `host:', then just change the |
1302 | * default host for the following lines. | | 1302 | * default host for the following lines. |
1303 | */ | | 1303 | */ |
1304 | if (*arg == '\0') { | | 1304 | if (*arg == '\0') { |
1305 | arg = skip(&cp); | | 1305 | arg = skip(&cp); |
| @@ -1402,60 +1402,58 @@ more: | | | @@ -1402,60 +1402,58 @@ more: |
1402 | if (sep->se_type == NORM_TYPE && | | 1402 | if (sep->se_type == NORM_TYPE && |
1403 | strncmp(arg, "faith/", strlen("faith/")) == 0) { | | 1403 | strncmp(arg, "faith/", strlen("faith/")) == 0) { |
1404 | arg += strlen("faith/"); | | 1404 | arg += strlen("faith/"); |
1405 | sep->se_type = FAITH_TYPE; | | 1405 | sep->se_type = FAITH_TYPE; |
1406 | } | | 1406 | } |
1407 | sep->se_proto = newstr(arg); | | 1407 | sep->se_proto = newstr(arg); |
1408 | | | 1408 | |
1409 | #define MALFORMED(arg) \ | | 1409 | #define MALFORMED(arg) \ |
1410 | do { \ | | 1410 | do { \ |
1411 | ERR("%s: malformed buffer size option `%s'", \ | | 1411 | ERR("%s: malformed buffer size option `%s'", \ |
1412 | sep->se_service, (arg)); \ | | 1412 | sep->se_service, (arg)); \ |
1413 | freeconfig(sep); \ | | 1413 | freeconfig(sep); \ |
1414 | goto more; \ | | 1414 | goto more; \ |
1415 | /*NOTREACHED*/ \ | | 1415 | } while (false) |
1416 | } while (/*CONSTCOND*/0) | | | |
1417 | | | 1416 | |
1418 | #define GETVAL(arg) \ | | 1417 | #define GETVAL(arg) \ |
1419 | do { \ | | 1418 | do { \ |
1420 | if (!isdigit((unsigned char)*(arg))) \ | | 1419 | if (!isdigit((unsigned char)*(arg))) \ |
1421 | MALFORMED(arg); \ | | 1420 | MALFORMED(arg); \ |
1422 | val = (int)strtol((arg), &cp0, 10); \ | | 1421 | val = (int)strtol((arg), &cp0, 10); \ |
1423 | if (cp0 != NULL) { \ | | 1422 | if (cp0 != NULL) { \ |
1424 | if (cp0[1] != '\0') \ | | 1423 | if (cp0[1] != '\0') \ |
1425 | MALFORMED((arg)); \ | | 1424 | MALFORMED((arg)); \ |
1426 | if (cp0[0] == 'k') \ | | 1425 | if (cp0[0] == 'k') \ |
1427 | val *= 1024; \ | | 1426 | val *= 1024; \ |
1428 | if (cp0[0] == 'm') \ | | 1427 | if (cp0[0] == 'm') \ |
1429 | val *= 1024 * 1024; \ | | 1428 | val *= 1024 * 1024; \ |
1430 | } \ | | 1429 | } \ |
1431 | if (val < 1) { \ | | 1430 | if (val < 1) { \ |
1432 | ERR("%s: invalid buffer size `%s'", \ | | 1431 | ERR("%s: invalid buffer size `%s'", \ |
1433 | sep->se_service, (arg)); \ | | 1432 | sep->se_service, (arg)); \ |
1434 | freeconfig(sep); \ | | 1433 | freeconfig(sep); \ |
1435 | goto more; \ | | 1434 | goto more; \ |
1436 | } \ | | 1435 | } \ |
1437 | /*NOTREACHED*/ \ | | 1436 | } while (false) |
1438 | } while (/*CONSTCOND*/0) | | | |
1439 | | | 1437 | |
1440 | #define ASSIGN(arg) \ | | 1438 | #define ASSIGN(arg) \ |
1441 | do { \ | | 1439 | do { \ |
1442 | if (strcmp((arg), "sndbuf") == 0) \ | | 1440 | if (strcmp((arg), "sndbuf") == 0) \ |
1443 | sep->se_sndbuf = val; \ | | 1441 | sep->se_sndbuf = val; \ |
1444 | else if (strcmp((arg), "rcvbuf") == 0) \ | | 1442 | else if (strcmp((arg), "rcvbuf") == 0) \ |
1445 | sep->se_rcvbuf = val; \ | | 1443 | sep->se_rcvbuf = val; \ |
1446 | else \ | | 1444 | else \ |
1447 | MALFORMED((arg)); \ | | 1445 | MALFORMED((arg)); \ |
1448 | } while (/*CONSTCOND*/0) | | 1446 | } while (false) |
1449 | | | 1447 | |
1450 | /* | | 1448 | /* |
1451 | * Extract the send and receive buffer sizes before parsing | | 1449 | * Extract the send and receive buffer sizes before parsing |
1452 | * the protocol. | | 1450 | * the protocol. |
1453 | */ | | 1451 | */ |
1454 | sep->se_sndbuf = sep->se_rcvbuf = 0; | | 1452 | sep->se_sndbuf = sep->se_rcvbuf = 0; |
1455 | buf0 = buf1 = sz0 = sz1 = NULL; | | 1453 | buf0 = buf1 = sz0 = sz1 = NULL; |
1456 | if ((buf0 = strchr(sep->se_proto, ',')) != NULL) { | | 1454 | if ((buf0 = strchr(sep->se_proto, ',')) != NULL) { |
1457 | /* Not meaningful for Tcpmux services. */ | | 1455 | /* Not meaningful for Tcpmux services. */ |
1458 | if (ISMUX(sep)) { | | 1456 | if (ISMUX(sep)) { |
1459 | ERR("%s: can't specify buffer sizes for " | | 1457 | ERR("%s: can't specify buffer sizes for " |
1460 | "tcpmux services", sep->se_service); | | 1458 | "tcpmux services", sep->se_service); |
1461 | goto more; | | 1459 | goto more; |
| @@ -1573,34 +1571,34 @@ do { \ | | | @@ -1573,34 +1571,34 @@ do { \ |
1573 | /* Parser server-program (path to binary or "internal") */ | | 1571 | /* Parser server-program (path to binary or "internal") */ |
1574 | arg = skip(&cp); | | 1572 | arg = skip(&cp); |
1575 | if (arg == NULL) { | | 1573 | if (arg == NULL) { |
1576 | LOG_TOO_FEW_ARGS(); | | 1574 | LOG_TOO_FEW_ARGS(); |
1577 | freeconfig(sep); | | 1575 | freeconfig(sep); |
1578 | goto more; | | 1576 | goto more; |
1579 | } | | 1577 | } |
1580 | if (parse_server(sep, arg)) { | | 1578 | if (parse_server(sep, arg)) { |
1581 | freeconfig(sep); | | 1579 | freeconfig(sep); |
1582 | goto more; | | 1580 | goto more; |
1583 | } | | 1581 | } |
1584 | | | 1582 | |
1585 | argc = 0; | | 1583 | argc = 0; |
1586 | for (arg = skip(&cp); cp; arg = skip(&cp)) { | | 1584 | for (arg = skip(&cp); cp != NULL; arg = skip(&cp)) { |
1587 | if (argc < MAXARGV) | | 1585 | if (argc < MAXARGV) |
1588 | sep->se_argv[argc++] = newstr(arg); | | 1586 | sep->se_argv[argc++] = newstr(arg); |
1589 | } | | 1587 | } |
1590 | while (argc <= MAXARGV) | | 1588 | while (argc <= MAXARGV) |
1591 | sep->se_argv[argc++] = NULL; | | 1589 | sep->se_argv[argc++] = NULL; |
1592 | #ifdef IPSEC | | 1590 | #ifdef IPSEC |
1593 | sep->se_policy = policy ? newstr(policy) : NULL; | | 1591 | sep->se_policy = policy != NULL ? newstr(policy) : NULL; |
1594 | #endif | | 1592 | #endif |
1595 | /* getconfigent read a positional service def, move to next line */ | | 1593 | /* getconfigent read a positional service def, move to next line */ |
1596 | *current_pos = nextline(fconfig); | | 1594 | *current_pos = nextline(fconfig); |
1597 | return (sep); | | 1595 | return (sep); |
1598 | } | | 1596 | } |
1599 | | | 1597 | |
1600 | void | | 1598 | void |
1601 | freeconfig(struct servtab *cp) | | 1599 | freeconfig(struct servtab *cp) |
1602 | { | | 1600 | { |
1603 | int i; | | 1601 | int i; |
1604 | | | 1602 | |
1605 | if (cp->se_hostaddr) | | 1603 | if (cp->se_hostaddr) |
1606 | free(cp->se_hostaddr); | | 1604 | free(cp->se_hostaddr); |
| @@ -1646,59 +1644,59 @@ again: | | | @@ -1646,59 +1644,59 @@ again: |
1646 | int c; | | 1644 | int c; |
1647 | | | 1645 | |
1648 | c = getc(fconfig); | | 1646 | c = getc(fconfig); |
1649 | (void) ungetc(c, fconfig); | | 1647 | (void) ungetc(c, fconfig); |
1650 | if (c == ' ' || c == '\t') | | 1648 | if (c == ' ' || c == '\t') |
1651 | if ((cp = nextline(fconfig)) != NULL) | | 1649 | if ((cp = nextline(fconfig)) != NULL) |
1652 | goto again; | | 1650 | goto again; |
1653 | *cpp = NULL; | | 1651 | *cpp = NULL; |
1654 | return (NULL); | | 1652 | return (NULL); |
1655 | } | | 1653 | } |
1656 | start = cp; | | 1654 | start = cp; |
1657 | /* Parse shell-style quotes */ | | 1655 | /* Parse shell-style quotes */ |
1658 | quote = '\0'; | | 1656 | quote = '\0'; |
1659 | while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) { | | 1657 | while (*cp != '\0' && (quote != '\0' || (*cp != ' ' && *cp != '\t'))) { |
1660 | if (*cp == '\'' || *cp == '"') { | | 1658 | if (*cp == '\'' || *cp == '"') { |
1661 | if (quote && *cp != quote) | | 1659 | if (quote != '\0' && *cp != quote) |
1662 | cp++; | | 1660 | cp++; |
1663 | else { | | 1661 | else { |
1664 | if (quote) | | 1662 | if (quote != '\0') |
1665 | quote = '\0'; | | 1663 | quote = '\0'; |
1666 | else | | 1664 | else |
1667 | quote = *cp; | | 1665 | quote = *cp; |
1668 | memmove(cp, cp+1, strlen(cp)); | | 1666 | memmove(cp, cp+1, strlen(cp)); |
1669 | } | | 1667 | } |
1670 | } else | | 1668 | } else |
1671 | cp++; | | 1669 | cp++; |
1672 | } | | 1670 | } |
1673 | if (*cp != '\0') | | 1671 | if (*cp != '\0') |
1674 | *cp++ = '\0'; | | 1672 | *cp++ = '\0'; |
1675 | *cpp = cp; | | 1673 | *cpp = cp; |
1676 | return (start); | | 1674 | return (start); |
1677 | } | | 1675 | } |
1678 | | | 1676 | |
1679 | char * | | 1677 | char * |
1680 | nextline(FILE *fd) | | 1678 | nextline(FILE *fd) |
1681 | { | | 1679 | { |
1682 | char *cp; | | 1680 | char *cp; |
1683 | | | 1681 | |
1684 | if (fgets(line, (int)sizeof(line), fd) == NULL) { | | 1682 | if (fgets(line, (int)sizeof(line), fd) == NULL) { |
1685 | if (ferror(fd)) { | | 1683 | if (ferror(fd) != 0) { |
1686 | ERR("Error when reading next line: %s", strerror(errno)); | | 1684 | ERR("Error when reading next line: %s", strerror(errno)); |
1687 | } | | 1685 | } |
1688 | return NULL; | | 1686 | return NULL; |
1689 | } | | 1687 | } |
1690 | cp = strchr(line, '\n'); | | 1688 | cp = strchr(line, '\n'); |
1691 | if (cp) | | 1689 | if (cp != NULL) |
1692 | *cp = '\0'; | | 1690 | *cp = '\0'; |
1693 | line_number++; | | 1691 | line_number++; |
1694 | return line; | | 1692 | return line; |
1695 | } | | 1693 | } |
1696 | | | 1694 | |
1697 | char * | | 1695 | char * |
1698 | newstr(const char *cp) | | 1696 | newstr(const char *cp) |
1699 | { | | 1697 | { |
1700 | char *dp; | | 1698 | char *dp; |
1701 | if ((dp = strdup((cp != NULL) ? cp : "")) != NULL) | | 1699 | if ((dp = strdup((cp != NULL) ? cp : "")) != NULL) |
1702 | return (dp); | | 1700 | return (dp); |
1703 | syslog(LOG_ERR, "strdup: %m"); | | 1701 | syslog(LOG_ERR, "strdup: %m"); |
1704 | exit(EXIT_FAILURE); | | 1702 | exit(EXIT_FAILURE); |
| @@ -1827,27 +1825,27 @@ initring(void) | | | @@ -1827,27 +1825,27 @@ initring(void) |
1827 | if (isprint(i)) | | 1825 | if (isprint(i)) |
1828 | *endring++ = (char)i; | | 1826 | *endring++ = (char)i; |
1829 | } | | 1827 | } |
1830 | | | 1828 | |
1831 | /* ARGSUSED */ | | 1829 | /* ARGSUSED */ |
1832 | static void | | 1830 | static void |
1833 | chargen_stream(int s, struct servtab *sep) /* Character generator */ | | 1831 | chargen_stream(int s, struct servtab *sep) /* Character generator */ |
1834 | { | | 1832 | { |
1835 | size_t len; | | 1833 | size_t len; |
1836 | char *rs, text[LINESIZ+2]; | | 1834 | char *rs, text[LINESIZ+2]; |
1837 | | | 1835 | |
1838 | inetd_setproctitle(sep->se_service, s); | | 1836 | inetd_setproctitle(sep->se_service, s); |
1839 | | | 1837 | |
1840 | if (!endring) { | | 1838 | if (endring == NULL) { |
1841 | initring(); | | 1839 | initring(); |
1842 | rs = ring; | | 1840 | rs = ring; |
1843 | } | | 1841 | } |
1844 | | | 1842 | |
1845 | text[LINESIZ] = '\r'; | | 1843 | text[LINESIZ] = '\r'; |
1846 | text[LINESIZ + 1] = '\n'; | | 1844 | text[LINESIZ + 1] = '\n'; |
1847 | for (rs = ring;;) { | | 1845 | for (rs = ring;;) { |
1848 | if ((len = (size_t)(endring - rs)) >= LINESIZ) | | 1846 | if ((len = (size_t)(endring - rs)) >= LINESIZ) |
1849 | memmove(text, rs, LINESIZ); | | 1847 | memmove(text, rs, LINESIZ); |
1850 | else { | | 1848 | else { |
1851 | memmove(text, rs, len); | | 1849 | memmove(text, rs, len); |
1852 | memmove(text + len, ring, LINESIZ - len); | | 1850 | memmove(text + len, ring, LINESIZ - len); |
1853 | } | | 1851 | } |
| @@ -1996,43 +1994,43 @@ print_service(const char *action, struct | | | @@ -1996,43 +1994,43 @@ print_service(const char *action, struct |
1996 | | | 1994 | |
1997 | if (isrpcservice(sep)) | | 1995 | if (isrpcservice(sep)) |
1998 | fprintf(stderr, | | 1996 | fprintf(stderr, |
1999 | "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" | | 1997 | "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" |
2000 | #ifdef IPSEC | | 1998 | #ifdef IPSEC |
2001 | " policy=\"%s\"" | | 1999 | " policy=\"%s\"" |
2002 | #endif | | 2000 | #endif |
2003 | "\n", | | 2001 | "\n", |
2004 | action, sep->se_service, | | 2002 | action, sep->se_service, |
2005 | sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, | | 2003 | sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, |
2006 | sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, | | 2004 | sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, |
2007 | (long)sep->se_bi, sep->se_server | | 2005 | (long)sep->se_bi, sep->se_server |
2008 | #ifdef IPSEC | | 2006 | #ifdef IPSEC |
2009 | , (sep->se_policy ? sep->se_policy : "") | | 2007 | , (sep->se_policy != NULL ? sep->se_policy : "") |
2010 | #endif | | 2008 | #endif |
2011 | ); | | 2009 | ); |
2012 | else | | 2010 | else |
2013 | fprintf(stderr, | | 2011 | fprintf(stderr, |
2014 | "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" | | 2012 | "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s" |
2015 | #ifdef IPSEC | | 2013 | #ifdef IPSEC |
2016 | " policy=%s" | | 2014 | " policy=%s" |
2017 | #endif | | 2015 | #endif |
2018 | "\n", | | 2016 | "\n", |
2019 | action, sep->se_hostaddr, sep->se_service, | | 2017 | action, sep->se_hostaddr, sep->se_service, |
2020 | sep->se_type == FAITH_TYPE ? "faith/" : "", | | 2018 | sep->se_type == FAITH_TYPE ? "faith/" : "", |
2021 | sep->se_proto, | | 2019 | sep->se_proto, |
2022 | sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, | | 2020 | sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group, |
2023 | (long)sep->se_bi, sep->se_server | | 2021 | (long)sep->se_bi, sep->se_server |
2024 | #ifdef IPSEC | | 2022 | #ifdef IPSEC |
2025 | , (sep->se_policy ? sep->se_policy : "") | | 2023 | , (sep->se_policy != NULL ? sep->se_policy : "") |
2026 | #endif | | 2024 | #endif |
2027 | ); | | 2025 | ); |
2028 | } | | 2026 | } |
2029 | #endif | | 2027 | #endif |
2030 | | | 2028 | |
2031 | static void | | 2029 | static void |
2032 | usage(void) | | 2030 | usage(void) |
2033 | { | | 2031 | { |
2034 | #ifdef LIBWRAP | | 2032 | #ifdef LIBWRAP |
2035 | (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); | | 2033 | (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); |
2036 | #else | | 2034 | #else |
2037 | (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); | | 2035 | (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); |
2038 | #endif | | 2036 | #endif |
| @@ -2080,47 +2078,47 @@ tcpmux(int ctrl, struct servtab *sep) | | | @@ -2080,47 +2078,47 @@ tcpmux(int ctrl, struct servtab *sep) |
2080 | /* Get requested service name */ | | 2078 | /* Get requested service name */ |
2081 | if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) { | | 2079 | if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) { |
2082 | strwrite(ctrl, "-Error reading service name\r\n"); | | 2080 | strwrite(ctrl, "-Error reading service name\r\n"); |
2083 | goto reject; | | 2081 | goto reject; |
2084 | } | | 2082 | } |
2085 | service[len] = '\0'; | | 2083 | service[len] = '\0'; |
2086 | | | 2084 | |
2087 | DPRINTF("tcpmux: %s: service requested", service); | | 2085 | DPRINTF("tcpmux: %s: service requested", service); |
2088 | | | 2086 | |
2089 | /* | | 2087 | /* |
2090 | * Help is a required command, and lists available services, | | 2088 | * Help is a required command, and lists available services, |
2091 | * one per line. | | 2089 | * one per line. |
2092 | */ | | 2090 | */ |
2093 | if (!strcasecmp(service, "help")) { | | 2091 | if (strcasecmp(service, "help") == 0) { |
2094 | strwrite(ctrl, "+Available services:\r\n"); | | 2092 | strwrite(ctrl, "+Available services:\r\n"); |
2095 | strwrite(ctrl, "help\r\n"); | | 2093 | strwrite(ctrl, "help\r\n"); |
2096 | for (sep = servtab; sep != NULL; sep = sep->se_next) { | | 2094 | for (sep = servtab; sep != NULL; sep = sep->se_next) { |
2097 | if (!ISMUX(sep)) | | 2095 | if (!ISMUX(sep)) |
2098 | continue; | | 2096 | continue; |
2099 | (void)write(ctrl, sep->se_service, | | 2097 | (void)write(ctrl, sep->se_service, |
2100 | strlen(sep->se_service)); | | 2098 | strlen(sep->se_service)); |
2101 | strwrite(ctrl, "\r\n"); | | 2099 | strwrite(ctrl, "\r\n"); |
2102 | } | | 2100 | } |
2103 | goto reject; | | 2101 | goto reject; |
2104 | } | | 2102 | } |
2105 | | | 2103 | |
2106 | /* Try matching a service in inetd.conf with the request */ | | 2104 | /* Try matching a service in inetd.conf with the request */ |
2107 | for (sep = servtab; sep != NULL; sep = sep->se_next) { | | 2105 | for (sep = servtab; sep != NULL; sep = sep->se_next) { |
2108 | if (!ISMUX(sep)) | | 2106 | if (!ISMUX(sep)) |
2109 | continue; | | 2107 | continue; |
2110 | if (!strcasecmp(service, sep->se_service)) { | | 2108 | if (strcasecmp(service, sep->se_service) == 0) { |
2111 | if (ISMUXPLUS(sep)) | | 2109 | if (ISMUXPLUS(sep)) |
2112 | strwrite(ctrl, "+Go\r\n"); | | 2110 | strwrite(ctrl, "+Go\r\n"); |
2113 | run_service(ctrl, sep, 1 /* forked */); | | 2111 | run_service(ctrl, sep, true /* forked */); |
2114 | return; | | 2112 | return; |
2115 | } | | 2113 | } |
2116 | } | | 2114 | } |
2117 | strwrite(ctrl, "-Service not available\r\n"); | | 2115 | strwrite(ctrl, "-Service not available\r\n"); |
2118 | reject: | | 2116 | reject: |
2119 | _exit(EXIT_FAILURE); | | 2117 | _exit(EXIT_FAILURE); |
2120 | } | | 2118 | } |
2121 | | | 2119 | |
2122 | /* | | 2120 | /* |
2123 | * check if the address/port where send data to is one of the obvious ports | | 2121 | * check if the address/port where send data to is one of the obvious ports |
2124 | * that are used for denial of service attacks like two echo ports | | 2122 | * that are used for denial of service attacks like two echo ports |
2125 | * just echoing data between them | | 2123 | * just echoing data between them |
2126 | */ | | 2124 | */ |
| @@ -2160,66 +2158,66 @@ port_good_dg(struct sockaddr *sa) | | | @@ -2160,66 +2158,66 @@ port_good_dg(struct sockaddr *sa) |
2160 | in6 = &sin6->sin6_addr; | | 2158 | in6 = &sin6->sin6_addr; |
2161 | port = ntohs(sin6->sin6_port); | | 2159 | port = ntohs(sin6->sin6_port); |
2162 | if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) | | 2160 | if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) |
2163 | goto bad; | | 2161 | goto bad; |
2164 | if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { | | 2162 | if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { |
2165 | memcpy(&in, &in6->s6_addr[12], sizeof(in)); | | 2163 | memcpy(&in, &in6->s6_addr[12], sizeof(in)); |
2166 | in.s_addr = ntohl(in.s_addr); | | 2164 | in.s_addr = ntohl(in.s_addr); |
2167 | goto v4chk; | | 2165 | goto v4chk; |
2168 | } | | 2166 | } |
2169 | break; | | 2167 | break; |
2170 | #endif | | 2168 | #endif |
2171 | default: | | 2169 | default: |
2172 | /* XXX unsupported af, is it safe to assume it to be safe? */ | | 2170 | /* XXX unsupported af, is it safe to assume it to be safe? */ |
2173 | return (1); | | 2171 | return true; |
2174 | } | | 2172 | } |
2175 | | | 2173 | |
2176 | for (i = 0; bad_ports[i] != 0; i++) { | | 2174 | for (i = 0; bad_ports[i] != 0; i++) { |
2177 | if (port == bad_ports[i]) | | 2175 | if (port == bad_ports[i]) |
2178 | goto bad; | | 2176 | goto bad; |
2179 | } | | 2177 | } |
2180 | | | 2178 | |
2181 | return (1); | | 2179 | return true; |
2182 | | | 2180 | |
2183 | bad: | | 2181 | bad: |
2184 | if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0, | | 2182 | if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0, |
2185 | niflags) != 0) | | 2183 | niflags) != 0) |
2186 | strlcpy(hbuf, "?", sizeof(hbuf)); | | 2184 | strlcpy(hbuf, "?", sizeof(hbuf)); |
2187 | syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", | | 2185 | syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", |
2188 | hbuf, port); | | 2186 | hbuf, port); |
2189 | return (0); | | 2187 | return false; |
2190 | } | | 2188 | } |
2191 | | | 2189 | |
2192 | /* XXX need optimization */ | | 2190 | /* XXX need optimization */ |
2193 | static int | | 2191 | static int |
2194 | dg_broadcast(struct in_addr *in) | | 2192 | dg_broadcast(struct in_addr *in) |
2195 | { | | 2193 | { |
2196 | struct ifaddrs *ifa, *ifap; | | 2194 | struct ifaddrs *ifa, *ifap; |
2197 | struct sockaddr_in *sin; | | 2195 | struct sockaddr_in *sin; |
2198 | | | 2196 | |
2199 | if (getifaddrs(&ifap) < 0) | | 2197 | if (getifaddrs(&ifap) < 0) |
2200 | return (0); | | 2198 | return false; |
2201 | for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | | 2199 | for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { |
2202 | if (ifa->ifa_addr->sa_family != AF_INET || | | 2200 | if (ifa->ifa_addr->sa_family != AF_INET || |
2203 | (ifa->ifa_flags & IFF_BROADCAST) == 0) | | 2201 | (ifa->ifa_flags & IFF_BROADCAST) == 0) |
2204 | continue; | | 2202 | continue; |
2205 | sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr; | | 2203 | sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr; |
2206 | if (sin->sin_addr.s_addr == in->s_addr) { | | 2204 | if (sin->sin_addr.s_addr == in->s_addr) { |
2207 | freeifaddrs(ifap); | | 2205 | freeifaddrs(ifap); |
2208 | return (1); | | 2206 | return true; |
2209 | } | | 2207 | } |
2210 | } | | 2208 | } |
2211 | freeifaddrs(ifap); | | 2209 | freeifaddrs(ifap); |
2212 | return (0); | | 2210 | return false; |
2213 | } | | 2211 | } |
2214 | | | 2212 | |
2215 | static int | | 2213 | static int |
2216 | my_kevent(const struct kevent *changelist, size_t nchanges, | | 2214 | my_kevent(const struct kevent *changelist, size_t nchanges, |
2217 | struct kevent *eventlist, size_t nevents) | | 2215 | struct kevent *eventlist, size_t nevents) |
2218 | { | | 2216 | { |
2219 | int result; | | 2217 | int result; |
2220 | | | 2218 | |
2221 | while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, | | 2219 | while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, |
2222 | NULL)) < 0) | | 2220 | NULL)) < 0) |
2223 | if (errno != EINTR) { | | 2221 | if (errno != EINTR) { |
2224 | syslog(LOG_ERR, "kevent: %m"); | | 2222 | syslog(LOG_ERR, "kevent: %m"); |
2225 | exit(EXIT_FAILURE); | | 2223 | exit(EXIT_FAILURE); |
| @@ -2235,27 +2233,27 @@ allocchange(void) | | | @@ -2235,27 +2233,27 @@ allocchange(void) |
2235 | (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0); | | 2233 | (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0); |
2236 | changes = 0; | | 2234 | changes = 0; |
2237 | } | | 2235 | } |
2238 | | | 2236 | |
2239 | return (&changebuf[changes++]); | | 2237 | return (&changebuf[changes++]); |
2240 | } | | 2238 | } |
2241 | | | 2239 | |
2242 | static void | | 2240 | static void |
2243 | config_root(void) | | 2241 | config_root(void) |
2244 | { | | 2242 | { |
2245 | struct servtab *sep; | | 2243 | struct servtab *sep; |
2246 | /* Uncheck services */ | | 2244 | /* Uncheck services */ |
2247 | for (sep = servtab; sep != NULL; sep = sep->se_next) { | | 2245 | for (sep = servtab; sep != NULL; sep = sep->se_next) { |
2248 | sep->se_checked = 0; | | 2246 | sep->se_checked = false; |
2249 | } | | 2247 | } |
2250 | defhost = newstr("*"); | | 2248 | defhost = newstr("*"); |
2251 | #ifdef IPSEC | | 2249 | #ifdef IPSEC |
2252 | policy = NULL; | | 2250 | policy = NULL; |
2253 | #endif | | 2251 | #endif |
2254 | fconfig = NULL; | | 2252 | fconfig = NULL; |
2255 | config(); | | 2253 | config(); |
2256 | purge_unchecked(); | | 2254 | purge_unchecked(); |
2257 | } | | 2255 | } |
2258 | | | 2256 | |
2259 | static void | | 2257 | static void |
2260 | purge_unchecked(void) | | 2258 | purge_unchecked(void) |
2261 | { | | 2259 | { |
| @@ -2294,27 +2292,27 @@ is_same_service(const struct servtab *se | | | @@ -2294,27 +2292,27 @@ is_same_service(const struct servtab *se |
2294 | sep->se_family == cp->se_family && | | 2292 | sep->se_family == cp->se_family && |
2295 | ISMUX(sep) == ISMUX(cp); | | 2293 | ISMUX(sep) == ISMUX(cp); |
2296 | } | | 2294 | } |
2297 | | | 2295 | |
2298 | int | | 2296 | int |
2299 | parse_protocol(struct servtab *sep) | | 2297 | parse_protocol(struct servtab *sep) |
2300 | { | | 2298 | { |
2301 | int val; | | 2299 | int val; |
2302 | | | 2300 | |
2303 | if (strcmp(sep->se_proto, "unix") == 0) { | | 2301 | if (strcmp(sep->se_proto, "unix") == 0) { |
2304 | sep->se_family = AF_LOCAL; | | 2302 | sep->se_family = AF_LOCAL; |
2305 | } else { | | 2303 | } else { |
2306 | val = (int)strlen(sep->se_proto); | | 2304 | val = (int)strlen(sep->se_proto); |
2307 | if (!val) { | | 2305 | if (val == 0) { |
2308 | ERR("%s: invalid protocol specified", | | 2306 | ERR("%s: invalid protocol specified", |
2309 | sep->se_service); | | 2307 | sep->se_service); |
2310 | return -1; | | 2308 | return -1; |
2311 | } | | 2309 | } |
2312 | val = sep->se_proto[val - 1]; | | 2310 | val = sep->se_proto[val - 1]; |
2313 | switch (val) { | | 2311 | switch (val) { |
2314 | case '4': /*tcp4 or udp4*/ | | 2312 | case '4': /*tcp4 or udp4*/ |
2315 | sep->se_family = AF_INET; | | 2313 | sep->se_family = AF_INET; |
2316 | break; | | 2314 | break; |
2317 | #ifdef INET6 | | 2315 | #ifdef INET6 |
2318 | case '6': /*tcp6 or udp6*/ | | 2316 | case '6': /*tcp6 or udp6*/ |
2319 | sep->se_family = AF_INET6; | | 2317 | sep->se_family = AF_INET6; |
2320 | break; | | 2318 | break; |
| @@ -2404,38 +2402,38 @@ parse_server(struct servtab *sep, const | | | @@ -2404,38 +2402,38 @@ parse_server(struct servtab *sep, const |
2404 | return -1; | | 2402 | return -1; |
2405 | } | | 2403 | } |
2406 | sep->se_bi = bi; | | 2404 | sep->se_bi = bi; |
2407 | sep->se_wait = bi->bi_wait; | | 2405 | sep->se_wait = bi->bi_wait; |
2408 | return 0; | | 2406 | return 0; |
2409 | } | | 2407 | } |
2410 | | | 2408 | |
2411 | /* TODO test to make sure accept filter still works */ | | 2409 | /* TODO test to make sure accept filter still works */ |
2412 | void | | 2410 | void |
2413 | parse_accept_filter(char *arg, struct servtab *sep) { | | 2411 | parse_accept_filter(char *arg, struct servtab *sep) { |
2414 | char *accf, *accf_arg; | | 2412 | char *accf, *accf_arg; |
2415 | /* one and only one accept filter */ | | 2413 | /* one and only one accept filter */ |
2416 | accf = strchr(arg, ':'); | | 2414 | accf = strchr(arg, ':'); |
2417 | if (!accf) | | 2415 | if (accf == NULL) |
2418 | return; | | 2416 | return; |
2419 | if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') { | | 2417 | if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') { |
2420 | /* more than one || nothing beyond */ | | 2418 | /* more than one || nothing beyond */ |
2421 | sep->se_socktype = -1; | | 2419 | sep->se_socktype = -1; |
2422 | return; | | 2420 | return; |
2423 | } | | 2421 | } |
2424 | | | 2422 | |
2425 | accf++; /* skip delimiter */ | | 2423 | accf++; /* skip delimiter */ |
2426 | strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name)); | | 2424 | strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name)); |
2427 | accf_arg = strchr(accf, ','); | | 2425 | accf_arg = strchr(accf, ','); |
2428 | if (!accf_arg) /* zero or one arg, no more */ | | 2426 | if (accf_arg == NULL) /* zero or one arg, no more */ |
2429 | return; | | 2427 | return; |
2430 | | | 2428 | |
2431 | if (strrchr(accf, ',') != accf_arg) { | | 2429 | if (strrchr(accf, ',') != accf_arg) { |
2432 | sep->se_socktype = -1; | | 2430 | sep->se_socktype = -1; |
2433 | } else { | | 2431 | } else { |
2434 | accf_arg++; | | 2432 | accf_arg++; |
2435 | strlcpy(sep->se_accf.af_arg, accf_arg, | | 2433 | strlcpy(sep->se_accf.af_arg, accf_arg, |
2436 | sizeof(sep->se_accf.af_arg)); | | 2434 | sizeof(sep->se_accf.af_arg)); |
2437 | } | | 2435 | } |
2438 | } | | 2436 | } |
2439 | | | 2437 | |
2440 | void | | 2438 | void |
2441 | parse_socktype(char* arg, struct servtab* sep) | | 2439 | parse_socktype(char* arg, struct servtab* sep) |
| @@ -2569,27 +2567,27 @@ read_glob_configs(char *pattern) { | | | @@ -2569,27 +2567,27 @@ read_glob_configs(char *pattern) { |
2569 | for (size_t i = 0; i < results.gl_pathc; i++) { | | 2567 | for (size_t i = 0; i < results.gl_pathc; i++) { |
2570 | include_matched_path(results.gl_pathv[i]); | | 2568 | include_matched_path(results.gl_pathv[i]); |
2571 | } | | 2569 | } |
2572 | | | 2570 | |
2573 | globfree(&results); | | 2571 | globfree(&results); |
2574 | } | | 2572 | } |
2575 | | | 2573 | |
2576 | static void | | 2574 | static void |
2577 | include_matched_path(char *glob_path) | | 2575 | include_matched_path(char *glob_path) |
2578 | { | | 2576 | { |
2579 | struct stat sb; | | 2577 | struct stat sb; |
2580 | char *tmp; | | 2578 | char *tmp; |
2581 | | | 2579 | |
2582 | if (lstat(glob_path, &sb)) { | | 2580 | if (lstat(glob_path, &sb) != 0) { |
2583 | ERR("Error calling stat on path '%s': %s", glob_path, | | 2581 | ERR("Error calling stat on path '%s': %s", glob_path, |
2584 | strerror(errno)); | | 2582 | strerror(errno)); |
2585 | return; | | 2583 | return; |
2586 | } | | 2584 | } |
2587 | | | 2585 | |
2588 | if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) { | | 2586 | if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) { |
2589 | DPRINTCONF("'%s' is not a file.", glob_path); | | 2587 | DPRINTCONF("'%s' is not a file.", glob_path); |
2590 | ERR("The matched path '%s' is not a regular file", glob_path); | | 2588 | ERR("The matched path '%s' is not a regular file", glob_path); |
2591 | return; | | 2589 | return; |
2592 | } | | 2590 | } |
2593 | | | 2591 | |
2594 | DPRINTCONF("Include '%s'", glob_path); | | 2592 | DPRINTCONF("Include '%s'", glob_path); |
2595 | | | 2593 | |
| @@ -2721,27 +2719,27 @@ rl_process(struct servtab *sep, int ctrl | | | @@ -2721,27 +2719,27 @@ rl_process(struct servtab *sep, int ctrl |
2721 | SERV_PARAMS(sep), | | 2719 | SERV_PARAMS(sep), |
2722 | sep->se_service_max, | | 2720 | sep->se_service_max, |
2723 | (intmax_t)CNT_INTVL, | | 2721 | (intmax_t)CNT_INTVL, |
2724 | (uintmax_t)RETRYTIME); | | 2722 | (uintmax_t)RETRYTIME); |
2725 | | | 2723 | |
2726 | DPRINTF(SERV_FMT ": service not started", | | 2724 | DPRINTF(SERV_FMT ": service not started", |
2727 | SERV_PARAMS(sep)); | | 2725 | SERV_PARAMS(sep)); |
2728 | | | 2726 | |
2729 | rl_drop_connection(sep, ctrl); | | 2727 | rl_drop_connection(sep, ctrl); |
2730 | | | 2728 | |
2731 | /* Close the server for 10 minutes */ | | 2729 | /* Close the server for 10 minutes */ |
2732 | close_sep(sep); | | 2730 | close_sep(sep); |
2733 | if (!timingout) { | | 2731 | if (!timingout) { |
2734 | timingout = 1; | | 2732 | timingout = true; |
2735 | alarm(RETRYTIME); | | 2733 | alarm(RETRYTIME); |
2736 | } | | 2734 | } |
2737 | | | 2735 | |
2738 | return -1; | | 2736 | return -1; |
2739 | } | | 2737 | } |
2740 | } | | 2738 | } |
2741 | | | 2739 | |
2742 | if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { | | 2740 | if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { |
2743 | rl_get_name(sep, ctrl, hbuf); | | 2741 | rl_get_name(sep, ctrl, hbuf); |
2744 | node = rl_try_get_ip(sep, hbuf); | | 2742 | node = rl_try_get_ip(sep, hbuf); |
2745 | if(node == NULL) { | | 2743 | if(node == NULL) { |
2746 | node = rl_add(sep, hbuf); | | 2744 | node = rl_add(sep, hbuf); |
2747 | } | | 2745 | } |
| @@ -2800,27 +2798,27 @@ rl_process(struct servtab *sep, int ctrl | | | @@ -2800,27 +2798,27 @@ rl_process(struct servtab *sep, int ctrl |
2800 | | | 2798 | |
2801 | sep->se_count++; | | 2799 | sep->se_count++; |
2802 | return 0; | | 2800 | return 0; |
2803 | } | | 2801 | } |
2804 | | | 2802 | |
2805 | /* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */ | | 2803 | /* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */ |
2806 | static void | | 2804 | static void |
2807 | rl_get_name(struct servtab *sep, int ctrl, char *hbuf) | | 2805 | rl_get_name(struct servtab *sep, int ctrl, char *hbuf) |
2808 | { | | 2806 | { |
2809 | struct sockaddr_storage addr; | | 2807 | struct sockaddr_storage addr; |
2810 | socklen_t len = sizeof(struct sockaddr_storage); | | 2808 | socklen_t len = sizeof(struct sockaddr_storage); |
2811 | switch (sep->se_socktype) { | | 2809 | switch (sep->se_socktype) { |
2812 | case SOCK_STREAM: | | 2810 | case SOCK_STREAM: |
2813 | if (getpeername(ctrl, (struct sockaddr *)&addr, &len)) { | | 2811 | if (getpeername(ctrl, (struct sockaddr *)&addr, &len) != 0) { |
2814 | /* error, log it and skip ip rate limiting */ | | 2812 | /* error, log it and skip ip rate limiting */ |
2815 | syslog(LOG_ERR, | | 2813 | syslog(LOG_ERR, |
2816 | SERV_FMT " failed to get peer name of the " | | 2814 | SERV_FMT " failed to get peer name of the " |
2817 | "connection", SERV_PARAMS(sep)); | | 2815 | "connection", SERV_PARAMS(sep)); |
2818 | exit(EXIT_FAILURE); | | 2816 | exit(EXIT_FAILURE); |
2819 | } | | 2817 | } |
2820 | break; | | 2818 | break; |
2821 | case SOCK_DGRAM: { | | 2819 | case SOCK_DGRAM: { |
2822 | struct msghdr header = { | | 2820 | struct msghdr header = { |
2823 | .msg_name = &addr, | | 2821 | .msg_name = &addr, |
2824 | .msg_namelen = sizeof(struct sockaddr_storage), | | 2822 | .msg_namelen = sizeof(struct sockaddr_storage), |
2825 | /* scatter/gather and control info is null */ | | 2823 | /* scatter/gather and control info is null */ |
2826 | }; | | 2824 | }; |
| @@ -2851,27 +2849,27 @@ rl_get_name(struct servtab *sep, int ctr | | | @@ -2851,27 +2849,27 @@ rl_get_name(struct servtab *sep, int ctr |
2851 | /* error, log it and skip ip rate limiting */ | | 2849 | /* error, log it and skip ip rate limiting */ |
2852 | syslog(LOG_ERR, | | 2850 | syslog(LOG_ERR, |
2853 | SERV_FMT ": failed to get name info of the incoming " | | 2851 | SERV_FMT ": failed to get name info of the incoming " |
2854 | "connection; exiting", | | 2852 | "connection; exiting", |
2855 | SERV_PARAMS(sep)); | | 2853 | SERV_PARAMS(sep)); |
2856 | exit(EXIT_FAILURE); | | 2854 | exit(EXIT_FAILURE); |
2857 | } | | 2855 | } |
2858 | } | | 2856 | } |
2859 | | | 2857 | |
2860 | static void | | 2858 | static void |
2861 | rl_drop_connection(struct servtab *sep, int ctrl) | | 2859 | rl_drop_connection(struct servtab *sep, int ctrl) |
2862 | { | | 2860 | { |
2863 | | | 2861 | |
2864 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { | | 2862 | if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { |
2865 | /* | | 2863 | /* |
2866 | * If the fd isn't a listen socket, | | 2864 | * If the fd isn't a listen socket, |
2867 | * close the individual connection too. | | 2865 | * close the individual connection too. |
2868 | */ | | 2866 | */ |
2869 | close(ctrl); | | 2867 | close(ctrl); |
2870 | return; | | 2868 | return; |
2871 | } | | 2869 | } |
2872 | if (sep->se_socktype != SOCK_DGRAM) { | | 2870 | if (sep->se_socktype != SOCK_DGRAM) { |
2873 | return; | | 2871 | return; |
2874 | } | | 2872 | } |
2875 | /* | | 2873 | /* |
2876 | * Drop the single datagram the service would have | | 2874 | * Drop the single datagram the service would have |
2877 | * consumed if nowait. If this is a wait service, this | | 2875 | * consumed if nowait. If this is a wait service, this |