1 /* $NetBSD: lpd.c,v 1.54 2006/01/18 23:17:38 garbled Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 35 #ifndef lint 36 __COPYRIGHT("@(#) Copyright (c) 1983, 1993, 1994\n\ 37 The Regents of the University of California. All rights reserved.\n"); 38 #endif /* not lint */ 39 40 #ifndef lint 41 #if 0 42 static char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95"; 43 #else 44 __RCSID("$NetBSD: lpd.c,v 1.54 2006/01/18 23:17:38 garbled Exp $"); 45 #endif 46 #endif /* not lint */ 47 48 /* 49 * lpd -- line printer daemon. 50 * 51 * Listen for a connection and perform the requested operation. 52 * Operations are: 53 * \1printer\n 54 * check the queue for jobs and print any found. 55 * \2printer\n 56 * receive a job from another machine and queue it. 57 * \3printer [users ...] [jobs ...]\n 58 * return the current state of the queue (short form). 59 * \4printer [users ...] [jobs ...]\n 60 * return the current state of the queue (long form). 61 * \5printer person [users ...] [jobs ...]\n 62 * remove jobs from the queue. 63 * 64 * Strategy to maintain protected spooling area: 65 * 1. Spooling area is writable only by daemon and spooling group 66 * 2. lpr runs setuid root and setgrp spooling group; it uses 67 * root to access any file it wants (verifying things before 68 * with an access call) and group id to know how it should 69 * set up ownership of files in the spooling area. 70 * 3. Files in spooling area are owned by root, group spooling 71 * group, with mode 660. 72 * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to 73 * access files and printer. Users can't get to anything 74 * w/o help of lpq and lprm programs. 75 */ 76 77 #include <sys/param.h> 78 #include <sys/wait.h> 79 #include <sys/types.h> 80 #include <sys/socket.h> 81 #include <sys/un.h> 82 #include <sys/stat.h> 83 #include <sys/file.h> 84 #include <sys/poll.h> 85 #include <netinet/in.h> 86 87 #include <err.h> 88 #include <netdb.h> 89 #include <unistd.h> 90 #include <syslog.h> 91 #include <signal.h> 92 #include <errno.h> 93 #include <fcntl.h> 94 #include <dirent.h> 95 #include <stdarg.h> 96 #include <stdio.h> 97 #include <stdlib.h> 98 #include <string.h> 99 #include <ctype.h> 100 #include <arpa/inet.h> 101 102 #ifdef LIBWRAP 103 #include <tcpd.h> 104 #endif 105 106 #include "lp.h" 107 #include "lp.local.h" 108 #include "pathnames.h" 109 #include "extern.h" 110 111 /* XXX from libc/net/rcmd.c */ 112 extern int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, 113 const char *, const char *); 114 115 #ifdef LIBWRAP 116 int allow_severity = LOG_AUTH|LOG_INFO; 117 int deny_severity = LOG_AUTH|LOG_WARNING; 118 #endif 119 120 int lflag; /* log requests flag */ 121 int rflag; /* allow of for remote printers */ 122 int sflag; /* secure (no inet) flag */ 123 int from_remote; /* from remote socket */ 124 char **blist; /* list of addresses to bind(2) to */ 125 int blist_size; 126 int blist_addrs; 127 128 int main(int, char **); 129 static void reapchild(int); 130 static void mcleanup(int); 131 static void doit(void); 132 static void startup(void); 133 static void chkhost(struct sockaddr *, int); 134 static void usage(void); 135 static struct pollfd *socksetup(int, int, const char *, int *); 136 137 uid_t uid, euid; 138 int child_count; 139 140 #define LPD_NOPORTCHK 0001 /* skip reserved-port check */ 141 142 int 143 main(int argc, char **argv) 144 { 145 struct sockaddr_storage frm; 146 socklen_t frmlen; 147 sigset_t nmask, omask; 148 int lfd, errs, i, f, nfds; 149 struct pollfd *socks; 150 int child_max = 32; /* more than enough to hose the system */ 151 int options = 0, check_options = 0; 152 struct servent *sp; 153 const char *port = "printer"; 154 char **newblist; 155 156 euid = geteuid(); /* these shouldn't be different */ 157 uid = getuid(); 158 gethostname(host, sizeof(host)); 159 host[sizeof(host) - 1] = '\0'; 160 setprogname(*argv); 161 162 errs = 0; 163 while ((i = getopt(argc, argv, "b:dln:srw:W")) != -1) 164 switch (i) { 165 case 'b': 166 if (blist_addrs >= blist_size) { 167 newblist = realloc(blist, 168 blist_size + sizeof(char *) * 4); 169 if (newblist == NULL) 170 err(1, "cant allocate bind addr list"); 171 blist = newblist; 172 blist_size += sizeof(char *) * 4; 173 } 174 blist[blist_addrs++] = strdup(optarg); 175 break; 176 case 'd': 177 options |= SO_DEBUG; 178 break; 179 case 'l': 180 lflag++; 181 break; 182 case 'n': 183 child_max = atoi(optarg); 184 if (child_max < 0 || child_max > 1024) 185 errx(1, "invalid number of children: %s", 186 optarg); 187 break; 188 case 'r': 189 rflag++; 190 break; 191 case 's': 192 sflag++; 193 break; 194 case 'w': 195 wait_time = atoi(optarg); 196 if (wait_time < 0) 197 errx(1, "wait time must be postive: %s", 198 optarg); 199 if (wait_time < 30) 200 warnx("warning: wait time less than 30 seconds"); 201 break; 202 case 'W':/* allow connections coming from a non-reserved port */ 203 /* (done by some lpr-implementations for MS-Windows) */ 204 check_options |= LPD_NOPORTCHK; 205 break; 206 default: 207 errs++; 208 } 209 argc -= optind; 210 argv += optind; 211 if (errs) 212 usage(); 213 214 switch (argc) { 215 case 1: 216 if ((i = atoi(argv[0])) == 0) 217 usage(); 218 if (i < 0 || i > USHRT_MAX) 219 errx(1, "port # %d is invalid", i); 220 221 port = argv[0]; 222 break; 223 case 0: 224 sp = getservbyname(port, "tcp"); 225 if (sp == NULL) 226 errx(1, "%s/tcp: unknown service", port); 227 break; 228 default: 229 usage(); 230 } 231 232 #ifndef DEBUG 233 /* 234 * Set up standard environment by detaching from the parent. 235 */ 236 daemon(0, 0); 237 #endif 238 239 openlog("lpd", LOG_PID, LOG_LPR); 240 syslog(LOG_INFO, "restarted"); 241 (void)umask(0); 242 lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644); 243 if (lfd < 0) { 244 syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 245 exit(1); 246 } 247 if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { 248 if (errno == EWOULDBLOCK) { /* active daemon present */ 249 syslog(LOG_ERR, "%s is locked; another lpd is running", 250 _PATH_MASTERLOCK); 251 exit(0); 252 } 253 syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 254 exit(1); 255 } 256 ftruncate(lfd, 0); 257 /* 258 * write process id for others to know 259 */ 260 (void)snprintf(line, sizeof(line), "%u\n", getpid()); 261 f = strlen(line); 262 if (write(lfd, line, f) != f) { 263 syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); 264 exit(1); 265 } 266 signal(SIGCHLD, reapchild); 267 /* 268 * Restart all the printers. 269 */ 270 startup(); 271 272 sigemptyset(&nmask); 273 sigaddset(&nmask, SIGHUP); 274 sigaddset(&nmask, SIGINT); 275 sigaddset(&nmask, SIGQUIT); 276 sigaddset(&nmask, SIGTERM); 277 sigprocmask(SIG_BLOCK, &nmask, &omask); 278 279 signal(SIGHUP, mcleanup); 280 signal(SIGINT, mcleanup); 281 signal(SIGQUIT, mcleanup); 282 signal(SIGTERM, mcleanup); 283 284 socks = socksetup(PF_UNSPEC, options, port, &nfds); 285 286 sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0); 287 288 if (blist != NULL) { 289 for (i = 0; i < blist_addrs; i++) 290 free(blist[i]); 291 free(blist); 292 } 293 294 /* 295 * Main loop: accept, do a request, continue. 296 */ 297 memset(&frm, 0, sizeof(frm)); 298 for (;;) { 299 int rv, s; 300 /* "short" so it overflows in about 2 hours */ 301 struct timespec sleeptime = {10, 0}; 302 303 while (child_max < child_count) { 304 syslog(LOG_WARNING, 305 "too many children, sleeping for %ld seconds", 306 (long)sleeptime.tv_sec); 307 nanosleep(&sleeptime, NULL); 308 sleeptime.tv_sec <<= 1; 309 if (sleeptime.tv_sec <= 0) { 310 syslog(LOG_CRIT, "sleeptime overflowed! help!"); 311 sleeptime.tv_sec = 10; 312 } 313 } 314 315 rv = poll(socks, nfds, INFTIM); 316 if (rv <= 0) { 317 if (rv < 0 && errno != EINTR) 318 syslog(LOG_WARNING, "poll: %m"); 319 continue; 320 } 321 s = -1; 322 for (i = 0; i < nfds; i++) 323 if (socks[i].revents & POLLIN) { 324 frmlen = sizeof(frm); 325 s = accept(socks[i].fd, 326 (struct sockaddr *)&frm, &frmlen); 327 break; 328 } 329 if (s < 0) { 330 if (errno != EINTR) 331 syslog(LOG_WARNING, "accept: %m"); 332 continue; 333 } 334 335 switch (fork()) { 336 case 0: 337 signal(SIGCHLD, SIG_DFL); 338 signal(SIGHUP, SIG_IGN); 339 signal(SIGINT, SIG_IGN); 340 signal(SIGQUIT, SIG_IGN); 341 signal(SIGTERM, SIG_IGN); 342 for (i = 0; i < nfds; i++) 343 (void)close(socks[i].fd); 344 dup2(s, STDOUT_FILENO); 345 (void)close(s); 346 if (frm.ss_family != AF_LOCAL) { 347 /* for both AF_INET and AF_INET6 */ 348 from_remote = 1; 349 chkhost((struct sockaddr *)&frm, check_options); 350 } else 351 from_remote = 0; 352 doit(); 353 exit(0); 354 case -1: 355 syslog(LOG_WARNING, "fork: %m, sleeping for 10 seconds..."); 356 sleep(10); 357 continue; 358 default: 359 child_count++; 360 } 361 (void)close(s); 362 } 363 } 364 365 static void 366 reapchild(int signo) 367 { 368 union wait status; 369 370 while (wait3((int *)&status, WNOHANG, 0) > 0) 371 child_count--; 372 } 373 374 static void 375 mcleanup(int signo) 376 { 377 if (lflag) 378 syslog(LOG_INFO, "exiting"); 379 unlink(_PATH_SOCKETNAME); 380 exit(0); 381 } 382 383 /* 384 * Stuff for handling job specifications 385 */ 386 char *user[MAXUSERS]; /* users to process */ 387 int users; /* # of users in user array */ 388 int requ[MAXREQUESTS]; /* job number of spool entries */ 389 int requests; /* # of spool requests */ 390 char *person; /* name of person doing lprm */ 391 392 char fromb[NI_MAXHOST]; /* buffer for client's machine name */ 393 char cbuf[BUFSIZ]; /* command line buffer */ 394 const char *cmdnames[] = { 395 "null", 396 "printjob", 397 "recvjob", 398 "displayq short", 399 "displayq long", 400 "rmjob" 401 }; 402 403 static void 404 doit(void) 405 { 406 char *cp; 407 int n; 408 409 for (;;) { 410 cp = cbuf; 411 do { 412 if (cp >= &cbuf[sizeof(cbuf) - 1]) 413 fatal("Command line too long"); 414 if ((n = read(STDOUT_FILENO, cp, 1)) != 1) { 415 if (n < 0) 416 fatal("Lost connection"); 417 return; 418 } 419 } while (*cp++ != '\n'); 420 *--cp = '\0'; 421 cp = cbuf; 422 if (lflag) { 423 if (*cp >= '\1' && *cp <= '\5') { 424 syslog(LOG_INFO, "%s requests %s %s", 425 from, cmdnames[(int)*cp], cp+1); 426 setproctitle("serving %s: %s %s", from, 427 cmdnames[(int)*cp], cp+1); 428 } 429 else 430 syslog(LOG_INFO, "bad request (%d) from %s", 431 *cp, from); 432 } 433 switch (*cp++) { 434 case '\1': /* check the queue and print any jobs there */ 435 printer = cp; 436 if (*printer == '\0') 437 printer = DEFLP; 438 printjob(); 439 break; 440 case '\2': /* receive files to be queued */ 441 if (!from_remote) { 442 syslog(LOG_INFO, "illegal request (%d)", *cp); 443 exit(1); 444 } 445 printer = cp; 446 if (*printer == '\0') 447 printer = DEFLP; 448 recvjob(); 449 break; 450 case '\3': /* display the queue (short form) */ 451 case '\4': /* display the queue (long form) */ 452 printer = cp; 453 if (*printer == '\0') 454 printer = DEFLP; 455 while (*cp) { 456 if (*cp != ' ') { 457 cp++; 458 continue; 459 } 460 *cp++ = '\0'; 461 while (isspace((unsigned char)*cp)) 462 cp++; 463 if (*cp == '\0') 464 break; 465 if (isdigit((unsigned char)*cp)) { 466 if (requests >= MAXREQUESTS) 467 fatal("Too many requests"); 468 requ[requests++] = atoi(cp); 469 } else { 470 if (users >= MAXUSERS) 471 fatal("Too many users"); 472 user[users++] = cp; 473 } 474 } 475 displayq(cbuf[0] - '\3'); 476 exit(0); 477 case '\5': /* remove a job from the queue */ 478 if (!from_remote) { 479 syslog(LOG_INFO, "illegal request (%d)", *cp); 480 exit(1); 481 } 482 printer = cp; 483 if (*printer == '\0') 484 printer = DEFLP; 485 while (*cp && *cp != ' ') 486 cp++; 487 if (!*cp) 488 break; 489 *cp++ = '\0'; 490 person = cp; 491 while (*cp) { 492 if (*cp != ' ') { 493 cp++; 494 continue; 495 } 496 *cp++ = '\0'; 497 while (isspace((unsigned char)*cp)) 498 cp++; 499 if (*cp == '\0') 500 break; 501 if (isdigit((unsigned char)*cp)) { 502 if (requests >= MAXREQUESTS) 503 fatal("Too many requests"); 504 requ[requests++] = atoi(cp); 505 } else { 506 if (users >= MAXUSERS) 507 fatal("Too many users"); 508 user[users++] = cp; 509 } 510 } 511 rmjob(); 512 break; 513 } 514 fatal("Illegal service request"); 515 } 516 } 517 518 /* 519 * Make a pass through the printcap database and start printing any 520 * files left from the last time the machine went down. 521 */ 522 static void 523 startup(void) 524 { 525 char *buf; 526 char *cp; 527 528 /* 529 * Restart the daemons. 530 */ 531 while (cgetnext(&buf, printcapdb) > 0) { 532 if (ckqueue(buf) <= 0) { 533 free(buf); 534 continue; /* no work to do for this printer */ 535 } 536 for (cp = buf; *cp; cp++) 537 if (*cp == '|' || *cp == ':') { 538 *cp = '\0'; 539 break; 540 } 541 if (lflag) 542 syslog(LOG_INFO, "work for %s", buf); 543 switch (fork()) { 544 case -1: 545 syslog(LOG_WARNING, "startup: cannot fork"); 546 mcleanup(0); 547 case 0: 548 printer = buf; 549 setproctitle("working on printer %s", printer); 550 cgetclose(); 551 printjob(); 552 /* NOTREACHED */ 553 default: 554 child_count++; 555 free(buf); 556 } 557 } 558 } 559 560 #define DUMMY ":nobody::" 561 562 /* 563 * Check to see if the from host has access to the line printer. 564 */ 565 static void 566 chkhost(struct sockaddr *f, int check_opts) 567 { 568 struct addrinfo hints, *res, *r; 569 FILE *hostf; 570 int good = 0; 571 char hst[NI_MAXHOST], ip[NI_MAXHOST]; 572 char serv[NI_MAXSERV]; 573 int error; 574 #ifdef LIBWRAP 575 struct request_info req; 576 #endif 577 578 error = getnameinfo(f, f->sa_len, NULL, 0, serv, sizeof(serv), 579 NI_NUMERICSERV); 580 if (error) 581 fatal("Malformed from address: %s", gai_strerror(error)); 582 583 if (!(check_opts & LPD_NOPORTCHK) && 584 atoi(serv) >= IPPORT_RESERVED) 585 fatal("Connect from invalid port (%s)", serv); 586 587 /* Need real hostname for temporary filenames */ 588 error = getnameinfo(f, f->sa_len, hst, sizeof(hst), NULL, 0, 589 NI_NAMEREQD); 590 if (error) { 591 error = getnameinfo(f, f->sa_len, hst, sizeof(hst), NULL, 0, 592 NI_NUMERICHOST); 593 if (error) 594 fatal("Host name for your address unknown"); 595 else 596 fatal("Host name for your address (%s) unknown", hst); 597 } 598 599 (void)strlcpy(fromb, hst, sizeof(fromb)); 600 from = fromb; 601 602 /* need address in stringform for comparison (no DNS lookup here) */ 603 error = getnameinfo(f, f->sa_len, hst, sizeof(hst), NULL, 0, 604 NI_NUMERICHOST); 605 if (error) 606 fatal("Cannot print address"); 607 608 /* Check for spoof, ala rlogind */ 609 memset(&hints, 0, sizeof(hints)); 610 hints.ai_family = PF_UNSPEC; 611 hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 612 error = getaddrinfo(fromb, NULL, &hints, &res); 613 if (error) { 614 fatal("hostname for your address (%s) unknown: %s", hst, 615 gai_strerror(error)); 616 } 617 good = 0; 618 for (r = res; good == 0 && r; r = r->ai_next) { 619 error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip), 620 NULL, 0, NI_NUMERICHOST); 621 if (!error && !strcmp(hst, ip)) 622 good = 1; 623 } 624 if (res) 625 freeaddrinfo(res); 626 if (good == 0) 627 fatal("address for your hostname (%s) not matched", hst); 628 629 setproctitle("serving %s", from); 630 631 #ifdef LIBWRAP 632 request_init(&req, RQ_DAEMON, "lpd", RQ_CLIENT_SIN, f, 633 RQ_FILE, STDOUT_FILENO, NULL); 634 fromhost(&req); 635 if (!hosts_access(&req)) 636 goto denied; 637 #endif 638 639 hostf = fopen(_PATH_HOSTSEQUIV, "r"); 640 if (hostf) { 641 if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) { 642 (void)fclose(hostf); 643 return; 644 } 645 (void)fclose(hostf); 646 } 647 hostf = fopen(_PATH_HOSTSLPD, "r"); 648 if (hostf) { 649 if (__ivaliduser_sa(hostf, f, f->sa_len, DUMMY, DUMMY) == 0) { 650 (void)fclose(hostf); 651 return; 652 } 653 (void)fclose(hostf); 654 } 655 #ifdef LIBWRAP 656 denied: 657 #endif 658 fatal("Your host does not have line printer access"); 659 /*NOTREACHED*/ 660 } 661 662 663 static void 664 usage(void) 665 { 666 667 (void)fprintf(stderr, 668 "Usage: %s [-dlrsW] [-b bind-address] [-n maxchild] " 669 "[-w maxwait] [port]\n", getprogname()); 670 exit(1); 671 } 672 673 /* setup server socket for specified address family */ 674 /* if af is PF_UNSPEC more than one socket may be returned */ 675 /* the returned list is dynamically allocated, so caller needs to free it */ 676 struct pollfd * 677 socksetup(int af, int options, const char *port, int *nfds) 678 { 679 struct sockaddr_un un; 680 struct addrinfo hints, *res, *r; 681 int error, s, blidx = 0, n; 682 struct pollfd *socks, *newsocks; 683 const int on = 1; 684 685 *nfds = 0; 686 687 socks = malloc(1 * sizeof(socks[0])); 688 if (!socks) { 689 syslog(LOG_ERR, "couldn't allocate memory for sockets"); 690 mcleanup(0); 691 } 692 693 s = socket(AF_LOCAL, SOCK_STREAM, 0); 694 if (s < 0) { 695 syslog(LOG_ERR, "socket(): %m"); 696 exit(1); 697 } 698 memset(&un, 0, sizeof(un)); 699 un.sun_family = AF_LOCAL; 700 strncpy(un.sun_path, _PATH_SOCKETNAME, sizeof(un.sun_path) - 1); 701 un.sun_len = SUN_LEN(&un); 702 (void)umask(07); 703 (void)unlink(_PATH_SOCKETNAME); 704 if (bind(s, (struct sockaddr *)&un, un.sun_len) < 0) { 705 syslog(LOG_ERR, "bind(): %m"); 706 exit(1); 707 } 708 (void)umask(0); 709 listen(s, 5); 710 socks[*nfds].fd = s; 711 socks[*nfds].events = POLLIN; 712 (*nfds)++; 713 714 if (sflag && !blist_addrs) 715 return (socks); 716 717 do { 718 memset(&hints, 0, sizeof(hints)); 719 hints.ai_flags = AI_PASSIVE; 720 hints.ai_family = af; 721 hints.ai_socktype = SOCK_STREAM; 722 error = getaddrinfo((blist_addrs == 0) ? NULL : blist[blidx], 723 port ? port : "printer", &hints, &res); 724 if (error) { 725 if (blist_addrs) 726 syslog(LOG_ERR, "%s: %s", blist[blidx], 727 gai_strerror(error)); 728 else 729 syslog(LOG_ERR, "%s", gai_strerror(error)); 730 mcleanup(0); 731 } 732 733 /* Count max number of sockets we may open */ 734 for (r = res, n = 0; r; r = r->ai_next, n++) 735 ; 736 newsocks = realloc(socks, (*nfds + n) * sizeof(socks[0])); 737 if (!newsocks) { 738 syslog(LOG_ERR, "couldn't allocate memory for sockets"); 739 mcleanup(0); 740 } 741 socks = newsocks; 742 743 for (r = res; r; r = r->ai_next) { 744 s = socket(r->ai_family, r->ai_socktype, 745 r->ai_protocol); 746 if (s < 0) { 747 syslog(LOG_DEBUG, "socket(): %m"); 748 continue; 749 } 750 if (options & SO_DEBUG) 751 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 752 &on, sizeof(on)) < 0) { 753 syslog(LOG_ERR, 754 "setsockopt (SO_DEBUG): %m"); 755 close(s); 756 continue; 757 } 758 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, 759 sizeof(on)) < 0) { 760 syslog(LOG_ERR, 761 "setsockopt (SO_REUSEPORT): %m"); 762 close(s); 763 continue; 764 } 765 if (r->ai_family == AF_INET6 && setsockopt(s, 766 IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { 767 syslog(LOG_ERR, 768 "setsockopt (IPV6_V6ONLY): %m"); 769 close(s); 770 continue; 771 } 772 if (bind(s, r->ai_addr, r->ai_addrlen) < 0) { 773 syslog(LOG_DEBUG, "bind(): %m"); 774 close(s); 775 continue; 776 } 777 listen(s, 5); 778 socks[*nfds].fd = s; 779 socks[*nfds].events = POLLIN; 780 (*nfds)++; 781 } 782 783 if (res) 784 freeaddrinfo(res); 785 } while (++blidx < blist_addrs); 786 787 return (socks); 788 } 789