1 /* 2 * Copyright (c) 1998-2000 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 16 17 #ifndef lint 18 # ifdef DAEMON 19 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.18 2000/09/21 21:52:16 ca Exp $ (with daemon mode)"; 20 # else /* DAEMON */ 21 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.18 2000/09/21 21:52:16 ca Exp $ (without daemon mode)"; 22 # endif /* DAEMON */ 23 #endif /* ! lint */ 24 25 #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 26 # define USE_SOCK_STREAM 1 27 #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 28 29 #if DAEMON || defined(USE_SOCK_STREAM) 30 # if NETINET || NETINET6 31 # include <arpa/inet.h> 32 # endif /* NETINET || NETINET6 */ 33 # if NAMED_BIND 34 # ifndef NO_DATA 35 # define NO_DATA NO_ADDRESS 36 # endif /* ! NO_DATA */ 37 # endif /* NAMED_BIND */ 38 #endif /* DAEMON || defined(USE_SOCK_STREAM) */ 39 40 #if DAEMON 41 42 # if STARTTLS 43 # include <openssl/rand.h> 44 # endif /* STARTTLS */ 45 46 # include <sys/time.h> 47 48 # if IP_SRCROUTE && NETINET 49 # include <netinet/in_systm.h> 50 # include <netinet/ip.h> 51 # if HAS_IN_H 52 # include <netinet/in.h> 53 # ifndef IPOPTION 54 # define IPOPTION ip_opts 55 # define IP_LIST ip_opts 56 # define IP_DST ip_dst 57 # endif /* ! IPOPTION */ 58 # else /* HAS_IN_H */ 59 # include <netinet/ip_var.h> 60 # ifndef IPOPTION 61 # define IPOPTION ipoption 62 # define IP_LIST ipopt_list 63 # define IP_DST ipopt_dst 64 # endif /* ! IPOPTION */ 65 # endif /* HAS_IN_H */ 66 # endif /* IP_SRCROUTE && NETINET */ 67 68 /* structure to describe a daemon */ 69 struct daemon 70 { 71 int d_socket; /* fd for socket */ 72 SOCKADDR d_addr; /* socket for incoming */ 73 u_short d_port; /* port number */ 74 int d_listenqueue; /* size of listen queue */ 75 int d_tcprcvbufsize; /* size of TCP receive buffer */ 76 int d_tcpsndbufsize; /* size of TCP send buffer */ 77 time_t d_refuse_connections_until; 78 bool d_firsttime; 79 int d_socksize; 80 BITMAP256 d_flags; /* flags; see sendmail.h */ 81 char *d_mflags; /* flags for use in macro */ 82 char *d_name; /* user-supplied name */ 83 }; 84 85 typedef struct daemon DAEMON_T; 86 87 static void connecttimeout __P((void)); 88 static int opendaemonsocket __P((struct daemon *, bool)); 89 static u_short setupdaemon __P((SOCKADDR *)); 90 91 /* 92 ** DAEMON.C -- routines to use when running as a daemon. 93 ** 94 ** This entire file is highly dependent on the 4.2 BSD 95 ** interprocess communication primitives. No attempt has 96 ** been made to make this file portable to Version 7, 97 ** Version 6, MPX files, etc. If you should try such a 98 ** thing yourself, I recommend chucking the entire file 99 ** and starting from scratch. Basic semantics are: 100 ** 101 ** getrequests(e) 102 ** Opens a port and initiates a connection. 103 ** Returns in a child. Must set InChannel and 104 ** OutChannel appropriately. 105 ** clrdaemon() 106 ** Close any open files associated with getting 107 ** the connection; this is used when running the queue, 108 ** etc., to avoid having extra file descriptors during 109 ** the queue run and to avoid confusing the network 110 ** code (if it cares). 111 ** makeconnection(host, port, outfile, infile, e) 112 ** Make a connection to the named host on the given 113 ** port. Set *outfile and *infile to the files 114 ** appropriate for communication. Returns zero on 115 ** success, else an exit status describing the 116 ** error. 117 ** host_map_lookup(map, hbuf, avp, pstat) 118 ** Convert the entry in hbuf into a canonical form. 119 */ 120 121 static DAEMON_T Daemons[MAXDAEMONS]; 122 static int ndaemons = 0; /* actual number of daemons */ 123 124 /* options for client */ 125 static int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ 126 static int TcpSndBufferSize = 0; /* size of TCP send buffer */ 127 128 /* 129 ** GETREQUESTS -- open mail IPC port and get requests. 130 ** 131 ** Parameters: 132 ** e -- the current envelope. 133 ** 134 ** Returns: 135 ** pointer to flags. 136 ** 137 ** Side Effects: 138 ** Waits until some interesting activity occurs. When 139 ** it does, a child is created to process it, and the 140 ** parent waits for completion. Return from this 141 ** routine is always in the child. The file pointers 142 ** "InChannel" and "OutChannel" should be set to point 143 ** to the communication channel. 144 */ 145 146 BITMAP256 * 147 getrequests(e) 148 ENVELOPE *e; 149 { 150 int t; 151 time_t last_disk_space_check = 0; 152 int idx, curdaemon = -1; 153 int i, olddaemon = 0; 154 # if XDEBUG 155 bool j_has_dot; 156 # endif /* XDEBUG */ 157 char status[MAXLINE]; 158 SOCKADDR sa; 159 SOCKADDR_LEN_T len = sizeof sa; 160 # if NETUNIX 161 extern int ControlSocket; 162 # endif /* NETUNIX */ 163 extern ENVELOPE BlankEnvelope; 164 165 #define D(x,idx) x[idx] 166 167 168 for (idx = 0; idx < ndaemons; idx++) 169 { 170 Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 171 Daemons[idx].d_firsttime = TRUE; 172 Daemons[idx].d_refuse_connections_until = (time_t) 0; 173 } 174 /* 175 ** Try to actually open the connection. 176 */ 177 178 if (tTd(15, 1)) 179 { 180 for (idx = 0; idx < ndaemons; idx++) 181 dprintf("getrequests: daemon %s: port %d\n", 182 Daemons[idx].d_name, 183 ntohs(Daemons[idx].d_port)); 184 } 185 186 /* get a socket for the SMTP connection */ 187 for (idx = 0; idx < ndaemons; idx++) 188 Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE); 189 190 if (opencontrolsocket() < 0) 191 sm_syslog(LOG_WARNING, NOQID, 192 "daemon could not open control socket %s: %s", 193 ControlSocketName, errstring(errno)); 194 195 (void) setsignal(SIGCHLD, reapchild); 196 197 /* write the pid to file */ 198 log_sendmail_pid(e); 199 200 # if XDEBUG 201 { 202 char jbuf[MAXHOSTNAMELEN]; 203 204 expand("\201j", jbuf, sizeof jbuf, e); 205 j_has_dot = strchr(jbuf, '.') != NULL; 206 } 207 # endif /* XDEBUG */ 208 209 /* Add parent process as first item */ 210 proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON); 211 212 if (tTd(15, 1)) 213 { 214 for (idx = 0; idx < ndaemons; idx++) 215 dprintf("getrequests: daemon %s: %d\n", 216 Daemons[idx].d_name, 217 Daemons[idx].d_socket); 218 } 219 220 for (;;) 221 { 222 register pid_t pid; 223 auto SOCKADDR_LEN_T lotherend; 224 bool timedout = FALSE; 225 bool control = FALSE; 226 int save_errno; 227 int pipefd[2]; 228 # if STARTTLS 229 long seed; 230 time_t timenow; 231 # endif /* STARTTLS */ 232 233 /* see if we are rejecting connections */ 234 (void) blocksignal(SIGALRM); 235 236 for (idx = 0; idx < ndaemons; idx++) 237 { 238 if (curtime() < Daemons[idx].d_refuse_connections_until) 239 continue; 240 if (refuseconnections(Daemons[idx].d_name, e, idx)) 241 { 242 if (Daemons[idx].d_socket >= 0) 243 { 244 /* close socket so peer fails quickly */ 245 (void) close(Daemons[idx].d_socket); 246 Daemons[idx].d_socket = -1; 247 } 248 249 /* refuse connections for next 15 seconds */ 250 Daemons[idx].d_refuse_connections_until = curtime() + 15; 251 } 252 else if (Daemons[idx].d_socket < 0 || 253 Daemons[idx].d_firsttime) 254 { 255 if (!Daemons[idx].d_firsttime && LogLevel >= 9) 256 sm_syslog(LOG_INFO, NOQID, 257 "accepting connections again for daemon %s", 258 Daemons[idx].d_name); 259 260 /* arrange to (re)open the socket if needed */ 261 (void) opendaemonsocket(&Daemons[idx], FALSE); 262 Daemons[idx].d_firsttime = FALSE; 263 } 264 } 265 266 if (curtime() >= last_disk_space_check) 267 { 268 if (!enoughdiskspace(MinBlocksFree + 1, FALSE)) 269 { 270 if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 271 { 272 /* log only if not logged before */ 273 if (LogLevel >= 9) 274 sm_syslog(LOG_INFO, NOQID, 275 "rejecting new messages: min free: %ld", 276 MinBlocksFree); 277 sm_setproctitle(TRUE, e, 278 "rejecting new messages: min free: %ld", 279 MinBlocksFree); 280 setbitn(D_ETRNONLY, Daemons[idx].d_flags); 281 } 282 } 283 else if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 284 { 285 /* log only if not logged before */ 286 if (LogLevel >= 9) 287 sm_syslog(LOG_INFO, NOQID, 288 "accepting new messages (again)"); 289 /* title will be set below */ 290 clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 291 } 292 /* only check disk space once a minute */ 293 last_disk_space_check = curtime() + 60; 294 } 295 296 # if XDEBUG 297 /* check for disaster */ 298 { 299 char jbuf[MAXHOSTNAMELEN]; 300 301 expand("\201j", jbuf, sizeof jbuf, e); 302 if (!wordinclass(jbuf, 'w')) 303 { 304 dumpstate("daemon lost $j"); 305 sm_syslog(LOG_ALERT, NOQID, 306 "daemon process doesn't have $j in $=w; see syslog"); 307 abort(); 308 } 309 else if (j_has_dot && strchr(jbuf, '.') == NULL) 310 { 311 dumpstate("daemon $j lost dot"); 312 sm_syslog(LOG_ALERT, NOQID, 313 "daemon process $j lost dot; see syslog"); 314 abort(); 315 } 316 } 317 # endif /* XDEBUG */ 318 319 # if 0 320 /* 321 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 322 ** fix the SVr4 problem. But it seems to have gone away, 323 ** so is it worth doing this? 324 */ 325 326 if (DaemonSocket >= 0 && 327 SetNonBlocking(DaemonSocket, FALSE) < 0) 328 log an error here; 329 # endif /* 0 */ 330 (void) releasesignal(SIGALRM); 331 332 for (;;) 333 { 334 int highest = -1; 335 fd_set readfds; 336 struct timeval timeout; 337 338 FD_ZERO(&readfds); 339 340 for (idx = 0; idx < ndaemons; idx++) 341 { 342 /* wait for a connection */ 343 if (Daemons[idx].d_socket >= 0) 344 { 345 if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 346 { 347 sm_setproctitle(TRUE, e, 348 "accepting connections"); 349 } 350 if (Daemons[idx].d_socket > highest) 351 highest = Daemons[idx].d_socket; 352 FD_SET((u_int)Daemons[idx].d_socket, &readfds); 353 } 354 } 355 356 # if NETUNIX 357 if (ControlSocket >= 0) 358 { 359 if (ControlSocket > highest) 360 highest = ControlSocket; 361 FD_SET(ControlSocket, &readfds); 362 } 363 # endif /* NETUNIX */ 364 365 /* 366 ** if one socket is closed, set the timeout 367 ** to 5 seconds (so it might get reopened soon), 368 ** otherwise (all sockets open) 60. 369 */ 370 idx = 0; 371 while (idx < ndaemons && Daemons[idx].d_socket >= 0) 372 idx++; 373 if (idx < ndaemons) 374 timeout.tv_sec = 5; 375 else 376 timeout.tv_sec = 60; 377 timeout.tv_usec = 0; 378 379 t = select(highest + 1, FDSET_CAST &readfds, 380 NULL, NULL, &timeout); 381 382 if (DoQueueRun) 383 (void) runqueue(TRUE, FALSE); 384 if (t <= 0) 385 { 386 timedout = TRUE; 387 break; 388 } 389 390 control = FALSE; 391 errno = 0; 392 curdaemon = -1; 393 394 /* look "round-robin" for an active socket */ 395 if ((idx = olddaemon + 1) >= ndaemons) 396 idx = 0; 397 for (i = 0; i < ndaemons; i++) 398 { 399 if (Daemons[idx].d_socket >= 0 && 400 FD_ISSET(Daemons[idx].d_socket, &readfds)) 401 { 402 lotherend = Daemons[idx].d_socksize; 403 t = accept(Daemons[idx].d_socket, 404 (struct sockaddr *)&RealHostAddr, 405 &lotherend); 406 olddaemon = curdaemon = idx; 407 break; 408 } 409 if (++idx >= ndaemons) 410 idx = 0; 411 } 412 # if NETUNIX 413 if (curdaemon == -1 && ControlSocket >= 0 && 414 FD_ISSET(ControlSocket, &readfds)) 415 { 416 struct sockaddr_un sa_un; 417 418 lotherend = sizeof sa_un; 419 t = accept(ControlSocket, 420 (struct sockaddr *)&sa_un, 421 &lotherend); 422 control = TRUE; 423 } 424 # endif /* NETUNIX */ 425 if (t >= 0 || errno != EINTR) 426 break; 427 } 428 if (timedout) 429 { 430 timedout = FALSE; 431 continue; 432 } 433 save_errno = errno; 434 (void) blocksignal(SIGALRM); 435 if (t < 0) 436 { 437 errno = save_errno; 438 syserr("getrequests: accept"); 439 440 /* arrange to re-open the socket next time around */ 441 (void) close(Daemons[curdaemon].d_socket); 442 Daemons[curdaemon].d_socket = -1; 443 # if SO_REUSEADDR_IS_BROKEN 444 /* 445 ** Give time for bound socket to be released. 446 ** This creates a denial-of-service if you can 447 ** force accept() to fail on affected systems. 448 */ 449 450 Daemons[curdaemon].d_refuse_connections_until = curtime() + 15; 451 # endif /* SO_REUSEADDR_IS_BROKEN */ 452 continue; 453 } 454 455 if (!control) 456 { 457 /* set some daemon related macros */ 458 switch (Daemons[curdaemon].d_addr.sa.sa_family) 459 { 460 case AF_UNSPEC: 461 define(macid("{daemon_family}", NULL), 462 "unspec", &BlankEnvelope); 463 break; 464 # if NETINET 465 case AF_INET: 466 define(macid("{daemon_family}", NULL), 467 "inet", &BlankEnvelope); 468 break; 469 # endif /* NETINET */ 470 # if NETINET6 471 case AF_INET6: 472 define(macid("{daemon_family}", NULL), 473 "inet6", &BlankEnvelope); 474 break; 475 # endif /* NETINET6 */ 476 # if NETISO 477 case AF_ISO: 478 define(macid("{daemon_family}", NULL), 479 "iso", &BlankEnvelope); 480 break; 481 # endif /* NETISO */ 482 # if NETNS 483 case AF_NS: 484 define(macid("{daemon_family}", NULL), 485 "ns", &BlankEnvelope); 486 break; 487 # endif /* NETNS */ 488 # if NETX25 489 case AF_CCITT: 490 define(macid("{daemon_family}", NULL), 491 "x.25", &BlankEnvelope); 492 break; 493 # endif /* NETX25 */ 494 } 495 define(macid("{daemon_name}", NULL), 496 Daemons[curdaemon].d_name, &BlankEnvelope); 497 if (Daemons[curdaemon].d_mflags != NULL) 498 define(macid("{daemon_flags}", NULL), 499 Daemons[curdaemon].d_mflags, 500 &BlankEnvelope); 501 else 502 define(macid("{daemon_flags}", NULL), 503 "", &BlankEnvelope); 504 } 505 506 /* 507 ** Create a subprocess to process the mail. 508 */ 509 510 if (tTd(15, 2)) 511 dprintf("getrequests: forking (fd = %d)\n", t); 512 513 /* 514 ** advance state of PRNG 515 ** this is necessary because otherwise all child processes 516 ** will produce the same PRN sequence and hence the selection 517 ** of a queue directory (and other things, e.g., MX selection) 518 ** are not "really" random. 519 */ 520 # if STARTTLS 521 seed = get_random(); 522 RAND_seed((void *) &last_disk_space_check, 523 sizeof last_disk_space_check); 524 timenow = curtime(); 525 RAND_seed((void *) &timenow, sizeof timenow); 526 RAND_seed((void *) &seed, sizeof seed); 527 # else /* STARTTLS */ 528 (void) get_random(); 529 # endif /* STARTTLS */ 530 531 /* 532 ** Create a pipe to keep the child from writing to the 533 ** socket until after the parent has closed it. Otherwise 534 ** the parent may hang if the child has closed it first. 535 */ 536 537 if (pipe(pipefd) < 0) 538 pipefd[0] = pipefd[1] = -1; 539 540 (void) blocksignal(SIGCHLD); 541 pid = fork(); 542 if (pid < 0) 543 { 544 syserr("daemon: cannot fork"); 545 if (pipefd[0] != -1) 546 { 547 (void) close(pipefd[0]); 548 (void) close(pipefd[1]); 549 } 550 (void) releasesignal(SIGCHLD); 551 (void) sleep(10); 552 (void) close(t); 553 continue; 554 } 555 556 if (pid == 0) 557 { 558 char *p; 559 FILE *inchannel, *outchannel = NULL; 560 561 /* 562 ** CHILD -- return to caller. 563 ** Collect verified idea of sending host. 564 ** Verify calling user id if possible here. 565 */ 566 567 if (!control) 568 { 569 define(macid("{daemon_addr}", NULL), 570 newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)), 571 &BlankEnvelope); 572 (void) snprintf(status, sizeof status, "%d", 573 ntohs(Daemons[curdaemon].d_port)); 574 define(macid("{daemon_port}", NULL), 575 newstr(status), &BlankEnvelope); 576 } 577 578 (void) releasesignal(SIGALRM); 579 (void) releasesignal(SIGCHLD); 580 (void) setsignal(SIGCHLD, SIG_DFL); 581 (void) setsignal(SIGHUP, intsig); 582 for (idx = 0; idx < ndaemons; idx++) 583 { 584 if (Daemons[idx].d_socket >= 0) 585 (void) close(Daemons[idx].d_socket); 586 } 587 clrcontrol(); 588 589 /* Avoid SMTP daemon actions if control command */ 590 if (control) 591 { 592 /* Add control socket process */ 593 proc_list_add(getpid(), "console socket child", 594 PROC_CONTROL_CHILD); 595 } 596 else 597 { 598 proc_list_clear(); 599 600 /* Add parent process as first child item */ 601 proc_list_add(getpid(), "daemon child", 602 PROC_DAEMON_CHILD); 603 604 /* don't schedule queue runs if ETRN */ 605 QueueIntvl = 0; 606 607 sm_setproctitle(TRUE, e, "startup with %s", 608 anynet_ntoa(&RealHostAddr)); 609 } 610 611 if (pipefd[0] != -1) 612 { 613 auto char c; 614 615 /* 616 ** Wait for the parent to close the write end 617 ** of the pipe, which we will see as an EOF. 618 ** This guarantees that we won't write to the 619 ** socket until after the parent has closed 620 ** the pipe. 621 */ 622 623 /* close the write end of the pipe */ 624 (void) close(pipefd[1]); 625 626 /* we shouldn't be interrupted, but ... */ 627 while (read(pipefd[0], &c, 1) < 0 && 628 errno == EINTR) 629 continue; 630 (void) close(pipefd[0]); 631 } 632 633 /* control socket processing */ 634 if (control) 635 { 636 control_command(t, e); 637 638 /* NOTREACHED */ 639 exit(EX_SOFTWARE); 640 } 641 642 /* determine host name */ 643 p = hostnamebyanyaddr(&RealHostAddr); 644 if (strlen(p) > (SIZE_T) MAXNAME) 645 p[MAXNAME] = '\0'; 646 RealHostName = newstr(p); 647 if (RealHostName[0] == '[') 648 { 649 /* TEMP, FAIL: which one? */ 650 define(macid("{client_resolve}", NULL), 651 (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL", 652 &BlankEnvelope); 653 } 654 else 655 define(macid("{client_resolve}", NULL), "OK", 656 &BlankEnvelope); 657 sm_setproctitle(TRUE, e, "startup with %s", p); 658 659 if ((inchannel = fdopen(t, "r")) == NULL || 660 (t = dup(t)) < 0 || 661 (outchannel = fdopen(t, "w")) == NULL) 662 { 663 syserr("cannot open SMTP server channel, fd=%d", t); 664 finis(FALSE, EX_OK); 665 } 666 667 InChannel = inchannel; 668 OutChannel = outchannel; 669 DisConnected = FALSE; 670 671 # ifdef XLA 672 if (!xla_host_ok(RealHostName)) 673 { 674 message("421 4.4.5 Too many SMTP sessions for this host"); 675 finis(FALSE, EX_OK); 676 } 677 # endif /* XLA */ 678 /* find out name for interface of connection */ 679 if (getsockname(fileno(InChannel), &sa.sa, 680 &len) == 0) 681 { 682 p = hostnamebyanyaddr(&sa); 683 if (tTd(15, 9)) 684 dprintf("getreq: got name %s\n", p); 685 define(macid("{if_name}", NULL), 686 newstr(p), &BlankEnvelope); 687 688 /* do this only if it is not the loopback */ 689 /* interface: how to figure out? XXX */ 690 if (!isloopback(sa)) 691 { 692 define(macid("{if_addr}", NULL), 693 newstr(anynet_ntoa(&sa)), 694 &BlankEnvelope); 695 p = xalloc(5); 696 snprintf(p, 4, "%d", sa.sa.sa_family); 697 define(macid("{if_family}", NULL), p, 698 &BlankEnvelope); 699 if (tTd(15, 7)) 700 dprintf("getreq: got addr %s and family %s\n", 701 macvalue(macid("{if_addr}", NULL), 702 &BlankEnvelope), 703 macvalue(macid("{if_addr}", NULL), 704 &BlankEnvelope)); 705 } 706 else 707 { 708 define(macid("{if_addr}", NULL), NULL, 709 &BlankEnvelope); 710 define(macid("{if_family}", NULL), NULL, 711 &BlankEnvelope); 712 } 713 } 714 else 715 { 716 if (tTd(15, 7)) 717 dprintf("getreq: getsockname failed\n"); 718 define(macid("{if_name}", NULL), NULL, 719 &BlankEnvelope); 720 define(macid("{if_addr}", NULL), NULL, 721 &BlankEnvelope); 722 define(macid("{if_family}", NULL), NULL, 723 &BlankEnvelope); 724 } 725 break; 726 } 727 728 /* parent -- keep track of children */ 729 if (control) 730 { 731 snprintf(status, sizeof status, "control socket server child"); 732 proc_list_add(pid, status, PROC_CONTROL); 733 } 734 else 735 { 736 snprintf(status, sizeof status, 737 "SMTP server child for %s", 738 anynet_ntoa(&RealHostAddr)); 739 proc_list_add(pid, status, PROC_DAEMON); 740 } 741 (void) releasesignal(SIGCHLD); 742 743 /* close the read end of the synchronization pipe */ 744 if (pipefd[0] != -1) 745 { 746 (void) close(pipefd[0]); 747 pipefd[0] = -1; 748 } 749 750 /* close the port so that others will hang (for a while) */ 751 (void) close(t); 752 753 /* release the child by closing the read end of the sync pipe */ 754 if (pipefd[1] != -1) 755 { 756 (void) close(pipefd[1]); 757 pipefd[1] = -1; 758 } 759 } 760 761 if (tTd(15, 2)) 762 dprintf("getreq: returning\n"); 763 return &Daemons[curdaemon].d_flags; 764 } 765 /* 766 ** OPENDAEMONSOCKET -- open SMTP socket 767 ** 768 ** Deals with setting all appropriate options. 769 ** 770 ** Parameters: 771 ** d -- the structure for the daemon to open. 772 ** firsttime -- set if this is the initial open. 773 ** 774 ** Returns: 775 ** Size in bytes of the daemon socket addr. 776 ** 777 ** Side Effects: 778 ** Leaves DaemonSocket set to the open socket. 779 ** Exits if the socket cannot be created. 780 */ 781 782 # define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 783 784 static int 785 opendaemonsocket(d, firsttime) 786 struct daemon *d; 787 bool firsttime; 788 { 789 int on = 1; 790 int fdflags; 791 SOCKADDR_LEN_T socksize = 0; 792 int ntries = 0; 793 int save_errno; 794 795 if (tTd(15, 2)) 796 dprintf("opendaemonsocket(%s)\n", d->d_name); 797 798 do 799 { 800 if (ntries > 0) 801 (void) sleep(5); 802 if (firsttime || d->d_socket < 0) 803 { 804 d->d_socket = socket(d->d_addr.sa.sa_family, 805 SOCK_STREAM, 0); 806 if (d->d_socket < 0) 807 { 808 save_errno = errno; 809 syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name); 810 severe: 811 if (LogLevel > 0) 812 sm_syslog(LOG_ALERT, NOQID, 813 "daemon %s: problem creating SMTP socket", d->d_name); 814 d->d_socket = -1; 815 continue; 816 } 817 818 /* turn on network debugging? */ 819 if (tTd(15, 101)) 820 (void) setsockopt(d->d_socket, SOL_SOCKET, 821 SO_DEBUG, (char *)&on, 822 sizeof on); 823 824 (void) setsockopt(d->d_socket, SOL_SOCKET, 825 SO_REUSEADDR, (char *)&on, sizeof on); 826 (void) setsockopt(d->d_socket, SOL_SOCKET, 827 SO_KEEPALIVE, (char *)&on, sizeof on); 828 829 # ifdef SO_RCVBUF 830 if (d->d_tcprcvbufsize > 0) 831 { 832 if (setsockopt(d->d_socket, SOL_SOCKET, 833 SO_RCVBUF, 834 (char *) &d->d_tcprcvbufsize, 835 sizeof(d->d_tcprcvbufsize)) < 0) 836 syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 837 } 838 # endif /* SO_RCVBUF */ 839 # ifdef SO_SNDBUF 840 if (d->d_tcpsndbufsize > 0) 841 { 842 if (setsockopt(d->d_socket, SOL_SOCKET, 843 SO_SNDBUF, 844 (char *) &d->d_tcpsndbufsize, 845 sizeof(d->d_tcpsndbufsize)) < 0) 846 syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 847 } 848 # endif /* SO_SNDBUF */ 849 850 if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 851 fcntl(d->d_socket, F_SETFD, 852 fdflags | FD_CLOEXEC) == -1) 853 { 854 save_errno = errno; 855 syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 856 d->d_name, 857 fdflags == -1 ? "get" : "set", 858 errstring(save_errno)); 859 (void) close(d->d_socket); 860 goto severe; 861 } 862 863 switch (d->d_addr.sa.sa_family) 864 { 865 # if NETINET 866 case AF_INET: 867 socksize = sizeof d->d_addr.sin; 868 break; 869 # endif /* NETINET */ 870 871 # if NETINET6 872 case AF_INET6: 873 socksize = sizeof d->d_addr.sin6; 874 break; 875 # endif /* NETINET6 */ 876 877 # if NETISO 878 case AF_ISO: 879 socksize = sizeof d->d_addr.siso; 880 break; 881 # endif /* NETISO */ 882 883 default: 884 socksize = sizeof d->d_addr; 885 break; 886 } 887 888 if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 889 { 890 /* probably another daemon already */ 891 save_errno = errno; 892 syserr("opendaemonsocket: daemon %s: cannot bind", 893 d->d_name); 894 (void) close(d->d_socket); 895 goto severe; 896 } 897 } 898 if (!firsttime && 899 listen(d->d_socket, d->d_listenqueue) < 0) 900 { 901 save_errno = errno; 902 syserr("opendaemonsocket: daemon %s: cannot listen", 903 d->d_name); 904 (void) close(d->d_socket); 905 goto severe; 906 } 907 return socksize; 908 } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 909 syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 910 d->d_name); 911 /* NOTREACHED */ 912 return -1; /* avoid compiler warning on IRIX */ 913 } 914 /* 915 ** SETUPDAEMON -- setup socket for daemon 916 ** 917 ** Parameters: 918 ** daemonaddr -- socket for daemon 919 ** daemon -- number of daemon 920 ** 921 ** Returns: 922 ** port number on which daemon should run 923 ** 924 */ 925 static u_short 926 setupdaemon(daemonaddr) 927 SOCKADDR *daemonaddr; 928 { 929 u_short port; 930 931 /* 932 ** Set up the address for the mailer. 933 */ 934 935 if (daemonaddr->sa.sa_family == AF_UNSPEC) 936 { 937 memset(daemonaddr, '\0', sizeof *daemonaddr); 938 # if NETINET 939 daemonaddr->sa.sa_family = AF_INET; 940 # endif /* NETINET */ 941 } 942 943 switch (daemonaddr->sa.sa_family) 944 { 945 # if NETINET 946 case AF_INET: 947 if (daemonaddr->sin.sin_addr.s_addr == 0) 948 daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 949 port = daemonaddr->sin.sin_port; 950 break; 951 # endif /* NETINET */ 952 953 # if NETINET6 954 case AF_INET6: 955 if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 956 daemonaddr->sin6.sin6_addr = in6addr_any; 957 port = daemonaddr->sin6.sin6_port; 958 break; 959 # endif /* NETINET6 */ 960 961 default: 962 /* unknown protocol */ 963 port = 0; 964 break; 965 } 966 if (port == 0) 967 { 968 # ifdef NO_GETSERVBYNAME 969 port = htons(25); 970 # else /* NO_GETSERVBYNAME */ 971 { 972 register struct servent *sp; 973 974 sp = getservbyname("smtp", "tcp"); 975 if (sp == NULL) 976 { 977 syserr("554 5.3.5 service \"smtp\" unknown"); 978 port = htons(25); 979 } 980 else 981 port = sp->s_port; 982 } 983 # endif /* NO_GETSERVBYNAME */ 984 } 985 986 switch (daemonaddr->sa.sa_family) 987 { 988 # if NETINET 989 case AF_INET: 990 daemonaddr->sin.sin_port = port; 991 break; 992 # endif /* NETINET */ 993 994 # if NETINET6 995 case AF_INET6: 996 daemonaddr->sin6.sin6_port = port; 997 break; 998 # endif /* NETINET6 */ 999 1000 default: 1001 /* unknown protocol */ 1002 break; 1003 } 1004 return(port); 1005 } 1006 /* 1007 ** CLRDAEMON -- reset the daemon connection 1008 ** 1009 ** Parameters: 1010 ** none. 1011 ** 1012 ** Returns: 1013 ** none. 1014 ** 1015 ** Side Effects: 1016 ** releases any resources used by the passive daemon. 1017 */ 1018 1019 void 1020 clrdaemon() 1021 { 1022 int i; 1023 1024 for (i = 0; i < ndaemons; i++) 1025 { 1026 if (Daemons[i].d_socket >= 0) 1027 (void) close(Daemons[i].d_socket); 1028 Daemons[i].d_socket = -1; 1029 } 1030 } 1031 /* 1032 ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 1033 ** 1034 ** Parameters: 1035 ** p -- the options line. 1036 ** d -- the daemon structure to fill in. 1037 ** 1038 ** Returns: 1039 ** none. 1040 */ 1041 1042 static void 1043 setsockaddroptions(p, d) 1044 register char *p; 1045 struct daemon *d; 1046 { 1047 # if NETISO 1048 short port; 1049 # endif /* NETISO */ 1050 int l; 1051 char *h, *flags; 1052 1053 # if NETINET 1054 if (d->d_addr.sa.sa_family == AF_UNSPEC) 1055 d->d_addr.sa.sa_family = AF_INET; 1056 # endif /* NETINET */ 1057 1058 while (p != NULL) 1059 { 1060 register char *f; 1061 register char *v; 1062 1063 while (isascii(*p) && isspace(*p)) 1064 p++; 1065 if (*p == '\0') 1066 break; 1067 f = p; 1068 p = strchr(p, ','); 1069 if (p != NULL) 1070 *p++ = '\0'; 1071 v = strchr(f, '='); 1072 if (v == NULL) 1073 continue; 1074 while (isascii(*++v) && isspace(*v)) 1075 continue; 1076 if (isascii(*f) && islower(*f)) 1077 *f = toupper(*f); 1078 1079 switch (*f) 1080 { 1081 case 'F': /* address family */ 1082 if (isascii(*v) && isdigit(*v)) 1083 d->d_addr.sa.sa_family = atoi(v); 1084 # if NETINET 1085 else if (strcasecmp(v, "inet") == 0) 1086 d->d_addr.sa.sa_family = AF_INET; 1087 # endif /* NETINET */ 1088 # if NETINET6 1089 else if (strcasecmp(v, "inet6") == 0) 1090 d->d_addr.sa.sa_family = AF_INET6; 1091 # endif /* NETINET6 */ 1092 # if NETISO 1093 else if (strcasecmp(v, "iso") == 0) 1094 d->d_addr.sa.sa_family = AF_ISO; 1095 # endif /* NETISO */ 1096 # if NETNS 1097 else if (strcasecmp(v, "ns") == 0) 1098 d->d_addr.sa.sa_family = AF_NS; 1099 # endif /* NETNS */ 1100 # if NETX25 1101 else if (strcasecmp(v, "x.25") == 0) 1102 d->d_addr.sa.sa_family = AF_CCITT; 1103 # endif /* NETX25 */ 1104 else 1105 syserr("554 5.3.5 Unknown address family %s in Family=option", 1106 v); 1107 break; 1108 1109 case 'A': /* address */ 1110 switch (d->d_addr.sa.sa_family) 1111 { 1112 # if NETINET 1113 case AF_INET: 1114 if (!isascii(*v) || !isdigit(*v) || 1115 ((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE)) 1116 { 1117 register struct hostent *hp; 1118 1119 hp = sm_gethostbyname(v, AF_INET); 1120 if (hp == NULL) 1121 syserr("554 5.3.0 host \"%s\" unknown", 1122 v); 1123 else 1124 { 1125 while (*(hp->h_addr_list) && 1126 hp->h_addrtype != AF_INET) 1127 hp->h_addr_list++; 1128 if (*(hp->h_addr_list) == NULL) 1129 syserr("554 5.3.0 host \"%s\" unknown", 1130 v); 1131 else 1132 memmove(&d->d_addr.sin.sin_addr, 1133 *(hp->h_addr_list), 1134 INADDRSZ); 1135 } 1136 } 1137 break; 1138 # endif /* NETINET */ 1139 1140 # if NETINET6 1141 case AF_INET6: 1142 if (!isascii(*v) || !isxdigit(*v) || 1143 inet_pton(AF_INET6, v, 1144 &d->d_addr.sin6.sin6_addr) != 1) 1145 { 1146 register struct hostent *hp; 1147 1148 hp = sm_gethostbyname(v, AF_INET6); 1149 if (hp == NULL) 1150 syserr("554 5.3.0 host \"%s\" unknown", 1151 v); 1152 else 1153 { 1154 while (*(hp->h_addr_list) && 1155 hp->h_addrtype != AF_INET6) 1156 hp->h_addr_list++; 1157 if (*(hp->h_addr_list) == NULL) 1158 syserr("554 5.3.0 host \"%s\" unknown", 1159 v); 1160 else 1161 memmove(&d->d_addr.sin6.sin6_addr, 1162 *(hp->h_addr_list), 1163 IN6ADDRSZ); 1164 } 1165 } 1166 break; 1167 # endif /* NETINET6 */ 1168 1169 default: 1170 syserr("554 5.3.5 address= option unsupported for family %d", 1171 d->d_addr.sa.sa_family); 1172 break; 1173 } 1174 break; 1175 1176 case 'P': /* port */ 1177 switch (d->d_addr.sa.sa_family) 1178 { 1179 # if NETINET 1180 case AF_INET: 1181 if (isascii(*v) && isdigit(*v)) 1182 d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)v)); 1183 else 1184 { 1185 # ifdef NO_GETSERVBYNAME 1186 syserr("554 5.3.5 invalid port number: %s", 1187 v); 1188 # else /* NO_GETSERVBYNAME */ 1189 register struct servent *sp; 1190 1191 sp = getservbyname(v, "tcp"); 1192 if (sp == NULL) 1193 syserr("554 5.3.5 service \"%s\" unknown", 1194 v); 1195 else 1196 d->d_addr.sin.sin_port = sp->s_port; 1197 # endif /* NO_GETSERVBYNAME */ 1198 } 1199 break; 1200 # endif /* NETINET */ 1201 1202 # if NETINET6 1203 case AF_INET6: 1204 if (isascii(*v) && isdigit(*v)) 1205 d->d_addr.sin6.sin6_port = htons((u_short)atoi(v)); 1206 else 1207 { 1208 # ifdef NO_GETSERVBYNAME 1209 syserr("554 5.3.5 invalid port number: %s", 1210 v); 1211 # else /* NO_GETSERVBYNAME */ 1212 register struct servent *sp; 1213 1214 sp = getservbyname(v, "tcp"); 1215 if (sp == NULL) 1216 syserr("554 5.3.5 service \"%s\" unknown", 1217 v); 1218 else 1219 d->d_addr.sin6.sin6_port = sp->s_port; 1220 # endif /* NO_GETSERVBYNAME */ 1221 } 1222 break; 1223 # endif /* NETINET6 */ 1224 1225 # if NETISO 1226 case AF_ISO: 1227 /* assume two byte transport selector */ 1228 if (isascii(*v) && isdigit(*v)) 1229 port = htons((u_short)atoi(v)); 1230 else 1231 { 1232 # ifdef NO_GETSERVBYNAME 1233 syserr("554 5.3.5 invalid port number: %s", 1234 v); 1235 # else /* NO_GETSERVBYNAME */ 1236 register struct servent *sp; 1237 1238 sp = getservbyname(v, "tcp"); 1239 if (sp == NULL) 1240 syserr("554 5.3.5 service \"%s\" unknown", 1241 v); 1242 else 1243 port = sp->s_port; 1244 # endif /* NO_GETSERVBYNAME */ 1245 } 1246 memmove(TSEL(&d->d_addr.siso), 1247 (char *) &port, 2); 1248 break; 1249 # endif /* NETISO */ 1250 1251 default: 1252 syserr("554 5.3.5 Port= option unsupported for family %d", 1253 d->d_addr.sa.sa_family); 1254 break; 1255 } 1256 break; 1257 1258 case 'L': /* listen queue size */ 1259 d->d_listenqueue = atoi(v); 1260 break; 1261 1262 case 'M': /* modifiers (flags) */ 1263 l = 3 * strlen(v) + 3; 1264 h = v; 1265 flags = xalloc(l); 1266 d->d_mflags = flags; 1267 for (; *h != '\0'; h++) 1268 { 1269 if (!(isascii(*h) && isspace(*h))) 1270 { 1271 if (flags != d->d_mflags) 1272 *flags++ = ' '; 1273 *flags++ = *h; 1274 if (isupper(*h)) 1275 *flags++ = *h; 1276 } 1277 } 1278 *flags++ = '\0'; 1279 for (; *v != '\0'; v++) 1280 if (!(isascii(*v) && isspace(*v))) 1281 setbitn(*v, d->d_flags); 1282 break; 1283 1284 case 'S': /* send buffer size */ 1285 d->d_tcpsndbufsize = atoi(v); 1286 break; 1287 1288 case 'R': /* receive buffer size */ 1289 d->d_tcprcvbufsize = atoi(v); 1290 break; 1291 1292 case 'N': /* name */ 1293 d->d_name = v; 1294 break; 1295 1296 default: 1297 syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 1298 f); 1299 } 1300 } 1301 } 1302 /* 1303 ** SETDAEMONOPTIONS -- set options for running the MTA daemon 1304 ** 1305 ** Parameters: 1306 ** p -- the options line. 1307 ** 1308 ** Returns: 1309 ** TRUE if successful, FALSE otherwise. 1310 */ 1311 1312 bool 1313 setdaemonoptions(p) 1314 register char *p; 1315 { 1316 if (ndaemons >= MAXDAEMONS) 1317 return FALSE; 1318 Daemons[ndaemons].d_socket = -1; 1319 Daemons[ndaemons].d_listenqueue = 10; 1320 clrbitmap(Daemons[ndaemons].d_flags); 1321 setsockaddroptions(p, &Daemons[ndaemons]); 1322 1323 if (Daemons[ndaemons].d_name != NULL) 1324 Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name); 1325 else 1326 { 1327 char num[30]; 1328 1329 snprintf(num, sizeof num, "Daemon%d", ndaemons); 1330 Daemons[ndaemons].d_name = newstr(num); 1331 } 1332 1333 if (tTd(37, 1)) 1334 { 1335 dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name); 1336 if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags)) 1337 dprintf("ETRNONLY "); 1338 if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags)) 1339 dprintf("NOETRN "); 1340 dprintf("\n"); 1341 } 1342 ++ndaemons; 1343 return TRUE; 1344 } 1345 /* 1346 ** INITDAEMON -- initialize daemon if not yet done. 1347 ** 1348 ** Parameters: 1349 ** none 1350 ** 1351 ** Returns: 1352 ** none 1353 ** 1354 ** Side Effects: 1355 ** initializes structure for one daemon. 1356 */ 1357 void 1358 initdaemon() 1359 { 1360 if (ndaemons == 0) 1361 { 1362 Daemons[ndaemons].d_socket = -1; 1363 Daemons[ndaemons].d_listenqueue = 10; 1364 Daemons[ndaemons].d_name = "Daemon0"; 1365 ndaemons = 1; 1366 } 1367 } 1368 /* 1369 ** SETCLIENTOPTIONS -- set options for running the client 1370 ** 1371 ** Parameters: 1372 ** p -- the options line. 1373 ** 1374 ** Returns: 1375 ** none. 1376 */ 1377 1378 static SOCKADDR ClientAddr; /* address for client */ 1379 1380 void 1381 setclientoptions(p) 1382 register char *p; 1383 { 1384 struct daemon d; 1385 extern ENVELOPE BlankEnvelope; 1386 1387 memset(&d, '\0', sizeof d); 1388 setsockaddroptions(p, &d); 1389 1390 /* grab what we need */ 1391 memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr); 1392 TcpSndBufferSize = d.d_tcpsndbufsize; 1393 TcpRcvBufferSize = d.d_tcprcvbufsize; 1394 if (d.d_mflags != NULL) 1395 define(macid("{client_flags}", NULL), d.d_mflags, 1396 &BlankEnvelope); 1397 else 1398 define(macid("{client_flags}", NULL), "", &BlankEnvelope); 1399 } 1400 /* 1401 ** ADDR_FAMILY -- determine address family from address 1402 ** 1403 ** Parameters: 1404 ** addr -- the string representation of the address 1405 ** 1406 ** Returns: 1407 ** AF_INET, AF_INET6 or AF_UNSPEC 1408 ** 1409 ** Side Effects: 1410 ** none. 1411 */ 1412 1413 static int 1414 addr_family(addr) 1415 char *addr; 1416 { 1417 # if NETINET6 1418 SOCKADDR clt_addr; 1419 # endif /* NETINET6 */ 1420 1421 # if NETINET 1422 if (inet_addr(addr) != INADDR_NONE) 1423 { 1424 if (tTd(16, 9)) 1425 printf("addr_family(%s): INET\n", addr); 1426 return AF_INET; 1427 } 1428 # endif /* NETINET */ 1429 # if NETINET6 1430 if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 1431 { 1432 if (tTd(16, 9)) 1433 printf("addr_family(%s): INET6\n", addr); 1434 return AF_INET6; 1435 } 1436 # endif /* NETINET6 */ 1437 if (tTd(16, 9)) 1438 printf("addr_family(%s): UNSPEC\n", addr); 1439 return AF_UNSPEC; 1440 } 1441 /* 1442 ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 1443 ** 1444 ** Parameters: 1445 ** host -- the name of the host. 1446 ** port -- the port number to connect to. 1447 ** mci -- a pointer to the mail connection information 1448 ** structure to be filled in. 1449 ** e -- the current envelope. 1450 ** 1451 ** Returns: 1452 ** An exit code telling whether the connection could be 1453 ** made and if not why not. 1454 ** 1455 ** Side Effects: 1456 ** none. 1457 */ 1458 1459 static jmp_buf CtxConnectTimeout; 1460 1461 SOCKADDR CurHostAddr; /* address of current host */ 1462 1463 int 1464 makeconnection(host, port, mci, e) 1465 char *host; 1466 volatile u_int port; 1467 register MCI *mci; 1468 ENVELOPE *e; 1469 { 1470 register volatile int addrno = 0; 1471 register volatile int s; 1472 register struct hostent *volatile hp = (struct hostent *)NULL; 1473 SOCKADDR addr; 1474 SOCKADDR clt_addr; 1475 int save_errno = 0; 1476 volatile SOCKADDR_LEN_T addrlen; 1477 volatile bool firstconnect; 1478 EVENT *volatile ev = NULL; 1479 # if NETINET6 1480 volatile bool v6found = FALSE; 1481 # endif /* NETINET6 */ 1482 volatile int family = InetMode; 1483 SOCKADDR_LEN_T len; 1484 volatile SOCKADDR_LEN_T socksize = 0; 1485 volatile bool clt_bind; 1486 BITMAP256 d_flags; 1487 char *p; 1488 extern ENVELOPE BlankEnvelope; 1489 1490 /* retranslate ${daemon_flags} into bitmap */ 1491 clrbitmap(d_flags); 1492 if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL) 1493 { 1494 for (; *p != '\0'; p++) 1495 { 1496 if (!(isascii(*p) && isspace(*p))) 1497 setbitn(*p, d_flags); 1498 } 1499 } 1500 1501 /* "add" ${client_flags} to bitmap */ 1502 if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL) 1503 { 1504 for (; *p != '\0'; p++) 1505 { 1506 /* look for just this one flag */ 1507 if (*p == D_IFNHELO) 1508 { 1509 setbitn(*p, d_flags); 1510 break; 1511 } 1512 } 1513 } 1514 1515 # if NETINET6 1516 v4retry: 1517 # endif /* NETINET6 */ 1518 clt_bind = FALSE; 1519 1520 /* Set up the address for outgoing connection. */ 1521 if (bitnset(D_BINDIF, d_flags) && 1522 (p = macvalue(macid("{if_addr}", NULL), e)) != NULL) 1523 { 1524 # if NETINET6 1525 char p6[INET6_ADDRSTRLEN]; 1526 # endif /* NETINET6 */ 1527 1528 memset(&clt_addr, '\0', sizeof clt_addr); 1529 1530 /* infer the address family from the address itself */ 1531 clt_addr.sa.sa_family = addr_family(p); 1532 switch (clt_addr.sa.sa_family) 1533 { 1534 # if NETINET 1535 case AF_INET: 1536 if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p)) 1537 != INADDR_NONE) 1538 { 1539 clt_bind = TRUE; 1540 socksize = sizeof (struct sockaddr_in); 1541 } 1542 else if (clt_addr.sin.sin_port != 0) 1543 { 1544 clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 1545 clt_bind = TRUE; 1546 socksize = sizeof (struct sockaddr_in); 1547 } 1548 break; 1549 # endif /* NETINET */ 1550 1551 # if NETINET6 1552 case AF_INET6: 1553 if (inet_addr(p) != INADDR_NONE) 1554 snprintf(p6, sizeof p6, "::ffff:%s", p); 1555 else 1556 strlcpy(p6, p, sizeof p6); 1557 if (inet_pton(AF_INET6, p6, 1558 &clt_addr.sin6.sin6_addr) == 1) 1559 { 1560 clt_bind = TRUE; 1561 socksize = sizeof (struct sockaddr_in6); 1562 } 1563 else if (clt_addr.sin6.sin6_port != 0) 1564 { 1565 if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 1566 clt_addr.sin6.sin6_addr = in6addr_any; 1567 clt_bind = TRUE; 1568 socksize = sizeof (struct sockaddr_in6); 1569 } 1570 break; 1571 # endif /* NETINET6 */ 1572 1573 # if 0 1574 default: 1575 syserr("554 5.3.5 Address= option unsupported for family %d", 1576 clt_addr.sa.sa_family); 1577 break; 1578 # endif /* 0 */ 1579 } 1580 if (clt_bind) 1581 family = clt_addr.sa.sa_family; 1582 } 1583 else 1584 { 1585 STRUCTCOPY(ClientAddr, clt_addr); 1586 if (clt_addr.sa.sa_family == AF_UNSPEC) 1587 clt_addr.sa.sa_family = InetMode; 1588 switch (clt_addr.sa.sa_family) 1589 { 1590 # if NETINET 1591 case AF_INET: 1592 if (clt_addr.sin.sin_addr.s_addr == 0) 1593 clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 1594 else 1595 clt_bind = TRUE; 1596 if (clt_addr.sin.sin_port != 0) 1597 clt_bind = TRUE; 1598 socksize = sizeof (struct sockaddr_in); 1599 break; 1600 # endif /* NETINET */ 1601 # if NETINET6 1602 case AF_INET6: 1603 if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 1604 clt_addr.sin6.sin6_addr = in6addr_any; 1605 else 1606 clt_bind = TRUE; 1607 socksize = sizeof (struct sockaddr_in6); 1608 if (clt_addr.sin6.sin6_port != 0) 1609 clt_bind = TRUE; 1610 break; 1611 # endif /* NETINET6 */ 1612 # if NETISO 1613 case AF_ISO: 1614 socksize = sizeof clt_addr.siso; 1615 clt_bind = TRUE; 1616 break; 1617 # endif /* NETISO */ 1618 default: 1619 break; 1620 } 1621 } 1622 1623 /* 1624 ** Set up the address for the mailer. 1625 ** Accept "[a.b.c.d]" syntax for host name. 1626 */ 1627 1628 # if NAMED_BIND 1629 h_errno = 0; 1630 # endif /* NAMED_BIND */ 1631 errno = 0; 1632 memset(&CurHostAddr, '\0', sizeof CurHostAddr); 1633 memset(&addr, '\0', sizeof addr); 1634 SmtpPhase = mci->mci_phase = "initial connection"; 1635 CurHostName = host; 1636 1637 if (host[0] == '[') 1638 { 1639 p = strchr(host, ']'); 1640 if (p != NULL) 1641 { 1642 # if NETINET 1643 unsigned long hid = INADDR_NONE; 1644 # endif /* NETINET */ 1645 # if NETINET6 1646 struct sockaddr_in6 hid6; 1647 # endif /* NETINET6 */ 1648 1649 *p = '\0'; 1650 # if NETINET6 1651 memset(&hid6, '\0', sizeof hid6); 1652 # endif /* NETINET6 */ 1653 # if NETINET 1654 if (family == AF_INET && 1655 (hid = inet_addr(&host[1])) != INADDR_NONE) 1656 { 1657 addr.sin.sin_family = AF_INET; 1658 addr.sin.sin_addr.s_addr = hid; 1659 } 1660 else 1661 # endif /* NETINET */ 1662 # if NETINET6 1663 if (family == AF_INET6 && 1664 inet_pton(AF_INET6, &host[1], 1665 &hid6.sin6_addr) == 1) 1666 { 1667 addr.sin6.sin6_family = AF_INET6; 1668 addr.sin6.sin6_addr = hid6.sin6_addr; 1669 } 1670 else 1671 # endif /* NETINET6 */ 1672 { 1673 /* try it as a host name (avoid MX lookup) */ 1674 hp = sm_gethostbyname(&host[1], family); 1675 if (hp == NULL && p[-1] == '.') 1676 { 1677 # if NAMED_BIND 1678 int oldopts = _res.options; 1679 1680 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 1681 # endif /* NAMED_BIND */ 1682 p[-1] = '\0'; 1683 hp = sm_gethostbyname(&host[1], 1684 family); 1685 p[-1] = '.'; 1686 # if NAMED_BIND 1687 _res.options = oldopts; 1688 # endif /* NAMED_BIND */ 1689 } 1690 *p = ']'; 1691 goto gothostent; 1692 } 1693 *p = ']'; 1694 } 1695 if (p == NULL) 1696 { 1697 extern char MsgBuf[]; 1698 1699 usrerrenh("5.1.2", 1700 "553 Invalid numeric domain spec \"%s\"", 1701 host); 1702 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 1703 errno = EINVAL; 1704 return EX_NOHOST; 1705 } 1706 } 1707 else 1708 { 1709 /* contortion to get around SGI cc complaints */ 1710 { 1711 p = &host[strlen(host) - 1]; 1712 hp = sm_gethostbyname(host, family); 1713 if (hp == NULL && *p == '.') 1714 { 1715 # if NAMED_BIND 1716 int oldopts = _res.options; 1717 1718 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 1719 # endif /* NAMED_BIND */ 1720 *p = '\0'; 1721 hp = sm_gethostbyname(host, family); 1722 *p = '.'; 1723 # if NAMED_BIND 1724 _res.options = oldopts; 1725 # endif /* NAMED_BIND */ 1726 } 1727 } 1728 gothostent: 1729 if (hp == NULL) 1730 { 1731 # if NAMED_BIND 1732 /* check for name server timeouts */ 1733 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || 1734 (errno == ECONNREFUSED && UseNameServer)) 1735 { 1736 save_errno = errno; 1737 mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL); 1738 errno = save_errno; 1739 return EX_TEMPFAIL; 1740 } 1741 # endif /* NAMED_BIND */ 1742 # if NETINET6 1743 /* 1744 ** Try v6 first, then fall back to v4. 1745 ** If we found a v6 address, but no v4 1746 ** addresses, then TEMPFAIL. 1747 */ 1748 1749 if (family == AF_INET6) 1750 { 1751 family = AF_INET; 1752 goto v4retry; 1753 } 1754 if (v6found) 1755 goto v6tempfail; 1756 # endif /* NETINET6 */ 1757 save_errno = errno; 1758 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1759 errno = save_errno; 1760 return EX_NOHOST; 1761 } 1762 addr.sa.sa_family = hp->h_addrtype; 1763 switch (hp->h_addrtype) 1764 { 1765 # if NETINET 1766 case AF_INET: 1767 memmove(&addr.sin.sin_addr, 1768 hp->h_addr, 1769 INADDRSZ); 1770 break; 1771 # endif /* NETINET */ 1772 1773 # if NETINET6 1774 case AF_INET6: 1775 memmove(&addr.sin6.sin6_addr, 1776 hp->h_addr, 1777 IN6ADDRSZ); 1778 break; 1779 # endif /* NETINET6 */ 1780 1781 default: 1782 if (hp->h_length > sizeof addr.sa.sa_data) 1783 { 1784 syserr("makeconnection: long sa_data: family %d len %d", 1785 hp->h_addrtype, hp->h_length); 1786 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1787 errno = EINVAL; 1788 return EX_NOHOST; 1789 } 1790 memmove(addr.sa.sa_data, 1791 hp->h_addr, 1792 hp->h_length); 1793 break; 1794 } 1795 addrno = 1; 1796 } 1797 1798 /* 1799 ** Determine the port number. 1800 */ 1801 1802 if (port == 0) 1803 { 1804 # ifdef NO_GETSERVBYNAME 1805 port = htons(25); 1806 # else /* NO_GETSERVBYNAME */ 1807 register struct servent *sp = getservbyname("smtp", "tcp"); 1808 1809 if (sp == NULL) 1810 { 1811 if (LogLevel > 2) 1812 sm_syslog(LOG_ERR, NOQID, 1813 "makeconnection: service \"smtp\" unknown"); 1814 port = htons(25); 1815 } 1816 else 1817 port = sp->s_port; 1818 # endif /* NO_GETSERVBYNAME */ 1819 } 1820 1821 switch (addr.sa.sa_family) 1822 { 1823 # if NETINET 1824 case AF_INET: 1825 addr.sin.sin_port = port; 1826 addrlen = sizeof (struct sockaddr_in); 1827 break; 1828 # endif /* NETINET */ 1829 1830 # if NETINET6 1831 case AF_INET6: 1832 addr.sin6.sin6_port = port; 1833 addrlen = sizeof (struct sockaddr_in6); 1834 break; 1835 # endif /* NETINET6 */ 1836 1837 # if NETISO 1838 case AF_ISO: 1839 /* assume two byte transport selector */ 1840 memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 1841 addrlen = sizeof (struct sockaddr_iso); 1842 break; 1843 # endif /* NETISO */ 1844 1845 default: 1846 syserr("Can't connect to address family %d", addr.sa.sa_family); 1847 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 1848 errno = EINVAL; 1849 return EX_NOHOST; 1850 } 1851 1852 /* 1853 ** Try to actually open the connection. 1854 */ 1855 1856 # ifdef XLA 1857 /* if too many connections, don't bother trying */ 1858 if (!xla_noqueue_ok(host)) 1859 return EX_TEMPFAIL; 1860 # endif /* XLA */ 1861 1862 firstconnect = TRUE; 1863 for (;;) 1864 { 1865 if (tTd(16, 1)) 1866 dprintf("makeconnection (%s [%s])\n", 1867 host, anynet_ntoa(&addr)); 1868 1869 /* save for logging */ 1870 CurHostAddr = addr; 1871 1872 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 1873 { 1874 int rport = IPPORT_RESERVED - 1; 1875 1876 s = rresvport(&rport); 1877 } 1878 else 1879 { 1880 s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 1881 } 1882 if (s < 0) 1883 { 1884 save_errno = errno; 1885 syserr("makeconnection: cannot create socket"); 1886 # ifdef XLA 1887 xla_host_end(host); 1888 # endif /* XLA */ 1889 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 1890 errno = save_errno; 1891 return EX_TEMPFAIL; 1892 } 1893 1894 # ifdef SO_SNDBUF 1895 if (TcpSndBufferSize > 0) 1896 { 1897 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 1898 (char *) &TcpSndBufferSize, 1899 sizeof(TcpSndBufferSize)) < 0) 1900 syserr("makeconnection: setsockopt(SO_SNDBUF)"); 1901 } 1902 # endif /* SO_SNDBUF */ 1903 # ifdef SO_RCVBUF 1904 if (TcpRcvBufferSize > 0) 1905 { 1906 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 1907 (char *) &TcpRcvBufferSize, 1908 sizeof(TcpRcvBufferSize)) < 0) 1909 syserr("makeconnection: setsockopt(SO_RCVBUF)"); 1910 } 1911 # endif /* SO_RCVBUF */ 1912 1913 1914 if (tTd(16, 1)) 1915 dprintf("makeconnection: fd=%d\n", s); 1916 1917 /* turn on network debugging? */ 1918 if (tTd(16, 101)) 1919 { 1920 int on = 1; 1921 1922 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 1923 (char *)&on, sizeof on); 1924 } 1925 if (e->e_xfp != NULL) 1926 (void) fflush(e->e_xfp); /* for debugging */ 1927 errno = 0; /* for debugging */ 1928 1929 if (clt_bind) 1930 { 1931 int on = 1; 1932 1933 switch (clt_addr.sa.sa_family) 1934 { 1935 # if NETINET 1936 case AF_INET: 1937 if (clt_addr.sin.sin_port != 0) 1938 (void) setsockopt(s, SOL_SOCKET, 1939 SO_REUSEADDR, 1940 (char *) &on, 1941 sizeof on); 1942 break; 1943 # endif /* NETINET */ 1944 1945 # if NETINET6 1946 case AF_INET6: 1947 if (clt_addr.sin6.sin6_port != 0) 1948 (void) setsockopt(s, SOL_SOCKET, 1949 SO_REUSEADDR, 1950 (char *) &on, 1951 sizeof on); 1952 break; 1953 # endif /* NETINET6 */ 1954 } 1955 1956 if (bind(s, &clt_addr.sa, socksize) < 0) 1957 { 1958 save_errno = errno; 1959 (void) close(s); 1960 errno = save_errno; 1961 syserr("makeconnection: cannot bind socket [%s]", 1962 anynet_ntoa(&clt_addr)); 1963 errno = save_errno; 1964 return EX_TEMPFAIL; 1965 } 1966 } 1967 1968 /* 1969 ** Linux seems to hang in connect for 90 minutes (!!!). 1970 ** Time out the connect to avoid this problem. 1971 */ 1972 1973 if (setjmp(CtxConnectTimeout) == 0) 1974 { 1975 int i; 1976 1977 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 1978 ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); 1979 else if (TimeOuts.to_connect != 0) 1980 ev = setevent(TimeOuts.to_connect, connecttimeout, 0); 1981 else 1982 ev = NULL; 1983 1984 switch (ConnectOnlyTo.sa.sa_family) 1985 { 1986 # if NETINET 1987 case AF_INET: 1988 addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 1989 break; 1990 # endif /* NETINET */ 1991 1992 # if NETINET6 1993 case AF_INET6: 1994 memmove(&addr.sin6.sin6_addr, 1995 &ConnectOnlyTo.sin6.sin6_addr, 1996 IN6ADDRSZ); 1997 break; 1998 # endif /* NETINET6 */ 1999 } 2000 i = connect(s, (struct sockaddr *) &addr, addrlen); 2001 save_errno = errno; 2002 if (ev != NULL) 2003 clrevent(ev); 2004 if (i >= 0) 2005 break; 2006 } 2007 else 2008 save_errno = errno; 2009 2010 /* if running demand-dialed connection, try again */ 2011 if (DialDelay > 0 && firstconnect) 2012 { 2013 if (tTd(16, 1)) 2014 dprintf("Connect failed (%s); trying again...\n", 2015 errstring(save_errno)); 2016 firstconnect = FALSE; 2017 (void) sleep(DialDelay); 2018 continue; 2019 } 2020 2021 /* couldn't connect.... figure out why */ 2022 (void) close(s); 2023 2024 if (LogLevel >= 14) 2025 sm_syslog(LOG_INFO, e->e_id, 2026 "makeconnection (%s [%s]) failed: %s", 2027 host, anynet_ntoa(&addr), 2028 errstring(save_errno)); 2029 2030 if (hp != NULL && hp->h_addr_list[addrno] != NULL) 2031 { 2032 if (tTd(16, 1)) 2033 dprintf("Connect failed (%s); trying new address....\n", 2034 errstring(save_errno)); 2035 switch (addr.sa.sa_family) 2036 { 2037 # if NETINET 2038 case AF_INET: 2039 memmove(&addr.sin.sin_addr, 2040 hp->h_addr_list[addrno++], 2041 INADDRSZ); 2042 break; 2043 # endif /* NETINET */ 2044 2045 # if NETINET6 2046 case AF_INET6: 2047 memmove(&addr.sin6.sin6_addr, 2048 hp->h_addr_list[addrno++], 2049 IN6ADDRSZ); 2050 break; 2051 # endif /* NETINET6 */ 2052 2053 default: 2054 memmove(addr.sa.sa_data, 2055 hp->h_addr_list[addrno++], 2056 hp->h_length); 2057 break; 2058 } 2059 continue; 2060 } 2061 errno = save_errno; 2062 2063 # if NETINET6 2064 if (family == AF_INET6) 2065 { 2066 if (tTd(16, 1)) 2067 dprintf("Connect failed (%s); retrying with AF_INET....\n", 2068 errstring(save_errno)); 2069 v6found = TRUE; 2070 family = AF_INET; 2071 goto v4retry; 2072 } 2073 v6tempfail: 2074 # endif /* NETINET6 */ 2075 /* couldn't open connection */ 2076 # if NETINET6 2077 /* Don't clobber an already saved errno from v4retry */ 2078 if (errno > 0) 2079 # endif /* NETINET6 */ 2080 save_errno = errno; 2081 if (tTd(16, 1)) 2082 dprintf("Connect failed (%s)\n", errstring(save_errno)); 2083 # ifdef XLA 2084 xla_host_end(host); 2085 # endif /* XLA */ 2086 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2087 errno = save_errno; 2088 return EX_TEMPFAIL; 2089 } 2090 2091 /* connection ok, put it into canonical form */ 2092 mci->mci_out = NULL; 2093 if ((mci->mci_out = fdopen(s, "w")) == NULL || 2094 (s = dup(s)) < 0 || 2095 (mci->mci_in = fdopen(s, "r")) == NULL) 2096 { 2097 save_errno = errno; 2098 syserr("cannot open SMTP client channel, fd=%d", s); 2099 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2100 if (mci->mci_out != NULL) 2101 (void) fclose(mci->mci_out); 2102 (void) close(s); 2103 errno = save_errno; 2104 return EX_TEMPFAIL; 2105 } 2106 2107 /* find out name for Interface through which we connect */ 2108 len = sizeof addr; 2109 if (getsockname(s, &addr.sa, &len) == 0) 2110 { 2111 char *name; 2112 char *p; 2113 2114 define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)), 2115 &BlankEnvelope); 2116 p = xalloc(5); 2117 snprintf(p, 4, "%d", addr.sa.sa_family); 2118 define(macid("{if_family}", NULL), p, &BlankEnvelope); 2119 2120 name = hostnamebyanyaddr(&addr); 2121 define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope); 2122 if (LogLevel > 11) 2123 { 2124 /* log connection information */ 2125 sm_syslog(LOG_INFO, e->e_id, 2126 "SMTP outgoing connect on %.40s", name); 2127 } 2128 if (bitnset(D_IFNHELO, d_flags)) 2129 { 2130 if (name[0] != '[' && strchr(name, '.') != NULL) 2131 mci->mci_heloname = newstr(name); 2132 } 2133 } 2134 else 2135 { 2136 define(macid("{if_name}", NULL), NULL, &BlankEnvelope); 2137 define(macid("{if_addr}", NULL), NULL, &BlankEnvelope); 2138 define(macid("{if_family}", NULL), NULL, &BlankEnvelope); 2139 } 2140 mci_setstat(mci, EX_OK, NULL, NULL); 2141 return EX_OK; 2142 } 2143 2144 static void 2145 connecttimeout() 2146 { 2147 errno = ETIMEDOUT; 2148 longjmp(CtxConnectTimeout, 1); 2149 } 2150 /* 2151 ** MAKECONNECTION_DS -- make a connection to a domain socket. 2152 ** 2153 ** Parameters: 2154 ** mux_path -- the path of the socket to connect to. 2155 ** mci -- a pointer to the mail connection information 2156 ** structure to be filled in. 2157 ** 2158 ** Returns: 2159 ** An exit code telling whether the connection could be 2160 ** made and if not why not. 2161 ** 2162 ** Side Effects: 2163 ** none. 2164 */ 2165 2166 # if NETUNIX 2167 int makeconnection_ds(mux_path, mci) 2168 char *mux_path; 2169 register MCI *mci; 2170 { 2171 int sock; 2172 int rval, save_errno; 2173 long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 2174 struct sockaddr_un unix_addr; 2175 2176 /* if not safe, don't connect */ 2177 rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 2178 sff, S_IRUSR|S_IWUSR, NULL); 2179 2180 if (rval != 0) 2181 { 2182 syserr("makeconnection_ds: unsafe domain socket"); 2183 mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 2184 errno = rval; 2185 return EX_TEMPFAIL; 2186 } 2187 2188 /* prepare address structure */ 2189 memset(&unix_addr, '\0', sizeof unix_addr); 2190 unix_addr.sun_family = AF_UNIX; 2191 2192 if (strlen(mux_path) >= sizeof unix_addr.sun_path) 2193 { 2194 syserr("makeconnection_ds: domain socket name too long"); 2195 /* XXX why TEMPFAIL ? */ 2196 mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 2197 errno = ENAMETOOLONG; 2198 return EX_UNAVAILABLE; 2199 } 2200 (void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path); 2201 2202 /* initialize domain socket */ 2203 sock = socket(AF_UNIX, SOCK_STREAM, 0); 2204 if (sock == -1) 2205 { 2206 save_errno = errno; 2207 syserr("makeconnection_ds: could not create domain socket"); 2208 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2209 errno = save_errno; 2210 return EX_TEMPFAIL; 2211 } 2212 2213 /* connect to server */ 2214 if (connect(sock, (struct sockaddr *) &unix_addr, 2215 sizeof(unix_addr)) == -1) 2216 { 2217 save_errno = errno; 2218 syserr("Could not connect to socket %s", mux_path); 2219 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2220 (void) close(sock); 2221 errno = save_errno; 2222 return EX_TEMPFAIL; 2223 } 2224 2225 /* connection ok, put it into canonical form */ 2226 mci->mci_out = NULL; 2227 if ((mci->mci_out = fdopen(sock, "w")) == NULL || 2228 (sock = dup(sock)) < 0 || 2229 (mci->mci_in = fdopen(sock, "r")) == NULL) 2230 { 2231 save_errno = errno; 2232 syserr("cannot open SMTP client channel, fd=%d", sock); 2233 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2234 if (mci->mci_out != NULL) 2235 (void) fclose(mci->mci_out); 2236 (void) close(sock); 2237 errno = save_errno; 2238 return EX_TEMPFAIL; 2239 } 2240 2241 mci_setstat(mci, EX_OK, NULL, NULL); 2242 errno = 0; 2243 return EX_OK; 2244 } 2245 # endif /* NETUNIX */ 2246 /* 2247 ** MYHOSTNAME -- return the name of this host. 2248 ** 2249 ** Parameters: 2250 ** hostbuf -- a place to return the name of this host. 2251 ** size -- the size of hostbuf. 2252 ** 2253 ** Returns: 2254 ** A list of aliases for this host. 2255 ** 2256 ** Side Effects: 2257 ** Adds numeric codes to $=w. 2258 */ 2259 2260 struct hostent * 2261 myhostname(hostbuf, size) 2262 char hostbuf[]; 2263 int size; 2264 { 2265 register struct hostent *hp; 2266 2267 if (gethostname(hostbuf, size) < 0) 2268 { 2269 (void) strlcpy(hostbuf, "localhost", size); 2270 } 2271 hp = sm_gethostbyname(hostbuf, InetMode); 2272 if (hp == NULL) 2273 return NULL; 2274 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 2275 (void) cleanstrcpy(hostbuf, hp->h_name, size); 2276 2277 # if NETINFO 2278 if (strchr(hostbuf, '.') == NULL) 2279 { 2280 char *domainname; 2281 2282 domainname = ni_propval("/locations", NULL, "resolver", 2283 "domain", '\0'); 2284 if (domainname != NULL && 2285 strlen(domainname) + strlen(hostbuf) + 1 < size) 2286 { 2287 (void) strlcat(hostbuf, ".", size); 2288 (void) strlcat(hostbuf, domainname, size); 2289 } 2290 } 2291 # endif /* NETINFO */ 2292 2293 /* 2294 ** If there is still no dot in the name, try looking for a 2295 ** dotted alias. 2296 */ 2297 2298 if (strchr(hostbuf, '.') == NULL) 2299 { 2300 char **ha; 2301 2302 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 2303 { 2304 if (strchr(*ha, '.') != NULL) 2305 { 2306 (void) cleanstrcpy(hostbuf, *ha, size - 1); 2307 hostbuf[size - 1] = '\0'; 2308 break; 2309 } 2310 } 2311 } 2312 2313 /* 2314 ** If _still_ no dot, wait for a while and try again -- it is 2315 ** possible that some service is starting up. This can result 2316 ** in excessive delays if the system is badly configured, but 2317 ** there really isn't a way around that, particularly given that 2318 ** the config file hasn't been read at this point. 2319 ** All in all, a bit of a mess. 2320 */ 2321 2322 if (strchr(hostbuf, '.') == NULL && 2323 !getcanonname(hostbuf, size, TRUE)) 2324 { 2325 sm_syslog(LOG_CRIT, NOQID, 2326 "My unqualified host name (%s) unknown; sleeping for retry", 2327 hostbuf); 2328 message("My unqualified host name (%s) unknown; sleeping for retry", 2329 hostbuf); 2330 (void) sleep(60); 2331 if (!getcanonname(hostbuf, size, TRUE)) 2332 { 2333 sm_syslog(LOG_ALERT, NOQID, 2334 "unable to qualify my own domain name (%s) -- using short name", 2335 hostbuf); 2336 message("WARNING: unable to qualify my own domain name (%s) -- using short name", 2337 hostbuf); 2338 } 2339 } 2340 return hp; 2341 } 2342 /* 2343 ** ADDRCMP -- compare two host addresses 2344 ** 2345 ** Parameters: 2346 ** hp -- hostent structure for the first address 2347 ** ha -- actual first address 2348 ** sa -- second address 2349 ** 2350 ** Returns: 2351 ** 0 -- if ha and sa match 2352 ** else -- they don't match 2353 */ 2354 2355 static int 2356 addrcmp(hp, ha, sa) 2357 struct hostent *hp; 2358 char *ha; 2359 SOCKADDR *sa; 2360 { 2361 # if NETINET6 2362 u_char *a; 2363 # endif /* NETINET6 */ 2364 2365 switch (sa->sa.sa_family) 2366 { 2367 # if NETINET 2368 case AF_INET: 2369 if (hp->h_addrtype == AF_INET) 2370 return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 2371 break; 2372 # endif /* NETINET */ 2373 2374 # if NETINET6 2375 case AF_INET6: 2376 a = (u_char *) &sa->sin6.sin6_addr; 2377 2378 /* Straight binary comparison */ 2379 if (hp->h_addrtype == AF_INET6) 2380 return memcmp(ha, a, IN6ADDRSZ); 2381 2382 /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 2383 if (hp->h_addrtype == AF_INET && 2384 IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 2385 return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 2386 break; 2387 # endif /* NETINET6 */ 2388 } 2389 return -1; 2390 } 2391 /* 2392 ** GETAUTHINFO -- get the real host name associated with a file descriptor 2393 ** 2394 ** Uses RFC1413 protocol to try to get info from the other end. 2395 ** 2396 ** Parameters: 2397 ** fd -- the descriptor 2398 ** may_be_forged -- an outage that is set to TRUE if the 2399 ** forward lookup of RealHostName does not match 2400 ** RealHostAddr; set to FALSE if they do match. 2401 ** 2402 ** Returns: 2403 ** The user@host information associated with this descriptor. 2404 */ 2405 2406 static jmp_buf CtxAuthTimeout; 2407 2408 static void 2409 authtimeout() 2410 { 2411 longjmp(CtxAuthTimeout, 1); 2412 } 2413 2414 char * 2415 getauthinfo(fd, may_be_forged) 2416 int fd; 2417 bool *may_be_forged; 2418 { 2419 volatile u_short port = 0; 2420 SOCKADDR_LEN_T falen; 2421 register char *volatile p = NULL; 2422 SOCKADDR la; 2423 SOCKADDR_LEN_T lalen; 2424 register struct servent *sp; 2425 volatile int s; 2426 int i = 0; 2427 EVENT *ev; 2428 int nleft; 2429 struct hostent *hp; 2430 char *ostype = NULL; 2431 char **ha; 2432 char ibuf[MAXNAME + 1]; 2433 static char hbuf[MAXNAME * 2 + 11]; 2434 2435 *may_be_forged = FALSE; 2436 falen = sizeof RealHostAddr; 2437 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 2438 falen <= 0 || RealHostAddr.sa.sa_family == 0) 2439 { 2440 if (i < 0) 2441 { 2442 /* 2443 ** ENOTSOCK is OK: bail on anything else, but reset 2444 ** errno in this case, so a mis-report doesn't 2445 ** happen later. 2446 */ 2447 if (errno != ENOTSOCK) 2448 return NULL; 2449 errno = 0; 2450 } 2451 (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", 2452 RealUserName); 2453 if (tTd(9, 1)) 2454 dprintf("getauthinfo: %s\n", hbuf); 2455 return hbuf; 2456 } 2457 2458 if (RealHostName == NULL) 2459 { 2460 /* translate that to a host name */ 2461 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 2462 if (strlen(RealHostName) > MAXNAME) 2463 RealHostName[MAXNAME] = '\0'; 2464 } 2465 2466 /* cross check RealHostName with forward DNS lookup */ 2467 if (anynet_ntoa(&RealHostAddr)[0] == '[' || 2468 RealHostName[0] == '[') 2469 { 2470 /* 2471 ** address is not a socket or have an 2472 ** IP address with no forward lookup 2473 */ 2474 *may_be_forged = FALSE; 2475 } 2476 else 2477 { 2478 /* try to match the reverse against the forward lookup */ 2479 hp = sm_gethostbyname(RealHostName, 2480 RealHostAddr.sa.sa_family); 2481 2482 if (hp == NULL) 2483 *may_be_forged = TRUE; 2484 else 2485 { 2486 for (ha = hp->h_addr_list; *ha != NULL; ha++) 2487 if (addrcmp(hp, *ha, &RealHostAddr) == 0) 2488 break; 2489 *may_be_forged = *ha == NULL; 2490 } 2491 } 2492 2493 if (TimeOuts.to_ident == 0) 2494 goto noident; 2495 2496 lalen = sizeof la; 2497 switch (RealHostAddr.sa.sa_family) 2498 { 2499 # if NETINET 2500 case AF_INET: 2501 if (getsockname(fd, &la.sa, &lalen) < 0 || 2502 lalen <= 0 || 2503 la.sa.sa_family != AF_INET) 2504 { 2505 /* no ident info */ 2506 goto noident; 2507 } 2508 port = RealHostAddr.sin.sin_port; 2509 2510 /* create ident query */ 2511 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2512 ntohs(RealHostAddr.sin.sin_port), 2513 ntohs(la.sin.sin_port)); 2514 2515 /* create local address */ 2516 la.sin.sin_port = 0; 2517 2518 /* create foreign address */ 2519 # ifdef NO_GETSERVBYNAME 2520 RealHostAddr.sin.sin_port = htons(113); 2521 # else /* NO_GETSERVBYNAME */ 2522 sp = getservbyname("auth", "tcp"); 2523 if (sp != NULL) 2524 RealHostAddr.sin.sin_port = sp->s_port; 2525 else 2526 RealHostAddr.sin.sin_port = htons(113); 2527 break; 2528 # endif /* NO_GETSERVBYNAME */ 2529 # endif /* NETINET */ 2530 2531 # if NETINET6 2532 case AF_INET6: 2533 if (getsockname(fd, &la.sa, &lalen) < 0 || 2534 lalen <= 0 || 2535 la.sa.sa_family != AF_INET6) 2536 { 2537 /* no ident info */ 2538 goto noident; 2539 } 2540 port = RealHostAddr.sin6.sin6_port; 2541 2542 /* create ident query */ 2543 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 2544 ntohs(RealHostAddr.sin6.sin6_port), 2545 ntohs(la.sin6.sin6_port)); 2546 2547 /* create local address */ 2548 la.sin6.sin6_port = 0; 2549 2550 /* create foreign address */ 2551 # ifdef NO_GETSERVBYNAME 2552 RealHostAddr.sin6.sin6_port = htons(113); 2553 # else /* NO_GETSERVBYNAME */ 2554 sp = getservbyname("auth", "tcp"); 2555 if (sp != NULL) 2556 RealHostAddr.sin6.sin6_port = sp->s_port; 2557 else 2558 RealHostAddr.sin6.sin6_port = htons(113); 2559 break; 2560 # endif /* NO_GETSERVBYNAME */ 2561 # endif /* NETINET6 */ 2562 default: 2563 /* no ident info */ 2564 goto noident; 2565 } 2566 2567 s = -1; 2568 if (setjmp(CtxAuthTimeout) != 0) 2569 { 2570 if (s >= 0) 2571 (void) close(s); 2572 goto noident; 2573 } 2574 2575 /* put a timeout around the whole thing */ 2576 ev = setevent(TimeOuts.to_ident, authtimeout, 0); 2577 2578 2579 /* connect to foreign IDENT server using same address as SMTP socket */ 2580 s = socket(la.sa.sa_family, SOCK_STREAM, 0); 2581 if (s < 0) 2582 { 2583 clrevent(ev); 2584 goto noident; 2585 } 2586 if (bind(s, &la.sa, lalen) < 0 || 2587 connect(s, &RealHostAddr.sa, lalen) < 0) 2588 { 2589 goto closeident; 2590 } 2591 2592 if (tTd(9, 10)) 2593 dprintf("getauthinfo: sent %s", ibuf); 2594 2595 /* send query */ 2596 if (write(s, ibuf, strlen(ibuf)) < 0) 2597 goto closeident; 2598 2599 /* get result */ 2600 p = &ibuf[0]; 2601 nleft = sizeof ibuf - 1; 2602 while ((i = read(s, p, nleft)) > 0) 2603 { 2604 p += i; 2605 nleft -= i; 2606 *p = '\0'; 2607 if (strchr(ibuf, '\n') != NULL) 2608 break; 2609 } 2610 (void) close(s); 2611 clrevent(ev); 2612 if (i < 0 || p == &ibuf[0]) 2613 goto noident; 2614 2615 if (*--p == '\n' && *--p == '\r') 2616 p--; 2617 *++p = '\0'; 2618 2619 if (tTd(9, 3)) 2620 dprintf("getauthinfo: got %s\n", ibuf); 2621 2622 /* parse result */ 2623 p = strchr(ibuf, ':'); 2624 if (p == NULL) 2625 { 2626 /* malformed response */ 2627 goto noident; 2628 } 2629 while (isascii(*++p) && isspace(*p)) 2630 continue; 2631 if (strncasecmp(p, "userid", 6) != 0) 2632 { 2633 /* presumably an error string */ 2634 goto noident; 2635 } 2636 p += 6; 2637 while (isascii(*p) && isspace(*p)) 2638 p++; 2639 if (*p++ != ':') 2640 { 2641 /* either useridxx or malformed response */ 2642 goto noident; 2643 } 2644 2645 /* p now points to the OSTYPE field */ 2646 while (isascii(*p) && isspace(*p)) 2647 p++; 2648 ostype = p; 2649 p = strchr(p, ':'); 2650 if (p == NULL) 2651 { 2652 /* malformed response */ 2653 goto noident; 2654 } 2655 else 2656 { 2657 char *charset; 2658 2659 *p = '\0'; 2660 charset = strchr(ostype, ','); 2661 if (charset != NULL) 2662 *charset = '\0'; 2663 } 2664 2665 /* 1413 says don't do this -- but it's broken otherwise */ 2666 while (isascii(*++p) && isspace(*p)) 2667 continue; 2668 2669 /* p now points to the authenticated name -- copy carefully */ 2670 if (strncasecmp(ostype, "other", 5) == 0 && 2671 (ostype[5] == ' ' || ostype[5] == '\0')) 2672 { 2673 snprintf(hbuf, sizeof hbuf, "IDENT:"); 2674 cleanstrcpy(&hbuf[6], p, MAXNAME); 2675 } 2676 else 2677 cleanstrcpy(hbuf, p, MAXNAME); 2678 i = strlen(hbuf); 2679 snprintf(&hbuf[i], sizeof hbuf - i, "@%s", 2680 RealHostName == NULL ? "localhost" : RealHostName); 2681 goto postident; 2682 2683 closeident: 2684 (void) close(s); 2685 clrevent(ev); 2686 2687 noident: 2688 /* put back the original incoming port */ 2689 switch (RealHostAddr.sa.sa_family) 2690 { 2691 # if NETINET 2692 case AF_INET: 2693 if (port > 0) 2694 RealHostAddr.sin.sin_port = port; 2695 break; 2696 # endif /* NETINET */ 2697 2698 # if NETINET6 2699 case AF_INET6: 2700 if (port > 0) 2701 RealHostAddr.sin6.sin6_port = port; 2702 break; 2703 # endif /* NETINET6 */ 2704 } 2705 2706 if (RealHostName == NULL) 2707 { 2708 if (tTd(9, 1)) 2709 dprintf("getauthinfo: NULL\n"); 2710 return NULL; 2711 } 2712 snprintf(hbuf, sizeof hbuf, "%s", RealHostName); 2713 2714 postident: 2715 # if IP_SRCROUTE 2716 # ifndef GET_IPOPT_DST 2717 # define GET_IPOPT_DST(dst) (dst) 2718 # endif /* ! GET_IPOPT_DST */ 2719 /* 2720 ** Extract IP source routing information. 2721 ** 2722 ** Format of output for a connection from site a through b 2723 ** through c to d: 2724 ** loose: @site-c@site-b:site-a 2725 ** strict: !@site-c@site-b:site-a 2726 ** 2727 ** o - pointer within ipopt_list structure. 2728 ** q - pointer within ls/ss rr route data 2729 ** p - pointer to hbuf 2730 */ 2731 2732 if (RealHostAddr.sa.sa_family == AF_INET) 2733 { 2734 SOCKOPT_LEN_T ipoptlen; 2735 int j; 2736 u_char *q; 2737 u_char *o; 2738 int l; 2739 struct IPOPTION ipopt; 2740 2741 ipoptlen = sizeof ipopt; 2742 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 2743 (char *) &ipopt, &ipoptlen) < 0) 2744 goto noipsr; 2745 if (ipoptlen == 0) 2746 goto noipsr; 2747 o = (u_char *) ipopt.IP_LIST; 2748 while (o != NULL && o < (u_char *) &ipopt + ipoptlen) 2749 { 2750 switch (*o) 2751 { 2752 case IPOPT_EOL: 2753 o = NULL; 2754 break; 2755 2756 case IPOPT_NOP: 2757 o++; 2758 break; 2759 2760 case IPOPT_SSRR: 2761 case IPOPT_LSRR: 2762 /* 2763 ** Source routing. 2764 ** o[0] is the option type (loose/strict). 2765 ** o[1] is the length of this option, 2766 ** including option type and 2767 ** length. 2768 ** o[2] is the pointer into the route 2769 ** data. 2770 ** o[3] begins the route data. 2771 */ 2772 2773 p = &hbuf[strlen(hbuf)]; 2774 l = sizeof hbuf - (hbuf - p) - 6; 2775 snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", 2776 *o == IPOPT_SSRR ? "!" : "", 2777 l > 240 ? 120 : l / 2, 2778 inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 2779 i = strlen(p); 2780 p += i; 2781 l -= strlen(p); 2782 2783 j = o[1] / sizeof(struct in_addr) - 1; 2784 2785 /* q skips length and router pointer to data */ 2786 q = &o[3]; 2787 for ( ; j >= 0; j--) 2788 { 2789 struct in_addr addr; 2790 2791 memcpy(&addr, q, sizeof(addr)); 2792 snprintf(p, SPACELEFT(hbuf, p), 2793 "%c%.*s", 2794 j != 0 ? '@' : ':', 2795 l > 240 ? 120 : 2796 j == 0 ? l : l / 2, 2797 inet_ntoa(addr)); 2798 i = strlen(p); 2799 p += i; 2800 l -= i + 1; 2801 q += sizeof(struct in_addr); 2802 } 2803 o += o[1]; 2804 break; 2805 2806 default: 2807 /* Skip over option */ 2808 o += o[1]; 2809 break; 2810 } 2811 } 2812 snprintf(p, SPACELEFT(hbuf, p), "]"); 2813 goto postipsr; 2814 } 2815 2816 noipsr: 2817 # endif /* IP_SRCROUTE */ 2818 if (RealHostName != NULL && RealHostName[0] != '[') 2819 { 2820 p = &hbuf[strlen(hbuf)]; 2821 (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 2822 anynet_ntoa(&RealHostAddr)); 2823 } 2824 if (*may_be_forged) 2825 { 2826 p = &hbuf[strlen(hbuf)]; 2827 (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); 2828 } 2829 2830 # if IP_SRCROUTE 2831 postipsr: 2832 # endif /* IP_SRCROUTE */ 2833 if (tTd(9, 1)) 2834 dprintf("getauthinfo: %s\n", hbuf); 2835 2836 /* put back the original incoming port */ 2837 switch (RealHostAddr.sa.sa_family) 2838 { 2839 # if NETINET 2840 case AF_INET: 2841 if (port > 0) 2842 RealHostAddr.sin.sin_port = port; 2843 break; 2844 # endif /* NETINET */ 2845 2846 # if NETINET6 2847 case AF_INET6: 2848 if (port > 0) 2849 RealHostAddr.sin6.sin6_port = port; 2850 break; 2851 # endif /* NETINET6 */ 2852 } 2853 2854 return hbuf; 2855 } 2856 /* 2857 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 2858 ** 2859 ** Parameters: 2860 ** map -- a pointer to this map. 2861 ** name -- the (presumably unqualified) hostname. 2862 ** av -- unused -- for compatibility with other mapping 2863 ** functions. 2864 ** statp -- an exit status (out parameter) -- set to 2865 ** EX_TEMPFAIL if the name server is unavailable. 2866 ** 2867 ** Returns: 2868 ** The mapping, if found. 2869 ** NULL if no mapping found. 2870 ** 2871 ** Side Effects: 2872 ** Looks up the host specified in hbuf. If it is not 2873 ** the canonical name for that host, return the canonical 2874 ** name (unless MF_MATCHONLY is set, which will cause the 2875 ** status only to be returned). 2876 */ 2877 2878 char * 2879 host_map_lookup(map, name, av, statp) 2880 MAP *map; 2881 char *name; 2882 char **av; 2883 int *statp; 2884 { 2885 register struct hostent *hp; 2886 # if NETINET 2887 struct in_addr in_addr; 2888 # endif /* NETINET */ 2889 # if NETINET6 2890 struct in6_addr in6_addr; 2891 # endif /* NETINET6 */ 2892 char *cp, *ans = NULL; 2893 register STAB *s; 2894 char hbuf[MAXNAME + 1]; 2895 2896 /* 2897 ** See if we have already looked up this name. If so, just 2898 ** return it. 2899 */ 2900 2901 s = stab(name, ST_NAMECANON, ST_ENTER); 2902 if (bitset(NCF_VALID, s->s_namecanon.nc_flags)) 2903 { 2904 if (tTd(9, 1)) 2905 dprintf("host_map_lookup(%s) => CACHE %s\n", 2906 name, 2907 s->s_namecanon.nc_cname == NULL 2908 ? "NULL" 2909 : s->s_namecanon.nc_cname); 2910 errno = s->s_namecanon.nc_errno; 2911 # if NAMED_BIND 2912 h_errno = s->s_namecanon.nc_herrno; 2913 # endif /* NAMED_BIND */ 2914 *statp = s->s_namecanon.nc_stat; 2915 if (*statp == EX_TEMPFAIL) 2916 { 2917 CurEnv->e_status = "4.4.3"; 2918 message("851 %s: Name server timeout", 2919 shortenstring(name, 33)); 2920 } 2921 if (*statp != EX_OK) 2922 return NULL; 2923 if (s->s_namecanon.nc_cname == NULL) 2924 { 2925 syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d", 2926 name, 2927 s->s_namecanon.nc_errno, 2928 s->s_namecanon.nc_herrno); 2929 return NULL; 2930 } 2931 if (bitset(MF_MATCHONLY, map->map_mflags)) 2932 cp = map_rewrite(map, name, strlen(name), NULL); 2933 else 2934 cp = map_rewrite(map, 2935 s->s_namecanon.nc_cname, 2936 strlen(s->s_namecanon.nc_cname), 2937 av); 2938 return cp; 2939 } 2940 2941 /* 2942 ** If we are running without a regular network connection (usually 2943 ** dial-on-demand) and we are just queueing, we want to avoid DNS 2944 ** lookups because those could try to connect to a server. 2945 */ 2946 2947 if (CurEnv->e_sendmode == SM_DEFER && 2948 bitset(MF_DEFER, map->map_mflags)) 2949 { 2950 if (tTd(9, 1)) 2951 dprintf("host_map_lookup(%s) => DEFERRED\n", name); 2952 *statp = EX_TEMPFAIL; 2953 return NULL; 2954 } 2955 2956 /* 2957 ** If first character is a bracket, then it is an address 2958 ** lookup. Address is copied into a temporary buffer to 2959 ** strip the brackets and to preserve name if address is 2960 ** unknown. 2961 */ 2962 2963 if (tTd(9, 1)) 2964 dprintf("host_map_lookup(%s) => ", name); 2965 if (*name != '[') 2966 { 2967 snprintf(hbuf, sizeof hbuf, "%s", name); 2968 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) 2969 ans = hbuf; 2970 } 2971 else 2972 { 2973 if ((cp = strchr(name, ']')) == NULL) 2974 return NULL; 2975 *cp = '\0'; 2976 2977 hp = NULL; 2978 # if NETINET 2979 if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 2980 hp = sm_gethostbyaddr((char *)&in_addr, 2981 INADDRSZ, AF_INET); 2982 # endif /* NETINET */ 2983 # if NETINET6 2984 if (hp == NULL && 2985 inet_pton(AF_INET6, &name[1], &in6_addr) == 1) 2986 hp = sm_gethostbyaddr((char *)&in6_addr, 2987 IN6ADDRSZ, AF_INET6); 2988 # endif /* NETINET6 */ 2989 *cp = ']'; 2990 2991 if (hp != NULL) 2992 { 2993 /* found a match -- copy out */ 2994 ans = denlstring((char *) hp->h_name, TRUE, TRUE); 2995 } 2996 } 2997 2998 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 2999 3000 /* Found an answer */ 3001 if (ans != NULL) 3002 { 3003 s->s_namecanon.nc_stat = *statp = EX_OK; 3004 s->s_namecanon.nc_cname = newstr(ans); 3005 if (bitset(MF_MATCHONLY, map->map_mflags)) 3006 cp = map_rewrite(map, name, strlen(name), NULL); 3007 else 3008 cp = map_rewrite(map, ans, strlen(ans), av); 3009 return cp; 3010 } 3011 3012 3013 /* No match found */ 3014 s->s_namecanon.nc_errno = errno; 3015 # if NAMED_BIND 3016 s->s_namecanon.nc_herrno = h_errno; 3017 if (tTd(9, 1)) 3018 dprintf("FAIL (%d)\n", h_errno); 3019 switch (h_errno) 3020 { 3021 case TRY_AGAIN: 3022 if (UseNameServer) 3023 { 3024 CurEnv->e_status = "4.4.3"; 3025 message("851 %s: Name server timeout", 3026 shortenstring(name, 33)); 3027 } 3028 *statp = EX_TEMPFAIL; 3029 break; 3030 3031 case HOST_NOT_FOUND: 3032 case NO_DATA: 3033 *statp = EX_NOHOST; 3034 break; 3035 3036 case NO_RECOVERY: 3037 *statp = EX_SOFTWARE; 3038 break; 3039 3040 default: 3041 *statp = EX_UNAVAILABLE; 3042 break; 3043 } 3044 # else /* NAMED_BIND */ 3045 if (tTd(9, 1)) 3046 dprintf("FAIL\n"); 3047 *statp = EX_NOHOST; 3048 # endif /* NAMED_BIND */ 3049 s->s_namecanon.nc_stat = *statp; 3050 return NULL; 3051 } 3052 #else /* DAEMON */ 3053 /* code for systems without sophisticated networking */ 3054 3055 /* 3056 ** MYHOSTNAME -- stub version for case of no daemon code. 3057 ** 3058 ** Can't convert to upper case here because might be a UUCP name. 3059 ** 3060 ** Mark, you can change this to be anything you want...... 3061 */ 3062 3063 char ** 3064 myhostname(hostbuf, size) 3065 char hostbuf[]; 3066 int size; 3067 { 3068 register FILE *f; 3069 3070 hostbuf[0] = '\0'; 3071 f = fopen("/usr/include/whoami", "r"); 3072 if (f != NULL) 3073 { 3074 (void) fgets(hostbuf, size, f); 3075 fixcrlf(hostbuf, TRUE); 3076 (void) fclose(f); 3077 } 3078 return NULL; 3079 } 3080 /* 3081 ** GETAUTHINFO -- get the real host name associated with a file descriptor 3082 ** 3083 ** Parameters: 3084 ** fd -- the descriptor 3085 ** may_be_forged -- an outage that is set to TRUE if the 3086 ** forward lookup of RealHostName does not match 3087 ** RealHostAddr; set to FALSE if they do match. 3088 ** 3089 ** Returns: 3090 ** The host name associated with this descriptor, if it can 3091 ** be determined. 3092 ** NULL otherwise. 3093 ** 3094 ** Side Effects: 3095 ** none 3096 */ 3097 3098 char * 3099 getauthinfo(fd, may_be_forged) 3100 int fd; 3101 bool *may_be_forged; 3102 { 3103 *may_be_forged = FALSE; 3104 return NULL; 3105 } 3106 /* 3107 ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3108 ** 3109 ** Parameters: 3110 ** map -- a pointer to the database map. 3111 ** name -- a buffer containing a hostname. 3112 ** avp -- a pointer to a (cf file defined) argument vector. 3113 ** statp -- an exit status (out parameter). 3114 ** 3115 ** Returns: 3116 ** mapped host name 3117 ** FALSE otherwise. 3118 ** 3119 ** Side Effects: 3120 ** Looks up the host specified in name. If it is not 3121 ** the canonical name for that host, replace it with 3122 ** the canonical name. If the name is unknown, or it 3123 ** is already the canonical name, leave it unchanged. 3124 */ 3125 3126 /*ARGSUSED*/ 3127 char * 3128 host_map_lookup(map, name, avp, statp) 3129 MAP *map; 3130 char *name; 3131 char **avp; 3132 char *statp; 3133 { 3134 register struct hostent *hp = NULL; 3135 char *cp; 3136 3137 hp = sm_gethostbyname(name, InetMode); 3138 if (hp == NULL && InetMode != AF_INET) 3139 hp = sm_gethostbyname(name, AF_INET); 3140 if (hp == NULL) 3141 { 3142 # if NAMED_BIND 3143 if (tTd(9, 1)) 3144 dprintf("FAIL (%d)\n", h_errno); 3145 switch (h_errno) 3146 { 3147 case TRY_AGAIN: 3148 if (UseNameServer) 3149 { 3150 CurEnv->e_status = "4.4.3"; 3151 message("851 %s: Name server timeout", 3152 shortenstring(name, 33)); 3153 } 3154 *statp = EX_TEMPFAIL; 3155 break; 3156 3157 case HOST_NOT_FOUND: 3158 case NO_DATA: 3159 *statp = EX_NOHOST; 3160 break; 3161 3162 case NO_RECOVERY: 3163 *statp = EX_SOFTWARE; 3164 break; 3165 3166 default: 3167 *statp = EX_UNAVAILABLE; 3168 break; 3169 } 3170 #else /* NAMED_BIND */ 3171 *statp = EX_NOHOST; 3172 #endif /* NAMED_BIND */ 3173 return NULL; 3174 } 3175 if (bitset(MF_MATCHONLY, map->map_mflags)) 3176 cp = map_rewrite(map, name, strlen(name), NULL); 3177 else 3178 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); 3179 return cp; 3180 } 3181 3182 #endif /* DAEMON */ 3183 /* 3184 ** HOST_MAP_INIT -- initialize host class structures 3185 */ 3186 3187 bool 3188 host_map_init(map, args) 3189 MAP *map; 3190 char *args; 3191 { 3192 register char *p = args; 3193 3194 for (;;) 3195 { 3196 while (isascii(*p) && isspace(*p)) 3197 p++; 3198 if (*p != '-') 3199 break; 3200 switch (*++p) 3201 { 3202 case 'a': 3203 map->map_app = ++p; 3204 break; 3205 3206 case 'T': 3207 map->map_tapp = ++p; 3208 break; 3209 3210 case 'm': 3211 map->map_mflags |= MF_MATCHONLY; 3212 break; 3213 3214 case 't': 3215 map->map_mflags |= MF_NODEFER; 3216 break; 3217 3218 case 'S': /* only for consistency */ 3219 map->map_spacesub = *++p; 3220 break; 3221 3222 case 'D': 3223 map->map_mflags |= MF_DEFER; 3224 break; 3225 } 3226 while (*p != '\0' && !(isascii(*p) && isspace(*p))) 3227 p++; 3228 if (*p != '\0') 3229 *p++ = '\0'; 3230 } 3231 if (map->map_app != NULL) 3232 map->map_app = newstr(map->map_app); 3233 if (map->map_tapp != NULL) 3234 map->map_tapp = newstr(map->map_tapp); 3235 return TRUE; 3236 } 3237 3238 #if NETINET6 3239 /* 3240 ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 3241 ** 3242 ** Parameters: 3243 ** s6a -- a pointer to an in6_addr structure. 3244 ** dst -- buffer to store result in 3245 ** dst_len -- size of dst buffer 3246 ** 3247 ** Returns: 3248 ** A printable version of that structure. 3249 */ 3250 char * 3251 anynet_ntop(s6a, dst, dst_len) 3252 struct in6_addr *s6a; 3253 char *dst; 3254 size_t dst_len; 3255 { 3256 register char *ap; 3257 3258 if (IN6_IS_ADDR_V4MAPPED(s6a)) 3259 ap = (char *) inet_ntop(AF_INET, 3260 &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 3261 dst, dst_len); 3262 else 3263 ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 3264 return ap; 3265 } 3266 #endif /* NETINET6 */ 3267 /* 3268 ** ANYNET_NTOA -- convert a network address to printable form. 3269 ** 3270 ** Parameters: 3271 ** sap -- a pointer to a sockaddr structure. 3272 ** 3273 ** Returns: 3274 ** A printable version of that sockaddr. 3275 */ 3276 3277 #ifdef USE_SOCK_STREAM 3278 3279 # if NETLINK 3280 # include <net/if_dl.h> 3281 # endif /* NETLINK */ 3282 3283 char * 3284 anynet_ntoa(sap) 3285 register SOCKADDR *sap; 3286 { 3287 register char *bp; 3288 register char *ap; 3289 int l; 3290 static char buf[100]; 3291 3292 /* check for null/zero family */ 3293 if (sap == NULL) 3294 return "NULLADDR"; 3295 if (sap->sa.sa_family == 0) 3296 return "0"; 3297 3298 switch (sap->sa.sa_family) 3299 { 3300 # if NETUNIX 3301 case AF_UNIX: 3302 if (sap->sunix.sun_path[0] != '\0') 3303 snprintf(buf, sizeof buf, "[UNIX: %.64s]", 3304 sap->sunix.sun_path); 3305 else 3306 snprintf(buf, sizeof buf, "[UNIX: localhost]"); 3307 return buf; 3308 # endif /* NETUNIX */ 3309 3310 # if NETINET 3311 case AF_INET: 3312 return (char *) inet_ntoa(sap->sin.sin_addr); 3313 # endif /* NETINET */ 3314 3315 # if NETINET6 3316 case AF_INET6: 3317 ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); 3318 if (ap != NULL) 3319 return ap; 3320 break; 3321 # endif /* NETINET6 */ 3322 3323 # if NETLINK 3324 case AF_LINK: 3325 snprintf(buf, sizeof buf, "[LINK: %s]", 3326 link_ntoa((struct sockaddr_dl *) &sap->sa)); 3327 return buf; 3328 # endif /* NETLINK */ 3329 default: 3330 /* this case is needed when nothing is #defined */ 3331 /* in order to keep the switch syntactically correct */ 3332 break; 3333 } 3334 3335 /* unknown family -- just dump bytes */ 3336 (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 3337 bp = &buf[strlen(buf)]; 3338 ap = sap->sa.sa_data; 3339 for (l = sizeof sap->sa.sa_data; --l >= 0; ) 3340 { 3341 (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377); 3342 bp += 3; 3343 } 3344 *--bp = '\0'; 3345 return buf; 3346 } 3347 /* 3348 ** HOSTNAMEBYANYADDR -- return name of host based on address 3349 ** 3350 ** Parameters: 3351 ** sap -- SOCKADDR pointer 3352 ** 3353 ** Returns: 3354 ** text representation of host name. 3355 ** 3356 ** Side Effects: 3357 ** none. 3358 */ 3359 3360 char * 3361 hostnamebyanyaddr(sap) 3362 register SOCKADDR *sap; 3363 { 3364 register struct hostent *hp; 3365 # if NAMED_BIND 3366 int saveretry; 3367 # endif /* NAMED_BIND */ 3368 # if NETINET6 3369 struct in6_addr in6_addr; 3370 # endif /* NETINET6 */ 3371 3372 # if NAMED_BIND 3373 /* shorten name server timeout to avoid higher level timeouts */ 3374 saveretry = _res.retry; 3375 if (_res.retry * _res.retrans > 20) 3376 _res.retry = 20 / _res.retrans; 3377 # endif /* NAMED_BIND */ 3378 3379 switch (sap->sa.sa_family) 3380 { 3381 # if NETINET 3382 case AF_INET: 3383 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 3384 INADDRSZ, 3385 AF_INET); 3386 break; 3387 # endif /* NETINET */ 3388 3389 # if NETINET6 3390 case AF_INET6: 3391 hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 3392 IN6ADDRSZ, 3393 AF_INET6); 3394 break; 3395 # endif /* NETINET6 */ 3396 3397 # if NETISO 3398 case AF_ISO: 3399 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 3400 sizeof sap->siso.siso_addr, 3401 AF_ISO); 3402 break; 3403 # endif /* NETISO */ 3404 3405 # if NETUNIX 3406 case AF_UNIX: 3407 hp = NULL; 3408 break; 3409 # endif /* NETUNIX */ 3410 3411 default: 3412 hp = sm_gethostbyaddr(sap->sa.sa_data, 3413 sizeof sap->sa.sa_data, 3414 sap->sa.sa_family); 3415 break; 3416 } 3417 3418 # if NAMED_BIND 3419 _res.retry = saveretry; 3420 # endif /* NAMED_BIND */ 3421 3422 # if NETINET || NETINET6 3423 if (hp != NULL && hp->h_name[0] != '[' 3424 # if NETINET6 3425 && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 3426 # endif /* NETINET6 */ 3427 # if NETINET 3428 && inet_addr(hp->h_name) == INADDR_NONE 3429 # endif /* NETINET */ 3430 ) 3431 return denlstring((char *) hp->h_name, TRUE, TRUE); 3432 # endif /* NETINET || NETINET6 */ 3433 # if NETUNIX 3434 if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 3435 return "localhost"; 3436 # endif /* NETUNIX */ 3437 { 3438 static char buf[203]; 3439 3440 (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap)); 3441 return buf; 3442 } 3443 } 3444 #endif /* USE_SOCK_STREAM */ 3445