1 /* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 */ 12 13 #include <errno.h> 14 #include "sendmail.h" 15 16 #ifndef lint 17 #ifdef DAEMON 18 static char sccsid[] = "@(#)daemon.c 8.236 (Berkeley) 1/25/1999 (with daemon mode)"; 19 #else 20 static char sccsid[] = "@(#)daemon.c 8.236 (Berkeley) 1/25/1999 (without daemon mode)"; 21 #endif 22 #endif /* not lint */ 23 24 #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 25 # define USE_SOCK_STREAM 1 26 #endif 27 28 #if DAEMON || defined(USE_SOCK_STREAM) 29 # include <arpa/inet.h> 30 # if NAMED_BIND 31 # include <resolv.h> 32 # ifndef NO_DATA 33 # define NO_DATA NO_ADDRESS 34 # endif 35 # endif 36 #endif 37 38 #if DAEMON 39 40 # include <sys/time.h> 41 42 # if IP_SRCROUTE 43 # include <netinet/in_systm.h> 44 # include <netinet/ip.h> 45 # include <netinet/ip_var.h> 46 # endif 47 48 /* 49 ** DAEMON.C -- routines to use when running as a daemon. 50 ** 51 ** This entire file is highly dependent on the 4.2 BSD 52 ** interprocess communication primitives. No attempt has 53 ** been made to make this file portable to Version 7, 54 ** Version 6, MPX files, etc. If you should try such a 55 ** thing yourself, I recommend chucking the entire file 56 ** and starting from scratch. Basic semantics are: 57 ** 58 ** getrequests(e) 59 ** Opens a port and initiates a connection. 60 ** Returns in a child. Must set InChannel and 61 ** OutChannel appropriately. 62 ** clrdaemon() 63 ** Close any open files associated with getting 64 ** the connection; this is used when running the queue, 65 ** etc., to avoid having extra file descriptors during 66 ** the queue run and to avoid confusing the network 67 ** code (if it cares). 68 ** makeconnection(host, port, outfile, infile, e) 69 ** Make a connection to the named host on the given 70 ** port. Set *outfile and *infile to the files 71 ** appropriate for communication. Returns zero on 72 ** success, else an exit status describing the 73 ** error. 74 ** host_map_lookup(map, hbuf, avp, pstat) 75 ** Convert the entry in hbuf into a canonical form. 76 */ 77 /* 78 ** GETREQUESTS -- open mail IPC port and get requests. 79 ** 80 ** Parameters: 81 ** e -- the current envelope. 82 ** 83 ** Returns: 84 ** none. 85 ** 86 ** Side Effects: 87 ** Waits until some interesting activity occurs. When 88 ** it does, a child is created to process it, and the 89 ** parent waits for completion. Return from this 90 ** routine is always in the child. The file pointers 91 ** "InChannel" and "OutChannel" should be set to point 92 ** to the communication channel. 93 */ 94 95 int DaemonSocket = -1; /* fd describing socket */ 96 SOCKADDR DaemonAddr; /* socket for incoming */ 97 int ListenQueueSize = 10; /* size of listen queue */ 98 int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 99 int TcpSndBufferSize = 0; /* size of TCP send buffer */ 100 101 void 102 getrequests(e) 103 ENVELOPE *e; 104 { 105 int t; 106 time_t refuse_connections_until = 0; 107 bool firsttime = TRUE; 108 FILE *pidf; 109 int sff; 110 int socksize; 111 u_short port; 112 #if XDEBUG 113 bool j_has_dot; 114 #endif 115 char status[MAXLINE]; 116 extern void reapchild __P((int)); 117 #ifdef NETUNIX 118 extern int ControlSocket; 119 #endif 120 extern int opendaemonsocket __P((bool)); 121 extern int opencontrolsocket __P((void)); 122 123 /* 124 ** Set up the address for the mailer. 125 */ 126 127 switch (DaemonAddr.sa.sa_family) 128 { 129 case AF_UNSPEC: 130 DaemonAddr.sa.sa_family = AF_INET; 131 /* fall through ... */ 132 133 case AF_INET: 134 if (DaemonAddr.sin.sin_addr.s_addr == 0) 135 DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY; 136 port = DaemonAddr.sin.sin_port; 137 break; 138 139 default: 140 /* unknown protocol */ 141 port = 0; 142 break; 143 } 144 if (port == 0) 145 { 146 register struct servent *sp; 147 148 sp = getservbyname("smtp", "tcp"); 149 if (sp == NULL) 150 { 151 syserr("554 service \"smtp\" unknown"); 152 port = htons(25); 153 } 154 else 155 port = sp->s_port; 156 } 157 158 switch (DaemonAddr.sa.sa_family) 159 { 160 case AF_INET: 161 DaemonAddr.sin.sin_port = port; 162 break; 163 164 default: 165 /* unknown protocol */ 166 break; 167 } 168 169 /* 170 ** Try to actually open the connection. 171 */ 172 173 if (tTd(15, 1)) 174 printf("getrequests: port 0x%x\n", port); 175 176 /* get a socket for the SMTP connection */ 177 socksize = opendaemonsocket(TRUE); 178 179 if (opencontrolsocket() < 0) 180 sm_syslog(LOG_WARNING, NOQID, 181 "daemon could not open control socket %s: %s", 182 ControlSocketName, errstring(errno)); 183 184 (void) setsignal(SIGCHLD, reapchild); 185 186 /* write the pid to the log file for posterity */ 187 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; 188 if (TrustedUid != 0 && RealUid == TrustedUid) 189 sff |= SFF_OPENASROOT; 190 pidf = safefopen(PidFile, O_WRONLY|O_TRUNC, 0644, sff); 191 if (pidf == NULL) 192 { 193 sm_syslog(LOG_ERR, NOQID, "unable to write %s", PidFile); 194 } 195 else 196 { 197 extern char *CommandLineArgs; 198 199 /* write the process id on line 1 */ 200 fprintf(pidf, "%ld\n", (long) getpid()); 201 202 /* line 2 contains all command line flags */ 203 fprintf(pidf, "%s\n", CommandLineArgs); 204 205 /* flush and close */ 206 fclose(pidf); 207 } 208 209 #if XDEBUG 210 { 211 char jbuf[MAXHOSTNAMELEN]; 212 213 expand("\201j", jbuf, sizeof jbuf, e); 214 j_has_dot = strchr(jbuf, '.') != NULL; 215 } 216 #endif 217 218 /* Add parent process as first item */ 219 proc_list_add(getpid(), "Sendmail daemon"); 220 221 if (tTd(15, 1)) 222 printf("getrequests: %d\n", DaemonSocket); 223 224 for (;;) 225 { 226 register pid_t pid; 227 auto SOCKADDR_LEN_T lotherend; 228 bool timedout = FALSE; 229 bool control = FALSE; 230 int savederrno; 231 int pipefd[2]; 232 extern bool refuseconnections __P((int)); 233 234 /* see if we are rejecting connections */ 235 (void) blocksignal(SIGALRM); 236 if (curtime() >= refuse_connections_until) 237 { 238 if (refuseconnections(ntohs(port))) 239 { 240 if (DaemonSocket >= 0) 241 { 242 /* close socket so peer fails quickly */ 243 (void) close(DaemonSocket); 244 DaemonSocket = -1; 245 } 246 247 /* refuse connections for next 15 seconds */ 248 refuse_connections_until = curtime() + 15; 249 } 250 else if (DaemonSocket < 0 || firsttime) 251 { 252 /* arrange to (re)open the socket if needed */ 253 (void) opendaemonsocket(FALSE); 254 firsttime = FALSE; 255 } 256 } 257 258 #if XDEBUG 259 /* check for disaster */ 260 { 261 char jbuf[MAXHOSTNAMELEN]; 262 extern void dumpstate __P((char *)); 263 264 expand("\201j", jbuf, sizeof jbuf, e); 265 if (!wordinclass(jbuf, 'w')) 266 { 267 dumpstate("daemon lost $j"); 268 sm_syslog(LOG_ALERT, NOQID, 269 "daemon process doesn't have $j in $=w; see syslog"); 270 abort(); 271 } 272 else if (j_has_dot && strchr(jbuf, '.') == NULL) 273 { 274 dumpstate("daemon $j lost dot"); 275 sm_syslog(LOG_ALERT, NOQID, 276 "daemon process $j lost dot; see syslog"); 277 abort(); 278 } 279 } 280 #endif 281 282 #if 0 283 /* 284 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 285 ** fix the SVr4 problem. But it seems to have gone away, 286 ** so is it worth doing this? 287 */ 288 289 if (DaemonSocket >= 0 && 290 SetNonBlocking(DaemonSocket, FALSE) < 0) 291 log an error here; 292 #endif 293 (void) releasesignal(SIGALRM); 294 for (;;) 295 { 296 int highest = -1; 297 fd_set readfds; 298 struct timeval timeout; 299 300 FD_ZERO(&readfds); 301 302 /* wait for a connection */ 303 if (DaemonSocket >= 0) 304 { 305 sm_setproctitle(TRUE, 306 "accepting connections on port %d", 307 ntohs(port)); 308 if (DaemonSocket > highest) 309 highest = DaemonSocket; 310 FD_SET(DaemonSocket, &readfds); 311 } 312 #ifdef NETUNIX 313 if (ControlSocket >= 0) 314 { 315 if (ControlSocket > highest) 316 highest = ControlSocket; 317 FD_SET(ControlSocket, &readfds); 318 } 319 #endif 320 if (DaemonSocket >= 0) 321 timeout.tv_sec = 60; 322 else 323 timeout.tv_sec = 5; 324 timeout.tv_usec = 0; 325 326 t = select(highest + 1, FDSET_CAST &readfds, 327 NULL, NULL, &timeout); 328 329 if (DoQueueRun) 330 (void) runqueue(TRUE, FALSE); 331 if (t <= 0) 332 { 333 timedout = TRUE; 334 break; 335 } 336 337 control = FALSE; 338 errno = 0; 339 if (DaemonSocket >= 0 && 340 FD_ISSET(DaemonSocket, &readfds)) 341 { 342 lotherend = socksize; 343 t = accept(DaemonSocket, 344 (struct sockaddr *)&RealHostAddr, 345 &lotherend); 346 } 347 #ifdef NETUNIX 348 else if (ControlSocket >= 0 && 349 FD_ISSET(ControlSocket, &readfds)) 350 { 351 struct sockaddr_un sa_un; 352 353 lotherend = sizeof sa_un; 354 t = accept(ControlSocket, 355 (struct sockaddr *)&sa_un, 356 &lotherend); 357 control = TRUE; 358 } 359 #endif 360 if (t >= 0 || errno != EINTR) 361 break; 362 } 363 if (timedout) 364 { 365 timedout = FALSE; 366 continue; 367 } 368 if (control) 369 { 370 if (t >= 0) 371 { 372 extern void control_command __P((int, ENVELOPE *)); 373 374 control_command(t, e); 375 } 376 else 377 syserr("getrequests: control accept"); 378 continue; 379 } 380 savederrno = errno; 381 (void) blocksignal(SIGALRM); 382 if (t < 0) 383 { 384 errno = savederrno; 385 syserr("getrequests: accept"); 386 387 /* arrange to re-open the socket next time around */ 388 (void) close(DaemonSocket); 389 DaemonSocket = -1; 390 continue; 391 } 392 393 /* 394 ** Create a subprocess to process the mail. 395 */ 396 397 if (tTd(15, 2)) 398 printf("getrequests: forking (fd = %d)\n", t); 399 400 /* 401 ** Create a pipe to keep the child from writing to the 402 ** socket until after the parent has closed it. Otherwise 403 ** the parent may hang if the child has closed it first. 404 */ 405 406 if (pipe(pipefd) < 0) 407 pipefd[0] = pipefd[1] = -1; 408 409 blocksignal(SIGCHLD); 410 pid = fork(); 411 if (pid < 0) 412 { 413 syserr("daemon: cannot fork"); 414 if (pipefd[0] != -1) 415 { 416 (void) close(pipefd[0]); 417 (void) close(pipefd[1]); 418 } 419 (void) releasesignal(SIGCHLD); 420 sleep(10); 421 (void) close(t); 422 continue; 423 } 424 425 if (pid == 0) 426 { 427 char *p; 428 extern SIGFUNC_DECL intsig __P((int)); 429 FILE *inchannel, *outchannel; 430 431 /* 432 ** CHILD -- return to caller. 433 ** Collect verified idea of sending host. 434 ** Verify calling user id if possible here. 435 */ 436 437 (void) releasesignal(SIGALRM); 438 (void) releasesignal(SIGCHLD); 439 (void) setsignal(SIGCHLD, SIG_DFL); 440 (void) setsignal(SIGHUP, intsig); 441 (void) close(DaemonSocket); 442 clrcontrol(); 443 proc_list_clear(); 444 445 /* Add parent process as first child item */ 446 proc_list_add(getpid(), "daemon child"); 447 448 /* don't schedule queue runs if we are told to ETRN */ 449 QueueIntvl = 0; 450 451 sm_setproctitle(TRUE, "startup with %s", 452 anynet_ntoa(&RealHostAddr)); 453 454 if (pipefd[0] != -1) 455 { 456 auto char c; 457 458 /* 459 ** Wait for the parent to close the write end 460 ** of the pipe, which we will see as an EOF. 461 ** This guarantees that we won't write to the 462 ** socket until after the parent has closed 463 ** the pipe. 464 */ 465 466 /* close the write end of the pipe */ 467 (void) close(pipefd[1]); 468 469 /* we shouldn't be interrupted, but ... */ 470 while (read(pipefd[0], &c, 1) < 0 && 471 errno == EINTR) 472 continue; 473 (void) close(pipefd[0]); 474 } 475 476 /* determine host name */ 477 p = hostnamebyanyaddr(&RealHostAddr); 478 if (strlen(p) > (SIZE_T) MAXNAME) 479 p[MAXNAME] = '\0'; 480 RealHostName = newstr(p); 481 sm_setproctitle(TRUE, "startup with %s", p); 482 483 if ((inchannel = fdopen(t, "r")) == NULL || 484 (t = dup(t)) < 0 || 485 (outchannel = fdopen(t, "w")) == NULL) 486 { 487 syserr("cannot open SMTP server channel, fd=%d", t); 488 finis(FALSE, EX_OK); 489 } 490 491 InChannel = inchannel; 492 OutChannel = outchannel; 493 DisConnected = FALSE; 494 495 #ifdef XLA 496 if (!xla_host_ok(RealHostName)) 497 { 498 message("421 Too many SMTP sessions for this host"); 499 finis(FALSE, EX_OK); 500 } 501 #endif 502 break; 503 } 504 505 /* parent -- keep track of children */ 506 snprintf(status, sizeof status, "SMTP server child for %s", 507 anynet_ntoa(&RealHostAddr)); 508 proc_list_add(pid, status); 509 (void) releasesignal(SIGCHLD); 510 511 /* close the read end of the synchronization pipe */ 512 if (pipefd[0] != -1) 513 (void) close(pipefd[0]); 514 515 /* close the port so that others will hang (for a while) */ 516 (void) close(t); 517 518 /* release the child by closing the read end of the sync pipe */ 519 if (pipefd[1] != -1) 520 (void) close(pipefd[1]); 521 } 522 if (tTd(15, 2)) 523 printf("getreq: returning\n"); 524 return; 525 } 526 /* 527 ** OPENDAEMONSOCKET -- open the SMTP socket 528 ** 529 ** Deals with setting all appropriate options. DaemonAddr must 530 ** be set up in advance. 531 ** 532 ** Parameters: 533 ** firsttime -- set if this is the initial open. 534 ** 535 ** Returns: 536 ** Size in bytes of the daemon socket addr. 537 ** 538 ** Side Effects: 539 ** Leaves DaemonSocket set to the open socket. 540 ** Exits if the socket cannot be created. 541 */ 542 543 #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 544 545 int 546 opendaemonsocket(firsttime) 547 bool firsttime; 548 { 549 int on = 1; 550 int socksize = 0; 551 int ntries = 0; 552 int saveerrno; 553 554 if (tTd(15, 2)) 555 printf("opendaemonsocket()\n"); 556 557 do 558 { 559 if (ntries > 0) 560 sleep(5); 561 if (firsttime || DaemonSocket < 0) 562 { 563 DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); 564 if (DaemonSocket < 0) 565 { 566 saveerrno = errno; 567 syserr("opendaemonsocket: can't create server SMTP socket"); 568 severe: 569 if (LogLevel > 0) 570 sm_syslog(LOG_ALERT, NOQID, 571 "problem creating SMTP socket"); 572 DaemonSocket = -1; 573 continue; 574 } 575 576 /* turn on network debugging? */ 577 if (tTd(15, 101)) 578 (void) setsockopt(DaemonSocket, SOL_SOCKET, 579 SO_DEBUG, (char *)&on, 580 sizeof on); 581 582 (void) setsockopt(DaemonSocket, SOL_SOCKET, 583 SO_REUSEADDR, (char *)&on, sizeof on); 584 (void) setsockopt(DaemonSocket, SOL_SOCKET, 585 SO_KEEPALIVE, (char *)&on, sizeof on); 586 587 #ifdef SO_RCVBUF 588 if (TcpRcvBufferSize > 0) 589 { 590 if (setsockopt(DaemonSocket, SOL_SOCKET, 591 SO_RCVBUF, 592 (char *) &TcpRcvBufferSize, 593 sizeof(TcpRcvBufferSize)) < 0) 594 syserr("opendaemonsocket: setsockopt(SO_RCVBUF)"); 595 } 596 #endif 597 598 switch (DaemonAddr.sa.sa_family) 599 { 600 # if NETINET 601 case AF_INET: 602 socksize = sizeof DaemonAddr.sin; 603 break; 604 # endif 605 606 # if NETISO 607 case AF_ISO: 608 socksize = sizeof DaemonAddr.siso; 609 break; 610 # endif 611 612 default: 613 socksize = sizeof DaemonAddr; 614 break; 615 } 616 617 if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) 618 { 619 /* probably another daemon already */ 620 saveerrno = errno; 621 syserr("opendaemonsocket: cannot bind"); 622 (void) close(DaemonSocket); 623 goto severe; 624 } 625 } 626 if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) 627 { 628 saveerrno = errno; 629 syserr("opendaemonsocket: cannot listen"); 630 (void) close(DaemonSocket); 631 goto severe; 632 } 633 return socksize; 634 } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno)); 635 syserr("!opendaemonsocket: server SMTP socket wedged: exiting"); 636 /*NOTREACHED*/ 637 return -1; /* avoid compiler warning on IRIX */ 638 } 639 /* 640 ** CLRDAEMON -- reset the daemon connection 641 ** 642 ** Parameters: 643 ** none. 644 ** 645 ** Returns: 646 ** none. 647 ** 648 ** Side Effects: 649 ** releases any resources used by the passive daemon. 650 */ 651 652 void 653 clrdaemon() 654 { 655 if (DaemonSocket >= 0) 656 (void) close(DaemonSocket); 657 DaemonSocket = -1; 658 } 659 /* 660 ** SETDAEMONOPTIONS -- set options for running the daemon 661 ** 662 ** Parameters: 663 ** p -- the options line. 664 ** 665 ** Returns: 666 ** none. 667 */ 668 669 void 670 setdaemonoptions(p) 671 register char *p; 672 { 673 if (DaemonAddr.sa.sa_family == AF_UNSPEC) 674 DaemonAddr.sa.sa_family = AF_INET; 675 676 while (p != NULL) 677 { 678 register char *f; 679 register char *v; 680 681 while (isascii(*p) && isspace(*p)) 682 p++; 683 if (*p == '\0') 684 break; 685 f = p; 686 p = strchr(p, ','); 687 if (p != NULL) 688 *p++ = '\0'; 689 v = strchr(f, '='); 690 if (v == NULL) 691 continue; 692 while (isascii(*++v) && isspace(*v)) 693 continue; 694 if (isascii(*f) && islower(*f)) 695 *f = toupper(*f); 696 697 switch (*f) 698 { 699 case 'F': /* address family */ 700 if (isascii(*v) && isdigit(*v)) 701 DaemonAddr.sa.sa_family = atoi(v); 702 #if NETINET 703 else if (strcasecmp(v, "inet") == 0) 704 DaemonAddr.sa.sa_family = AF_INET; 705 #endif 706 #if NETISO 707 else if (strcasecmp(v, "iso") == 0) 708 DaemonAddr.sa.sa_family = AF_ISO; 709 #endif 710 #if NETNS 711 else if (strcasecmp(v, "ns") == 0) 712 DaemonAddr.sa.sa_family = AF_NS; 713 #endif 714 #if NETX25 715 else if (strcasecmp(v, "x.25") == 0) 716 DaemonAddr.sa.sa_family = AF_CCITT; 717 #endif 718 else 719 syserr("554 Unknown address family %s in Family=option", v); 720 break; 721 722 case 'A': /* address */ 723 switch (DaemonAddr.sa.sa_family) 724 { 725 #if NETINET 726 case AF_INET: 727 if (isascii(*v) && isdigit(*v)) 728 DaemonAddr.sin.sin_addr.s_addr = inet_addr(v); 729 else 730 { 731 register struct hostent *hp; 732 733 hp = sm_gethostbyname(v); 734 if (hp == NULL) 735 syserr("554 host \"%s\" unknown", v); 736 else 737 bcopy(hp->h_addr, &DaemonAddr.sin.sin_addr, INADDRSZ); 738 } 739 break; 740 #endif 741 742 default: 743 syserr("554 Address= option unsupported for family %d", 744 DaemonAddr.sa.sa_family); 745 break; 746 } 747 break; 748 749 case 'P': /* port */ 750 switch (DaemonAddr.sa.sa_family) 751 { 752 #if NETISO 753 short port; 754 #endif 755 756 #if NETINET 757 case AF_INET: 758 if (isascii(*v) && isdigit(*v)) 759 DaemonAddr.sin.sin_port = htons(atoi(v)); 760 else 761 { 762 register struct servent *sp; 763 764 sp = getservbyname(v, "tcp"); 765 if (sp == NULL) 766 syserr("554 service \"%s\" unknown", v); 767 else 768 DaemonAddr.sin.sin_port = sp->s_port; 769 } 770 break; 771 #endif 772 773 #if NETISO 774 case AF_ISO: 775 /* assume two byte transport selector */ 776 if (isascii(*v) && isdigit(*v)) 777 port = htons(atoi(v)); 778 else 779 { 780 register struct servent *sp; 781 782 sp = getservbyname(v, "tcp"); 783 if (sp == NULL) 784 syserr("554 service \"%s\" unknown", v); 785 else 786 port = sp->s_port; 787 } 788 bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2); 789 break; 790 #endif 791 792 default: 793 syserr("554 Port= option unsupported for family %d", 794 DaemonAddr.sa.sa_family); 795 break; 796 } 797 break; 798 799 case 'L': /* listen queue size */ 800 ListenQueueSize = atoi(v); 801 break; 802 803 case 'S': /* send buffer size */ 804 TcpSndBufferSize = atoi(v); 805 break; 806 807 case 'R': /* receive buffer size */ 808 TcpRcvBufferSize = atoi(v); 809 break; 810 811 default: 812 syserr("554 DaemonPortOptions parameter \"%s\" unknown", f); 813 } 814 } 815 } 816 /* 817 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 818 ** 819 ** Parameters: 820 ** host -- the name of the host. 821 ** port -- the port number to connect to. 822 ** mci -- a pointer to the mail connection information 823 ** structure to be filled in. 824 ** e -- the current envelope. 825 ** 826 ** Returns: 827 ** An exit code telling whether the connection could be 828 ** made and if not why not. 829 ** 830 ** Side Effects: 831 ** none. 832 */ 833 834 static jmp_buf CtxConnectTimeout; 835 836 static void 837 connecttimeout() 838 { 839 errno = ETIMEDOUT; 840 longjmp(CtxConnectTimeout, 1); 841 } 842 843 SOCKADDR CurHostAddr; /* address of current host */ 844 845 int 846 makeconnection(host, port, mci, e) 847 char *host; 848 u_short port; 849 register MCI *mci; 850 ENVELOPE *e; 851 { 852 register volatile int addrno = 0; 853 register volatile int s; 854 register struct hostent *volatile hp = (struct hostent *)NULL; 855 SOCKADDR addr; 856 int sav_errno; 857 volatile int addrlen; 858 volatile bool firstconnect; 859 EVENT *volatile ev = NULL; 860 861 /* 862 ** Set up the address for the mailer. 863 ** Accept "[a.b.c.d]" syntax for host name. 864 */ 865 866 #if NAMED_BIND 867 h_errno = 0; 868 #endif 869 errno = 0; 870 bzero(&CurHostAddr, sizeof CurHostAddr); 871 SmtpPhase = mci->mci_phase = "initial connection"; 872 CurHostName = host; 873 874 if (host[0] == '[') 875 { 876 #if NETINET 877 unsigned long hid = INADDR_NONE; 878 #endif 879 register char *p = strchr(host, ']'); 880 881 if (p != NULL) 882 { 883 *p = '\0'; 884 #if NETINET 885 hid = inet_addr(&host[1]); 886 if (hid == INADDR_NONE) 887 #endif 888 { 889 /* try it as a host name (avoid MX lookup) */ 890 hp = sm_gethostbyname(&host[1]); 891 if (hp == NULL && p[-1] == '.') 892 { 893 #if NAMED_BIND 894 int oldopts = _res.options; 895 896 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 897 #endif 898 p[-1] = '\0'; 899 hp = sm_gethostbyname(&host[1]); 900 p[-1] = '.'; 901 #if NAMED_BIND 902 _res.options = oldopts; 903 #endif 904 } 905 *p = ']'; 906 goto gothostent; 907 } 908 *p = ']'; 909 } 910 if (p == NULL) 911 { 912 extern char MsgBuf[]; 913 914 usrerr("553 Invalid numeric domain spec \"%s\"", host); 915 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 916 return EX_NOHOST; 917 } 918 #if NETINET 919 addr.sin.sin_family = AF_INET; /*XXX*/ 920 addr.sin.sin_addr.s_addr = hid; 921 #endif 922 } 923 else 924 { 925 /* contortion to get around SGI cc complaints */ 926 { 927 register char *p = &host[strlen(host) - 1]; 928 929 hp = sm_gethostbyname(host); 930 if (hp == NULL && *p == '.') 931 { 932 #if NAMED_BIND 933 int oldopts = _res.options; 934 935 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 936 #endif 937 *p = '\0'; 938 hp = sm_gethostbyname(host); 939 *p = '.'; 940 #if NAMED_BIND 941 _res.options = oldopts; 942 #endif 943 } 944 } 945 gothostent: 946 if (hp == NULL) 947 { 948 #if NAMED_BIND 949 /* check for name server timeouts */ 950 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 951 (errno == ECONNREFUSED && UseNameServer)) 952 { 953 mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL); 954 return EX_TEMPFAIL; 955 } 956 #endif 957 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 958 return (EX_NOHOST); 959 } 960 addr.sa.sa_family = hp->h_addrtype; 961 switch (hp->h_addrtype) 962 { 963 #if NETINET 964 case AF_INET: 965 bcopy(hp->h_addr, 966 &addr.sin.sin_addr, 967 INADDRSZ); 968 break; 969 #endif 970 971 default: 972 if (hp->h_length > sizeof addr.sa.sa_data) 973 { 974 syserr("makeconnection: long sa_data: family %d len %d", 975 hp->h_addrtype, hp->h_length); 976 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 977 return EX_NOHOST; 978 } 979 bcopy(hp->h_addr, 980 addr.sa.sa_data, 981 hp->h_length); 982 break; 983 } 984 addrno = 1; 985 } 986 987 /* 988 ** Determine the port number. 989 */ 990 991 if (port == 0) 992 { 993 register struct servent *sp = getservbyname("smtp", "tcp"); 994 995 if (sp == NULL) 996 { 997 if (LogLevel > 2) 998 sm_syslog(LOG_ERR, NOQID, 999 "makeconnection: service \"smtp\" unknown"); 1000 port = htons(25); 1001 } 1002 else 1003 port = sp->s_port; 1004 } 1005 1006 switch (addr.sa.sa_family) 1007 { 1008 #if NETINET 1009 case AF_INET: 1010 addr.sin.sin_port = port; 1011 addrlen = sizeof (struct sockaddr_in); 1012 break; 1013 #endif 1014 1015 #if NETISO 1016 case AF_ISO: 1017 /* assume two byte transport selector */ 1018 bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 1019 addrlen = sizeof (struct sockaddr_iso); 1020 break; 1021 #endif 1022 1023 default: 1024 syserr("Can't connect to address family %d", addr.sa.sa_family); 1025 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1026 return (EX_NOHOST); 1027 } 1028 1029 /* 1030 ** Try to actually open the connection. 1031 */ 1032 1033 #ifdef XLA 1034 /* if too many connections, don't bother trying */ 1035 if (!xla_noqueue_ok(host)) 1036 return EX_TEMPFAIL; 1037 #endif 1038 1039 firstconnect = TRUE; 1040 for (;;) 1041 { 1042 if (tTd(16, 1)) 1043 printf("makeconnection (%s [%s])\n", 1044 host, anynet_ntoa(&addr)); 1045 1046 /* save for logging */ 1047 CurHostAddr = addr; 1048 1049 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 1050 { 1051 int rport = IPPORT_RESERVED - 1; 1052 1053 s = rresvport(&rport); 1054 } 1055 else 1056 { 1057 s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 1058 } 1059 if (s < 0) 1060 { 1061 sav_errno = errno; 1062 syserr("makeconnection: cannot create socket"); 1063 #ifdef XLA 1064 xla_host_end(host); 1065 #endif 1066 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 1067 return EX_TEMPFAIL; 1068 } 1069 1070 #ifdef SO_SNDBUF 1071 if (TcpSndBufferSize > 0) 1072 { 1073 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 1074 (char *) &TcpSndBufferSize, 1075 sizeof(TcpSndBufferSize)) < 0) 1076 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 1077 } 1078 #endif 1079 1080 if (tTd(16, 1)) 1081 printf("makeconnection: fd=%d\n", s); 1082 1083 /* turn on network debugging? */ 1084 if (tTd(16, 101)) 1085 { 1086 int on = 1; 1087 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 1088 (char *)&on, sizeof on); 1089 } 1090 if (e->e_xfp != NULL) 1091 (void) fflush(e->e_xfp); /* for debugging */ 1092 errno = 0; /* for debugging */ 1093 1094 /* 1095 ** Linux seems to hang in connect for 90 minutes (!!!). 1096 ** Time out the connect to avoid this problem. 1097 */ 1098 1099 if (setjmp(CtxConnectTimeout) == 0) 1100 { 1101 int i; 1102 1103 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 1104 ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); 1105 else if (TimeOuts.to_connect != 0) 1106 ev = setevent(TimeOuts.to_connect, connecttimeout, 0); 1107 else 1108 ev = NULL; 1109 1110 #if _FFR_CONNECTONLYTO_OPTION 1111 /* for testing */ 1112 if (ConnectOnlyTo != 0) 1113 addr.sin.sin_addr.s_addr = ConnectOnlyTo; 1114 #endif 1115 i = connect(s, (struct sockaddr *) &addr, addrlen); 1116 sav_errno = errno; 1117 if (ev != NULL) 1118 clrevent(ev); 1119 if (i >= 0) 1120 break; 1121 } 1122 else 1123 sav_errno = errno; 1124 1125 /* if running demand-dialed connection, try again */ 1126 if (DialDelay > 0 && firstconnect) 1127 { 1128 if (tTd(16, 1)) 1129 printf("Connect failed (%s); trying again...\n", 1130 errstring(sav_errno)); 1131 firstconnect = FALSE; 1132 sleep(DialDelay); 1133 continue; 1134 } 1135 1136 /* couldn't connect.... figure out why */ 1137 (void) close(s); 1138 1139 if (LogLevel >= 14) 1140 sm_syslog(LOG_INFO, e->e_id, 1141 "makeconnection (%s [%s]) failed: %s", 1142 host, anynet_ntoa(&addr), 1143 errstring(sav_errno)); 1144 1145 if (hp != NULL && hp->h_addr_list[addrno] != NULL) 1146 { 1147 if (tTd(16, 1)) 1148 printf("Connect failed (%s); trying new address....\n", 1149 errstring(sav_errno)); 1150 switch (addr.sa.sa_family) 1151 { 1152 #if NETINET 1153 case AF_INET: 1154 bcopy(hp->h_addr_list[addrno++], 1155 &addr.sin.sin_addr, 1156 INADDRSZ); 1157 break; 1158 #endif 1159 1160 default: 1161 bcopy(hp->h_addr_list[addrno++], 1162 addr.sa.sa_data, 1163 hp->h_length); 1164 break; 1165 } 1166 continue; 1167 } 1168 1169 /* couldn't open connection */ 1170 #ifdef XLA 1171 xla_host_end(host); 1172 #endif 1173 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 1174 return EX_TEMPFAIL; 1175 } 1176 1177 /* connection ok, put it into canonical form */ 1178 if ((mci->mci_out = fdopen(s, "w")) == NULL || 1179 (s = dup(s)) < 0 || 1180 (mci->mci_in = fdopen(s, "r")) == NULL) 1181 { 1182 syserr("cannot open SMTP client channel, fd=%d", s); 1183 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 1184 return EX_TEMPFAIL; 1185 } 1186 1187 mci_setstat(mci, EX_OK, NULL, NULL); 1188 return (EX_OK); 1189 } 1190 /* 1191 ** MYHOSTNAME -- return the name of this host. 1192 ** 1193 ** Parameters: 1194 ** hostbuf -- a place to return the name of this host. 1195 ** size -- the size of hostbuf. 1196 ** 1197 ** Returns: 1198 ** A list of aliases for this host. 1199 ** 1200 ** Side Effects: 1201 ** Adds numeric codes to $=w. 1202 */ 1203 1204 struct hostent * 1205 myhostname(hostbuf, size) 1206 char hostbuf[]; 1207 int size; 1208 { 1209 register struct hostent *hp; 1210 1211 if (gethostname(hostbuf, size) < 0) 1212 { 1213 (void) strcpy(hostbuf, "localhost"); 1214 } 1215 hp = sm_gethostbyname(hostbuf); 1216 if (hp == NULL) 1217 return NULL; 1218 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 1219 { 1220 (void) strncpy(hostbuf, hp->h_name, size - 1); 1221 hostbuf[size - 1] = '\0'; 1222 } 1223 1224 /* 1225 ** If there is still no dot in the name, try looking for a 1226 ** dotted alias. 1227 */ 1228 1229 if (strchr(hostbuf, '.') == NULL) 1230 { 1231 char **ha; 1232 1233 for (ha = hp->h_aliases; *ha != NULL; ha++) 1234 { 1235 if (strchr(*ha, '.') != NULL) 1236 { 1237 (void) strncpy(hostbuf, *ha, size - 1); 1238 hostbuf[size - 1] = '\0'; 1239 break; 1240 } 1241 } 1242 } 1243 1244 /* 1245 ** If _still_ no dot, wait for a while and try again -- it is 1246 ** possible that some service is starting up. This can result 1247 ** in excessive delays if the system is badly configured, but 1248 ** there really isn't a way around that, particularly given that 1249 ** the config file hasn't been read at this point. 1250 ** All in all, a bit of a mess. 1251 */ 1252 1253 if (strchr(hostbuf, '.') == NULL && 1254 !getcanonname(hostbuf, size, TRUE)) 1255 { 1256 sm_syslog(LOG_CRIT, NOQID, 1257 "My unqualified host name (%s) unknown; sleeping for retry", 1258 hostbuf); 1259 message("My unqualified host name (%s) unknown; sleeping for retry", 1260 hostbuf); 1261 sleep(60); 1262 if (!getcanonname(hostbuf, size, TRUE)) 1263 { 1264 sm_syslog(LOG_ALERT, NOQID, 1265 "unable to qualify my own domain name (%s) -- using short name", 1266 hostbuf); 1267 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 1268 hostbuf); 1269 } 1270 } 1271 return (hp); 1272 } 1273 /* 1274 ** ADDRCMP -- compare two host addresses 1275 ** 1276 ** Parameters: 1277 ** hp -- hostent structure for the first address 1278 ** ha -- actual first address 1279 ** sa -- second address 1280 ** 1281 ** Returns: 1282 ** 0 -- if ha and sa match 1283 ** else -- they don't match 1284 */ 1285 1286 int 1287 addrcmp(hp, ha, sa) 1288 struct hostent *hp; 1289 char *ha; 1290 SOCKADDR *sa; 1291 { 1292 switch (sa->sa.sa_family) 1293 { 1294 case AF_INET: 1295 if (hp->h_addrtype == AF_INET) 1296 return bcmp(ha, (char *) &sa->sin.sin_addr, hp->h_length); 1297 break; 1298 1299 } 1300 return -1; 1301 } 1302 /* 1303 ** GETAUTHINFO -- get the real host name asociated with a file descriptor 1304 ** 1305 ** Uses RFC1413 protocol to try to get info from the other end. 1306 ** 1307 ** Parameters: 1308 ** fd -- the descriptor 1309 ** may_be_forged -- an outage that is set to TRUE if the 1310 ** forward lookup of RealHostName does not match 1311 ** RealHostAddr; set to FALSE if they do match. 1312 ** 1313 ** Returns: 1314 ** The user@host information associated with this descriptor. 1315 */ 1316 1317 static jmp_buf CtxAuthTimeout; 1318 1319 static void 1320 authtimeout() 1321 { 1322 longjmp(CtxAuthTimeout, 1); 1323 } 1324 1325 char * 1326 getauthinfo(fd, may_be_forged) 1327 int fd; 1328 bool *may_be_forged; 1329 { 1330 SOCKADDR_LEN_T falen; 1331 register char *volatile p = NULL; 1332 SOCKADDR la; 1333 SOCKADDR_LEN_T lalen; 1334 register struct servent *sp; 1335 volatile int s; 1336 int i = 0; 1337 EVENT *ev; 1338 int nleft; 1339 struct hostent *hp; 1340 char *ostype = NULL; 1341 char **ha; 1342 char ibuf[MAXNAME + 1]; 1343 static char hbuf[MAXNAME * 2 + 11]; 1344 1345 *may_be_forged = FALSE; 1346 falen = sizeof RealHostAddr; 1347 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 1348 falen <= 0 || RealHostAddr.sa.sa_family == 0) 1349 { 1350 if (i < 0 && errno != ENOTSOCK) 1351 return NULL; 1352 (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", 1353 RealUserName); 1354 if (tTd(9, 1)) 1355 printf("getauthinfo: %s\n", hbuf); 1356 return hbuf; 1357 } 1358 1359 if (RealHostName == NULL) 1360 { 1361 /* translate that to a host name */ 1362 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 1363 if (strlen(RealHostName) > MAXNAME) 1364 RealHostName[MAXNAME] = '\0'; 1365 } 1366 1367 /* cross check RealHostName with forward DNS lookup */ 1368 if (anynet_ntoa(&RealHostAddr)[0] == '[' || 1369 RealHostName[0] == '[') 1370 { 1371 /* 1372 ** address is not a socket or have an 1373 ** IP address with no forward lookup 1374 */ 1375 *may_be_forged = FALSE; 1376 } 1377 else 1378 { 1379 /* try to match the reverse against the forward lookup */ 1380 hp = sm_gethostbyname(RealHostName); 1381 1382 if (hp == NULL) 1383 *may_be_forged = TRUE; 1384 else 1385 { 1386 for (ha = hp->h_addr_list; *ha != NULL; ha++) 1387 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 1388 break; 1389 *may_be_forged = *ha == NULL; 1390 } 1391 } 1392 1393 if (TimeOuts.to_ident == 0) 1394 goto noident; 1395 1396 lalen = sizeof la; 1397 if (RealHostAddr.sa.sa_family != AF_INET || 1398 getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 || 1399 la.sa.sa_family != AF_INET) 1400 { 1401 /* no ident info */ 1402 goto noident; 1403 } 1404 1405 /* create ident query */ 1406 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 1407 ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port)); 1408 1409 /* create local address */ 1410 la.sin.sin_port = 0; 1411 1412 /* create foreign address */ 1413 sp = getservbyname("auth", "tcp"); 1414 if (sp != NULL) 1415 RealHostAddr.sin.sin_port = sp->s_port; 1416 else 1417 RealHostAddr.sin.sin_port = htons(113); 1418 1419 s = -1; 1420 if (setjmp(CtxAuthTimeout) != 0) 1421 { 1422 if (s >= 0) 1423 (void) close(s); 1424 goto noident; 1425 } 1426 1427 /* put a timeout around the whole thing */ 1428 ev = setevent(TimeOuts.to_ident, authtimeout, 0); 1429 1430 /* connect to foreign IDENT server using same address as SMTP socket */ 1431 s = socket(AF_INET, SOCK_STREAM, 0); 1432 if (s < 0) 1433 { 1434 clrevent(ev); 1435 goto noident; 1436 } 1437 if (bind(s, &la.sa, sizeof la.sin) < 0 || 1438 connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0) 1439 { 1440 goto closeident; 1441 } 1442 1443 if (tTd(9, 10)) 1444 printf("getauthinfo: sent %s", ibuf); 1445 1446 /* send query */ 1447 if (write(s, ibuf, strlen(ibuf)) < 0) 1448 goto closeident; 1449 1450 /* get result */ 1451 p = &ibuf[0]; 1452 nleft = sizeof ibuf - 1; 1453 while ((i = read(s, p, nleft)) > 0) 1454 { 1455 p += i; 1456 nleft -= i; 1457 *p = '\0'; 1458 if (strchr(ibuf, '\n') != NULL) 1459 break; 1460 } 1461 (void) close(s); 1462 clrevent(ev); 1463 if (i < 0 || p == &ibuf[0]) 1464 goto noident; 1465 1466 if (*--p == '\n' && *--p == '\r') 1467 p--; 1468 *++p = '\0'; 1469 1470 if (tTd(9, 3)) 1471 printf("getauthinfo: got %s\n", ibuf); 1472 1473 /* parse result */ 1474 p = strchr(ibuf, ':'); 1475 if (p == NULL) 1476 { 1477 /* malformed response */ 1478 goto noident; 1479 } 1480 while (isascii(*++p) && isspace(*p)) 1481 continue; 1482 if (strncasecmp(p, "userid", 6) != 0) 1483 { 1484 /* presumably an error string */ 1485 goto noident; 1486 } 1487 p += 6; 1488 while (isascii(*p) && isspace(*p)) 1489 p++; 1490 if (*p++ != ':') 1491 { 1492 /* either useridxx or malformed response */ 1493 goto noident; 1494 } 1495 1496 /* p now points to the OSTYPE field */ 1497 while (isascii(*p) && isspace(*p)) 1498 p++; 1499 ostype = p; 1500 p = strchr(p, ':'); 1501 if (p == NULL) 1502 { 1503 /* malformed response */ 1504 goto noident; 1505 } 1506 else 1507 { 1508 char *charset; 1509 1510 *p = '\0'; 1511 charset = strchr(ostype, ','); 1512 if (charset != NULL) 1513 *charset = '\0'; 1514 } 1515 1516 /* 1413 says don't do this -- but it's broken otherwise */ 1517 while (isascii(*++p) && isspace(*p)) 1518 continue; 1519 1520 /* p now points to the authenticated name -- copy carefully */ 1521 if (strncasecmp(ostype, "other", 5) == 0 && 1522 (ostype[5] == ' ' || ostype[5] == '\0')) 1523 { 1524 snprintf(hbuf, sizeof hbuf, "IDENT:"); 1525 cleanstrcpy(&hbuf[6], p, MAXNAME); 1526 } 1527 else 1528 cleanstrcpy(hbuf, p, MAXNAME); 1529 i = strlen(hbuf); 1530 snprintf(&hbuf[i], sizeof hbuf - i, "@%s", 1531 RealHostName == NULL ? "localhost" : RealHostName); 1532 goto postident; 1533 1534 closeident: 1535 (void) close(s); 1536 clrevent(ev); 1537 1538 noident: 1539 if (RealHostName == NULL) 1540 { 1541 if (tTd(9, 1)) 1542 printf("getauthinfo: NULL\n"); 1543 return NULL; 1544 } 1545 snprintf(hbuf, sizeof hbuf, "%s", RealHostName); 1546 1547 postident: 1548 #if IP_SRCROUTE 1549 # ifndef GET_IPOPT_DST 1550 # define GET_IPOPT_DST(dst) (dst) 1551 # endif 1552 /* 1553 ** Extract IP source routing information. 1554 ** 1555 ** Format of output for a connection from site a through b 1556 ** through c to d: 1557 ** loose: @site-c@site-b:site-a 1558 ** strict: !@site-c@site-b:site-a 1559 ** 1560 ** o - pointer within ipopt_list structure. 1561 ** q - pointer within ls/ss rr route data 1562 ** p - pointer to hbuf 1563 */ 1564 1565 if (RealHostAddr.sa.sa_family == AF_INET) 1566 { 1567 SOCKOPT_LEN_T ipoptlen; 1568 int j; 1569 u_char *q; 1570 u_char *o; 1571 int l; 1572 struct in_addr addr; 1573 struct ipoption ipopt; 1574 1575 ipoptlen = sizeof ipopt; 1576 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 1577 (char *) &ipopt, &ipoptlen) < 0) 1578 goto noipsr; 1579 if (ipoptlen == 0) 1580 goto noipsr; 1581 o = (u_char *) ipopt.ipopt_list; 1582 while (o != NULL && o < (u_char *) &ipopt + ipoptlen) 1583 { 1584 switch (*o) 1585 { 1586 case IPOPT_EOL: 1587 o = NULL; 1588 break; 1589 1590 case IPOPT_NOP: 1591 o++; 1592 break; 1593 1594 case IPOPT_SSRR: 1595 case IPOPT_LSRR: 1596 /* 1597 ** Source routing. 1598 ** o[0] is the option type (loose/strict). 1599 ** o[1] is the length of this option, 1600 ** including option type and 1601 ** length. 1602 ** o[2] is the pointer into the route 1603 ** data. 1604 ** o[3] begins the route data. 1605 */ 1606 1607 p = &hbuf[strlen(hbuf)]; 1608 l = sizeof hbuf - (hbuf - p) - 6; 1609 snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", 1610 *o == IPOPT_SSRR ? "!" : "", 1611 l > 240 ? 120 : l / 2, 1612 inet_ntoa(GET_IPOPT_DST(ipopt.ipopt_dst))); 1613 i = strlen(p); 1614 p += i; 1615 l -= strlen(p); 1616 1617 j = o[1] / sizeof(struct in_addr) - 1; 1618 1619 /* q skips length and router pointer to data */ 1620 q = &o[3]; 1621 for ( ; j >= 0; j--) 1622 { 1623 memcpy(&addr, q, sizeof(addr)); 1624 snprintf(p, SPACELEFT(hbuf, p), 1625 "%c%.*s", 1626 j != 0 ? '@' : ':', 1627 l > 240 ? 120 : 1628 j == 0 ? l : l / 2, 1629 inet_ntoa(addr)); 1630 i = strlen(p); 1631 p += i; 1632 l -= i + 1; 1633 q += sizeof(struct in_addr); 1634 } 1635 o += o[1]; 1636 break; 1637 1638 default: 1639 /* Skip over option */ 1640 o += o[1]; 1641 break; 1642 } 1643 } 1644 snprintf(p, SPACELEFT(hbuf, p), "]"); 1645 goto postipsr; 1646 } 1647 1648 noipsr: 1649 #endif 1650 if (RealHostName != NULL && RealHostName[0] != '[') 1651 { 1652 p = &hbuf[strlen(hbuf)]; 1653 (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 1654 anynet_ntoa(&RealHostAddr)); 1655 } 1656 if (*may_be_forged) 1657 { 1658 p = &hbuf[strlen(hbuf)]; 1659 (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); 1660 } 1661 1662 #if IP_SRCROUTE 1663 postipsr: 1664 #endif 1665 if (tTd(9, 1)) 1666 printf("getauthinfo: %s\n", hbuf); 1667 return hbuf; 1668 } 1669 /* 1670 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 1671 ** 1672 ** Parameters: 1673 ** map -- a pointer to this map. 1674 ** name -- the (presumably unqualified) hostname. 1675 ** av -- unused -- for compatibility with other mapping 1676 ** functions. 1677 ** statp -- an exit status (out parameter) -- set to 1678 ** EX_TEMPFAIL if the name server is unavailable. 1679 ** 1680 ** Returns: 1681 ** The mapping, if found. 1682 ** NULL if no mapping found. 1683 ** 1684 ** Side Effects: 1685 ** Looks up the host specified in hbuf. If it is not 1686 ** the canonical name for that host, return the canonical 1687 ** name (unless MF_MATCHONLY is set, which will cause the 1688 ** status only to be returned). 1689 */ 1690 1691 char * 1692 host_map_lookup(map, name, av, statp) 1693 MAP *map; 1694 char *name; 1695 char **av; 1696 int *statp; 1697 { 1698 register struct hostent *hp; 1699 struct in_addr in_addr; 1700 char *cp; 1701 register STAB *s; 1702 char hbuf[MAXNAME + 1]; 1703 1704 /* 1705 ** See if we have already looked up this name. If so, just 1706 ** return it. 1707 */ 1708 1709 s = stab(name, ST_NAMECANON, ST_ENTER); 1710 if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 1711 { 1712 if (tTd(9, 1)) 1713 printf("host_map_lookup(%s) => CACHE %s\n", 1714 name, 1715 s->s_namecanon.nc_cname == NULL 1716 ? "NULL" 1717 : s->s_namecanon.nc_cname); 1718 errno = s->s_namecanon.nc_errno; 1719 #if NAMED_BIND 1720 h_errno = s->s_namecanon.nc_herrno; 1721 #endif 1722 *statp = s->s_namecanon.nc_stat; 1723 if (*statp == EX_TEMPFAIL) 1724 { 1725 CurEnv->e_status = "4.4.3"; 1726 message("851 %s: Name server timeout", 1727 shortenstring(name, 33)); 1728 } 1729 if (*statp != EX_OK) 1730 return NULL; 1731 if (s->s_namecanon.nc_cname == NULL) 1732 { 1733 syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d", 1734 name, 1735 s->s_namecanon.nc_errno, 1736 s->s_namecanon.nc_herrno); 1737 return NULL; 1738 } 1739 if (bitset(MF_MATCHONLY, map->map_mflags)) 1740 cp = map_rewrite(map, name, strlen(name), NULL); 1741 else 1742 cp = map_rewrite(map, 1743 s->s_namecanon.nc_cname, 1744 strlen(s->s_namecanon.nc_cname), 1745 av); 1746 return cp; 1747 } 1748 1749 /* 1750 ** If we are running without a regular network connection (usually 1751 ** dial-on-demand) and we are just queueing, we want to avoid DNS 1752 ** lookups because those could try to connect to a server. 1753 */ 1754 1755 if (CurEnv->e_sendmode == SM_DEFER) 1756 { 1757 if (tTd(9, 1)) 1758 printf("host_map_lookup(%s) => DEFERRED\n", name); 1759 *statp = EX_TEMPFAIL; 1760 return NULL; 1761 } 1762 1763 /* 1764 ** If first character is a bracket, then it is an address 1765 ** lookup. Address is copied into a temporary buffer to 1766 ** strip the brackets and to preserve name if address is 1767 ** unknown. 1768 */ 1769 1770 if (*name != '[') 1771 { 1772 if (tTd(9, 1)) 1773 printf("host_map_lookup(%s) => ", name); 1774 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 1775 snprintf(hbuf, sizeof hbuf, "%s", name); 1776 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) 1777 { 1778 if (tTd(9, 1)) 1779 printf("%s\n", hbuf); 1780 s->s_namecanon.nc_stat = EX_OK; 1781 s->s_namecanon.nc_cname = newstr(hbuf); 1782 if (bitset(MF_MATCHONLY, map->map_mflags)) 1783 cp = map_rewrite(map, name, strlen(name), NULL); 1784 else 1785 cp = map_rewrite(map, hbuf, strlen(hbuf), av); 1786 return cp; 1787 } 1788 else 1789 { 1790 s->s_namecanon.nc_errno = errno; 1791 #if NAMED_BIND 1792 s->s_namecanon.nc_herrno = h_errno; 1793 if (tTd(9, 1)) 1794 printf("FAIL (%d)\n", h_errno); 1795 switch (h_errno) 1796 { 1797 case TRY_AGAIN: 1798 if (UseNameServer) 1799 { 1800 CurEnv->e_status = "4.4.3"; 1801 message("851 %s: Name server timeout", 1802 shortenstring(name, 33)); 1803 } 1804 *statp = EX_TEMPFAIL; 1805 break; 1806 1807 case HOST_NOT_FOUND: 1808 case NO_DATA: 1809 *statp = EX_NOHOST; 1810 break; 1811 1812 case NO_RECOVERY: 1813 *statp = EX_SOFTWARE; 1814 break; 1815 1816 default: 1817 *statp = EX_UNAVAILABLE; 1818 break; 1819 } 1820 #else 1821 if (tTd(9, 1)) 1822 printf("FAIL\n"); 1823 *statp = EX_NOHOST; 1824 #endif 1825 s->s_namecanon.nc_stat = *statp; 1826 return NULL; 1827 } 1828 } 1829 if ((cp = strchr(name, ']')) == NULL) 1830 return (NULL); 1831 *cp = '\0'; 1832 in_addr.s_addr = inet_addr(&name[1]); 1833 *cp = ']'; 1834 1835 /* nope -- ask the name server */ 1836 hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); 1837 s->s_namecanon.nc_errno = errno; 1838 #if NAMED_BIND 1839 s->s_namecanon.nc_herrno = h_errno; 1840 #endif 1841 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 1842 if (hp == NULL) 1843 { 1844 s->s_namecanon.nc_stat = *statp = EX_NOHOST; 1845 return (NULL); 1846 } 1847 1848 /* found a match -- copy out */ 1849 hp->h_name = denlstring((char *) hp->h_name, TRUE, TRUE); 1850 s->s_namecanon.nc_stat = *statp = EX_OK; 1851 s->s_namecanon.nc_cname = newstr(hp->h_name); 1852 if (bitset(MF_MATCHONLY, map->map_mflags)) 1853 cp = map_rewrite(map, name, strlen(name), NULL); 1854 else 1855 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); 1856 return cp; 1857 } 1858 1859 # else /* DAEMON */ 1860 /* code for systems without sophisticated networking */ 1861 1862 /* 1863 ** MYHOSTNAME -- stub version for case of no daemon code. 1864 ** 1865 ** Can't convert to upper case here because might be a UUCP name. 1866 ** 1867 ** Mark, you can change this to be anything you want...... 1868 */ 1869 1870 char ** 1871 myhostname(hostbuf, size) 1872 char hostbuf[]; 1873 int size; 1874 { 1875 register FILE *f; 1876 1877 hostbuf[0] = '\0'; 1878 f = fopen("/usr/include/whoami", "r"); 1879 if (f != NULL) 1880 { 1881 (void) fgets(hostbuf, size, f); 1882 fixcrlf(hostbuf, TRUE); 1883 (void) fclose(f); 1884 } 1885 return (NULL); 1886 } 1887 /* 1888 ** GETAUTHINFO -- get the real host name asociated with a file descriptor 1889 ** 1890 ** Parameters: 1891 ** fd -- the descriptor 1892 ** may_be_forged -- an outage that is set to TRUE if the 1893 ** forward lookup of RealHostName does not match 1894 ** RealHostAddr; set to FALSE if they do match. 1895 ** 1896 ** Returns: 1897 ** The host name associated with this descriptor, if it can 1898 ** be determined. 1899 ** NULL otherwise. 1900 ** 1901 ** Side Effects: 1902 ** none 1903 */ 1904 1905 char * 1906 getauthinfo(fd, may_be_forged) 1907 int fd; 1908 bool *may_be_forged; 1909 { 1910 *may_be_forged = FALSE; 1911 return NULL; 1912 } 1913 /* 1914 ** MAPHOSTNAME -- turn a hostname into canonical form 1915 ** 1916 ** Parameters: 1917 ** map -- a pointer to the database map. 1918 ** name -- a buffer containing a hostname. 1919 ** avp -- a pointer to a (cf file defined) argument vector. 1920 ** statp -- an exit status (out parameter). 1921 ** 1922 ** Returns: 1923 ** mapped host name 1924 ** FALSE otherwise. 1925 ** 1926 ** Side Effects: 1927 ** Looks up the host specified in name. If it is not 1928 ** the canonical name for that host, replace it with 1929 ** the canonical name. If the name is unknown, or it 1930 ** is already the canonical name, leave it unchanged. 1931 */ 1932 1933 /*ARGSUSED*/ 1934 char * 1935 host_map_lookup(map, name, avp, statp) 1936 MAP *map; 1937 char *name; 1938 char **avp; 1939 char *statp; 1940 { 1941 register struct hostent *hp; 1942 char *cp; 1943 1944 hp = sm_gethostbyname(name); 1945 if (hp == NULL) 1946 { 1947 *statp = EX_NOHOST; 1948 return NULL; 1949 } 1950 if (bitset(MF_MATCHONLY, map->map_mflags)) 1951 cp = map_rewrite(map, name, strlen(name), NULL); 1952 else 1953 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); 1954 return cp; 1955 } 1956 1957 #endif /* DAEMON */ 1958 /* 1959 ** HOST_MAP_INIT -- initialize host class structures 1960 */ 1961 1962 bool 1963 host_map_init(map, args) 1964 MAP *map; 1965 char *args; 1966 { 1967 register char *p = args; 1968 1969 for (;;) 1970 { 1971 while (isascii(*p) && isspace(*p)) 1972 p++; 1973 if (*p != '-') 1974 break; 1975 switch (*++p) 1976 { 1977 case 'a': 1978 map->map_app = ++p; 1979 break; 1980 1981 case 'T': 1982 map->map_tapp = ++p; 1983 break; 1984 1985 case 'm': 1986 map->map_mflags |= MF_MATCHONLY; 1987 break; 1988 1989 case 't': 1990 map->map_mflags |= MF_NODEFER; 1991 break; 1992 } 1993 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 1994 p++; 1995 if (*p != '\0') 1996 *p++ = '\0'; 1997 } 1998 if (map->map_app != NULL) 1999 map->map_app = newstr(map->map_app); 2000 if (map->map_tapp != NULL) 2001 map->map_tapp = newstr(map->map_tapp); 2002 return TRUE; 2003 } 2004 /* 2005 ** ANYNET_NTOA -- convert a network address to printable form. 2006 ** 2007 ** Parameters: 2008 ** sap -- a pointer to a sockaddr structure. 2009 ** 2010 ** Returns: 2011 ** A printable version of that sockaddr. 2012 */ 2013 2014 #ifdef USE_SOCK_STREAM 2015 2016 #if NETLINK 2017 # include <net/if_dl.h> 2018 #endif 2019 2020 char * 2021 anynet_ntoa(sap) 2022 register SOCKADDR *sap; 2023 { 2024 register char *bp; 2025 register char *ap; 2026 int l; 2027 static char buf[100]; 2028 2029 /* check for null/zero family */ 2030 if (sap == NULL) 2031 return "NULLADDR"; 2032 if (sap->sa.sa_family == 0) 2033 return "0"; 2034 2035 switch (sap->sa.sa_family) 2036 { 2037 #if NETUNIX 2038 case AF_UNIX: 2039 if (sap->sunix.sun_path[0] != '\0') 2040 snprintf(buf, sizeof buf, "[UNIX: %.64s]", 2041 sap->sunix.sun_path); 2042 else 2043 snprintf(buf, sizeof buf, "[UNIX: localhost]"); 2044 return buf; 2045 #endif 2046 2047 #if NETINET 2048 case AF_INET: 2049 return inet_ntoa(sap->sin.sin_addr); 2050 #endif 2051 2052 #if NETLINK 2053 case AF_LINK: 2054 snprintf(buf, sizeof buf, "[LINK: %s]", 2055 link_ntoa((struct sockaddr_dl *) &sap->sa)); 2056 return buf; 2057 #endif 2058 default: 2059 /* this case is needed when nothing is #defined */ 2060 /* in order to keep the switch syntactically correct */ 2061 break; 2062 } 2063 2064 /* unknown family -- just dump bytes */ 2065 (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 2066 bp = &buf[strlen(buf)]; 2067 ap = sap->sa.sa_data; 2068 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 2069 { 2070 (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377); 2071 bp += 3; 2072 } 2073 *--bp = '\0'; 2074 return buf; 2075 } 2076 /* 2077 ** HOSTNAMEBYANYADDR -- return name of host based on address 2078 ** 2079 ** Parameters: 2080 ** sap -- SOCKADDR pointer 2081 ** 2082 ** Returns: 2083 ** text representation of host name. 2084 ** 2085 ** Side Effects: 2086 ** none. 2087 */ 2088 2089 char * 2090 hostnamebyanyaddr(sap) 2091 register SOCKADDR *sap; 2092 { 2093 register struct hostent *hp; 2094 int saveretry; 2095 2096 #if NAMED_BIND 2097 /* shorten name server timeout to avoid higher level timeouts */ 2098 saveretry = _res.retry; 2099 _res.retry = 3; 2100 #endif /* NAMED_BIND */ 2101 2102 switch (sap->sa.sa_family) 2103 { 2104 #if NETINET 2105 case AF_INET: 2106 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 2107 INADDRSZ, 2108 AF_INET); 2109 break; 2110 #endif 2111 2112 #if NETISO 2113 case AF_ISO: 2114 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 2115 sizeof sap->siso.siso_addr, 2116 AF_ISO); 2117 break; 2118 #endif 2119 2120 #if NETUNIX 2121 case AF_UNIX: 2122 hp = NULL; 2123 break; 2124 #endif 2125 2126 default: 2127 hp = sm_gethostbyaddr(sap->sa.sa_data, 2128 sizeof sap->sa.sa_data, 2129 sap->sa.sa_family); 2130 break; 2131 } 2132 2133 #if NAMED_BIND 2134 _res.retry = saveretry; 2135 #endif /* NAMED_BIND */ 2136 2137 if (hp != NULL && hp->h_name[0] != '[' && 2138 inet_addr(hp->h_name) == INADDR_NONE) 2139 return denlstring((char *) hp->h_name, TRUE, TRUE); 2140 #if NETUNIX 2141 else if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 2142 return "localhost"; 2143 #endif 2144 else 2145 { 2146 /* produce a dotted quad */ 2147 static char buf[203]; 2148 2149 (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap)); 2150 return buf; 2151 } 2152 } 2153 2154 #endif /* SOCK_STREAM */ 2155