1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #include <errno.h> 10 #include <signal.h> 11 #include "sendmail.h" 12 13 #ifndef lint 14 #ifdef DAEMON 15 static char sccsid[] = "@(#)daemon.c 6.25 (Berkeley) 03/24/93 (with daemon mode)"; 16 #else 17 static char sccsid[] = "@(#)daemon.c 6.25 (Berkeley) 03/24/93 (without daemon mode)"; 18 #endif 19 #endif /* not lint */ 20 21 #ifdef DAEMON 22 23 # include <netdb.h> 24 # include <sys/wait.h> 25 # include <sys/time.h> 26 27 #ifdef NETISO 28 # include <netiso/iso.h> 29 #endif 30 31 /* 32 ** DAEMON.C -- routines to use when running as a daemon. 33 ** 34 ** This entire file is highly dependent on the 4.2 BSD 35 ** interprocess communication primitives. No attempt has 36 ** been made to make this file portable to Version 7, 37 ** Version 6, MPX files, etc. If you should try such a 38 ** thing yourself, I recommend chucking the entire file 39 ** and starting from scratch. Basic semantics are: 40 ** 41 ** getrequests() 42 ** Opens a port and initiates a connection. 43 ** Returns in a child. Must set InChannel and 44 ** OutChannel appropriately. 45 ** clrdaemon() 46 ** Close any open files associated with getting 47 ** the connection; this is used when running the queue, 48 ** etc., to avoid having extra file descriptors during 49 ** the queue run and to avoid confusing the network 50 ** code (if it cares). 51 ** makeconnection(host, port, outfile, infile, usesecureport) 52 ** Make a connection to the named host on the given 53 ** port. Set *outfile and *infile to the files 54 ** appropriate for communication. Returns zero on 55 ** success, else an exit status describing the 56 ** error. 57 ** maphostname(map, hbuf, hbufsiz, avp) 58 ** Convert the entry in hbuf into a canonical form. 59 */ 60 61 extern char *anynet_ntoa(); 62 /* 63 ** GETREQUESTS -- open mail IPC port and get requests. 64 ** 65 ** Parameters: 66 ** none. 67 ** 68 ** Returns: 69 ** none. 70 ** 71 ** Side Effects: 72 ** Waits until some interesting activity occurs. When 73 ** it does, a child is created to process it, and the 74 ** parent waits for completion. Return from this 75 ** routine is always in the child. The file pointers 76 ** "InChannel" and "OutChannel" should be set to point 77 ** to the communication channel. 78 */ 79 80 int DaemonSocket = -1; /* fd describing socket */ 81 82 getrequests() 83 { 84 int t; 85 register struct servent *sp; 86 int on = 1; 87 bool refusingconnections = TRUE; 88 FILE *pidf; 89 SOCKADDR srvraddr; 90 extern void reapchild(); 91 92 /* 93 ** Set up the address for the mailer. 94 */ 95 96 sp = getservbyname("smtp", "tcp"); 97 if (sp == NULL) 98 { 99 syserr("554 server \"smtp\" unknown"); 100 goto severe; 101 } 102 srvraddr.sin.sin_family = AF_INET; 103 srvraddr.sin.sin_addr.s_addr = INADDR_ANY; 104 srvraddr.sin.sin_port = sp->s_port; 105 106 /* 107 ** Try to actually open the connection. 108 */ 109 110 if (tTd(15, 1)) 111 printf("getrequests: port 0x%x\n", srvraddr.sin.sin_port); 112 113 /* get a socket for the SMTP connection */ 114 DaemonSocket = socket(AF_INET, SOCK_STREAM, 0); 115 if (DaemonSocket < 0) 116 { 117 /* probably another daemon already */ 118 syserr("getrequests: can't create socket"); 119 severe: 120 # ifdef LOG 121 if (LogLevel > 0) 122 syslog(LOG_ALERT, "problem creating SMTP socket"); 123 # endif /* LOG */ 124 finis(); 125 } 126 127 /* turn on network debugging? */ 128 if (tTd(15, 101)) 129 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on); 130 131 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on); 132 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on); 133 134 if (bind(DaemonSocket, &srvraddr.sa, sizeof srvraddr) < 0) 135 { 136 syserr("getrequests: cannot bind"); 137 (void) close(DaemonSocket); 138 goto severe; 139 } 140 141 (void) signal(SIGCHLD, reapchild); 142 143 /* write the pid to the log file for posterity */ 144 pidf = fopen(PidFile, "w"); 145 if (pidf != NULL) 146 { 147 fprintf(pidf, "%d\n", getpid()); 148 fclose(pidf); 149 } 150 151 152 if (tTd(15, 1)) 153 printf("getrequests: %d\n", DaemonSocket); 154 155 for (;;) 156 { 157 register int pid; 158 auto int lotherend; 159 extern bool refuseconnections(); 160 161 /* see if we are rejecting connections */ 162 CurrentLA = getla(); 163 if (refuseconnections()) 164 { 165 if (!refusingconnections) 166 { 167 /* don't queue so peer will fail quickly */ 168 (void) listen(DaemonSocket, 0); 169 refusingconnections = TRUE; 170 } 171 setproctitle("rejecting connections: load average: %d", 172 CurrentLA); 173 sleep(5); 174 continue; 175 } 176 177 if (refusingconnections) 178 { 179 /* start listening again */ 180 if (listen(DaemonSocket, 10) < 0) 181 { 182 syserr("getrequests: cannot listen"); 183 (void) close(DaemonSocket); 184 goto severe; 185 } 186 setproctitle("accepting connections"); 187 refusingconnections = FALSE; 188 } 189 190 /* wait for a connection */ 191 do 192 { 193 errno = 0; 194 lotherend = sizeof RealHostAddr; 195 t = accept(DaemonSocket, 196 (struct sockaddr *)&RealHostAddr, &lotherend); 197 } while (t < 0 && errno == EINTR); 198 if (t < 0) 199 { 200 syserr("getrequests: accept"); 201 sleep(5); 202 continue; 203 } 204 205 /* 206 ** Create a subprocess to process the mail. 207 */ 208 209 if (tTd(15, 2)) 210 printf("getrequests: forking (fd = %d)\n", t); 211 212 pid = fork(); 213 if (pid < 0) 214 { 215 syserr("daemon: cannot fork"); 216 sleep(10); 217 (void) close(t); 218 continue; 219 } 220 221 if (pid == 0) 222 { 223 extern struct hostent *gethostbyaddr(); 224 register struct hostent *hp; 225 char buf[MAXNAME]; 226 227 /* 228 ** CHILD -- return to caller. 229 ** Collect verified idea of sending host. 230 ** Verify calling user id if possible here. 231 */ 232 233 (void) signal(SIGCHLD, SIG_DFL); 234 235 /* determine host name */ 236 switch (RealHostAddr.sa.sa_family) 237 { 238 #ifdef NETINET 239 case AF_INET: 240 hp = gethostbyaddr((char *) &RealHostAddr.sin.sin_addr, 241 sizeof RealHostAddr.sin.sin_addr, 242 AF_INET); 243 break; 244 #endif 245 246 #ifdef NETISO 247 case AF_ISO: 248 hp = gethostbyaddr((char *) &RealHostAddr.siso.siso_addr, 249 sizeof RealHostAddr.siso.siso_addr, 250 AF_ISO); 251 break; 252 #endif 253 254 default: 255 hp = gethostbyaddr(RealHostAddr.sa.sa_data, 256 sizeof RealHostAddr.sa.sa_data, 257 RealHostAddr.sa.sa_family); 258 break; 259 } 260 261 if (hp != NULL) 262 (void) strcpy(buf, hp->h_name); 263 else 264 { 265 /* produce a dotted quad */ 266 (void) sprintf(buf, "[%s]", 267 anynet_ntoa(&RealHostAddr)); 268 } 269 270 #ifdef LOG 271 if (LogLevel > 10) 272 { 273 /* log connection information */ 274 syslog(LOG_INFO, "connect from %s (%s)", 275 buf, anynet_ntoa(&RealHostAddr)); 276 } 277 #endif 278 279 /* should we check for illegal connection here? XXX */ 280 281 RealHostName = newstr(buf); 282 283 (void) close(DaemonSocket); 284 InChannel = fdopen(t, "r"); 285 OutChannel = fdopen(dup(t), "w"); 286 if (tTd(15, 2)) 287 printf("getreq: returning\n"); 288 return; 289 } 290 291 /* close the port so that others will hang (for a while) */ 292 (void) close(t); 293 } 294 /*NOTREACHED*/ 295 } 296 /* 297 ** CLRDAEMON -- reset the daemon connection 298 ** 299 ** Parameters: 300 ** none. 301 ** 302 ** Returns: 303 ** none. 304 ** 305 ** Side Effects: 306 ** releases any resources used by the passive daemon. 307 */ 308 309 clrdaemon() 310 { 311 if (DaemonSocket >= 0) 312 (void) close(DaemonSocket); 313 DaemonSocket = -1; 314 } 315 /* 316 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 317 ** 318 ** Parameters: 319 ** host -- the name of the host. 320 ** port -- the port number to connect to. 321 ** mci -- a pointer to the mail connection information 322 ** structure to be filled in. 323 ** usesecureport -- if set, use a low numbered (reserved) 324 ** port to provide some rudimentary authentication. 325 ** 326 ** Returns: 327 ** An exit code telling whether the connection could be 328 ** made and if not why not. 329 ** 330 ** Side Effects: 331 ** none. 332 */ 333 334 SOCKADDR CurHostAddr; /* address of current host */ 335 336 int 337 makeconnection(host, port, mci, usesecureport) 338 char *host; 339 u_short port; 340 register MCI *mci; 341 bool usesecureport; 342 { 343 register int i, s; 344 register struct hostent *hp = (struct hostent *)NULL; 345 SOCKADDR addr; 346 int sav_errno; 347 int addrlen; 348 #ifdef NAMED_BIND 349 extern int h_errno; 350 #endif 351 352 /* 353 ** Set up the address for the mailer. 354 ** Accept "[a.b.c.d]" syntax for host name. 355 */ 356 357 #ifdef NAMED_BIND 358 h_errno = 0; 359 #endif 360 errno = 0; 361 362 if (host[0] == '[') 363 { 364 long hid; 365 register char *p = strchr(host, ']'); 366 367 if (p != NULL) 368 { 369 *p = '\0'; 370 hid = inet_addr(&host[1]); 371 if (hid == -1) 372 { 373 /* try it as a host name (avoid MX lookup) */ 374 hp = gethostbyname(&host[1]); 375 *p = ']'; 376 goto gothostent; 377 } 378 *p = ']'; 379 } 380 if (p == NULL) 381 { 382 usrerr("553 Invalid numeric domain spec \"%s\"", host); 383 return (EX_NOHOST); 384 } 385 addr.sin.sin_family = AF_INET; 386 addr.sin.sin_addr.s_addr = hid; 387 } 388 else 389 { 390 hp = gethostbyname(host); 391 gothostent: 392 if (hp == NULL) 393 { 394 #ifdef NAMED_BIND 395 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 396 return (EX_TEMPFAIL); 397 398 /* if name server is specified, assume temp fail */ 399 if (errno == ECONNREFUSED && UseNameServer) 400 return (EX_TEMPFAIL); 401 #endif 402 return (EX_NOHOST); 403 } 404 addr.sa.sa_family = hp->h_addrtype; 405 switch (hp->h_addrtype) 406 { 407 #ifdef NETINET 408 case AF_INET: 409 bcopy(hp->h_addr, 410 &addr.sin.sin_addr, 411 hp->h_length); 412 break; 413 #endif 414 415 default: 416 bcopy(hp->h_addr, 417 addr.sa.sa_data, 418 hp->h_length); 419 break; 420 } 421 i = 1; 422 } 423 424 /* 425 ** Determine the port number. 426 */ 427 428 if (port != 0) 429 port = htons(port); 430 else 431 { 432 register struct servent *sp = getservbyname("smtp", "tcp"); 433 434 if (sp == NULL) 435 { 436 syserr("554 makeconnection: server \"smtp\" unknown"); 437 return (EX_OSERR); 438 } 439 port = sp->s_port; 440 } 441 442 switch (addr.sa.sa_family) 443 { 444 case AF_INET: 445 addr.sin.sin_port = port; 446 addrlen = sizeof (struct sockaddr_in); 447 break; 448 449 #ifdef NETISO 450 case AF_ISO: 451 /* assume two byte transport selector */ 452 bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 453 addrlen = sizeof (struct sockaddr_iso); 454 break; 455 #endif 456 457 default: 458 syserr("Can't connect to address family %d", addr.sa.sa_family); 459 return (EX_NOHOST); 460 } 461 462 /* 463 ** Try to actually open the connection. 464 */ 465 466 for (;;) 467 { 468 if (tTd(16, 1)) 469 printf("makeconnection (%s [%s])\n", 470 host, anynet_ntoa(&addr)); 471 472 /* save for logging */ 473 CurHostAddr = addr; 474 475 if (usesecureport) 476 { 477 int rport = IPPORT_RESERVED - 1; 478 479 s = rresvport(&rport); 480 } 481 else 482 { 483 s = socket(AF_INET, SOCK_STREAM, 0); 484 } 485 if (s < 0) 486 { 487 sav_errno = errno; 488 syserr("makeconnection: no socket"); 489 goto failure; 490 } 491 492 if (tTd(16, 1)) 493 printf("makeconnection: fd=%d\n", s); 494 495 /* turn on network debugging? */ 496 if (tTd(16, 101)) 497 { 498 int on = 1; 499 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 500 (char *)&on, sizeof on); 501 } 502 if (CurEnv->e_xfp != NULL) 503 (void) fflush(CurEnv->e_xfp); /* for debugging */ 504 errno = 0; /* for debugging */ 505 if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 506 break; 507 508 /* couldn't connect.... figure out why */ 509 sav_errno = errno; 510 (void) close(s); 511 if (hp && hp->h_addr_list[i]) 512 { 513 extern char *errstring(); 514 515 if (tTd(16, 1)) 516 printf("Connect failed (%s); trying new address....\n", 517 errstring(sav_errno)); 518 switch (addr.sa.sa_family) 519 { 520 #ifdef NETINET 521 case AF_INET: 522 bcopy(hp->h_addr_list[i++], 523 &addr.sin.sin_addr, 524 hp->h_length); 525 break; 526 #endif 527 528 default: 529 bcopy(hp->h_addr_list[i++], 530 addr.sa.sa_data, 531 hp->h_length); 532 break; 533 } 534 continue; 535 } 536 537 /* failure, decide if temporary or not */ 538 failure: 539 if (transienterror(sav_errno)) 540 return EX_TEMPFAIL; 541 else 542 { 543 extern char *errstring(); 544 545 message("%s", errstring(sav_errno)); 546 return (EX_UNAVAILABLE); 547 } 548 } 549 550 /* connection ok, put it into canonical form */ 551 mci->mci_out = fdopen(s, "w"); 552 mci->mci_in = fdopen(dup(s), "r"); 553 554 return (EX_OK); 555 } 556 /* 557 ** MYHOSTNAME -- return the name of this host. 558 ** 559 ** Parameters: 560 ** hostbuf -- a place to return the name of this host. 561 ** size -- the size of hostbuf. 562 ** 563 ** Returns: 564 ** A list of aliases for this host. 565 ** 566 ** Side Effects: 567 ** Sets the MyIpAddrs buffer to a list of my IP addresses. 568 */ 569 570 struct in_addr MyIpAddrs[MAXIPADDR + 1]; 571 572 char ** 573 myhostname(hostbuf, size) 574 char hostbuf[]; 575 int size; 576 { 577 register struct hostent *hp; 578 extern struct hostent *gethostbyname(); 579 580 if (gethostname(hostbuf, size) < 0) 581 { 582 (void) strcpy(hostbuf, "localhost"); 583 } 584 hp = gethostbyname(hostbuf); 585 if (hp != NULL) 586 { 587 (void) strncpy(hostbuf, hp->h_name, size - 1); 588 hostbuf[size - 1] = '\0'; 589 590 if (hp->h_addrtype == AF_INET && hp->h_length == 4) 591 { 592 register int i; 593 594 for (i = 0; i < MAXIPADDR; i++) 595 { 596 if (hp->h_addr_list[i] == NULL) 597 break; 598 MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 599 } 600 MyIpAddrs[i].s_addr = 0; 601 } 602 603 return (hp->h_aliases); 604 } 605 else 606 return (NULL); 607 } 608 /* 609 ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 610 ** 611 ** Parameters: 612 ** fd -- the descriptor 613 ** 614 ** Returns: 615 ** The host name associated with this descriptor, if it can 616 ** be determined. 617 ** NULL otherwise. 618 ** 619 ** Side Effects: 620 ** none 621 */ 622 623 char * 624 getrealhostname(fd) 625 int fd; 626 { 627 register struct hostent *hp; 628 SOCKADDR sa; 629 int salen; 630 char hbuf[MAXNAME]; 631 extern struct hostent *gethostbyaddr(); 632 633 salen = sizeof sa; 634 if (getsockname(fd, &sa.sa, &salen) < 0 || salen <= 0) 635 return NULL; 636 hp = gethostbyaddr(sa.sa.sa_data, salen, sa.sa.sa_family); 637 if (hp != NULL) 638 (void) strcpy(hbuf, hp->h_name); 639 else 640 (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 641 return hbuf; 642 } 643 /* 644 ** MAPHOSTNAME -- turn a hostname into canonical form 645 ** 646 ** Parameters: 647 ** map -- a pointer to this map (unused). 648 ** hbuf -- a buffer containing a hostname. 649 ** hbsize -- the size of hbuf. 650 ** avp -- unused -- for compatibility with other mapping 651 ** functions. 652 ** 653 ** Returns: 654 ** The mapping, if found. 655 ** NULL if no mapping found. 656 ** 657 ** Side Effects: 658 ** Looks up the host specified in hbuf. If it is not 659 ** the canonical name for that host, return the canonical 660 ** name. 661 */ 662 663 char * 664 maphostname(map, hbuf, hbsize, avp) 665 MAP *map; 666 char *hbuf; 667 int hbsize; 668 char **avp; 669 { 670 register struct hostent *hp; 671 u_long in_addr; 672 char *cp; 673 int i; 674 struct hostent *gethostbyaddr(); 675 676 /* allow room for null */ 677 hbsize--; 678 679 /* 680 * If first character is a bracket, then it is an address 681 * lookup. Address is copied into a temporary buffer to 682 * strip the brackets and to preserve hbuf if address is 683 * unknown. 684 */ 685 686 if (*hbuf != '[') 687 { 688 extern bool getcanonname(); 689 690 if (tTd(9, 1)) 691 printf("maphostname(%s, %d) => ", hbuf, hbsize); 692 if (getcanonname(hbuf, hbsize)) 693 { 694 if (tTd(9, 1)) 695 printf("%s\n", hbuf); 696 return hbuf; 697 } 698 else 699 { 700 if (tTd(9, 1)) 701 printf("FAIL\n"); 702 return NULL; 703 } 704 } 705 if ((cp = strchr(hbuf, ']')) == NULL) 706 return (NULL); 707 *cp = '\0'; 708 in_addr = inet_addr(&hbuf[1]); 709 710 /* check to see if this is one of our addresses */ 711 for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 712 { 713 if (MyIpAddrs[i].s_addr == in_addr) 714 { 715 strncpy(hbuf, MyHostName, hbsize); 716 hbuf[hbsize] = '\0'; 717 return hbuf; 718 } 719 } 720 721 /* nope -- ask the name server */ 722 hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 723 if (hp == NULL) 724 return (NULL); 725 726 /* found a match -- copy out */ 727 if (strlen(hp->h_name) > hbsize) 728 hp->h_name[hbsize] = '\0'; 729 (void) strcpy(hbuf, hp->h_name); 730 return hbuf; 731 } 732 /* 733 ** ANYNET_NTOA -- convert a network address to printable form. 734 ** 735 ** Parameters: 736 ** sap -- a pointer to a sockaddr structure. 737 ** 738 ** Returns: 739 ** A printable version of that sockaddr. 740 */ 741 742 char * 743 anynet_ntoa(sap) 744 register SOCKADDR *sap; 745 { 746 register char *bp; 747 register char *ap; 748 int l; 749 static char buf[80]; 750 751 /* check for null/zero family */ 752 if (sap == NULL) 753 return "NULLADDR"; 754 if (sap->sa.sa_family == 0) 755 return "0"; 756 757 #ifdef NETINET 758 if (sap->sa.sa_family == AF_INET) 759 { 760 extern char *inet_ntoa(); 761 762 return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 763 } 764 #endif 765 766 /* unknown family -- just dump bytes */ 767 (void) sprintf(buf, "Family %d: ", sap->sa.sa_family); 768 bp = &buf[strlen(buf)]; 769 ap = sap->sa.sa_data; 770 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 771 { 772 (void) sprintf(bp, "%02x:", *ap++ & 0377); 773 bp += 3; 774 } 775 *--bp = '\0'; 776 return buf; 777 } 778 779 # else /* DAEMON */ 780 /* code for systems without sophisticated networking */ 781 782 /* 783 ** MYHOSTNAME -- stub version for case of no daemon code. 784 ** 785 ** Can't convert to upper case here because might be a UUCP name. 786 ** 787 ** Mark, you can change this to be anything you want...... 788 */ 789 790 char ** 791 myhostname(hostbuf, size) 792 char hostbuf[]; 793 int size; 794 { 795 register FILE *f; 796 797 hostbuf[0] = '\0'; 798 f = fopen("/usr/include/whoami", "r"); 799 if (f != NULL) 800 { 801 (void) fgets(hostbuf, size, f); 802 fixcrlf(hostbuf, TRUE); 803 (void) fclose(f); 804 } 805 return (NULL); 806 } 807 /* 808 ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 809 ** 810 ** Parameters: 811 ** fd -- the descriptor 812 ** 813 ** Returns: 814 ** The host name associated with this descriptor, if it can 815 ** be determined. 816 ** NULL otherwise. 817 ** 818 ** Side Effects: 819 ** none 820 */ 821 822 char * 823 getrealhostname(fd) 824 int fd; 825 { 826 return NULL; 827 } 828 /* 829 ** MAPHOSTNAME -- turn a hostname into canonical form 830 ** 831 ** Parameters: 832 ** map -- a pointer to the database map. 833 ** hbuf -- a buffer containing a hostname. 834 ** avp -- a pointer to a (cf file defined) argument vector. 835 ** 836 ** Returns: 837 ** mapped host name 838 ** FALSE otherwise. 839 ** 840 ** Side Effects: 841 ** Looks up the host specified in hbuf. If it is not 842 ** the canonical name for that host, replace it with 843 ** the canonical name. If the name is unknown, or it 844 ** is already the canonical name, leave it unchanged. 845 */ 846 847 /*ARGSUSED*/ 848 char * 849 maphostname(map, hbuf, hbsize, avp) 850 MAP *map; 851 char *hbuf; 852 int hbsize; 853 char **avp; 854 { 855 return NULL; 856 } 857 858 #endif /* DAEMON */ 859