daemon.c revision 157001
1/* 2 * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14#include <sendmail.h> 15 16SM_RCSID("@(#)$Id: daemon.c,v 8.665 2006/03/02 19:12:00 ca Exp $") 17 18#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 19# define USE_SOCK_STREAM 1 20#endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 21 22#if defined(USE_SOCK_STREAM) 23# if NETINET || NETINET6 24# include <arpa/inet.h> 25# endif /* NETINET || NETINET6 */ 26# if NAMED_BIND 27# ifndef NO_DATA 28# define NO_DATA NO_ADDRESS 29# endif /* ! NO_DATA */ 30# endif /* NAMED_BIND */ 31#endif /* defined(USE_SOCK_STREAM) */ 32 33#if STARTTLS 34# include <openssl/rand.h> 35#endif /* STARTTLS */ 36 37#include <sm/time.h> 38 39#if IP_SRCROUTE && NETINET 40# include <netinet/in_systm.h> 41# include <netinet/ip.h> 42# if HAS_IN_H 43# include <netinet/in.h> 44# ifndef IPOPTION 45# define IPOPTION ip_opts 46# define IP_LIST ip_opts 47# define IP_DST ip_dst 48# endif /* ! IPOPTION */ 49# else /* HAS_IN_H */ 50# include <netinet/ip_var.h> 51# ifndef IPOPTION 52# define IPOPTION ipoption 53# define IP_LIST ipopt_list 54# define IP_DST ipopt_dst 55# endif /* ! IPOPTION */ 56# endif /* HAS_IN_H */ 57#endif /* IP_SRCROUTE && NETINET */ 58 59#include <sm/fdset.h> 60 61/* structure to describe a daemon or a client */ 62struct daemon 63{ 64 int d_socket; /* fd for socket */ 65 SOCKADDR d_addr; /* socket for incoming */ 66 unsigned short d_port; /* port number */ 67 int d_listenqueue; /* size of listen queue */ 68 int d_tcprcvbufsize; /* size of TCP receive buffer */ 69 int d_tcpsndbufsize; /* size of TCP send buffer */ 70 time_t d_refuse_connections_until; 71 bool d_firsttime; 72 int d_socksize; 73 BITMAP256 d_flags; /* flags; see sendmail.h */ 74 char *d_mflags; /* flags for use in macro */ 75 char *d_name; /* user-supplied name */ 76#if MILTER 77 char *d_inputfilterlist; 78 struct milter *d_inputfilters[MAXFILTERS]; 79#endif /* MILTER */ 80#if _FFR_SS_PER_DAEMON 81 int d_supersafe; 82#endif /* _FFR_SS_PER_DAEMON */ 83#if _FFR_DM_PER_DAEMON 84 int d_dm; /* DeliveryMode */ 85#endif /* _FFR_DM_PER_DAEMON */ 86}; 87 88typedef struct daemon DAEMON_T; 89 90#define SAFE_NOTSET (-1) /* SuperSafe (per daemon) option not set */ 91/* see also sendmail.h: SuperSafe values */ 92 93static void connecttimeout __P((int)); 94static int opendaemonsocket __P((DAEMON_T *, bool)); 95static unsigned short setupdaemon __P((SOCKADDR *)); 96static void getrequests_checkdiskspace __P((ENVELOPE *e)); 97static void setsockaddroptions __P((char *, DAEMON_T *)); 98static void printdaemonflags __P((DAEMON_T *)); 99static int addr_family __P((char *)); 100static int addrcmp __P((struct hostent *, char *, SOCKADDR *)); 101static void authtimeout __P((int)); 102 103/* 104** DAEMON.C -- routines to use when running as a daemon. 105** 106** This entire file is highly dependent on the 4.2 BSD 107** interprocess communication primitives. No attempt has 108** been made to make this file portable to Version 7, 109** Version 6, MPX files, etc. If you should try such a 110** thing yourself, I recommend chucking the entire file 111** and starting from scratch. Basic semantics are: 112** 113** getrequests(e) 114** Opens a port and initiates a connection. 115** Returns in a child. Must set InChannel and 116** OutChannel appropriately. 117** clrdaemon() 118** Close any open files associated with getting 119** the connection; this is used when running the queue, 120** etc., to avoid having extra file descriptors during 121** the queue run and to avoid confusing the network 122** code (if it cares). 123** makeconnection(host, port, mci, e, enough) 124** Make a connection to the named host on the given 125** port. Returns zero on success, else an exit status 126** describing the error. 127** host_map_lookup(map, hbuf, avp, pstat) 128** Convert the entry in hbuf into a canonical form. 129*/ 130 131static DAEMON_T Daemons[MAXDAEMONS]; 132static int NDaemons = 0; /* actual number of daemons */ 133 134static time_t NextDiskSpaceCheck = 0; 135 136/* 137** GETREQUESTS -- open mail IPC port and get requests. 138** 139** Parameters: 140** e -- the current envelope. 141** 142** Returns: 143** pointer to flags. 144** 145** Side Effects: 146** Waits until some interesting activity occurs. When 147** it does, a child is created to process it, and the 148** parent waits for completion. Return from this 149** routine is always in the child. The file pointers 150** "InChannel" and "OutChannel" should be set to point 151** to the communication channel. 152** May restart persistent queue runners if they have ended 153** for some reason. 154*/ 155 156BITMAP256 * 157getrequests(e) 158 ENVELOPE *e; 159{ 160 int t; 161 int idx, curdaemon = -1; 162 int i, olddaemon = 0; 163#if XDEBUG 164 bool j_has_dot; 165#endif /* XDEBUG */ 166 char status[MAXLINE]; 167 SOCKADDR sa; 168 SOCKADDR_LEN_T len = sizeof sa; 169#if _FFR_QUEUE_RUN_PARANOIA 170 time_t lastrun; 171#endif /* _FFR_QUEUE_RUN_PARANOIA */ 172# if NETUNIX 173 extern int ControlSocket; 174# endif /* NETUNIX */ 175 extern ENVELOPE BlankEnvelope; 176 extern bool refuseconnections __P((char *, ENVELOPE *, int, bool)); 177 178 179 /* initialize data for function that generates queue ids */ 180 init_qid_alg(); 181 for (idx = 0; idx < NDaemons; idx++) 182 { 183 Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 184 Daemons[idx].d_firsttime = true; 185 Daemons[idx].d_refuse_connections_until = (time_t) 0; 186 } 187 188 /* 189 ** Try to actually open the connection. 190 */ 191 192 if (tTd(15, 1)) 193 { 194 for (idx = 0; idx < NDaemons; idx++) 195 { 196 sm_dprintf("getrequests: daemon %s: port %d\n", 197 Daemons[idx].d_name, 198 ntohs(Daemons[idx].d_port)); 199 } 200 } 201 202 /* get a socket for the SMTP connection */ 203 for (idx = 0; idx < NDaemons; idx++) 204 Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], true); 205 206 if (opencontrolsocket() < 0) 207 sm_syslog(LOG_WARNING, NOQID, 208 "daemon could not open control socket %s: %s", 209 ControlSocketName, sm_errstring(errno)); 210 211 /* If there are any queue runners released reapchild() co-ord's */ 212 (void) sm_signal(SIGCHLD, reapchild); 213 214 /* write the pid to file, command line args to syslog */ 215 log_sendmail_pid(e); 216 217#if XDEBUG 218 { 219 char jbuf[MAXHOSTNAMELEN]; 220 221 expand("\201j", jbuf, sizeof jbuf, e); 222 j_has_dot = strchr(jbuf, '.') != NULL; 223 } 224#endif /* XDEBUG */ 225 226 /* Add parent process as first item */ 227 proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1, NULL); 228 229 if (tTd(15, 1)) 230 { 231 for (idx = 0; idx < NDaemons; idx++) 232 sm_dprintf("getrequests: daemon %s: %d\n", 233 Daemons[idx].d_name, 234 Daemons[idx].d_socket); 235 } 236 237 for (;;) 238 { 239 register pid_t pid; 240 auto SOCKADDR_LEN_T lotherend; 241 bool timedout = false; 242 bool control = false; 243 int save_errno; 244 int pipefd[2]; 245 time_t now; 246#if STARTTLS 247 long seed; 248#endif /* STARTTLS */ 249 250 /* see if we are rejecting connections */ 251 (void) sm_blocksignal(SIGALRM); 252 CHECK_RESTART; 253 254 for (idx = 0; idx < NDaemons; idx++) 255 { 256 /* 257 ** XXX do this call outside the loop? 258 ** no: refuse_connections may sleep(). 259 */ 260 261 now = curtime(); 262 if (now < Daemons[idx].d_refuse_connections_until) 263 continue; 264 if (bitnset(D_DISABLE, Daemons[idx].d_flags)) 265 continue; 266 if (refuseconnections(Daemons[idx].d_name, e, idx, 267 curdaemon == idx)) 268 { 269 if (Daemons[idx].d_socket >= 0) 270 { 271 /* close socket so peer fails quickly */ 272 (void) close(Daemons[idx].d_socket); 273 Daemons[idx].d_socket = -1; 274 } 275 276 /* refuse connections for next 15 seconds */ 277 Daemons[idx].d_refuse_connections_until = now + 15; 278 } 279 else if (Daemons[idx].d_socket < 0 || 280 Daemons[idx].d_firsttime) 281 { 282 if (!Daemons[idx].d_firsttime && LogLevel > 8) 283 sm_syslog(LOG_INFO, NOQID, 284 "accepting connections again for daemon %s", 285 Daemons[idx].d_name); 286 287 /* arrange to (re)open the socket if needed */ 288 (void) opendaemonsocket(&Daemons[idx], false); 289 Daemons[idx].d_firsttime = false; 290 } 291 } 292 293 /* May have been sleeping above, check again */ 294 CHECK_RESTART; 295 296 getrequests_checkdiskspace(e); 297 298#if XDEBUG 299 /* check for disaster */ 300 { 301 char jbuf[MAXHOSTNAMELEN]; 302 303 expand("\201j", jbuf, sizeof jbuf, e); 304 if (!wordinclass(jbuf, 'w')) 305 { 306 dumpstate("daemon lost $j"); 307 sm_syslog(LOG_ALERT, NOQID, 308 "daemon process doesn't have $j in $=w; see syslog"); 309 abort(); 310 } 311 else if (j_has_dot && strchr(jbuf, '.') == NULL) 312 { 313 dumpstate("daemon $j lost dot"); 314 sm_syslog(LOG_ALERT, NOQID, 315 "daemon process $j lost dot; see syslog"); 316 abort(); 317 } 318 } 319#endif /* XDEBUG */ 320 321#if 0 322 /* 323 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 324 ** fix the SVr4 problem. But it seems to have gone away, 325 ** so is it worth doing this? 326 */ 327 328 if (DaemonSocket >= 0 && 329 SetNonBlocking(DaemonSocket, false) < 0) 330 log an error here; 331#endif /* 0 */ 332 (void) sm_releasesignal(SIGALRM); 333 334 for (;;) 335 { 336 bool setproc = false; 337 int highest = -1; 338 fd_set readfds; 339 struct timeval timeout; 340 341 CHECK_RESTART; 342 FD_ZERO(&readfds); 343 for (idx = 0; idx < NDaemons; idx++) 344 { 345 /* wait for a connection */ 346 if (Daemons[idx].d_socket >= 0) 347 { 348 if (!setproc && 349 !bitnset(D_ETRNONLY, 350 Daemons[idx].d_flags)) 351 { 352 sm_setproctitle(true, e, 353 "accepting connections"); 354 setproc = true; 355 } 356 if (Daemons[idx].d_socket > highest) 357 highest = Daemons[idx].d_socket; 358 SM_FD_SET(Daemons[idx].d_socket, 359 &readfds); 360 } 361 } 362 363#if NETUNIX 364 if (ControlSocket >= 0) 365 { 366 if (ControlSocket > highest) 367 highest = ControlSocket; 368 SM_FD_SET(ControlSocket, &readfds); 369 } 370#endif /* NETUNIX */ 371 372 timeout.tv_sec = 5; 373 timeout.tv_usec = 0; 374 375 t = select(highest + 1, FDSET_CAST &readfds, 376 NULL, NULL, &timeout); 377 378 /* Did someone signal while waiting? */ 379 CHECK_RESTART; 380 381 curdaemon = -1; 382 if (doqueuerun()) 383 { 384 (void) runqueue(true, false, false, false); 385#if _FFR_QUEUE_RUN_PARANOIA 386 lastrun = now; 387#endif /* _FFR_QUEUE_RUN_PARANOIA */ 388 } 389#if _FFR_QUEUE_RUN_PARANOIA 390 else if (CheckQueueRunners > 0 && QueueIntvl > 0 && 391 lastrun + QueueIntvl + CheckQueueRunners < now) 392 { 393 394 /* 395 ** set lastrun unconditionally to avoid 396 ** calling checkqueuerunner() all the time. 397 ** That's also why we currently ignore the 398 ** result of the function call. 399 */ 400 401 (void) checkqueuerunner(); 402 lastrun = now; 403 } 404#endif /* _FFR_QUEUE_RUN_PARANOIA */ 405 406 if (t <= 0) 407 { 408 timedout = true; 409 break; 410 } 411 412 control = false; 413 errno = 0; 414 415 /* look "round-robin" for an active socket */ 416 if ((idx = olddaemon + 1) >= NDaemons) 417 idx = 0; 418 for (i = 0; i < NDaemons; i++) 419 { 420 if (Daemons[idx].d_socket >= 0 && 421 SM_FD_ISSET(Daemons[idx].d_socket, 422 &readfds)) 423 { 424 lotherend = Daemons[idx].d_socksize; 425 memset(&RealHostAddr, '\0', 426 sizeof RealHostAddr); 427 t = accept(Daemons[idx].d_socket, 428 (struct sockaddr *)&RealHostAddr, 429 &lotherend); 430 431 /* 432 ** If remote side closes before 433 ** accept() finishes, sockaddr 434 ** might not be fully filled in. 435 */ 436 437 if (t >= 0 && 438 (lotherend == 0 || 439# ifdef BSD4_4_SOCKADDR 440 RealHostAddr.sa.sa_len == 0 || 441# endif /* BSD4_4_SOCKADDR */ 442 RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) 443 { 444 (void) close(t); 445 t = -1; 446 errno = EINVAL; 447 } 448 olddaemon = curdaemon = idx; 449 break; 450 } 451 if (++idx >= NDaemons) 452 idx = 0; 453 } 454#if NETUNIX 455 if (curdaemon == -1 && ControlSocket >= 0 && 456 SM_FD_ISSET(ControlSocket, &readfds)) 457 { 458 struct sockaddr_un sa_un; 459 460 lotherend = sizeof sa_un; 461 memset(&sa_un, '\0', sizeof sa_un); 462 t = accept(ControlSocket, 463 (struct sockaddr *)&sa_un, 464 &lotherend); 465 466 /* 467 ** If remote side closes before 468 ** accept() finishes, sockaddr 469 ** might not be fully filled in. 470 */ 471 472 if (t >= 0 && 473 (lotherend == 0 || 474# ifdef BSD4_4_SOCKADDR 475 sa_un.sun_len == 0 || 476# endif /* BSD4_4_SOCKADDR */ 477 sa_un.sun_family != AF_UNIX)) 478 { 479 (void) close(t); 480 t = -1; 481 errno = EINVAL; 482 } 483 if (t >= 0) 484 control = true; 485 } 486#else /* NETUNIX */ 487 if (curdaemon == -1) 488 { 489 /* No daemon to service */ 490 continue; 491 } 492#endif /* NETUNIX */ 493 if (t >= 0 || errno != EINTR) 494 break; 495 } 496 if (timedout) 497 { 498 timedout = false; 499 continue; 500 } 501 save_errno = errno; 502 (void) sm_blocksignal(SIGALRM); 503 if (t < 0) 504 { 505 errno = save_errno; 506 507 /* let's ignore these temporary errors */ 508 if (save_errno == EINTR 509#ifdef EAGAIN 510 || save_errno == EAGAIN 511#endif /* EAGAIN */ 512#ifdef ECONNABORTED 513 || save_errno == ECONNABORTED 514#endif /* ECONNABORTED */ 515#ifdef EWOULDBLOCK 516 || save_errno == EWOULDBLOCK 517#endif /* EWOULDBLOCK */ 518 ) 519 continue; 520 521 syserr("getrequests: accept"); 522 523 /* arrange to re-open the socket next time around */ 524 (void) close(Daemons[curdaemon].d_socket); 525 Daemons[curdaemon].d_socket = -1; 526#if SO_REUSEADDR_IS_BROKEN 527 /* 528 ** Give time for bound socket to be released. 529 ** This creates a denial-of-service if you can 530 ** force accept() to fail on affected systems. 531 */ 532 533 Daemons[curdaemon].d_refuse_connections_until = curtime() + 15; 534#endif /* SO_REUSEADDR_IS_BROKEN */ 535 continue; 536 } 537 538 if (!control) 539 { 540 /* set some daemon related macros */ 541 switch (Daemons[curdaemon].d_addr.sa.sa_family) 542 { 543 case AF_UNSPEC: 544 macdefine(&BlankEnvelope.e_macro, A_PERM, 545 macid("{daemon_family}"), "unspec"); 546 break; 547#if _FFR_DAEMON_NETUNIX 548# if NETUNIX 549 case AF_UNIX: 550 macdefine(&BlankEnvelope.e_macro, A_PERM, 551 macid("{daemon_family}"), "local"); 552 break; 553# endif /* NETUNIX */ 554#endif /* _FFR_DAEMON_NETUNIX */ 555#if NETINET 556 case AF_INET: 557 macdefine(&BlankEnvelope.e_macro, A_PERM, 558 macid("{daemon_family}"), "inet"); 559 break; 560#endif /* NETINET */ 561#if NETINET6 562 case AF_INET6: 563 macdefine(&BlankEnvelope.e_macro, A_PERM, 564 macid("{daemon_family}"), "inet6"); 565 break; 566#endif /* NETINET6 */ 567#if NETISO 568 case AF_ISO: 569 macdefine(&BlankEnvelope.e_macro, A_PERM, 570 macid("{daemon_family}"), "iso"); 571 break; 572#endif /* NETISO */ 573#if NETNS 574 case AF_NS: 575 macdefine(&BlankEnvelope.e_macro, A_PERM, 576 macid("{daemon_family}"), "ns"); 577 break; 578#endif /* NETNS */ 579#if NETX25 580 case AF_CCITT: 581 macdefine(&BlankEnvelope.e_macro, A_PERM, 582 macid("{daemon_family}"), "x.25"); 583 break; 584#endif /* NETX25 */ 585 } 586 macdefine(&BlankEnvelope.e_macro, A_PERM, 587 macid("{daemon_name}"), 588 Daemons[curdaemon].d_name); 589 if (Daemons[curdaemon].d_mflags != NULL) 590 macdefine(&BlankEnvelope.e_macro, A_PERM, 591 macid("{daemon_flags}"), 592 Daemons[curdaemon].d_mflags); 593 else 594 macdefine(&BlankEnvelope.e_macro, A_PERM, 595 macid("{daemon_flags}"), ""); 596 } 597 598 /* 599 ** If connection rate is exceeded here, connection shall be 600 ** refused later by a new call after fork() by the 601 ** validate_connection() function. Closing the connection 602 ** at this point violates RFC 2821. 603 ** Do NOT remove this call, its side effects are needed. 604 */ 605 606 connection_rate_check(&RealHostAddr, NULL); 607 608 /* 609 ** Create a subprocess to process the mail. 610 */ 611 612 if (tTd(15, 2)) 613 sm_dprintf("getrequests: forking (fd = %d)\n", t); 614 615 /* 616 ** Advance state of PRNG. 617 ** This is necessary because otherwise all child processes 618 ** will produce the same PRN sequence and hence the selection 619 ** of a queue directory (and other things, e.g., MX selection) 620 ** are not "really" random. 621 */ 622#if STARTTLS 623 /* XXX get some better "random" data? */ 624 seed = get_random(); 625 RAND_seed((void *) &NextDiskSpaceCheck, 626 sizeof NextDiskSpaceCheck); 627 RAND_seed((void *) &now, sizeof now); 628 RAND_seed((void *) &seed, sizeof seed); 629#else /* STARTTLS */ 630 (void) get_random(); 631#endif /* STARTTLS */ 632 633#if NAMED_BIND 634 /* 635 ** Update MX records for FallbackMX. 636 ** Let's hope this is fast otherwise we screw up the 637 ** response time. 638 */ 639 640 if (FallbackMX != NULL) 641 (void) getfallbackmxrr(FallbackMX); 642#endif /* NAMED_BIND */ 643 644 if (tTd(93, 100)) 645 { 646 /* don't fork, handle connection in this process */ 647 pid = 0; 648 pipefd[0] = pipefd[1] = -1; 649 } 650 else 651 { 652 /* 653 ** Create a pipe to keep the child from writing to 654 ** the socket until after the parent has closed 655 ** it. Otherwise the parent may hang if the child 656 ** has closed it first. 657 */ 658 659 if (pipe(pipefd) < 0) 660 pipefd[0] = pipefd[1] = -1; 661 662 (void) sm_blocksignal(SIGCHLD); 663 pid = fork(); 664 if (pid < 0) 665 { 666 syserr("daemon: cannot fork"); 667 if (pipefd[0] != -1) 668 { 669 (void) close(pipefd[0]); 670 (void) close(pipefd[1]); 671 } 672 (void) sm_releasesignal(SIGCHLD); 673 (void) sleep(10); 674 (void) close(t); 675 continue; 676 } 677 } 678 679 if (pid == 0) 680 { 681 char *p; 682 SM_FILE_T *inchannel, *outchannel = NULL; 683 684 /* 685 ** CHILD -- return to caller. 686 ** Collect verified idea of sending host. 687 ** Verify calling user id if possible here. 688 */ 689 690 /* Reset global flags */ 691 RestartRequest = NULL; 692 RestartWorkGroup = false; 693 ShutdownRequest = NULL; 694 PendingSignal = 0; 695 CurrentPid = getpid(); 696 close_sendmail_pid(); 697 698 (void) sm_releasesignal(SIGALRM); 699 (void) sm_releasesignal(SIGCHLD); 700 (void) sm_signal(SIGCHLD, SIG_DFL); 701 (void) sm_signal(SIGHUP, SIG_DFL); 702 (void) sm_signal(SIGTERM, intsig); 703 704 /* turn on profiling */ 705 /* SM_PROF(0); */ 706 707 /* 708 ** Initialize exception stack and default exception 709 ** handler for child process. 710 */ 711 712 sm_exc_newthread(fatal_error); 713 714 if (!control) 715 { 716 macdefine(&BlankEnvelope.e_macro, A_TEMP, 717 macid("{daemon_addr}"), 718 anynet_ntoa(&Daemons[curdaemon].d_addr)); 719 (void) sm_snprintf(status, sizeof status, "%d", 720 ntohs(Daemons[curdaemon].d_port)); 721 macdefine(&BlankEnvelope.e_macro, A_TEMP, 722 macid("{daemon_port}"), status); 723 } 724 725 for (idx = 0; idx < NDaemons; idx++) 726 { 727 if (Daemons[idx].d_socket >= 0) 728 (void) close(Daemons[idx].d_socket); 729 Daemons[idx].d_socket = -1; 730 } 731 clrcontrol(); 732 733 /* Avoid SMTP daemon actions if control command */ 734 if (control) 735 { 736 /* Add control socket process */ 737 proc_list_add(CurrentPid, 738 "console socket child", 739 PROC_CONTROL_CHILD, 0, -1, NULL); 740 } 741 else 742 { 743 proc_list_clear(); 744 745 /* clean up background delivery children */ 746 (void) sm_signal(SIGCHLD, reapchild); 747 748 /* Add parent process as first child item */ 749 proc_list_add(CurrentPid, "daemon child", 750 PROC_DAEMON_CHILD, 0, -1, NULL); 751 752 /* don't schedule queue runs if ETRN */ 753 QueueIntvl = 0; 754#if _FFR_SS_PER_DAEMON 755 if (Daemons[curdaemon].d_supersafe != 756 SAFE_NOTSET) 757 SuperSafe = Daemons[curdaemon].d_supersafe; 758#endif /* _FFR_SS_PER_DAEMON */ 759#if _FFR_DM_PER_DAEMON 760 if (Daemons[curdaemon].d_dm != DM_NOTSET) 761 set_delivery_mode( 762 Daemons[curdaemon].d_dm, e); 763#endif /* _FFR_DM_PER_DAEMON */ 764 765 sm_setproctitle(true, e, "startup with %s", 766 anynet_ntoa(&RealHostAddr)); 767 } 768 769 if (pipefd[0] != -1) 770 { 771 auto char c; 772 773 /* 774 ** Wait for the parent to close the write end 775 ** of the pipe, which we will see as an EOF. 776 ** This guarantees that we won't write to the 777 ** socket until after the parent has closed 778 ** the pipe. 779 */ 780 781 /* close the write end of the pipe */ 782 (void) close(pipefd[1]); 783 784 /* we shouldn't be interrupted, but ... */ 785 while (read(pipefd[0], &c, 1) < 0 && 786 errno == EINTR) 787 continue; 788 (void) close(pipefd[0]); 789 } 790 791 /* control socket processing */ 792 if (control) 793 { 794 control_command(t, e); 795 /* NOTREACHED */ 796 exit(EX_SOFTWARE); 797 } 798 799 /* determine host name */ 800 p = hostnamebyanyaddr(&RealHostAddr); 801 if (strlen(p) > MAXNAME) /* XXX - 1 ? */ 802 p[MAXNAME] = '\0'; 803 RealHostName = newstr(p); 804 if (RealHostName[0] == '[') 805 { 806 macdefine(&BlankEnvelope.e_macro, A_PERM, 807 macid("{client_resolve}"), 808 h_errno == TRY_AGAIN ? "TEMP" : "FAIL"); 809 } 810 else 811 { 812 macdefine(&BlankEnvelope.e_macro, A_PERM, 813 macid("{client_resolve}"), "OK"); 814 } 815 sm_setproctitle(true, e, "startup with %s", p); 816 markstats(e, NULL, STATS_CONNECT); 817 818 if ((inchannel = sm_io_open(SmFtStdiofd, 819 SM_TIME_DEFAULT, 820 (void *) &t, 821 SM_IO_RDONLY_B, 822 NULL)) == NULL || 823 (t = dup(t)) < 0 || 824 (outchannel = sm_io_open(SmFtStdiofd, 825 SM_TIME_DEFAULT, 826 (void *) &t, 827 SM_IO_WRONLY_B, 828 NULL)) == NULL) 829 { 830 syserr("cannot open SMTP server channel, fd=%d", 831 t); 832 finis(false, true, EX_OK); 833 } 834 sm_io_automode(inchannel, outchannel); 835 836 InChannel = inchannel; 837 OutChannel = outchannel; 838 DisConnected = false; 839 840#if XLA 841 if (!xla_host_ok(RealHostName)) 842 { 843 message("421 4.4.5 Too many SMTP sessions for this host"); 844 finis(false, true, EX_OK); 845 } 846#endif /* XLA */ 847 /* find out name for interface of connection */ 848 if (getsockname(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 849 NULL), &sa.sa, &len) == 0) 850 { 851 p = hostnamebyanyaddr(&sa); 852 if (tTd(15, 9)) 853 sm_dprintf("getreq: got name %s\n", p); 854 macdefine(&BlankEnvelope.e_macro, A_TEMP, 855 macid("{if_name}"), p); 856 857 /* 858 ** Do this only if it is not the loopback 859 ** interface. 860 */ 861 862 if (!isloopback(sa)) 863 { 864 char *addr; 865 char family[5]; 866 867 addr = anynet_ntoa(&sa); 868 (void) sm_snprintf(family, 869 sizeof(family), 870 "%d", sa.sa.sa_family); 871 macdefine(&BlankEnvelope.e_macro, 872 A_TEMP, 873 macid("{if_addr}"), addr); 874 macdefine(&BlankEnvelope.e_macro, 875 A_TEMP, 876 macid("{if_family}"), family); 877 if (tTd(15, 7)) 878 sm_dprintf("getreq: got addr %s and family %s\n", 879 addr, family); 880 } 881 else 882 { 883 macdefine(&BlankEnvelope.e_macro, 884 A_PERM, 885 macid("{if_addr}"), NULL); 886 macdefine(&BlankEnvelope.e_macro, 887 A_PERM, 888 macid("{if_family}"), NULL); 889 } 890 } 891 else 892 { 893 if (tTd(15, 7)) 894 sm_dprintf("getreq: getsockname failed\n"); 895 macdefine(&BlankEnvelope.e_macro, A_PERM, 896 macid("{if_name}"), NULL); 897 macdefine(&BlankEnvelope.e_macro, A_PERM, 898 macid("{if_addr}"), NULL); 899 macdefine(&BlankEnvelope.e_macro, A_PERM, 900 macid("{if_family}"), NULL); 901 } 902 break; 903 } 904 905 /* parent -- keep track of children */ 906 if (control) 907 { 908 (void) sm_snprintf(status, sizeof status, 909 "control socket server child"); 910 proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL); 911 } 912 else 913 { 914 (void) sm_snprintf(status, sizeof status, 915 "SMTP server child for %s", 916 anynet_ntoa(&RealHostAddr)); 917 proc_list_add(pid, status, PROC_DAEMON, 0, -1, 918 &RealHostAddr); 919 } 920 (void) sm_releasesignal(SIGCHLD); 921 922 /* close the read end of the synchronization pipe */ 923 if (pipefd[0] != -1) 924 { 925 (void) close(pipefd[0]); 926 pipefd[0] = -1; 927 } 928 929 /* close the port so that others will hang (for a while) */ 930 (void) close(t); 931 932 /* release the child by closing the read end of the sync pipe */ 933 if (pipefd[1] != -1) 934 { 935 (void) close(pipefd[1]); 936 pipefd[1] = -1; 937 } 938 } 939 if (tTd(15, 2)) 940 sm_dprintf("getreq: returning\n"); 941 942#if MILTER 943 /* set the filters for this daemon */ 944 if (Daemons[curdaemon].d_inputfilterlist != NULL) 945 { 946 for (i = 0; 947 (i < MAXFILTERS && 948 Daemons[curdaemon].d_inputfilters[i] != NULL); 949 i++) 950 { 951 InputFilters[i] = Daemons[curdaemon].d_inputfilters[i]; 952 } 953 if (i < MAXFILTERS) 954 InputFilters[i] = NULL; 955 } 956#endif /* MILTER */ 957 return &Daemons[curdaemon].d_flags; 958} 959 960/* 961** GETREQUESTS_CHECKDISKSPACE -- check available diskspace. 962** 963** Parameters: 964** e -- envelope. 965** 966** Returns: 967** none. 968** 969** Side Effects: 970** Modifies Daemon flags (D_ETRNONLY) if not enough disk space. 971*/ 972 973static void 974getrequests_checkdiskspace(e) 975 ENVELOPE *e; 976{ 977 bool logged = false; 978 int idx; 979 time_t now; 980 981 now = curtime(); 982 if (now < NextDiskSpaceCheck) 983 return; 984 985 /* Check if there is available disk space in all queue groups. */ 986 if (!enoughdiskspace(0, NULL)) 987 { 988 for (idx = 0; idx < NDaemons; ++idx) 989 { 990 if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 991 continue; 992 993 /* log only if not logged before */ 994 if (!logged) 995 { 996 if (LogLevel > 8) 997 sm_syslog(LOG_INFO, NOQID, 998 "rejecting new messages: min free: %ld", 999 MinBlocksFree); 1000 sm_setproctitle(true, e, 1001 "rejecting new messages: min free: %ld", 1002 MinBlocksFree); 1003 logged = true; 1004 } 1005 setbitn(D_ETRNONLY, Daemons[idx].d_flags); 1006 } 1007 } 1008 else 1009 { 1010 for (idx = 0; idx < NDaemons; ++idx) 1011 { 1012 if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 1013 continue; 1014 1015 /* log only if not logged before */ 1016 if (!logged) 1017 { 1018 if (LogLevel > 8) 1019 sm_syslog(LOG_INFO, NOQID, 1020 "accepting new messages (again)"); 1021 logged = true; 1022 } 1023 1024 /* title will be set later */ 1025 clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 1026 } 1027 } 1028 1029 /* only check disk space once a minute */ 1030 NextDiskSpaceCheck = now + 60; 1031} 1032 1033/* 1034** OPENDAEMONSOCKET -- open SMTP socket 1035** 1036** Deals with setting all appropriate options. 1037** 1038** Parameters: 1039** d -- the structure for the daemon to open. 1040** firsttime -- set if this is the initial open. 1041** 1042** Returns: 1043** Size in bytes of the daemon socket addr. 1044** 1045** Side Effects: 1046** Leaves DaemonSocket set to the open socket. 1047** Exits if the socket cannot be created. 1048*/ 1049 1050#define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 1051 1052static int 1053opendaemonsocket(d, firsttime) 1054 DAEMON_T *d; 1055 bool firsttime; 1056{ 1057 int on = 1; 1058 int fdflags; 1059 SOCKADDR_LEN_T socksize = 0; 1060 int ntries = 0; 1061 int save_errno; 1062 1063 if (tTd(15, 2)) 1064 sm_dprintf("opendaemonsocket(%s)\n", d->d_name); 1065 1066 do 1067 { 1068 if (ntries > 0) 1069 (void) sleep(5); 1070 if (firsttime || d->d_socket < 0) 1071 { 1072#if _FFR_DAEMON_NETUNIX 1073# if NETUNIX 1074 if (d->d_addr.sa.sa_family == AF_UNIX) 1075 { 1076 int rval; 1077 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK|SFF_CREAT; 1078 1079 /* if not safe, don't use it */ 1080 rval = safefile(d->d_addr.sunix.sun_path, 1081 RunAsUid, RunAsGid, 1082 RunAsUserName, sff, 1083 S_IRUSR|S_IWUSR, NULL); 1084 if (rval != 0) 1085 { 1086 save_errno = errno; 1087 syserr("opendaemonsocket: daemon %s: unsafe domain socket %s", 1088 d->d_name, 1089 d->d_addr.sunix.sun_path); 1090 goto fail; 1091 } 1092 1093 /* Don't try to overtake an existing socket */ 1094 (void) unlink(d->d_addr.sunix.sun_path); 1095 } 1096# endif /* NETUNIX */ 1097#endif /* _FFR_DOMAIN_NETUNIX */ 1098 d->d_socket = socket(d->d_addr.sa.sa_family, 1099 SOCK_STREAM, 0); 1100 if (d->d_socket < 0) 1101 { 1102 save_errno = errno; 1103 syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", 1104 d->d_name); 1105 fail: 1106 if (bitnset(D_OPTIONAL, d->d_flags) && 1107 (!transienterror(save_errno) || 1108 ntries >= MAXOPENTRIES - 1)) 1109 { 1110 syserr("opendaemonsocket: daemon %s: optional socket disabled", 1111 d->d_name); 1112 setbitn(D_DISABLE, d->d_flags); 1113 d->d_socket = -1; 1114 return -1; 1115 } 1116 severe: 1117 if (LogLevel > 0) 1118 sm_syslog(LOG_ALERT, NOQID, 1119 "daemon %s: problem creating SMTP socket", 1120 d->d_name); 1121 d->d_socket = -1; 1122 continue; 1123 } 1124 1125 if (SM_FD_SETSIZE > 0 && d->d_socket >= SM_FD_SETSIZE) 1126 { 1127 save_errno = EINVAL; 1128 syserr("opendaemonsocket: daemon %s: server SMTP socket (%d) too large", 1129 d->d_name, d->d_socket); 1130 goto fail; 1131 } 1132 1133 /* turn on network debugging? */ 1134 if (tTd(15, 101)) 1135 (void) setsockopt(d->d_socket, SOL_SOCKET, 1136 SO_DEBUG, (char *)&on, 1137 sizeof on); 1138 1139 (void) setsockopt(d->d_socket, SOL_SOCKET, 1140 SO_REUSEADDR, (char *)&on, sizeof on); 1141 (void) setsockopt(d->d_socket, SOL_SOCKET, 1142 SO_KEEPALIVE, (char *)&on, sizeof on); 1143 1144#ifdef SO_RCVBUF 1145 if (d->d_tcprcvbufsize > 0) 1146 { 1147 if (setsockopt(d->d_socket, SOL_SOCKET, 1148 SO_RCVBUF, 1149 (char *) &d->d_tcprcvbufsize, 1150 sizeof(d->d_tcprcvbufsize)) < 0) 1151 syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 1152 } 1153#endif /* SO_RCVBUF */ 1154#ifdef SO_SNDBUF 1155 if (d->d_tcpsndbufsize > 0) 1156 { 1157 if (setsockopt(d->d_socket, SOL_SOCKET, 1158 SO_SNDBUF, 1159 (char *) &d->d_tcpsndbufsize, 1160 sizeof(d->d_tcpsndbufsize)) < 0) 1161 syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 1162 } 1163#endif /* SO_SNDBUF */ 1164 1165 if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 1166 fcntl(d->d_socket, F_SETFD, 1167 fdflags | FD_CLOEXEC) == -1) 1168 { 1169 save_errno = errno; 1170 syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 1171 d->d_name, 1172 fdflags == -1 ? "get" : "set", 1173 sm_errstring(save_errno)); 1174 (void) close(d->d_socket); 1175 goto severe; 1176 } 1177 1178 switch (d->d_addr.sa.sa_family) 1179 { 1180#if _FFR_DAEMON_NETUNIX 1181# ifdef NETUNIX 1182 case AF_UNIX: 1183 socksize = sizeof d->d_addr.sunix; 1184 break; 1185# endif /* NETUNIX */ 1186#endif /* _FFR_DAEMON_NETUNIX */ 1187#if NETINET 1188 case AF_INET: 1189 socksize = sizeof d->d_addr.sin; 1190 break; 1191#endif /* NETINET */ 1192 1193#if NETINET6 1194 case AF_INET6: 1195 socksize = sizeof d->d_addr.sin6; 1196 break; 1197#endif /* NETINET6 */ 1198 1199#if NETISO 1200 case AF_ISO: 1201 socksize = sizeof d->d_addr.siso; 1202 break; 1203#endif /* NETISO */ 1204 1205 default: 1206 socksize = sizeof d->d_addr; 1207 break; 1208 } 1209 1210 if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 1211 { 1212 /* probably another daemon already */ 1213 save_errno = errno; 1214 syserr("opendaemonsocket: daemon %s: cannot bind", 1215 d->d_name); 1216 (void) close(d->d_socket); 1217 goto fail; 1218 } 1219 } 1220 if (!firsttime && 1221 listen(d->d_socket, d->d_listenqueue) < 0) 1222 { 1223 save_errno = errno; 1224 syserr("opendaemonsocket: daemon %s: cannot listen", 1225 d->d_name); 1226 (void) close(d->d_socket); 1227 goto severe; 1228 } 1229 return socksize; 1230 } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 1231 syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 1232 d->d_name); 1233 /* NOTREACHED */ 1234 return -1; /* avoid compiler warning on IRIX */ 1235} 1236/* 1237** SETUPDAEMON -- setup socket for daemon 1238** 1239** Parameters: 1240** daemonaddr -- socket for daemon 1241** 1242** Returns: 1243** port number on which daemon should run 1244** 1245*/ 1246 1247static unsigned short 1248setupdaemon(daemonaddr) 1249 SOCKADDR *daemonaddr; 1250{ 1251 unsigned short port; 1252 1253 /* 1254 ** Set up the address for the mailer. 1255 */ 1256 1257 if (daemonaddr->sa.sa_family == AF_UNSPEC) 1258 { 1259 memset(daemonaddr, '\0', sizeof *daemonaddr); 1260#if NETINET 1261 daemonaddr->sa.sa_family = AF_INET; 1262#endif /* NETINET */ 1263 } 1264 1265 switch (daemonaddr->sa.sa_family) 1266 { 1267#if NETINET 1268 case AF_INET: 1269 if (daemonaddr->sin.sin_addr.s_addr == 0) 1270 daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 1271 port = daemonaddr->sin.sin_port; 1272 break; 1273#endif /* NETINET */ 1274 1275#if NETINET6 1276 case AF_INET6: 1277 if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 1278 daemonaddr->sin6.sin6_addr = in6addr_any; 1279 port = daemonaddr->sin6.sin6_port; 1280 break; 1281#endif /* NETINET6 */ 1282 1283 default: 1284 /* unknown protocol */ 1285 port = 0; 1286 break; 1287 } 1288 if (port == 0) 1289 { 1290#ifdef NO_GETSERVBYNAME 1291 port = htons(25); 1292#else /* NO_GETSERVBYNAME */ 1293 { 1294 register struct servent *sp; 1295 1296 sp = getservbyname("smtp", "tcp"); 1297 if (sp == NULL) 1298 { 1299 syserr("554 5.3.5 service \"smtp\" unknown"); 1300 port = htons(25); 1301 } 1302 else 1303 port = sp->s_port; 1304 } 1305#endif /* NO_GETSERVBYNAME */ 1306 } 1307 1308 switch (daemonaddr->sa.sa_family) 1309 { 1310#if NETINET 1311 case AF_INET: 1312 daemonaddr->sin.sin_port = port; 1313 break; 1314#endif /* NETINET */ 1315 1316#if NETINET6 1317 case AF_INET6: 1318 daemonaddr->sin6.sin6_port = port; 1319 break; 1320#endif /* NETINET6 */ 1321 1322 default: 1323 /* unknown protocol */ 1324 break; 1325 } 1326 return port; 1327} 1328/* 1329** CLRDAEMON -- reset the daemon connection 1330** 1331** Parameters: 1332** none. 1333** 1334** Returns: 1335** none. 1336** 1337** Side Effects: 1338** releases any resources used by the passive daemon. 1339*/ 1340 1341void 1342clrdaemon() 1343{ 1344 int i; 1345 1346 for (i = 0; i < NDaemons; i++) 1347 { 1348 if (Daemons[i].d_socket >= 0) 1349 (void) close(Daemons[i].d_socket); 1350 Daemons[i].d_socket = -1; 1351 } 1352} 1353 1354/* 1355** GETMODIFIERS -- get modifier flags 1356** 1357** Parameters: 1358** v -- the modifiers (input text line). 1359** modifiers -- pointer to flag field to represent modifiers. 1360** 1361** Returns: 1362** (xallocat()ed) string representation of modifiers. 1363** 1364** Side Effects: 1365** fills in modifiers. 1366*/ 1367 1368char * 1369getmodifiers(v, modifiers) 1370 char *v; 1371 BITMAP256 modifiers; 1372{ 1373 int l; 1374 char *h, *f, *flags; 1375 1376 /* maximum length of flags: upper case Option -> "OO " */ 1377 l = 3 * strlen(v) + 3; 1378 1379 /* is someone joking? */ 1380 if (l < 0 || l > 256) 1381 { 1382 if (LogLevel > 2) 1383 sm_syslog(LOG_ERR, NOQID, 1384 "getmodifiers too long, ignored"); 1385 return NULL; 1386 } 1387 flags = xalloc(l); 1388 f = flags; 1389 clrbitmap(modifiers); 1390 for (h = v; *h != '\0'; h++) 1391 { 1392 if (isascii(*h) && !isspace(*h) && isprint(*h)) 1393 { 1394 setbitn(*h, modifiers); 1395 if (flags != f) 1396 *flags++ = ' '; 1397 *flags++ = *h; 1398 if (isupper(*h)) 1399 *flags++ = *h; 1400 } 1401 } 1402 *flags++ = '\0'; 1403 return f; 1404} 1405 1406/* 1407** CHKDAEMONMODIFIERS -- check whether all daemons have set a flag. 1408** 1409** Parameters: 1410** flag -- the flag to test. 1411** 1412** Returns: 1413** true iff all daemons have set flag. 1414*/ 1415 1416bool 1417chkdaemonmodifiers(flag) 1418 int flag; 1419{ 1420 int i; 1421 1422 for (i = 0; i < NDaemons; i++) 1423 if (!bitnset((char) flag, Daemons[i].d_flags)) 1424 return false; 1425 return true; 1426} 1427 1428/* 1429** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 1430** 1431** Parameters: 1432** p -- the options line. 1433** d -- the daemon structure to fill in. 1434** 1435** Returns: 1436** none. 1437*/ 1438 1439static void 1440setsockaddroptions(p, d) 1441 char *p; 1442 DAEMON_T *d; 1443{ 1444#if NETISO 1445 short portno; 1446#endif /* NETISO */ 1447 char *port = NULL; 1448 char *addr = NULL; 1449 1450#if NETINET 1451 if (d->d_addr.sa.sa_family == AF_UNSPEC) 1452 d->d_addr.sa.sa_family = AF_INET; 1453#endif /* NETINET */ 1454#if _FFR_SS_PER_DAEMON 1455 d->d_supersafe = SAFE_NOTSET; 1456#endif /* _FFR_SS_PER_DAEMON */ 1457#if _FFR_DM_PER_DAEMON 1458 d->d_dm = DM_NOTSET; 1459#endif /* _FFR_DM_PER_DAEMON */ 1460 1461 while (p != NULL) 1462 { 1463 register char *f; 1464 register char *v; 1465 1466 while (isascii(*p) && isspace(*p)) 1467 p++; 1468 if (*p == '\0') 1469 break; 1470 f = p; 1471 p = strchr(p, ','); 1472 if (p != NULL) 1473 *p++ = '\0'; 1474 v = strchr(f, '='); 1475 if (v == NULL) 1476 continue; 1477 while (isascii(*++v) && isspace(*v)) 1478 continue; 1479 if (isascii(*f) && islower(*f)) 1480 *f = toupper(*f); 1481 1482 switch (*f) 1483 { 1484 case 'A': /* address */ 1485 addr = v; 1486 break; 1487 1488#if _FFR_DM_PER_DAEMON 1489 case 'D': /* DeliveryMode */ 1490 switch (*v) 1491 { 1492 case SM_QUEUE: 1493 case SM_DEFER: 1494 case SM_DELIVER: 1495 case SM_FORK: 1496 d->d_dm = *v; 1497 break; 1498 default: 1499 syserr("554 5.3.5 Unknown delivery mode %c", 1500 *v); 1501 break; 1502 } 1503 break; 1504#endif /* _FFR_DM_PER_DAEMON */ 1505 1506 case 'F': /* address family */ 1507 if (isascii(*v) && isdigit(*v)) 1508 d->d_addr.sa.sa_family = atoi(v); 1509#if _FFR_DAEMON_NETUNIX 1510# ifdef NETUNIX 1511 else if (sm_strcasecmp(v, "unix") == 0 || 1512 sm_strcasecmp(v, "local") == 0) 1513 d->d_addr.sa.sa_family = AF_UNIX; 1514# endif /* NETUNIX */ 1515#endif /* _FFR_DAEMON_NETUNIX */ 1516#if NETINET 1517 else if (sm_strcasecmp(v, "inet") == 0) 1518 d->d_addr.sa.sa_family = AF_INET; 1519#endif /* NETINET */ 1520#if NETINET6 1521 else if (sm_strcasecmp(v, "inet6") == 0) 1522 d->d_addr.sa.sa_family = AF_INET6; 1523#endif /* NETINET6 */ 1524#if NETISO 1525 else if (sm_strcasecmp(v, "iso") == 0) 1526 d->d_addr.sa.sa_family = AF_ISO; 1527#endif /* NETISO */ 1528#if NETNS 1529 else if (sm_strcasecmp(v, "ns") == 0) 1530 d->d_addr.sa.sa_family = AF_NS; 1531#endif /* NETNS */ 1532#if NETX25 1533 else if (sm_strcasecmp(v, "x.25") == 0) 1534 d->d_addr.sa.sa_family = AF_CCITT; 1535#endif /* NETX25 */ 1536 else 1537 syserr("554 5.3.5 Unknown address family %s in Family=option", 1538 v); 1539 break; 1540 1541#if MILTER 1542 case 'I': 1543 d->d_inputfilterlist = v; 1544 break; 1545#endif /* MILTER */ 1546 1547 case 'L': /* listen queue size */ 1548 d->d_listenqueue = atoi(v); 1549 break; 1550 1551 case 'M': /* modifiers (flags) */ 1552 d->d_mflags = getmodifiers(v, d->d_flags); 1553 break; 1554 1555 case 'N': /* name */ 1556 d->d_name = v; 1557 break; 1558 1559 case 'P': /* port */ 1560 port = v; 1561 break; 1562 1563 case 'R': /* receive buffer size */ 1564 d->d_tcprcvbufsize = atoi(v); 1565 break; 1566 1567 case 'S': /* send buffer size */ 1568 d->d_tcpsndbufsize = atoi(v); 1569 break; 1570 1571#if _FFR_SS_PER_DAEMON 1572 case 'T': /* SuperSafe */ 1573 if (tolower(*v) == 'i') 1574 d->d_supersafe = SAFE_INTERACTIVE; 1575 else if (tolower(*v) == 'p') 1576# if MILTER 1577 d->d_supersafe = SAFE_REALLY_POSTMILTER; 1578# else /* MILTER */ 1579 (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 1580 "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 1581# endif /* MILTER */ 1582 else 1583 d->d_supersafe = atobool(v) ? SAFE_REALLY 1584 : SAFE_NO; 1585 break; 1586#endif /* _FFR_SS_PER_DAEMON */ 1587 1588 default: 1589 syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 1590 f); 1591 } 1592 } 1593 1594 /* Check addr and port after finding family */ 1595 if (addr != NULL) 1596 { 1597 switch (d->d_addr.sa.sa_family) 1598 { 1599#if _FFR_DAEMON_NETUNIX 1600# if NETUNIX 1601 case AF_UNIX: 1602 if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) 1603 { 1604 errno = ENAMETOOLONG; 1605 syserr("setsockaddroptions: domain socket name too long: %s > %d", 1606 addr, sizeof(d->d_addr.sunix.sun_path)); 1607 break; 1608 } 1609 1610 /* file safety check done in opendaemonsocket() */ 1611 (void) memset(&d->d_addr.sunix.sun_path, '\0', 1612 sizeof(d->d_addr.sunix.sun_path)); 1613 (void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path, 1614 addr, 1615 sizeof(d->d_addr.sunix.sun_path)); 1616 break; 1617# endif /* NETUNIX */ 1618#endif /* _FFR_DAEMON_NETUNIX */ 1619#if NETINET 1620 case AF_INET: 1621 if (!isascii(*addr) || !isdigit(*addr) || 1622 ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) 1623 == INADDR_NONE)) 1624 { 1625 register struct hostent *hp; 1626 1627 hp = sm_gethostbyname(addr, AF_INET); 1628 if (hp == NULL) 1629 syserr("554 5.3.0 host \"%s\" unknown", 1630 addr); 1631 else 1632 { 1633 while (*(hp->h_addr_list) != NULL && 1634 hp->h_addrtype != AF_INET) 1635 hp->h_addr_list++; 1636 if (*(hp->h_addr_list) == NULL) 1637 syserr("554 5.3.0 host \"%s\" unknown", 1638 addr); 1639 else 1640 memmove(&d->d_addr.sin.sin_addr, 1641 *(hp->h_addr_list), 1642 INADDRSZ); 1643# if NETINET6 1644 freehostent(hp); 1645 hp = NULL; 1646# endif /* NETINET6 */ 1647 } 1648 } 1649 break; 1650#endif /* NETINET */ 1651 1652#if NETINET6 1653 case AF_INET6: 1654 if (anynet_pton(AF_INET6, addr, 1655 &d->d_addr.sin6.sin6_addr) != 1) 1656 { 1657 register struct hostent *hp; 1658 1659 hp = sm_gethostbyname(addr, AF_INET6); 1660 if (hp == NULL) 1661 syserr("554 5.3.0 host \"%s\" unknown", 1662 addr); 1663 else 1664 { 1665 while (*(hp->h_addr_list) != NULL && 1666 hp->h_addrtype != AF_INET6) 1667 hp->h_addr_list++; 1668 if (*(hp->h_addr_list) == NULL) 1669 syserr("554 5.3.0 host \"%s\" unknown", 1670 addr); 1671 else 1672 memmove(&d->d_addr.sin6.sin6_addr, 1673 *(hp->h_addr_list), 1674 IN6ADDRSZ); 1675 freehostent(hp); 1676 hp = NULL; 1677 } 1678 } 1679 break; 1680#endif /* NETINET6 */ 1681 1682 default: 1683 syserr("554 5.3.5 address= option unsupported for family %d", 1684 d->d_addr.sa.sa_family); 1685 break; 1686 } 1687 } 1688 1689 if (port != NULL) 1690 { 1691 switch (d->d_addr.sa.sa_family) 1692 { 1693#if NETINET 1694 case AF_INET: 1695 if (isascii(*port) && isdigit(*port)) 1696 d->d_addr.sin.sin_port = htons((unsigned short) 1697 atoi((const char *) port)); 1698 else 1699 { 1700# ifdef NO_GETSERVBYNAME 1701 syserr("554 5.3.5 invalid port number: %s", 1702 port); 1703# else /* NO_GETSERVBYNAME */ 1704 register struct servent *sp; 1705 1706 sp = getservbyname(port, "tcp"); 1707 if (sp == NULL) 1708 syserr("554 5.3.5 service \"%s\" unknown", 1709 port); 1710 else 1711 d->d_addr.sin.sin_port = sp->s_port; 1712# endif /* NO_GETSERVBYNAME */ 1713 } 1714 break; 1715#endif /* NETINET */ 1716 1717#if NETINET6 1718 case AF_INET6: 1719 if (isascii(*port) && isdigit(*port)) 1720 d->d_addr.sin6.sin6_port = htons((unsigned short) 1721 atoi(port)); 1722 else 1723 { 1724# ifdef NO_GETSERVBYNAME 1725 syserr("554 5.3.5 invalid port number: %s", 1726 port); 1727# else /* NO_GETSERVBYNAME */ 1728 register struct servent *sp; 1729 1730 sp = getservbyname(port, "tcp"); 1731 if (sp == NULL) 1732 syserr("554 5.3.5 service \"%s\" unknown", 1733 port); 1734 else 1735 d->d_addr.sin6.sin6_port = sp->s_port; 1736# endif /* NO_GETSERVBYNAME */ 1737 } 1738 break; 1739#endif /* NETINET6 */ 1740 1741#if NETISO 1742 case AF_ISO: 1743 /* assume two byte transport selector */ 1744 if (isascii(*port) && isdigit(*port)) 1745 portno = htons((unsigned short) atoi(port)); 1746 else 1747 { 1748# ifdef NO_GETSERVBYNAME 1749 syserr("554 5.3.5 invalid port number: %s", 1750 port); 1751# else /* NO_GETSERVBYNAME */ 1752 register struct servent *sp; 1753 1754 sp = getservbyname(port, "tcp"); 1755 if (sp == NULL) 1756 syserr("554 5.3.5 service \"%s\" unknown", 1757 port); 1758 else 1759 portno = sp->s_port; 1760# endif /* NO_GETSERVBYNAME */ 1761 } 1762 memmove(TSEL(&d->d_addr.siso), 1763 (char *) &portno, 2); 1764 break; 1765#endif /* NETISO */ 1766 1767 default: 1768 syserr("554 5.3.5 Port= option unsupported for family %d", 1769 d->d_addr.sa.sa_family); 1770 break; 1771 } 1772 } 1773} 1774/* 1775** SETDAEMONOPTIONS -- set options for running the MTA daemon 1776** 1777** Parameters: 1778** p -- the options line. 1779** 1780** Returns: 1781** true if successful, false otherwise. 1782** 1783** Side Effects: 1784** increments number of daemons. 1785*/ 1786 1787#define DEF_LISTENQUEUE 10 1788 1789struct dflags 1790{ 1791 char *d_name; 1792 int d_flag; 1793}; 1794 1795static struct dflags DaemonFlags[] = 1796{ 1797 { "AUTHREQ", D_AUTHREQ }, 1798 { "BINDIF", D_BINDIF }, 1799 { "CANONREQ", D_CANONREQ }, 1800 { "IFNHELO", D_IFNHELO }, 1801 { "FQMAIL", D_FQMAIL }, 1802 { "FQRCPT", D_FQRCPT }, 1803 { "SMTPS", D_SMTPS }, 1804 { "UNQUALOK", D_UNQUALOK }, 1805 { "NOAUTH", D_NOAUTH }, 1806 { "NOCANON", D_NOCANON }, 1807 { "NOETRN", D_NOETRN }, 1808 { "NOTLS", D_NOTLS }, 1809 { "ETRNONLY", D_ETRNONLY }, 1810 { "OPTIONAL", D_OPTIONAL }, 1811 { "DISABLE", D_DISABLE }, 1812 { "ISSET", D_ISSET }, 1813 { NULL, 0 } 1814}; 1815 1816static void 1817printdaemonflags(d) 1818 DAEMON_T *d; 1819{ 1820 register struct dflags *df; 1821 bool first = true; 1822 1823 for (df = DaemonFlags; df->d_name != NULL; df++) 1824 { 1825 if (!bitnset(df->d_flag, d->d_flags)) 1826 continue; 1827 if (first) 1828 sm_dprintf("<%s", df->d_name); 1829 else 1830 sm_dprintf(",%s", df->d_name); 1831 first = false; 1832 } 1833 if (!first) 1834 sm_dprintf(">"); 1835} 1836 1837bool 1838setdaemonoptions(p) 1839 register char *p; 1840{ 1841 if (NDaemons >= MAXDAEMONS) 1842 return false; 1843 Daemons[NDaemons].d_socket = -1; 1844 Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1845 clrbitmap(Daemons[NDaemons].d_flags); 1846 setsockaddroptions(p, &Daemons[NDaemons]); 1847 1848#if MILTER 1849 if (Daemons[NDaemons].d_inputfilterlist != NULL) 1850 Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist); 1851#endif /* MILTER */ 1852 1853 if (Daemons[NDaemons].d_name != NULL) 1854 Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name); 1855 else 1856 { 1857 char num[30]; 1858 1859 (void) sm_snprintf(num, sizeof num, "Daemon%d", NDaemons); 1860 Daemons[NDaemons].d_name = newstr(num); 1861 } 1862 1863 if (tTd(37, 1)) 1864 { 1865 sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name); 1866 printdaemonflags(&Daemons[NDaemons]); 1867 sm_dprintf("\n"); 1868 } 1869 ++NDaemons; 1870 return true; 1871} 1872/* 1873** INITDAEMON -- initialize daemon if not yet done. 1874** 1875** Parameters: 1876** none 1877** 1878** Returns: 1879** none 1880** 1881** Side Effects: 1882** initializes structure for one daemon. 1883*/ 1884 1885void 1886initdaemon() 1887{ 1888 if (NDaemons == 0) 1889 { 1890 Daemons[NDaemons].d_socket = -1; 1891 Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1892 Daemons[NDaemons].d_name = "Daemon0"; 1893 NDaemons = 1; 1894 } 1895} 1896/* 1897** SETCLIENTOPTIONS -- set options for running the client 1898** 1899** Parameters: 1900** p -- the options line. 1901** 1902** Returns: 1903** none. 1904*/ 1905 1906static DAEMON_T ClientSettings[AF_MAX + 1]; 1907 1908void 1909setclientoptions(p) 1910 register char *p; 1911{ 1912 int family; 1913 DAEMON_T d; 1914 1915 memset(&d, '\0', sizeof d); 1916 setsockaddroptions(p, &d); 1917 1918 /* grab what we need */ 1919 family = d.d_addr.sa.sa_family; 1920 STRUCTCOPY(d, ClientSettings[family]); 1921 setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */ 1922 if (d.d_name != NULL) 1923 ClientSettings[family].d_name = newstr(d.d_name); 1924 else 1925 { 1926 char num[30]; 1927 1928 (void) sm_snprintf(num, sizeof num, "Client%d", family); 1929 ClientSettings[family].d_name = newstr(num); 1930 } 1931} 1932/* 1933** ADDR_FAMILY -- determine address family from address 1934** 1935** Parameters: 1936** addr -- the string representation of the address 1937** 1938** Returns: 1939** AF_INET, AF_INET6 or AF_UNSPEC 1940** 1941** Side Effects: 1942** none. 1943*/ 1944 1945static int 1946addr_family(addr) 1947 char *addr; 1948{ 1949#if NETINET6 1950 SOCKADDR clt_addr; 1951#endif /* NETINET6 */ 1952 1953#if NETINET 1954 if (inet_addr(addr) != INADDR_NONE) 1955 { 1956 if (tTd(16, 9)) 1957 sm_dprintf("addr_family(%s): INET\n", addr); 1958 return AF_INET; 1959 } 1960#endif /* NETINET */ 1961#if NETINET6 1962 if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 1963 { 1964 if (tTd(16, 9)) 1965 sm_dprintf("addr_family(%s): INET6\n", addr); 1966 return AF_INET6; 1967 } 1968#endif /* NETINET6 */ 1969#if _FFR_DAEMON_NETUNIX 1970# if NETUNIX 1971 if (*addr == '/') 1972 { 1973 if (tTd(16, 9)) 1974 sm_dprintf("addr_family(%s): LOCAL\n", addr); 1975 return AF_UNIX; 1976 } 1977# endif /* NETUNIX */ 1978#endif /* _FFR_DAEMON_NETUNIX */ 1979 if (tTd(16, 9)) 1980 sm_dprintf("addr_family(%s): UNSPEC\n", addr); 1981 return AF_UNSPEC; 1982} 1983 1984/* 1985** CHKCLIENTMODIFIERS -- check whether all clients have set a flag. 1986** 1987** Parameters: 1988** flag -- the flag to test. 1989** 1990** Returns: 1991** true iff all configured clients have set the flag. 1992*/ 1993 1994bool 1995chkclientmodifiers(flag) 1996 int flag; 1997{ 1998 int i; 1999 bool flagisset; 2000 2001 flagisset = false; 2002 for (i = 0; i < AF_MAX; i++) 2003 { 2004 if (bitnset(D_ISSET, ClientSettings[i].d_flags)) 2005 { 2006 if (!bitnset((char) flag, ClientSettings[i].d_flags)) 2007 return false; 2008 flagisset = true; 2009 } 2010 } 2011 return flagisset; 2012} 2013 2014#if MILTER 2015/* 2016** SETUP_DAEMON_FILTERS -- Parse per-socket filters 2017** 2018** Parameters: 2019** none 2020** 2021** Returns: 2022** none 2023*/ 2024 2025void 2026setup_daemon_milters() 2027{ 2028 int idx; 2029 2030 if (OpMode == MD_SMTP) 2031 { 2032 /* no need to configure the daemons */ 2033 return; 2034 } 2035 2036 for (idx = 0; idx < NDaemons; idx++) 2037 { 2038 if (Daemons[idx].d_inputfilterlist != NULL) 2039 { 2040 milter_config(Daemons[idx].d_inputfilterlist, 2041 Daemons[idx].d_inputfilters, 2042 MAXFILTERS); 2043 } 2044 } 2045} 2046#endif /* MILTER */ 2047/* 2048** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 2049** 2050** Parameters: 2051** host -- the name of the host. 2052** port -- the port number to connect to. 2053** mci -- a pointer to the mail connection information 2054** structure to be filled in. 2055** e -- the current envelope. 2056** enough -- time at which to stop further connection attempts. 2057** (0 means no limit) 2058** 2059** Returns: 2060** An exit code telling whether the connection could be 2061** made and if not why not. 2062** 2063** Side Effects: 2064** none. 2065*/ 2066 2067static jmp_buf CtxConnectTimeout; 2068 2069SOCKADDR CurHostAddr; /* address of current host */ 2070 2071int 2072makeconnection(host, port, mci, e, enough) 2073 char *host; 2074 volatile unsigned int port; 2075 register MCI *mci; 2076 ENVELOPE *e; 2077 time_t enough; 2078{ 2079 register volatile int addrno = 0; 2080 volatile int s; 2081 register struct hostent *volatile hp = (struct hostent *) NULL; 2082 SOCKADDR addr; 2083 SOCKADDR clt_addr; 2084 int save_errno = 0; 2085 volatile SOCKADDR_LEN_T addrlen; 2086 volatile bool firstconnect; 2087 SM_EVENT *volatile ev = NULL; 2088#if NETINET6 2089 volatile bool v6found = false; 2090#endif /* NETINET6 */ 2091 volatile int family = InetMode; 2092 SOCKADDR_LEN_T len; 2093 volatile SOCKADDR_LEN_T socksize = 0; 2094 volatile bool clt_bind; 2095 BITMAP256 d_flags; 2096 char *p; 2097 extern ENVELOPE BlankEnvelope; 2098 2099 /* retranslate {daemon_flags} into bitmap */ 2100 clrbitmap(d_flags); 2101 if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL) 2102 { 2103 for (; *p != '\0'; p++) 2104 { 2105 if (!(isascii(*p) && isspace(*p))) 2106 setbitn(bitidx(*p), d_flags); 2107 } 2108 } 2109 2110#if NETINET6 2111 v4retry: 2112#endif /* NETINET6 */ 2113 clt_bind = false; 2114 2115 /* Set up the address for outgoing connection. */ 2116 if (bitnset(D_BINDIF, d_flags) && 2117 (p = macvalue(macid("{if_addr}"), e)) != NULL && 2118 *p != '\0') 2119 { 2120#if NETINET6 2121 char p6[INET6_ADDRSTRLEN]; 2122#endif /* NETINET6 */ 2123 2124 memset(&clt_addr, '\0', sizeof clt_addr); 2125 2126 /* infer the address family from the address itself */ 2127 clt_addr.sa.sa_family = addr_family(p); 2128 switch (clt_addr.sa.sa_family) 2129 { 2130#if NETINET 2131 case AF_INET: 2132 clt_addr.sin.sin_addr.s_addr = inet_addr(p); 2133 if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 2134 clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) 2135 { 2136 clt_bind = true; 2137 socksize = sizeof (struct sockaddr_in); 2138 } 2139 break; 2140#endif /* NETINET */ 2141 2142#if NETINET6 2143 case AF_INET6: 2144 if (inet_addr(p) != INADDR_NONE) 2145 (void) sm_snprintf(p6, sizeof p6, 2146 "IPv6:::ffff:%s", p); 2147 else 2148 (void) sm_strlcpy(p6, p, sizeof p6); 2149 if (anynet_pton(AF_INET6, p6, 2150 &clt_addr.sin6.sin6_addr) == 1 && 2151 !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 2152 { 2153 clt_bind = true; 2154 socksize = sizeof (struct sockaddr_in6); 2155 } 2156 break; 2157#endif /* NETINET6 */ 2158 2159#if 0 2160 default: 2161 syserr("554 5.3.5 Address= option unsupported for family %d", 2162 clt_addr.sa.sa_family); 2163 break; 2164#endif /* 0 */ 2165 } 2166 if (clt_bind) 2167 family = clt_addr.sa.sa_family; 2168 } 2169 2170 /* D_BINDIF not set or not available, fallback to ClientPortOptions */ 2171 if (!clt_bind) 2172 { 2173 STRUCTCOPY(ClientSettings[family].d_addr, clt_addr); 2174 switch (clt_addr.sa.sa_family) 2175 { 2176#if NETINET 2177 case AF_INET: 2178 if (clt_addr.sin.sin_addr.s_addr == 0) 2179 clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 2180 else 2181 clt_bind = true; 2182 if (clt_addr.sin.sin_port != 0) 2183 clt_bind = true; 2184 socksize = sizeof (struct sockaddr_in); 2185 break; 2186#endif /* NETINET */ 2187#if NETINET6 2188 case AF_INET6: 2189 if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 2190 clt_addr.sin6.sin6_addr = in6addr_any; 2191 else 2192 clt_bind = true; 2193 socksize = sizeof (struct sockaddr_in6); 2194 if (clt_addr.sin6.sin6_port != 0) 2195 clt_bind = true; 2196 break; 2197#endif /* NETINET6 */ 2198#if NETISO 2199 case AF_ISO: 2200 socksize = sizeof clt_addr.siso; 2201 clt_bind = true; 2202 break; 2203#endif /* NETISO */ 2204 default: 2205 break; 2206 } 2207 } 2208 2209 /* 2210 ** Set up the address for the mailer. 2211 ** Accept "[a.b.c.d]" syntax for host name. 2212 */ 2213 2214 SM_SET_H_ERRNO(0); 2215 errno = 0; 2216 memset(&CurHostAddr, '\0', sizeof CurHostAddr); 2217 memset(&addr, '\0', sizeof addr); 2218 SmtpPhase = mci->mci_phase = "initial connection"; 2219 CurHostName = host; 2220 2221 if (host[0] == '[') 2222 { 2223 p = strchr(host, ']'); 2224 if (p != NULL) 2225 { 2226#if NETINET 2227 unsigned long hid = INADDR_NONE; 2228#endif /* NETINET */ 2229#if NETINET6 2230 struct sockaddr_in6 hid6; 2231#endif /* NETINET6 */ 2232 2233 *p = '\0'; 2234#if NETINET6 2235 memset(&hid6, '\0', sizeof hid6); 2236#endif /* NETINET6 */ 2237#if NETINET 2238 if (family == AF_INET && 2239 (hid = inet_addr(&host[1])) != INADDR_NONE) 2240 { 2241 addr.sin.sin_family = AF_INET; 2242 addr.sin.sin_addr.s_addr = hid; 2243 } 2244 else 2245#endif /* NETINET */ 2246#if NETINET6 2247 if (family == AF_INET6 && 2248 anynet_pton(AF_INET6, &host[1], 2249 &hid6.sin6_addr) == 1) 2250 { 2251 addr.sin6.sin6_family = AF_INET6; 2252 addr.sin6.sin6_addr = hid6.sin6_addr; 2253 } 2254 else 2255#endif /* NETINET6 */ 2256 { 2257 /* try it as a host name (avoid MX lookup) */ 2258 hp = sm_gethostbyname(&host[1], family); 2259 if (hp == NULL && p[-1] == '.') 2260 { 2261#if NAMED_BIND 2262 int oldopts = _res.options; 2263 2264 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2265#endif /* NAMED_BIND */ 2266 p[-1] = '\0'; 2267 hp = sm_gethostbyname(&host[1], 2268 family); 2269 p[-1] = '.'; 2270#if NAMED_BIND 2271 _res.options = oldopts; 2272#endif /* NAMED_BIND */ 2273 } 2274 *p = ']'; 2275 goto gothostent; 2276 } 2277 *p = ']'; 2278 } 2279 if (p == NULL) 2280 { 2281 extern char MsgBuf[]; 2282 2283 usrerrenh("5.1.2", 2284 "553 Invalid numeric domain spec \"%s\"", 2285 host); 2286 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 2287 errno = EINVAL; 2288 return EX_NOHOST; 2289 } 2290 } 2291 else 2292 { 2293 /* contortion to get around SGI cc complaints */ 2294 { 2295 p = &host[strlen(host) - 1]; 2296 hp = sm_gethostbyname(host, family); 2297 if (hp == NULL && *p == '.') 2298 { 2299#if NAMED_BIND 2300 int oldopts = _res.options; 2301 2302 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2303#endif /* NAMED_BIND */ 2304 *p = '\0'; 2305 hp = sm_gethostbyname(host, family); 2306 *p = '.'; 2307#if NAMED_BIND 2308 _res.options = oldopts; 2309#endif /* NAMED_BIND */ 2310 } 2311 } 2312gothostent: 2313 if (hp == NULL) 2314 { 2315#if NAMED_BIND 2316 /* check for name server timeouts */ 2317# if NETINET6 2318 if (WorkAroundBrokenAAAA && family == AF_INET6 && 2319 errno == ETIMEDOUT) 2320 { 2321 /* 2322 ** An attempt with family AF_INET may 2323 ** succeed By skipping the next section 2324 ** of code, we will try AF_INET before 2325 ** failing. 2326 */ 2327 2328 if (tTd(16, 10)) 2329 sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n"); 2330 } 2331 else 2332# endif /* NETINET6 */ 2333 { 2334 if (errno == ETIMEDOUT || 2335 h_errno == TRY_AGAIN || 2336 (errno == ECONNREFUSED && UseNameServer)) 2337 { 2338 save_errno = errno; 2339 mci_setstat(mci, EX_TEMPFAIL, 2340 "4.4.3", NULL); 2341 errno = save_errno; 2342 return EX_TEMPFAIL; 2343 } 2344 } 2345#endif /* NAMED_BIND */ 2346#if NETINET6 2347 /* 2348 ** Try v6 first, then fall back to v4. 2349 ** If we found a v6 address, but no v4 2350 ** addresses, then TEMPFAIL. 2351 */ 2352 2353 if (family == AF_INET6) 2354 { 2355 family = AF_INET; 2356 goto v4retry; 2357 } 2358 if (v6found) 2359 goto v6tempfail; 2360#endif /* NETINET6 */ 2361 save_errno = errno; 2362 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2363 errno = save_errno; 2364 return EX_NOHOST; 2365 } 2366 addr.sa.sa_family = hp->h_addrtype; 2367 switch (hp->h_addrtype) 2368 { 2369#if NETINET 2370 case AF_INET: 2371 memmove(&addr.sin.sin_addr, 2372 hp->h_addr, 2373 INADDRSZ); 2374 break; 2375#endif /* NETINET */ 2376 2377#if NETINET6 2378 case AF_INET6: 2379 memmove(&addr.sin6.sin6_addr, 2380 hp->h_addr, 2381 IN6ADDRSZ); 2382 break; 2383#endif /* NETINET6 */ 2384 2385 default: 2386 if (hp->h_length > sizeof addr.sa.sa_data) 2387 { 2388 syserr("makeconnection: long sa_data: family %d len %d", 2389 hp->h_addrtype, hp->h_length); 2390 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2391 errno = EINVAL; 2392 return EX_NOHOST; 2393 } 2394 memmove(addr.sa.sa_data, hp->h_addr, hp->h_length); 2395 break; 2396 } 2397 addrno = 1; 2398 } 2399 2400 /* 2401 ** Determine the port number. 2402 */ 2403 2404 if (port == 0) 2405 { 2406#ifdef NO_GETSERVBYNAME 2407 port = htons(25); 2408#else /* NO_GETSERVBYNAME */ 2409 register struct servent *sp = getservbyname("smtp", "tcp"); 2410 2411 if (sp == NULL) 2412 { 2413 if (LogLevel > 2) 2414 sm_syslog(LOG_ERR, NOQID, 2415 "makeconnection: service \"smtp\" unknown"); 2416 port = htons(25); 2417 } 2418 else 2419 port = sp->s_port; 2420#endif /* NO_GETSERVBYNAME */ 2421 } 2422 2423#if NETINET6 2424 if (addr.sa.sa_family == AF_INET6 && 2425 IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) && 2426 ClientSettings[AF_INET].d_addr.sa.sa_family != 0) 2427 { 2428 /* 2429 ** Ignore mapped IPv4 address since 2430 ** there is a ClientPortOptions setting 2431 ** for IPv4. 2432 */ 2433 2434 goto nextaddr; 2435 } 2436#endif /* NETINET6 */ 2437 2438 switch (addr.sa.sa_family) 2439 { 2440#if NETINET 2441 case AF_INET: 2442 addr.sin.sin_port = port; 2443 addrlen = sizeof (struct sockaddr_in); 2444 break; 2445#endif /* NETINET */ 2446 2447#if NETINET6 2448 case AF_INET6: 2449 addr.sin6.sin6_port = port; 2450 addrlen = sizeof (struct sockaddr_in6); 2451 break; 2452#endif /* NETINET6 */ 2453 2454#if NETISO 2455 case AF_ISO: 2456 /* assume two byte transport selector */ 2457 memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 2458 addrlen = sizeof (struct sockaddr_iso); 2459 break; 2460#endif /* NETISO */ 2461 2462 default: 2463 syserr("Can't connect to address family %d", addr.sa.sa_family); 2464 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2465 errno = EINVAL; 2466#if NETINET6 2467 if (hp != NULL) 2468 freehostent(hp); 2469#endif /* NETINET6 */ 2470 return EX_NOHOST; 2471 } 2472 2473 /* 2474 ** Try to actually open the connection. 2475 */ 2476 2477#if XLA 2478 /* if too many connections, don't bother trying */ 2479 if (!xla_noqueue_ok(host)) 2480 { 2481# if NETINET6 2482 if (hp != NULL) 2483 freehostent(hp); 2484# endif /* NETINET6 */ 2485 return EX_TEMPFAIL; 2486 } 2487#endif /* XLA */ 2488 2489 firstconnect = true; 2490 for (;;) 2491 { 2492 if (tTd(16, 1)) 2493 sm_dprintf("makeconnection (%s [%s].%d (%d))\n", 2494 host, anynet_ntoa(&addr), ntohs(port), 2495 (int) addr.sa.sa_family); 2496 2497 /* save for logging */ 2498 CurHostAddr = addr; 2499 2500#if HASRRESVPORT 2501 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 2502 { 2503 int rport = IPPORT_RESERVED - 1; 2504 2505 s = rresvport(&rport); 2506 } 2507 else 2508#endif /* HASRRESVPORT */ 2509 { 2510 s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 2511 } 2512 if (s < 0) 2513 { 2514 save_errno = errno; 2515 syserr("makeconnection: cannot create socket"); 2516#if XLA 2517 xla_host_end(host); 2518#endif /* XLA */ 2519 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2520#if NETINET6 2521 if (hp != NULL) 2522 freehostent(hp); 2523#endif /* NETINET6 */ 2524 errno = save_errno; 2525 return EX_TEMPFAIL; 2526 } 2527 2528#ifdef SO_SNDBUF 2529 if (ClientSettings[family].d_tcpsndbufsize > 0) 2530 { 2531 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 2532 (char *) &ClientSettings[family].d_tcpsndbufsize, 2533 sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0) 2534 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 2535 } 2536#endif /* SO_SNDBUF */ 2537#ifdef SO_RCVBUF 2538 if (ClientSettings[family].d_tcprcvbufsize > 0) 2539 { 2540 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2541 (char *) &ClientSettings[family].d_tcprcvbufsize, 2542 sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0) 2543 syserr("makeconnection: setsockopt(SO_RCVBUF)"); 2544 } 2545#endif /* SO_RCVBUF */ 2546 2547 if (tTd(16, 1)) 2548 sm_dprintf("makeconnection: fd=%d\n", s); 2549 2550 /* turn on network debugging? */ 2551 if (tTd(16, 101)) 2552 { 2553 int on = 1; 2554 2555 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2556 (char *)&on, sizeof on); 2557 } 2558 if (e->e_xfp != NULL) /* for debugging */ 2559 (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 2560 errno = 0; /* for debugging */ 2561 2562 if (clt_bind) 2563 { 2564 int on = 1; 2565 2566 switch (clt_addr.sa.sa_family) 2567 { 2568#if NETINET 2569 case AF_INET: 2570 if (clt_addr.sin.sin_port != 0) 2571 (void) setsockopt(s, SOL_SOCKET, 2572 SO_REUSEADDR, 2573 (char *) &on, 2574 sizeof on); 2575 break; 2576#endif /* NETINET */ 2577 2578#if NETINET6 2579 case AF_INET6: 2580 if (clt_addr.sin6.sin6_port != 0) 2581 (void) setsockopt(s, SOL_SOCKET, 2582 SO_REUSEADDR, 2583 (char *) &on, 2584 sizeof on); 2585 break; 2586#endif /* NETINET6 */ 2587 } 2588 2589 if (bind(s, &clt_addr.sa, socksize) < 0) 2590 { 2591 save_errno = errno; 2592 (void) close(s); 2593 errno = save_errno; 2594 syserr("makeconnection: cannot bind socket [%s]", 2595 anynet_ntoa(&clt_addr)); 2596#if NETINET6 2597 if (hp != NULL) 2598 freehostent(hp); 2599#endif /* NETINET6 */ 2600 errno = save_errno; 2601 return EX_TEMPFAIL; 2602 } 2603 } 2604 2605 /* 2606 ** Linux seems to hang in connect for 90 minutes (!!!). 2607 ** Time out the connect to avoid this problem. 2608 */ 2609 2610 if (setjmp(CtxConnectTimeout) == 0) 2611 { 2612 int i; 2613 2614 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 2615 ev = sm_setevent(TimeOuts.to_iconnect, 2616 connecttimeout, 0); 2617 else if (TimeOuts.to_connect != 0) 2618 ev = sm_setevent(TimeOuts.to_connect, 2619 connecttimeout, 0); 2620 else 2621 ev = NULL; 2622 2623 switch (ConnectOnlyTo.sa.sa_family) 2624 { 2625#if NETINET 2626 case AF_INET: 2627 addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 2628 break; 2629#endif /* NETINET */ 2630 2631#if NETINET6 2632 case AF_INET6: 2633 memmove(&addr.sin6.sin6_addr, 2634 &ConnectOnlyTo.sin6.sin6_addr, 2635 IN6ADDRSZ); 2636 break; 2637#endif /* NETINET6 */ 2638 } 2639 if (tTd(16, 1)) 2640 sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr)); 2641 i = connect(s, (struct sockaddr *) &addr, addrlen); 2642 save_errno = errno; 2643 if (ev != NULL) 2644 sm_clrevent(ev); 2645 if (i >= 0) 2646 break; 2647 } 2648 else 2649 save_errno = errno; 2650 2651 /* couldn't connect.... figure out why */ 2652 (void) close(s); 2653 2654 /* if running demand-dialed connection, try again */ 2655 if (DialDelay > 0 && firstconnect && 2656 bitnset(M_DIALDELAY, mci->mci_mailer->m_flags)) 2657 { 2658 if (tTd(16, 1)) 2659 sm_dprintf("Connect failed (%s); trying again...\n", 2660 sm_errstring(save_errno)); 2661 firstconnect = false; 2662 (void) sleep(DialDelay); 2663 continue; 2664 } 2665 2666 if (LogLevel > 13) 2667 sm_syslog(LOG_INFO, e->e_id, 2668 "makeconnection (%s [%s]) failed: %s", 2669 host, anynet_ntoa(&addr), 2670 sm_errstring(save_errno)); 2671 2672#if NETINET6 2673nextaddr: 2674#endif /* NETINET6 */ 2675 if (hp != NULL && hp->h_addr_list[addrno] != NULL && 2676 (enough == 0 || curtime() < enough)) 2677 { 2678 if (tTd(16, 1)) 2679 sm_dprintf("Connect failed (%s); trying new address....\n", 2680 sm_errstring(save_errno)); 2681 switch (addr.sa.sa_family) 2682 { 2683#if NETINET 2684 case AF_INET: 2685 memmove(&addr.sin.sin_addr, 2686 hp->h_addr_list[addrno++], 2687 INADDRSZ); 2688 break; 2689#endif /* NETINET */ 2690 2691#if NETINET6 2692 case AF_INET6: 2693 memmove(&addr.sin6.sin6_addr, 2694 hp->h_addr_list[addrno++], 2695 IN6ADDRSZ); 2696 break; 2697#endif /* NETINET6 */ 2698 2699 default: 2700 memmove(addr.sa.sa_data, 2701 hp->h_addr_list[addrno++], 2702 hp->h_length); 2703 break; 2704 } 2705 continue; 2706 } 2707 errno = save_errno; 2708 2709#if NETINET6 2710 if (family == AF_INET6) 2711 { 2712 if (tTd(16, 1)) 2713 sm_dprintf("Connect failed (%s); retrying with AF_INET....\n", 2714 sm_errstring(save_errno)); 2715 v6found = true; 2716 family = AF_INET; 2717 if (hp != NULL) 2718 { 2719 freehostent(hp); 2720 hp = NULL; 2721 } 2722 goto v4retry; 2723 } 2724 v6tempfail: 2725#endif /* NETINET6 */ 2726 /* couldn't open connection */ 2727#if NETINET6 2728 /* Don't clobber an already saved errno from v4retry */ 2729 if (errno > 0) 2730#endif /* NETINET6 */ 2731 save_errno = errno; 2732 if (tTd(16, 1)) 2733 sm_dprintf("Connect failed (%s)\n", 2734 sm_errstring(save_errno)); 2735#if XLA 2736 xla_host_end(host); 2737#endif /* XLA */ 2738 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2739#if NETINET6 2740 if (hp != NULL) 2741 freehostent(hp); 2742#endif /* NETINET6 */ 2743 errno = save_errno; 2744 return EX_TEMPFAIL; 2745 } 2746 2747#if NETINET6 2748 if (hp != NULL) 2749 { 2750 freehostent(hp); 2751 hp = NULL; 2752 } 2753#endif /* NETINET6 */ 2754 2755 /* connection ok, put it into canonical form */ 2756 mci->mci_out = NULL; 2757 if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2758 (void *) &s, 2759 SM_IO_WRONLY_B, NULL)) == NULL || 2760 (s = dup(s)) < 0 || 2761 (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2762 (void *) &s, 2763 SM_IO_RDONLY_B, NULL)) == NULL) 2764 { 2765 save_errno = errno; 2766 syserr("cannot open SMTP client channel, fd=%d", s); 2767 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2768 if (mci->mci_out != NULL) 2769 (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2770 (void) close(s); 2771 errno = save_errno; 2772 return EX_TEMPFAIL; 2773 } 2774 sm_io_automode(mci->mci_out, mci->mci_in); 2775 2776 /* set {client_flags} */ 2777 if (ClientSettings[addr.sa.sa_family].d_mflags != NULL) 2778 { 2779 macdefine(&mci->mci_macro, A_PERM, 2780 macid("{client_flags}"), 2781 ClientSettings[addr.sa.sa_family].d_mflags); 2782 } 2783 else 2784 macdefine(&mci->mci_macro, A_PERM, 2785 macid("{client_flags}"), ""); 2786 2787 /* "add" {client_flags} to bitmap */ 2788 if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags)) 2789 { 2790 /* look for just this one flag */ 2791 setbitn(D_IFNHELO, d_flags); 2792 } 2793 2794 /* find out name for Interface through which we connect */ 2795 len = sizeof addr; 2796 if (getsockname(s, &addr.sa, &len) == 0) 2797 { 2798 char *name; 2799 char family[5]; 2800 2801 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2802 macid("{if_addr_out}"), anynet_ntoa(&addr)); 2803 (void) sm_snprintf(family, sizeof(family), "%d", 2804 addr.sa.sa_family); 2805 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2806 macid("{if_family_out}"), family); 2807 2808 name = hostnamebyanyaddr(&addr); 2809 macdefine(&BlankEnvelope.e_macro, A_TEMP, 2810 macid("{if_name_out}"), name); 2811 if (LogLevel > 11) 2812 { 2813 /* log connection information */ 2814 sm_syslog(LOG_INFO, e->e_id, 2815 "SMTP outgoing connect on %.40s", name); 2816 } 2817 if (bitnset(D_IFNHELO, d_flags)) 2818 { 2819 if (name[0] != '[' && strchr(name, '.') != NULL) 2820 mci->mci_heloname = newstr(name); 2821 } 2822 } 2823 else 2824 { 2825 macdefine(&BlankEnvelope.e_macro, A_PERM, 2826 macid("{if_name_out}"), NULL); 2827 macdefine(&BlankEnvelope.e_macro, A_PERM, 2828 macid("{if_addr_out}"), NULL); 2829 macdefine(&BlankEnvelope.e_macro, A_PERM, 2830 macid("{if_family_out}"), NULL); 2831 } 2832 2833#if _FFR_HELONAME 2834 /* Use the configured HeloName as appropriate */ 2835 if (HeloName != NULL && HeloName[0] != '\0') 2836 mci->mci_heloname = newstr(HeloName); 2837#endif /* _FFR_HELONAME */ 2838 2839 mci_setstat(mci, EX_OK, NULL, NULL); 2840 return EX_OK; 2841} 2842 2843static void 2844connecttimeout(ignore) 2845 int ignore; 2846{ 2847 /* 2848 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2849 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2850 ** DOING. 2851 */ 2852 2853 errno = ETIMEDOUT; 2854 longjmp(CtxConnectTimeout, 1); 2855} 2856/* 2857** MAKECONNECTION_DS -- make a connection to a domain socket. 2858** 2859** Parameters: 2860** mux_path -- the path of the socket to connect to. 2861** mci -- a pointer to the mail connection information 2862** structure to be filled in. 2863** 2864** Returns: 2865** An exit code telling whether the connection could be 2866** made and if not why not. 2867** 2868** Side Effects: 2869** none. 2870*/ 2871 2872#if NETUNIX 2873int 2874makeconnection_ds(mux_path, mci) 2875 char *mux_path; 2876 register MCI *mci; 2877{ 2878 int sock; 2879 int rval, save_errno; 2880 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 2881 struct sockaddr_un unix_addr; 2882 2883 /* if not safe, don't connect */ 2884 rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 2885 sff, S_IRUSR|S_IWUSR, NULL); 2886 2887 if (rval != 0) 2888 { 2889 syserr("makeconnection_ds: unsafe domain socket %s", 2890 mux_path); 2891 mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 2892 errno = rval; 2893 return EX_TEMPFAIL; 2894 } 2895 2896 /* prepare address structure */ 2897 memset(&unix_addr, '\0', sizeof unix_addr); 2898 unix_addr.sun_family = AF_UNIX; 2899 2900 if (strlen(mux_path) >= sizeof unix_addr.sun_path) 2901 { 2902 syserr("makeconnection_ds: domain socket name %s too long", 2903 mux_path); 2904 2905 /* XXX why TEMPFAIL but 5.x.y ? */ 2906 mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 2907 errno = ENAMETOOLONG; 2908 return EX_UNAVAILABLE; 2909 } 2910 (void) sm_strlcpy(unix_addr.sun_path, mux_path, 2911 sizeof unix_addr.sun_path); 2912 2913 /* initialize domain socket */ 2914 sock = socket(AF_UNIX, SOCK_STREAM, 0); 2915 if (sock == -1) 2916 { 2917 save_errno = errno; 2918 syserr("makeconnection_ds: could not create domain socket %s", 2919 mux_path); 2920 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2921 errno = save_errno; 2922 return EX_TEMPFAIL; 2923 } 2924 2925 /* connect to server */ 2926 if (connect(sock, (struct sockaddr *) &unix_addr, 2927 sizeof(unix_addr)) == -1) 2928 { 2929 save_errno = errno; 2930 syserr("Could not connect to socket %s", mux_path); 2931 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2932 (void) close(sock); 2933 errno = save_errno; 2934 return EX_TEMPFAIL; 2935 } 2936 2937 /* connection ok, put it into canonical form */ 2938 mci->mci_out = NULL; 2939 if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2940 (void *) &sock, SM_IO_WRONLY_B, NULL)) 2941 == NULL 2942 || (sock = dup(sock)) < 0 || 2943 (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2944 (void *) &sock, SM_IO_RDONLY_B, NULL)) 2945 == NULL) 2946 { 2947 save_errno = errno; 2948 syserr("cannot open SMTP client channel, fd=%d", sock); 2949 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2950 if (mci->mci_out != NULL) 2951 (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2952 (void) close(sock); 2953 errno = save_errno; 2954 return EX_TEMPFAIL; 2955 } 2956 sm_io_automode(mci->mci_out, mci->mci_in); 2957 2958 mci_setstat(mci, EX_OK, NULL, NULL); 2959 errno = 0; 2960 return EX_OK; 2961} 2962#endif /* NETUNIX */ 2963/* 2964** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon 2965** 2966** Parameters: 2967** none. 2968** 2969** Returns: 2970** none. 2971** 2972** Side Effects: 2973** closes control socket, exits. 2974*/ 2975 2976void 2977shutdown_daemon() 2978{ 2979 int i; 2980 char *reason; 2981 2982 sm_allsignals(true); 2983 2984 reason = ShutdownRequest; 2985 ShutdownRequest = NULL; 2986 PendingSignal = 0; 2987 2988 if (LogLevel > 9) 2989 sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s", 2990 reason == NULL ? "implicit call" : reason); 2991 2992 FileName = NULL; 2993 closecontrolsocket(true); 2994#if XLA 2995 xla_all_end(); 2996#endif /* XLA */ 2997 2998 for (i = 0; i < NDaemons; i++) 2999 { 3000 if (Daemons[i].d_socket >= 0) 3001 { 3002 (void) close(Daemons[i].d_socket); 3003 Daemons[i].d_socket = -1; 3004 3005#if _FFR_DAEMON_NETUNIX 3006# if NETUNIX 3007 /* Remove named sockets */ 3008 if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) 3009 { 3010 int rval; 3011 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT; 3012 3013 /* if not safe, don't use it */ 3014 rval = safefile(Daemons[i].d_addr.sunix.sun_path, 3015 RunAsUid, RunAsGid, 3016 RunAsUserName, sff, 3017 S_IRUSR|S_IWUSR, NULL); 3018 if (rval == 0 && 3019 unlink(Daemons[i].d_addr.sunix.sun_path) < 0) 3020 { 3021 sm_syslog(LOG_WARNING, NOQID, 3022 "Could not remove daemon %s socket: %s: %s", 3023 Daemons[i].d_name, 3024 Daemons[i].d_addr.sunix.sun_path, 3025 sm_errstring(errno)); 3026 } 3027 } 3028# endif /* NETUNIX */ 3029#endif /* _FFR_DAEMON_NETUNIX */ 3030 } 3031 } 3032 3033 finis(false, true, EX_OK); 3034} 3035/* 3036** RESTART_DAEMON -- Performs a clean restart of the daemon 3037** 3038** Parameters: 3039** none. 3040** 3041** Returns: 3042** none. 3043** 3044** Side Effects: 3045** restarts the daemon or exits if restart fails. 3046*/ 3047 3048/* Make a non-DFL/IGN signal a noop */ 3049#define SM_NOOP_SIGNAL(sig, old) \ 3050do \ 3051{ \ 3052 (old) = sm_signal((sig), sm_signal_noop); \ 3053 if ((old) == SIG_IGN || (old) == SIG_DFL) \ 3054 (void) sm_signal((sig), (old)); \ 3055} while (0) 3056 3057void 3058restart_daemon() 3059{ 3060 bool drop; 3061 int save_errno; 3062 char *reason; 3063 sigfunc_t ignore, oalrm, ousr1; 3064 extern int DtableSize; 3065 3066 /* clear the events to turn off SIGALRMs */ 3067 sm_clear_events(); 3068 sm_allsignals(true); 3069 3070 reason = RestartRequest; 3071 RestartRequest = NULL; 3072 PendingSignal = 0; 3073 3074 if (SaveArgv[0][0] != '/') 3075 { 3076 if (LogLevel > 3) 3077 sm_syslog(LOG_INFO, NOQID, 3078 "could not restart: need full path"); 3079 finis(false, true, EX_OSFILE); 3080 /* NOTREACHED */ 3081 } 3082 if (LogLevel > 3) 3083 sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 3084 SaveArgv[0], 3085 reason == NULL ? "implicit call" : reason); 3086 3087 closecontrolsocket(true); 3088#if SM_CONF_SHM 3089 cleanup_shm(DaemonPid == getpid()); 3090#endif /* SM_CONF_SHM */ 3091 3092 /* close locked pid file */ 3093 close_sendmail_pid(); 3094 3095 /* 3096 ** Want to drop to the user who started the process in all cases 3097 ** *but* when running as "smmsp" for the clientmqueue queue run 3098 ** daemon. In that case, UseMSP will be true, RunAsUid should not 3099 ** be root, and RealUid should be either 0 or RunAsUid. 3100 */ 3101 3102 drop = !(UseMSP && RunAsUid != 0 && 3103 (RealUid == 0 || RealUid == RunAsUid)); 3104 3105 if (drop_privileges(drop) != EX_OK) 3106 { 3107 if (LogLevel > 0) 3108 sm_syslog(LOG_ALERT, NOQID, 3109 "could not drop privileges: %s", 3110 sm_errstring(errno)); 3111 finis(false, true, EX_OSERR); 3112 /* NOTREACHED */ 3113 } 3114 3115 sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 3116 3117 /* 3118 ** Need to allow signals before execve() to make them "harmless". 3119 ** However, the default action can be "terminate", so it isn't 3120 ** really harmless. Setting signals to IGN will cause them to be 3121 ** ignored in the new process to, so that isn't a good alternative. 3122 */ 3123 3124 SM_NOOP_SIGNAL(SIGALRM, oalrm); 3125 SM_NOOP_SIGNAL(SIGCHLD, ignore); 3126 SM_NOOP_SIGNAL(SIGHUP, ignore); 3127 SM_NOOP_SIGNAL(SIGINT, ignore); 3128 SM_NOOP_SIGNAL(SIGPIPE, ignore); 3129 SM_NOOP_SIGNAL(SIGTERM, ignore); 3130#ifdef SIGUSR1 3131 SM_NOOP_SIGNAL(SIGUSR1, ousr1); 3132#endif /* SIGUSR1 */ 3133 3134 /* Turn back on signals */ 3135 sm_allsignals(false); 3136 3137 (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 3138 save_errno = errno; 3139 3140 /* block signals again and restore needed signals */ 3141 sm_allsignals(true); 3142 3143 /* For finis() events */ 3144 (void) sm_signal(SIGALRM, oalrm); 3145 3146#ifdef SIGUSR1 3147 /* For debugging finis() */ 3148 (void) sm_signal(SIGUSR1, ousr1); 3149#endif /* SIGUSR1 */ 3150 3151 errno = save_errno; 3152 if (LogLevel > 0) 3153 sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s", 3154 SaveArgv[0], sm_errstring(errno)); 3155 finis(false, true, EX_OSFILE); 3156 /* NOTREACHED */ 3157} 3158/* 3159** MYHOSTNAME -- return the name of this host. 3160** 3161** Parameters: 3162** hostbuf -- a place to return the name of this host. 3163** size -- the size of hostbuf. 3164** 3165** Returns: 3166** A list of aliases for this host. 3167** 3168** Side Effects: 3169** Adds numeric codes to $=w. 3170*/ 3171 3172struct hostent * 3173myhostname(hostbuf, size) 3174 char hostbuf[]; 3175 int size; 3176{ 3177 register struct hostent *hp; 3178 3179 if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 3180 (void) sm_strlcpy(hostbuf, "localhost", size); 3181 hp = sm_gethostbyname(hostbuf, InetMode); 3182#if NETINET && NETINET6 3183 if (hp == NULL && InetMode == AF_INET6) 3184 { 3185 /* 3186 ** It's possible that this IPv6 enabled machine doesn't 3187 ** actually have any IPv6 interfaces and, therefore, no 3188 ** IPv6 addresses. Fall back to AF_INET. 3189 */ 3190 3191 hp = sm_gethostbyname(hostbuf, AF_INET); 3192 } 3193#endif /* NETINET && NETINET6 */ 3194 if (hp == NULL) 3195 return NULL; 3196 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 3197 (void) cleanstrcpy(hostbuf, hp->h_name, size); 3198 3199#if NETINFO 3200 if (strchr(hostbuf, '.') == NULL) 3201 { 3202 char *domainname; 3203 3204 domainname = ni_propval("/locations", NULL, "resolver", 3205 "domain", '\0'); 3206 if (domainname != NULL && 3207 strlen(domainname) + strlen(hostbuf) + 1 < size) 3208 (void) sm_strlcat2(hostbuf, ".", domainname, size); 3209 } 3210#endif /* NETINFO */ 3211 3212 /* 3213 ** If there is still no dot in the name, try looking for a 3214 ** dotted alias. 3215 */ 3216 3217 if (strchr(hostbuf, '.') == NULL) 3218 { 3219 char **ha; 3220 3221 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 3222 { 3223 if (strchr(*ha, '.') != NULL) 3224 { 3225 (void) cleanstrcpy(hostbuf, *ha, size - 1); 3226 hostbuf[size - 1] = '\0'; 3227 break; 3228 } 3229 } 3230 } 3231 3232 /* 3233 ** If _still_ no dot, wait for a while and try again -- it is 3234 ** possible that some service is starting up. This can result 3235 ** in excessive delays if the system is badly configured, but 3236 ** there really isn't a way around that, particularly given that 3237 ** the config file hasn't been read at this point. 3238 ** All in all, a bit of a mess. 3239 */ 3240 3241 if (strchr(hostbuf, '.') == NULL && 3242 !getcanonname(hostbuf, size, true, NULL)) 3243 { 3244 sm_syslog(LOG_CRIT, NOQID, 3245 "My unqualified host name (%s) unknown; sleeping for retry", 3246 hostbuf); 3247 message("My unqualified host name (%s) unknown; sleeping for retry", 3248 hostbuf); 3249 (void) sleep(60); 3250 if (!getcanonname(hostbuf, size, true, NULL)) 3251 { 3252 sm_syslog(LOG_ALERT, NOQID, 3253 "unable to qualify my own domain name (%s) -- using short name", 3254 hostbuf); 3255 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 3256 hostbuf); 3257 } 3258 } 3259 return hp; 3260} 3261/* 3262** ADDRCMP -- compare two host addresses 3263** 3264** Parameters: 3265** hp -- hostent structure for the first address 3266** ha -- actual first address 3267** sa -- second address 3268** 3269** Returns: 3270** 0 -- if ha and sa match 3271** else -- they don't match 3272*/ 3273 3274static int 3275addrcmp(hp, ha, sa) 3276 struct hostent *hp; 3277 char *ha; 3278 SOCKADDR *sa; 3279{ 3280#if NETINET6 3281 unsigned char *a; 3282#endif /* NETINET6 */ 3283 3284 switch (sa->sa.sa_family) 3285 { 3286#if NETINET 3287 case AF_INET: 3288 if (hp->h_addrtype == AF_INET) 3289 return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 3290 break; 3291#endif /* NETINET */ 3292 3293#if NETINET6 3294 case AF_INET6: 3295 a = (unsigned char *) &sa->sin6.sin6_addr; 3296 3297 /* Straight binary comparison */ 3298 if (hp->h_addrtype == AF_INET6) 3299 return memcmp(ha, a, IN6ADDRSZ); 3300 3301 /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 3302 if (hp->h_addrtype == AF_INET && 3303 IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 3304 return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 3305 break; 3306#endif /* NETINET6 */ 3307 } 3308 return -1; 3309} 3310/* 3311** GETAUTHINFO -- get the real host name associated with a file descriptor 3312** 3313** Uses RFC1413 protocol to try to get info from the other end. 3314** 3315** Parameters: 3316** fd -- the descriptor 3317** may_be_forged -- an outage that is set to true if the 3318** forward lookup of RealHostName does not match 3319** RealHostAddr; set to false if they do match. 3320** 3321** Returns: 3322** The user@host information associated with this descriptor. 3323*/ 3324 3325static jmp_buf CtxAuthTimeout; 3326 3327static void 3328authtimeout(ignore) 3329 int ignore; 3330{ 3331 /* 3332 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 3333 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 3334 ** DOING. 3335 */ 3336 3337 errno = ETIMEDOUT; 3338 longjmp(CtxAuthTimeout, 1); 3339} 3340 3341char * 3342getauthinfo(fd, may_be_forged) 3343 int fd; 3344 bool *may_be_forged; 3345{ 3346 unsigned short SM_NONVOLATILE port = 0; 3347 SOCKADDR_LEN_T falen; 3348 register char *volatile p = NULL; 3349 SOCKADDR la; 3350 SOCKADDR_LEN_T lalen; 3351#ifndef NO_GETSERVBYNAME 3352 register struct servent *sp; 3353# if NETINET 3354 static unsigned short port4 = 0; 3355# endif /* NETINET */ 3356# if NETINET6 3357 static unsigned short port6 = 0; 3358# endif /* NETINET6 */ 3359#endif /* ! NO_GETSERVBYNAME */ 3360 volatile int s; 3361 int i = 0; 3362 size_t len; 3363 SM_EVENT *ev; 3364 int nleft; 3365 struct hostent *hp; 3366 char *ostype = NULL; 3367 char **ha; 3368 char ibuf[MAXNAME + 1]; 3369 static char hbuf[MAXNAME + MAXAUTHINFO + 11]; 3370 3371 *may_be_forged = false; 3372 falen = sizeof RealHostAddr; 3373 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 3374 falen <= 0 || RealHostAddr.sa.sa_family == 0) 3375 { 3376 if (i < 0) 3377 { 3378 /* 3379 ** ENOTSOCK is OK: bail on anything else, but reset 3380 ** errno in this case, so a mis-report doesn't 3381 ** happen later. 3382 */ 3383 3384 if (errno != ENOTSOCK) 3385 return NULL; 3386 errno = 0; 3387 } 3388 (void) sm_strlcpyn(hbuf, sizeof hbuf, 2, RealUserName, 3389 "@localhost"); 3390 if (tTd(9, 1)) 3391 sm_dprintf("getauthinfo: %s\n", hbuf); 3392 return hbuf; 3393 } 3394 3395 if (RealHostName == NULL) 3396 { 3397 /* translate that to a host name */ 3398 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 3399 if (strlen(RealHostName) > MAXNAME) 3400 RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ 3401 } 3402 3403 /* cross check RealHostName with forward DNS lookup */ 3404 if (anynet_ntoa(&RealHostAddr)[0] != '[' && 3405 RealHostName[0] != '[') 3406 { 3407 int family; 3408 3409 family = RealHostAddr.sa.sa_family; 3410#if NETINET6 && NEEDSGETIPNODE 3411 /* 3412 ** If RealHostAddr is an IPv6 connection with an 3413 ** IPv4-mapped address, we need RealHostName's IPv4 3414 ** address(es) for addrcmp() to compare against 3415 ** RealHostAddr. 3416 ** 3417 ** Actually, we only need to do this for systems 3418 ** which NEEDSGETIPNODE since the real getipnodebyname() 3419 ** already does V4MAPPED address via the AI_V4MAPPEDCFG 3420 ** flag. A better fix to this problem is to add this 3421 ** functionality to our stub getipnodebyname(). 3422 */ 3423 3424 if (family == AF_INET6 && 3425 IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 3426 family = AF_INET; 3427#endif /* NETINET6 && NEEDSGETIPNODE */ 3428 3429 /* try to match the reverse against the forward lookup */ 3430 hp = sm_gethostbyname(RealHostName, family); 3431 if (hp == NULL) 3432 { 3433 /* XXX: Could be a temporary error on forward lookup */ 3434 *may_be_forged = true; 3435 } 3436 else 3437 { 3438 for (ha = hp->h_addr_list; *ha != NULL; ha++) 3439 { 3440 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 3441 break; 3442 } 3443 *may_be_forged = *ha == NULL; 3444#if NETINET6 3445 freehostent(hp); 3446 hp = NULL; 3447#endif /* NETINET6 */ 3448 } 3449 } 3450 3451 if (TimeOuts.to_ident == 0) 3452 goto noident; 3453 3454 lalen = sizeof la; 3455 switch (RealHostAddr.sa.sa_family) 3456 { 3457#if NETINET 3458 case AF_INET: 3459 if (getsockname(fd, &la.sa, &lalen) < 0 || 3460 lalen <= 0 || 3461 la.sa.sa_family != AF_INET) 3462 { 3463 /* no ident info */ 3464 goto noident; 3465 } 3466 port = RealHostAddr.sin.sin_port; 3467 3468 /* create ident query */ 3469 (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 3470 ntohs(RealHostAddr.sin.sin_port), 3471 ntohs(la.sin.sin_port)); 3472 3473 /* create local address */ 3474 la.sin.sin_port = 0; 3475 3476 /* create foreign address */ 3477# ifdef NO_GETSERVBYNAME 3478 RealHostAddr.sin.sin_port = htons(113); 3479# else /* NO_GETSERVBYNAME */ 3480 3481 /* 3482 ** getservbyname() consumes about 5% of the time 3483 ** when receiving a small message (almost all of the time 3484 ** spent in this routine). 3485 ** Hence we store the port in a static variable 3486 ** to save this time. 3487 ** The portnumber shouldn't change very often... 3488 ** This code makes the assumption that the port number 3489 ** is not 0. 3490 */ 3491 3492 if (port4 == 0) 3493 { 3494 sp = getservbyname("auth", "tcp"); 3495 if (sp != NULL) 3496 port4 = sp->s_port; 3497 else 3498 port4 = htons(113); 3499 } 3500 RealHostAddr.sin.sin_port = port4; 3501 break; 3502# endif /* NO_GETSERVBYNAME */ 3503#endif /* NETINET */ 3504 3505#if NETINET6 3506 case AF_INET6: 3507 if (getsockname(fd, &la.sa, &lalen) < 0 || 3508 lalen <= 0 || 3509 la.sa.sa_family != AF_INET6) 3510 { 3511 /* no ident info */ 3512 goto noident; 3513 } 3514 port = RealHostAddr.sin6.sin6_port; 3515 3516 /* create ident query */ 3517 (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 3518 ntohs(RealHostAddr.sin6.sin6_port), 3519 ntohs(la.sin6.sin6_port)); 3520 3521 /* create local address */ 3522 la.sin6.sin6_port = 0; 3523 3524 /* create foreign address */ 3525# ifdef NO_GETSERVBYNAME 3526 RealHostAddr.sin6.sin6_port = htons(113); 3527# else /* NO_GETSERVBYNAME */ 3528 if (port6 == 0) 3529 { 3530 sp = getservbyname("auth", "tcp"); 3531 if (sp != NULL) 3532 port6 = sp->s_port; 3533 else 3534 port6 = htons(113); 3535 } 3536 RealHostAddr.sin6.sin6_port = port6; 3537 break; 3538# endif /* NO_GETSERVBYNAME */ 3539#endif /* NETINET6 */ 3540 default: 3541 /* no ident info */ 3542 goto noident; 3543 } 3544 3545 s = -1; 3546 if (setjmp(CtxAuthTimeout) != 0) 3547 { 3548 if (s >= 0) 3549 (void) close(s); 3550 goto noident; 3551 } 3552 3553 /* put a timeout around the whole thing */ 3554 ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0); 3555 3556 /* connect to foreign IDENT server using same address as SMTP socket */ 3557 s = socket(la.sa.sa_family, SOCK_STREAM, 0); 3558 if (s < 0) 3559 { 3560 sm_clrevent(ev); 3561 goto noident; 3562 } 3563 if (bind(s, &la.sa, lalen) < 0 || 3564 connect(s, &RealHostAddr.sa, lalen) < 0) 3565 goto closeident; 3566 3567 if (tTd(9, 10)) 3568 sm_dprintf("getauthinfo: sent %s", ibuf); 3569 3570 /* send query */ 3571 if (write(s, ibuf, strlen(ibuf)) < 0) 3572 goto closeident; 3573 3574 /* get result */ 3575 p = &ibuf[0]; 3576 nleft = sizeof ibuf - 1; 3577 while ((i = read(s, p, nleft)) > 0) 3578 { 3579 char *s; 3580 3581 p += i; 3582 nleft -= i; 3583 *p = '\0'; 3584 if ((s = strchr(ibuf, '\n')) != NULL) 3585 { 3586 if (p > s + 1) 3587 { 3588 p = s + 1; 3589 *p = '\0'; 3590 } 3591 break; 3592 } 3593 if (nleft <= 0) 3594 break; 3595 } 3596 (void) close(s); 3597 sm_clrevent(ev); 3598 if (i < 0 || p == &ibuf[0]) 3599 goto noident; 3600 3601 if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r') 3602 p--; 3603 *++p = '\0'; 3604 3605 if (tTd(9, 3)) 3606 sm_dprintf("getauthinfo: got %s\n", ibuf); 3607 3608 /* parse result */ 3609 p = strchr(ibuf, ':'); 3610 if (p == NULL) 3611 { 3612 /* malformed response */ 3613 goto noident; 3614 } 3615 while (isascii(*++p) && isspace(*p)) 3616 continue; 3617 if (sm_strncasecmp(p, "userid", 6) != 0) 3618 { 3619 /* presumably an error string */ 3620 goto noident; 3621 } 3622 p += 6; 3623 while (isascii(*p) && isspace(*p)) 3624 p++; 3625 if (*p++ != ':') 3626 { 3627 /* either useridxx or malformed response */ 3628 goto noident; 3629 } 3630 3631 /* p now points to the OSTYPE field */ 3632 while (isascii(*p) && isspace(*p)) 3633 p++; 3634 ostype = p; 3635 p = strchr(p, ':'); 3636 if (p == NULL) 3637 { 3638 /* malformed response */ 3639 goto noident; 3640 } 3641 else 3642 { 3643 char *charset; 3644 3645 *p = '\0'; 3646 charset = strchr(ostype, ','); 3647 if (charset != NULL) 3648 *charset = '\0'; 3649 } 3650 3651 /* 1413 says don't do this -- but it's broken otherwise */ 3652 while (isascii(*++p) && isspace(*p)) 3653 continue; 3654 3655 /* p now points to the authenticated name -- copy carefully */ 3656 if (sm_strncasecmp(ostype, "other", 5) == 0 && 3657 (ostype[5] == ' ' || ostype[5] == '\0')) 3658 { 3659 (void) sm_strlcpy(hbuf, "IDENT:", sizeof hbuf); 3660 cleanstrcpy(&hbuf[6], p, MAXAUTHINFO); 3661 } 3662 else 3663 cleanstrcpy(hbuf, p, MAXAUTHINFO); 3664 len = strlen(hbuf); 3665 (void) sm_strlcpyn(&hbuf[len], sizeof hbuf - len, 2, "@", 3666 RealHostName == NULL ? "localhost" : RealHostName); 3667 goto postident; 3668 3669closeident: 3670 (void) close(s); 3671 sm_clrevent(ev); 3672 3673noident: 3674 /* put back the original incoming port */ 3675 switch (RealHostAddr.sa.sa_family) 3676 { 3677#if NETINET 3678 case AF_INET: 3679 if (port > 0) 3680 RealHostAddr.sin.sin_port = port; 3681 break; 3682#endif /* NETINET */ 3683 3684#if NETINET6 3685 case AF_INET6: 3686 if (port > 0) 3687 RealHostAddr.sin6.sin6_port = port; 3688 break; 3689#endif /* NETINET6 */ 3690 } 3691 3692 if (RealHostName == NULL) 3693 { 3694 if (tTd(9, 1)) 3695 sm_dprintf("getauthinfo: NULL\n"); 3696 return NULL; 3697 } 3698 (void) sm_strlcpy(hbuf, RealHostName, sizeof hbuf); 3699 3700postident: 3701#if IP_SRCROUTE 3702# ifndef GET_IPOPT_DST 3703# define GET_IPOPT_DST(dst) (dst) 3704# endif /* ! GET_IPOPT_DST */ 3705 /* 3706 ** Extract IP source routing information. 3707 ** 3708 ** Format of output for a connection from site a through b 3709 ** through c to d: 3710 ** loose: @site-c@site-b:site-a 3711 ** strict: !@site-c@site-b:site-a 3712 ** 3713 ** o - pointer within ipopt_list structure. 3714 ** q - pointer within ls/ss rr route data 3715 ** p - pointer to hbuf 3716 */ 3717 3718 if (RealHostAddr.sa.sa_family == AF_INET) 3719 { 3720 SOCKOPT_LEN_T ipoptlen; 3721 int j; 3722 unsigned char *q; 3723 unsigned char *o; 3724 int l; 3725 struct IPOPTION ipopt; 3726 3727 ipoptlen = sizeof ipopt; 3728 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 3729 (char *) &ipopt, &ipoptlen) < 0) 3730 goto noipsr; 3731 if (ipoptlen == 0) 3732 goto noipsr; 3733 o = (unsigned char *) ipopt.IP_LIST; 3734 while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen) 3735 { 3736 switch (*o) 3737 { 3738 case IPOPT_EOL: 3739 o = NULL; 3740 break; 3741 3742 case IPOPT_NOP: 3743 o++; 3744 break; 3745 3746 case IPOPT_SSRR: 3747 case IPOPT_LSRR: 3748 /* 3749 ** Source routing. 3750 ** o[0] is the option type (loose/strict). 3751 ** o[1] is the length of this option, 3752 ** including option type and 3753 ** length. 3754 ** o[2] is the pointer into the route 3755 ** data. 3756 ** o[3] begins the route data. 3757 */ 3758 3759 p = &hbuf[strlen(hbuf)]; 3760 l = sizeof hbuf - (hbuf - p) - 6; 3761 (void) sm_snprintf(p, SPACELEFT(hbuf, p), 3762 " [%s@%.*s", 3763 *o == IPOPT_SSRR ? "!" : "", 3764 l > 240 ? 120 : l / 2, 3765 inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 3766 i = strlen(p); 3767 p += i; 3768 l -= strlen(p); 3769 3770 j = o[1] / sizeof(struct in_addr) - 1; 3771 3772 /* q skips length and router pointer to data */ 3773 q = &o[3]; 3774 for ( ; j >= 0; j--) 3775 { 3776 struct in_addr addr; 3777 3778 memcpy(&addr, q, sizeof(addr)); 3779 (void) sm_snprintf(p, 3780 SPACELEFT(hbuf, p), 3781 "%c%.*s", 3782 j != 0 ? '@' : ':', 3783 l > 240 ? 120 : 3784 j == 0 ? l : l / 2, 3785 inet_ntoa(addr)); 3786 i = strlen(p); 3787 p += i; 3788 l -= i + 1; 3789 q += sizeof(struct in_addr); 3790 } 3791 o += o[1]; 3792 break; 3793 3794 default: 3795 /* Skip over option */ 3796 o += o[1]; 3797 break; 3798 } 3799 } 3800 (void) sm_snprintf(p, SPACELEFT(hbuf, p), "]"); 3801 goto postipsr; 3802 } 3803 3804noipsr: 3805#endif /* IP_SRCROUTE */ 3806 if (RealHostName != NULL && RealHostName[0] != '[') 3807 { 3808 p = &hbuf[strlen(hbuf)]; 3809 (void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 3810 anynet_ntoa(&RealHostAddr)); 3811 } 3812 if (*may_be_forged) 3813 { 3814 p = &hbuf[strlen(hbuf)]; 3815 (void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p)); 3816 macdefine(&BlankEnvelope.e_macro, A_PERM, 3817 macid("{client_resolve}"), "FORGED"); 3818 } 3819 3820#if IP_SRCROUTE 3821postipsr: 3822#endif /* IP_SRCROUTE */ 3823 3824 /* put back the original incoming port */ 3825 switch (RealHostAddr.sa.sa_family) 3826 { 3827#if NETINET 3828 case AF_INET: 3829 if (port > 0) 3830 RealHostAddr.sin.sin_port = port; 3831 break; 3832#endif /* NETINET */ 3833 3834#if NETINET6 3835 case AF_INET6: 3836 if (port > 0) 3837 RealHostAddr.sin6.sin6_port = port; 3838 break; 3839#endif /* NETINET6 */ 3840 } 3841 3842 if (tTd(9, 1)) 3843 sm_dprintf("getauthinfo: %s\n", hbuf); 3844 return hbuf; 3845} 3846/* 3847** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3848** 3849** Parameters: 3850** map -- a pointer to this map. 3851** name -- the (presumably unqualified) hostname. 3852** av -- unused -- for compatibility with other mapping 3853** functions. 3854** statp -- an exit status (out parameter) -- set to 3855** EX_TEMPFAIL if the name server is unavailable. 3856** 3857** Returns: 3858** The mapping, if found. 3859** NULL if no mapping found. 3860** 3861** Side Effects: 3862** Looks up the host specified in hbuf. If it is not 3863** the canonical name for that host, return the canonical 3864** name (unless MF_MATCHONLY is set, which will cause the 3865** status only to be returned). 3866*/ 3867 3868char * 3869host_map_lookup(map, name, av, statp) 3870 MAP *map; 3871 char *name; 3872 char **av; 3873 int *statp; 3874{ 3875 register struct hostent *hp; 3876#if NETINET 3877 struct in_addr in_addr; 3878#endif /* NETINET */ 3879#if NETINET6 3880 struct in6_addr in6_addr; 3881#endif /* NETINET6 */ 3882 char *cp, *ans = NULL; 3883 register STAB *s; 3884 time_t now; 3885#if NAMED_BIND 3886 time_t SM_NONVOLATILE retrans = 0; 3887 int SM_NONVOLATILE retry = 0; 3888#endif /* NAMED_BIND */ 3889 char hbuf[MAXNAME + 1]; 3890 3891 /* 3892 ** See if we have already looked up this name. If so, just 3893 ** return it (unless expired). 3894 */ 3895 3896 now = curtime(); 3897 s = stab(name, ST_NAMECANON, ST_ENTER); 3898 if (bitset(NCF_VALID, s->s_namecanon.nc_flags) && 3899 s->s_namecanon.nc_exp >= now) 3900 { 3901 if (tTd(9, 1)) 3902 sm_dprintf("host_map_lookup(%s) => CACHE %s\n", 3903 name, 3904 s->s_namecanon.nc_cname == NULL 3905 ? "NULL" 3906 : s->s_namecanon.nc_cname); 3907 errno = s->s_namecanon.nc_errno; 3908 SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 3909 *statp = s->s_namecanon.nc_stat; 3910 if (*statp == EX_TEMPFAIL) 3911 { 3912 CurEnv->e_status = "4.4.3"; 3913 message("851 %s: Name server timeout", 3914 shortenstring(name, 33)); 3915 } 3916 if (*statp != EX_OK) 3917 return NULL; 3918 if (s->s_namecanon.nc_cname == NULL) 3919 { 3920 syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d", 3921 name, 3922 s->s_namecanon.nc_errno, 3923 s->s_namecanon.nc_herrno); 3924 return NULL; 3925 } 3926 if (bitset(MF_MATCHONLY, map->map_mflags)) 3927 cp = map_rewrite(map, name, strlen(name), NULL); 3928 else 3929 cp = map_rewrite(map, 3930 s->s_namecanon.nc_cname, 3931 strlen(s->s_namecanon.nc_cname), 3932 av); 3933 return cp; 3934 } 3935 3936 /* 3937 ** If we are running without a regular network connection (usually 3938 ** dial-on-demand) and we are just queueing, we want to avoid DNS 3939 ** lookups because those could try to connect to a server. 3940 */ 3941 3942 if (CurEnv->e_sendmode == SM_DEFER && 3943 bitset(MF_DEFER, map->map_mflags)) 3944 { 3945 if (tTd(9, 1)) 3946 sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name); 3947 *statp = EX_TEMPFAIL; 3948 return NULL; 3949 } 3950 3951 /* 3952 ** If first character is a bracket, then it is an address 3953 ** lookup. Address is copied into a temporary buffer to 3954 ** strip the brackets and to preserve name if address is 3955 ** unknown. 3956 */ 3957 3958 if (tTd(9, 1)) 3959 sm_dprintf("host_map_lookup(%s) => ", name); 3960#if NAMED_BIND 3961 if (map->map_timeout > 0) 3962 { 3963 retrans = _res.retrans; 3964 _res.retrans = map->map_timeout; 3965 } 3966 if (map->map_retry > 0) 3967 { 3968 retry = _res.retry; 3969 _res.retry = map->map_retry; 3970 } 3971#endif /* NAMED_BIND */ 3972 3973 /* set default TTL */ 3974 s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL; 3975 if (*name != '[') 3976 { 3977 int ttl; 3978 3979 (void) sm_strlcpy(hbuf, name, sizeof hbuf); 3980 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX, &ttl)) 3981 { 3982 ans = hbuf; 3983 if (ttl > 0) 3984 s->s_namecanon.nc_exp = now + SM_MIN(ttl, 3985 SM_DEFAULT_TTL); 3986 } 3987 } 3988 else 3989 { 3990 if ((cp = strchr(name, ']')) == NULL) 3991 { 3992 if (tTd(9, 1)) 3993 sm_dprintf("FAILED\n"); 3994 return NULL; 3995 } 3996 *cp = '\0'; 3997 3998 hp = NULL; 3999#if NETINET 4000 if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 4001 hp = sm_gethostbyaddr((char *)&in_addr, 4002 INADDRSZ, AF_INET); 4003#endif /* NETINET */ 4004#if NETINET6 4005 if (hp == NULL && 4006 anynet_pton(AF_INET6, &name[1], &in6_addr) == 1) 4007 hp = sm_gethostbyaddr((char *)&in6_addr, 4008 IN6ADDRSZ, AF_INET6); 4009#endif /* NETINET6 */ 4010 *cp = ']'; 4011 4012 if (hp != NULL) 4013 { 4014 /* found a match -- copy out */ 4015 ans = denlstring((char *) hp->h_name, true, true); 4016#if NETINET6 4017 if (ans == hp->h_name) 4018 { 4019 static char n[MAXNAME + 1]; 4020 4021 /* hp->h_name is about to disappear */ 4022 (void) sm_strlcpy(n, ans, sizeof n); 4023 ans = n; 4024 } 4025 freehostent(hp); 4026 hp = NULL; 4027#endif /* NETINET6 */ 4028 } 4029 } 4030#if NAMED_BIND 4031 if (map->map_timeout > 0) 4032 _res.retrans = retrans; 4033 if (map->map_retry > 0) 4034 _res.retry = retry; 4035#endif /* NAMED_BIND */ 4036 4037 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 4038 4039 /* Found an answer */ 4040 if (ans != NULL) 4041 { 4042 s->s_namecanon.nc_stat = *statp = EX_OK; 4043 if (s->s_namecanon.nc_cname != NULL) 4044 sm_free(s->s_namecanon.nc_cname); 4045 s->s_namecanon.nc_cname = sm_strdup_x(ans); 4046 if (bitset(MF_MATCHONLY, map->map_mflags)) 4047 cp = map_rewrite(map, name, strlen(name), NULL); 4048 else 4049 cp = map_rewrite(map, ans, strlen(ans), av); 4050 if (tTd(9, 1)) 4051 sm_dprintf("FOUND %s\n", ans); 4052 return cp; 4053 } 4054 4055 4056 /* No match found */ 4057 s->s_namecanon.nc_errno = errno; 4058#if NAMED_BIND 4059 s->s_namecanon.nc_herrno = h_errno; 4060 if (tTd(9, 1)) 4061 sm_dprintf("FAIL (%d)\n", h_errno); 4062 switch (h_errno) 4063 { 4064 case TRY_AGAIN: 4065 if (UseNameServer) 4066 { 4067 CurEnv->e_status = "4.4.3"; 4068 message("851 %s: Name server timeout", 4069 shortenstring(name, 33)); 4070 } 4071 *statp = EX_TEMPFAIL; 4072 break; 4073 4074 case HOST_NOT_FOUND: 4075 case NO_DATA: 4076 *statp = EX_NOHOST; 4077 break; 4078 4079 case NO_RECOVERY: 4080 *statp = EX_SOFTWARE; 4081 break; 4082 4083 default: 4084 *statp = EX_UNAVAILABLE; 4085 break; 4086 } 4087#else /* NAMED_BIND */ 4088 if (tTd(9, 1)) 4089 sm_dprintf("FAIL\n"); 4090 *statp = EX_NOHOST; 4091#endif /* NAMED_BIND */ 4092 s->s_namecanon.nc_stat = *statp; 4093 return NULL; 4094} 4095/* 4096** HOST_MAP_INIT -- initialize host class structures 4097** 4098** Parameters: 4099** map -- a pointer to this map. 4100** args -- argument string. 4101** 4102** Returns: 4103** true. 4104*/ 4105 4106bool 4107host_map_init(map, args) 4108 MAP *map; 4109 char *args; 4110{ 4111 register char *p = args; 4112 4113 for (;;) 4114 { 4115 while (isascii(*p) && isspace(*p)) 4116 p++; 4117 if (*p != '-') 4118 break; 4119 switch (*++p) 4120 { 4121 case 'a': 4122 map->map_app = ++p; 4123 break; 4124 4125 case 'T': 4126 map->map_tapp = ++p; 4127 break; 4128 4129 case 'm': 4130 map->map_mflags |= MF_MATCHONLY; 4131 break; 4132 4133 case 't': 4134 map->map_mflags |= MF_NODEFER; 4135 break; 4136 4137 case 'S': /* only for consistency */ 4138 map->map_spacesub = *++p; 4139 break; 4140 4141 case 'D': 4142 map->map_mflags |= MF_DEFER; 4143 break; 4144 4145 case 'd': 4146 { 4147 char *h; 4148 4149 while (isascii(*++p) && isspace(*p)) 4150 continue; 4151 h = strchr(p, ' '); 4152 if (h != NULL) 4153 *h = '\0'; 4154 map->map_timeout = convtime(p, 's'); 4155 if (h != NULL) 4156 *h = ' '; 4157 } 4158 break; 4159 4160 case 'r': 4161 while (isascii(*++p) && isspace(*p)) 4162 continue; 4163 map->map_retry = atoi(p); 4164 break; 4165 } 4166 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 4167 p++; 4168 if (*p != '\0') 4169 *p++ = '\0'; 4170 } 4171 if (map->map_app != NULL) 4172 map->map_app = newstr(map->map_app); 4173 if (map->map_tapp != NULL) 4174 map->map_tapp = newstr(map->map_tapp); 4175 return true; 4176} 4177 4178#if NETINET6 4179/* 4180** ANYNET_NTOP -- convert an IPv6 network address to printable form. 4181** 4182** Parameters: 4183** s6a -- a pointer to an in6_addr structure. 4184** dst -- buffer to store result in 4185** dst_len -- size of dst buffer 4186** 4187** Returns: 4188** A printable version of that structure. 4189*/ 4190 4191char * 4192anynet_ntop(s6a, dst, dst_len) 4193 struct in6_addr *s6a; 4194 char *dst; 4195 size_t dst_len; 4196{ 4197 register char *ap; 4198 4199 if (IN6_IS_ADDR_V4MAPPED(s6a)) 4200 ap = (char *) inet_ntop(AF_INET, 4201 &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 4202 dst, dst_len); 4203 else 4204 { 4205 char *d; 4206 size_t sz; 4207 4208 /* Save pointer to beginning of string */ 4209 d = dst; 4210 4211 /* Add IPv6: protocol tag */ 4212 sz = sm_strlcpy(dst, "IPv6:", dst_len); 4213 if (sz >= dst_len) 4214 return NULL; 4215 dst += sz; 4216 dst_len -= sz; 4217 ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 4218 4219 /* Restore pointer to beginning of string */ 4220 if (ap != NULL) 4221 ap = d; 4222 } 4223 return ap; 4224} 4225 4226/* 4227** ANYNET_PTON -- convert printed form to network address. 4228** 4229** Wrapper for inet_pton() which handles IPv6: labels. 4230** 4231** Parameters: 4232** family -- address family 4233** src -- string 4234** dst -- destination address structure 4235** 4236** Returns: 4237** 1 if the address was valid 4238** 0 if the address wasn't parseable 4239** -1 if error 4240*/ 4241 4242int 4243anynet_pton(family, src, dst) 4244 int family; 4245 const char *src; 4246 void *dst; 4247{ 4248 if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0) 4249 src += 5; 4250 return inet_pton(family, src, dst); 4251} 4252#endif /* NETINET6 */ 4253/* 4254** ANYNET_NTOA -- convert a network address to printable form. 4255** 4256** Parameters: 4257** sap -- a pointer to a sockaddr structure. 4258** 4259** Returns: 4260** A printable version of that sockaddr. 4261*/ 4262 4263#ifdef USE_SOCK_STREAM 4264 4265# if NETLINK 4266# include <net/if_dl.h> 4267# endif /* NETLINK */ 4268 4269char * 4270anynet_ntoa(sap) 4271 register SOCKADDR *sap; 4272{ 4273 register char *bp; 4274 register char *ap; 4275 int l; 4276 static char buf[100]; 4277 4278 /* check for null/zero family */ 4279 if (sap == NULL) 4280 return "NULLADDR"; 4281 if (sap->sa.sa_family == 0) 4282 return "0"; 4283 4284 switch (sap->sa.sa_family) 4285 { 4286# if NETUNIX 4287 case AF_UNIX: 4288 if (sap->sunix.sun_path[0] != '\0') 4289 (void) sm_snprintf(buf, sizeof buf, "[UNIX: %.64s]", 4290 sap->sunix.sun_path); 4291 else 4292 (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof buf); 4293 return buf; 4294# endif /* NETUNIX */ 4295 4296# if NETINET 4297 case AF_INET: 4298 return (char *) inet_ntoa(sap->sin.sin_addr); 4299# endif /* NETINET */ 4300 4301# if NETINET6 4302 case AF_INET6: 4303 ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); 4304 if (ap != NULL) 4305 return ap; 4306 break; 4307# endif /* NETINET6 */ 4308 4309# if NETLINK 4310 case AF_LINK: 4311 (void) sm_snprintf(buf, sizeof buf, "[LINK: %s]", 4312 link_ntoa((struct sockaddr_dl *) &sap->sa)); 4313 return buf; 4314# endif /* NETLINK */ 4315 default: 4316 /* this case is needed when nothing is #defined */ 4317 /* in order to keep the switch syntactically correct */ 4318 break; 4319 } 4320 4321 /* unknown family -- just dump bytes */ 4322 (void) sm_snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 4323 bp = &buf[strlen(buf)]; 4324 ap = sap->sa.sa_data; 4325 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 4326 { 4327 (void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:", 4328 *ap++ & 0377); 4329 bp += 3; 4330 } 4331 *--bp = '\0'; 4332 return buf; 4333} 4334/* 4335** HOSTNAMEBYANYADDR -- return name of host based on address 4336** 4337** Parameters: 4338** sap -- SOCKADDR pointer 4339** 4340** Returns: 4341** text representation of host name. 4342** 4343** Side Effects: 4344** none. 4345*/ 4346 4347char * 4348hostnamebyanyaddr(sap) 4349 register SOCKADDR *sap; 4350{ 4351 register struct hostent *hp; 4352# if NAMED_BIND 4353 int saveretry; 4354# endif /* NAMED_BIND */ 4355# if NETINET6 4356 struct in6_addr in6_addr; 4357# endif /* NETINET6 */ 4358 4359# if NAMED_BIND 4360 /* shorten name server timeout to avoid higher level timeouts */ 4361 saveretry = _res.retry; 4362 if (_res.retry * _res.retrans > 20) 4363 _res.retry = 20 / _res.retrans; 4364# endif /* NAMED_BIND */ 4365 4366 switch (sap->sa.sa_family) 4367 { 4368# if NETINET 4369 case AF_INET: 4370 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 4371 INADDRSZ, AF_INET); 4372 break; 4373# endif /* NETINET */ 4374 4375# if NETINET6 4376 case AF_INET6: 4377 hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 4378 IN6ADDRSZ, AF_INET6); 4379 break; 4380# endif /* NETINET6 */ 4381 4382# if NETISO 4383 case AF_ISO: 4384 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 4385 sizeof sap->siso.siso_addr, AF_ISO); 4386 break; 4387# endif /* NETISO */ 4388 4389# if NETUNIX 4390 case AF_UNIX: 4391 hp = NULL; 4392 break; 4393# endif /* NETUNIX */ 4394 4395 default: 4396 hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof sap->sa.sa_data, 4397 sap->sa.sa_family); 4398 break; 4399 } 4400 4401# if NAMED_BIND 4402 _res.retry = saveretry; 4403# endif /* NAMED_BIND */ 4404 4405# if NETINET || NETINET6 4406 if (hp != NULL && hp->h_name[0] != '[' 4407# if NETINET6 4408 && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 4409# endif /* NETINET6 */ 4410# if NETINET 4411 && inet_addr(hp->h_name) == INADDR_NONE 4412# endif /* NETINET */ 4413 ) 4414 { 4415 char *name; 4416 4417 name = denlstring((char *) hp->h_name, true, true); 4418# if NETINET6 4419 if (name == hp->h_name) 4420 { 4421 static char n[MAXNAME + 1]; 4422 4423 /* Copy the string, hp->h_name is about to disappear */ 4424 (void) sm_strlcpy(n, name, sizeof n); 4425 name = n; 4426 } 4427 freehostent(hp); 4428# endif /* NETINET6 */ 4429 return name; 4430 } 4431# endif /* NETINET || NETINET6 */ 4432 4433# if NETINET6 4434 if (hp != NULL) 4435 { 4436 freehostent(hp); 4437 hp = NULL; 4438 } 4439# endif /* NETINET6 */ 4440 4441# if NETUNIX 4442 if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 4443 return "localhost"; 4444# endif /* NETUNIX */ 4445 { 4446 static char buf[203]; 4447 4448 (void) sm_snprintf(buf, sizeof buf, "[%.200s]", 4449 anynet_ntoa(sap)); 4450 return buf; 4451 } 4452} 4453#endif /* USE_SOCK_STREAM */ 4454