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