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