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