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.68 2001/07/20 18:45:58 gshapiro Exp $ (with daemon mode)"; 20 # else /* DAEMON */ 21 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.68 2001/07/20 18:45:58 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 if (!control) 706 { 707 define(macid("{daemon_addr}", NULL), 708 newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)), 709 &BlankEnvelope); 710 (void) snprintf(status, sizeof status, "%d", 711 ntohs(Daemons[curdaemon].d_port)); 712 define(macid("{daemon_port}", NULL), 713 newstr(status), &BlankEnvelope); 714 } 715 716 for (idx = 0; idx < ndaemons; idx++) 717 { 718 if (Daemons[idx].d_socket >= 0) 719 (void) close(Daemons[idx].d_socket); 720 Daemons[idx].d_socket = -1; 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 /* Make a non-DFL/IGN signal a noop */ 2485 #define SM_NOOP_SIGNAL(sig, old) \ 2486 do \ 2487 { \ 2488 (old) = setsignal((sig), sm_signal_noop); \ 2489 if ((old) == SIG_IGN || (old) == SIG_DFL) \ 2490 (void) setsignal((sig), (old)); \ 2491 } while (0) 2492 2493 static void 2494 restart_daemon() 2495 { 2496 int i; 2497 int save_errno; 2498 char *reason; 2499 sigfunc_t ignore, oalrm, ousr1; 2500 extern int DtableSize; 2501 2502 /* clear the events to turn off SIGALRMs */ 2503 clear_events(); 2504 allsignals(TRUE); 2505 2506 reason = RestartRequest; 2507 RestartRequest = NULL; 2508 PendingSignal = 0; 2509 2510 if (SaveArgv[0][0] != '/') 2511 { 2512 if (LogLevel > 3) 2513 sm_syslog(LOG_INFO, NOQID, 2514 "could not restart: need full path"); 2515 finis(FALSE, EX_OSFILE); 2516 } 2517 if (LogLevel > 3) 2518 sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 2519 SaveArgv[0], 2520 reason == NULL ? "implicit call" : reason); 2521 2522 closecontrolsocket(TRUE); 2523 if (drop_privileges(TRUE) != EX_OK) 2524 { 2525 if (LogLevel > 0) 2526 sm_syslog(LOG_ALERT, NOQID, 2527 "could not set[ug]id(%d, %d): %m", 2528 RunAsUid, RunAsGid); 2529 finis(FALSE, EX_OSERR); 2530 } 2531 2532 /* arrange for all the files to be closed */ 2533 for (i = 3; i < DtableSize; i++) 2534 { 2535 register int j; 2536 2537 if ((j = fcntl(i, F_GETFD, 0)) != -1) 2538 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 2539 } 2540 2541 /* 2542 ** Need to allow signals before execve() to make them "harmless". 2543 ** However, the default action can be "terminate", so it isn't 2544 ** really harmless. Setting signals to IGN will cause them to be 2545 ** ignored in the new process to, so that isn't a good alternative. 2546 */ 2547 2548 SM_NOOP_SIGNAL(SIGALRM, oalrm); 2549 SM_NOOP_SIGNAL(SIGCHLD, ignore); 2550 SM_NOOP_SIGNAL(SIGHUP, ignore); 2551 SM_NOOP_SIGNAL(SIGINT, ignore); 2552 SM_NOOP_SIGNAL(SIGPIPE, ignore); 2553 SM_NOOP_SIGNAL(SIGTERM, ignore); 2554 #ifdef SIGUSR1 2555 SM_NOOP_SIGNAL(SIGUSR1, ousr1); 2556 #endif /* SIGUSR1 */ 2557 allsignals(FALSE); 2558 2559 (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 2560 save_errno = errno; 2561 2562 /* block signals again and restore needed signals */ 2563 allsignals(TRUE); 2564 2565 /* For finis() events */ 2566 (void) setsignal(SIGALRM, oalrm); 2567 2568 #ifdef SIGUSR1 2569 /* For debugging finis() */ 2570 (void) setsignal(SIGUSR1, ousr1); 2571 #endif /* SIGUSR1 */ 2572 2573 errno = save_errno; 2574 if (LogLevel > 0) 2575 sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", 2576 SaveArgv[0]); 2577 finis(FALSE, EX_OSFILE); 2578 } 2579 /* 2580 ** MYHOSTNAME -- return the name of this host. 2581 ** 2582 ** Parameters: 2583 ** hostbuf -- a place to return the name of this host. 2584 ** size -- the size of hostbuf. 2585 ** 2586 ** Returns: 2587 ** A list of aliases for this host. 2588 ** 2589 ** Side Effects: 2590 ** Adds numeric codes to $=w. 2591 */ 2592 2593 struct hostent * 2594 myhostname(hostbuf, size) 2595 char hostbuf[]; 2596 int size; 2597 { 2598 register struct hostent *hp; 2599 2600 if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 2601 (void) strlcpy(hostbuf, "localhost", size); 2602 hp = sm_gethostbyname(hostbuf, InetMode); 2603 # if NETINET && NETINET6 2604 if (hp == NULL && InetMode == AF_INET6) 2605 { 2606 /* 2607 ** It's possible that this IPv6 enabled machine doesn't 2608 ** actually have any IPv6 interfaces and, therefore, no 2609 ** IPv6 addresses. Fall back to AF_INET. 2610 */ 2611 2612 hp = sm_gethostbyname(hostbuf, AF_INET); 2613 } 2614 # endif /* NETINET && NETINET6 */ 2615 2616 if (hp == NULL) 2617 return NULL; 2618 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 2619 (void) cleanstrcpy(hostbuf, hp->h_name, size); 2620 2621 # if NETINFO 2622 if (strchr(hostbuf, '.') == NULL) 2623 { 2624 char *domainname; 2625 2626 domainname = ni_propval("/locations", NULL, "resolver", 2627 "domain", '\0'); 2628 if (domainname != NULL && 2629 strlen(domainname) + strlen(hostbuf) + 1 < size) 2630 { 2631 (void) strlcat(hostbuf, ".", size); 2632 (void) strlcat(hostbuf, domainname, size); 2633 } 2634 } 2635 # endif /* NETINFO */ 2636 2637 /* 2638 ** If there is still no dot in the name, try looking for a 2639 ** dotted alias. 2640 */ 2641 2642 if (strchr(hostbuf, '.') == NULL) 2643 { 2644 char **ha; 2645 2646 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 2647 { 2648 if (strchr(*ha, '.') != NULL) 2649 { 2650 (void) cleanstrcpy(hostbuf, *ha, size - 1); 2651 hostbuf[size - 1] = '\0'; 2652 break; 2653 } 2654 } 2655 } 2656 2657 /* 2658 ** If _still_ no dot, wait for a while and try again -- it is 2659 ** possible that some service is starting up. This can result 2660 ** in excessive delays if the system is badly configured, but 2661 ** there really isn't a way around that, particularly given that 2662 ** the config file hasn't been read at this point. 2663 ** All in all, a bit of a mess. 2664 */ 2665 2666 if (strchr(hostbuf, '.') == NULL && 2667 !getcanonname(hostbuf, size, TRUE)) 2668 { 2669 sm_syslog(LOG_CRIT, NOQID, 2670 "My unqualified host name (%s) unknown; sleeping for retry", 2671 hostbuf); 2672 message("My unqualified host name (%s) unknown; sleeping for retry", 2673 hostbuf); 2674 (void) sleep(60); 2675 if (!getcanonname(hostbuf, size, TRUE)) 2676 { 2677 sm_syslog(LOG_ALERT, NOQID, 2678 "unable to qualify my own domain name (%s) -- using short name", 2679 hostbuf); 2680 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 2681 hostbuf); 2682 } 2683 } 2684 return hp; 2685 } 2686 /* 2687 ** ADDRCMP -- compare two host addresses 2688 ** 2689 ** Parameters: 2690 ** hp -- hostent structure for the first address 2691 ** ha -- actual first address 2692 ** sa -- second address 2693 ** 2694 ** Returns: 2695 ** 0 -- if ha and sa match 2696 ** else -- they don't match 2697 */ 2698 2699 static int 2700 addrcmp(hp, ha, sa) 2701 struct hostent *hp; 2702 char *ha; 2703 SOCKADDR *sa; 2704 { 2705 # if NETINET6 2706 u_char *a; 2707 # endif /* NETINET6 */ 2708 2709 switch (sa->sa.sa_family) 2710 { 2711 # if NETINET 2712 case AF_INET: 2713 if (hp->h_addrtype == AF_INET) 2714 return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 2715 break; 2716 # endif /* NETINET */ 2717 2718 # if NETINET6 2719 case AF_INET6: 2720 a = (u_char *) &sa->sin6.sin6_addr; 2721 2722 /* Straight binary comparison */ 2723 if (hp->h_addrtype == AF_INET6) 2724 return memcmp(ha, a, IN6ADDRSZ); 2725 2726 /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 2727 if (hp->h_addrtype == AF_INET && 2728 IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 2729 return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 2730 break; 2731 # endif /* NETINET6 */ 2732 } 2733 return -1; 2734 } 2735 /* 2736 ** GETAUTHINFO -- get the real host name associated with a file descriptor 2737 ** 2738 ** Uses RFC1413 protocol to try to get info from the other end. 2739 ** 2740 ** Parameters: 2741 ** fd -- the descriptor 2742 ** may_be_forged -- an outage that is set to TRUE if the 2743 ** forward lookup of RealHostName does not match 2744 ** RealHostAddr; set to FALSE if they do match. 2745 ** 2746 ** Returns: 2747 ** The user@host information associated with this descriptor. 2748 */ 2749 2750 static jmp_buf CtxAuthTimeout; 2751 2752 static void 2753 authtimeout() 2754 { 2755 /* 2756 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2757 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2758 ** DOING. 2759 */ 2760 2761 errno = ETIMEDOUT; 2762 longjmp(CtxAuthTimeout, 1); 2763 } 2764 2765 char * 2766 getauthinfo(fd, may_be_forged) 2767 int fd; 2768 bool *may_be_forged; 2769 { 2770 volatile u_short port = 0; 2771 SOCKADDR_LEN_T falen; 2772 register char *volatile p = NULL; 2773 SOCKADDR la; 2774 SOCKADDR_LEN_T lalen; 2775 register struct servent *sp; 2776 volatile int s; 2777 int i = 0; 2778 EVENT *ev; 2779 int nleft; 2780 struct hostent *hp; 2781 char *ostype = NULL; 2782 char **ha; 2783 char ibuf[MAXNAME + 1]; 2784 static char hbuf[MAXNAME * 2 + 11]; 2785 2786 *may_be_forged = FALSE; 2787 falen = sizeof RealHostAddr; 2788 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 2789 falen <= 0 || RealHostAddr.sa.sa_family == 0) 2790 { 2791 if (i < 0) 2792 { 2793 /* 2794 ** ENOTSOCK is OK: bail on anything else, but reset 2795 ** errno in this case, so a mis-report doesn't 2796 ** happen later. 2797 */ 2798 if (errno != ENOTSOCK) 2799 return NULL; 2800 errno = 0; 2801 } 2802 (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", 2803 RealUserName); 2804 if (tTd(9, 1)) 2805 dprintf("getauthinfo: %s\n", hbuf); 2806 return hbuf; 2807 } 2808 2809 if (RealHostName == NULL) 2810 { 2811 /* translate that to a host name */ 2812 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 2813 if (strlen(RealHostName) > MAXNAME) 2814 RealHostName[MAXNAME] = '\0'; 2815 } 2816 2817 /* cross check RealHostName with forward DNS lookup */ 2818 if (anynet_ntoa(&RealHostAddr)[0] == '[' || 2819 RealHostName[0] == '[') 2820 { 2821 /* 2822 ** address is not a socket or have an 2823 ** IP address with no forward lookup 2824 */ 2825 *may_be_forged = FALSE; 2826 } 2827 else 2828 { 2829 int family; 2830 2831 family = RealHostAddr.sa.sa_family; 2832 # if NETINET6 && NEEDSGETIPNODE 2833 /* 2834 ** If RealHostAddr is an IPv6 connection with an 2835 ** IPv4-mapped address, we need RealHostName's IPv4 2836 ** address(es) for addrcmp() to compare against 2837 ** RealHostAddr. 2838 ** 2839 ** Actually, we only need to do this for systems 2840 ** which NEEDSGETIPNODE since the real getipnodebyname() 2841 ** already does V4MAPPED address via the AI_V4MAPPEDCFG 2842 ** flag. A better fix to this problem is to add this 2843 ** functionality to our stub getipnodebyname(). 2844 */ 2845 2846 if (family == AF_INET6 && 2847 IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 2848 family = AF_INET; 2849 # endif /* NETINET6 && NEEDSGETIPNODE */ 2850 2851 /* try to match the reverse against the forward lookup */ 2852 hp = sm_gethostbyname(RealHostName, family); 2853 if (hp == NULL) 2854 *may_be_forged = TRUE; 2855 else 2856 { 2857 for (ha = hp->h_addr_list; *ha != NULL; ha++) 2858 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 2859 break; 2860 *may_be_forged = *ha == NULL; 2861 # if _FFR_FREEHOSTENT && NETINET6 2862 freehostent(hp); 2863 hp = NULL; 2864 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 2865 } 2866 } 2867 2868 if (TimeOuts.to_ident == 0) 2869 goto noident; 2870 2871 lalen = sizeof la; 2872 switch (RealHostAddr.sa.sa_family) 2873 { 2874 # if NETINET 2875 case AF_INET: 2876 if (getsockname(fd, &la.sa, &lalen) < 0 || 2877 lalen <= 0 || 2878 la.sa.sa_family != AF_INET) 2879 { 2880 /* no ident info */ 2881 goto noident; 2882 } 2883 port = RealHostAddr.sin.sin_port; 2884 2885 /* create ident query */ 2886 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2887 ntohs(RealHostAddr.sin.sin_port), 2888 ntohs(la.sin.sin_port)); 2889 2890 /* create local address */ 2891 la.sin.sin_port = 0; 2892 2893 /* create foreign address */ 2894 # ifdef NO_GETSERVBYNAME 2895 RealHostAddr.sin.sin_port = htons(113); 2896 # else /* NO_GETSERVBYNAME */ 2897 sp = getservbyname("auth", "tcp"); 2898 if (sp != NULL) 2899 RealHostAddr.sin.sin_port = sp->s_port; 2900 else 2901 RealHostAddr.sin.sin_port = htons(113); 2902 break; 2903 # endif /* NO_GETSERVBYNAME */ 2904 # endif /* NETINET */ 2905 2906 # if NETINET6 2907 case AF_INET6: 2908 if (getsockname(fd, &la.sa, &lalen) < 0 || 2909 lalen <= 0 || 2910 la.sa.sa_family != AF_INET6) 2911 { 2912 /* no ident info */ 2913 goto noident; 2914 } 2915 port = RealHostAddr.sin6.sin6_port; 2916 2917 /* create ident query */ 2918 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2919 ntohs(RealHostAddr.sin6.sin6_port), 2920 ntohs(la.sin6.sin6_port)); 2921 2922 /* create local address */ 2923 la.sin6.sin6_port = 0; 2924 2925 /* create foreign address */ 2926 # ifdef NO_GETSERVBYNAME 2927 RealHostAddr.sin6.sin6_port = htons(113); 2928 # else /* NO_GETSERVBYNAME */ 2929 sp = getservbyname("auth", "tcp"); 2930 if (sp != NULL) 2931 RealHostAddr.sin6.sin6_port = sp->s_port; 2932 else 2933 RealHostAddr.sin6.sin6_port = htons(113); 2934 break; 2935 # endif /* NO_GETSERVBYNAME */ 2936 # endif /* NETINET6 */ 2937 default: 2938 /* no ident info */ 2939 goto noident; 2940 } 2941 2942 s = -1; 2943 if (setjmp(CtxAuthTimeout) != 0) 2944 { 2945 if (s >= 0) 2946 (void) close(s); 2947 goto noident; 2948 } 2949 2950 /* put a timeout around the whole thing */ 2951 ev = setevent(TimeOuts.to_ident, authtimeout, 0); 2952 2953 2954 /* connect to foreign IDENT server using same address as SMTP socket */ 2955 s = socket(la.sa.sa_family, SOCK_STREAM, 0); 2956 if (s < 0) 2957 { 2958 clrevent(ev); 2959 goto noident; 2960 } 2961 if (bind(s, &la.sa, lalen) < 0 || 2962 connect(s, &RealHostAddr.sa, lalen) < 0) 2963 { 2964 goto closeident; 2965 } 2966 2967 if (tTd(9, 10)) 2968 dprintf("getauthinfo: sent %s", ibuf); 2969 2970 /* send query */ 2971 if (write(s, ibuf, strlen(ibuf)) < 0) 2972 goto closeident; 2973 2974 /* get result */ 2975 p = &ibuf[0]; 2976 nleft = sizeof ibuf - 1; 2977 while ((i = read(s, p, nleft)) > 0) 2978 { 2979 p += i; 2980 nleft -= i; 2981 *p = '\0'; 2982 if (strchr(ibuf, '\n') != NULL) 2983 break; 2984 } 2985 (void) close(s); 2986 clrevent(ev); 2987 if (i < 0 || p == &ibuf[0]) 2988 goto noident; 2989 2990 if (*--p == '\n' && *--p == '\r') 2991 p--; 2992 *++p = '\0'; 2993 2994 if (tTd(9, 3)) 2995 dprintf("getauthinfo: got %s\n", ibuf); 2996 2997 /* parse result */ 2998 p = strchr(ibuf, ':'); 2999 if (p == NULL) 3000 { 3001 /* malformed response */ 3002 goto noident; 3003 } 3004 while (isascii(*++p) && isspace(*p)) 3005 continue; 3006 if (strncasecmp(p, "userid", 6) != 0) 3007 { 3008 /* presumably an error string */ 3009 goto noident; 3010 } 3011 p += 6; 3012 while (isascii(*p) && isspace(*p)) 3013 p++; 3014 if (*p++ != ':') 3015 { 3016 /* either useridxx or malformed response */ 3017 goto noident; 3018 } 3019 3020 /* p now points to the OSTYPE field */ 3021 while (isascii(*p) && isspace(*p)) 3022 p++; 3023 ostype = p; 3024 p = strchr(p, ':'); 3025 if (p == NULL) 3026 { 3027 /* malformed response */ 3028 goto noident; 3029 } 3030 else 3031 { 3032 char *charset; 3033 3034 *p = '\0'; 3035 charset = strchr(ostype, ','); 3036 if (charset != NULL) 3037 *charset = '\0'; 3038 } 3039 3040 /* 1413 says don't do this -- but it's broken otherwise */ 3041 while (isascii(*++p) && isspace(*p)) 3042 continue; 3043 3044 /* p now points to the authenticated name -- copy carefully */ 3045 if (strncasecmp(ostype, "other", 5) == 0 && 3046 (ostype[5] == ' ' || ostype[5] == '\0')) 3047 { 3048 snprintf(hbuf, sizeof hbuf, "IDENT:"); 3049 cleanstrcpy(&hbuf[6], p, MAXNAME); 3050 } 3051 else 3052 cleanstrcpy(hbuf, p, MAXNAME); 3053 i = strlen(hbuf); 3054 snprintf(&hbuf[i], sizeof hbuf - i, "@%s", 3055 RealHostName == NULL ? "localhost" : RealHostName); 3056 goto postident; 3057 3058 closeident: 3059 (void) close(s); 3060 clrevent(ev); 3061 3062 noident: 3063 /* put back the original incoming port */ 3064 switch (RealHostAddr.sa.sa_family) 3065 { 3066 # if NETINET 3067 case AF_INET: 3068 if (port > 0) 3069 RealHostAddr.sin.sin_port = port; 3070 break; 3071 # endif /* NETINET */ 3072 3073 # if NETINET6 3074 case AF_INET6: 3075 if (port > 0) 3076 RealHostAddr.sin6.sin6_port = port; 3077 break; 3078 # endif /* NETINET6 */ 3079 } 3080 3081 if (RealHostName == NULL) 3082 { 3083 if (tTd(9, 1)) 3084 dprintf("getauthinfo: NULL\n"); 3085 return NULL; 3086 } 3087 snprintf(hbuf, sizeof hbuf, "%s", RealHostName); 3088 3089 postident: 3090 # if IP_SRCROUTE 3091 # ifndef GET_IPOPT_DST 3092 # define GET_IPOPT_DST(dst) (dst) 3093 # endif /* ! GET_IPOPT_DST */ 3094 /* 3095 ** Extract IP source routing information. 3096 ** 3097 ** Format of output for a connection from site a through b 3098 ** through c to d: 3099 ** loose: @site-c@site-b:site-a 3100 ** strict: !@site-c@site-b:site-a 3101 ** 3102 ** o - pointer within ipopt_list structure. 3103 ** q - pointer within ls/ss rr route data 3104 ** p - pointer to hbuf 3105 */ 3106 3107 if (RealHostAddr.sa.sa_family == AF_INET) 3108 { 3109 SOCKOPT_LEN_T ipoptlen; 3110 int j; 3111 u_char *q; 3112 u_char *o; 3113 int l; 3114 struct IPOPTION ipopt; 3115 3116 ipoptlen = sizeof ipopt; 3117 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 3118 (char *) &ipopt, &ipoptlen) < 0) 3119 goto noipsr; 3120 if (ipoptlen == 0) 3121 goto noipsr; 3122 o = (u_char *) ipopt.IP_LIST; 3123 while (o != NULL && o < (u_char *) &ipopt + ipoptlen) 3124 { 3125 switch (*o) 3126 { 3127 case IPOPT_EOL: 3128 o = NULL; 3129 break; 3130 3131 case IPOPT_NOP: 3132 o++; 3133 break; 3134 3135 case IPOPT_SSRR: 3136 case IPOPT_LSRR: 3137 /* 3138 ** Source routing. 3139 ** o[0] is the option type (loose/strict). 3140 ** o[1] is the length of this option, 3141 ** including option type and 3142 ** length. 3143 ** o[2] is the pointer into the route 3144 ** data. 3145 ** o[3] begins the route data. 3146 */ 3147 3148 p = &hbuf[strlen(hbuf)]; 3149 l = sizeof hbuf - (hbuf - p) - 6; 3150 snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", 3151 *o == IPOPT_SSRR ? "!" : "", 3152 l > 240 ? 120 : l / 2, 3153 inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 3154 i = strlen(p); 3155 p += i; 3156 l -= strlen(p); 3157 3158 j = o[1] / sizeof(struct in_addr) - 1; 3159 3160 /* q skips length and router pointer to data */ 3161 q = &o[3]; 3162 for ( ; j >= 0; j--) 3163 { 3164 struct in_addr addr; 3165 3166 memcpy(&addr, q, sizeof(addr)); 3167 snprintf(p, SPACELEFT(hbuf, p), 3168 "%c%.*s", 3169 j != 0 ? '@' : ':', 3170 l > 240 ? 120 : 3171 j == 0 ? l : l / 2, 3172 inet_ntoa(addr)); 3173 i = strlen(p); 3174 p += i; 3175 l -= i + 1; 3176 q += sizeof(struct in_addr); 3177 } 3178 o += o[1]; 3179 break; 3180 3181 default: 3182 /* Skip over option */ 3183 o += o[1]; 3184 break; 3185 } 3186 } 3187 snprintf(p, SPACELEFT(hbuf, p), "]"); 3188 goto postipsr; 3189 } 3190 3191 noipsr: 3192 # endif /* IP_SRCROUTE */ 3193 if (RealHostName != NULL && RealHostName[0] != '[') 3194 { 3195 p = &hbuf[strlen(hbuf)]; 3196 (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 3197 anynet_ntoa(&RealHostAddr)); 3198 } 3199 if (*may_be_forged) 3200 { 3201 p = &hbuf[strlen(hbuf)]; 3202 (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); 3203 } 3204 3205 # if IP_SRCROUTE 3206 postipsr: 3207 # endif /* IP_SRCROUTE */ 3208 if (tTd(9, 1)) 3209 dprintf("getauthinfo: %s\n", hbuf); 3210 3211 /* put back the original incoming port */ 3212 switch (RealHostAddr.sa.sa_family) 3213 { 3214 # if NETINET 3215 case AF_INET: 3216 if (port > 0) 3217 RealHostAddr.sin.sin_port = port; 3218 break; 3219 # endif /* NETINET */ 3220 3221 # if NETINET6 3222 case AF_INET6: 3223 if (port > 0) 3224 RealHostAddr.sin6.sin6_port = port; 3225 break; 3226 # endif /* NETINET6 */ 3227 } 3228 3229 return hbuf; 3230 } 3231 /* 3232 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3233 ** 3234 ** Parameters: 3235 ** map -- a pointer to this map. 3236 ** name -- the (presumably unqualified) hostname. 3237 ** av -- unused -- for compatibility with other mapping 3238 ** functions. 3239 ** statp -- an exit status (out parameter) -- set to 3240 ** EX_TEMPFAIL if the name server is unavailable. 3241 ** 3242 ** Returns: 3243 ** The mapping, if found. 3244 ** NULL if no mapping found. 3245 ** 3246 ** Side Effects: 3247 ** Looks up the host specified in hbuf. If it is not 3248 ** the canonical name for that host, return the canonical 3249 ** name (unless MF_MATCHONLY is set, which will cause the 3250 ** status only to be returned). 3251 */ 3252 3253 char * 3254 host_map_lookup(map, name, av, statp) 3255 MAP *map; 3256 char *name; 3257 char **av; 3258 int *statp; 3259 { 3260 register struct hostent *hp; 3261 # if NETINET 3262 struct in_addr in_addr; 3263 # endif /* NETINET */ 3264 # if NETINET6 3265 struct in6_addr in6_addr; 3266 # endif /* NETINET6 */ 3267 char *cp, *ans = NULL; 3268 register STAB *s; 3269 char hbuf[MAXNAME + 1]; 3270 3271 /* 3272 ** See if we have already looked up this name. If so, just 3273 ** return it. 3274 */ 3275 3276 s = stab(name, ST_NAMECANON, ST_ENTER); 3277 if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 3278 { 3279 if (tTd(9, 1)) 3280 dprintf("host_map_lookup(%s) => CACHE %s\n", 3281 name, 3282 s->s_namecanon.nc_cname == NULL 3283 ? "NULL" 3284 : s->s_namecanon.nc_cname); 3285 errno = s->s_namecanon.nc_errno; 3286 # if NAMED_BIND 3287 SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 3288 # endif /* NAMED_BIND */ 3289 *statp = s->s_namecanon.nc_stat; 3290 if (*statp == EX_TEMPFAIL) 3291 { 3292 CurEnv->e_status = "4.4.3"; 3293 message("851 %s: Name server timeout", 3294 shortenstring(name, 33)); 3295 } 3296 if (*statp != EX_OK) 3297 return NULL; 3298 if (s->s_namecanon.nc_cname == NULL) 3299 { 3300 syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d", 3301 name, 3302 s->s_namecanon.nc_errno, 3303 s->s_namecanon.nc_herrno); 3304 return NULL; 3305 } 3306 if (bitset(MF_MATCHONLY, map->map_mflags)) 3307 cp = map_rewrite(map, name, strlen(name), NULL); 3308 else 3309 cp = map_rewrite(map, 3310 s->s_namecanon.nc_cname, 3311 strlen(s->s_namecanon.nc_cname), 3312 av); 3313 return cp; 3314 } 3315 3316 /* 3317 ** If we are running without a regular network connection (usually 3318 ** dial-on-demand) and we are just queueing, we want to avoid DNS 3319 ** lookups because those could try to connect to a server. 3320 */ 3321 3322 if (CurEnv->e_sendmode == SM_DEFER && 3323 bitset(MF_DEFER, map->map_mflags)) 3324 { 3325 if (tTd(9, 1)) 3326 dprintf("host_map_lookup(%s) => DEFERRED\n", name); 3327 *statp = EX_TEMPFAIL; 3328 return NULL; 3329 } 3330 3331 /* 3332 ** If first character is a bracket, then it is an address 3333 ** lookup. Address is copied into a temporary buffer to 3334 ** strip the brackets and to preserve name if address is 3335 ** unknown. 3336 */ 3337 3338 if (tTd(9, 1)) 3339 dprintf("host_map_lookup(%s) => ", name); 3340 if (*name != '[') 3341 { 3342 snprintf(hbuf, sizeof hbuf, "%s", name); 3343 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) 3344 ans = hbuf; 3345 } 3346 else 3347 { 3348 if ((cp = strchr(name, ']')) == NULL) 3349 { 3350 if (tTd(9, 1)) 3351 dprintf("FAILED\n"); 3352 return NULL; 3353 } 3354 *cp = '\0'; 3355 3356 hp = NULL; 3357 # if NETINET 3358 if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 3359 hp = sm_gethostbyaddr((char *)&in_addr, 3360 INADDRSZ, AF_INET); 3361 # endif /* NETINET */ 3362 # if NETINET6 3363 if (hp == NULL && 3364 inet_pton(AF_INET6, &name[1], &in6_addr) == 1) 3365 hp = sm_gethostbyaddr((char *)&in6_addr, 3366 IN6ADDRSZ, AF_INET6); 3367 # endif /* NETINET6 */ 3368 *cp = ']'; 3369 3370 if (hp != NULL) 3371 { 3372 /* found a match -- copy out */ 3373 ans = denlstring((char *) hp->h_name, TRUE, TRUE); 3374 # if _FFR_FREEHOSTENT && NETINET6 3375 freehostent(hp); 3376 hp = NULL; 3377 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3378 } 3379 } 3380 3381 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 3382 3383 /* Found an answer */ 3384 if (ans != NULL) 3385 { 3386 s->s_namecanon.nc_stat = *statp = EX_OK; 3387 s->s_namecanon.nc_cname = newstr(ans); 3388 if (bitset(MF_MATCHONLY, map->map_mflags)) 3389 cp = map_rewrite(map, name, strlen(name), NULL); 3390 else 3391 cp = map_rewrite(map, ans, strlen(ans), av); 3392 if (tTd(9, 1)) 3393 dprintf("FOUND %s\n", ans); 3394 return cp; 3395 } 3396 3397 3398 /* No match found */ 3399 s->s_namecanon.nc_errno = errno; 3400 # if NAMED_BIND 3401 s->s_namecanon.nc_herrno = h_errno; 3402 if (tTd(9, 1)) 3403 dprintf("FAIL (%d)\n", h_errno); 3404 switch (h_errno) 3405 { 3406 case TRY_AGAIN: 3407 if (UseNameServer) 3408 { 3409 CurEnv->e_status = "4.4.3"; 3410 message("851 %s: Name server timeout", 3411 shortenstring(name, 33)); 3412 } 3413 *statp = EX_TEMPFAIL; 3414 break; 3415 3416 case HOST_NOT_FOUND: 3417 case NO_DATA: 3418 *statp = EX_NOHOST; 3419 break; 3420 3421 case NO_RECOVERY: 3422 *statp = EX_SOFTWARE; 3423 break; 3424 3425 default: 3426 *statp = EX_UNAVAILABLE; 3427 break; 3428 } 3429 # else /* NAMED_BIND */ 3430 if (tTd(9, 1)) 3431 dprintf("FAIL\n"); 3432 *statp = EX_NOHOST; 3433 # endif /* NAMED_BIND */ 3434 s->s_namecanon.nc_stat = *statp; 3435 return NULL; 3436 } 3437 #else /* DAEMON */ 3438 /* code for systems without sophisticated networking */ 3439 3440 /* 3441 ** MYHOSTNAME -- stub version for case of no daemon code. 3442 ** 3443 ** Can't convert to upper case here because might be a UUCP name. 3444 ** 3445 ** Mark, you can change this to be anything you want...... 3446 */ 3447 3448 char ** 3449 myhostname(hostbuf, size) 3450 char hostbuf[]; 3451 int size; 3452 { 3453 register FILE *f; 3454 3455 hostbuf[0] = '\0'; 3456 f = fopen("/usr/include/whoami", "r"); 3457 if (f != NULL) 3458 { 3459 (void) fgets(hostbuf, size, f); 3460 fixcrlf(hostbuf, TRUE); 3461 (void) fclose(f); 3462 } 3463 if (hostbuf[0] == '\0') 3464 (void) strlcpy(hostbuf, "localhost", size); 3465 return NULL; 3466 } 3467 /* 3468 ** GETAUTHINFO -- get the real host name associated with a file descriptor 3469 ** 3470 ** Parameters: 3471 ** fd -- the descriptor 3472 ** may_be_forged -- an outage that is set to TRUE if the 3473 ** forward lookup of RealHostName does not match 3474 ** RealHostAddr; set to FALSE if they do match. 3475 ** 3476 ** Returns: 3477 ** The host name associated with this descriptor, if it can 3478 ** be determined. 3479 ** NULL otherwise. 3480 ** 3481 ** Side Effects: 3482 ** none 3483 */ 3484 3485 char * 3486 getauthinfo(fd, may_be_forged) 3487 int fd; 3488 bool *may_be_forged; 3489 { 3490 *may_be_forged = FALSE; 3491 return NULL; 3492 } 3493 /* 3494 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3495 ** 3496 ** Parameters: 3497 ** map -- a pointer to the database map. 3498 ** name -- a buffer containing a hostname. 3499 ** avp -- a pointer to a (cf file defined) argument vector. 3500 ** statp -- an exit status (out parameter). 3501 ** 3502 ** Returns: 3503 ** mapped host name 3504 ** FALSE otherwise. 3505 ** 3506 ** Side Effects: 3507 ** Looks up the host specified in name. If it is not 3508 ** the canonical name for that host, replace it with 3509 ** the canonical name. If the name is unknown, or it 3510 ** is already the canonical name, leave it unchanged. 3511 */ 3512 3513 /*ARGSUSED*/ 3514 char * 3515 host_map_lookup(map, name, avp, statp) 3516 MAP *map; 3517 char *name; 3518 char **avp; 3519 char *statp; 3520 { 3521 register struct hostent *hp = NULL; 3522 char *cp; 3523 3524 hp = sm_gethostbyname(name, InetMode); 3525 if (hp == NULL && InetMode != AF_INET) 3526 hp = sm_gethostbyname(name, AF_INET); 3527 if (hp == NULL) 3528 { 3529 # if NAMED_BIND 3530 if (tTd(9, 1)) 3531 dprintf("FAIL (%d)\n", h_errno); 3532 switch (h_errno) 3533 { 3534 case TRY_AGAIN: 3535 if (UseNameServer) 3536 { 3537 CurEnv->e_status = "4.4.3"; 3538 message("851 %s: Name server timeout", 3539 shortenstring(name, 33)); 3540 } 3541 *statp = EX_TEMPFAIL; 3542 break; 3543 3544 case HOST_NOT_FOUND: 3545 case NO_DATA: 3546 *statp = EX_NOHOST; 3547 break; 3548 3549 case NO_RECOVERY: 3550 *statp = EX_SOFTWARE; 3551 break; 3552 3553 default: 3554 *statp = EX_UNAVAILABLE; 3555 break; 3556 } 3557 #else /* NAMED_BIND */ 3558 *statp = EX_NOHOST; 3559 #endif /* NAMED_BIND */ 3560 return NULL; 3561 } 3562 if (bitset(MF_MATCHONLY, map->map_mflags)) 3563 cp = map_rewrite(map, name, strlen(name), NULL); 3564 else 3565 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); 3566 # if _FFR_FREEHOSTENT && NETINET6 3567 freehostent(hp); 3568 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3569 return cp; 3570 } 3571 3572 #endif /* DAEMON */ 3573 /* 3574 ** HOST_MAP_INIT -- initialize host class structures 3575 */ 3576 3577 bool 3578 host_map_init(map, args) 3579 MAP *map; 3580 char *args; 3581 { 3582 register char *p = args; 3583 3584 for (;;) 3585 { 3586 while (isascii(*p) && isspace(*p)) 3587 p++; 3588 if (*p != '-') 3589 break; 3590 switch (*++p) 3591 { 3592 case 'a': 3593 map->map_app = ++p; 3594 break; 3595 3596 case 'T': 3597 map->map_tapp = ++p; 3598 break; 3599 3600 case 'm': 3601 map->map_mflags |= MF_MATCHONLY; 3602 break; 3603 3604 case 't': 3605 map->map_mflags |= MF_NODEFER; 3606 break; 3607 3608 case 'S': /* only for consistency */ 3609 map->map_spacesub = *++p; 3610 break; 3611 3612 case 'D': 3613 map->map_mflags |= MF_DEFER; 3614 break; 3615 } 3616 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 3617 p++; 3618 if (*p != '\0') 3619 *p++ = '\0'; 3620 } 3621 if (map->map_app != NULL) 3622 map->map_app = newstr(map->map_app); 3623 if (map->map_tapp != NULL) 3624 map->map_tapp = newstr(map->map_tapp); 3625 return TRUE; 3626 } 3627 3628 #if NETINET6 3629 /* 3630 ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 3631 ** 3632 ** Parameters: 3633 ** s6a -- a pointer to an in6_addr structure. 3634 ** dst -- buffer to store result in 3635 ** dst_len -- size of dst buffer 3636 ** 3637 ** Returns: 3638 ** A printable version of that structure. 3639 */ 3640 char * 3641 anynet_ntop(s6a, dst, dst_len) 3642 struct in6_addr *s6a; 3643 char *dst; 3644 size_t dst_len; 3645 { 3646 register char *ap; 3647 3648 if (IN6_IS_ADDR_V4MAPPED(s6a)) 3649 ap = (char *) inet_ntop(AF_INET, 3650 &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 3651 dst, dst_len); 3652 else 3653 ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 3654 return ap; 3655 } 3656 #endif /* NETINET6 */ 3657 /* 3658 ** ANYNET_NTOA -- convert a network address to printable form. 3659 ** 3660 ** Parameters: 3661 ** sap -- a pointer to a sockaddr structure. 3662 ** 3663 ** Returns: 3664 ** A printable version of that sockaddr. 3665 */ 3666 3667 #ifdef USE_SOCK_STREAM 3668 3669 # if NETLINK 3670 # include <net/if_dl.h> 3671 # endif /* NETLINK */ 3672 3673 char * 3674 anynet_ntoa(sap) 3675 register SOCKADDR *sap; 3676 { 3677 register char *bp; 3678 register char *ap; 3679 int l; 3680 static char buf[100]; 3681 3682 /* check for null/zero family */ 3683 if (sap == NULL) 3684 return "NULLADDR"; 3685 if (sap->sa.sa_family == 0) 3686 return "0"; 3687 3688 switch (sap->sa.sa_family) 3689 { 3690 # if NETUNIX 3691 case AF_UNIX: 3692 if (sap->sunix.sun_path[0] != '\0') 3693 snprintf(buf, sizeof buf, "[UNIX: %.64s]", 3694 sap->sunix.sun_path); 3695 else 3696 snprintf(buf, sizeof buf, "[UNIX: localhost]"); 3697 return buf; 3698 # endif /* NETUNIX */ 3699 3700 # if NETINET 3701 case AF_INET: 3702 return (char *) inet_ntoa(sap->sin.sin_addr); 3703 # endif /* NETINET */ 3704 3705 # if NETINET6 3706 case AF_INET6: 3707 ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); 3708 if (ap != NULL) 3709 return ap; 3710 break; 3711 # endif /* NETINET6 */ 3712 3713 # if NETLINK 3714 case AF_LINK: 3715 snprintf(buf, sizeof buf, "[LINK: %s]", 3716 link_ntoa((struct sockaddr_dl *) &sap->sa)); 3717 return buf; 3718 # endif /* NETLINK */ 3719 default: 3720 /* this case is needed when nothing is #defined */ 3721 /* in order to keep the switch syntactically correct */ 3722 break; 3723 } 3724 3725 /* unknown family -- just dump bytes */ 3726 (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 3727 bp = &buf[strlen(buf)]; 3728 ap = sap->sa.sa_data; 3729 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 3730 { 3731 (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377); 3732 bp += 3; 3733 } 3734 *--bp = '\0'; 3735 return buf; 3736 } 3737 /* 3738 ** HOSTNAMEBYANYADDR -- return name of host based on address 3739 ** 3740 ** Parameters: 3741 ** sap -- SOCKADDR pointer 3742 ** 3743 ** Returns: 3744 ** text representation of host name. 3745 ** 3746 ** Side Effects: 3747 ** none. 3748 */ 3749 3750 char * 3751 hostnamebyanyaddr(sap) 3752 register SOCKADDR *sap; 3753 { 3754 register struct hostent *hp; 3755 # if NAMED_BIND 3756 int saveretry; 3757 # endif /* NAMED_BIND */ 3758 # if NETINET6 3759 struct in6_addr in6_addr; 3760 # endif /* NETINET6 */ 3761 3762 # if NAMED_BIND 3763 /* shorten name server timeout to avoid higher level timeouts */ 3764 saveretry = _res.retry; 3765 if (_res.retry * _res.retrans > 20) 3766 _res.retry = 20 / _res.retrans; 3767 # endif /* NAMED_BIND */ 3768 3769 switch (sap->sa.sa_family) 3770 { 3771 # if NETINET 3772 case AF_INET: 3773 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 3774 INADDRSZ, 3775 AF_INET); 3776 break; 3777 # endif /* NETINET */ 3778 3779 # if NETINET6 3780 case AF_INET6: 3781 hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 3782 IN6ADDRSZ, 3783 AF_INET6); 3784 break; 3785 # endif /* NETINET6 */ 3786 3787 # if NETISO 3788 case AF_ISO: 3789 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 3790 sizeof sap->siso.siso_addr, 3791 AF_ISO); 3792 break; 3793 # endif /* NETISO */ 3794 3795 # if NETUNIX 3796 case AF_UNIX: 3797 hp = NULL; 3798 break; 3799 # endif /* NETUNIX */ 3800 3801 default: 3802 hp = sm_gethostbyaddr(sap->sa.sa_data, 3803 sizeof sap->sa.sa_data, 3804 sap->sa.sa_family); 3805 break; 3806 } 3807 3808 # if NAMED_BIND 3809 _res.retry = saveretry; 3810 # endif /* NAMED_BIND */ 3811 3812 # if NETINET || NETINET6 3813 if (hp != NULL && hp->h_name[0] != '[' 3814 # if NETINET6 3815 && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 3816 # endif /* NETINET6 */ 3817 # if NETINET 3818 && inet_addr(hp->h_name) == INADDR_NONE 3819 # endif /* NETINET */ 3820 ) 3821 { 3822 char *name; 3823 3824 name = denlstring((char *) hp->h_name, TRUE, TRUE); 3825 3826 # if _FFR_FREEHOSTENT && NETINET6 3827 if (name == hp->h_name) 3828 { 3829 static char n[MAXNAME + 1]; 3830 3831 /* Copy the string, hp->h_name is about to disappear */ 3832 strlcpy(n, name, sizeof n); 3833 name = n; 3834 } 3835 3836 freehostent(hp); 3837 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3838 return name; 3839 } 3840 # endif /* NETINET || NETINET6 */ 3841 3842 # if _FFR_FREEHOSTENT && NETINET6 3843 if (hp != NULL) 3844 { 3845 freehostent(hp); 3846 hp = NULL; 3847 } 3848 # endif /* _FFR_FREEHOSTENT && NETINET6 */ 3849 3850 # if NETUNIX 3851 if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 3852 return "localhost"; 3853 # endif /* NETUNIX */ 3854 { 3855 static char buf[203]; 3856 3857 (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap)); 3858 return buf; 3859 } 3860 } 3861 #endif /* USE_SOCK_STREAM */ 3862