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.20 (Berkeley) 03/19/93 (with daemon mode)"; 16 #else 17 static char sccsid[] = "@(#)daemon.c 6.20 (Berkeley) 03/19/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 struct sockaddr_in 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_family = AF_INET; 103 srvraddr.sin_addr.s_addr = INADDR_ANY; 104 srvraddr.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_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, (struct sockaddr *)&srvraddr, 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 hp = gethostbyaddr(RealHostAddr.sa_u.sa_data, 237 sizeof RealHostAddr.sa_u.sa_data, 238 RealHostAddr.sa_family); 239 if (hp != NULL) 240 (void) strcpy(buf, hp->h_name); 241 else 242 { 243 /* produce a dotted quad */ 244 (void) sprintf(buf, "[%s]", 245 anynet_ntoa(&RealHostAddr)); 246 } 247 248 #ifdef LOG 249 if (LogLevel > 10) 250 { 251 /* log connection information */ 252 syslog(LOG_INFO, "connect from %s (%s)", 253 buf, anynet_ntoa(&RealHostAddr)); 254 } 255 #endif 256 257 /* should we check for illegal connection here? XXX */ 258 259 RealHostName = newstr(buf); 260 261 (void) close(DaemonSocket); 262 InChannel = fdopen(t, "r"); 263 OutChannel = fdopen(dup(t), "w"); 264 if (tTd(15, 2)) 265 printf("getreq: returning\n"); 266 return; 267 } 268 269 /* close the port so that others will hang (for a while) */ 270 (void) close(t); 271 } 272 /*NOTREACHED*/ 273 } 274 /* 275 ** CLRDAEMON -- reset the daemon connection 276 ** 277 ** Parameters: 278 ** none. 279 ** 280 ** Returns: 281 ** none. 282 ** 283 ** Side Effects: 284 ** releases any resources used by the passive daemon. 285 */ 286 287 clrdaemon() 288 { 289 if (DaemonSocket >= 0) 290 (void) close(DaemonSocket); 291 DaemonSocket = -1; 292 } 293 /* 294 ** MAKECONNECTION -- make a connection to an SMTP socket on another machine. 295 ** 296 ** Parameters: 297 ** host -- the name of the host. 298 ** port -- the port number to connect to. 299 ** mci -- a pointer to the mail connection information 300 ** structure to be filled in. 301 ** usesecureport -- if set, use a low numbered (reserved) 302 ** port to provide some rudimentary authentication. 303 ** 304 ** Returns: 305 ** An exit code telling whether the connection could be 306 ** made and if not why not. 307 ** 308 ** Side Effects: 309 ** none. 310 */ 311 312 SOCKADDR CurHostAddr; /* address of current host */ 313 314 int 315 makeconnection(host, port, mci, usesecureport) 316 char *host; 317 u_short port; 318 register MCI *mci; 319 bool usesecureport; 320 { 321 register int i, s; 322 register struct hostent *hp = (struct hostent *)NULL; 323 SOCKADDR addr; 324 int sav_errno; 325 int addrlen; 326 #ifdef NAMED_BIND 327 extern int h_errno; 328 #endif 329 330 /* 331 ** Set up the address for the mailer. 332 ** Accept "[a.b.c.d]" syntax for host name. 333 */ 334 335 #ifdef NAMED_BIND 336 h_errno = 0; 337 #endif 338 errno = 0; 339 340 if (host[0] == '[') 341 { 342 long hid; 343 register char *p = strchr(host, ']'); 344 345 if (p != NULL) 346 { 347 *p = '\0'; 348 hid = inet_addr(&host[1]); 349 if (hid == -1) 350 { 351 /* try it as a host name (avoid MX lookup) */ 352 hp = gethostbyname(&host[1]); 353 *p = ']'; 354 goto gothostent; 355 } 356 *p = ']'; 357 } 358 if (p == NULL) 359 { 360 usrerr("553 Invalid numeric domain spec \"%s\"", host); 361 return (EX_NOHOST); 362 } 363 addr.sa_family = AF_INET; 364 addr.sa_len = sizeof hid; 365 addr.sa_u.sa_inet.sin_addr.s_addr = hid; 366 } 367 else 368 { 369 hp = gethostbyname(host); 370 gothostent: 371 if (hp == NULL) 372 { 373 #ifdef NAMED_BIND 374 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) 375 return (EX_TEMPFAIL); 376 377 /* if name server is specified, assume temp fail */ 378 if (errno == ECONNREFUSED && UseNameServer) 379 return (EX_TEMPFAIL); 380 #endif 381 return (EX_NOHOST); 382 } 383 addr.sa_family = hp->h_addrtype; 384 addr.sa_len = hp->h_length; 385 if (addr.sa_family == AF_INET) 386 bcopy(hp->h_addr, 387 &addr.sa_u.sa_inet.sin_addr, 388 hp->h_length); 389 else 390 bcopy(hp->h_addr, 391 addr.sa_u.sa_data, 392 hp->h_length); 393 i = 1; 394 } 395 396 /* 397 ** Determine the port number. 398 */ 399 400 if (port != 0) 401 port = htons(port); 402 else 403 { 404 register struct servent *sp = getservbyname("smtp", "tcp"); 405 406 if (sp == NULL) 407 { 408 syserr("554 makeconnection: server \"smtp\" unknown"); 409 return (EX_OSERR); 410 } 411 port = sp->s_port; 412 } 413 414 switch (addr.sa_family) 415 { 416 case AF_INET: 417 addr.sa_u.sa_inet.sin_port = port; 418 addrlen = sizeof (struct sockaddr_in); 419 break; 420 421 #ifdef NETISO 422 case AF_ISO: 423 /* assume two byte transport selector */ 424 bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); 425 addrlen = sizeof (struct sockaddr_iso); 426 break; 427 #endif 428 429 default: 430 syserr("Can't connect to address family %d", addr.sa_family); 431 return (EX_NOHOST); 432 } 433 434 /* 435 ** Try to actually open the connection. 436 */ 437 438 for (;;) 439 { 440 if (tTd(16, 1)) 441 printf("makeconnection (%s [%s])\n", 442 host, anynet_ntoa(&addr)); 443 444 /* save for logging */ 445 CurHostAddr = addr; 446 447 if (usesecureport) 448 { 449 int rport = IPPORT_RESERVED - 1; 450 451 s = rresvport(&rport); 452 } 453 else 454 { 455 s = socket(AF_INET, SOCK_STREAM, 0); 456 } 457 if (s < 0) 458 { 459 sav_errno = errno; 460 syserr("makeconnection: no socket"); 461 goto failure; 462 } 463 464 if (tTd(16, 1)) 465 printf("makeconnection: fd=%d\n", s); 466 467 /* turn on network debugging? */ 468 if (tTd(16, 101)) 469 { 470 int on = 1; 471 (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 472 (char *)&on, sizeof on); 473 } 474 if (CurEnv->e_xfp != NULL) 475 (void) fflush(CurEnv->e_xfp); /* for debugging */ 476 errno = 0; /* for debugging */ 477 if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) 478 break; 479 480 /* couldn't connect.... figure out why */ 481 sav_errno = errno; 482 (void) close(s); 483 if (hp && hp->h_addr_list[i]) 484 { 485 extern char *errstring(); 486 487 if (tTd(16, 1)) 488 printf("Connect failed (%s); trying new address....\n", 489 errstring(sav_errno)); 490 if (addr.sa_family == AF_INET) 491 bcopy(hp->h_addr_list[i++], 492 &addr.sa_u.sa_inet.sin_addr, 493 hp->h_length); 494 else 495 bcopy(hp->h_addr_list[i++], 496 addr.sa_u.sa_data, 497 hp->h_length); 498 continue; 499 } 500 501 /* failure, decide if temporary or not */ 502 failure: 503 if (transienterror(sav_errno)) 504 return EX_TEMPFAIL; 505 else 506 { 507 extern char *errstring(); 508 509 message("%s", errstring(sav_errno)); 510 return (EX_UNAVAILABLE); 511 } 512 } 513 514 /* connection ok, put it into canonical form */ 515 mci->mci_out = fdopen(s, "w"); 516 mci->mci_in = fdopen(dup(s), "r"); 517 518 return (EX_OK); 519 } 520 /* 521 ** MYHOSTNAME -- return the name of this host. 522 ** 523 ** Parameters: 524 ** hostbuf -- a place to return the name of this host. 525 ** size -- the size of hostbuf. 526 ** 527 ** Returns: 528 ** A list of aliases for this host. 529 ** 530 ** Side Effects: 531 ** Sets the MyIpAddrs buffer to a list of my IP addresses. 532 */ 533 534 struct in_addr MyIpAddrs[MAXIPADDR + 1]; 535 536 char ** 537 myhostname(hostbuf, size) 538 char hostbuf[]; 539 int size; 540 { 541 register struct hostent *hp; 542 extern struct hostent *gethostbyname(); 543 544 if (gethostname(hostbuf, size) < 0) 545 { 546 (void) strcpy(hostbuf, "localhost"); 547 } 548 hp = gethostbyname(hostbuf); 549 if (hp != NULL) 550 { 551 (void) strncpy(hostbuf, hp->h_name, size - 1); 552 hostbuf[size - 1] = '\0'; 553 554 if (hp->h_addrtype == AF_INET && hp->h_length == 4) 555 { 556 register int i; 557 558 for (i = 0; i < MAXIPADDR; i++) 559 { 560 if (hp->h_addr_list[i] == NULL) 561 break; 562 MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i]; 563 } 564 MyIpAddrs[i].s_addr = 0; 565 } 566 567 return (hp->h_aliases); 568 } 569 else 570 return (NULL); 571 } 572 /* 573 ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 574 ** 575 ** Parameters: 576 ** fd -- the descriptor 577 ** 578 ** Returns: 579 ** The host name associated with this descriptor, if it can 580 ** be determined. 581 ** NULL otherwise. 582 ** 583 ** Side Effects: 584 ** none 585 */ 586 587 char * 588 getrealhostname(fd) 589 int fd; 590 { 591 register struct hostent *hp; 592 struct sockaddr sa; 593 int salen; 594 char hbuf[MAXNAME]; 595 extern struct hostent *gethostbyaddr(); 596 597 salen = sizeof sa; 598 if (getsockname(fd, &sa, &salen) < 0 || salen <= 0) 599 return NULL; 600 hp = gethostbyaddr(sa.sa_data, sa.sa_len, 601 sa.sa_family); 602 if (hp != NULL) 603 (void) strcpy(hbuf, hp->h_name); 604 else 605 (void) sprintf(hbuf, "[%s]", anynet_ntoa(&sa)); 606 return hbuf; 607 } 608 /* 609 ** MAPHOSTNAME -- turn a hostname into canonical form 610 ** 611 ** Parameters: 612 ** map -- a pointer to this map (unused). 613 ** hbuf -- a buffer containing a hostname. 614 ** hbsize -- the size of hbuf. 615 ** avp -- unused -- for compatibility with other mapping 616 ** functions. 617 ** 618 ** Returns: 619 ** The mapping, if found. 620 ** NULL if no mapping found. 621 ** 622 ** Side Effects: 623 ** Looks up the host specified in hbuf. If it is not 624 ** the canonical name for that host, return the canonical 625 ** name. 626 */ 627 628 char * 629 maphostname(map, hbuf, hbsize, avp) 630 MAP *map; 631 char *hbuf; 632 int hbsize; 633 char **avp; 634 { 635 register struct hostent *hp; 636 u_long in_addr; 637 char *cp; 638 int i; 639 struct hostent *gethostbyaddr(); 640 641 /* allow room for null */ 642 hbsize--; 643 644 /* 645 * If first character is a bracket, then it is an address 646 * lookup. Address is copied into a temporary buffer to 647 * strip the brackets and to preserve hbuf if address is 648 * unknown. 649 */ 650 651 if (*hbuf != '[') 652 { 653 extern bool getcanonname(); 654 655 if (getcanonname(hbuf, hbsize)) 656 return hbuf; 657 else 658 return NULL; 659 } 660 if ((cp = strchr(hbuf, ']')) == NULL) 661 return (NULL); 662 *cp = '\0'; 663 in_addr = inet_addr(&hbuf[1]); 664 665 /* check to see if this is one of our addresses */ 666 for (i = 0; MyIpAddrs[i].s_addr != 0; i++) 667 { 668 if (MyIpAddrs[i].s_addr == in_addr) 669 { 670 strncpy(hbuf, MyHostName, hbsize); 671 hbuf[hbsize] = '\0'; 672 return hbuf; 673 } 674 } 675 676 /* nope -- ask the name server */ 677 hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); 678 if (hp == NULL) 679 return (NULL); 680 681 /* found a match -- copy out */ 682 if (strlen(hp->h_name) > hbsize) 683 hp->h_name[hbsize] = '\0'; 684 (void) strcpy(hbuf, hp->h_name); 685 return hbuf; 686 } 687 /* 688 ** ANYNET_NTOA -- convert a network address to printable form. 689 ** 690 ** Parameters: 691 ** sap -- a pointer to a sockaddr structure. 692 ** 693 ** Returns: 694 ** A printable version of that sockaddr. 695 */ 696 697 char * 698 anynet_ntoa(sap) 699 register SOCKADDR *sap; 700 { 701 register char *bp; 702 register char *ap; 703 int l; 704 static char buf[80]; 705 706 if (sap->sa_family == AF_INET) 707 { 708 extern char *inet_ntoa(); 709 710 return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); 711 } 712 713 /* unknown family -- just dump bytes */ 714 (void) sprintf(buf, "Family %d: ", sap->sa_family); 715 bp = &buf[strlen(buf)]; 716 ap = sap->sa_u.sa_data; 717 for (l = sap->sa_len; --l >= 0; ) 718 { 719 (void) sprintf(bp, "%02x:", *ap++ & 0377); 720 bp += 3; 721 } 722 *--bp = '\0'; 723 return buf; 724 } 725 726 # else /* DAEMON */ 727 /* code for systems without sophisticated networking */ 728 729 /* 730 ** MYHOSTNAME -- stub version for case of no daemon code. 731 ** 732 ** Can't convert to upper case here because might be a UUCP name. 733 ** 734 ** Mark, you can change this to be anything you want...... 735 */ 736 737 char ** 738 myhostname(hostbuf, size) 739 char hostbuf[]; 740 int size; 741 { 742 register FILE *f; 743 744 hostbuf[0] = '\0'; 745 f = fopen("/usr/include/whoami", "r"); 746 if (f != NULL) 747 { 748 (void) fgets(hostbuf, size, f); 749 fixcrlf(hostbuf, TRUE); 750 (void) fclose(f); 751 } 752 return (NULL); 753 } 754 /* 755 ** GETREALHOSTNAME -- get the real host name asociated with a file descriptor 756 ** 757 ** Parameters: 758 ** fd -- the descriptor 759 ** 760 ** Returns: 761 ** The host name associated with this descriptor, if it can 762 ** be determined. 763 ** NULL otherwise. 764 ** 765 ** Side Effects: 766 ** none 767 */ 768 769 char * 770 getrealhostname(fd) 771 int fd; 772 { 773 return NULL; 774 } 775 /* 776 ** MAPHOSTNAME -- turn a hostname into canonical form 777 ** 778 ** Parameters: 779 ** map -- a pointer to the database map. 780 ** hbuf -- a buffer containing a hostname. 781 ** avp -- a pointer to a (cf file defined) argument vector. 782 ** 783 ** Returns: 784 ** mapped host name 785 ** FALSE otherwise. 786 ** 787 ** Side Effects: 788 ** Looks up the host specified in hbuf. If it is not 789 ** the canonical name for that host, replace it with 790 ** the canonical name. If the name is unknown, or it 791 ** is already the canonical name, leave it unchanged. 792 */ 793 794 /*ARGSUSED*/ 795 char * 796 maphostname(map, hbuf, hbsize, avp) 797 MAP *map; 798 char *hbuf; 799 int hbsize; 800 char **avp; 801 { 802 return NULL; 803 } 804 805 #endif /* DAEMON */ 806