1 /* 2 * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 17 #ifndef lint 18 # ifdef DAEMON 19 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (with daemon mode)"; 20 # else /* DAEMON */ 21 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (without daemon mode)"; 22 # endif /* DAEMON */ 23 #endif /* ! lint */ 24 25 #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 26 # define USE_SOCK_STREAM 1 27 #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 28 29 #if DAEMON || defined(USE_SOCK_STREAM) 30 # if NETINET || NETINET6 31 # include <arpa/inet.h> 32 # endif /* NETINET || NETINET6 */ 33 # if NAMED_BIND 34 # ifndef NO_DATA 35 # define NO_DATA NO_ADDRESS 36 # endif /* ! NO_DATA */ 37 # endif /* NAMED_BIND */ 38 #endif /* DAEMON || defined(USE_SOCK_STREAM) */ 39 40 #if DAEMON 41 42 # if STARTTLS 43 # include <openssl/rand.h> 44 # endif /* STARTTLS */ 45 46 # include <sys/time.h> 47 48 # if IP_SRCROUTE && NETINET 49 # include <netinet/in_systm.h> 50 # include <netinet/ip.h> 51 # if HAS_IN_H 52 # include <netinet/in.h> 53 # ifndef IPOPTION 54 # define IPOPTION ip_opts 55 # define IP_LIST ip_opts 56 # define IP_DST ip_dst 57 # endif /* ! IPOPTION */ 58 # else /* HAS_IN_H */ 59 # include <netinet/ip_var.h> 60 # ifndef IPOPTION 61 # define IPOPTION ipoption 62 # define IP_LIST ipopt_list 63 # define IP_DST ipopt_dst 64 # endif /* ! IPOPTION */ 65 # endif /* HAS_IN_H */ 66 # endif /* IP_SRCROUTE && NETINET */ 67 68 /* structure to describe a daemon */ 69 struct daemon 70 { 71 int d_socket; /* fd for socket */ 72 SOCKADDR d_addr; /* socket for incoming */ 73 u_short d_port; /* port number */ 74 int d_listenqueue; /* size of listen queue */ 75 int d_tcprcvbufsize; /* size of TCP receive buffer */ 76 int d_tcpsndbufsize; /* size of TCP send buffer */ 77 time_t d_refuse_connections_until; 78 bool d_firsttime; 79 int d_socksize; 80 BITMAP256 d_flags; /* flags; see sendmail.h */ 81 char *d_mflags; /* flags for use in macro */ 82 char *d_name; /* user-supplied name */ 83 }; 84 85 typedef struct daemon DAEMON_T; 86 87 static void connecttimeout __P((void)); 88 static int opendaemonsocket __P((struct daemon *, bool)); 89 static u_short setupdaemon __P((SOCKADDR *)); 90 static SIGFUNC_DECL sighup __P((int)); 91 static void restart_daemon __P((void)); 92 93 /* 94 ** DAEMON.C -- routines to use when running as a daemon. 95 ** 96 ** This entire file is highly dependent on the 4.2 BSD 97 ** interprocess communication primitives. No attempt has 98 ** been made to make this file portable to Version 7, 99 ** Version 6, MPX files, etc. If you should try such a 100 ** thing yourself, I recommend chucking the entire file 101 ** and starting from scratch. Basic semantics are: 102 ** 103 ** getrequests(e) 104 ** Opens a port and initiates a connection. 105 ** Returns in a child. Must set InChannel and 106 ** OutChannel appropriately. 107 ** clrdaemon() 108 ** Close any open files associated with getting 109 ** the connection; this is used when running the queue, 110 ** etc., to avoid having extra file descriptors during 111 ** the queue run and to avoid confusing the network 112 ** code (if it cares). 113 ** makeconnection(host, port, outfile, infile, e) 114 ** Make a connection to the named host on the given 115 ** port. Set *outfile and *infile to the files 116 ** appropriate for communication. Returns zero on 117 ** success, else an exit status describing the 118 ** error. 119 ** host_map_lookup(map, hbuf, avp, pstat) 120 ** Convert the entry in hbuf into a canonical form. 121 */ 122 123 static DAEMON_T Daemons[MAXDAEMONS]; 124 static int ndaemons = 0; /* actual number of daemons */ 125 126 /* options for client */ 127 static int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 128 static int TcpSndBufferSize = 0; /* size of TCP send buffer */ 129 130 /* 131 ** GETREQUESTS -- open mail IPC port and get requests. 132 ** 133 ** Parameters: 134 ** e -- the current envelope. 135 ** 136 ** Returns: 137 ** pointer to flags. 138 ** 139 ** Side Effects: 140 ** Waits until some interesting activity occurs. When 141 ** it does, a child is created to process it, and the 142 ** parent waits for completion. Return from this 143 ** routine is always in the child. The file pointers 144 ** "InChannel" and "OutChannel" should be set to point 145 ** to the communication channel. 146 */ 147 148 BITMAP256 * 149 getrequests(e) 150 ENVELOPE *e; 151 { 152 int t; 153 time_t last_disk_space_check = 0; 154 int idx, curdaemon = -1; 155 int i, olddaemon = 0; 156 # if XDEBUG 157 bool j_has_dot; 158 # endif /* XDEBUG */ 159 char status[MAXLINE]; 160 SOCKADDR sa; 161 SOCKADDR_LEN_T len = sizeof sa; 162 # if NETUNIX 163 extern int ControlSocket; 164 # endif /* NETUNIX */ 165 extern ENVELOPE BlankEnvelope; 166 167 168 for (idx = 0; idx < ndaemons; idx++) 169 { 170 Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 171 Daemons[idx].d_firsttime = TRUE; 172 Daemons[idx].d_refuse_connections_until = (time_t) 0; 173 } 174 175 /* 176 ** Try to actually open the connection. 177 */ 178 179 if (tTd(15, 1)) 180 { 181 for (idx = 0; idx < ndaemons; idx++) 182 { 183 dprintf("getrequests: daemon %s: port %d\n", 184 Daemons[idx].d_name, 185 ntohs(Daemons[idx].d_port)); 186 } 187 } 188 189 /* get a socket for the SMTP connection */ 190 for (idx = 0; idx < ndaemons; idx++) 191 Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE); 192 193 if (opencontrolsocket() < 0) 194 sm_syslog(LOG_WARNING, NOQID, 195 "daemon could not open control socket %s: %s", 196 ControlSocketName, errstring(errno)); 197 198 (void) setsignal(SIGCHLD, reapchild); 199 (void) setsignal(SIGHUP, sighup); 200 201 /* workaround: can't seem to release the signal in the parent */ 202 (void) releasesignal(SIGHUP); 203 204 /* write the pid to file */ 205 log_sendmail_pid(e); 206 207 # if XDEBUG 208 { 209 char jbuf[MAXHOSTNAMELEN]; 210 211 expand("\201j", jbuf, sizeof jbuf, e); 212 j_has_dot = strchr(jbuf, '.') != NULL; 213 } 214 # endif /* XDEBUG */ 215 216 /* Add parent process as first item */ 217 proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON); 218 219 if (tTd(15, 1)) 220 { 221 for (idx = 0; idx < ndaemons; idx++) 222 dprintf("getrequests: daemon %s: %d\n", 223 Daemons[idx].d_name, 224 Daemons[idx].d_socket); 225 } 226 227 for (;;) 228 { 229 register pid_t pid; 230 auto SOCKADDR_LEN_T lotherend; 231 bool timedout = FALSE; 232 bool control = FALSE; 233 int save_errno; 234 int pipefd[2]; 235 time_t timenow; 236 # if STARTTLS 237 long seed; 238 # endif /* STARTTLS */ 239 extern bool refuseconnections __P((char *, ENVELOPE *, int)); 240 241 /* see if we are rejecting connections */ 242 (void) blocksignal(SIGALRM); 243 244 if (ShutdownRequest != NULL) 245 shutdown_daemon(); 246 else if (RestartRequest != NULL) 247 restart_daemon(); 248 249 timenow = curtime(); 250 251 /* 252 ** Use ConnRateThrottle only if the 253 ** last pass was for a connection 254 */ 255 256 if (ConnRateThrottle > 0 && curdaemon >= 0) 257 { 258 static int conncnt = 0; 259 static time_t lastconn = 0; 260 261 if (timenow != lastconn) 262 { 263 lastconn = timenow; 264 conncnt = 1; 265 } 266 else if (++conncnt > ConnRateThrottle) 267 { 268 /* sleep to flatten out connection load */ 269 sm_setproctitle(TRUE, e, 270 "deferring connections: %d per second", 271 ConnRateThrottle); 272 if (LogLevel >= 9) 273 sm_syslog(LOG_INFO, NOQID, 274 "deferring connections: %d per second", 275 ConnRateThrottle); 276 (void) sleep(1); 277 } 278 } 279 280 for (idx = 0; idx < ndaemons; idx++) 281 { 282 if (timenow < Daemons[idx].d_refuse_connections_until) 283 continue; 284 if (refuseconnections(Daemons[idx].d_name, e, idx)) 285 { 286 if (Daemons[idx].d_socket >= 0) 287 { 288 /* close socket so peer fails quickly */ 289 (void) close(Daemons[idx].d_socket); 290 Daemons[idx].d_socket = -1; 291 } 292 293 /* refuse connections for next 15 seconds */ 294 Daemons[idx].d_refuse_connections_until = timenow + 15; 295 } 296 else if (Daemons[idx].d_socket < 0 || 297 Daemons[idx].d_firsttime) 298 { 299 if (!Daemons[idx].d_firsttime && LogLevel >= 9) 300 sm_syslog(LOG_INFO, NOQID, 301 "accepting connections again for daemon %s", 302 Daemons[idx].d_name); 303 304 /* arrange to (re)open the socket if needed */ 305 (void) opendaemonsocket(&Daemons[idx], FALSE); 306 Daemons[idx].d_firsttime = FALSE; 307 } 308 } 309 310 /* May have been sleeping above, check again */ 311 if (ShutdownRequest != NULL) 312 shutdown_daemon(); 313 else if (RestartRequest != NULL) 314 restart_daemon(); 315 316 if (timenow >= last_disk_space_check) 317 { 318 bool logged = FALSE; 319 320 if (!enoughdiskspace(MinBlocksFree + 1, FALSE)) 321 { 322 for (idx = 0; idx < ndaemons; idx++) 323 { 324 if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 325 { 326 /* log only if not logged before */ 327 if (!logged) 328 { 329 if (LogLevel >= 9) 330 sm_syslog(LOG_INFO, NOQID, 331 "rejecting new messages: min free: %ld", 332 MinBlocksFree); 333 logged = TRUE; 334 sm_setproctitle(TRUE, e, 335 "rejecting new messages: min free: %ld", 336 MinBlocksFree); 337 } 338 setbitn(D_ETRNONLY, Daemons[idx].d_flags); 339 } 340 } 341 } 342 else 343 { 344 for (idx = 0; idx < ndaemons; idx++) 345 { 346 if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 347 { 348 /* log only if not logged before */ 349 if (!logged) 350 { 351 if (LogLevel >= 9) 352 sm_syslog(LOG_INFO, NOQID, 353 "accepting new messages (again)"); 354 logged = TRUE; 355 } 356 357 /* title will be set below */ 358 clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 359 } 360 } 361 } 362 /* only check disk space once a minute */ 363 last_disk_space_check = timenow + 60; 364 } 365 366 # if XDEBUG 367 /* check for disaster */ 368 { 369 char jbuf[MAXHOSTNAMELEN]; 370 371 expand("\201j", jbuf, sizeof jbuf, e); 372 if (!wordinclass(jbuf, 'w')) 373 { 374 dumpstate("daemon lost $j"); 375 sm_syslog(LOG_ALERT, NOQID, 376 "daemon process doesn't have $j in $=w; see syslog"); 377 abort(); 378 } 379 else if (j_has_dot && strchr(jbuf, '.') == NULL) 380 { 381 dumpstate("daemon $j lost dot"); 382 sm_syslog(LOG_ALERT, NOQID, 383 "daemon process $j lost dot; see syslog"); 384 abort(); 385 } 386 } 387 # endif /* XDEBUG */ 388 389 # if 0 390 /* 391 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 392 ** fix the SVr4 problem. But it seems to have gone away, 393 ** so is it worth doing this? 394 */ 395 396 if (DaemonSocket >= 0 && 397 SetNonBlocking(DaemonSocket, FALSE) < 0) 398 log an error here; 399 # endif /* 0 */ 400 (void) releasesignal(SIGALRM); 401 402 for (;;) 403 { 404 bool setproc = FALSE; 405 int highest = -1; 406 fd_set readfds; 407 struct timeval timeout; 408 409 if (ShutdownRequest != NULL) 410 shutdown_daemon(); 411 else if (RestartRequest != NULL) 412 restart_daemon(); 413 414 FD_ZERO(&readfds); 415 416 for (idx = 0; idx < ndaemons; idx++) 417 { 418 /* wait for a connection */ 419 if (Daemons[idx].d_socket >= 0) 420 { 421 if (!setproc && 422 !bitnset(D_ETRNONLY, 423 Daemons[idx].d_flags)) 424 { 425 sm_setproctitle(TRUE, e, 426 "accepting connections"); 427 setproc = TRUE; 428 } 429 if (Daemons[idx].d_socket > highest) 430 highest = Daemons[idx].d_socket; 431 FD_SET((u_int)Daemons[idx].d_socket, &readfds); 432 } 433 } 434 435 # if NETUNIX 436 if (ControlSocket >= 0) 437 { 438 if (ControlSocket > highest) 439 highest = ControlSocket; 440 FD_SET(ControlSocket, &readfds); 441 } 442 # endif /* NETUNIX */ 443 444 timeout.tv_sec = 5; 445 timeout.tv_usec = 0; 446 447 t = select(highest + 1, FDSET_CAST &readfds, 448 NULL, NULL, &timeout); 449 450 /* Did someone signal while waiting? */ 451 if (ShutdownRequest != NULL) 452 shutdown_daemon(); 453 else if (RestartRequest != NULL) 454 restart_daemon(); 455 456 457 458 if (DoQueueRun) 459 (void) runqueue(TRUE, FALSE); 460 461 curdaemon = -1; 462 if (t <= 0) 463 { 464 timedout = TRUE; 465 break; 466 } 467 468 control = FALSE; 469 errno = 0; 470 471 /* look "round-robin" for an active socket */ 472 if ((idx = olddaemon + 1) >= ndaemons) 473 idx = 0; 474 for (i = 0; i < ndaemons; i++) 475 { 476 if (Daemons[idx].d_socket >= 0 && 477 FD_ISSET(Daemons[idx].d_socket, &readfds)) 478 { 479 lotherend = Daemons[idx].d_socksize; 480 memset(&RealHostAddr, '\0', 481 sizeof RealHostAddr); 482 t = accept(Daemons[idx].d_socket, 483 (struct sockaddr *)&RealHostAddr, 484 &lotherend); 485 486 /* 487 ** If remote side closes before 488 ** accept() finishes, sockaddr 489 ** might not be fully filled in. 490 */ 491 492 if (t >= 0 && 493 (lotherend == 0 || 494 # ifdef BSD4_4_SOCKADDR 495 RealHostAddr.sa.sa_len == 0 || 496 # endif /* BSD4_4_SOCKADDR */ 497 RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) 498 { 499 (void) close(t); 500 t = -1; 501 errno = EINVAL; 502 } 503 olddaemon = curdaemon = idx; 504 break; 505 } 506 if (++idx >= ndaemons) 507 idx = 0; 508 } 509 # if NETUNIX 510 if (curdaemon == -1 && ControlSocket >= 0 && 511 FD_ISSET(ControlSocket, &readfds)) 512 { 513 struct sockaddr_un sa_un; 514 515 lotherend = sizeof sa_un; 516 memset(&sa_un, '\0', sizeof sa_un); 517 t = accept(ControlSocket, 518 (struct sockaddr *)&sa_un, 519 &lotherend); 520 521 /* 522 ** If remote side closes before 523 ** accept() finishes, sockaddr 524 ** might not be fully filled in. 525 */ 526 527 if (t >= 0 && 528 (lotherend == 0 || 529 # ifdef BSD4_4_SOCKADDR 530 sa_un.sun_len == 0 || 531 # endif /* BSD4_4_SOCKADDR */ 532 sa_un.sun_family != AF_UNIX)) 533 { 534 (void) close(t); 535 t = -1; 536 errno = EINVAL; 537 } 538 if (t >= 0) 539 control = TRUE; 540 } 541 # else /* NETUNIX */ 542 if (curdaemon == -1) 543 { 544 /* No daemon to service */ 545 continue; 546 } 547 # endif /* NETUNIX */ 548 if (t >= 0 || errno != EINTR) 549 break; 550 } 551 if (timedout) 552 { 553 timedout = FALSE; 554 continue; 555 } 556 save_errno = errno; 557 timenow = curtime(); 558 (void) blocksignal(SIGALRM); 559 if (t < 0) 560 { 561 errno = save_errno; 562 syserr("getrequests: accept"); 563 564 /* arrange to re-open the socket next time around */ 565 (void) close(Daemons[curdaemon].d_socket); 566 Daemons[curdaemon].d_socket = -1; 567 # if SO_REUSEADDR_IS_BROKEN 568 /* 569 ** Give time for bound socket to be released. 570 ** This creates a denial-of-service if you can 571 ** force accept() to fail on affected systems. 572 */ 573 574 Daemons[curdaemon].d_refuse_connections_until = timenow + 15; 575 # endif /* SO_REUSEADDR_IS_BROKEN */ 576 continue; 577 } 578 579 if (!control) 580 { 581 /* set some daemon related macros */ 582 switch (Daemons[curdaemon].d_addr.sa.sa_family) 583 { 584 case AF_UNSPEC: 585 define(macid("{daemon_family}", NULL), 586 "unspec", &BlankEnvelope); 587 break; 588 # if NETINET 589 case AF_INET: 590 define(macid("{daemon_family}", NULL), 591 "inet", &BlankEnvelope); 592 break; 593 # endif /* NETINET */ 594 # if NETINET6 595 case AF_INET6: 596 define(macid("{daemon_family}", NULL), 597 "inet6", &BlankEnvelope); 598 break; 599 # endif /* NETINET6 */ 600 # if NETISO 601 case AF_ISO: 602 define(macid("{daemon_family}", NULL), 603 "iso", &BlankEnvelope); 604 break; 605 # endif /* NETISO */ 606 # if NETNS 607 case AF_NS: 608 define(macid("{daemon_family}", NULL), 609 "ns", &BlankEnvelope); 610 break; 611 # endif /* NETNS */ 612 # if NETX25 613 case AF_CCITT: 614 define(macid("{daemon_family}", NULL), 615 "x.25", &BlankEnvelope); 616 break; 617 # endif /* NETX25 */ 618 } 619 define(macid("{daemon_name}", NULL), 620 Daemons[curdaemon].d_name, &BlankEnvelope); 621 if (Daemons[curdaemon].d_mflags != NULL) 622 define(macid("{daemon_flags}", NULL), 623 Daemons[curdaemon].d_mflags, 624 &BlankEnvelope); 625 else 626 define(macid("{daemon_flags}", NULL), 627 "", &BlankEnvelope); 628 } 629 630 /* 631 ** Create a subprocess to process the mail. 632 */ 633 634 if (tTd(15, 2)) 635 dprintf("getrequests: forking (fd = %d)\n", t); 636 637 /* 638 ** advance state of PRNG 639 ** this is necessary because otherwise all child processes 640 ** will produce the same PRN sequence and hence the selection 641 ** of a queue directory (and other things, e.g., MX selection) 642 ** are not "really" random. 643 */ 644 # if STARTTLS 645 seed = get_random(); 646 RAND_seed((void *) &last_disk_space_check, 647 sizeof last_disk_space_check); 648 RAND_seed((void *) &timenow, sizeof timenow); 649 RAND_seed((void *) &seed, sizeof seed); 650 # else /* STARTTLS */ 651 (void) get_random(); 652 # endif /* STARTTLS */ 653 654 #ifndef DEBUG_NO_FORK 655 /* 656 ** Create a pipe to keep the child from writing to the 657 ** socket until after the parent has closed it. Otherwise 658 ** the parent may hang if the child has closed it first. 659 */ 660 661 if (pipe(pipefd) < 0) 662 pipefd[0] = pipefd[1] = -1; 663 664 (void) blocksignal(SIGCHLD); 665 pid = fork(); 666 if (pid < 0) 667 { 668 syserr("daemon: cannot fork"); 669 if (pipefd[0] != -1) 670 { 671 (void) close(pipefd[0]); 672 (void) close(pipefd[1]); 673 } 674 (void) releasesignal(SIGCHLD); 675 (void) sleep(10); 676 (void) close(t); 677 continue; 678 } 679 #else /* ! DEBUG_NO_FORK */ 680 pid = 0; 681 #endif /* ! DEBUG_NO_FORK */ 682 683 if (pid == 0) 684 { 685 char *p; 686 FILE *inchannel, *outchannel = NULL; 687 688 /* 689 ** CHILD -- return to caller. 690 ** Collect verified idea of sending host. 691 ** Verify calling user id if possible here. 692 */ 693 694 /* Reset global flags */ 695 RestartRequest = NULL; 696 ShutdownRequest = NULL; 697 PendingSignal = 0; 698 699 (void) releasesignal(SIGALRM); 700 (void) releasesignal(SIGCHLD); 701 (void) setsignal(SIGCHLD, SIG_DFL); 702 (void) setsignal(SIGHUP, SIG_DFL); 703 (void) setsignal(SIGTERM, intsig); 704 705 706 if (!control) 707 { 708 define(macid("{daemon_addr}", NULL), 709 newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)), 710 &BlankEnvelope); 711 (void) snprintf(status, sizeof status, "%d", 712 ntohs(Daemons[curdaemon].d_port)); 713 define(macid("{daemon_port}", NULL), 714 newstr(status), &BlankEnvelope); 715 } 716 717 for (idx = 0; idx < ndaemons; idx++) 718 { 719 if (Daemons[idx].d_socket >= 0) 720 (void) close(Daemons[idx].d_socket); 721 } 722 clrcontrol(); 723 724 /* Avoid SMTP daemon actions if control command */ 725 if (control) 726 { 727 /* Add control socket process */ 728 proc_list_add(getpid(), "console socket child", 729 PROC_CONTROL_CHILD); 730 } 731 else 732 { 733 proc_list_clear(); 734 735 /* Add parent process as first child item */ 736 proc_list_add(getpid(), "daemon child", 737 PROC_DAEMON_CHILD); 738 739 /* don't schedule queue runs if ETRN */ 740 QueueIntvl = 0; 741 742 sm_setproctitle(TRUE, e, "startup with %s", 743 anynet_ntoa(&RealHostAddr)); 744 } 745 746 #ifndef DEBUG_NO_FORK 747 if (pipefd[0] != -1) 748 { 749 auto char c; 750 751 /* 752 ** Wait for the parent to close the write end 753 ** of the pipe, which we will see as an EOF. 754 ** This guarantees that we won't write to the 755 ** socket until after the parent has closed 756 ** the pipe. 757 */ 758 759 /* close the write end of the pipe */ 760 (void) close(pipefd[1]); 761 762 /* we shouldn't be interrupted, but ... */ 763 while (read(pipefd[0], &c, 1) < 0 && 764 errno == EINTR) 765 continue; 766 (void) close(pipefd[0]); 767 } 768 #endif /* ! DEBUG_NO_FORK */ 769 770 /* control socket processing */ 771 if (control) 772 { 773 control_command(t, e); 774 775 /* NOTREACHED */ 776 exit(EX_SOFTWARE); 777 } 778 779 /* determine host name */ 780 p = hostnamebyanyaddr(&RealHostAddr); 781 if (strlen(p) > (SIZE_T) MAXNAME) 782 p[MAXNAME] = '\0'; 783 RealHostName = newstr(p); 784 if (RealHostName[0] == '[') 785 { 786 /* TEMP, FAIL: which one? */ 787 define(macid("{client_resolve}", NULL), 788 (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL", 789 &BlankEnvelope); 790 } 791 else 792 define(macid("{client_resolve}", NULL), "OK", 793 &BlankEnvelope); 794 sm_setproctitle(TRUE, e, "startup with %s", p); 795 796 if ((inchannel = fdopen(t, "r")) == NULL || 797 (t = dup(t)) < 0 || 798 (outchannel = fdopen(t, "w")) == NULL) 799 { 800 syserr("cannot open SMTP server channel, fd=%d", t); 801 finis(FALSE, EX_OK); 802 } 803 804 InChannel = inchannel; 805 OutChannel = outchannel; 806 DisConnected = FALSE; 807 808 # ifdef XLA 809 if (!xla_host_ok(RealHostName)) 810 { 811 message("421 4.4.5 Too many SMTP sessions for this host"); 812 finis(FALSE, EX_OK); 813 } 814 # endif /* XLA */ 815 /* find out name for interface of connection */ 816 if (getsockname(fileno(InChannel), &sa.sa, 817 &len) == 0) 818 { 819 p = hostnamebyanyaddr(&sa); 820 if (tTd(15, 9)) 821 dprintf("getreq: got name %s\n", p); 822 define(macid("{if_name}", NULL), 823 newstr(p), &BlankEnvelope); 824 825 /* do this only if it is not the loopback */ 826 /* interface: how to figure out? XXX */ 827 if (!isloopback(sa)) 828 { 829 define(macid("{if_addr}", NULL), 830 newstr(anynet_ntoa(&sa)), 831 &BlankEnvelope); 832 p = xalloc(5); 833 snprintf(p, 4, "%d", sa.sa.sa_family); 834 define(macid("{if_family}", NULL), p, 835 &BlankEnvelope); 836 if (tTd(15, 7)) 837 dprintf("getreq: got addr %s and family %s\n", 838 macvalue(macid("{if_addr}", NULL), 839 &BlankEnvelope), 840 macvalue(macid("{if_addr}", NULL), 841 &BlankEnvelope)); 842 } 843 else 844 { 845 define(macid("{if_addr}", NULL), NULL, 846 &BlankEnvelope); 847 define(macid("{if_family}", NULL), NULL, 848 &BlankEnvelope); 849 } 850 } 851 else 852 { 853 if (tTd(15, 7)) 854 dprintf("getreq: getsockname failed\n"); 855 define(macid("{if_name}", NULL), NULL, 856 &BlankEnvelope); 857 define(macid("{if_addr}", NULL), NULL, 858 &BlankEnvelope); 859 define(macid("{if_family}", NULL), NULL, 860 &BlankEnvelope); 861 } 862 break; 863 } 864 865 /* parent -- keep track of children */ 866 if (control) 867 { 868 snprintf(status, sizeof status, "control socket server child"); 869 proc_list_add(pid, status, PROC_CONTROL); 870 } 871 else 872 { 873 snprintf(status, sizeof status, 874 "SMTP server child for %s", 875 anynet_ntoa(&RealHostAddr)); 876 proc_list_add(pid, status, PROC_DAEMON); 877 } 878 (void) releasesignal(SIGCHLD); 879 880 /* close the read end of the synchronization pipe */ 881 if (pipefd[0] != -1) 882 { 883 (void) close(pipefd[0]); 884 pipefd[0] = -1; 885 } 886 887 /* close the port so that others will hang (for a while) */ 888 (void) close(t); 889 890 /* release the child by closing the read end of the sync pipe */ 891 if (pipefd[1] != -1) 892 { 893 (void) close(pipefd[1]); 894 pipefd[1] = -1; 895 } 896 } 897 898 if (tTd(15, 2)) 899 dprintf("getreq: returning\n"); 900 return &Daemons[curdaemon].d_flags; 901 } 902 /* 903 ** OPENDAEMONSOCKET -- open SMTP socket 904 ** 905 ** Deals with setting all appropriate options. 906 ** 907 ** Parameters: 908 ** d -- the structure for the daemon to open. 909 ** firsttime -- set if this is the initial open. 910 ** 911 ** Returns: 912 ** Size in bytes of the daemon socket addr. 913 ** 914 ** Side Effects: 915 ** Leaves DaemonSocket set to the open socket. 916 ** Exits if the socket cannot be created. 917 */ 918 919 # define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 920 921 static int 922 opendaemonsocket(d, firsttime) 923 struct daemon *d; 924 bool firsttime; 925 { 926 int on = 1; 927 int fdflags; 928 SOCKADDR_LEN_T socksize = 0; 929 int ntries = 0; 930 int save_errno; 931 932 if (tTd(15, 2)) 933 dprintf("opendaemonsocket(%s)\n", d->d_name); 934 935 do 936 { 937 if (ntries > 0) 938 (void) sleep(5); 939 if (firsttime || d->d_socket < 0) 940 { 941 d->d_socket = socket(d->d_addr.sa.sa_family, 942 SOCK_STREAM, 0); 943 if (d->d_socket < 0) 944 { 945 save_errno = errno; 946 syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name); 947 severe: 948 if (LogLevel > 0) 949 sm_syslog(LOG_ALERT, NOQID, 950 "daemon %s: problem creating SMTP socket", d->d_name); 951 d->d_socket = -1; 952 continue; 953 } 954 955 /* turn on network debugging? */ 956 if (tTd(15, 101)) 957 (void) setsockopt(d->d_socket, SOL_SOCKET, 958 SO_DEBUG, (char *)&on, 959 sizeof on); 960 961 (void) setsockopt(d->d_socket, SOL_SOCKET, 962 SO_REUSEADDR, (char *)&on, sizeof on); 963 (void) setsockopt(d->d_socket, SOL_SOCKET, 964 SO_KEEPALIVE, (char *)&on, sizeof on); 965 966 # ifdef SO_RCVBUF 967 if (d->d_tcprcvbufsize > 0) 968 { 969 if (setsockopt(d->d_socket, SOL_SOCKET, 970 SO_RCVBUF, 971 (char *) &d->d_tcprcvbufsize, 972 sizeof(d->d_tcprcvbufsize)) < 0) 973 syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 974 } 975 # endif /* SO_RCVBUF */ 976 # ifdef SO_SNDBUF 977 if (d->d_tcpsndbufsize > 0) 978 { 979 if (setsockopt(d->d_socket, SOL_SOCKET, 980 SO_SNDBUF, 981 (char *) &d->d_tcpsndbufsize, 982 sizeof(d->d_tcpsndbufsize)) < 0) 983 syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 984 } 985 # endif /* SO_SNDBUF */ 986 987 if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 988 fcntl(d->d_socket, F_SETFD, 989 fdflags | FD_CLOEXEC) == -1) 990 { 991 save_errno = errno; 992 syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 993 d->d_name, 994 fdflags == -1 ? "get" : "set", 995 errstring(save_errno)); 996 (void) close(d->d_socket); 997 goto severe; 998 } 999 1000 switch (d->d_addr.sa.sa_family) 1001 { 1002 # if NETINET 1003 case AF_INET: 1004 socksize = sizeof d->d_addr.sin; 1005 break; 1006 # endif /* NETINET */ 1007 1008 # if NETINET6 1009 case AF_INET6: 1010 socksize = sizeof d->d_addr.sin6; 1011 break; 1012 # endif /* NETINET6 */ 1013 1014 # if NETISO 1015 case AF_ISO: 1016 socksize = sizeof d->d_addr.siso; 1017 break; 1018 # endif /* NETISO */ 1019 1020 default: 1021 socksize = sizeof d->d_addr; 1022 break; 1023 } 1024 1025 if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 1026 { 1027 /* probably another daemon already */ 1028 save_errno = errno; 1029 syserr("opendaemonsocket: daemon %s: cannot bind", 1030 d->d_name); 1031 (void) close(d->d_socket); 1032 goto severe; 1033 } 1034 } 1035 if (!firsttime && 1036 listen(d->d_socket, d->d_listenqueue) < 0) 1037 { 1038 save_errno = errno; 1039 syserr("opendaemonsocket: daemon %s: cannot listen", 1040 d->d_name); 1041 (void) close(d->d_socket); 1042 goto severe; 1043 } 1044 return socksize; 1045 } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 1046 syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 1047 d->d_name); 1048 /* NOTREACHED */ 1049 return -1; /* avoid compiler warning on IRIX */ 1050 } 1051 /* 1052 ** SETUPDAEMON -- setup socket for daemon 1053 ** 1054 ** Parameters: 1055 ** daemonaddr -- socket for daemon 1056 ** daemon -- number of daemon 1057 ** 1058 ** Returns: 1059 ** port number on which daemon should run 1060 ** 1061 */ 1062 static u_short 1063 setupdaemon(daemonaddr) 1064 SOCKADDR *daemonaddr; 1065 { 1066 u_short port; 1067 1068 /* 1069 ** Set up the address for the mailer. 1070 */ 1071 1072 if (daemonaddr->sa.sa_family == AF_UNSPEC) 1073 { 1074 memset(daemonaddr, '\0', sizeof *daemonaddr); 1075 # if NETINET 1076 daemonaddr->sa.sa_family = AF_INET; 1077 # endif /* NETINET */ 1078 } 1079 1080 switch (daemonaddr->sa.sa_family) 1081 { 1082 # if NETINET 1083 case AF_INET: 1084 if (daemonaddr->sin.sin_addr.s_addr == 0) 1085 daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 1086 port = daemonaddr->sin.sin_port; 1087 break; 1088 # endif /* NETINET */ 1089 1090 # if NETINET6 1091 case AF_INET6: 1092 if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 1093 daemonaddr->sin6.sin6_addr = in6addr_any; 1094 port = daemonaddr->sin6.sin6_port; 1095 break; 1096 # endif /* NETINET6 */ 1097 1098 default: 1099 /* unknown protocol */ 1100 port = 0; 1101 break; 1102 } 1103 if (port == 0) 1104 { 1105 # ifdef NO_GETSERVBYNAME 1106 port = htons(25); 1107 # else /* NO_GETSERVBYNAME */ 1108 { 1109 register struct servent *sp; 1110 1111 sp = getservbyname("smtp", "tcp"); 1112 if (sp == NULL) 1113 { 1114 syserr("554 5.3.5 service \"smtp\" unknown"); 1115 port = htons(25); 1116 } 1117 else 1118 port = sp->s_port; 1119 } 1120 # endif /* NO_GETSERVBYNAME */ 1121 } 1122 1123 switch (daemonaddr->sa.sa_family) 1124 { 1125 # if NETINET 1126 case AF_INET: 1127 daemonaddr->sin.sin_port = port; 1128 break; 1129 # endif /* NETINET */ 1130 1131 # if NETINET6 1132 case AF_INET6: 1133 daemonaddr->sin6.sin6_port = port; 1134 break; 1135 # endif /* NETINET6 */ 1136 1137 default: 1138 /* unknown protocol */ 1139 break; 1140 } 1141 return(port); 1142 } 1143 /* 1144 ** CLRDAEMON -- reset the daemon connection 1145 ** 1146 ** Parameters: 1147 ** none. 1148 ** 1149 ** Returns: 1150 ** none. 1151 ** 1152 ** Side Effects: 1153 ** releases any resources used by the passive daemon. 1154 */ 1155 1156 void 1157 clrdaemon() 1158 { 1159 int i; 1160 1161 for (i = 0; i < ndaemons; i++) 1162 { 1163 if (Daemons[i].d_socket >= 0) 1164 (void) close(Daemons[i].d_socket); 1165 Daemons[i].d_socket = -1; 1166 } 1167 } 1168 /* 1169 ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 1170 ** 1171 ** Parameters: 1172 ** p -- the options line. 1173 ** d -- the daemon structure to fill in. 1174 ** 1175 ** Returns: 1176 ** none. 1177 */ 1178 1179 static void 1180 setsockaddroptions(p, d) 1181 register char *p; 1182 struct daemon *d; 1183 { 1184 # if NETISO 1185 short portno; 1186 # endif /* NETISO */ 1187 int l; 1188 char *h, *flags; 1189 char *port = NULL; 1190 char *addr = NULL; 1191 1192 # if NETINET 1193 if (d->d_addr.sa.sa_family == AF_UNSPEC) 1194 d->d_addr.sa.sa_family = AF_INET; 1195 # endif /* NETINET */ 1196 1197 while (p != NULL) 1198 { 1199 register char *f; 1200 register char *v; 1201 1202 while (isascii(*p) && isspace(*p)) 1203 p++; 1204 if (*p == '\0') 1205 break; 1206 f = p; 1207 p = strchr(p, ','); 1208 if (p != NULL) 1209 *p++ = '\0'; 1210 v = strchr(f, '='); 1211 if (v == NULL) 1212 continue; 1213 while (isascii(*++v) && isspace(*v)) 1214 continue; 1215 if (isascii(*f) && islower(*f)) 1216 *f = toupper(*f); 1217 1218 switch (*f) 1219 { 1220 case 'F': /* address family */ 1221 if (isascii(*v) && isdigit(*v)) 1222 d->d_addr.sa.sa_family = atoi(v); 1223 # if NETINET 1224 else if (strcasecmp(v, "inet") == 0) 1225 d->d_addr.sa.sa_family = AF_INET; 1226 # endif /* NETINET */ 1227 # if NETINET6 1228 else if (strcasecmp(v, "inet6") == 0) 1229 d->d_addr.sa.sa_family = AF_INET6; 1230 # endif /* NETINET6 */ 1231 # if NETISO 1232 else if (strcasecmp(v, "iso") == 0) 1233 d->d_addr.sa.sa_family = AF_ISO; 1234 # endif /* NETISO */ 1235 # if NETNS 1236 else if (strcasecmp(v, "ns") == 0) 1237 d->d_addr.sa.sa_family = AF_NS; 1238 # endif /* NETNS */ 1239 # if NETX25 1240 else if (strcasecmp(v, "x.25") == 0) 1241 d->d_addr.sa.sa_family = AF_CCITT; 1242 # endif /* NETX25 */ 1243 else 1244 syserr("554 5.3.5 Unknown address family %s in Family=option", 1245 v); 1246 break; 1247 1248 case 'A': /* address */ 1249 addr = v; 1250 break; 1251 1252 case 'P': /* port */ 1253 port = v; 1254 break; 1255 1256 case 'L': /* listen queue size */ 1257 d->d_listenqueue = atoi(v); 1258 break; 1259 1260 case 'M': /* modifiers (flags) */ 1261 l = 3 * strlen(v) + 3; 1262 h = v; 1263 flags = xalloc(l); 1264 d->d_mflags = flags; 1265 for (; *h != '\0'; h++) 1266 { 1267 if (!(isascii(*h) && isspace(*h))) 1268 { 1269 if (flags != d->d_mflags) 1270 *flags++ = ' '; 1271 *flags++ = *h; 1272 if (isupper(*h)) 1273 *flags++ = *h; 1274 } 1275 } 1276 *flags++ = '\0'; 1277 for (; *v != '\0'; v++) 1278 if (!(isascii(*v) && isspace(*v))) 1279 setbitn(bitidx(*v), d->d_flags); 1280 break; 1281 1282 case 'S': /* send buffer size */ 1283 d->d_tcpsndbufsize = atoi(v); 1284 break; 1285 1286 case 'R': /* receive buffer size */ 1287 d->d_tcprcvbufsize = atoi(v); 1288 break; 1289 1290 case 'N': /* name */ 1291 d->d_name = v; 1292 break; 1293 1294 default: 1295 syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 1296 f); 1297 } 1298 } 1299 1300 /* Check addr and port after finding family */ 1301 if (addr != NULL) 1302 { 1303 switch (d->d_addr.sa.sa_family) 1304 { 1305 # if NETINET 1306 case AF_INET: 1307 if (!isascii(*addr) || !isdigit(*addr) || 1308 ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) == INADDR_NONE)) 1309 { 1310 register struct hostent *hp; 1311 1312 hp = sm_gethostbyname(addr, AF_INET); 1313 if (hp == NULL) 1314 syserr("554 5.3.0 host \"%s\" unknown", 1315 addr); 1316 else 1317 { 1318 while (*(hp->h_addr_list) != NULL && 1319 hp->h_addrtype != AF_INET) 1320 hp->h_addr_list++; 1321 if (*(hp->h_addr_list) == NULL) 1322 syserr("554 5.3.0 host \"%s\" unknown", 1323 addr); 1324 else 1325 memmove(&d->d_addr.sin.sin_addr, 1326 *(hp->h_addr_list), 1327 INADDRSZ); 1328 # if _FFR_FREEHOSTENT && NETINET6 1329 freehostent(hp); 1330 hp = NULL; 1331 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 1332 } 1333 } 1334 break; 1335 # endif /* NETINET */ 1336 1337 # if NETINET6 1338 case AF_INET6: 1339 if (!isascii(*addr) || 1340 (!isxdigit(*addr) && *addr != ':') || 1341 inet_pton(AF_INET6, addr, 1342 &d->d_addr.sin6.sin6_addr) != 1) 1343 { 1344 register struct hostent *hp; 1345 1346 hp = sm_gethostbyname(addr, AF_INET6); 1347 if (hp == NULL) 1348 syserr("554 5.3.0 host \"%s\" unknown", 1349 addr); 1350 else 1351 { 1352 while (*(hp->h_addr_list) != NULL && 1353 hp->h_addrtype != AF_INET6) 1354 hp->h_addr_list++; 1355 if (*(hp->h_addr_list) == NULL) 1356 syserr("554 5.3.0 host \"%s\" unknown", 1357 addr); 1358 else 1359 memmove(&d->d_addr.sin6.sin6_addr, 1360 *(hp->h_addr_list), 1361 IN6ADDRSZ); 1362 # if _FFR_FREEHOSTENT 1363 freehostent(hp); 1364 hp = NULL; 1365 # endif /* _FFR_FREEHOSTENT */ 1366 } 1367 } 1368 break; 1369 # endif /* NETINET6 */ 1370 1371 default: 1372 syserr("554 5.3.5 address= option unsupported for family %d", 1373 d->d_addr.sa.sa_family); 1374 break; 1375 } 1376 } 1377 1378 if (port != NULL) 1379 { 1380 switch (d->d_addr.sa.sa_family) 1381 { 1382 # if NETINET 1383 case AF_INET: 1384 if (isascii(*port) && isdigit(*port)) 1385 d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)port)); 1386 else 1387 { 1388 # ifdef NO_GETSERVBYNAME 1389 syserr("554 5.3.5 invalid port number: %s", 1390 port); 1391 # else /* NO_GETSERVBYNAME */ 1392 register struct servent *sp; 1393 1394 sp = getservbyname(port, "tcp"); 1395 if (sp == NULL) 1396 syserr("554 5.3.5 service \"%s\" unknown", 1397 port); 1398 else 1399 d->d_addr.sin.sin_port = sp->s_port; 1400 # endif /* NO_GETSERVBYNAME */ 1401 } 1402 break; 1403 # endif /* NETINET */ 1404 1405 # if NETINET6 1406 case AF_INET6: 1407 if (isascii(*port) && isdigit(*port)) 1408 d->d_addr.sin6.sin6_port = htons((u_short)atoi(port)); 1409 else 1410 { 1411 # ifdef NO_GETSERVBYNAME 1412 syserr("554 5.3.5 invalid port number: %s", 1413 port); 1414 # else /* NO_GETSERVBYNAME */ 1415 register struct servent *sp; 1416 1417 sp = getservbyname(port, "tcp"); 1418 if (sp == NULL) 1419 syserr("554 5.3.5 service \"%s\" unknown", 1420 port); 1421 else 1422 d->d_addr.sin6.sin6_port = sp->s_port; 1423 # endif /* NO_GETSERVBYNAME */ 1424 } 1425 break; 1426 # endif /* NETINET6 */ 1427 1428 # if NETISO 1429 case AF_ISO: 1430 /* assume two byte transport selector */ 1431 if (isascii(*port) && isdigit(*port)) 1432 portno = htons((u_short)atoi(port)); 1433 else 1434 { 1435 # ifdef NO_GETSERVBYNAME 1436 syserr("554 5.3.5 invalid port number: %s", 1437 port); 1438 # else /* NO_GETSERVBYNAME */ 1439 register struct servent *sp; 1440 1441 sp = getservbyname(port, "tcp"); 1442 if (sp == NULL) 1443 syserr("554 5.3.5 service \"%s\" unknown", 1444 port); 1445 else 1446 portno = sp->s_port; 1447 # endif /* NO_GETSERVBYNAME */ 1448 } 1449 memmove(TSEL(&d->d_addr.siso), 1450 (char *) &portno, 2); 1451 break; 1452 # endif /* NETISO */ 1453 1454 default: 1455 syserr("554 5.3.5 Port= option unsupported for family %d", 1456 d->d_addr.sa.sa_family); 1457 break; 1458 } 1459 } 1460 } 1461 /* 1462 ** SETDAEMONOPTIONS -- set options for running the MTA daemon 1463 ** 1464 ** Parameters: 1465 ** p -- the options line. 1466 ** 1467 ** Returns: 1468 ** TRUE if successful, FALSE otherwise. 1469 */ 1470 1471 bool 1472 setdaemonoptions(p) 1473 register char *p; 1474 { 1475 if (ndaemons >= MAXDAEMONS) 1476 return FALSE; 1477 Daemons[ndaemons].d_socket = -1; 1478 Daemons[ndaemons].d_listenqueue = 10; 1479 clrbitmap(Daemons[ndaemons].d_flags); 1480 setsockaddroptions(p, &Daemons[ndaemons]); 1481 1482 if (Daemons[ndaemons].d_name != NULL) 1483 Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name); 1484 else 1485 { 1486 char num[30]; 1487 1488 snprintf(num, sizeof num, "Daemon%d", ndaemons); 1489 Daemons[ndaemons].d_name = newstr(num); 1490 } 1491 1492 if (tTd(37, 1)) 1493 { 1494 dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name); 1495 if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags)) 1496 dprintf("ETRNONLY "); 1497 if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags)) 1498 dprintf("NOETRN "); 1499 dprintf("\n"); 1500 } 1501 ++ndaemons; 1502 return TRUE; 1503 } 1504 /* 1505 ** INITDAEMON -- initialize daemon if not yet done. 1506 ** 1507 ** Parameters: 1508 ** none 1509 ** 1510 ** Returns: 1511 ** none 1512 ** 1513 ** Side Effects: 1514 ** initializes structure for one daemon. 1515 */ 1516 void 1517 initdaemon() 1518 { 1519 if (ndaemons == 0) 1520 { 1521 Daemons[ndaemons].d_socket = -1; 1522 Daemons[ndaemons].d_listenqueue = 10; 1523 Daemons[ndaemons].d_name = "Daemon0"; 1524 ndaemons = 1; 1525 } 1526 } 1527 /* 1528 ** SETCLIENTOPTIONS -- set options for running the client 1529 ** 1530 ** Parameters: 1531 ** p -- the options line. 1532 ** 1533 ** Returns: 1534 ** none. 1535 */ 1536 1537 static SOCKADDR ClientAddr; /* address for client */ 1538 1539 void 1540 setclientoptions(p) 1541 register char *p; 1542 { 1543 struct daemon d; 1544 extern ENVELOPE BlankEnvelope; 1545 1546 memset(&d, '\0', sizeof d); 1547 setsockaddroptions(p, &d); 1548 1549 /* grab what we need */ 1550 memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr); 1551 TcpSndBufferSize = d.d_tcpsndbufsize; 1552 TcpRcvBufferSize = d.d_tcprcvbufsize; 1553 if (d.d_mflags != NULL) 1554 define(macid("{client_flags}", NULL), d.d_mflags, 1555 &BlankEnvelope); 1556 else 1557 define(macid("{client_flags}", NULL), "", &BlankEnvelope); 1558 } 1559 /* 1560 ** ADDR_FAMILY -- determine address family from address 1561 ** 1562 ** Parameters: 1563 ** addr -- the string representation of the address 1564 ** 1565 ** Returns: 1566 ** AF_INET, AF_INET6 or AF_UNSPEC 1567 ** 1568 ** Side Effects: 1569 ** none. 1570 */ 1571 1572 static int 1573 addr_family(addr) 1574 char *addr; 1575 { 1576 # if NETINET6 1577 SOCKADDR clt_addr; 1578 # endif /* NETINET6 */ 1579 1580 # if NETINET 1581 if (inet_addr(addr) != INADDR_NONE) 1582 { 1583 if (tTd(16, 9)) 1584 printf("addr_family(%s): INET\n", addr); 1585 return AF_INET; 1586 } 1587 # endif /* NETINET */ 1588 # if NETINET6 1589 if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 1590 { 1591 if (tTd(16, 9)) 1592 printf("addr_family(%s): INET6\n", addr); 1593 return AF_INET6; 1594 } 1595 # endif /* NETINET6 */ 1596 if (tTd(16, 9)) 1597 printf("addr_family(%s): UNSPEC\n", addr); 1598 return AF_UNSPEC; 1599 } 1600 /* 1601 ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 1602 ** 1603 ** Parameters: 1604 ** host -- the name of the host. 1605 ** port -- the port number to connect to. 1606 ** mci -- a pointer to the mail connection information 1607 ** structure to be filled in. 1608 ** e -- the current envelope. 1609 ** 1610 ** Returns: 1611 ** An exit code telling whether the connection could be 1612 ** made and if not why not. 1613 ** 1614 ** Side Effects: 1615 ** none. 1616 */ 1617 1618 static jmp_buf CtxConnectTimeout; 1619 1620 SOCKADDR CurHostAddr; /* address of current host */ 1621 1622 int 1623 makeconnection(host, port, mci, e) 1624 char *host; 1625 volatile u_int port; 1626 register MCI *mci; 1627 ENVELOPE *e; 1628 { 1629 register volatile int addrno = 0; 1630 register volatile int s; 1631 register struct hostent *volatile hp = (struct hostent *)NULL; 1632 SOCKADDR addr; 1633 SOCKADDR clt_addr; 1634 int save_errno = 0; 1635 volatile SOCKADDR_LEN_T addrlen; 1636 volatile bool firstconnect; 1637 EVENT *volatile ev = NULL; 1638 # if NETINET6 1639 volatile bool v6found = FALSE; 1640 # endif /* NETINET6 */ 1641 volatile int family = InetMode; 1642 SOCKADDR_LEN_T len; 1643 volatile SOCKADDR_LEN_T socksize = 0; 1644 volatile bool clt_bind; 1645 BITMAP256 d_flags; 1646 char *p; 1647 extern ENVELOPE BlankEnvelope; 1648 1649 /* retranslate ${daemon_flags} into bitmap */ 1650 clrbitmap(d_flags); 1651 if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL) 1652 { 1653 for (; *p != '\0'; p++) 1654 { 1655 if (!(isascii(*p) && isspace(*p))) 1656 setbitn(bitidx(*p), d_flags); 1657 } 1658 } 1659 1660 /* "add" ${client_flags} to bitmap */ 1661 if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL) 1662 { 1663 for (; *p != '\0'; p++) 1664 { 1665 /* look for just this one flag */ 1666 if (*p == D_IFNHELO) 1667 { 1668 setbitn(bitidx(*p), d_flags); 1669 break; 1670 } 1671 } 1672 } 1673 1674 # if NETINET6 1675 v4retry: 1676 # endif /* NETINET6 */ 1677 clt_bind = FALSE; 1678 1679 /* Set up the address for outgoing connection. */ 1680 if (bitnset(D_BINDIF, d_flags) && 1681 (p = macvalue(macid("{if_addr}", NULL), e)) != NULL && 1682 *p != '\0') 1683 { 1684 # if NETINET6 1685 char p6[INET6_ADDRSTRLEN]; 1686 # endif /* NETINET6 */ 1687 1688 memset(&clt_addr, '\0', sizeof clt_addr); 1689 1690 /* infer the address family from the address itself */ 1691 clt_addr.sa.sa_family = addr_family(p); 1692 switch (clt_addr.sa.sa_family) 1693 { 1694 # if NETINET 1695 case AF_INET: 1696 clt_addr.sin.sin_addr.s_addr = inet_addr(p); 1697 if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 1698 clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) 1699 { 1700 clt_bind = TRUE; 1701 socksize = sizeof (struct sockaddr_in); 1702 } 1703 break; 1704 # endif /* NETINET */ 1705 1706 # if NETINET6 1707 case AF_INET6: 1708 if (inet_addr(p) != INADDR_NONE) 1709 snprintf(p6, sizeof p6, "::ffff:%s", p); 1710 else 1711 strlcpy(p6, p, sizeof p6); 1712 if (inet_pton(AF_INET6, p6, 1713 &clt_addr.sin6.sin6_addr) == 1 && 1714 !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 1715 { 1716 clt_bind = TRUE; 1717 socksize = sizeof (struct sockaddr_in6); 1718 } 1719 break; 1720 # endif /* NETINET6 */ 1721 1722 # if 0 1723 default: 1724 syserr("554 5.3.5 Address= option unsupported for family %d", 1725 clt_addr.sa.sa_family); 1726 break; 1727 # endif /* 0 */ 1728 } 1729 if (clt_bind) 1730 family = clt_addr.sa.sa_family; 1731 } 1732 else 1733 { 1734 STRUCTCOPY(ClientAddr, clt_addr); 1735 if (clt_addr.sa.sa_family == AF_UNSPEC) 1736 clt_addr.sa.sa_family = family; 1737 switch (clt_addr.sa.sa_family) 1738 { 1739 # if NETINET 1740 case AF_INET: 1741 if (clt_addr.sin.sin_addr.s_addr == 0) 1742 clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 1743 else 1744 clt_bind = TRUE; 1745 if (clt_addr.sin.sin_port != 0) 1746 clt_bind = TRUE; 1747 socksize = sizeof (struct sockaddr_in); 1748 break; 1749 # endif /* NETINET */ 1750 # if NETINET6 1751 case AF_INET6: 1752 if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 1753 clt_addr.sin6.sin6_addr = in6addr_any; 1754 else 1755 clt_bind = TRUE; 1756 socksize = sizeof (struct sockaddr_in6); 1757 if (clt_addr.sin6.sin6_port != 0) 1758 clt_bind = TRUE; 1759 break; 1760 # endif /* NETINET6 */ 1761 # if NETISO 1762 case AF_ISO: 1763 socksize = sizeof clt_addr.siso; 1764 clt_bind = TRUE; 1765 break; 1766 # endif /* NETISO */ 1767 default: 1768 break; 1769 } 1770 } 1771 1772 /* 1773 ** Set up the address for the mailer. 1774 ** Accept "[a.b.c.d]" syntax for host name. 1775 */ 1776 1777 # if NAMED_BIND 1778 SM_SET_H_ERRNO(0); 1779 # endif /* NAMED_BIND */ 1780 errno = 0; 1781 memset(&CurHostAddr, '\0', sizeof CurHostAddr); 1782 memset(&addr, '\0', sizeof addr); 1783 SmtpPhase = mci->mci_phase = "initial connection"; 1784 CurHostName = host; 1785 1786 if (host[0] == '[') 1787 { 1788 p = strchr(host, ']'); 1789 if (p != NULL) 1790 { 1791 # if NETINET 1792 unsigned long hid = INADDR_NONE; 1793 # endif /* NETINET */ 1794 # if NETINET6 1795 struct sockaddr_in6 hid6; 1796 # endif /* NETINET6 */ 1797 1798 *p = '\0'; 1799 # if NETINET6 1800 memset(&hid6, '\0', sizeof hid6); 1801 # endif /* NETINET6 */ 1802 # if NETINET 1803 if (family == AF_INET && 1804 (hid = inet_addr(&host[1])) != INADDR_NONE) 1805 { 1806 addr.sin.sin_family = AF_INET; 1807 addr.sin.sin_addr.s_addr = hid; 1808 } 1809 else 1810 # endif /* NETINET */ 1811 # if NETINET6 1812 if (family == AF_INET6 && 1813 inet_pton(AF_INET6, &host[1], 1814 &hid6.sin6_addr) == 1) 1815 { 1816 addr.sin6.sin6_family = AF_INET6; 1817 addr.sin6.sin6_addr = hid6.sin6_addr; 1818 } 1819 else 1820 # endif /* NETINET6 */ 1821 { 1822 /* try it as a host name (avoid MX lookup) */ 1823 hp = sm_gethostbyname(&host[1], family); 1824 if (hp == NULL && p[-1] == '.') 1825 { 1826 # if NAMED_BIND 1827 int oldopts = _res.options; 1828 1829 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 1830 # endif /* NAMED_BIND */ 1831 p[-1] = '\0'; 1832 hp = sm_gethostbyname(&host[1], 1833 family); 1834 p[-1] = '.'; 1835 # if NAMED_BIND 1836 _res.options = oldopts; 1837 # endif /* NAMED_BIND */ 1838 } 1839 *p = ']'; 1840 goto gothostent; 1841 } 1842 *p = ']'; 1843 } 1844 if (p == NULL) 1845 { 1846 extern char MsgBuf[]; 1847 1848 usrerrenh("5.1.2", 1849 "553 Invalid numeric domain spec \"%s\"", 1850 host); 1851 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 1852 errno = EINVAL; 1853 return EX_NOHOST; 1854 } 1855 } 1856 else 1857 { 1858 /* contortion to get around SGI cc complaints */ 1859 { 1860 p = &host[strlen(host) - 1]; 1861 hp = sm_gethostbyname(host, family); 1862 if (hp == NULL && *p == '.') 1863 { 1864 # if NAMED_BIND 1865 int oldopts = _res.options; 1866 1867 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 1868 # endif /* NAMED_BIND */ 1869 *p = '\0'; 1870 hp = sm_gethostbyname(host, family); 1871 *p = '.'; 1872 # if NAMED_BIND 1873 _res.options = oldopts; 1874 # endif /* NAMED_BIND */ 1875 } 1876 } 1877 gothostent: 1878 if (hp == NULL) 1879 { 1880 # if NAMED_BIND 1881 /* check for name server timeouts */ 1882 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 1883 (errno == ECONNREFUSED && UseNameServer)) 1884 { 1885 save_errno = errno; 1886 mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL); 1887 errno = save_errno; 1888 return EX_TEMPFAIL; 1889 } 1890 # endif /* NAMED_BIND */ 1891 # if NETINET6 1892 /* 1893 ** Try v6 first, then fall back to v4. 1894 ** If we found a v6 address, but no v4 1895 ** addresses, then TEMPFAIL. 1896 */ 1897 1898 if (family == AF_INET6) 1899 { 1900 family = AF_INET; 1901 goto v4retry; 1902 } 1903 if (v6found) 1904 goto v6tempfail; 1905 # endif /* NETINET6 */ 1906 save_errno = errno; 1907 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1908 errno = save_errno; 1909 return EX_NOHOST; 1910 } 1911 addr.sa.sa_family = hp->h_addrtype; 1912 switch (hp->h_addrtype) 1913 { 1914 # if NETINET 1915 case AF_INET: 1916 memmove(&addr.sin.sin_addr, 1917 hp->h_addr, 1918 INADDRSZ); 1919 break; 1920 # endif /* NETINET */ 1921 1922 # if NETINET6 1923 case AF_INET6: 1924 memmove(&addr.sin6.sin6_addr, 1925 hp->h_addr, 1926 IN6ADDRSZ); 1927 break; 1928 # endif /* NETINET6 */ 1929 1930 default: 1931 if (hp->h_length > sizeof addr.sa.sa_data) 1932 { 1933 syserr("makeconnection: long sa_data: family %d len %d", 1934 hp->h_addrtype, hp->h_length); 1935 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1936 errno = EINVAL; 1937 return EX_NOHOST; 1938 } 1939 memmove(addr.sa.sa_data, 1940 hp->h_addr, 1941 hp->h_length); 1942 break; 1943 } 1944 addrno = 1; 1945 } 1946 1947 /* 1948 ** Determine the port number. 1949 */ 1950 1951 if (port == 0) 1952 { 1953 # ifdef NO_GETSERVBYNAME 1954 port = htons(25); 1955 # else /* NO_GETSERVBYNAME */ 1956 register struct servent *sp = getservbyname("smtp", "tcp"); 1957 1958 if (sp == NULL) 1959 { 1960 if (LogLevel > 2) 1961 sm_syslog(LOG_ERR, NOQID, 1962 "makeconnection: service \"smtp\" unknown"); 1963 port = htons(25); 1964 } 1965 else 1966 port = sp->s_port; 1967 # endif /* NO_GETSERVBYNAME */ 1968 } 1969 1970 switch (addr.sa.sa_family) 1971 { 1972 # if NETINET 1973 case AF_INET: 1974 addr.sin.sin_port = port; 1975 addrlen = sizeof (struct sockaddr_in); 1976 break; 1977 # endif /* NETINET */ 1978 1979 # if NETINET6 1980 case AF_INET6: 1981 addr.sin6.sin6_port = port; 1982 addrlen = sizeof (struct sockaddr_in6); 1983 break; 1984 # endif /* NETINET6 */ 1985 1986 # if NETISO 1987 case AF_ISO: 1988 /* assume two byte transport selector */ 1989 memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 1990 addrlen = sizeof (struct sockaddr_iso); 1991 break; 1992 # endif /* NETISO */ 1993 1994 default: 1995 syserr("Can't connect to address family %d", addr.sa.sa_family); 1996 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1997 errno = EINVAL; 1998 # if _FFR_FREEHOSTENT && NETINET6 1999 if (hp != NULL) 2000 freehostent(hp); 2001 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2002 return EX_NOHOST; 2003 } 2004 2005 /* 2006 ** Try to actually open the connection. 2007 */ 2008 2009 # ifdef XLA 2010 /* if too many connections, don't bother trying */ 2011 if (!xla_noqueue_ok(host)) 2012 { 2013 # if _FFR_FREEHOSTENT && NETINET6 2014 if (hp != NULL) 2015 freehostent(hp); 2016 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2017 return EX_TEMPFAIL; 2018 } 2019 # endif /* XLA */ 2020 2021 firstconnect = TRUE; 2022 for (;;) 2023 { 2024 if (tTd(16, 1)) 2025 dprintf("makeconnection (%s [%s].%d (%d))\n", 2026 host, anynet_ntoa(&addr), ntohs(port), 2027 addr.sa.sa_family); 2028 2029 /* save for logging */ 2030 CurHostAddr = addr; 2031 2032 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 2033 { 2034 int rport = IPPORT_RESERVED - 1; 2035 2036 s = rresvport(&rport); 2037 } 2038 else 2039 { 2040 s = socket(clt_addr.sa.sa_family, SOCK_STREAM, 0); 2041 } 2042 if (s < 0) 2043 { 2044 save_errno = errno; 2045 syserr("makeconnection: cannot create socket"); 2046 # ifdef XLA 2047 xla_host_end(host); 2048 # endif /* XLA */ 2049 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2050 # if _FFR_FREEHOSTENT && NETINET6 2051 if (hp != NULL) 2052 freehostent(hp); 2053 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2054 errno = save_errno; 2055 return EX_TEMPFAIL; 2056 } 2057 2058 # ifdef SO_SNDBUF 2059 if (TcpSndBufferSize > 0) 2060 { 2061 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 2062 (char *) &TcpSndBufferSize, 2063 sizeof(TcpSndBufferSize)) < 0) 2064 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 2065 } 2066 # endif /* SO_SNDBUF */ 2067 # ifdef SO_RCVBUF 2068 if (TcpRcvBufferSize > 0) 2069 { 2070 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2071 (char *) &TcpRcvBufferSize, 2072 sizeof(TcpRcvBufferSize)) < 0) 2073 syserr("makeconnection: setsockopt(SO_RCVBUF)"); 2074 } 2075 # endif /* SO_RCVBUF */ 2076 2077 2078 if (tTd(16, 1)) 2079 dprintf("makeconnection: fd=%d\n", s); 2080 2081 /* turn on network debugging? */ 2082 if (tTd(16, 101)) 2083 { 2084 int on = 1; 2085 2086 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2087 (char *)&on, sizeof on); 2088 } 2089 if (e->e_xfp != NULL) 2090 (void) fflush(e->e_xfp); /* for debugging */ 2091 errno = 0; /* for debugging */ 2092 2093 if (clt_bind) 2094 { 2095 int on = 1; 2096 2097 switch (clt_addr.sa.sa_family) 2098 { 2099 # if NETINET 2100 case AF_INET: 2101 if (clt_addr.sin.sin_port != 0) 2102 (void) setsockopt(s, SOL_SOCKET, 2103 SO_REUSEADDR, 2104 (char *) &on, 2105 sizeof on); 2106 break; 2107 # endif /* NETINET */ 2108 2109 # if NETINET6 2110 case AF_INET6: 2111 if (clt_addr.sin6.sin6_port != 0) 2112 (void) setsockopt(s, SOL_SOCKET, 2113 SO_REUSEADDR, 2114 (char *) &on, 2115 sizeof on); 2116 break; 2117 # endif /* NETINET6 */ 2118 } 2119 2120 if (bind(s, &clt_addr.sa, socksize) < 0) 2121 { 2122 save_errno = errno; 2123 (void) close(s); 2124 errno = save_errno; 2125 syserr("makeconnection: cannot bind socket [%s]", 2126 anynet_ntoa(&clt_addr)); 2127 # if _FFR_FREEHOSTENT && NETINET6 2128 if (hp != NULL) 2129 freehostent(hp); 2130 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2131 errno = save_errno; 2132 return EX_TEMPFAIL; 2133 } 2134 } 2135 2136 /* 2137 ** Linux seems to hang in connect for 90 minutes (!!!). 2138 ** Time out the connect to avoid this problem. 2139 */ 2140 2141 if (setjmp(CtxConnectTimeout) == 0) 2142 { 2143 int i; 2144 2145 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 2146 ev = setevent(TimeOuts.to_iconnect, 2147 connecttimeout, 0); 2148 else if (TimeOuts.to_connect != 0) 2149 ev = setevent(TimeOuts.to_connect, 2150 connecttimeout, 0); 2151 else 2152 ev = NULL; 2153 2154 switch (ConnectOnlyTo.sa.sa_family) 2155 { 2156 # if NETINET 2157 case AF_INET: 2158 addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 2159 break; 2160 # endif /* NETINET */ 2161 2162 # if NETINET6 2163 case AF_INET6: 2164 memmove(&addr.sin6.sin6_addr, 2165 &ConnectOnlyTo.sin6.sin6_addr, 2166 IN6ADDRSZ); 2167 break; 2168 # endif /* NETINET6 */ 2169 } 2170 i = connect(s, (struct sockaddr *) &addr, addrlen); 2171 save_errno = errno; 2172 if (ev != NULL) 2173 clrevent(ev); 2174 if (i >= 0) 2175 break; 2176 } 2177 else 2178 save_errno = errno; 2179 2180 /* if running demand-dialed connection, try again */ 2181 if (DialDelay > 0 && firstconnect) 2182 { 2183 if (tTd(16, 1)) 2184 dprintf("Connect failed (%s); trying again...\n", 2185 errstring(save_errno)); 2186 firstconnect = FALSE; 2187 (void) sleep(DialDelay); 2188 continue; 2189 } 2190 2191 /* couldn't connect.... figure out why */ 2192 (void) close(s); 2193 2194 if (LogLevel >= 14) 2195 sm_syslog(LOG_INFO, e->e_id, 2196 "makeconnection (%s [%s]) failed: %s", 2197 host, anynet_ntoa(&addr), 2198 errstring(save_errno)); 2199 2200 if (hp != NULL && hp->h_addr_list[addrno] != NULL) 2201 { 2202 if (tTd(16, 1)) 2203 dprintf("Connect failed (%s); trying new address....\n", 2204 errstring(save_errno)); 2205 switch (addr.sa.sa_family) 2206 { 2207 # if NETINET 2208 case AF_INET: 2209 memmove(&addr.sin.sin_addr, 2210 hp->h_addr_list[addrno++], 2211 INADDRSZ); 2212 break; 2213 # endif /* NETINET */ 2214 2215 # if NETINET6 2216 case AF_INET6: 2217 memmove(&addr.sin6.sin6_addr, 2218 hp->h_addr_list[addrno++], 2219 IN6ADDRSZ); 2220 break; 2221 # endif /* NETINET6 */ 2222 2223 default: 2224 memmove(addr.sa.sa_data, 2225 hp->h_addr_list[addrno++], 2226 hp->h_length); 2227 break; 2228 } 2229 continue; 2230 } 2231 errno = save_errno; 2232 2233 # if NETINET6 2234 if (family == AF_INET6) 2235 { 2236 if (tTd(16, 1)) 2237 dprintf("Connect failed (%s); retrying with AF_INET....\n", 2238 errstring(save_errno)); 2239 v6found = TRUE; 2240 family = AF_INET; 2241 # if _FFR_FREEHOSTENT 2242 if (hp != NULL) 2243 { 2244 freehostent(hp); 2245 hp = NULL; 2246 } 2247 # endif /* _FFR_FREEHOSTENT */ 2248 goto v4retry; 2249 } 2250 v6tempfail: 2251 # endif /* NETINET6 */ 2252 /* couldn't open connection */ 2253 # if NETINET6 2254 /* Don't clobber an already saved errno from v4retry */ 2255 if (errno > 0) 2256 # endif /* NETINET6 */ 2257 save_errno = errno; 2258 if (tTd(16, 1)) 2259 dprintf("Connect failed (%s)\n", errstring(save_errno)); 2260 # ifdef XLA 2261 xla_host_end(host); 2262 # endif /* XLA */ 2263 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2264 # if _FFR_FREEHOSTENT && NETINET6 2265 if (hp != NULL) 2266 freehostent(hp); 2267 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2268 errno = save_errno; 2269 return EX_TEMPFAIL; 2270 } 2271 2272 # if _FFR_FREEHOSTENT && NETINET6 2273 if (hp != NULL) 2274 { 2275 freehostent(hp); 2276 hp = NULL; 2277 } 2278 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2279 2280 /* connection ok, put it into canonical form */ 2281 mci->mci_out = NULL; 2282 if ((mci->mci_out = fdopen(s, "w")) == NULL || 2283 (s = dup(s)) < 0 || 2284 (mci->mci_in = fdopen(s, "r")) == NULL) 2285 { 2286 save_errno = errno; 2287 syserr("cannot open SMTP client channel, fd=%d", s); 2288 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2289 if (mci->mci_out != NULL) 2290 (void) fclose(mci->mci_out); 2291 (void) close(s); 2292 errno = save_errno; 2293 return EX_TEMPFAIL; 2294 } 2295 2296 /* find out name for Interface through which we connect */ 2297 len = sizeof addr; 2298 if (getsockname(s, &addr.sa, &len) == 0) 2299 { 2300 char *name; 2301 char *p; 2302 2303 define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)), 2304 &BlankEnvelope); 2305 p = xalloc(5); 2306 snprintf(p, 4, "%d", addr.sa.sa_family); 2307 define(macid("{if_family}", NULL), p, &BlankEnvelope); 2308 2309 name = hostnamebyanyaddr(&addr); 2310 define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope); 2311 if (LogLevel > 11) 2312 { 2313 /* log connection information */ 2314 sm_syslog(LOG_INFO, e->e_id, 2315 "SMTP outgoing connect on %.40s", name); 2316 } 2317 if (bitnset(D_IFNHELO, d_flags)) 2318 { 2319 if (name[0] != '[' && strchr(name, '.') != NULL) 2320 mci->mci_heloname = newstr(name); 2321 } 2322 } 2323 else 2324 { 2325 define(macid("{if_name}", NULL), NULL, &BlankEnvelope); 2326 define(macid("{if_addr}", NULL), NULL, &BlankEnvelope); 2327 define(macid("{if_family}", NULL), NULL, &BlankEnvelope); 2328 } 2329 mci_setstat(mci, EX_OK, NULL, NULL); 2330 return EX_OK; 2331 } 2332 2333 static void 2334 connecttimeout() 2335 { 2336 /* 2337 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2338 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2339 ** DOING. 2340 */ 2341 2342 errno = ETIMEDOUT; 2343 longjmp(CtxConnectTimeout, 1); 2344 } 2345 /* 2346 ** MAKECONNECTION_DS -- make a connection to a domain socket. 2347 ** 2348 ** Parameters: 2349 ** mux_path -- the path of the socket to connect to. 2350 ** mci -- a pointer to the mail connection information 2351 ** structure to be filled in. 2352 ** 2353 ** Returns: 2354 ** An exit code telling whether the connection could be 2355 ** made and if not why not. 2356 ** 2357 ** Side Effects: 2358 ** none. 2359 */ 2360 2361 # if NETUNIX 2362 int makeconnection_ds(mux_path, mci) 2363 char *mux_path; 2364 register MCI *mci; 2365 { 2366 int sock; 2367 int rval, save_errno; 2368 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 2369 struct sockaddr_un unix_addr; 2370 2371 /* if not safe, don't connect */ 2372 rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 2373 sff, S_IRUSR|S_IWUSR, NULL); 2374 2375 if (rval != 0) 2376 { 2377 syserr("makeconnection_ds: unsafe domain socket"); 2378 mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 2379 errno = rval; 2380 return EX_TEMPFAIL; 2381 } 2382 2383 /* prepare address structure */ 2384 memset(&unix_addr, '\0', sizeof unix_addr); 2385 unix_addr.sun_family = AF_UNIX; 2386 2387 if (strlen(mux_path) >= sizeof unix_addr.sun_path) 2388 { 2389 syserr("makeconnection_ds: domain socket name too long"); 2390 /* XXX why TEMPFAIL ? */ 2391 mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 2392 errno = ENAMETOOLONG; 2393 return EX_UNAVAILABLE; 2394 } 2395 (void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path); 2396 2397 /* initialize domain socket */ 2398 sock = socket(AF_UNIX, SOCK_STREAM, 0); 2399 if (sock == -1) 2400 { 2401 save_errno = errno; 2402 syserr("makeconnection_ds: could not create domain socket"); 2403 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2404 errno = save_errno; 2405 return EX_TEMPFAIL; 2406 } 2407 2408 /* connect to server */ 2409 if (connect(sock, (struct sockaddr *) &unix_addr, 2410 sizeof(unix_addr)) == -1) 2411 { 2412 save_errno = errno; 2413 syserr("Could not connect to socket %s", mux_path); 2414 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2415 (void) close(sock); 2416 errno = save_errno; 2417 return EX_TEMPFAIL; 2418 } 2419 2420 /* connection ok, put it into canonical form */ 2421 mci->mci_out = NULL; 2422 if ((mci->mci_out = fdopen(sock, "w")) == NULL || 2423 (sock = dup(sock)) < 0 || 2424 (mci->mci_in = fdopen(sock, "r")) == NULL) 2425 { 2426 save_errno = errno; 2427 syserr("cannot open SMTP client channel, fd=%d", sock); 2428 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2429 if (mci->mci_out != NULL) 2430 (void) fclose(mci->mci_out); 2431 (void) close(sock); 2432 errno = save_errno; 2433 return EX_TEMPFAIL; 2434 } 2435 2436 mci_setstat(mci, EX_OK, NULL, NULL); 2437 errno = 0; 2438 return EX_OK; 2439 } 2440 # endif /* NETUNIX */ 2441 /* 2442 ** SIGHUP -- handle a SIGHUP signal 2443 ** 2444 ** Parameters: 2445 ** sig -- incoming signal. 2446 ** 2447 ** Returns: 2448 ** none. 2449 ** 2450 ** Side Effects: 2451 ** Sets RestartRequest which should cause the daemon 2452 ** to restart. 2453 ** 2454 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2455 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2456 ** DOING. 2457 */ 2458 2459 /* ARGSUSED */ 2460 static SIGFUNC_DECL 2461 sighup(sig) 2462 int sig; 2463 { 2464 int save_errno = errno; 2465 2466 FIX_SYSV_SIGNAL(sig, sighup); 2467 RestartRequest = "signal"; 2468 errno = save_errno; 2469 return SIGFUNC_RETURN; 2470 } 2471 /* 2472 ** RESTART_DAEMON -- Performs a clean restart of the daemon 2473 ** 2474 ** Parameters: 2475 ** none. 2476 ** 2477 ** Returns: 2478 ** none. 2479 ** 2480 ** Side Effects: 2481 ** restarts the daemon or exits if restart fails. 2482 */ 2483 2484 static void 2485 restart_daemon() 2486 { 2487 int i; 2488 int save_errno; 2489 char *reason; 2490 sigfunc_t oalrm, ochld, ohup, oint, opipe, oterm, ousr1; 2491 extern int DtableSize; 2492 2493 allsignals(TRUE); 2494 2495 reason = RestartRequest; 2496 RestartRequest = NULL; 2497 PendingSignal = 0; 2498 2499 if (SaveArgv[0][0] != '/') 2500 { 2501 if (LogLevel > 3) 2502 sm_syslog(LOG_INFO, NOQID, 2503 "could not restart: need full path"); 2504 finis(FALSE, EX_OSFILE); 2505 } 2506 if (LogLevel > 3) 2507 sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 2508 SaveArgv[0], 2509 reason == NULL ? "implicit call" : reason); 2510 2511 closecontrolsocket(TRUE); 2512 if (drop_privileges(TRUE) != EX_OK) 2513 { 2514 if (LogLevel > 0) 2515 sm_syslog(LOG_ALERT, NOQID, 2516 "could not set[ug]id(%d, %d): %m", 2517 RunAsUid, RunAsGid); 2518 finis(FALSE, EX_OSERR); 2519 } 2520 2521 /* arrange for all the files to be closed */ 2522 for (i = 3; i < DtableSize; i++) 2523 { 2524 register int j; 2525 2526 if ((j = fcntl(i, F_GETFD, 0)) != -1) 2527 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 2528 } 2529 2530 /* need to allow signals before execve() so make them harmless */ 2531 oalrm = setsignal(SIGALRM, SIG_DFL); 2532 ochld = setsignal(SIGCHLD, SIG_DFL); 2533 ohup = setsignal(SIGHUP, SIG_DFL); 2534 oint = setsignal(SIGINT, SIG_DFL); 2535 opipe = setsignal(SIGPIPE, SIG_DFL); 2536 oterm = setsignal(SIGTERM, SIG_DFL); 2537 ousr1 = setsignal(SIGUSR1, SIG_DFL); 2538 allsignals(FALSE); 2539 2540 (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 2541 save_errno = errno; 2542 2543 /* restore signals */ 2544 allsignals(TRUE); 2545 (void) setsignal(SIGALRM, oalrm); 2546 (void) setsignal(SIGCHLD, ochld); 2547 (void) setsignal(SIGHUP, ohup); 2548 (void) setsignal(SIGINT, oint); 2549 (void) setsignal(SIGPIPE, opipe); 2550 (void) setsignal(SIGTERM, oterm); 2551 (void) setsignal(SIGUSR1, ousr1); 2552 2553 errno = save_errno; 2554 if (LogLevel > 0) 2555 sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", 2556 SaveArgv[0]); 2557 finis(FALSE, EX_OSFILE); 2558 } 2559 /* 2560 ** MYHOSTNAME -- return the name of this host. 2561 ** 2562 ** Parameters: 2563 ** hostbuf -- a place to return the name of this host. 2564 ** size -- the size of hostbuf. 2565 ** 2566 ** Returns: 2567 ** A list of aliases for this host. 2568 ** 2569 ** Side Effects: 2570 ** Adds numeric codes to $=w. 2571 */ 2572 2573 struct hostent * 2574 myhostname(hostbuf, size) 2575 char hostbuf[]; 2576 int size; 2577 { 2578 register struct hostent *hp; 2579 2580 if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 2581 (void) strlcpy(hostbuf, "localhost", size); 2582 hp = sm_gethostbyname(hostbuf, InetMode); 2583 if (hp == NULL) 2584 return NULL; 2585 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 2586 (void) cleanstrcpy(hostbuf, hp->h_name, size); 2587 2588 # if NETINFO 2589 if (strchr(hostbuf, '.') == NULL) 2590 { 2591 char *domainname; 2592 2593 domainname = ni_propval("/locations", NULL, "resolver", 2594 "domain", '\0'); 2595 if (domainname != NULL && 2596 strlen(domainname) + strlen(hostbuf) + 1 < size) 2597 { 2598 (void) strlcat(hostbuf, ".", size); 2599 (void) strlcat(hostbuf, domainname, size); 2600 } 2601 } 2602 # endif /* NETINFO */ 2603 2604 /* 2605 ** If there is still no dot in the name, try looking for a 2606 ** dotted alias. 2607 */ 2608 2609 if (strchr(hostbuf, '.') == NULL) 2610 { 2611 char **ha; 2612 2613 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 2614 { 2615 if (strchr(*ha, '.') != NULL) 2616 { 2617 (void) cleanstrcpy(hostbuf, *ha, size - 1); 2618 hostbuf[size - 1] = '\0'; 2619 break; 2620 } 2621 } 2622 } 2623 2624 /* 2625 ** If _still_ no dot, wait for a while and try again -- it is 2626 ** possible that some service is starting up. This can result 2627 ** in excessive delays if the system is badly configured, but 2628 ** there really isn't a way around that, particularly given that 2629 ** the config file hasn't been read at this point. 2630 ** All in all, a bit of a mess. 2631 */ 2632 2633 if (strchr(hostbuf, '.') == NULL && 2634 !getcanonname(hostbuf, size, TRUE)) 2635 { 2636 sm_syslog(LOG_CRIT, NOQID, 2637 "My unqualified host name (%s) unknown; sleeping for retry", 2638 hostbuf); 2639 message("My unqualified host name (%s) unknown; sleeping for retry", 2640 hostbuf); 2641 (void) sleep(60); 2642 if (!getcanonname(hostbuf, size, TRUE)) 2643 { 2644 sm_syslog(LOG_ALERT, NOQID, 2645 "unable to qualify my own domain name (%s) -- using short name", 2646 hostbuf); 2647 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 2648 hostbuf); 2649 } 2650 } 2651 return hp; 2652 } 2653 /* 2654 ** ADDRCMP -- compare two host addresses 2655 ** 2656 ** Parameters: 2657 ** hp -- hostent structure for the first address 2658 ** ha -- actual first address 2659 ** sa -- second address 2660 ** 2661 ** Returns: 2662 ** 0 -- if ha and sa match 2663 ** else -- they don't match 2664 */ 2665 2666 static int 2667 addrcmp(hp, ha, sa) 2668 struct hostent *hp; 2669 char *ha; 2670 SOCKADDR *sa; 2671 { 2672 # if NETINET6 2673 u_char *a; 2674 # endif /* NETINET6 */ 2675 2676 switch (sa->sa.sa_family) 2677 { 2678 # if NETINET 2679 case AF_INET: 2680 if (hp->h_addrtype == AF_INET) 2681 return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 2682 break; 2683 # endif /* NETINET */ 2684 2685 # if NETINET6 2686 case AF_INET6: 2687 a = (u_char *) &sa->sin6.sin6_addr; 2688 2689 /* Straight binary comparison */ 2690 if (hp->h_addrtype == AF_INET6) 2691 return memcmp(ha, a, IN6ADDRSZ); 2692 2693 /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 2694 if (hp->h_addrtype == AF_INET && 2695 IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 2696 return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 2697 break; 2698 # endif /* NETINET6 */ 2699 } 2700 return -1; 2701 } 2702 /* 2703 ** GETAUTHINFO -- get the real host name associated with a file descriptor 2704 ** 2705 ** Uses RFC1413 protocol to try to get info from the other end. 2706 ** 2707 ** Parameters: 2708 ** fd -- the descriptor 2709 ** may_be_forged -- an outage that is set to TRUE if the 2710 ** forward lookup of RealHostName does not match 2711 ** RealHostAddr; set to FALSE if they do match. 2712 ** 2713 ** Returns: 2714 ** The user@host information associated with this descriptor. 2715 */ 2716 2717 static jmp_buf CtxAuthTimeout; 2718 2719 static void 2720 authtimeout() 2721 { 2722 /* 2723 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2724 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2725 ** DOING. 2726 */ 2727 2728 errno = ETIMEDOUT; 2729 longjmp(CtxAuthTimeout, 1); 2730 } 2731 2732 char * 2733 getauthinfo(fd, may_be_forged) 2734 int fd; 2735 bool *may_be_forged; 2736 { 2737 volatile u_short port = 0; 2738 SOCKADDR_LEN_T falen; 2739 register char *volatile p = NULL; 2740 SOCKADDR la; 2741 SOCKADDR_LEN_T lalen; 2742 register struct servent *sp; 2743 volatile int s; 2744 int i = 0; 2745 EVENT *ev; 2746 int nleft; 2747 struct hostent *hp; 2748 char *ostype = NULL; 2749 char **ha; 2750 char ibuf[MAXNAME + 1]; 2751 static char hbuf[MAXNAME * 2 + 11]; 2752 2753 *may_be_forged = FALSE; 2754 falen = sizeof RealHostAddr; 2755 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 2756 falen <= 0 || RealHostAddr.sa.sa_family == 0) 2757 { 2758 if (i < 0) 2759 { 2760 /* 2761 ** ENOTSOCK is OK: bail on anything else, but reset 2762 ** errno in this case, so a mis-report doesn't 2763 ** happen later. 2764 */ 2765 if (errno != ENOTSOCK) 2766 return NULL; 2767 errno = 0; 2768 } 2769 (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", 2770 RealUserName); 2771 if (tTd(9, 1)) 2772 dprintf("getauthinfo: %s\n", hbuf); 2773 return hbuf; 2774 } 2775 2776 if (RealHostName == NULL) 2777 { 2778 /* translate that to a host name */ 2779 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 2780 if (strlen(RealHostName) > MAXNAME) 2781 RealHostName[MAXNAME] = '\0'; 2782 } 2783 2784 /* cross check RealHostName with forward DNS lookup */ 2785 if (anynet_ntoa(&RealHostAddr)[0] == '[' || 2786 RealHostName[0] == '[') 2787 { 2788 /* 2789 ** address is not a socket or have an 2790 ** IP address with no forward lookup 2791 */ 2792 *may_be_forged = FALSE; 2793 } 2794 else 2795 { 2796 /* try to match the reverse against the forward lookup */ 2797 hp = sm_gethostbyname(RealHostName, 2798 RealHostAddr.sa.sa_family); 2799 2800 if (hp == NULL) 2801 *may_be_forged = TRUE; 2802 else 2803 { 2804 for (ha = hp->h_addr_list; *ha != NULL; ha++) 2805 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 2806 break; 2807 *may_be_forged = *ha == NULL; 2808 # if _FFR_FREEHOSTENT && NETINET6 2809 freehostent(hp); 2810 hp = NULL; 2811 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2812 } 2813 } 2814 2815 if (TimeOuts.to_ident == 0) 2816 goto noident; 2817 2818 lalen = sizeof la; 2819 switch (RealHostAddr.sa.sa_family) 2820 { 2821 # if NETINET 2822 case AF_INET: 2823 if (getsockname(fd, &la.sa, &lalen) < 0 || 2824 lalen <= 0 || 2825 la.sa.sa_family != AF_INET) 2826 { 2827 /* no ident info */ 2828 goto noident; 2829 } 2830 port = RealHostAddr.sin.sin_port; 2831 2832 /* create ident query */ 2833 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2834 ntohs(RealHostAddr.sin.sin_port), 2835 ntohs(la.sin.sin_port)); 2836 2837 /* create local address */ 2838 la.sin.sin_port = 0; 2839 2840 /* create foreign address */ 2841 # ifdef NO_GETSERVBYNAME 2842 RealHostAddr.sin.sin_port = htons(113); 2843 # else /* NO_GETSERVBYNAME */ 2844 sp = getservbyname("auth", "tcp"); 2845 if (sp != NULL) 2846 RealHostAddr.sin.sin_port = sp->s_port; 2847 else 2848 RealHostAddr.sin.sin_port = htons(113); 2849 break; 2850 # endif /* NO_GETSERVBYNAME */ 2851 # endif /* NETINET */ 2852 2853 # if NETINET6 2854 case AF_INET6: 2855 if (getsockname(fd, &la.sa, &lalen) < 0 || 2856 lalen <= 0 || 2857 la.sa.sa_family != AF_INET6) 2858 { 2859 /* no ident info */ 2860 goto noident; 2861 } 2862 port = RealHostAddr.sin6.sin6_port; 2863 2864 /* create ident query */ 2865 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2866 ntohs(RealHostAddr.sin6.sin6_port), 2867 ntohs(la.sin6.sin6_port)); 2868 2869 /* create local address */ 2870 la.sin6.sin6_port = 0; 2871 2872 /* create foreign address */ 2873 # ifdef NO_GETSERVBYNAME 2874 RealHostAddr.sin6.sin6_port = htons(113); 2875 # else /* NO_GETSERVBYNAME */ 2876 sp = getservbyname("auth", "tcp"); 2877 if (sp != NULL) 2878 RealHostAddr.sin6.sin6_port = sp->s_port; 2879 else 2880 RealHostAddr.sin6.sin6_port = htons(113); 2881 break; 2882 # endif /* NO_GETSERVBYNAME */ 2883 # endif /* NETINET6 */ 2884 default: 2885 /* no ident info */ 2886 goto noident; 2887 } 2888 2889 s = -1; 2890 if (setjmp(CtxAuthTimeout) != 0) 2891 { 2892 if (s >= 0) 2893 (void) close(s); 2894 goto noident; 2895 } 2896 2897 /* put a timeout around the whole thing */ 2898 ev = setevent(TimeOuts.to_ident, authtimeout, 0); 2899 2900 2901 /* connect to foreign IDENT server using same address as SMTP socket */ 2902 s = socket(la.sa.sa_family, SOCK_STREAM, 0); 2903 if (s < 0) 2904 { 2905 clrevent(ev); 2906 goto noident; 2907 } 2908 if (bind(s, &la.sa, lalen) < 0 || 2909 connect(s, &RealHostAddr.sa, lalen) < 0) 2910 { 2911 goto closeident; 2912 } 2913 2914 if (tTd(9, 10)) 2915 dprintf("getauthinfo: sent %s", ibuf); 2916 2917 /* send query */ 2918 if (write(s, ibuf, strlen(ibuf)) < 0) 2919 goto closeident; 2920 2921 /* get result */ 2922 p = &ibuf[0]; 2923 nleft = sizeof ibuf - 1; 2924 while ((i = read(s, p, nleft)) > 0) 2925 { 2926 p += i; 2927 nleft -= i; 2928 *p = '\0'; 2929 if (strchr(ibuf, '\n') != NULL) 2930 break; 2931 } 2932 (void) close(s); 2933 clrevent(ev); 2934 if (i < 0 || p == &ibuf[0]) 2935 goto noident; 2936 2937 if (*--p == '\n' && *--p == '\r') 2938 p--; 2939 *++p = '\0'; 2940 2941 if (tTd(9, 3)) 2942 dprintf("getauthinfo: got %s\n", ibuf); 2943 2944 /* parse result */ 2945 p = strchr(ibuf, ':'); 2946 if (p == NULL) 2947 { 2948 /* malformed response */ 2949 goto noident; 2950 } 2951 while (isascii(*++p) && isspace(*p)) 2952 continue; 2953 if (strncasecmp(p, "userid", 6) != 0) 2954 { 2955 /* presumably an error string */ 2956 goto noident; 2957 } 2958 p += 6; 2959 while (isascii(*p) && isspace(*p)) 2960 p++; 2961 if (*p++ != ':') 2962 { 2963 /* either useridxx or malformed response */ 2964 goto noident; 2965 } 2966 2967 /* p now points to the OSTYPE field */ 2968 while (isascii(*p) && isspace(*p)) 2969 p++; 2970 ostype = p; 2971 p = strchr(p, ':'); 2972 if (p == NULL) 2973 { 2974 /* malformed response */ 2975 goto noident; 2976 } 2977 else 2978 { 2979 char *charset; 2980 2981 *p = '\0'; 2982 charset = strchr(ostype, ','); 2983 if (charset != NULL) 2984 *charset = '\0'; 2985 } 2986 2987 /* 1413 says don't do this -- but it's broken otherwise */ 2988 while (isascii(*++p) && isspace(*p)) 2989 continue; 2990 2991 /* p now points to the authenticated name -- copy carefully */ 2992 if (strncasecmp(ostype, "other", 5) == 0 && 2993 (ostype[5] == ' ' || ostype[5] == '\0')) 2994 { 2995 snprintf(hbuf, sizeof hbuf, "IDENT:"); 2996 cleanstrcpy(&hbuf[6], p, MAXNAME); 2997 } 2998 else 2999 cleanstrcpy(hbuf, p, MAXNAME); 3000 i = strlen(hbuf); 3001 snprintf(&hbuf[i], sizeof hbuf - i, "@%s", 3002 RealHostName == NULL ? "localhost" : RealHostName); 3003 goto postident; 3004 3005 closeident: 3006 (void) close(s); 3007 clrevent(ev); 3008 3009 noident: 3010 /* put back the original incoming port */ 3011 switch (RealHostAddr.sa.sa_family) 3012 { 3013 # if NETINET 3014 case AF_INET: 3015 if (port > 0) 3016 RealHostAddr.sin.sin_port = port; 3017 break; 3018 # endif /* NETINET */ 3019 3020 # if NETINET6 3021 case AF_INET6: 3022 if (port > 0) 3023 RealHostAddr.sin6.sin6_port = port; 3024 break; 3025 # endif /* NETINET6 */ 3026 } 3027 3028 if (RealHostName == NULL) 3029 { 3030 if (tTd(9, 1)) 3031 dprintf("getauthinfo: NULL\n"); 3032 return NULL; 3033 } 3034 snprintf(hbuf, sizeof hbuf, "%s", RealHostName); 3035 3036 postident: 3037 # if IP_SRCROUTE 3038 # ifndef GET_IPOPT_DST 3039 # define GET_IPOPT_DST(dst) (dst) 3040 # endif /* ! GET_IPOPT_DST */ 3041 /* 3042 ** Extract IP source routing information. 3043 ** 3044 ** Format of output for a connection from site a through b 3045 ** through c to d: 3046 ** loose: @site-c@site-b:site-a 3047 ** strict: !@site-c@site-b:site-a 3048 ** 3049 ** o - pointer within ipopt_list structure. 3050 ** q - pointer within ls/ss rr route data 3051 ** p - pointer to hbuf 3052 */ 3053 3054 if (RealHostAddr.sa.sa_family == AF_INET) 3055 { 3056 SOCKOPT_LEN_T ipoptlen; 3057 int j; 3058 u_char *q; 3059 u_char *o; 3060 int l; 3061 struct IPOPTION ipopt; 3062 3063 ipoptlen = sizeof ipopt; 3064 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 3065 (char *) &ipopt, &ipoptlen) < 0) 3066 goto noipsr; 3067 if (ipoptlen == 0) 3068 goto noipsr; 3069 o = (u_char *) ipopt.IP_LIST; 3070 while (o != NULL && o < (u_char *) &ipopt + ipoptlen) 3071 { 3072 switch (*o) 3073 { 3074 case IPOPT_EOL: 3075 o = NULL; 3076 break; 3077 3078 case IPOPT_NOP: 3079 o++; 3080 break; 3081 3082 case IPOPT_SSRR: 3083 case IPOPT_LSRR: 3084 /* 3085 ** Source routing. 3086 ** o[0] is the option type (loose/strict). 3087 ** o[1] is the length of this option, 3088 ** including option type and 3089 ** length. 3090 ** o[2] is the pointer into the route 3091 ** data. 3092 ** o[3] begins the route data. 3093 */ 3094 3095 p = &hbuf[strlen(hbuf)]; 3096 l = sizeof hbuf - (hbuf - p) - 6; 3097 snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", 3098 *o == IPOPT_SSRR ? "!" : "", 3099 l > 240 ? 120 : l / 2, 3100 inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 3101 i = strlen(p); 3102 p += i; 3103 l -= strlen(p); 3104 3105 j = o[1] / sizeof(struct in_addr) - 1; 3106 3107 /* q skips length and router pointer to data */ 3108 q = &o[3]; 3109 for ( ; j >= 0; j--) 3110 { 3111 struct in_addr addr; 3112 3113 memcpy(&addr, q, sizeof(addr)); 3114 snprintf(p, SPACELEFT(hbuf, p), 3115 "%c%.*s", 3116 j != 0 ? '@' : ':', 3117 l > 240 ? 120 : 3118 j == 0 ? l : l / 2, 3119 inet_ntoa(addr)); 3120 i = strlen(p); 3121 p += i; 3122 l -= i + 1; 3123 q += sizeof(struct in_addr); 3124 } 3125 o += o[1]; 3126 break; 3127 3128 default: 3129 /* Skip over option */ 3130 o += o[1]; 3131 break; 3132 } 3133 } 3134 snprintf(p, SPACELEFT(hbuf, p), "]"); 3135 goto postipsr; 3136 } 3137 3138 noipsr: 3139 # endif /* IP_SRCROUTE */ 3140 if (RealHostName != NULL && RealHostName[0] != '[') 3141 { 3142 p = &hbuf[strlen(hbuf)]; 3143 (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 3144 anynet_ntoa(&RealHostAddr)); 3145 } 3146 if (*may_be_forged) 3147 { 3148 p = &hbuf[strlen(hbuf)]; 3149 (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); 3150 } 3151 3152 # if IP_SRCROUTE 3153 postipsr: 3154 # endif /* IP_SRCROUTE */ 3155 if (tTd(9, 1)) 3156 dprintf("getauthinfo: %s\n", hbuf); 3157 3158 /* put back the original incoming port */ 3159 switch (RealHostAddr.sa.sa_family) 3160 { 3161 # if NETINET 3162 case AF_INET: 3163 if (port > 0) 3164 RealHostAddr.sin.sin_port = port; 3165 break; 3166 # endif /* NETINET */ 3167 3168 # if NETINET6 3169 case AF_INET6: 3170 if (port > 0) 3171 RealHostAddr.sin6.sin6_port = port; 3172 break; 3173 # endif /* NETINET6 */ 3174 } 3175 3176 return hbuf; 3177 } 3178 /* 3179 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3180 ** 3181 ** Parameters: 3182 ** map -- a pointer to this map. 3183 ** name -- the (presumably unqualified) hostname. 3184 ** av -- unused -- for compatibility with other mapping 3185 ** functions. 3186 ** statp -- an exit status (out parameter) -- set to 3187 ** EX_TEMPFAIL if the name server is unavailable. 3188 ** 3189 ** Returns: 3190 ** The mapping, if found. 3191 ** NULL if no mapping found. 3192 ** 3193 ** Side Effects: 3194 ** Looks up the host specified in hbuf. If it is not 3195 ** the canonical name for that host, return the canonical 3196 ** name (unless MF_MATCHONLY is set, which will cause the 3197 ** status only to be returned). 3198 */ 3199 3200 char * 3201 host_map_lookup(map, name, av, statp) 3202 MAP *map; 3203 char *name; 3204 char **av; 3205 int *statp; 3206 { 3207 register struct hostent *hp; 3208 # if NETINET 3209 struct in_addr in_addr; 3210 # endif /* NETINET */ 3211 # if NETINET6 3212 struct in6_addr in6_addr; 3213 # endif /* NETINET6 */ 3214 char *cp, *ans = NULL; 3215 register STAB *s; 3216 char hbuf[MAXNAME + 1]; 3217 3218 /* 3219 ** See if we have already looked up this name. If so, just 3220 ** return it. 3221 */ 3222 3223 s = stab(name, ST_NAMECANON, ST_ENTER); 3224 if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 3225 { 3226 if (tTd(9, 1)) 3227 dprintf("host_map_lookup(%s) => CACHE %s\n", 3228 name, 3229 s->s_namecanon.nc_cname == NULL 3230 ? "NULL" 3231 : s->s_namecanon.nc_cname); 3232 errno = s->s_namecanon.nc_errno; 3233 # if NAMED_BIND 3234 SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 3235 # endif /* NAMED_BIND */ 3236 *statp = s->s_namecanon.nc_stat; 3237 if (*statp == EX_TEMPFAIL) 3238 { 3239 CurEnv->e_status = "4.4.3"; 3240 message("851 %s: Name server timeout", 3241 shortenstring(name, 33)); 3242 } 3243 if (*statp != EX_OK) 3244 return NULL; 3245 if (s->s_namecanon.nc_cname == NULL) 3246 { 3247 syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d", 3248 name, 3249 s->s_namecanon.nc_errno, 3250 s->s_namecanon.nc_herrno); 3251 return NULL; 3252 } 3253 if (bitset(MF_MATCHONLY, map->map_mflags)) 3254 cp = map_rewrite(map, name, strlen(name), NULL); 3255 else 3256 cp = map_rewrite(map, 3257 s->s_namecanon.nc_cname, 3258 strlen(s->s_namecanon.nc_cname), 3259 av); 3260 return cp; 3261 } 3262 3263 /* 3264 ** If we are running without a regular network connection (usually 3265 ** dial-on-demand) and we are just queueing, we want to avoid DNS 3266 ** lookups because those could try to connect to a server. 3267 */ 3268 3269 if (CurEnv->e_sendmode == SM_DEFER && 3270 bitset(MF_DEFER, map->map_mflags)) 3271 { 3272 if (tTd(9, 1)) 3273 dprintf("host_map_lookup(%s) => DEFERRED\n", name); 3274 *statp = EX_TEMPFAIL; 3275 return NULL; 3276 } 3277 3278 /* 3279 ** If first character is a bracket, then it is an address 3280 ** lookup. Address is copied into a temporary buffer to 3281 ** strip the brackets and to preserve name if address is 3282 ** unknown. 3283 */ 3284 3285 if (tTd(9, 1)) 3286 dprintf("host_map_lookup(%s) => ", name); 3287 if (*name != '[') 3288 { 3289 snprintf(hbuf, sizeof hbuf, "%s", name); 3290 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) 3291 ans = hbuf; 3292 } 3293 else 3294 { 3295 if ((cp = strchr(name, ']')) == NULL) 3296 { 3297 if (tTd(9, 1)) 3298 dprintf("FAILED\n"); 3299 return NULL; 3300 } 3301 *cp = '\0'; 3302 3303 hp = NULL; 3304 # if NETINET 3305 if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 3306 hp = sm_gethostbyaddr((char *)&in_addr, 3307 INADDRSZ, AF_INET); 3308 # endif /* NETINET */ 3309 # if NETINET6 3310 if (hp == NULL && 3311 inet_pton(AF_INET6, &name[1], &in6_addr) == 1) 3312 hp = sm_gethostbyaddr((char *)&in6_addr, 3313 IN6ADDRSZ, AF_INET6); 3314 # endif /* NETINET6 */ 3315 *cp = ']'; 3316 3317 if (hp != NULL) 3318 { 3319 /* found a match -- copy out */ 3320 ans = denlstring((char *) hp->h_name, TRUE, TRUE); 3321 # if _FFR_FREEHOSTENT && NETINET6 3322 freehostent(hp); 3323 hp = NULL; 3324 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3325 } 3326 } 3327 3328 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 3329 3330 /* Found an answer */ 3331 if (ans != NULL) 3332 { 3333 s->s_namecanon.nc_stat = *statp = EX_OK; 3334 s->s_namecanon.nc_cname = newstr(ans); 3335 if (bitset(MF_MATCHONLY, map->map_mflags)) 3336 cp = map_rewrite(map, name, strlen(name), NULL); 3337 else 3338 cp = map_rewrite(map, ans, strlen(ans), av); 3339 if (tTd(9, 1)) 3340 dprintf("FOUND %s\n", ans); 3341 return cp; 3342 } 3343 3344 3345 /* No match found */ 3346 s->s_namecanon.nc_errno = errno; 3347 # if NAMED_BIND 3348 s->s_namecanon.nc_herrno = h_errno; 3349 if (tTd(9, 1)) 3350 dprintf("FAIL (%d)\n", h_errno); 3351 switch (h_errno) 3352 { 3353 case TRY_AGAIN: 3354 if (UseNameServer) 3355 { 3356 CurEnv->e_status = "4.4.3"; 3357 message("851 %s: Name server timeout", 3358 shortenstring(name, 33)); 3359 } 3360 *statp = EX_TEMPFAIL; 3361 break; 3362 3363 case HOST_NOT_FOUND: 3364 case NO_DATA: 3365 *statp = EX_NOHOST; 3366 break; 3367 3368 case NO_RECOVERY: 3369 *statp = EX_SOFTWARE; 3370 break; 3371 3372 default: 3373 *statp = EX_UNAVAILABLE; 3374 break; 3375 } 3376 # else /* NAMED_BIND */ 3377 if (tTd(9, 1)) 3378 dprintf("FAIL\n"); 3379 *statp = EX_NOHOST; 3380 # endif /* NAMED_BIND */ 3381 s->s_namecanon.nc_stat = *statp; 3382 return NULL; 3383 } 3384 #else /* DAEMON */ 3385 /* code for systems without sophisticated networking */ 3386 3387 /* 3388 ** MYHOSTNAME -- stub version for case of no daemon code. 3389 ** 3390 ** Can't convert to upper case here because might be a UUCP name. 3391 ** 3392 ** Mark, you can change this to be anything you want...... 3393 */ 3394 3395 char ** 3396 myhostname(hostbuf, size) 3397 char hostbuf[]; 3398 int size; 3399 { 3400 register FILE *f; 3401 3402 hostbuf[0] = '\0'; 3403 f = fopen("/usr/include/whoami", "r"); 3404 if (f != NULL) 3405 { 3406 (void) fgets(hostbuf, size, f); 3407 fixcrlf(hostbuf, TRUE); 3408 (void) fclose(f); 3409 } 3410 if (hostbuf[0] == '\0') 3411 (void) strlcpy(hostbuf, "localhost", size); 3412 return NULL; 3413 } 3414 /* 3415 ** GETAUTHINFO -- get the real host name associated with a file descriptor 3416 ** 3417 ** Parameters: 3418 ** fd -- the descriptor 3419 ** may_be_forged -- an outage that is set to TRUE if the 3420 ** forward lookup of RealHostName does not match 3421 ** RealHostAddr; set to FALSE if they do match. 3422 ** 3423 ** Returns: 3424 ** The host name associated with this descriptor, if it can 3425 ** be determined. 3426 ** NULL otherwise. 3427 ** 3428 ** Side Effects: 3429 ** none 3430 */ 3431 3432 char * 3433 getauthinfo(fd, may_be_forged) 3434 int fd; 3435 bool *may_be_forged; 3436 { 3437 *may_be_forged = FALSE; 3438 return NULL; 3439 } 3440 /* 3441 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3442 ** 3443 ** Parameters: 3444 ** map -- a pointer to the database map. 3445 ** name -- a buffer containing a hostname. 3446 ** avp -- a pointer to a (cf file defined) argument vector. 3447 ** statp -- an exit status (out parameter). 3448 ** 3449 ** Returns: 3450 ** mapped host name 3451 ** FALSE otherwise. 3452 ** 3453 ** Side Effects: 3454 ** Looks up the host specified in name. If it is not 3455 ** the canonical name for that host, replace it with 3456 ** the canonical name. If the name is unknown, or it 3457 ** is already the canonical name, leave it unchanged. 3458 */ 3459 3460 /*ARGSUSED*/ 3461 char * 3462 host_map_lookup(map, name, avp, statp) 3463 MAP *map; 3464 char *name; 3465 char **avp; 3466 char *statp; 3467 { 3468 register struct hostent *hp = NULL; 3469 char *cp; 3470 3471 hp = sm_gethostbyname(name, InetMode); 3472 if (hp == NULL && InetMode != AF_INET) 3473 hp = sm_gethostbyname(name, AF_INET); 3474 if (hp == NULL) 3475 { 3476 # if NAMED_BIND 3477 if (tTd(9, 1)) 3478 dprintf("FAIL (%d)\n", h_errno); 3479 switch (h_errno) 3480 { 3481 case TRY_AGAIN: 3482 if (UseNameServer) 3483 { 3484 CurEnv->e_status = "4.4.3"; 3485 message("851 %s: Name server timeout", 3486 shortenstring(name, 33)); 3487 } 3488 *statp = EX_TEMPFAIL; 3489 break; 3490 3491 case HOST_NOT_FOUND: 3492 case NO_DATA: 3493 *statp = EX_NOHOST; 3494 break; 3495 3496 case NO_RECOVERY: 3497 *statp = EX_SOFTWARE; 3498 break; 3499 3500 default: 3501 *statp = EX_UNAVAILABLE; 3502 break; 3503 } 3504 #else /* NAMED_BIND */ 3505 *statp = EX_NOHOST; 3506 #endif /* NAMED_BIND */ 3507 return NULL; 3508 } 3509 if (bitset(MF_MATCHONLY, map->map_mflags)) 3510 cp = map_rewrite(map, name, strlen(name), NULL); 3511 else 3512 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); 3513 # if _FFR_FREEHOSTENT && NETINET6 3514 freehostent(hp); 3515 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3516 return cp; 3517 } 3518 3519 #endif /* DAEMON */ 3520 /* 3521 ** HOST_MAP_INIT -- initialize host class structures 3522 */ 3523 3524 bool 3525 host_map_init(map, args) 3526 MAP *map; 3527 char *args; 3528 { 3529 register char *p = args; 3530 3531 for (;;) 3532 { 3533 while (isascii(*p) && isspace(*p)) 3534 p++; 3535 if (*p != '-') 3536 break; 3537 switch (*++p) 3538 { 3539 case 'a': 3540 map->map_app = ++p; 3541 break; 3542 3543 case 'T': 3544 map->map_tapp = ++p; 3545 break; 3546 3547 case 'm': 3548 map->map_mflags |= MF_MATCHONLY; 3549 break; 3550 3551 case 't': 3552 map->map_mflags |= MF_NODEFER; 3553 break; 3554 3555 case 'S': /* only for consistency */ 3556 map->map_spacesub = *++p; 3557 break; 3558 3559 case 'D': 3560 map->map_mflags |= MF_DEFER; 3561 break; 3562 } 3563 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 3564 p++; 3565 if (*p != '\0') 3566 *p++ = '\0'; 3567 } 3568 if (map->map_app != NULL) 3569 map->map_app = newstr(map->map_app); 3570 if (map->map_tapp != NULL) 3571 map->map_tapp = newstr(map->map_tapp); 3572 return TRUE; 3573 } 3574 3575 #if NETINET6 3576 /* 3577 ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 3578 ** 3579 ** Parameters: 3580 ** s6a -- a pointer to an in6_addr structure. 3581 ** dst -- buffer to store result in 3582 ** dst_len -- size of dst buffer 3583 ** 3584 ** Returns: 3585 ** A printable version of that structure. 3586 */ 3587 char * 3588 anynet_ntop(s6a, dst, dst_len) 3589 struct in6_addr *s6a; 3590 char *dst; 3591 size_t dst_len; 3592 { 3593 register char *ap; 3594 3595 if (IN6_IS_ADDR_V4MAPPED(s6a)) 3596 ap = (char *) inet_ntop(AF_INET, 3597 &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 3598 dst, dst_len); 3599 else 3600 ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 3601 return ap; 3602 } 3603 #endif /* NETINET6 */ 3604 /* 3605 ** ANYNET_NTOA -- convert a network address to printable form. 3606 ** 3607 ** Parameters: 3608 ** sap -- a pointer to a sockaddr structure. 3609 ** 3610 ** Returns: 3611 ** A printable version of that sockaddr. 3612 */ 3613 3614 #ifdef USE_SOCK_STREAM 3615 3616 # if NETLINK 3617 # include <net/if_dl.h> 3618 # endif /* NETLINK */ 3619 3620 char * 3621 anynet_ntoa(sap) 3622 register SOCKADDR *sap; 3623 { 3624 register char *bp; 3625 register char *ap; 3626 int l; 3627 static char buf[100]; 3628 3629 /* check for null/zero family */ 3630 if (sap == NULL) 3631 return "NULLADDR"; 3632 if (sap->sa.sa_family == 0) 3633 return "0"; 3634 3635 switch (sap->sa.sa_family) 3636 { 3637 # if NETUNIX 3638 case AF_UNIX: 3639 if (sap->sunix.sun_path[0] != '\0') 3640 snprintf(buf, sizeof buf, "[UNIX: %.64s]", 3641 sap->sunix.sun_path); 3642 else 3643 snprintf(buf, sizeof buf, "[UNIX: localhost]"); 3644 return buf; 3645 # endif /* NETUNIX */ 3646 3647 # if NETINET 3648 case AF_INET: 3649 return (char *) inet_ntoa(sap->sin.sin_addr); 3650 # endif /* NETINET */ 3651 3652 # if NETINET6 3653 case AF_INET6: 3654 ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); 3655 if (ap != NULL) 3656 return ap; 3657 break; 3658 # endif /* NETINET6 */ 3659 3660 # if NETLINK 3661 case AF_LINK: 3662 snprintf(buf, sizeof buf, "[LINK: %s]", 3663 link_ntoa((struct sockaddr_dl *) &sap->sa)); 3664 return buf; 3665 # endif /* NETLINK */ 3666 default: 3667 /* this case is needed when nothing is #defined */ 3668 /* in order to keep the switch syntactically correct */ 3669 break; 3670 } 3671 3672 /* unknown family -- just dump bytes */ 3673 (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 3674 bp = &buf[strlen(buf)]; 3675 ap = sap->sa.sa_data; 3676 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 3677 { 3678 (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377); 3679 bp += 3; 3680 } 3681 *--bp = '\0'; 3682 return buf; 3683 } 3684 /* 3685 ** HOSTNAMEBYANYADDR -- return name of host based on address 3686 ** 3687 ** Parameters: 3688 ** sap -- SOCKADDR pointer 3689 ** 3690 ** Returns: 3691 ** text representation of host name. 3692 ** 3693 ** Side Effects: 3694 ** none. 3695 */ 3696 3697 char * 3698 hostnamebyanyaddr(sap) 3699 register SOCKADDR *sap; 3700 { 3701 register struct hostent *hp; 3702 # if NAMED_BIND 3703 int saveretry; 3704 # endif /* NAMED_BIND */ 3705 # if NETINET6 3706 struct in6_addr in6_addr; 3707 # endif /* NETINET6 */ 3708 3709 # if NAMED_BIND 3710 /* shorten name server timeout to avoid higher level timeouts */ 3711 saveretry = _res.retry; 3712 if (_res.retry * _res.retrans > 20) 3713 _res.retry = 20 / _res.retrans; 3714 # endif /* NAMED_BIND */ 3715 3716 switch (sap->sa.sa_family) 3717 { 3718 # if NETINET 3719 case AF_INET: 3720 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 3721 INADDRSZ, 3722 AF_INET); 3723 break; 3724 # endif /* NETINET */ 3725 3726 # if NETINET6 3727 case AF_INET6: 3728 hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 3729 IN6ADDRSZ, 3730 AF_INET6); 3731 break; 3732 # endif /* NETINET6 */ 3733 3734 # if NETISO 3735 case AF_ISO: 3736 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 3737 sizeof sap->siso.siso_addr, 3738 AF_ISO); 3739 break; 3740 # endif /* NETISO */ 3741 3742 # if NETUNIX 3743 case AF_UNIX: 3744 hp = NULL; 3745 break; 3746 # endif /* NETUNIX */ 3747 3748 default: 3749 hp = sm_gethostbyaddr(sap->sa.sa_data, 3750 sizeof sap->sa.sa_data, 3751 sap->sa.sa_family); 3752 break; 3753 } 3754 3755 # if NAMED_BIND 3756 _res.retry = saveretry; 3757 # endif /* NAMED_BIND */ 3758 3759 # if NETINET || NETINET6 3760 if (hp != NULL && hp->h_name[0] != '[' 3761 # if NETINET6 3762 && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 3763 # endif /* NETINET6 */ 3764 # if NETINET 3765 && inet_addr(hp->h_name) == INADDR_NONE 3766 # endif /* NETINET */ 3767 ) 3768 { 3769 char *name; 3770 3771 name = denlstring((char *) hp->h_name, TRUE, TRUE); 3772 3773 # if _FFR_FREEHOSTENT && NETINET6 3774 if (name == hp->h_name) 3775 { 3776 static char n[MAXNAME + 1]; 3777 3778 /* Copy the string, hp->h_name is about to disappear */ 3779 strlcpy(n, name, sizeof n); 3780 name = n; 3781 } 3782 3783 freehostent(hp); 3784 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3785 return name; 3786 } 3787 # endif /* NETINET || NETINET6 */ 3788 3789 # if _FFR_FREEHOSTENT && NETINET6 3790 if (hp != NULL) 3791 { 3792 freehostent(hp); 3793 hp = NULL; 3794 } 3795 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3796 3797 # if NETUNIX 3798 if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 3799 return "localhost"; 3800 # endif /* NETUNIX */ 3801 { 3802 static char buf[203]; 3803 3804 (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap)); 3805 return buf; 3806 } 3807 } 3808 #endif /* USE_SOCK_STREAM */ 3809