17c478bd9Sstevel@tonic-gate /* 2*e9af4bc0SJohn Beck * Copyright (c) 1998-2007, 2009 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 57c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1993 67c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 97c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 107c478bd9Sstevel@tonic-gate * the sendmail distribution. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate */ 137c478bd9Sstevel@tonic-gate 147c478bd9Sstevel@tonic-gate #include <sendmail.h> 15058561cbSjbeck #include "map.h" 167c478bd9Sstevel@tonic-gate 17*e9af4bc0SJohn Beck SM_RCSID("@(#)$Id: daemon.c,v 8.683 2009/12/18 01:12:40 ca Exp $") 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 207c478bd9Sstevel@tonic-gate # define USE_SOCK_STREAM 1 217c478bd9Sstevel@tonic-gate #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate #if defined(USE_SOCK_STREAM) 247c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 257c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 267c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 277c478bd9Sstevel@tonic-gate # if NAMED_BIND 287c478bd9Sstevel@tonic-gate # ifndef NO_DATA 297c478bd9Sstevel@tonic-gate # define NO_DATA NO_ADDRESS 307c478bd9Sstevel@tonic-gate # endif /* ! NO_DATA */ 317c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 327c478bd9Sstevel@tonic-gate #endif /* defined(USE_SOCK_STREAM) */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #if STARTTLS 357c478bd9Sstevel@tonic-gate # include <openssl/rand.h> 367c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 377c478bd9Sstevel@tonic-gate 3849218d4fSjbeck #include <sm/time.h> 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #if IP_SRCROUTE && NETINET 417c478bd9Sstevel@tonic-gate # include <netinet/in_systm.h> 427c478bd9Sstevel@tonic-gate # include <netinet/ip.h> 437c478bd9Sstevel@tonic-gate # if HAS_IN_H 447c478bd9Sstevel@tonic-gate # include <netinet/in.h> 457c478bd9Sstevel@tonic-gate # ifndef IPOPTION 467c478bd9Sstevel@tonic-gate # define IPOPTION ip_opts 477c478bd9Sstevel@tonic-gate # define IP_LIST ip_opts 487c478bd9Sstevel@tonic-gate # define IP_DST ip_dst 497c478bd9Sstevel@tonic-gate # endif /* ! IPOPTION */ 507c478bd9Sstevel@tonic-gate # else /* HAS_IN_H */ 517c478bd9Sstevel@tonic-gate # include <netinet/ip_var.h> 527c478bd9Sstevel@tonic-gate # ifndef IPOPTION 537c478bd9Sstevel@tonic-gate # define IPOPTION ipoption 547c478bd9Sstevel@tonic-gate # define IP_LIST ipopt_list 557c478bd9Sstevel@tonic-gate # define IP_DST ipopt_dst 567c478bd9Sstevel@tonic-gate # endif /* ! IPOPTION */ 577c478bd9Sstevel@tonic-gate # endif /* HAS_IN_H */ 587c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE && NETINET */ 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate #include <sm/fdset.h> 617c478bd9Sstevel@tonic-gate 62058561cbSjbeck #define DAEMON_C 1 63058561cbSjbeck #include <daemon.h> 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static void connecttimeout __P((int)); 667c478bd9Sstevel@tonic-gate static int opendaemonsocket __P((DAEMON_T *, bool)); 677c478bd9Sstevel@tonic-gate static unsigned short setupdaemon __P((SOCKADDR *)); 687c478bd9Sstevel@tonic-gate static void getrequests_checkdiskspace __P((ENVELOPE *e)); 697c478bd9Sstevel@tonic-gate static void setsockaddroptions __P((char *, DAEMON_T *)); 707c478bd9Sstevel@tonic-gate static void printdaemonflags __P((DAEMON_T *)); 717c478bd9Sstevel@tonic-gate static int addr_family __P((char *)); 727c478bd9Sstevel@tonic-gate static int addrcmp __P((struct hostent *, char *, SOCKADDR *)); 737c478bd9Sstevel@tonic-gate static void authtimeout __P((int)); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate /* 767c478bd9Sstevel@tonic-gate ** DAEMON.C -- routines to use when running as a daemon. 777c478bd9Sstevel@tonic-gate ** 787c478bd9Sstevel@tonic-gate ** This entire file is highly dependent on the 4.2 BSD 797c478bd9Sstevel@tonic-gate ** interprocess communication primitives. No attempt has 807c478bd9Sstevel@tonic-gate ** been made to make this file portable to Version 7, 817c478bd9Sstevel@tonic-gate ** Version 6, MPX files, etc. If you should try such a 827c478bd9Sstevel@tonic-gate ** thing yourself, I recommend chucking the entire file 837c478bd9Sstevel@tonic-gate ** and starting from scratch. Basic semantics are: 847c478bd9Sstevel@tonic-gate ** 857c478bd9Sstevel@tonic-gate ** getrequests(e) 867c478bd9Sstevel@tonic-gate ** Opens a port and initiates a connection. 877c478bd9Sstevel@tonic-gate ** Returns in a child. Must set InChannel and 887c478bd9Sstevel@tonic-gate ** OutChannel appropriately. 897c478bd9Sstevel@tonic-gate ** clrdaemon() 907c478bd9Sstevel@tonic-gate ** Close any open files associated with getting 917c478bd9Sstevel@tonic-gate ** the connection; this is used when running the queue, 927c478bd9Sstevel@tonic-gate ** etc., to avoid having extra file descriptors during 937c478bd9Sstevel@tonic-gate ** the queue run and to avoid confusing the network 947c478bd9Sstevel@tonic-gate ** code (if it cares). 957c478bd9Sstevel@tonic-gate ** makeconnection(host, port, mci, e, enough) 967c478bd9Sstevel@tonic-gate ** Make a connection to the named host on the given 977c478bd9Sstevel@tonic-gate ** port. Returns zero on success, else an exit status 987c478bd9Sstevel@tonic-gate ** describing the error. 997c478bd9Sstevel@tonic-gate ** host_map_lookup(map, hbuf, avp, pstat) 1007c478bd9Sstevel@tonic-gate ** Convert the entry in hbuf into a canonical form. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate static int NDaemons = 0; /* actual number of daemons */ 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static time_t NextDiskSpaceCheck = 0; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate ** GETREQUESTS -- open mail IPC port and get requests. 1097c478bd9Sstevel@tonic-gate ** 1107c478bd9Sstevel@tonic-gate ** Parameters: 1117c478bd9Sstevel@tonic-gate ** e -- the current envelope. 1127c478bd9Sstevel@tonic-gate ** 1137c478bd9Sstevel@tonic-gate ** Returns: 1147c478bd9Sstevel@tonic-gate ** pointer to flags. 1157c478bd9Sstevel@tonic-gate ** 1167c478bd9Sstevel@tonic-gate ** Side Effects: 1177c478bd9Sstevel@tonic-gate ** Waits until some interesting activity occurs. When 1187c478bd9Sstevel@tonic-gate ** it does, a child is created to process it, and the 1197c478bd9Sstevel@tonic-gate ** parent waits for completion. Return from this 1207c478bd9Sstevel@tonic-gate ** routine is always in the child. The file pointers 1217c478bd9Sstevel@tonic-gate ** "InChannel" and "OutChannel" should be set to point 1227c478bd9Sstevel@tonic-gate ** to the communication channel. 1237c478bd9Sstevel@tonic-gate ** May restart persistent queue runners if they have ended 1247c478bd9Sstevel@tonic-gate ** for some reason. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate BITMAP256 * 1287c478bd9Sstevel@tonic-gate getrequests(e) 1297c478bd9Sstevel@tonic-gate ENVELOPE *e; 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate int t; 1327c478bd9Sstevel@tonic-gate int idx, curdaemon = -1; 1337c478bd9Sstevel@tonic-gate int i, olddaemon = 0; 1347c478bd9Sstevel@tonic-gate #if XDEBUG 1357c478bd9Sstevel@tonic-gate bool j_has_dot; 1367c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 1377c478bd9Sstevel@tonic-gate char status[MAXLINE]; 1387c478bd9Sstevel@tonic-gate SOCKADDR sa; 139058561cbSjbeck SOCKADDR_LEN_T len = sizeof(sa); 1407c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 1417c478bd9Sstevel@tonic-gate time_t lastrun; 1427c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 1437c478bd9Sstevel@tonic-gate # if NETUNIX 1447c478bd9Sstevel@tonic-gate extern int ControlSocket; 1457c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1467c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* initialize data for function that generates queue ids */ 1507c478bd9Sstevel@tonic-gate init_qid_alg(); 1517c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 1547c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime = true; 1557c478bd9Sstevel@tonic-gate Daemons[idx].d_refuse_connections_until = (time_t) 0; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate ** Try to actually open the connection. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (tTd(15, 1)) 1637c478bd9Sstevel@tonic-gate { 1647c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 1657c478bd9Sstevel@tonic-gate { 1667c478bd9Sstevel@tonic-gate sm_dprintf("getrequests: daemon %s: port %d\n", 1677c478bd9Sstevel@tonic-gate Daemons[idx].d_name, 1687c478bd9Sstevel@tonic-gate ntohs(Daemons[idx].d_port)); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* get a socket for the SMTP connection */ 1737c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 1747c478bd9Sstevel@tonic-gate Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], true); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate if (opencontrolsocket() < 0) 1777c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 1787c478bd9Sstevel@tonic-gate "daemon could not open control socket %s: %s", 1797c478bd9Sstevel@tonic-gate ControlSocketName, sm_errstring(errno)); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* If there are any queue runners released reapchild() co-ord's */ 1827c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, reapchild); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* write the pid to file, command line args to syslog */ 1857c478bd9Sstevel@tonic-gate log_sendmail_pid(e); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate #if XDEBUG 1887c478bd9Sstevel@tonic-gate { 1897c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; 1907c478bd9Sstevel@tonic-gate 191058561cbSjbeck expand("\201j", jbuf, sizeof(jbuf), e); 1927c478bd9Sstevel@tonic-gate j_has_dot = strchr(jbuf, '.') != NULL; 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* Add parent process as first item */ 1977c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1, NULL); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (tTd(15, 1)) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 202*e9af4bc0SJohn Beck sm_dprintf("getrequests: daemon %s: socket %d\n", 2037c478bd9Sstevel@tonic-gate Daemons[idx].d_name, 2047c478bd9Sstevel@tonic-gate Daemons[idx].d_socket); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate for (;;) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate register pid_t pid; 2107c478bd9Sstevel@tonic-gate auto SOCKADDR_LEN_T lotherend; 2117c478bd9Sstevel@tonic-gate bool timedout = false; 2127c478bd9Sstevel@tonic-gate bool control = false; 2137c478bd9Sstevel@tonic-gate int save_errno; 2147c478bd9Sstevel@tonic-gate int pipefd[2]; 2157c478bd9Sstevel@tonic-gate time_t now; 2167c478bd9Sstevel@tonic-gate #if STARTTLS 2177c478bd9Sstevel@tonic-gate long seed; 2187c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* see if we are rejecting connections */ 2217c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGALRM); 2227c478bd9Sstevel@tonic-gate CHECK_RESTART; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate ** XXX do this call outside the loop? 2287c478bd9Sstevel@tonic-gate ** no: refuse_connections may sleep(). 2297c478bd9Sstevel@tonic-gate */ 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate now = curtime(); 2327c478bd9Sstevel@tonic-gate if (now < Daemons[idx].d_refuse_connections_until) 2337c478bd9Sstevel@tonic-gate continue; 2347c478bd9Sstevel@tonic-gate if (bitnset(D_DISABLE, Daemons[idx].d_flags)) 2357c478bd9Sstevel@tonic-gate continue; 236058561cbSjbeck if (refuseconnections(e, idx, curdaemon == idx)) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate /* close socket so peer fails quickly */ 2417c478bd9Sstevel@tonic-gate (void) close(Daemons[idx].d_socket); 2427c478bd9Sstevel@tonic-gate Daemons[idx].d_socket = -1; 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* refuse connections for next 15 seconds */ 2467c478bd9Sstevel@tonic-gate Daemons[idx].d_refuse_connections_until = now + 15; 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate else if (Daemons[idx].d_socket < 0 || 2497c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime) 2507c478bd9Sstevel@tonic-gate { 2517c478bd9Sstevel@tonic-gate if (!Daemons[idx].d_firsttime && LogLevel > 8) 2527c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 2537c478bd9Sstevel@tonic-gate "accepting connections again for daemon %s", 2547c478bd9Sstevel@tonic-gate Daemons[idx].d_name); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* arrange to (re)open the socket if needed */ 2577c478bd9Sstevel@tonic-gate (void) opendaemonsocket(&Daemons[idx], false); 2587c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime = false; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* May have been sleeping above, check again */ 2637c478bd9Sstevel@tonic-gate CHECK_RESTART; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate getrequests_checkdiskspace(e); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate #if XDEBUG 2687c478bd9Sstevel@tonic-gate /* check for disaster */ 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; 2717c478bd9Sstevel@tonic-gate 272058561cbSjbeck expand("\201j", jbuf, sizeof(jbuf), e); 2737c478bd9Sstevel@tonic-gate if (!wordinclass(jbuf, 'w')) 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate dumpstate("daemon lost $j"); 2767c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 2777c478bd9Sstevel@tonic-gate "daemon process doesn't have $j in $=w; see syslog"); 2787c478bd9Sstevel@tonic-gate abort(); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate else if (j_has_dot && strchr(jbuf, '.') == NULL) 2817c478bd9Sstevel@tonic-gate { 2827c478bd9Sstevel@tonic-gate dumpstate("daemon $j lost dot"); 2837c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 2847c478bd9Sstevel@tonic-gate "daemon process $j lost dot; see syslog"); 2857c478bd9Sstevel@tonic-gate abort(); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate #if 0 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 2937c478bd9Sstevel@tonic-gate ** fix the SVr4 problem. But it seems to have gone away, 2947c478bd9Sstevel@tonic-gate ** so is it worth doing this? 2957c478bd9Sstevel@tonic-gate */ 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (DaemonSocket >= 0 && 2987c478bd9Sstevel@tonic-gate SetNonBlocking(DaemonSocket, false) < 0) 2997c478bd9Sstevel@tonic-gate log an error here; 3007c478bd9Sstevel@tonic-gate #endif /* 0 */ 3017c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate for (;;) 3047c478bd9Sstevel@tonic-gate { 3057c478bd9Sstevel@tonic-gate bool setproc = false; 3067c478bd9Sstevel@tonic-gate int highest = -1; 3077c478bd9Sstevel@tonic-gate fd_set readfds; 3087c478bd9Sstevel@tonic-gate struct timeval timeout; 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate CHECK_RESTART; 3117c478bd9Sstevel@tonic-gate FD_ZERO(&readfds); 3127c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate /* wait for a connection */ 3157c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 3167c478bd9Sstevel@tonic-gate { 3177c478bd9Sstevel@tonic-gate if (!setproc && 3187c478bd9Sstevel@tonic-gate !bitnset(D_ETRNONLY, 3197c478bd9Sstevel@tonic-gate Daemons[idx].d_flags)) 3207c478bd9Sstevel@tonic-gate { 3217c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, 3227c478bd9Sstevel@tonic-gate "accepting connections"); 3237c478bd9Sstevel@tonic-gate setproc = true; 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket > highest) 3267c478bd9Sstevel@tonic-gate highest = Daemons[idx].d_socket; 3277c478bd9Sstevel@tonic-gate SM_FD_SET(Daemons[idx].d_socket, 3287c478bd9Sstevel@tonic-gate &readfds); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate #if NETUNIX 3337c478bd9Sstevel@tonic-gate if (ControlSocket >= 0) 3347c478bd9Sstevel@tonic-gate { 3357c478bd9Sstevel@tonic-gate if (ControlSocket > highest) 3367c478bd9Sstevel@tonic-gate highest = ControlSocket; 3377c478bd9Sstevel@tonic-gate SM_FD_SET(ControlSocket, &readfds); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate timeout.tv_sec = 5; 3427c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate t = select(highest + 1, FDSET_CAST &readfds, 3457c478bd9Sstevel@tonic-gate NULL, NULL, &timeout); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* Did someone signal while waiting? */ 3487c478bd9Sstevel@tonic-gate CHECK_RESTART; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate curdaemon = -1; 3517c478bd9Sstevel@tonic-gate if (doqueuerun()) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate (void) runqueue(true, false, false, false); 3547c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 3557c478bd9Sstevel@tonic-gate lastrun = now; 3567c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 359445f2479Sjbeck else if (CheckQueueRunners > 0 && QueueIntvl > 0 && 360445f2479Sjbeck lastrun + QueueIntvl + CheckQueueRunners < now) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate ** set lastrun unconditionally to avoid 3657c478bd9Sstevel@tonic-gate ** calling checkqueuerunner() all the time. 3667c478bd9Sstevel@tonic-gate ** That's also why we currently ignore the 3677c478bd9Sstevel@tonic-gate ** result of the function call. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate (void) checkqueuerunner(); 3717c478bd9Sstevel@tonic-gate lastrun = now; 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate if (t <= 0) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate timedout = true; 3787c478bd9Sstevel@tonic-gate break; 3797c478bd9Sstevel@tonic-gate } 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate control = false; 3827c478bd9Sstevel@tonic-gate errno = 0; 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate /* look "round-robin" for an active socket */ 3857c478bd9Sstevel@tonic-gate if ((idx = olddaemon + 1) >= NDaemons) 3867c478bd9Sstevel@tonic-gate idx = 0; 3877c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0 && 3907c478bd9Sstevel@tonic-gate SM_FD_ISSET(Daemons[idx].d_socket, 3917c478bd9Sstevel@tonic-gate &readfds)) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate lotherend = Daemons[idx].d_socksize; 3947c478bd9Sstevel@tonic-gate memset(&RealHostAddr, '\0', 395058561cbSjbeck sizeof(RealHostAddr)); 3967c478bd9Sstevel@tonic-gate t = accept(Daemons[idx].d_socket, 3977c478bd9Sstevel@tonic-gate (struct sockaddr *)&RealHostAddr, 3987c478bd9Sstevel@tonic-gate &lotherend); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate ** If remote side closes before 4027c478bd9Sstevel@tonic-gate ** accept() finishes, sockaddr 4037c478bd9Sstevel@tonic-gate ** might not be fully filled in. 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate if (t >= 0 && 4077c478bd9Sstevel@tonic-gate (lotherend == 0 || 4087c478bd9Sstevel@tonic-gate # ifdef BSD4_4_SOCKADDR 4097c478bd9Sstevel@tonic-gate RealHostAddr.sa.sa_len == 0 || 4107c478bd9Sstevel@tonic-gate # endif /* BSD4_4_SOCKADDR */ 4117c478bd9Sstevel@tonic-gate RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate (void) close(t); 4147c478bd9Sstevel@tonic-gate t = -1; 4157c478bd9Sstevel@tonic-gate errno = EINVAL; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate olddaemon = curdaemon = idx; 4187c478bd9Sstevel@tonic-gate break; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate if (++idx >= NDaemons) 4217c478bd9Sstevel@tonic-gate idx = 0; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate #if NETUNIX 4247c478bd9Sstevel@tonic-gate if (curdaemon == -1 && ControlSocket >= 0 && 4257c478bd9Sstevel@tonic-gate SM_FD_ISSET(ControlSocket, &readfds)) 4267c478bd9Sstevel@tonic-gate { 4277c478bd9Sstevel@tonic-gate struct sockaddr_un sa_un; 4287c478bd9Sstevel@tonic-gate 429058561cbSjbeck lotherend = sizeof(sa_un); 430058561cbSjbeck memset(&sa_un, '\0', sizeof(sa_un)); 4317c478bd9Sstevel@tonic-gate t = accept(ControlSocket, 4327c478bd9Sstevel@tonic-gate (struct sockaddr *)&sa_un, 4337c478bd9Sstevel@tonic-gate &lotherend); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate /* 4367c478bd9Sstevel@tonic-gate ** If remote side closes before 4377c478bd9Sstevel@tonic-gate ** accept() finishes, sockaddr 4387c478bd9Sstevel@tonic-gate ** might not be fully filled in. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate if (t >= 0 && 4427c478bd9Sstevel@tonic-gate (lotherend == 0 || 4437c478bd9Sstevel@tonic-gate # ifdef BSD4_4_SOCKADDR 4447c478bd9Sstevel@tonic-gate sa_un.sun_len == 0 || 4457c478bd9Sstevel@tonic-gate # endif /* BSD4_4_SOCKADDR */ 4467c478bd9Sstevel@tonic-gate sa_un.sun_family != AF_UNIX)) 4477c478bd9Sstevel@tonic-gate { 4487c478bd9Sstevel@tonic-gate (void) close(t); 4497c478bd9Sstevel@tonic-gate t = -1; 4507c478bd9Sstevel@tonic-gate errno = EINVAL; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate if (t >= 0) 4537c478bd9Sstevel@tonic-gate control = true; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate #else /* NETUNIX */ 4567c478bd9Sstevel@tonic-gate if (curdaemon == -1) 4577c478bd9Sstevel@tonic-gate { 4587c478bd9Sstevel@tonic-gate /* No daemon to service */ 4597c478bd9Sstevel@tonic-gate continue; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 4627c478bd9Sstevel@tonic-gate if (t >= 0 || errno != EINTR) 4637c478bd9Sstevel@tonic-gate break; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate if (timedout) 4667c478bd9Sstevel@tonic-gate { 4677c478bd9Sstevel@tonic-gate timedout = false; 4687c478bd9Sstevel@tonic-gate continue; 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate save_errno = errno; 4717c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGALRM); 4727c478bd9Sstevel@tonic-gate if (t < 0) 4737c478bd9Sstevel@tonic-gate { 4747c478bd9Sstevel@tonic-gate errno = save_errno; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* let's ignore these temporary errors */ 4777c478bd9Sstevel@tonic-gate if (save_errno == EINTR 4787c478bd9Sstevel@tonic-gate #ifdef EAGAIN 4797c478bd9Sstevel@tonic-gate || save_errno == EAGAIN 4807c478bd9Sstevel@tonic-gate #endif /* EAGAIN */ 4817c478bd9Sstevel@tonic-gate #ifdef ECONNABORTED 4827c478bd9Sstevel@tonic-gate || save_errno == ECONNABORTED 4837c478bd9Sstevel@tonic-gate #endif /* ECONNABORTED */ 4847c478bd9Sstevel@tonic-gate #ifdef EWOULDBLOCK 4857c478bd9Sstevel@tonic-gate || save_errno == EWOULDBLOCK 4867c478bd9Sstevel@tonic-gate #endif /* EWOULDBLOCK */ 4877c478bd9Sstevel@tonic-gate ) 4887c478bd9Sstevel@tonic-gate continue; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate syserr("getrequests: accept"); 4917c478bd9Sstevel@tonic-gate 4923ee0e492Sjbeck if (curdaemon >= 0) 4933ee0e492Sjbeck { 4943ee0e492Sjbeck /* arrange to re-open socket next time around */ 4953ee0e492Sjbeck (void) close(Daemons[curdaemon].d_socket); 4963ee0e492Sjbeck Daemons[curdaemon].d_socket = -1; 4977c478bd9Sstevel@tonic-gate #if SO_REUSEADDR_IS_BROKEN 4983ee0e492Sjbeck /* 4993ee0e492Sjbeck ** Give time for bound socket to be released. 5003ee0e492Sjbeck ** This creates a denial-of-service if you can 5013ee0e492Sjbeck ** force accept() to fail on affected systems. 5023ee0e492Sjbeck */ 5037c478bd9Sstevel@tonic-gate 5043ee0e492Sjbeck Daemons[curdaemon].d_refuse_connections_until = 5053ee0e492Sjbeck curtime() + 15; 5067c478bd9Sstevel@tonic-gate #endif /* SO_REUSEADDR_IS_BROKEN */ 5073ee0e492Sjbeck } 5087c478bd9Sstevel@tonic-gate continue; 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate if (!control) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate /* set some daemon related macros */ 5147c478bd9Sstevel@tonic-gate switch (Daemons[curdaemon].d_addr.sa.sa_family) 5157c478bd9Sstevel@tonic-gate { 5167c478bd9Sstevel@tonic-gate case AF_UNSPEC: 5177c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5187c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "unspec"); 5197c478bd9Sstevel@tonic-gate break; 5207c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 5217c478bd9Sstevel@tonic-gate # if NETUNIX 5227c478bd9Sstevel@tonic-gate case AF_UNIX: 5237c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5247c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "local"); 5257c478bd9Sstevel@tonic-gate break; 5267c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 5277c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 5287c478bd9Sstevel@tonic-gate #if NETINET 5297c478bd9Sstevel@tonic-gate case AF_INET: 5307c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5317c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "inet"); 5327c478bd9Sstevel@tonic-gate break; 5337c478bd9Sstevel@tonic-gate #endif /* NETINET */ 5347c478bd9Sstevel@tonic-gate #if NETINET6 5357c478bd9Sstevel@tonic-gate case AF_INET6: 5367c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5377c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "inet6"); 5387c478bd9Sstevel@tonic-gate break; 5397c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 5407c478bd9Sstevel@tonic-gate #if NETISO 5417c478bd9Sstevel@tonic-gate case AF_ISO: 5427c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5437c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "iso"); 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate #endif /* NETISO */ 5467c478bd9Sstevel@tonic-gate #if NETNS 5477c478bd9Sstevel@tonic-gate case AF_NS: 5487c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5497c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "ns"); 5507c478bd9Sstevel@tonic-gate break; 5517c478bd9Sstevel@tonic-gate #endif /* NETNS */ 5527c478bd9Sstevel@tonic-gate #if NETX25 5537c478bd9Sstevel@tonic-gate case AF_CCITT: 5547c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5557c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "x.25"); 5567c478bd9Sstevel@tonic-gate break; 5577c478bd9Sstevel@tonic-gate #endif /* NETX25 */ 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5607c478bd9Sstevel@tonic-gate macid("{daemon_name}"), 5617c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_name); 5627c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_mflags != NULL) 5637c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5647c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), 5657c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_mflags); 5667c478bd9Sstevel@tonic-gate else 5677c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 5687c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), ""); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate ** If connection rate is exceeded here, connection shall be 5737c478bd9Sstevel@tonic-gate ** refused later by a new call after fork() by the 5747c478bd9Sstevel@tonic-gate ** validate_connection() function. Closing the connection 5757c478bd9Sstevel@tonic-gate ** at this point violates RFC 2821. 5767c478bd9Sstevel@tonic-gate ** Do NOT remove this call, its side effects are needed. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate connection_rate_check(&RealHostAddr, NULL); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 5827c478bd9Sstevel@tonic-gate ** Create a subprocess to process the mail. 5837c478bd9Sstevel@tonic-gate */ 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 5867c478bd9Sstevel@tonic-gate sm_dprintf("getrequests: forking (fd = %d)\n", t); 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate /* 5897c478bd9Sstevel@tonic-gate ** Advance state of PRNG. 5907c478bd9Sstevel@tonic-gate ** This is necessary because otherwise all child processes 5917c478bd9Sstevel@tonic-gate ** will produce the same PRN sequence and hence the selection 5927c478bd9Sstevel@tonic-gate ** of a queue directory (and other things, e.g., MX selection) 5937c478bd9Sstevel@tonic-gate ** are not "really" random. 5947c478bd9Sstevel@tonic-gate */ 5957c478bd9Sstevel@tonic-gate #if STARTTLS 5967c478bd9Sstevel@tonic-gate /* XXX get some better "random" data? */ 5977c478bd9Sstevel@tonic-gate seed = get_random(); 5987c478bd9Sstevel@tonic-gate RAND_seed((void *) &NextDiskSpaceCheck, 599058561cbSjbeck sizeof(NextDiskSpaceCheck)); 600058561cbSjbeck RAND_seed((void *) &now, sizeof(now)); 601058561cbSjbeck RAND_seed((void *) &seed, sizeof(seed)); 6027c478bd9Sstevel@tonic-gate #else /* STARTTLS */ 6037c478bd9Sstevel@tonic-gate (void) get_random(); 6047c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate #if NAMED_BIND 6077c478bd9Sstevel@tonic-gate /* 6087c478bd9Sstevel@tonic-gate ** Update MX records for FallbackMX. 6097c478bd9Sstevel@tonic-gate ** Let's hope this is fast otherwise we screw up the 6107c478bd9Sstevel@tonic-gate ** response time. 6117c478bd9Sstevel@tonic-gate */ 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate if (FallbackMX != NULL) 6147c478bd9Sstevel@tonic-gate (void) getfallbackmxrr(FallbackMX); 6157c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate if (tTd(93, 100)) 6187c478bd9Sstevel@tonic-gate { 6197c478bd9Sstevel@tonic-gate /* don't fork, handle connection in this process */ 6207c478bd9Sstevel@tonic-gate pid = 0; 6217c478bd9Sstevel@tonic-gate pipefd[0] = pipefd[1] = -1; 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate else 6247c478bd9Sstevel@tonic-gate { 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate ** Create a pipe to keep the child from writing to 6277c478bd9Sstevel@tonic-gate ** the socket until after the parent has closed 6287c478bd9Sstevel@tonic-gate ** it. Otherwise the parent may hang if the child 6297c478bd9Sstevel@tonic-gate ** has closed it first. 6307c478bd9Sstevel@tonic-gate */ 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate if (pipe(pipefd) < 0) 6337c478bd9Sstevel@tonic-gate pipefd[0] = pipefd[1] = -1; 6347c478bd9Sstevel@tonic-gate 6357c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGCHLD); 6367c478bd9Sstevel@tonic-gate pid = fork(); 6377c478bd9Sstevel@tonic-gate if (pid < 0) 6387c478bd9Sstevel@tonic-gate { 6397c478bd9Sstevel@tonic-gate syserr("daemon: cannot fork"); 6407c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 6417c478bd9Sstevel@tonic-gate { 6427c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 6437c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 6467c478bd9Sstevel@tonic-gate (void) sleep(10); 6477c478bd9Sstevel@tonic-gate (void) close(t); 6487c478bd9Sstevel@tonic-gate continue; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate if (pid == 0) 6537c478bd9Sstevel@tonic-gate { 6547c478bd9Sstevel@tonic-gate char *p; 6557c478bd9Sstevel@tonic-gate SM_FILE_T *inchannel, *outchannel = NULL; 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate ** CHILD -- return to caller. 6597c478bd9Sstevel@tonic-gate ** Collect verified idea of sending host. 6607c478bd9Sstevel@tonic-gate ** Verify calling user id if possible here. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* Reset global flags */ 6647c478bd9Sstevel@tonic-gate RestartRequest = NULL; 6657c478bd9Sstevel@tonic-gate RestartWorkGroup = false; 6667c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 6677c478bd9Sstevel@tonic-gate PendingSignal = 0; 6687c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 6697c478bd9Sstevel@tonic-gate close_sendmail_pid(); 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 6727c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 6737c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, SIG_DFL); 6747c478bd9Sstevel@tonic-gate (void) sm_signal(SIGHUP, SIG_DFL); 6757c478bd9Sstevel@tonic-gate (void) sm_signal(SIGTERM, intsig); 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* turn on profiling */ 6787c478bd9Sstevel@tonic-gate /* SM_PROF(0); */ 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate ** Initialize exception stack and default exception 6827c478bd9Sstevel@tonic-gate ** handler for child process. 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate sm_exc_newthread(fatal_error); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate if (!control) 6887c478bd9Sstevel@tonic-gate { 6897c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 6907c478bd9Sstevel@tonic-gate macid("{daemon_addr}"), 6917c478bd9Sstevel@tonic-gate anynet_ntoa(&Daemons[curdaemon].d_addr)); 692058561cbSjbeck (void) sm_snprintf(status, sizeof(status), "%d", 6937c478bd9Sstevel@tonic-gate ntohs(Daemons[curdaemon].d_port)); 6947c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 6957c478bd9Sstevel@tonic-gate macid("{daemon_port}"), status); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 6997c478bd9Sstevel@tonic-gate { 7007c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 7017c478bd9Sstevel@tonic-gate (void) close(Daemons[idx].d_socket); 7027c478bd9Sstevel@tonic-gate Daemons[idx].d_socket = -1; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate clrcontrol(); 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* Avoid SMTP daemon actions if control command */ 7077c478bd9Sstevel@tonic-gate if (control) 7087c478bd9Sstevel@tonic-gate { 7097c478bd9Sstevel@tonic-gate /* Add control socket process */ 7107c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, 7117c478bd9Sstevel@tonic-gate "console socket child", 7127c478bd9Sstevel@tonic-gate PROC_CONTROL_CHILD, 0, -1, NULL); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate else 7157c478bd9Sstevel@tonic-gate { 7167c478bd9Sstevel@tonic-gate proc_list_clear(); 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* clean up background delivery children */ 7197c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, reapchild); 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate /* Add parent process as first child item */ 7227c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, "daemon child", 7237c478bd9Sstevel@tonic-gate PROC_DAEMON_CHILD, 0, -1, NULL); 7247c478bd9Sstevel@tonic-gate /* don't schedule queue runs if ETRN */ 7257c478bd9Sstevel@tonic-gate QueueIntvl = 0; 726058561cbSjbeck 727058561cbSjbeck /* 728058561cbSjbeck ** Hack: override global variables if 729058561cbSjbeck ** the corresponding DaemonPortOption 730058561cbSjbeck ** is set. 731058561cbSjbeck */ 7327c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 7337c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_supersafe != 734058561cbSjbeck DPO_NOTSET) 735058561cbSjbeck SuperSafe = Daemons[curdaemon]. 736058561cbSjbeck d_supersafe; 7377c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 7387c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_dm != DM_NOTSET) 7397c478bd9Sstevel@tonic-gate set_delivery_mode( 7407c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_dm, e); 741058561cbSjbeck 742058561cbSjbeck if (Daemons[curdaemon].d_refuseLA != 743058561cbSjbeck DPO_NOTSET) 744058561cbSjbeck RefuseLA = Daemons[curdaemon]. 745058561cbSjbeck d_refuseLA; 746058561cbSjbeck if (Daemons[curdaemon].d_queueLA != DPO_NOTSET) 747058561cbSjbeck QueueLA = Daemons[curdaemon].d_queueLA; 748058561cbSjbeck if (Daemons[curdaemon].d_delayLA != DPO_NOTSET) 749058561cbSjbeck DelayLA = Daemons[curdaemon].d_delayLA; 750058561cbSjbeck if (Daemons[curdaemon].d_maxchildren != 751058561cbSjbeck DPO_NOTSET) 752058561cbSjbeck MaxChildren = Daemons[curdaemon]. 753058561cbSjbeck d_maxchildren; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, "startup with %s", 7567c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 7607c478bd9Sstevel@tonic-gate { 7617c478bd9Sstevel@tonic-gate auto char c; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate ** Wait for the parent to close the write end 7657c478bd9Sstevel@tonic-gate ** of the pipe, which we will see as an EOF. 7667c478bd9Sstevel@tonic-gate ** This guarantees that we won't write to the 7677c478bd9Sstevel@tonic-gate ** socket until after the parent has closed 7687c478bd9Sstevel@tonic-gate ** the pipe. 7697c478bd9Sstevel@tonic-gate */ 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* close the write end of the pipe */ 7727c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* we shouldn't be interrupted, but ... */ 7757c478bd9Sstevel@tonic-gate while (read(pipefd[0], &c, 1) < 0 && 7767c478bd9Sstevel@tonic-gate errno == EINTR) 7777c478bd9Sstevel@tonic-gate continue; 7787c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate /* control socket processing */ 7827c478bd9Sstevel@tonic-gate if (control) 7837c478bd9Sstevel@tonic-gate { 7847c478bd9Sstevel@tonic-gate control_command(t, e); 7857c478bd9Sstevel@tonic-gate /* NOTREACHED */ 7867c478bd9Sstevel@tonic-gate exit(EX_SOFTWARE); 7877c478bd9Sstevel@tonic-gate } 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* determine host name */ 7907c478bd9Sstevel@tonic-gate p = hostnamebyanyaddr(&RealHostAddr); 7917c478bd9Sstevel@tonic-gate if (strlen(p) > MAXNAME) /* XXX - 1 ? */ 7927c478bd9Sstevel@tonic-gate p[MAXNAME] = '\0'; 7937c478bd9Sstevel@tonic-gate RealHostName = newstr(p); 7947c478bd9Sstevel@tonic-gate if (RealHostName[0] == '[') 7957c478bd9Sstevel@tonic-gate { 7967c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 7977c478bd9Sstevel@tonic-gate macid("{client_resolve}"), 7987c478bd9Sstevel@tonic-gate h_errno == TRY_AGAIN ? "TEMP" : "FAIL"); 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate else 8017c478bd9Sstevel@tonic-gate { 8027c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 8037c478bd9Sstevel@tonic-gate macid("{client_resolve}"), "OK"); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, "startup with %s", p); 8067c478bd9Sstevel@tonic-gate markstats(e, NULL, STATS_CONNECT); 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate if ((inchannel = sm_io_open(SmFtStdiofd, 8097c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8107c478bd9Sstevel@tonic-gate (void *) &t, 8117c478bd9Sstevel@tonic-gate SM_IO_RDONLY_B, 8127c478bd9Sstevel@tonic-gate NULL)) == NULL || 8137c478bd9Sstevel@tonic-gate (t = dup(t)) < 0 || 8147c478bd9Sstevel@tonic-gate (outchannel = sm_io_open(SmFtStdiofd, 8157c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 8167c478bd9Sstevel@tonic-gate (void *) &t, 8177c478bd9Sstevel@tonic-gate SM_IO_WRONLY_B, 8187c478bd9Sstevel@tonic-gate NULL)) == NULL) 8197c478bd9Sstevel@tonic-gate { 8207c478bd9Sstevel@tonic-gate syserr("cannot open SMTP server channel, fd=%d", 8217c478bd9Sstevel@tonic-gate t); 8227c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate sm_io_automode(inchannel, outchannel); 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate InChannel = inchannel; 8277c478bd9Sstevel@tonic-gate OutChannel = outchannel; 8287c478bd9Sstevel@tonic-gate DisConnected = false; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate #if XLA 8317c478bd9Sstevel@tonic-gate if (!xla_host_ok(RealHostName)) 8327c478bd9Sstevel@tonic-gate { 8337c478bd9Sstevel@tonic-gate message("421 4.4.5 Too many SMTP sessions for this host"); 8347c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate #endif /* XLA */ 8377c478bd9Sstevel@tonic-gate /* find out name for interface of connection */ 8387c478bd9Sstevel@tonic-gate if (getsockname(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 8397c478bd9Sstevel@tonic-gate NULL), &sa.sa, &len) == 0) 8407c478bd9Sstevel@tonic-gate { 8417c478bd9Sstevel@tonic-gate p = hostnamebyanyaddr(&sa); 8427c478bd9Sstevel@tonic-gate if (tTd(15, 9)) 8437c478bd9Sstevel@tonic-gate sm_dprintf("getreq: got name %s\n", p); 8447c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 8457c478bd9Sstevel@tonic-gate macid("{if_name}"), p); 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* 8487c478bd9Sstevel@tonic-gate ** Do this only if it is not the loopback 8497c478bd9Sstevel@tonic-gate ** interface. 8507c478bd9Sstevel@tonic-gate */ 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate if (!isloopback(sa)) 8537c478bd9Sstevel@tonic-gate { 8547c478bd9Sstevel@tonic-gate char *addr; 8557c478bd9Sstevel@tonic-gate char family[5]; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate addr = anynet_ntoa(&sa); 8587c478bd9Sstevel@tonic-gate (void) sm_snprintf(family, 8597c478bd9Sstevel@tonic-gate sizeof(family), 8607c478bd9Sstevel@tonic-gate "%d", sa.sa.sa_family); 8617c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 8627c478bd9Sstevel@tonic-gate A_TEMP, 8637c478bd9Sstevel@tonic-gate macid("{if_addr}"), addr); 8647c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 8657c478bd9Sstevel@tonic-gate A_TEMP, 8667c478bd9Sstevel@tonic-gate macid("{if_family}"), family); 8677c478bd9Sstevel@tonic-gate if (tTd(15, 7)) 8687c478bd9Sstevel@tonic-gate sm_dprintf("getreq: got addr %s and family %s\n", 8697c478bd9Sstevel@tonic-gate addr, family); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate else 8727c478bd9Sstevel@tonic-gate { 8737c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 8747c478bd9Sstevel@tonic-gate A_PERM, 8757c478bd9Sstevel@tonic-gate macid("{if_addr}"), NULL); 8767c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 8777c478bd9Sstevel@tonic-gate A_PERM, 8787c478bd9Sstevel@tonic-gate macid("{if_family}"), NULL); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate else 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate if (tTd(15, 7)) 8847c478bd9Sstevel@tonic-gate sm_dprintf("getreq: getsockname failed\n"); 8857c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 8867c478bd9Sstevel@tonic-gate macid("{if_name}"), NULL); 8877c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 8887c478bd9Sstevel@tonic-gate macid("{if_addr}"), NULL); 8897c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 8907c478bd9Sstevel@tonic-gate macid("{if_family}"), NULL); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate break; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate /* parent -- keep track of children */ 8967c478bd9Sstevel@tonic-gate if (control) 8977c478bd9Sstevel@tonic-gate { 898058561cbSjbeck (void) sm_snprintf(status, sizeof(status), 8997c478bd9Sstevel@tonic-gate "control socket server child"); 9007c478bd9Sstevel@tonic-gate proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate else 9037c478bd9Sstevel@tonic-gate { 904058561cbSjbeck (void) sm_snprintf(status, sizeof(status), 9057c478bd9Sstevel@tonic-gate "SMTP server child for %s", 9067c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 9077c478bd9Sstevel@tonic-gate proc_list_add(pid, status, PROC_DAEMON, 0, -1, 9087c478bd9Sstevel@tonic-gate &RealHostAddr); 9097c478bd9Sstevel@tonic-gate } 9107c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate /* close the read end of the synchronization pipe */ 9137c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 9147c478bd9Sstevel@tonic-gate { 9157c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 9167c478bd9Sstevel@tonic-gate pipefd[0] = -1; 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate /* close the port so that others will hang (for a while) */ 9207c478bd9Sstevel@tonic-gate (void) close(t); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* release the child by closing the read end of the sync pipe */ 9237c478bd9Sstevel@tonic-gate if (pipefd[1] != -1) 9247c478bd9Sstevel@tonic-gate { 9257c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 9267c478bd9Sstevel@tonic-gate pipefd[1] = -1; 9277c478bd9Sstevel@tonic-gate } 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 9307c478bd9Sstevel@tonic-gate sm_dprintf("getreq: returning\n"); 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate #if MILTER 9337c478bd9Sstevel@tonic-gate /* set the filters for this daemon */ 9347c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_inputfilterlist != NULL) 9357c478bd9Sstevel@tonic-gate { 9367c478bd9Sstevel@tonic-gate for (i = 0; 9377c478bd9Sstevel@tonic-gate (i < MAXFILTERS && 9387c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_inputfilters[i] != NULL); 9397c478bd9Sstevel@tonic-gate i++) 9407c478bd9Sstevel@tonic-gate { 9417c478bd9Sstevel@tonic-gate InputFilters[i] = Daemons[curdaemon].d_inputfilters[i]; 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate if (i < MAXFILTERS) 9447c478bd9Sstevel@tonic-gate InputFilters[i] = NULL; 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate #endif /* MILTER */ 9477c478bd9Sstevel@tonic-gate return &Daemons[curdaemon].d_flags; 9487c478bd9Sstevel@tonic-gate } 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate /* 9517c478bd9Sstevel@tonic-gate ** GETREQUESTS_CHECKDISKSPACE -- check available diskspace. 9527c478bd9Sstevel@tonic-gate ** 9537c478bd9Sstevel@tonic-gate ** Parameters: 9547c478bd9Sstevel@tonic-gate ** e -- envelope. 9557c478bd9Sstevel@tonic-gate ** 9567c478bd9Sstevel@tonic-gate ** Returns: 9577c478bd9Sstevel@tonic-gate ** none. 9587c478bd9Sstevel@tonic-gate ** 9597c478bd9Sstevel@tonic-gate ** Side Effects: 9607c478bd9Sstevel@tonic-gate ** Modifies Daemon flags (D_ETRNONLY) if not enough disk space. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate static void 9647c478bd9Sstevel@tonic-gate getrequests_checkdiskspace(e) 9657c478bd9Sstevel@tonic-gate ENVELOPE *e; 9667c478bd9Sstevel@tonic-gate { 9677c478bd9Sstevel@tonic-gate bool logged = false; 9687c478bd9Sstevel@tonic-gate int idx; 9697c478bd9Sstevel@tonic-gate time_t now; 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate now = curtime(); 9727c478bd9Sstevel@tonic-gate if (now < NextDiskSpaceCheck) 9737c478bd9Sstevel@tonic-gate return; 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate /* Check if there is available disk space in all queue groups. */ 9767c478bd9Sstevel@tonic-gate if (!enoughdiskspace(0, NULL)) 9777c478bd9Sstevel@tonic-gate { 9787c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; ++idx) 9797c478bd9Sstevel@tonic-gate { 9807c478bd9Sstevel@tonic-gate if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 9817c478bd9Sstevel@tonic-gate continue; 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate /* log only if not logged before */ 9847c478bd9Sstevel@tonic-gate if (!logged) 9857c478bd9Sstevel@tonic-gate { 9867c478bd9Sstevel@tonic-gate if (LogLevel > 8) 9877c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 9887c478bd9Sstevel@tonic-gate "rejecting new messages: min free: %ld", 9897c478bd9Sstevel@tonic-gate MinBlocksFree); 9907c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, 9917c478bd9Sstevel@tonic-gate "rejecting new messages: min free: %ld", 9927c478bd9Sstevel@tonic-gate MinBlocksFree); 9937c478bd9Sstevel@tonic-gate logged = true; 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate setbitn(D_ETRNONLY, Daemons[idx].d_flags); 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate else 9997c478bd9Sstevel@tonic-gate { 10007c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; ++idx) 10017c478bd9Sstevel@tonic-gate { 10027c478bd9Sstevel@tonic-gate if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 10037c478bd9Sstevel@tonic-gate continue; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate /* log only if not logged before */ 10067c478bd9Sstevel@tonic-gate if (!logged) 10077c478bd9Sstevel@tonic-gate { 10087c478bd9Sstevel@tonic-gate if (LogLevel > 8) 10097c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 10107c478bd9Sstevel@tonic-gate "accepting new messages (again)"); 10117c478bd9Sstevel@tonic-gate logged = true; 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate /* title will be set later */ 10157c478bd9Sstevel@tonic-gate clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate /* only check disk space once a minute */ 10207c478bd9Sstevel@tonic-gate NextDiskSpaceCheck = now + 60; 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 10237c478bd9Sstevel@tonic-gate /* 10247c478bd9Sstevel@tonic-gate ** OPENDAEMONSOCKET -- open SMTP socket 10257c478bd9Sstevel@tonic-gate ** 10267c478bd9Sstevel@tonic-gate ** Deals with setting all appropriate options. 10277c478bd9Sstevel@tonic-gate ** 10287c478bd9Sstevel@tonic-gate ** Parameters: 10297c478bd9Sstevel@tonic-gate ** d -- the structure for the daemon to open. 10307c478bd9Sstevel@tonic-gate ** firsttime -- set if this is the initial open. 10317c478bd9Sstevel@tonic-gate ** 10327c478bd9Sstevel@tonic-gate ** Returns: 10337c478bd9Sstevel@tonic-gate ** Size in bytes of the daemon socket addr. 10347c478bd9Sstevel@tonic-gate ** 10357c478bd9Sstevel@tonic-gate ** Side Effects: 10367c478bd9Sstevel@tonic-gate ** Leaves DaemonSocket set to the open socket. 10377c478bd9Sstevel@tonic-gate ** Exits if the socket cannot be created. 10387c478bd9Sstevel@tonic-gate */ 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate static int 10437c478bd9Sstevel@tonic-gate opendaemonsocket(d, firsttime) 10447c478bd9Sstevel@tonic-gate DAEMON_T *d; 10457c478bd9Sstevel@tonic-gate bool firsttime; 10467c478bd9Sstevel@tonic-gate { 10477c478bd9Sstevel@tonic-gate int on = 1; 10487c478bd9Sstevel@tonic-gate int fdflags; 10497c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T socksize = 0; 10507c478bd9Sstevel@tonic-gate int ntries = 0; 10517c478bd9Sstevel@tonic-gate int save_errno; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 10547c478bd9Sstevel@tonic-gate sm_dprintf("opendaemonsocket(%s)\n", d->d_name); 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate do 10577c478bd9Sstevel@tonic-gate { 10587c478bd9Sstevel@tonic-gate if (ntries > 0) 10597c478bd9Sstevel@tonic-gate (void) sleep(5); 10607c478bd9Sstevel@tonic-gate if (firsttime || d->d_socket < 0) 10617c478bd9Sstevel@tonic-gate { 10627c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 10637c478bd9Sstevel@tonic-gate # if NETUNIX 10647c478bd9Sstevel@tonic-gate if (d->d_addr.sa.sa_family == AF_UNIX) 10657c478bd9Sstevel@tonic-gate { 10667c478bd9Sstevel@tonic-gate int rval; 10677c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK|SFF_CREAT; 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate /* if not safe, don't use it */ 10707c478bd9Sstevel@tonic-gate rval = safefile(d->d_addr.sunix.sun_path, 10717c478bd9Sstevel@tonic-gate RunAsUid, RunAsGid, 10727c478bd9Sstevel@tonic-gate RunAsUserName, sff, 10737c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 10747c478bd9Sstevel@tonic-gate if (rval != 0) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate save_errno = errno; 10777c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: unsafe domain socket %s", 10787c478bd9Sstevel@tonic-gate d->d_name, 10797c478bd9Sstevel@tonic-gate d->d_addr.sunix.sun_path); 10807c478bd9Sstevel@tonic-gate goto fail; 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate /* Don't try to overtake an existing socket */ 10847c478bd9Sstevel@tonic-gate (void) unlink(d->d_addr.sunix.sun_path); 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 10877c478bd9Sstevel@tonic-gate #endif /* _FFR_DOMAIN_NETUNIX */ 10887c478bd9Sstevel@tonic-gate d->d_socket = socket(d->d_addr.sa.sa_family, 10897c478bd9Sstevel@tonic-gate SOCK_STREAM, 0); 10907c478bd9Sstevel@tonic-gate if (d->d_socket < 0) 10917c478bd9Sstevel@tonic-gate { 10927c478bd9Sstevel@tonic-gate save_errno = errno; 10937c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", 10947c478bd9Sstevel@tonic-gate d->d_name); 10957c478bd9Sstevel@tonic-gate fail: 10967c478bd9Sstevel@tonic-gate if (bitnset(D_OPTIONAL, d->d_flags) && 10977c478bd9Sstevel@tonic-gate (!transienterror(save_errno) || 10987c478bd9Sstevel@tonic-gate ntries >= MAXOPENTRIES - 1)) 10997c478bd9Sstevel@tonic-gate { 11007c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: optional socket disabled", 11017c478bd9Sstevel@tonic-gate d->d_name); 11027c478bd9Sstevel@tonic-gate setbitn(D_DISABLE, d->d_flags); 11037c478bd9Sstevel@tonic-gate d->d_socket = -1; 11047c478bd9Sstevel@tonic-gate return -1; 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate severe: 11077c478bd9Sstevel@tonic-gate if (LogLevel > 0) 11087c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 11097c478bd9Sstevel@tonic-gate "daemon %s: problem creating SMTP socket", 11107c478bd9Sstevel@tonic-gate d->d_name); 11117c478bd9Sstevel@tonic-gate d->d_socket = -1; 11127c478bd9Sstevel@tonic-gate continue; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate if (SM_FD_SETSIZE > 0 && d->d_socket >= SM_FD_SETSIZE) 11167c478bd9Sstevel@tonic-gate { 11177c478bd9Sstevel@tonic-gate save_errno = EINVAL; 11187c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: server SMTP socket (%d) too large", 11197c478bd9Sstevel@tonic-gate d->d_name, d->d_socket); 11207c478bd9Sstevel@tonic-gate goto fail; 11217c478bd9Sstevel@tonic-gate } 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate /* turn on network debugging? */ 11247c478bd9Sstevel@tonic-gate if (tTd(15, 101)) 11257c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 11267c478bd9Sstevel@tonic-gate SO_DEBUG, (char *)&on, 1127058561cbSjbeck sizeof(on)); 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1130058561cbSjbeck SO_REUSEADDR, (char *)&on, sizeof(on)); 11317c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1132058561cbSjbeck SO_KEEPALIVE, (char *)&on, sizeof(on)); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate #ifdef SO_RCVBUF 11357c478bd9Sstevel@tonic-gate if (d->d_tcprcvbufsize > 0) 11367c478bd9Sstevel@tonic-gate { 11377c478bd9Sstevel@tonic-gate if (setsockopt(d->d_socket, SOL_SOCKET, 11387c478bd9Sstevel@tonic-gate SO_RCVBUF, 11397c478bd9Sstevel@tonic-gate (char *) &d->d_tcprcvbufsize, 11407c478bd9Sstevel@tonic-gate sizeof(d->d_tcprcvbufsize)) < 0) 11417c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 11427c478bd9Sstevel@tonic-gate } 11437c478bd9Sstevel@tonic-gate #endif /* SO_RCVBUF */ 11447c478bd9Sstevel@tonic-gate #ifdef SO_SNDBUF 11457c478bd9Sstevel@tonic-gate if (d->d_tcpsndbufsize > 0) 11467c478bd9Sstevel@tonic-gate { 11477c478bd9Sstevel@tonic-gate if (setsockopt(d->d_socket, SOL_SOCKET, 11487c478bd9Sstevel@tonic-gate SO_SNDBUF, 11497c478bd9Sstevel@tonic-gate (char *) &d->d_tcpsndbufsize, 11507c478bd9Sstevel@tonic-gate sizeof(d->d_tcpsndbufsize)) < 0) 11517c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate #endif /* SO_SNDBUF */ 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 11567c478bd9Sstevel@tonic-gate fcntl(d->d_socket, F_SETFD, 11577c478bd9Sstevel@tonic-gate fdflags | FD_CLOEXEC) == -1) 11587c478bd9Sstevel@tonic-gate { 11597c478bd9Sstevel@tonic-gate save_errno = errno; 11607c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 11617c478bd9Sstevel@tonic-gate d->d_name, 11627c478bd9Sstevel@tonic-gate fdflags == -1 ? "get" : "set", 11637c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 11647c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 11657c478bd9Sstevel@tonic-gate goto severe; 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 11697c478bd9Sstevel@tonic-gate { 11707c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 11717c478bd9Sstevel@tonic-gate # ifdef NETUNIX 11727c478bd9Sstevel@tonic-gate case AF_UNIX: 1173058561cbSjbeck socksize = sizeof(d->d_addr.sunix); 11747c478bd9Sstevel@tonic-gate break; 11757c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 11767c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 11777c478bd9Sstevel@tonic-gate #if NETINET 11787c478bd9Sstevel@tonic-gate case AF_INET: 1179058561cbSjbeck socksize = sizeof(d->d_addr.sin); 11807c478bd9Sstevel@tonic-gate break; 11817c478bd9Sstevel@tonic-gate #endif /* NETINET */ 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate #if NETINET6 11847c478bd9Sstevel@tonic-gate case AF_INET6: 1185058561cbSjbeck socksize = sizeof(d->d_addr.sin6); 11867c478bd9Sstevel@tonic-gate break; 11877c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate #if NETISO 11907c478bd9Sstevel@tonic-gate case AF_ISO: 1191058561cbSjbeck socksize = sizeof(d->d_addr.siso); 11927c478bd9Sstevel@tonic-gate break; 11937c478bd9Sstevel@tonic-gate #endif /* NETISO */ 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate default: 1196058561cbSjbeck socksize = sizeof(d->d_addr); 11977c478bd9Sstevel@tonic-gate break; 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 12017c478bd9Sstevel@tonic-gate { 12027c478bd9Sstevel@tonic-gate /* probably another daemon already */ 12037c478bd9Sstevel@tonic-gate save_errno = errno; 12047c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: cannot bind", 12057c478bd9Sstevel@tonic-gate d->d_name); 12067c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 12077c478bd9Sstevel@tonic-gate goto fail; 12087c478bd9Sstevel@tonic-gate } 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate if (!firsttime && 12117c478bd9Sstevel@tonic-gate listen(d->d_socket, d->d_listenqueue) < 0) 12127c478bd9Sstevel@tonic-gate { 12137c478bd9Sstevel@tonic-gate save_errno = errno; 12147c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: cannot listen", 12157c478bd9Sstevel@tonic-gate d->d_name); 12167c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 12177c478bd9Sstevel@tonic-gate goto severe; 12187c478bd9Sstevel@tonic-gate } 12197c478bd9Sstevel@tonic-gate return socksize; 12207c478bd9Sstevel@tonic-gate } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 12217c478bd9Sstevel@tonic-gate syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 12227c478bd9Sstevel@tonic-gate d->d_name); 12237c478bd9Sstevel@tonic-gate /* NOTREACHED */ 12247c478bd9Sstevel@tonic-gate return -1; /* avoid compiler warning on IRIX */ 12257c478bd9Sstevel@tonic-gate } 12267c478bd9Sstevel@tonic-gate /* 12277c478bd9Sstevel@tonic-gate ** SETUPDAEMON -- setup socket for daemon 12287c478bd9Sstevel@tonic-gate ** 12297c478bd9Sstevel@tonic-gate ** Parameters: 12307c478bd9Sstevel@tonic-gate ** daemonaddr -- socket for daemon 12317c478bd9Sstevel@tonic-gate ** 12327c478bd9Sstevel@tonic-gate ** Returns: 12337c478bd9Sstevel@tonic-gate ** port number on which daemon should run 12347c478bd9Sstevel@tonic-gate ** 12357c478bd9Sstevel@tonic-gate */ 12367c478bd9Sstevel@tonic-gate 12377c478bd9Sstevel@tonic-gate static unsigned short 12387c478bd9Sstevel@tonic-gate setupdaemon(daemonaddr) 12397c478bd9Sstevel@tonic-gate SOCKADDR *daemonaddr; 12407c478bd9Sstevel@tonic-gate { 12417c478bd9Sstevel@tonic-gate unsigned short port; 12427c478bd9Sstevel@tonic-gate 12437c478bd9Sstevel@tonic-gate /* 12447c478bd9Sstevel@tonic-gate ** Set up the address for the mailer. 12457c478bd9Sstevel@tonic-gate */ 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate if (daemonaddr->sa.sa_family == AF_UNSPEC) 12487c478bd9Sstevel@tonic-gate { 1249058561cbSjbeck memset(daemonaddr, '\0', sizeof(*daemonaddr)); 12507c478bd9Sstevel@tonic-gate #if NETINET 12517c478bd9Sstevel@tonic-gate daemonaddr->sa.sa_family = AF_INET; 12527c478bd9Sstevel@tonic-gate #endif /* NETINET */ 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate switch (daemonaddr->sa.sa_family) 12567c478bd9Sstevel@tonic-gate { 12577c478bd9Sstevel@tonic-gate #if NETINET 12587c478bd9Sstevel@tonic-gate case AF_INET: 12597c478bd9Sstevel@tonic-gate if (daemonaddr->sin.sin_addr.s_addr == 0) 1260d4660949Sjbeck daemonaddr->sin.sin_addr.s_addr = 1261d4660949Sjbeck LocalDaemon ? htonl(INADDR_LOOPBACK) : INADDR_ANY; 12627c478bd9Sstevel@tonic-gate port = daemonaddr->sin.sin_port; 12637c478bd9Sstevel@tonic-gate break; 12647c478bd9Sstevel@tonic-gate #endif /* NETINET */ 12657c478bd9Sstevel@tonic-gate 12667c478bd9Sstevel@tonic-gate #if NETINET6 12677c478bd9Sstevel@tonic-gate case AF_INET6: 12687c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 1269d4660949Sjbeck daemonaddr->sin6.sin6_addr = 1270d4660949Sjbeck LocalDaemon ? in6addr_loopback : in6addr_any; 12717c478bd9Sstevel@tonic-gate port = daemonaddr->sin6.sin6_port; 12727c478bd9Sstevel@tonic-gate break; 12737c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate default: 12767c478bd9Sstevel@tonic-gate /* unknown protocol */ 12777c478bd9Sstevel@tonic-gate port = 0; 12787c478bd9Sstevel@tonic-gate break; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate if (port == 0) 12817c478bd9Sstevel@tonic-gate { 12827c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 12837c478bd9Sstevel@tonic-gate port = htons(25); 12847c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 12857c478bd9Sstevel@tonic-gate { 12867c478bd9Sstevel@tonic-gate register struct servent *sp; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate sp = getservbyname("smtp", "tcp"); 12897c478bd9Sstevel@tonic-gate if (sp == NULL) 12907c478bd9Sstevel@tonic-gate { 12917c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"smtp\" unknown"); 12927c478bd9Sstevel@tonic-gate port = htons(25); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate else 12957c478bd9Sstevel@tonic-gate port = sp->s_port; 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate switch (daemonaddr->sa.sa_family) 13017c478bd9Sstevel@tonic-gate { 13027c478bd9Sstevel@tonic-gate #if NETINET 13037c478bd9Sstevel@tonic-gate case AF_INET: 13047c478bd9Sstevel@tonic-gate daemonaddr->sin.sin_port = port; 13057c478bd9Sstevel@tonic-gate break; 13067c478bd9Sstevel@tonic-gate #endif /* NETINET */ 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate #if NETINET6 13097c478bd9Sstevel@tonic-gate case AF_INET6: 13107c478bd9Sstevel@tonic-gate daemonaddr->sin6.sin6_port = port; 13117c478bd9Sstevel@tonic-gate break; 13127c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate default: 13157c478bd9Sstevel@tonic-gate /* unknown protocol */ 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate return port; 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate /* 13217c478bd9Sstevel@tonic-gate ** CLRDAEMON -- reset the daemon connection 13227c478bd9Sstevel@tonic-gate ** 13237c478bd9Sstevel@tonic-gate ** Parameters: 13247c478bd9Sstevel@tonic-gate ** none. 13257c478bd9Sstevel@tonic-gate ** 13267c478bd9Sstevel@tonic-gate ** Returns: 13277c478bd9Sstevel@tonic-gate ** none. 13287c478bd9Sstevel@tonic-gate ** 13297c478bd9Sstevel@tonic-gate ** Side Effects: 13307c478bd9Sstevel@tonic-gate ** releases any resources used by the passive daemon. 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate void 13347c478bd9Sstevel@tonic-gate clrdaemon() 13357c478bd9Sstevel@tonic-gate { 13367c478bd9Sstevel@tonic-gate int i; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 13397c478bd9Sstevel@tonic-gate { 13407c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 13417c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 13427c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate /* 13477c478bd9Sstevel@tonic-gate ** GETMODIFIERS -- get modifier flags 13487c478bd9Sstevel@tonic-gate ** 13497c478bd9Sstevel@tonic-gate ** Parameters: 13507c478bd9Sstevel@tonic-gate ** v -- the modifiers (input text line). 13517c478bd9Sstevel@tonic-gate ** modifiers -- pointer to flag field to represent modifiers. 13527c478bd9Sstevel@tonic-gate ** 13537c478bd9Sstevel@tonic-gate ** Returns: 13547c478bd9Sstevel@tonic-gate ** (xallocat()ed) string representation of modifiers. 13557c478bd9Sstevel@tonic-gate ** 13567c478bd9Sstevel@tonic-gate ** Side Effects: 13577c478bd9Sstevel@tonic-gate ** fills in modifiers. 13587c478bd9Sstevel@tonic-gate */ 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate char * 13617c478bd9Sstevel@tonic-gate getmodifiers(v, modifiers) 13627c478bd9Sstevel@tonic-gate char *v; 13637c478bd9Sstevel@tonic-gate BITMAP256 modifiers; 13647c478bd9Sstevel@tonic-gate { 13657c478bd9Sstevel@tonic-gate int l; 13667c478bd9Sstevel@tonic-gate char *h, *f, *flags; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* maximum length of flags: upper case Option -> "OO " */ 13697c478bd9Sstevel@tonic-gate l = 3 * strlen(v) + 3; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate /* is someone joking? */ 13727c478bd9Sstevel@tonic-gate if (l < 0 || l > 256) 13737c478bd9Sstevel@tonic-gate { 13747c478bd9Sstevel@tonic-gate if (LogLevel > 2) 13757c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 13767c478bd9Sstevel@tonic-gate "getmodifiers too long, ignored"); 13777c478bd9Sstevel@tonic-gate return NULL; 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate flags = xalloc(l); 13807c478bd9Sstevel@tonic-gate f = flags; 13817c478bd9Sstevel@tonic-gate clrbitmap(modifiers); 13827c478bd9Sstevel@tonic-gate for (h = v; *h != '\0'; h++) 13837c478bd9Sstevel@tonic-gate { 13847c478bd9Sstevel@tonic-gate if (isascii(*h) && !isspace(*h) && isprint(*h)) 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate setbitn(*h, modifiers); 13877c478bd9Sstevel@tonic-gate if (flags != f) 13887c478bd9Sstevel@tonic-gate *flags++ = ' '; 13897c478bd9Sstevel@tonic-gate *flags++ = *h; 13907c478bd9Sstevel@tonic-gate if (isupper(*h)) 13917c478bd9Sstevel@tonic-gate *flags++ = *h; 13927c478bd9Sstevel@tonic-gate } 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate *flags++ = '\0'; 13957c478bd9Sstevel@tonic-gate return f; 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate ** CHKDAEMONMODIFIERS -- check whether all daemons have set a flag. 14007c478bd9Sstevel@tonic-gate ** 14017c478bd9Sstevel@tonic-gate ** Parameters: 14027c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 14037c478bd9Sstevel@tonic-gate ** 14047c478bd9Sstevel@tonic-gate ** Returns: 14057c478bd9Sstevel@tonic-gate ** true iff all daemons have set flag. 14067c478bd9Sstevel@tonic-gate */ 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate bool 14097c478bd9Sstevel@tonic-gate chkdaemonmodifiers(flag) 14107c478bd9Sstevel@tonic-gate int flag; 14117c478bd9Sstevel@tonic-gate { 14127c478bd9Sstevel@tonic-gate int i; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 14157c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, Daemons[i].d_flags)) 14167c478bd9Sstevel@tonic-gate return false; 14177c478bd9Sstevel@tonic-gate return true; 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate /* 14217c478bd9Sstevel@tonic-gate ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 14227c478bd9Sstevel@tonic-gate ** 14237c478bd9Sstevel@tonic-gate ** Parameters: 14247c478bd9Sstevel@tonic-gate ** p -- the options line. 14257c478bd9Sstevel@tonic-gate ** d -- the daemon structure to fill in. 14267c478bd9Sstevel@tonic-gate ** 14277c478bd9Sstevel@tonic-gate ** Returns: 14287c478bd9Sstevel@tonic-gate ** none. 14297c478bd9Sstevel@tonic-gate */ 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate static void 14327c478bd9Sstevel@tonic-gate setsockaddroptions(p, d) 14337c478bd9Sstevel@tonic-gate char *p; 14347c478bd9Sstevel@tonic-gate DAEMON_T *d; 14357c478bd9Sstevel@tonic-gate { 14367c478bd9Sstevel@tonic-gate #if NETISO 14377c478bd9Sstevel@tonic-gate short portno; 14387c478bd9Sstevel@tonic-gate #endif /* NETISO */ 14397c478bd9Sstevel@tonic-gate char *port = NULL; 14407c478bd9Sstevel@tonic-gate char *addr = NULL; 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate #if NETINET 14437c478bd9Sstevel@tonic-gate if (d->d_addr.sa.sa_family == AF_UNSPEC) 14447c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 14457c478bd9Sstevel@tonic-gate #endif /* NETINET */ 144649218d4fSjbeck #if _FFR_SS_PER_DAEMON 1447058561cbSjbeck d->d_supersafe = DPO_NOTSET; 144849218d4fSjbeck #endif /* _FFR_SS_PER_DAEMON */ 144949218d4fSjbeck d->d_dm = DM_NOTSET; 1450058561cbSjbeck d->d_refuseLA = DPO_NOTSET; 1451058561cbSjbeck d->d_queueLA = DPO_NOTSET; 1452058561cbSjbeck d->d_delayLA = DPO_NOTSET; 1453058561cbSjbeck d->d_maxchildren = DPO_NOTSET; 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate while (p != NULL) 14567c478bd9Sstevel@tonic-gate { 14577c478bd9Sstevel@tonic-gate register char *f; 14587c478bd9Sstevel@tonic-gate register char *v; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 14617c478bd9Sstevel@tonic-gate p++; 14627c478bd9Sstevel@tonic-gate if (*p == '\0') 14637c478bd9Sstevel@tonic-gate break; 14647c478bd9Sstevel@tonic-gate f = p; 14657c478bd9Sstevel@tonic-gate p = strchr(p, ','); 14667c478bd9Sstevel@tonic-gate if (p != NULL) 14677c478bd9Sstevel@tonic-gate *p++ = '\0'; 14687c478bd9Sstevel@tonic-gate v = strchr(f, '='); 14697c478bd9Sstevel@tonic-gate if (v == NULL) 14707c478bd9Sstevel@tonic-gate continue; 14717c478bd9Sstevel@tonic-gate while (isascii(*++v) && isspace(*v)) 14727c478bd9Sstevel@tonic-gate continue; 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate switch (*f) 14757c478bd9Sstevel@tonic-gate { 14767c478bd9Sstevel@tonic-gate case 'A': /* address */ 14774aac33d3Sjbeck #if !_FFR_DPO_CS 14784aac33d3Sjbeck case 'a': 14794aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 14807c478bd9Sstevel@tonic-gate addr = v; 14817c478bd9Sstevel@tonic-gate break; 14827c478bd9Sstevel@tonic-gate 1483058561cbSjbeck case 'c': 1484058561cbSjbeck d->d_maxchildren = atoi(v); 1485058561cbSjbeck break; 1486058561cbSjbeck 14877c478bd9Sstevel@tonic-gate case 'D': /* DeliveryMode */ 14887c478bd9Sstevel@tonic-gate switch (*v) 14897c478bd9Sstevel@tonic-gate { 14907c478bd9Sstevel@tonic-gate case SM_QUEUE: 14917c478bd9Sstevel@tonic-gate case SM_DEFER: 14927c478bd9Sstevel@tonic-gate case SM_DELIVER: 1493445f2479Sjbeck case SM_FORK: 14947c478bd9Sstevel@tonic-gate d->d_dm = *v; 14957c478bd9Sstevel@tonic-gate break; 14967c478bd9Sstevel@tonic-gate default: 14977c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown delivery mode %c", 14987c478bd9Sstevel@tonic-gate *v); 14997c478bd9Sstevel@tonic-gate break; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate break; 1502058561cbSjbeck 1503058561cbSjbeck case 'd': /* delayLA */ 1504058561cbSjbeck d->d_delayLA = atoi(v); 1505058561cbSjbeck break; 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate case 'F': /* address family */ 15084aac33d3Sjbeck #if !_FFR_DPO_CS 15094aac33d3Sjbeck case 'f': 15104aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15117c478bd9Sstevel@tonic-gate if (isascii(*v) && isdigit(*v)) 15127c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = atoi(v); 15137c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 15147c478bd9Sstevel@tonic-gate # ifdef NETUNIX 15157c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "unix") == 0 || 15167c478bd9Sstevel@tonic-gate sm_strcasecmp(v, "local") == 0) 15177c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_UNIX; 15187c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 15197c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 15207c478bd9Sstevel@tonic-gate #if NETINET 15217c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet") == 0) 15227c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 15237c478bd9Sstevel@tonic-gate #endif /* NETINET */ 15247c478bd9Sstevel@tonic-gate #if NETINET6 15257c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet6") == 0) 15267c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET6; 15277c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 15287c478bd9Sstevel@tonic-gate #if NETISO 15297c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "iso") == 0) 15307c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_ISO; 15317c478bd9Sstevel@tonic-gate #endif /* NETISO */ 15327c478bd9Sstevel@tonic-gate #if NETNS 15337c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "ns") == 0) 15347c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_NS; 15357c478bd9Sstevel@tonic-gate #endif /* NETNS */ 15367c478bd9Sstevel@tonic-gate #if NETX25 15377c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "x.25") == 0) 15387c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_CCITT; 15397c478bd9Sstevel@tonic-gate #endif /* NETX25 */ 15407c478bd9Sstevel@tonic-gate else 15417c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown address family %s in Family=option", 15427c478bd9Sstevel@tonic-gate v); 15437c478bd9Sstevel@tonic-gate break; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate #if MILTER 15467c478bd9Sstevel@tonic-gate case 'I': 15474aac33d3Sjbeck # if !_FFR_DPO_CS 15484aac33d3Sjbeck case 'i': 15494aac33d3Sjbeck # endif /* !_FFR_DPO_CS */ 15507c478bd9Sstevel@tonic-gate d->d_inputfilterlist = v; 15517c478bd9Sstevel@tonic-gate break; 15527c478bd9Sstevel@tonic-gate #endif /* MILTER */ 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate case 'L': /* listen queue size */ 15554aac33d3Sjbeck #if !_FFR_DPO_CS 15564aac33d3Sjbeck case 'l': 15574aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15587c478bd9Sstevel@tonic-gate d->d_listenqueue = atoi(v); 15597c478bd9Sstevel@tonic-gate break; 15607c478bd9Sstevel@tonic-gate 15617c478bd9Sstevel@tonic-gate case 'M': /* modifiers (flags) */ 15624aac33d3Sjbeck #if !_FFR_DPO_CS 15634aac33d3Sjbeck case 'm': 15644aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15657c478bd9Sstevel@tonic-gate d->d_mflags = getmodifiers(v, d->d_flags); 15667c478bd9Sstevel@tonic-gate break; 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate case 'N': /* name */ 15694aac33d3Sjbeck #if !_FFR_DPO_CS 15704aac33d3Sjbeck case 'n': 15714aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15727c478bd9Sstevel@tonic-gate d->d_name = v; 15737c478bd9Sstevel@tonic-gate break; 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate case 'P': /* port */ 15764aac33d3Sjbeck #if !_FFR_DPO_CS 15774aac33d3Sjbeck case 'p': 15784aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15797c478bd9Sstevel@tonic-gate port = v; 15807c478bd9Sstevel@tonic-gate break; 15817c478bd9Sstevel@tonic-gate 1582058561cbSjbeck case 'q': 1583058561cbSjbeck d->d_queueLA = atoi(v); 1584058561cbSjbeck break; 1585058561cbSjbeck 15867c478bd9Sstevel@tonic-gate case 'R': /* receive buffer size */ 15877c478bd9Sstevel@tonic-gate d->d_tcprcvbufsize = atoi(v); 15887c478bd9Sstevel@tonic-gate break; 15897c478bd9Sstevel@tonic-gate 1590058561cbSjbeck case 'r': 1591058561cbSjbeck d->d_refuseLA = atoi(v); 1592058561cbSjbeck break; 1593058561cbSjbeck 15947c478bd9Sstevel@tonic-gate case 'S': /* send buffer size */ 15954aac33d3Sjbeck #if !_FFR_DPO_CS 15964aac33d3Sjbeck case 's': 15974aac33d3Sjbeck #endif /* !_FFR_DPO_CS */ 15987c478bd9Sstevel@tonic-gate d->d_tcpsndbufsize = atoi(v); 15997c478bd9Sstevel@tonic-gate break; 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 16027c478bd9Sstevel@tonic-gate case 'T': /* SuperSafe */ 16037c478bd9Sstevel@tonic-gate if (tolower(*v) == 'i') 16047c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_INTERACTIVE; 16057c478bd9Sstevel@tonic-gate else if (tolower(*v) == 'p') 16067c478bd9Sstevel@tonic-gate # if MILTER 16077c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_REALLY_POSTMILTER; 16087c478bd9Sstevel@tonic-gate # else /* MILTER */ 16097c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 16107c478bd9Sstevel@tonic-gate "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 16117c478bd9Sstevel@tonic-gate # endif /* MILTER */ 16127c478bd9Sstevel@tonic-gate else 16137c478bd9Sstevel@tonic-gate d->d_supersafe = atobool(v) ? SAFE_REALLY 16147c478bd9Sstevel@tonic-gate : SAFE_NO; 16157c478bd9Sstevel@tonic-gate break; 16167c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate default: 16197c478bd9Sstevel@tonic-gate syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 16207c478bd9Sstevel@tonic-gate f); 16217c478bd9Sstevel@tonic-gate } 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate /* Check addr and port after finding family */ 16257c478bd9Sstevel@tonic-gate if (addr != NULL) 16267c478bd9Sstevel@tonic-gate { 16277c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 16287c478bd9Sstevel@tonic-gate { 16297c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 16307c478bd9Sstevel@tonic-gate # if NETUNIX 16317c478bd9Sstevel@tonic-gate case AF_UNIX: 16327c478bd9Sstevel@tonic-gate if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) 16337c478bd9Sstevel@tonic-gate { 16347c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 16357c478bd9Sstevel@tonic-gate syserr("setsockaddroptions: domain socket name too long: %s > %d", 16367c478bd9Sstevel@tonic-gate addr, sizeof(d->d_addr.sunix.sun_path)); 16377c478bd9Sstevel@tonic-gate break; 16387c478bd9Sstevel@tonic-gate } 16397c478bd9Sstevel@tonic-gate 16407c478bd9Sstevel@tonic-gate /* file safety check done in opendaemonsocket() */ 16417c478bd9Sstevel@tonic-gate (void) memset(&d->d_addr.sunix.sun_path, '\0', 16427c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 16437c478bd9Sstevel@tonic-gate (void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path, 16447c478bd9Sstevel@tonic-gate addr, 16457c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 16467c478bd9Sstevel@tonic-gate break; 16477c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 16487c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 16497c478bd9Sstevel@tonic-gate #if NETINET 16507c478bd9Sstevel@tonic-gate case AF_INET: 16517c478bd9Sstevel@tonic-gate if (!isascii(*addr) || !isdigit(*addr) || 16527c478bd9Sstevel@tonic-gate ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) 16537c478bd9Sstevel@tonic-gate == INADDR_NONE)) 16547c478bd9Sstevel@tonic-gate { 16557c478bd9Sstevel@tonic-gate register struct hostent *hp; 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET); 16587c478bd9Sstevel@tonic-gate if (hp == NULL) 16597c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16607c478bd9Sstevel@tonic-gate addr); 16617c478bd9Sstevel@tonic-gate else 16627c478bd9Sstevel@tonic-gate { 16637c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 16647c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET) 16657c478bd9Sstevel@tonic-gate hp->h_addr_list++; 16667c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 16677c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16687c478bd9Sstevel@tonic-gate addr); 16697c478bd9Sstevel@tonic-gate else 16707c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin.sin_addr, 16717c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 16727c478bd9Sstevel@tonic-gate INADDRSZ); 16737c478bd9Sstevel@tonic-gate # if NETINET6 16747c478bd9Sstevel@tonic-gate freehostent(hp); 16757c478bd9Sstevel@tonic-gate hp = NULL; 16767c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate break; 16807c478bd9Sstevel@tonic-gate #endif /* NETINET */ 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate #if NETINET6 16837c478bd9Sstevel@tonic-gate case AF_INET6: 16847c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, 16857c478bd9Sstevel@tonic-gate &d->d_addr.sin6.sin6_addr) != 1) 16867c478bd9Sstevel@tonic-gate { 16877c478bd9Sstevel@tonic-gate register struct hostent *hp; 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET6); 16907c478bd9Sstevel@tonic-gate if (hp == NULL) 16917c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16927c478bd9Sstevel@tonic-gate addr); 16937c478bd9Sstevel@tonic-gate else 16947c478bd9Sstevel@tonic-gate { 16957c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 16967c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET6) 16977c478bd9Sstevel@tonic-gate hp->h_addr_list++; 16987c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 16997c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 17007c478bd9Sstevel@tonic-gate addr); 17017c478bd9Sstevel@tonic-gate else 17027c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin6.sin6_addr, 17037c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 17047c478bd9Sstevel@tonic-gate IN6ADDRSZ); 17057c478bd9Sstevel@tonic-gate freehostent(hp); 17067c478bd9Sstevel@tonic-gate hp = NULL; 17077c478bd9Sstevel@tonic-gate } 17087c478bd9Sstevel@tonic-gate } 17097c478bd9Sstevel@tonic-gate break; 17107c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate default: 17137c478bd9Sstevel@tonic-gate syserr("554 5.3.5 address= option unsupported for family %d", 17147c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 17157c478bd9Sstevel@tonic-gate break; 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate if (port != NULL) 17207c478bd9Sstevel@tonic-gate { 17217c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 17227c478bd9Sstevel@tonic-gate { 17237c478bd9Sstevel@tonic-gate #if NETINET 17247c478bd9Sstevel@tonic-gate case AF_INET: 17257c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17267c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = htons((unsigned short) 17277c478bd9Sstevel@tonic-gate atoi((const char *) port)); 17287c478bd9Sstevel@tonic-gate else 17297c478bd9Sstevel@tonic-gate { 17307c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 17317c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 17327c478bd9Sstevel@tonic-gate port); 17337c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 17347c478bd9Sstevel@tonic-gate register struct servent *sp; 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 17377c478bd9Sstevel@tonic-gate if (sp == NULL) 17387c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 17397c478bd9Sstevel@tonic-gate port); 17407c478bd9Sstevel@tonic-gate else 17417c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = sp->s_port; 17427c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate break; 17457c478bd9Sstevel@tonic-gate #endif /* NETINET */ 17467c478bd9Sstevel@tonic-gate 17477c478bd9Sstevel@tonic-gate #if NETINET6 17487c478bd9Sstevel@tonic-gate case AF_INET6: 17497c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17507c478bd9Sstevel@tonic-gate d->d_addr.sin6.sin6_port = htons((unsigned short) 17517c478bd9Sstevel@tonic-gate atoi(port)); 17527c478bd9Sstevel@tonic-gate else 17537c478bd9Sstevel@tonic-gate { 17547c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 17557c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 17567c478bd9Sstevel@tonic-gate port); 17577c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 17587c478bd9Sstevel@tonic-gate register struct servent *sp; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 17617c478bd9Sstevel@tonic-gate if (sp == NULL) 17627c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 17637c478bd9Sstevel@tonic-gate port); 17647c478bd9Sstevel@tonic-gate else 17657c478bd9Sstevel@tonic-gate d->d_addr.sin6.sin6_port = sp->s_port; 17667c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17677c478bd9Sstevel@tonic-gate } 17687c478bd9Sstevel@tonic-gate break; 17697c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 17707c478bd9Sstevel@tonic-gate 17717c478bd9Sstevel@tonic-gate #if NETISO 17727c478bd9Sstevel@tonic-gate case AF_ISO: 17737c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 17747c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17757c478bd9Sstevel@tonic-gate portno = htons((unsigned short) atoi(port)); 17767c478bd9Sstevel@tonic-gate else 17777c478bd9Sstevel@tonic-gate { 17787c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 17797c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 17807c478bd9Sstevel@tonic-gate port); 17817c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 17827c478bd9Sstevel@tonic-gate register struct servent *sp; 17837c478bd9Sstevel@tonic-gate 17847c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 17857c478bd9Sstevel@tonic-gate if (sp == NULL) 17867c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 17877c478bd9Sstevel@tonic-gate port); 17887c478bd9Sstevel@tonic-gate else 17897c478bd9Sstevel@tonic-gate portno = sp->s_port; 17907c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17917c478bd9Sstevel@tonic-gate } 17927c478bd9Sstevel@tonic-gate memmove(TSEL(&d->d_addr.siso), 17937c478bd9Sstevel@tonic-gate (char *) &portno, 2); 17947c478bd9Sstevel@tonic-gate break; 17957c478bd9Sstevel@tonic-gate #endif /* NETISO */ 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate default: 17987c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Port= option unsupported for family %d", 17997c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 18007c478bd9Sstevel@tonic-gate break; 18017c478bd9Sstevel@tonic-gate } 18027c478bd9Sstevel@tonic-gate } 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate /* 18057c478bd9Sstevel@tonic-gate ** SETDAEMONOPTIONS -- set options for running the MTA daemon 18067c478bd9Sstevel@tonic-gate ** 18077c478bd9Sstevel@tonic-gate ** Parameters: 18087c478bd9Sstevel@tonic-gate ** p -- the options line. 18097c478bd9Sstevel@tonic-gate ** 18107c478bd9Sstevel@tonic-gate ** Returns: 18117c478bd9Sstevel@tonic-gate ** true if successful, false otherwise. 18127c478bd9Sstevel@tonic-gate ** 18137c478bd9Sstevel@tonic-gate ** Side Effects: 18147c478bd9Sstevel@tonic-gate ** increments number of daemons. 18157c478bd9Sstevel@tonic-gate */ 18167c478bd9Sstevel@tonic-gate 18177c478bd9Sstevel@tonic-gate #define DEF_LISTENQUEUE 10 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate struct dflags 18207c478bd9Sstevel@tonic-gate { 18217c478bd9Sstevel@tonic-gate char *d_name; 18227c478bd9Sstevel@tonic-gate int d_flag; 18237c478bd9Sstevel@tonic-gate }; 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate static struct dflags DaemonFlags[] = 18267c478bd9Sstevel@tonic-gate { 18277c478bd9Sstevel@tonic-gate { "AUTHREQ", D_AUTHREQ }, 18287c478bd9Sstevel@tonic-gate { "BINDIF", D_BINDIF }, 18297c478bd9Sstevel@tonic-gate { "CANONREQ", D_CANONREQ }, 18307c478bd9Sstevel@tonic-gate { "IFNHELO", D_IFNHELO }, 18317c478bd9Sstevel@tonic-gate { "FQMAIL", D_FQMAIL }, 18327c478bd9Sstevel@tonic-gate { "FQRCPT", D_FQRCPT }, 18337c478bd9Sstevel@tonic-gate { "SMTPS", D_SMTPS }, 18347c478bd9Sstevel@tonic-gate { "UNQUALOK", D_UNQUALOK }, 18357c478bd9Sstevel@tonic-gate { "NOAUTH", D_NOAUTH }, 18367c478bd9Sstevel@tonic-gate { "NOCANON", D_NOCANON }, 18377c478bd9Sstevel@tonic-gate { "NOETRN", D_NOETRN }, 18387c478bd9Sstevel@tonic-gate { "NOTLS", D_NOTLS }, 18397c478bd9Sstevel@tonic-gate { "ETRNONLY", D_ETRNONLY }, 18407c478bd9Sstevel@tonic-gate { "OPTIONAL", D_OPTIONAL }, 18417c478bd9Sstevel@tonic-gate { "DISABLE", D_DISABLE }, 18427c478bd9Sstevel@tonic-gate { "ISSET", D_ISSET }, 18437c478bd9Sstevel@tonic-gate { NULL, 0 } 18447c478bd9Sstevel@tonic-gate }; 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate static void 18477c478bd9Sstevel@tonic-gate printdaemonflags(d) 18487c478bd9Sstevel@tonic-gate DAEMON_T *d; 18497c478bd9Sstevel@tonic-gate { 18507c478bd9Sstevel@tonic-gate register struct dflags *df; 18517c478bd9Sstevel@tonic-gate bool first = true; 18527c478bd9Sstevel@tonic-gate 18537c478bd9Sstevel@tonic-gate for (df = DaemonFlags; df->d_name != NULL; df++) 18547c478bd9Sstevel@tonic-gate { 18557c478bd9Sstevel@tonic-gate if (!bitnset(df->d_flag, d->d_flags)) 18567c478bd9Sstevel@tonic-gate continue; 18577c478bd9Sstevel@tonic-gate if (first) 18587c478bd9Sstevel@tonic-gate sm_dprintf("<%s", df->d_name); 18597c478bd9Sstevel@tonic-gate else 18607c478bd9Sstevel@tonic-gate sm_dprintf(",%s", df->d_name); 18617c478bd9Sstevel@tonic-gate first = false; 18627c478bd9Sstevel@tonic-gate } 18637c478bd9Sstevel@tonic-gate if (!first) 18647c478bd9Sstevel@tonic-gate sm_dprintf(">"); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate bool 18687c478bd9Sstevel@tonic-gate setdaemonoptions(p) 18697c478bd9Sstevel@tonic-gate register char *p; 18707c478bd9Sstevel@tonic-gate { 18717c478bd9Sstevel@tonic-gate if (NDaemons >= MAXDAEMONS) 18727c478bd9Sstevel@tonic-gate return false; 18737c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 18747c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 18757c478bd9Sstevel@tonic-gate clrbitmap(Daemons[NDaemons].d_flags); 18767c478bd9Sstevel@tonic-gate setsockaddroptions(p, &Daemons[NDaemons]); 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate #if MILTER 18797c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_inputfilterlist != NULL) 18807c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist); 18817c478bd9Sstevel@tonic-gate #endif /* MILTER */ 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_name != NULL) 18847c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name); 18857c478bd9Sstevel@tonic-gate else 18867c478bd9Sstevel@tonic-gate { 18877c478bd9Sstevel@tonic-gate char num[30]; 18887c478bd9Sstevel@tonic-gate 1889058561cbSjbeck (void) sm_snprintf(num, sizeof(num), "Daemon%d", NDaemons); 18907c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(num); 18917c478bd9Sstevel@tonic-gate } 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate if (tTd(37, 1)) 18947c478bd9Sstevel@tonic-gate { 18957c478bd9Sstevel@tonic-gate sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name); 18967c478bd9Sstevel@tonic-gate printdaemonflags(&Daemons[NDaemons]); 18977c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate ++NDaemons; 19007c478bd9Sstevel@tonic-gate return true; 19017c478bd9Sstevel@tonic-gate } 19027c478bd9Sstevel@tonic-gate /* 19037c478bd9Sstevel@tonic-gate ** INITDAEMON -- initialize daemon if not yet done. 19047c478bd9Sstevel@tonic-gate ** 19057c478bd9Sstevel@tonic-gate ** Parameters: 19067c478bd9Sstevel@tonic-gate ** none 19077c478bd9Sstevel@tonic-gate ** 19087c478bd9Sstevel@tonic-gate ** Returns: 19097c478bd9Sstevel@tonic-gate ** none 19107c478bd9Sstevel@tonic-gate ** 19117c478bd9Sstevel@tonic-gate ** Side Effects: 19127c478bd9Sstevel@tonic-gate ** initializes structure for one daemon. 19137c478bd9Sstevel@tonic-gate */ 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate void 19167c478bd9Sstevel@tonic-gate initdaemon() 19177c478bd9Sstevel@tonic-gate { 19187c478bd9Sstevel@tonic-gate if (NDaemons == 0) 19197c478bd9Sstevel@tonic-gate { 19207c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 19217c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 19227c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = "Daemon0"; 19237c478bd9Sstevel@tonic-gate NDaemons = 1; 19247c478bd9Sstevel@tonic-gate } 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate /* 19277c478bd9Sstevel@tonic-gate ** SETCLIENTOPTIONS -- set options for running the client 19287c478bd9Sstevel@tonic-gate ** 19297c478bd9Sstevel@tonic-gate ** Parameters: 19307c478bd9Sstevel@tonic-gate ** p -- the options line. 19317c478bd9Sstevel@tonic-gate ** 19327c478bd9Sstevel@tonic-gate ** Returns: 19337c478bd9Sstevel@tonic-gate ** none. 19347c478bd9Sstevel@tonic-gate */ 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate static DAEMON_T ClientSettings[AF_MAX + 1]; 19377c478bd9Sstevel@tonic-gate 19387c478bd9Sstevel@tonic-gate void 19397c478bd9Sstevel@tonic-gate setclientoptions(p) 19407c478bd9Sstevel@tonic-gate register char *p; 19417c478bd9Sstevel@tonic-gate { 19427c478bd9Sstevel@tonic-gate int family; 19437c478bd9Sstevel@tonic-gate DAEMON_T d; 19447c478bd9Sstevel@tonic-gate 1945058561cbSjbeck memset(&d, '\0', sizeof(d)); 19467c478bd9Sstevel@tonic-gate setsockaddroptions(p, &d); 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate /* grab what we need */ 19497c478bd9Sstevel@tonic-gate family = d.d_addr.sa.sa_family; 19507c478bd9Sstevel@tonic-gate STRUCTCOPY(d, ClientSettings[family]); 19517c478bd9Sstevel@tonic-gate setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */ 19527c478bd9Sstevel@tonic-gate if (d.d_name != NULL) 19537c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(d.d_name); 19547c478bd9Sstevel@tonic-gate else 19557c478bd9Sstevel@tonic-gate { 19567c478bd9Sstevel@tonic-gate char num[30]; 19577c478bd9Sstevel@tonic-gate 1958058561cbSjbeck (void) sm_snprintf(num, sizeof(num), "Client%d", family); 19597c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(num); 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate /* 19637c478bd9Sstevel@tonic-gate ** ADDR_FAMILY -- determine address family from address 19647c478bd9Sstevel@tonic-gate ** 19657c478bd9Sstevel@tonic-gate ** Parameters: 19667c478bd9Sstevel@tonic-gate ** addr -- the string representation of the address 19677c478bd9Sstevel@tonic-gate ** 19687c478bd9Sstevel@tonic-gate ** Returns: 19697c478bd9Sstevel@tonic-gate ** AF_INET, AF_INET6 or AF_UNSPEC 19707c478bd9Sstevel@tonic-gate ** 19717c478bd9Sstevel@tonic-gate ** Side Effects: 19727c478bd9Sstevel@tonic-gate ** none. 19737c478bd9Sstevel@tonic-gate */ 19747c478bd9Sstevel@tonic-gate 19757c478bd9Sstevel@tonic-gate static int 19767c478bd9Sstevel@tonic-gate addr_family(addr) 19777c478bd9Sstevel@tonic-gate char *addr; 19787c478bd9Sstevel@tonic-gate { 19797c478bd9Sstevel@tonic-gate #if NETINET6 19807c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 19817c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate #if NETINET 19847c478bd9Sstevel@tonic-gate if (inet_addr(addr) != INADDR_NONE) 19857c478bd9Sstevel@tonic-gate { 19867c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19877c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET\n", addr); 19887c478bd9Sstevel@tonic-gate return AF_INET; 19897c478bd9Sstevel@tonic-gate } 19907c478bd9Sstevel@tonic-gate #endif /* NETINET */ 19917c478bd9Sstevel@tonic-gate #if NETINET6 19927c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 19937c478bd9Sstevel@tonic-gate { 19947c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19957c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET6\n", addr); 19967c478bd9Sstevel@tonic-gate return AF_INET6; 19977c478bd9Sstevel@tonic-gate } 19987c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 19997c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 20007c478bd9Sstevel@tonic-gate # if NETUNIX 20017c478bd9Sstevel@tonic-gate if (*addr == '/') 20027c478bd9Sstevel@tonic-gate { 20037c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 20047c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): LOCAL\n", addr); 20057c478bd9Sstevel@tonic-gate return AF_UNIX; 20067c478bd9Sstevel@tonic-gate } 20077c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 20087c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 20097c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 20107c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): UNSPEC\n", addr); 20117c478bd9Sstevel@tonic-gate return AF_UNSPEC; 20127c478bd9Sstevel@tonic-gate } 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate /* 20157c478bd9Sstevel@tonic-gate ** CHKCLIENTMODIFIERS -- check whether all clients have set a flag. 20167c478bd9Sstevel@tonic-gate ** 20177c478bd9Sstevel@tonic-gate ** Parameters: 20187c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 20197c478bd9Sstevel@tonic-gate ** 20207c478bd9Sstevel@tonic-gate ** Returns: 20217c478bd9Sstevel@tonic-gate ** true iff all configured clients have set the flag. 20227c478bd9Sstevel@tonic-gate */ 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate bool 20257c478bd9Sstevel@tonic-gate chkclientmodifiers(flag) 20267c478bd9Sstevel@tonic-gate int flag; 20277c478bd9Sstevel@tonic-gate { 20287c478bd9Sstevel@tonic-gate int i; 20297c478bd9Sstevel@tonic-gate bool flagisset; 20307c478bd9Sstevel@tonic-gate 20317c478bd9Sstevel@tonic-gate flagisset = false; 20327c478bd9Sstevel@tonic-gate for (i = 0; i < AF_MAX; i++) 20337c478bd9Sstevel@tonic-gate { 20347c478bd9Sstevel@tonic-gate if (bitnset(D_ISSET, ClientSettings[i].d_flags)) 20357c478bd9Sstevel@tonic-gate { 20367c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, ClientSettings[i].d_flags)) 20377c478bd9Sstevel@tonic-gate return false; 20387c478bd9Sstevel@tonic-gate flagisset = true; 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate } 20417c478bd9Sstevel@tonic-gate return flagisset; 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate #if MILTER 20457c478bd9Sstevel@tonic-gate /* 20467c478bd9Sstevel@tonic-gate ** SETUP_DAEMON_FILTERS -- Parse per-socket filters 20477c478bd9Sstevel@tonic-gate ** 20487c478bd9Sstevel@tonic-gate ** Parameters: 20497c478bd9Sstevel@tonic-gate ** none 20507c478bd9Sstevel@tonic-gate ** 20517c478bd9Sstevel@tonic-gate ** Returns: 20527c478bd9Sstevel@tonic-gate ** none 20537c478bd9Sstevel@tonic-gate */ 20547c478bd9Sstevel@tonic-gate 20557c478bd9Sstevel@tonic-gate void 20567c478bd9Sstevel@tonic-gate setup_daemon_milters() 20577c478bd9Sstevel@tonic-gate { 20587c478bd9Sstevel@tonic-gate int idx; 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP) 20617c478bd9Sstevel@tonic-gate { 20627c478bd9Sstevel@tonic-gate /* no need to configure the daemons */ 20637c478bd9Sstevel@tonic-gate return; 20647c478bd9Sstevel@tonic-gate } 20657c478bd9Sstevel@tonic-gate 20667c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 20677c478bd9Sstevel@tonic-gate { 20687c478bd9Sstevel@tonic-gate if (Daemons[idx].d_inputfilterlist != NULL) 20697c478bd9Sstevel@tonic-gate { 20707c478bd9Sstevel@tonic-gate milter_config(Daemons[idx].d_inputfilterlist, 20717c478bd9Sstevel@tonic-gate Daemons[idx].d_inputfilters, 20727c478bd9Sstevel@tonic-gate MAXFILTERS); 20737c478bd9Sstevel@tonic-gate } 20747c478bd9Sstevel@tonic-gate } 20757c478bd9Sstevel@tonic-gate } 20767c478bd9Sstevel@tonic-gate #endif /* MILTER */ 20777c478bd9Sstevel@tonic-gate /* 20787c478bd9Sstevel@tonic-gate ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 20797c478bd9Sstevel@tonic-gate ** 20807c478bd9Sstevel@tonic-gate ** Parameters: 20817c478bd9Sstevel@tonic-gate ** host -- the name of the host. 20827c478bd9Sstevel@tonic-gate ** port -- the port number to connect to. 20837c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 20847c478bd9Sstevel@tonic-gate ** structure to be filled in. 20857c478bd9Sstevel@tonic-gate ** e -- the current envelope. 20867c478bd9Sstevel@tonic-gate ** enough -- time at which to stop further connection attempts. 20877c478bd9Sstevel@tonic-gate ** (0 means no limit) 20887c478bd9Sstevel@tonic-gate ** 20897c478bd9Sstevel@tonic-gate ** Returns: 20907c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 20917c478bd9Sstevel@tonic-gate ** made and if not why not. 20927c478bd9Sstevel@tonic-gate ** 20937c478bd9Sstevel@tonic-gate ** Side Effects: 20947c478bd9Sstevel@tonic-gate ** none. 20957c478bd9Sstevel@tonic-gate */ 20967c478bd9Sstevel@tonic-gate 20977c478bd9Sstevel@tonic-gate static jmp_buf CtxConnectTimeout; 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate SOCKADDR CurHostAddr; /* address of current host */ 21007c478bd9Sstevel@tonic-gate 21017c478bd9Sstevel@tonic-gate int 21027c478bd9Sstevel@tonic-gate makeconnection(host, port, mci, e, enough) 21037c478bd9Sstevel@tonic-gate char *host; 21047c478bd9Sstevel@tonic-gate volatile unsigned int port; 21057c478bd9Sstevel@tonic-gate register MCI *mci; 21067c478bd9Sstevel@tonic-gate ENVELOPE *e; 21077c478bd9Sstevel@tonic-gate time_t enough; 21087c478bd9Sstevel@tonic-gate { 21097c478bd9Sstevel@tonic-gate register volatile int addrno = 0; 21107c478bd9Sstevel@tonic-gate volatile int s; 21117c478bd9Sstevel@tonic-gate register struct hostent *volatile hp = (struct hostent *) NULL; 21127c478bd9Sstevel@tonic-gate SOCKADDR addr; 21137c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 21147c478bd9Sstevel@tonic-gate int save_errno = 0; 21157c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T addrlen; 21163ee0e492Sjbeck volatile bool firstconnect = true; 21177c478bd9Sstevel@tonic-gate SM_EVENT *volatile ev = NULL; 21187c478bd9Sstevel@tonic-gate #if NETINET6 21197c478bd9Sstevel@tonic-gate volatile bool v6found = false; 21207c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21217c478bd9Sstevel@tonic-gate volatile int family = InetMode; 21227c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T len; 21237c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T socksize = 0; 21247c478bd9Sstevel@tonic-gate volatile bool clt_bind; 21257c478bd9Sstevel@tonic-gate BITMAP256 d_flags; 21267c478bd9Sstevel@tonic-gate char *p; 21277c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 21287c478bd9Sstevel@tonic-gate 21297c478bd9Sstevel@tonic-gate /* retranslate {daemon_flags} into bitmap */ 21307c478bd9Sstevel@tonic-gate clrbitmap(d_flags); 21317c478bd9Sstevel@tonic-gate if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL) 21327c478bd9Sstevel@tonic-gate { 21337c478bd9Sstevel@tonic-gate for (; *p != '\0'; p++) 21347c478bd9Sstevel@tonic-gate { 21357c478bd9Sstevel@tonic-gate if (!(isascii(*p) && isspace(*p))) 21367c478bd9Sstevel@tonic-gate setbitn(bitidx(*p), d_flags); 21377c478bd9Sstevel@tonic-gate } 21387c478bd9Sstevel@tonic-gate } 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate #if NETINET6 21417c478bd9Sstevel@tonic-gate v4retry: 21427c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21437c478bd9Sstevel@tonic-gate clt_bind = false; 21447c478bd9Sstevel@tonic-gate 21457c478bd9Sstevel@tonic-gate /* Set up the address for outgoing connection. */ 21467c478bd9Sstevel@tonic-gate if (bitnset(D_BINDIF, d_flags) && 21477c478bd9Sstevel@tonic-gate (p = macvalue(macid("{if_addr}"), e)) != NULL && 21487c478bd9Sstevel@tonic-gate *p != '\0') 21497c478bd9Sstevel@tonic-gate { 21507c478bd9Sstevel@tonic-gate #if NETINET6 21517c478bd9Sstevel@tonic-gate char p6[INET6_ADDRSTRLEN]; 21527c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21537c478bd9Sstevel@tonic-gate 2154058561cbSjbeck memset(&clt_addr, '\0', sizeof(clt_addr)); 21557c478bd9Sstevel@tonic-gate 21567c478bd9Sstevel@tonic-gate /* infer the address family from the address itself */ 21577c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family = addr_family(p); 21587c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 21597c478bd9Sstevel@tonic-gate { 21607c478bd9Sstevel@tonic-gate #if NETINET 21617c478bd9Sstevel@tonic-gate case AF_INET: 21627c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr = inet_addr(p); 21637c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 2164*e9af4bc0SJohn Beck clt_addr.sin.sin_addr.s_addr != 2165*e9af4bc0SJohn Beck htonl(INADDR_LOOPBACK)) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate clt_bind = true; 2168058561cbSjbeck socksize = sizeof(struct sockaddr_in); 21697c478bd9Sstevel@tonic-gate } 21707c478bd9Sstevel@tonic-gate break; 21717c478bd9Sstevel@tonic-gate #endif /* NETINET */ 21727c478bd9Sstevel@tonic-gate 21737c478bd9Sstevel@tonic-gate #if NETINET6 21747c478bd9Sstevel@tonic-gate case AF_INET6: 21757c478bd9Sstevel@tonic-gate if (inet_addr(p) != INADDR_NONE) 2176058561cbSjbeck (void) sm_snprintf(p6, sizeof(p6), 21777c478bd9Sstevel@tonic-gate "IPv6:::ffff:%s", p); 21787c478bd9Sstevel@tonic-gate else 2179058561cbSjbeck (void) sm_strlcpy(p6, p, sizeof(p6)); 21807c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, p6, 21817c478bd9Sstevel@tonic-gate &clt_addr.sin6.sin6_addr) == 1 && 21827c478bd9Sstevel@tonic-gate !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 21837c478bd9Sstevel@tonic-gate { 21847c478bd9Sstevel@tonic-gate clt_bind = true; 2185058561cbSjbeck socksize = sizeof(struct sockaddr_in6); 21867c478bd9Sstevel@tonic-gate } 21877c478bd9Sstevel@tonic-gate break; 21887c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate #if 0 21917c478bd9Sstevel@tonic-gate default: 21927c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Address= option unsupported for family %d", 21937c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family); 21947c478bd9Sstevel@tonic-gate break; 21957c478bd9Sstevel@tonic-gate #endif /* 0 */ 21967c478bd9Sstevel@tonic-gate } 21977c478bd9Sstevel@tonic-gate if (clt_bind) 21987c478bd9Sstevel@tonic-gate family = clt_addr.sa.sa_family; 21997c478bd9Sstevel@tonic-gate } 22007c478bd9Sstevel@tonic-gate 22017c478bd9Sstevel@tonic-gate /* D_BINDIF not set or not available, fallback to ClientPortOptions */ 22027c478bd9Sstevel@tonic-gate if (!clt_bind) 22037c478bd9Sstevel@tonic-gate { 22047c478bd9Sstevel@tonic-gate STRUCTCOPY(ClientSettings[family].d_addr, clt_addr); 22057c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 22067c478bd9Sstevel@tonic-gate { 22077c478bd9Sstevel@tonic-gate #if NETINET 22087c478bd9Sstevel@tonic-gate case AF_INET: 22097c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr == 0) 2210d4660949Sjbeck clt_addr.sin.sin_addr.s_addr = LocalDaemon ? 2211d4660949Sjbeck htonl(INADDR_LOOPBACK) : INADDR_ANY; 22127c478bd9Sstevel@tonic-gate else 22137c478bd9Sstevel@tonic-gate clt_bind = true; 22147c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 22157c478bd9Sstevel@tonic-gate clt_bind = true; 2216058561cbSjbeck socksize = sizeof(struct sockaddr_in); 22177c478bd9Sstevel@tonic-gate break; 22187c478bd9Sstevel@tonic-gate #endif /* NETINET */ 22197c478bd9Sstevel@tonic-gate #if NETINET6 22207c478bd9Sstevel@tonic-gate case AF_INET6: 22217c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 2222d4660949Sjbeck clt_addr.sin6.sin6_addr = LocalDaemon ? 2223d4660949Sjbeck in6addr_loopback : in6addr_any; 22247c478bd9Sstevel@tonic-gate else 22257c478bd9Sstevel@tonic-gate clt_bind = true; 2226058561cbSjbeck socksize = sizeof(struct sockaddr_in6); 22277c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 22287c478bd9Sstevel@tonic-gate clt_bind = true; 22297c478bd9Sstevel@tonic-gate break; 22307c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22317c478bd9Sstevel@tonic-gate #if NETISO 22327c478bd9Sstevel@tonic-gate case AF_ISO: 2233058561cbSjbeck socksize = sizeof(clt_addr.siso); 22347c478bd9Sstevel@tonic-gate clt_bind = true; 22357c478bd9Sstevel@tonic-gate break; 22367c478bd9Sstevel@tonic-gate #endif /* NETISO */ 22377c478bd9Sstevel@tonic-gate default: 22387c478bd9Sstevel@tonic-gate break; 22397c478bd9Sstevel@tonic-gate } 22407c478bd9Sstevel@tonic-gate } 22417c478bd9Sstevel@tonic-gate 22427c478bd9Sstevel@tonic-gate /* 22437c478bd9Sstevel@tonic-gate ** Set up the address for the mailer. 22447c478bd9Sstevel@tonic-gate ** Accept "[a.b.c.d]" syntax for host name. 22457c478bd9Sstevel@tonic-gate */ 22467c478bd9Sstevel@tonic-gate 22477c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(0); 22487c478bd9Sstevel@tonic-gate errno = 0; 2249058561cbSjbeck memset(&CurHostAddr, '\0', sizeof(CurHostAddr)); 2250058561cbSjbeck memset(&addr, '\0', sizeof(addr)); 22517c478bd9Sstevel@tonic-gate SmtpPhase = mci->mci_phase = "initial connection"; 22527c478bd9Sstevel@tonic-gate CurHostName = host; 22537c478bd9Sstevel@tonic-gate 22547c478bd9Sstevel@tonic-gate if (host[0] == '[') 22557c478bd9Sstevel@tonic-gate { 22567c478bd9Sstevel@tonic-gate p = strchr(host, ']'); 22577c478bd9Sstevel@tonic-gate if (p != NULL) 22587c478bd9Sstevel@tonic-gate { 22597c478bd9Sstevel@tonic-gate #if NETINET 22607c478bd9Sstevel@tonic-gate unsigned long hid = INADDR_NONE; 22617c478bd9Sstevel@tonic-gate #endif /* NETINET */ 22627c478bd9Sstevel@tonic-gate #if NETINET6 22637c478bd9Sstevel@tonic-gate struct sockaddr_in6 hid6; 22647c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22657c478bd9Sstevel@tonic-gate 22667c478bd9Sstevel@tonic-gate *p = '\0'; 22677c478bd9Sstevel@tonic-gate #if NETINET6 2268058561cbSjbeck memset(&hid6, '\0', sizeof(hid6)); 22697c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22707c478bd9Sstevel@tonic-gate #if NETINET 22717c478bd9Sstevel@tonic-gate if (family == AF_INET && 22727c478bd9Sstevel@tonic-gate (hid = inet_addr(&host[1])) != INADDR_NONE) 22737c478bd9Sstevel@tonic-gate { 22747c478bd9Sstevel@tonic-gate addr.sin.sin_family = AF_INET; 22757c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = hid; 22767c478bd9Sstevel@tonic-gate } 22777c478bd9Sstevel@tonic-gate else 22787c478bd9Sstevel@tonic-gate #endif /* NETINET */ 22797c478bd9Sstevel@tonic-gate #if NETINET6 22807c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 22817c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &host[1], 22827c478bd9Sstevel@tonic-gate &hid6.sin6_addr) == 1) 22837c478bd9Sstevel@tonic-gate { 22847c478bd9Sstevel@tonic-gate addr.sin6.sin6_family = AF_INET6; 22857c478bd9Sstevel@tonic-gate addr.sin6.sin6_addr = hid6.sin6_addr; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate else 22887c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22897c478bd9Sstevel@tonic-gate { 22907c478bd9Sstevel@tonic-gate /* try it as a host name (avoid MX lookup) */ 22917c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], family); 22927c478bd9Sstevel@tonic-gate if (hp == NULL && p[-1] == '.') 22937c478bd9Sstevel@tonic-gate { 22947c478bd9Sstevel@tonic-gate #if NAMED_BIND 22957c478bd9Sstevel@tonic-gate int oldopts = _res.options; 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 22987c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 22997c478bd9Sstevel@tonic-gate p[-1] = '\0'; 23007c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], 23017c478bd9Sstevel@tonic-gate family); 23027c478bd9Sstevel@tonic-gate p[-1] = '.'; 23037c478bd9Sstevel@tonic-gate #if NAMED_BIND 23047c478bd9Sstevel@tonic-gate _res.options = oldopts; 23057c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate *p = ']'; 23087c478bd9Sstevel@tonic-gate goto gothostent; 23097c478bd9Sstevel@tonic-gate } 23107c478bd9Sstevel@tonic-gate *p = ']'; 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate if (p == NULL) 23137c478bd9Sstevel@tonic-gate { 23147c478bd9Sstevel@tonic-gate extern char MsgBuf[]; 23157c478bd9Sstevel@tonic-gate 23167c478bd9Sstevel@tonic-gate usrerrenh("5.1.2", 23177c478bd9Sstevel@tonic-gate "553 Invalid numeric domain spec \"%s\"", 23187c478bd9Sstevel@tonic-gate host); 23197c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 23207c478bd9Sstevel@tonic-gate errno = EINVAL; 23217c478bd9Sstevel@tonic-gate return EX_NOHOST; 23227c478bd9Sstevel@tonic-gate } 23237c478bd9Sstevel@tonic-gate } 23247c478bd9Sstevel@tonic-gate else 23257c478bd9Sstevel@tonic-gate { 23267c478bd9Sstevel@tonic-gate /* contortion to get around SGI cc complaints */ 23277c478bd9Sstevel@tonic-gate { 23287c478bd9Sstevel@tonic-gate p = &host[strlen(host) - 1]; 23297c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 23307c478bd9Sstevel@tonic-gate if (hp == NULL && *p == '.') 23317c478bd9Sstevel@tonic-gate { 23327c478bd9Sstevel@tonic-gate #if NAMED_BIND 23337c478bd9Sstevel@tonic-gate int oldopts = _res.options; 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 23367c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23377c478bd9Sstevel@tonic-gate *p = '\0'; 23387c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 23397c478bd9Sstevel@tonic-gate *p = '.'; 23407c478bd9Sstevel@tonic-gate #if NAMED_BIND 23417c478bd9Sstevel@tonic-gate _res.options = oldopts; 23427c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23437c478bd9Sstevel@tonic-gate } 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate gothostent: 2346*e9af4bc0SJohn Beck if (hp == NULL || hp->h_addr == NULL) 23477c478bd9Sstevel@tonic-gate { 23487c478bd9Sstevel@tonic-gate #if NAMED_BIND 23497c478bd9Sstevel@tonic-gate /* check for name server timeouts */ 23507c478bd9Sstevel@tonic-gate # if NETINET6 23517c478bd9Sstevel@tonic-gate if (WorkAroundBrokenAAAA && family == AF_INET6 && 23527c478bd9Sstevel@tonic-gate errno == ETIMEDOUT) 23537c478bd9Sstevel@tonic-gate { 23547c478bd9Sstevel@tonic-gate /* 23557c478bd9Sstevel@tonic-gate ** An attempt with family AF_INET may 23567c478bd9Sstevel@tonic-gate ** succeed By skipping the next section 23577c478bd9Sstevel@tonic-gate ** of code, we will try AF_INET before 23587c478bd9Sstevel@tonic-gate ** failing. 23597c478bd9Sstevel@tonic-gate */ 23607c478bd9Sstevel@tonic-gate 23617c478bd9Sstevel@tonic-gate if (tTd(16, 10)) 23627c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n"); 23637c478bd9Sstevel@tonic-gate } 23647c478bd9Sstevel@tonic-gate else 23657c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 23667c478bd9Sstevel@tonic-gate { 23677c478bd9Sstevel@tonic-gate if (errno == ETIMEDOUT || 2368058561cbSjbeck # if _FFR_GETHBN_ExFILE 2369058561cbSjbeck # ifdef EMFILE 2370058561cbSjbeck errno == EMFILE || 2371058561cbSjbeck # endif /* EMFILE */ 2372058561cbSjbeck # ifdef ENFILE 2373058561cbSjbeck errno == ENFILE || 2374058561cbSjbeck # endif /* ENFILE */ 2375058561cbSjbeck # endif /* _FFR_GETHBN_ExFILE */ 23767c478bd9Sstevel@tonic-gate h_errno == TRY_AGAIN || 23777c478bd9Sstevel@tonic-gate (errno == ECONNREFUSED && UseNameServer)) 23787c478bd9Sstevel@tonic-gate { 23797c478bd9Sstevel@tonic-gate save_errno = errno; 23807c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, 23817c478bd9Sstevel@tonic-gate "4.4.3", NULL); 23827c478bd9Sstevel@tonic-gate errno = save_errno; 23837c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 23847c478bd9Sstevel@tonic-gate } 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23877c478bd9Sstevel@tonic-gate #if NETINET6 23887c478bd9Sstevel@tonic-gate /* 23897c478bd9Sstevel@tonic-gate ** Try v6 first, then fall back to v4. 23907c478bd9Sstevel@tonic-gate ** If we found a v6 address, but no v4 23917c478bd9Sstevel@tonic-gate ** addresses, then TEMPFAIL. 23927c478bd9Sstevel@tonic-gate */ 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate if (family == AF_INET6) 23957c478bd9Sstevel@tonic-gate { 23967c478bd9Sstevel@tonic-gate family = AF_INET; 23977c478bd9Sstevel@tonic-gate goto v4retry; 23987c478bd9Sstevel@tonic-gate } 23997c478bd9Sstevel@tonic-gate if (v6found) 24007c478bd9Sstevel@tonic-gate goto v6tempfail; 24017c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24027c478bd9Sstevel@tonic-gate save_errno = errno; 24037c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 24047c478bd9Sstevel@tonic-gate errno = save_errno; 24057c478bd9Sstevel@tonic-gate return EX_NOHOST; 24067c478bd9Sstevel@tonic-gate } 24077c478bd9Sstevel@tonic-gate addr.sa.sa_family = hp->h_addrtype; 24087c478bd9Sstevel@tonic-gate switch (hp->h_addrtype) 24097c478bd9Sstevel@tonic-gate { 24107c478bd9Sstevel@tonic-gate #if NETINET 24117c478bd9Sstevel@tonic-gate case AF_INET: 24127c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 24137c478bd9Sstevel@tonic-gate hp->h_addr, 24147c478bd9Sstevel@tonic-gate INADDRSZ); 24157c478bd9Sstevel@tonic-gate break; 24167c478bd9Sstevel@tonic-gate #endif /* NETINET */ 24177c478bd9Sstevel@tonic-gate 24187c478bd9Sstevel@tonic-gate #if NETINET6 24197c478bd9Sstevel@tonic-gate case AF_INET6: 24207c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 24217c478bd9Sstevel@tonic-gate hp->h_addr, 24227c478bd9Sstevel@tonic-gate IN6ADDRSZ); 24237c478bd9Sstevel@tonic-gate break; 24247c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24257c478bd9Sstevel@tonic-gate 24267c478bd9Sstevel@tonic-gate default: 2427058561cbSjbeck if (hp->h_length > sizeof(addr.sa.sa_data)) 24287c478bd9Sstevel@tonic-gate { 24297c478bd9Sstevel@tonic-gate syserr("makeconnection: long sa_data: family %d len %d", 24307c478bd9Sstevel@tonic-gate hp->h_addrtype, hp->h_length); 24317c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 24327c478bd9Sstevel@tonic-gate errno = EINVAL; 24337c478bd9Sstevel@tonic-gate return EX_NOHOST; 24347c478bd9Sstevel@tonic-gate } 24357c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, hp->h_addr, hp->h_length); 24367c478bd9Sstevel@tonic-gate break; 24377c478bd9Sstevel@tonic-gate } 24387c478bd9Sstevel@tonic-gate addrno = 1; 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate /* 24427c478bd9Sstevel@tonic-gate ** Determine the port number. 24437c478bd9Sstevel@tonic-gate */ 24447c478bd9Sstevel@tonic-gate 24457c478bd9Sstevel@tonic-gate if (port == 0) 24467c478bd9Sstevel@tonic-gate { 24477c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 24487c478bd9Sstevel@tonic-gate port = htons(25); 24497c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 24507c478bd9Sstevel@tonic-gate register struct servent *sp = getservbyname("smtp", "tcp"); 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate if (sp == NULL) 24537c478bd9Sstevel@tonic-gate { 24547c478bd9Sstevel@tonic-gate if (LogLevel > 2) 24557c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 24567c478bd9Sstevel@tonic-gate "makeconnection: service \"smtp\" unknown"); 24577c478bd9Sstevel@tonic-gate port = htons(25); 24587c478bd9Sstevel@tonic-gate } 24597c478bd9Sstevel@tonic-gate else 24607c478bd9Sstevel@tonic-gate port = sp->s_port; 24617c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 24627c478bd9Sstevel@tonic-gate } 24637c478bd9Sstevel@tonic-gate 24647c478bd9Sstevel@tonic-gate #if NETINET6 24657c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_INET6 && 24667c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) && 24677c478bd9Sstevel@tonic-gate ClientSettings[AF_INET].d_addr.sa.sa_family != 0) 24687c478bd9Sstevel@tonic-gate { 24697c478bd9Sstevel@tonic-gate /* 24707c478bd9Sstevel@tonic-gate ** Ignore mapped IPv4 address since 24717c478bd9Sstevel@tonic-gate ** there is a ClientPortOptions setting 24727c478bd9Sstevel@tonic-gate ** for IPv4. 24737c478bd9Sstevel@tonic-gate */ 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate goto nextaddr; 24767c478bd9Sstevel@tonic-gate } 24777c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24787c478bd9Sstevel@tonic-gate 24797c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 24807c478bd9Sstevel@tonic-gate { 24817c478bd9Sstevel@tonic-gate #if NETINET 24827c478bd9Sstevel@tonic-gate case AF_INET: 24837c478bd9Sstevel@tonic-gate addr.sin.sin_port = port; 2484058561cbSjbeck addrlen = sizeof(struct sockaddr_in); 24857c478bd9Sstevel@tonic-gate break; 24867c478bd9Sstevel@tonic-gate #endif /* NETINET */ 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate #if NETINET6 24897c478bd9Sstevel@tonic-gate case AF_INET6: 24907c478bd9Sstevel@tonic-gate addr.sin6.sin6_port = port; 2491058561cbSjbeck addrlen = sizeof(struct sockaddr_in6); 24927c478bd9Sstevel@tonic-gate break; 24937c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24947c478bd9Sstevel@tonic-gate 24957c478bd9Sstevel@tonic-gate #if NETISO 24967c478bd9Sstevel@tonic-gate case AF_ISO: 24977c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 24987c478bd9Sstevel@tonic-gate memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 2499058561cbSjbeck addrlen = sizeof(struct sockaddr_iso); 25007c478bd9Sstevel@tonic-gate break; 25017c478bd9Sstevel@tonic-gate #endif /* NETISO */ 25027c478bd9Sstevel@tonic-gate 25037c478bd9Sstevel@tonic-gate default: 25047c478bd9Sstevel@tonic-gate syserr("Can't connect to address family %d", addr.sa.sa_family); 25057c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 25067c478bd9Sstevel@tonic-gate errno = EINVAL; 25077c478bd9Sstevel@tonic-gate #if NETINET6 25087c478bd9Sstevel@tonic-gate if (hp != NULL) 25097c478bd9Sstevel@tonic-gate freehostent(hp); 25107c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 25117c478bd9Sstevel@tonic-gate return EX_NOHOST; 25127c478bd9Sstevel@tonic-gate } 25137c478bd9Sstevel@tonic-gate 25147c478bd9Sstevel@tonic-gate /* 25157c478bd9Sstevel@tonic-gate ** Try to actually open the connection. 25167c478bd9Sstevel@tonic-gate */ 25177c478bd9Sstevel@tonic-gate 25187c478bd9Sstevel@tonic-gate #if XLA 25197c478bd9Sstevel@tonic-gate /* if too many connections, don't bother trying */ 25207c478bd9Sstevel@tonic-gate if (!xla_noqueue_ok(host)) 25217c478bd9Sstevel@tonic-gate { 25227c478bd9Sstevel@tonic-gate # if NETINET6 25237c478bd9Sstevel@tonic-gate if (hp != NULL) 25247c478bd9Sstevel@tonic-gate freehostent(hp); 25257c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 25267c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 25277c478bd9Sstevel@tonic-gate } 25287c478bd9Sstevel@tonic-gate #endif /* XLA */ 25297c478bd9Sstevel@tonic-gate 25307c478bd9Sstevel@tonic-gate for (;;) 25317c478bd9Sstevel@tonic-gate { 25327c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 25337c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection (%s [%s].%d (%d))\n", 25347c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), ntohs(port), 25357c478bd9Sstevel@tonic-gate (int) addr.sa.sa_family); 25367c478bd9Sstevel@tonic-gate 25377c478bd9Sstevel@tonic-gate /* save for logging */ 25387c478bd9Sstevel@tonic-gate CurHostAddr = addr; 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate #if HASRRESVPORT 25417c478bd9Sstevel@tonic-gate if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 25427c478bd9Sstevel@tonic-gate { 25437c478bd9Sstevel@tonic-gate int rport = IPPORT_RESERVED - 1; 25447c478bd9Sstevel@tonic-gate 25457c478bd9Sstevel@tonic-gate s = rresvport(&rport); 25467c478bd9Sstevel@tonic-gate } 25477c478bd9Sstevel@tonic-gate else 25487c478bd9Sstevel@tonic-gate #endif /* HASRRESVPORT */ 25497c478bd9Sstevel@tonic-gate { 25507c478bd9Sstevel@tonic-gate s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 25517c478bd9Sstevel@tonic-gate } 25527c478bd9Sstevel@tonic-gate if (s < 0) 25537c478bd9Sstevel@tonic-gate { 25547c478bd9Sstevel@tonic-gate save_errno = errno; 25557c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot create socket"); 25567c478bd9Sstevel@tonic-gate #if XLA 25577c478bd9Sstevel@tonic-gate xla_host_end(host); 25587c478bd9Sstevel@tonic-gate #endif /* XLA */ 25597c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 25607c478bd9Sstevel@tonic-gate #if NETINET6 25617c478bd9Sstevel@tonic-gate if (hp != NULL) 25627c478bd9Sstevel@tonic-gate freehostent(hp); 25637c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 25647c478bd9Sstevel@tonic-gate errno = save_errno; 25657c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 25667c478bd9Sstevel@tonic-gate } 25677c478bd9Sstevel@tonic-gate 25687c478bd9Sstevel@tonic-gate #ifdef SO_SNDBUF 25697c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcpsndbufsize > 0) 25707c478bd9Sstevel@tonic-gate { 25717c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 25727c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcpsndbufsize, 25737c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0) 25747c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_SNDBUF)"); 25757c478bd9Sstevel@tonic-gate } 25767c478bd9Sstevel@tonic-gate #endif /* SO_SNDBUF */ 25777c478bd9Sstevel@tonic-gate #ifdef SO_RCVBUF 25787c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcprcvbufsize > 0) 25797c478bd9Sstevel@tonic-gate { 25807c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 25817c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcprcvbufsize, 25827c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0) 25837c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_RCVBUF)"); 25847c478bd9Sstevel@tonic-gate } 25857c478bd9Sstevel@tonic-gate #endif /* SO_RCVBUF */ 25867c478bd9Sstevel@tonic-gate 25877c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 25887c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: fd=%d\n", s); 25897c478bd9Sstevel@tonic-gate 25907c478bd9Sstevel@tonic-gate /* turn on network debugging? */ 25917c478bd9Sstevel@tonic-gate if (tTd(16, 101)) 25927c478bd9Sstevel@tonic-gate { 25937c478bd9Sstevel@tonic-gate int on = 1; 25947c478bd9Sstevel@tonic-gate 25957c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2596058561cbSjbeck (char *)&on, sizeof(on)); 25977c478bd9Sstevel@tonic-gate } 25987c478bd9Sstevel@tonic-gate if (e->e_xfp != NULL) /* for debugging */ 25997c478bd9Sstevel@tonic-gate (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 26007c478bd9Sstevel@tonic-gate errno = 0; /* for debugging */ 26017c478bd9Sstevel@tonic-gate 26027c478bd9Sstevel@tonic-gate if (clt_bind) 26037c478bd9Sstevel@tonic-gate { 26047c478bd9Sstevel@tonic-gate int on = 1; 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 26077c478bd9Sstevel@tonic-gate { 26087c478bd9Sstevel@tonic-gate #if NETINET 26097c478bd9Sstevel@tonic-gate case AF_INET: 26107c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 26117c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 26127c478bd9Sstevel@tonic-gate SO_REUSEADDR, 26137c478bd9Sstevel@tonic-gate (char *) &on, 2614058561cbSjbeck sizeof(on)); 26157c478bd9Sstevel@tonic-gate break; 26167c478bd9Sstevel@tonic-gate #endif /* NETINET */ 26177c478bd9Sstevel@tonic-gate 26187c478bd9Sstevel@tonic-gate #if NETINET6 26197c478bd9Sstevel@tonic-gate case AF_INET6: 26207c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 26217c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 26227c478bd9Sstevel@tonic-gate SO_REUSEADDR, 26237c478bd9Sstevel@tonic-gate (char *) &on, 2624058561cbSjbeck sizeof(on)); 26257c478bd9Sstevel@tonic-gate break; 26267c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26277c478bd9Sstevel@tonic-gate } 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate if (bind(s, &clt_addr.sa, socksize) < 0) 26307c478bd9Sstevel@tonic-gate { 26317c478bd9Sstevel@tonic-gate save_errno = errno; 26327c478bd9Sstevel@tonic-gate (void) close(s); 26337c478bd9Sstevel@tonic-gate errno = save_errno; 26347c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot bind socket [%s]", 26357c478bd9Sstevel@tonic-gate anynet_ntoa(&clt_addr)); 26367c478bd9Sstevel@tonic-gate #if NETINET6 26377c478bd9Sstevel@tonic-gate if (hp != NULL) 26387c478bd9Sstevel@tonic-gate freehostent(hp); 26397c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26407c478bd9Sstevel@tonic-gate errno = save_errno; 26417c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 26427c478bd9Sstevel@tonic-gate } 26437c478bd9Sstevel@tonic-gate } 26447c478bd9Sstevel@tonic-gate 26457c478bd9Sstevel@tonic-gate /* 26467c478bd9Sstevel@tonic-gate ** Linux seems to hang in connect for 90 minutes (!!!). 26477c478bd9Sstevel@tonic-gate ** Time out the connect to avoid this problem. 26487c478bd9Sstevel@tonic-gate */ 26497c478bd9Sstevel@tonic-gate 26507c478bd9Sstevel@tonic-gate if (setjmp(CtxConnectTimeout) == 0) 26517c478bd9Sstevel@tonic-gate { 26527c478bd9Sstevel@tonic-gate int i; 26537c478bd9Sstevel@tonic-gate 26547c478bd9Sstevel@tonic-gate if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 26557c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_iconnect, 26567c478bd9Sstevel@tonic-gate connecttimeout, 0); 26577c478bd9Sstevel@tonic-gate else if (TimeOuts.to_connect != 0) 26587c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_connect, 26597c478bd9Sstevel@tonic-gate connecttimeout, 0); 26607c478bd9Sstevel@tonic-gate else 26617c478bd9Sstevel@tonic-gate ev = NULL; 26627c478bd9Sstevel@tonic-gate 26637c478bd9Sstevel@tonic-gate switch (ConnectOnlyTo.sa.sa_family) 26647c478bd9Sstevel@tonic-gate { 26657c478bd9Sstevel@tonic-gate #if NETINET 26667c478bd9Sstevel@tonic-gate case AF_INET: 26677c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 26687c478bd9Sstevel@tonic-gate break; 26697c478bd9Sstevel@tonic-gate #endif /* NETINET */ 26707c478bd9Sstevel@tonic-gate 26717c478bd9Sstevel@tonic-gate #if NETINET6 26727c478bd9Sstevel@tonic-gate case AF_INET6: 26737c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 26747c478bd9Sstevel@tonic-gate &ConnectOnlyTo.sin6.sin6_addr, 26757c478bd9Sstevel@tonic-gate IN6ADDRSZ); 26767c478bd9Sstevel@tonic-gate break; 26777c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26787c478bd9Sstevel@tonic-gate } 26797c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 26807c478bd9Sstevel@tonic-gate sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr)); 26817c478bd9Sstevel@tonic-gate i = connect(s, (struct sockaddr *) &addr, addrlen); 26827c478bd9Sstevel@tonic-gate save_errno = errno; 26837c478bd9Sstevel@tonic-gate if (ev != NULL) 26847c478bd9Sstevel@tonic-gate sm_clrevent(ev); 26857c478bd9Sstevel@tonic-gate if (i >= 0) 26867c478bd9Sstevel@tonic-gate break; 26877c478bd9Sstevel@tonic-gate } 26887c478bd9Sstevel@tonic-gate else 26897c478bd9Sstevel@tonic-gate save_errno = errno; 26907c478bd9Sstevel@tonic-gate 26917c478bd9Sstevel@tonic-gate /* couldn't connect.... figure out why */ 26927c478bd9Sstevel@tonic-gate (void) close(s); 26937c478bd9Sstevel@tonic-gate 26947c478bd9Sstevel@tonic-gate /* if running demand-dialed connection, try again */ 26957c478bd9Sstevel@tonic-gate if (DialDelay > 0 && firstconnect && 26967c478bd9Sstevel@tonic-gate bitnset(M_DIALDELAY, mci->mci_mailer->m_flags)) 26977c478bd9Sstevel@tonic-gate { 26987c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 26997c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying again...\n", 27007c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27017c478bd9Sstevel@tonic-gate firstconnect = false; 27027c478bd9Sstevel@tonic-gate (void) sleep(DialDelay); 27037c478bd9Sstevel@tonic-gate continue; 27047c478bd9Sstevel@tonic-gate } 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate if (LogLevel > 13) 27077c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 27087c478bd9Sstevel@tonic-gate "makeconnection (%s [%s]) failed: %s", 27097c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), 27107c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27117c478bd9Sstevel@tonic-gate 27127c478bd9Sstevel@tonic-gate #if NETINET6 27137c478bd9Sstevel@tonic-gate nextaddr: 27147c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27157c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_addr_list[addrno] != NULL && 27167c478bd9Sstevel@tonic-gate (enough == 0 || curtime() < enough)) 27177c478bd9Sstevel@tonic-gate { 27187c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 27197c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying new address....\n", 27207c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27217c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 27227c478bd9Sstevel@tonic-gate { 27237c478bd9Sstevel@tonic-gate #if NETINET 27247c478bd9Sstevel@tonic-gate case AF_INET: 27257c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 27267c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27277c478bd9Sstevel@tonic-gate INADDRSZ); 27287c478bd9Sstevel@tonic-gate break; 27297c478bd9Sstevel@tonic-gate #endif /* NETINET */ 27307c478bd9Sstevel@tonic-gate 27317c478bd9Sstevel@tonic-gate #if NETINET6 27327c478bd9Sstevel@tonic-gate case AF_INET6: 27337c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 27347c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27357c478bd9Sstevel@tonic-gate IN6ADDRSZ); 27367c478bd9Sstevel@tonic-gate break; 27377c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27387c478bd9Sstevel@tonic-gate 27397c478bd9Sstevel@tonic-gate default: 27407c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, 27417c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27427c478bd9Sstevel@tonic-gate hp->h_length); 27437c478bd9Sstevel@tonic-gate break; 27447c478bd9Sstevel@tonic-gate } 27457c478bd9Sstevel@tonic-gate continue; 27467c478bd9Sstevel@tonic-gate } 27477c478bd9Sstevel@tonic-gate errno = save_errno; 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate #if NETINET6 27507c478bd9Sstevel@tonic-gate if (family == AF_INET6) 27517c478bd9Sstevel@tonic-gate { 27527c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 27537c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); retrying with AF_INET....\n", 27547c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27557c478bd9Sstevel@tonic-gate v6found = true; 27567c478bd9Sstevel@tonic-gate family = AF_INET; 27577c478bd9Sstevel@tonic-gate if (hp != NULL) 27587c478bd9Sstevel@tonic-gate { 27597c478bd9Sstevel@tonic-gate freehostent(hp); 27607c478bd9Sstevel@tonic-gate hp = NULL; 27617c478bd9Sstevel@tonic-gate } 27627c478bd9Sstevel@tonic-gate goto v4retry; 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate v6tempfail: 27657c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27667c478bd9Sstevel@tonic-gate /* couldn't open connection */ 27677c478bd9Sstevel@tonic-gate #if NETINET6 27687c478bd9Sstevel@tonic-gate /* Don't clobber an already saved errno from v4retry */ 27697c478bd9Sstevel@tonic-gate if (errno > 0) 27707c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27717c478bd9Sstevel@tonic-gate save_errno = errno; 27727c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 27737c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s)\n", 27747c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27757c478bd9Sstevel@tonic-gate #if XLA 27767c478bd9Sstevel@tonic-gate xla_host_end(host); 27777c478bd9Sstevel@tonic-gate #endif /* XLA */ 27787c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 27797c478bd9Sstevel@tonic-gate #if NETINET6 27807c478bd9Sstevel@tonic-gate if (hp != NULL) 27817c478bd9Sstevel@tonic-gate freehostent(hp); 27827c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27837c478bd9Sstevel@tonic-gate errno = save_errno; 27847c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 27857c478bd9Sstevel@tonic-gate } 27867c478bd9Sstevel@tonic-gate 27877c478bd9Sstevel@tonic-gate #if NETINET6 27887c478bd9Sstevel@tonic-gate if (hp != NULL) 27897c478bd9Sstevel@tonic-gate { 27907c478bd9Sstevel@tonic-gate freehostent(hp); 27917c478bd9Sstevel@tonic-gate hp = NULL; 27927c478bd9Sstevel@tonic-gate } 27937c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27947c478bd9Sstevel@tonic-gate 27957c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 27967c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 27977c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 27987c478bd9Sstevel@tonic-gate (void *) &s, 27997c478bd9Sstevel@tonic-gate SM_IO_WRONLY_B, NULL)) == NULL || 28007c478bd9Sstevel@tonic-gate (s = dup(s)) < 0 || 28017c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 28027c478bd9Sstevel@tonic-gate (void *) &s, 28037c478bd9Sstevel@tonic-gate SM_IO_RDONLY_B, NULL)) == NULL) 28047c478bd9Sstevel@tonic-gate { 28057c478bd9Sstevel@tonic-gate save_errno = errno; 28067c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", s); 28077c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 28087c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 28097c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 28107c478bd9Sstevel@tonic-gate (void) close(s); 28117c478bd9Sstevel@tonic-gate errno = save_errno; 28127c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 28137c478bd9Sstevel@tonic-gate } 28147c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 28157c478bd9Sstevel@tonic-gate 28167c478bd9Sstevel@tonic-gate /* set {client_flags} */ 28177c478bd9Sstevel@tonic-gate if (ClientSettings[addr.sa.sa_family].d_mflags != NULL) 28187c478bd9Sstevel@tonic-gate { 28197c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 28207c478bd9Sstevel@tonic-gate macid("{client_flags}"), 28217c478bd9Sstevel@tonic-gate ClientSettings[addr.sa.sa_family].d_mflags); 28227c478bd9Sstevel@tonic-gate } 28237c478bd9Sstevel@tonic-gate else 28247c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 28257c478bd9Sstevel@tonic-gate macid("{client_flags}"), ""); 28267c478bd9Sstevel@tonic-gate 28277c478bd9Sstevel@tonic-gate /* "add" {client_flags} to bitmap */ 28287c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags)) 28297c478bd9Sstevel@tonic-gate { 28307c478bd9Sstevel@tonic-gate /* look for just this one flag */ 28317c478bd9Sstevel@tonic-gate setbitn(D_IFNHELO, d_flags); 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate /* find out name for Interface through which we connect */ 2835058561cbSjbeck len = sizeof(addr); 28367c478bd9Sstevel@tonic-gate if (getsockname(s, &addr.sa, &len) == 0) 28377c478bd9Sstevel@tonic-gate { 28387c478bd9Sstevel@tonic-gate char *name; 28397c478bd9Sstevel@tonic-gate char family[5]; 28407c478bd9Sstevel@tonic-gate 28417c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28427c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), anynet_ntoa(&addr)); 28437c478bd9Sstevel@tonic-gate (void) sm_snprintf(family, sizeof(family), "%d", 28447c478bd9Sstevel@tonic-gate addr.sa.sa_family); 28457c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28467c478bd9Sstevel@tonic-gate macid("{if_family_out}"), family); 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate name = hostnamebyanyaddr(&addr); 28497c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28507c478bd9Sstevel@tonic-gate macid("{if_name_out}"), name); 28517c478bd9Sstevel@tonic-gate if (LogLevel > 11) 28527c478bd9Sstevel@tonic-gate { 28537c478bd9Sstevel@tonic-gate /* log connection information */ 28547c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 28557c478bd9Sstevel@tonic-gate "SMTP outgoing connect on %.40s", name); 28567c478bd9Sstevel@tonic-gate } 28577c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, d_flags)) 28587c478bd9Sstevel@tonic-gate { 28597c478bd9Sstevel@tonic-gate if (name[0] != '[' && strchr(name, '.') != NULL) 28607c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(name); 28617c478bd9Sstevel@tonic-gate } 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate else 28647c478bd9Sstevel@tonic-gate { 28657c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28667c478bd9Sstevel@tonic-gate macid("{if_name_out}"), NULL); 28677c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28687c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), NULL); 28697c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28707c478bd9Sstevel@tonic-gate macid("{if_family_out}"), NULL); 28717c478bd9Sstevel@tonic-gate } 28727c478bd9Sstevel@tonic-gate 28737c478bd9Sstevel@tonic-gate /* Use the configured HeloName as appropriate */ 28747c478bd9Sstevel@tonic-gate if (HeloName != NULL && HeloName[0] != '\0') 28757c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(HeloName); 28767c478bd9Sstevel@tonic-gate 28777c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 28787c478bd9Sstevel@tonic-gate return EX_OK; 28797c478bd9Sstevel@tonic-gate } 28807c478bd9Sstevel@tonic-gate 28817c478bd9Sstevel@tonic-gate static void 28827c478bd9Sstevel@tonic-gate connecttimeout(ignore) 28837c478bd9Sstevel@tonic-gate int ignore; 28847c478bd9Sstevel@tonic-gate { 28857c478bd9Sstevel@tonic-gate /* 28867c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 28877c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 28887c478bd9Sstevel@tonic-gate ** DOING. 28897c478bd9Sstevel@tonic-gate */ 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 28927c478bd9Sstevel@tonic-gate longjmp(CtxConnectTimeout, 1); 28937c478bd9Sstevel@tonic-gate } 28947c478bd9Sstevel@tonic-gate /* 28957c478bd9Sstevel@tonic-gate ** MAKECONNECTION_DS -- make a connection to a domain socket. 28967c478bd9Sstevel@tonic-gate ** 28977c478bd9Sstevel@tonic-gate ** Parameters: 28987c478bd9Sstevel@tonic-gate ** mux_path -- the path of the socket to connect to. 28997c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 29007c478bd9Sstevel@tonic-gate ** structure to be filled in. 29017c478bd9Sstevel@tonic-gate ** 29027c478bd9Sstevel@tonic-gate ** Returns: 29037c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 29047c478bd9Sstevel@tonic-gate ** made and if not why not. 29057c478bd9Sstevel@tonic-gate ** 29067c478bd9Sstevel@tonic-gate ** Side Effects: 29077c478bd9Sstevel@tonic-gate ** none. 29087c478bd9Sstevel@tonic-gate */ 29097c478bd9Sstevel@tonic-gate 29107c478bd9Sstevel@tonic-gate #if NETUNIX 29117c478bd9Sstevel@tonic-gate int 29127c478bd9Sstevel@tonic-gate makeconnection_ds(mux_path, mci) 29137c478bd9Sstevel@tonic-gate char *mux_path; 29147c478bd9Sstevel@tonic-gate register MCI *mci; 29157c478bd9Sstevel@tonic-gate { 29167c478bd9Sstevel@tonic-gate int sock; 29177c478bd9Sstevel@tonic-gate int rval, save_errno; 29187c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 29197c478bd9Sstevel@tonic-gate struct sockaddr_un unix_addr; 29207c478bd9Sstevel@tonic-gate 29217c478bd9Sstevel@tonic-gate /* if not safe, don't connect */ 29227c478bd9Sstevel@tonic-gate rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 29237c478bd9Sstevel@tonic-gate sff, S_IRUSR|S_IWUSR, NULL); 29247c478bd9Sstevel@tonic-gate 29257c478bd9Sstevel@tonic-gate if (rval != 0) 29267c478bd9Sstevel@tonic-gate { 29277c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: unsafe domain socket %s", 29287c478bd9Sstevel@tonic-gate mux_path); 29297c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 29307c478bd9Sstevel@tonic-gate errno = rval; 29317c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29327c478bd9Sstevel@tonic-gate } 29337c478bd9Sstevel@tonic-gate 29347c478bd9Sstevel@tonic-gate /* prepare address structure */ 2935058561cbSjbeck memset(&unix_addr, '\0', sizeof(unix_addr)); 29367c478bd9Sstevel@tonic-gate unix_addr.sun_family = AF_UNIX; 29377c478bd9Sstevel@tonic-gate 2938058561cbSjbeck if (strlen(mux_path) >= sizeof(unix_addr.sun_path)) 29397c478bd9Sstevel@tonic-gate { 29407c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: domain socket name %s too long", 29417c478bd9Sstevel@tonic-gate mux_path); 29427c478bd9Sstevel@tonic-gate 29437c478bd9Sstevel@tonic-gate /* XXX why TEMPFAIL but 5.x.y ? */ 29447c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 29457c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 29467c478bd9Sstevel@tonic-gate return EX_UNAVAILABLE; 29477c478bd9Sstevel@tonic-gate } 29487c478bd9Sstevel@tonic-gate (void) sm_strlcpy(unix_addr.sun_path, mux_path, 2949058561cbSjbeck sizeof(unix_addr.sun_path)); 29507c478bd9Sstevel@tonic-gate 29517c478bd9Sstevel@tonic-gate /* initialize domain socket */ 29527c478bd9Sstevel@tonic-gate sock = socket(AF_UNIX, SOCK_STREAM, 0); 29537c478bd9Sstevel@tonic-gate if (sock == -1) 29547c478bd9Sstevel@tonic-gate { 29557c478bd9Sstevel@tonic-gate save_errno = errno; 29567c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: could not create domain socket %s", 29577c478bd9Sstevel@tonic-gate mux_path); 29587c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 29597c478bd9Sstevel@tonic-gate errno = save_errno; 29607c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29617c478bd9Sstevel@tonic-gate } 29627c478bd9Sstevel@tonic-gate 29637c478bd9Sstevel@tonic-gate /* connect to server */ 29647c478bd9Sstevel@tonic-gate if (connect(sock, (struct sockaddr *) &unix_addr, 29657c478bd9Sstevel@tonic-gate sizeof(unix_addr)) == -1) 29667c478bd9Sstevel@tonic-gate { 29677c478bd9Sstevel@tonic-gate save_errno = errno; 29687c478bd9Sstevel@tonic-gate syserr("Could not connect to socket %s", mux_path); 29697c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 29707c478bd9Sstevel@tonic-gate (void) close(sock); 29717c478bd9Sstevel@tonic-gate errno = save_errno; 29727c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29737c478bd9Sstevel@tonic-gate } 29747c478bd9Sstevel@tonic-gate 29757c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 29767c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 29777c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 29787c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_WRONLY_B, NULL)) 29797c478bd9Sstevel@tonic-gate == NULL 29807c478bd9Sstevel@tonic-gate || (sock = dup(sock)) < 0 || 29817c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 29827c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_RDONLY_B, NULL)) 29837c478bd9Sstevel@tonic-gate == NULL) 29847c478bd9Sstevel@tonic-gate { 29857c478bd9Sstevel@tonic-gate save_errno = errno; 29867c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", sock); 29877c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 29887c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 29897c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 29907c478bd9Sstevel@tonic-gate (void) close(sock); 29917c478bd9Sstevel@tonic-gate errno = save_errno; 29927c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29937c478bd9Sstevel@tonic-gate } 29947c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 29957c478bd9Sstevel@tonic-gate 29967c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 29977c478bd9Sstevel@tonic-gate errno = 0; 29987c478bd9Sstevel@tonic-gate return EX_OK; 29997c478bd9Sstevel@tonic-gate } 30007c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 30017c478bd9Sstevel@tonic-gate /* 30027c478bd9Sstevel@tonic-gate ** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon 30037c478bd9Sstevel@tonic-gate ** 30047c478bd9Sstevel@tonic-gate ** Parameters: 30057c478bd9Sstevel@tonic-gate ** none. 30067c478bd9Sstevel@tonic-gate ** 30077c478bd9Sstevel@tonic-gate ** Returns: 30087c478bd9Sstevel@tonic-gate ** none. 30097c478bd9Sstevel@tonic-gate ** 30107c478bd9Sstevel@tonic-gate ** Side Effects: 30117c478bd9Sstevel@tonic-gate ** closes control socket, exits. 30127c478bd9Sstevel@tonic-gate */ 30137c478bd9Sstevel@tonic-gate 30147c478bd9Sstevel@tonic-gate void 30157c478bd9Sstevel@tonic-gate shutdown_daemon() 30167c478bd9Sstevel@tonic-gate { 30177c478bd9Sstevel@tonic-gate int i; 30187c478bd9Sstevel@tonic-gate char *reason; 30197c478bd9Sstevel@tonic-gate 30207c478bd9Sstevel@tonic-gate sm_allsignals(true); 30217c478bd9Sstevel@tonic-gate 30227c478bd9Sstevel@tonic-gate reason = ShutdownRequest; 30237c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 30247c478bd9Sstevel@tonic-gate PendingSignal = 0; 30257c478bd9Sstevel@tonic-gate 30267c478bd9Sstevel@tonic-gate if (LogLevel > 9) 30277c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s", 30287c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 30297c478bd9Sstevel@tonic-gate 30307c478bd9Sstevel@tonic-gate FileName = NULL; 30317c478bd9Sstevel@tonic-gate closecontrolsocket(true); 30327c478bd9Sstevel@tonic-gate #if XLA 30337c478bd9Sstevel@tonic-gate xla_all_end(); 30347c478bd9Sstevel@tonic-gate #endif /* XLA */ 30357c478bd9Sstevel@tonic-gate 30367c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 30377c478bd9Sstevel@tonic-gate { 30387c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 30397c478bd9Sstevel@tonic-gate { 30407c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 30417c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 30427c478bd9Sstevel@tonic-gate 30437c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 30447c478bd9Sstevel@tonic-gate # if NETUNIX 30457c478bd9Sstevel@tonic-gate /* Remove named sockets */ 30467c478bd9Sstevel@tonic-gate if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) 30477c478bd9Sstevel@tonic-gate { 30487c478bd9Sstevel@tonic-gate int rval; 30497c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT; 30507c478bd9Sstevel@tonic-gate 30517c478bd9Sstevel@tonic-gate /* if not safe, don't use it */ 30527c478bd9Sstevel@tonic-gate rval = safefile(Daemons[i].d_addr.sunix.sun_path, 30537c478bd9Sstevel@tonic-gate RunAsUid, RunAsGid, 30547c478bd9Sstevel@tonic-gate RunAsUserName, sff, 30557c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 30567c478bd9Sstevel@tonic-gate if (rval == 0 && 30577c478bd9Sstevel@tonic-gate unlink(Daemons[i].d_addr.sunix.sun_path) < 0) 30587c478bd9Sstevel@tonic-gate { 30597c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 30607c478bd9Sstevel@tonic-gate "Could not remove daemon %s socket: %s: %s", 30617c478bd9Sstevel@tonic-gate Daemons[i].d_name, 30627c478bd9Sstevel@tonic-gate Daemons[i].d_addr.sunix.sun_path, 30637c478bd9Sstevel@tonic-gate sm_errstring(errno)); 30647c478bd9Sstevel@tonic-gate } 30657c478bd9Sstevel@tonic-gate } 30667c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 30677c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 30687c478bd9Sstevel@tonic-gate } 30697c478bd9Sstevel@tonic-gate } 30707c478bd9Sstevel@tonic-gate 30717c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 30727c478bd9Sstevel@tonic-gate } 30737c478bd9Sstevel@tonic-gate /* 30747c478bd9Sstevel@tonic-gate ** RESTART_DAEMON -- Performs a clean restart of the daemon 30757c478bd9Sstevel@tonic-gate ** 30767c478bd9Sstevel@tonic-gate ** Parameters: 30777c478bd9Sstevel@tonic-gate ** none. 30787c478bd9Sstevel@tonic-gate ** 30797c478bd9Sstevel@tonic-gate ** Returns: 30807c478bd9Sstevel@tonic-gate ** none. 30817c478bd9Sstevel@tonic-gate ** 30827c478bd9Sstevel@tonic-gate ** Side Effects: 30837c478bd9Sstevel@tonic-gate ** restarts the daemon or exits if restart fails. 30847c478bd9Sstevel@tonic-gate */ 30857c478bd9Sstevel@tonic-gate 30867c478bd9Sstevel@tonic-gate /* Make a non-DFL/IGN signal a noop */ 30877c478bd9Sstevel@tonic-gate #define SM_NOOP_SIGNAL(sig, old) \ 30887c478bd9Sstevel@tonic-gate do \ 30897c478bd9Sstevel@tonic-gate { \ 30907c478bd9Sstevel@tonic-gate (old) = sm_signal((sig), sm_signal_noop); \ 30917c478bd9Sstevel@tonic-gate if ((old) == SIG_IGN || (old) == SIG_DFL) \ 30927c478bd9Sstevel@tonic-gate (void) sm_signal((sig), (old)); \ 30937c478bd9Sstevel@tonic-gate } while (0) 30947c478bd9Sstevel@tonic-gate 30957c478bd9Sstevel@tonic-gate void 30967c478bd9Sstevel@tonic-gate restart_daemon() 30977c478bd9Sstevel@tonic-gate { 30987c478bd9Sstevel@tonic-gate bool drop; 30997c478bd9Sstevel@tonic-gate int save_errno; 31007c478bd9Sstevel@tonic-gate char *reason; 31017c478bd9Sstevel@tonic-gate sigfunc_t ignore, oalrm, ousr1; 31027c478bd9Sstevel@tonic-gate extern int DtableSize; 31037c478bd9Sstevel@tonic-gate 31047c478bd9Sstevel@tonic-gate /* clear the events to turn off SIGALRMs */ 31057c478bd9Sstevel@tonic-gate sm_clear_events(); 31067c478bd9Sstevel@tonic-gate sm_allsignals(true); 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate reason = RestartRequest; 31097c478bd9Sstevel@tonic-gate RestartRequest = NULL; 31107c478bd9Sstevel@tonic-gate PendingSignal = 0; 31117c478bd9Sstevel@tonic-gate 31127c478bd9Sstevel@tonic-gate if (SaveArgv[0][0] != '/') 31137c478bd9Sstevel@tonic-gate { 31147c478bd9Sstevel@tonic-gate if (LogLevel > 3) 31157c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 31167c478bd9Sstevel@tonic-gate "could not restart: need full path"); 31177c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 31187c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31197c478bd9Sstevel@tonic-gate } 31207c478bd9Sstevel@tonic-gate if (LogLevel > 3) 31217c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 31227c478bd9Sstevel@tonic-gate SaveArgv[0], 31237c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 31247c478bd9Sstevel@tonic-gate 31257c478bd9Sstevel@tonic-gate closecontrolsocket(true); 31267c478bd9Sstevel@tonic-gate #if SM_CONF_SHM 31277c478bd9Sstevel@tonic-gate cleanup_shm(DaemonPid == getpid()); 31287c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SHM */ 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate /* close locked pid file */ 31317c478bd9Sstevel@tonic-gate close_sendmail_pid(); 31327c478bd9Sstevel@tonic-gate 31337c478bd9Sstevel@tonic-gate /* 31347c478bd9Sstevel@tonic-gate ** Want to drop to the user who started the process in all cases 31357c478bd9Sstevel@tonic-gate ** *but* when running as "smmsp" for the clientmqueue queue run 31367c478bd9Sstevel@tonic-gate ** daemon. In that case, UseMSP will be true, RunAsUid should not 31377c478bd9Sstevel@tonic-gate ** be root, and RealUid should be either 0 or RunAsUid. 31387c478bd9Sstevel@tonic-gate */ 31397c478bd9Sstevel@tonic-gate 31407c478bd9Sstevel@tonic-gate drop = !(UseMSP && RunAsUid != 0 && 31417c478bd9Sstevel@tonic-gate (RealUid == 0 || RealUid == RunAsUid)); 31427c478bd9Sstevel@tonic-gate 31437c478bd9Sstevel@tonic-gate if (drop_privileges(drop) != EX_OK) 31447c478bd9Sstevel@tonic-gate { 31457c478bd9Sstevel@tonic-gate if (LogLevel > 0) 31467c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 31477c478bd9Sstevel@tonic-gate "could not drop privileges: %s", 31487c478bd9Sstevel@tonic-gate sm_errstring(errno)); 31497c478bd9Sstevel@tonic-gate finis(false, true, EX_OSERR); 31507c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31517c478bd9Sstevel@tonic-gate } 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 31547c478bd9Sstevel@tonic-gate 31557c478bd9Sstevel@tonic-gate /* 31567c478bd9Sstevel@tonic-gate ** Need to allow signals before execve() to make them "harmless". 31577c478bd9Sstevel@tonic-gate ** However, the default action can be "terminate", so it isn't 31587c478bd9Sstevel@tonic-gate ** really harmless. Setting signals to IGN will cause them to be 31597c478bd9Sstevel@tonic-gate ** ignored in the new process to, so that isn't a good alternative. 31607c478bd9Sstevel@tonic-gate */ 31617c478bd9Sstevel@tonic-gate 31627c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGALRM, oalrm); 31637c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGCHLD, ignore); 31647c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGHUP, ignore); 31657c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGINT, ignore); 31667c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGPIPE, ignore); 31677c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGTERM, ignore); 31687c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 31697c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGUSR1, ousr1); 31707c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 31717c478bd9Sstevel@tonic-gate 31727c478bd9Sstevel@tonic-gate /* Turn back on signals */ 31737c478bd9Sstevel@tonic-gate sm_allsignals(false); 31747c478bd9Sstevel@tonic-gate 31757c478bd9Sstevel@tonic-gate (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 31767c478bd9Sstevel@tonic-gate save_errno = errno; 31777c478bd9Sstevel@tonic-gate 31787c478bd9Sstevel@tonic-gate /* block signals again and restore needed signals */ 31797c478bd9Sstevel@tonic-gate sm_allsignals(true); 31807c478bd9Sstevel@tonic-gate 31817c478bd9Sstevel@tonic-gate /* For finis() events */ 31827c478bd9Sstevel@tonic-gate (void) sm_signal(SIGALRM, oalrm); 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 31857c478bd9Sstevel@tonic-gate /* For debugging finis() */ 31867c478bd9Sstevel@tonic-gate (void) sm_signal(SIGUSR1, ousr1); 31877c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 31887c478bd9Sstevel@tonic-gate 31897c478bd9Sstevel@tonic-gate errno = save_errno; 31907c478bd9Sstevel@tonic-gate if (LogLevel > 0) 31917c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s", 31927c478bd9Sstevel@tonic-gate SaveArgv[0], sm_errstring(errno)); 31937c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 31947c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31957c478bd9Sstevel@tonic-gate } 31967c478bd9Sstevel@tonic-gate /* 31977c478bd9Sstevel@tonic-gate ** MYHOSTNAME -- return the name of this host. 31987c478bd9Sstevel@tonic-gate ** 31997c478bd9Sstevel@tonic-gate ** Parameters: 32007c478bd9Sstevel@tonic-gate ** hostbuf -- a place to return the name of this host. 32017c478bd9Sstevel@tonic-gate ** size -- the size of hostbuf. 32027c478bd9Sstevel@tonic-gate ** 32037c478bd9Sstevel@tonic-gate ** Returns: 32047c478bd9Sstevel@tonic-gate ** A list of aliases for this host. 32057c478bd9Sstevel@tonic-gate ** 32067c478bd9Sstevel@tonic-gate ** Side Effects: 32077c478bd9Sstevel@tonic-gate ** Adds numeric codes to $=w. 32087c478bd9Sstevel@tonic-gate */ 32097c478bd9Sstevel@tonic-gate 32107c478bd9Sstevel@tonic-gate struct hostent * 32117c478bd9Sstevel@tonic-gate myhostname(hostbuf, size) 32127c478bd9Sstevel@tonic-gate char hostbuf[]; 32137c478bd9Sstevel@tonic-gate int size; 32147c478bd9Sstevel@tonic-gate { 32157c478bd9Sstevel@tonic-gate register struct hostent *hp; 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 32187c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hostbuf, "localhost", size); 32197c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, InetMode); 32207c478bd9Sstevel@tonic-gate #if NETINET && NETINET6 32217c478bd9Sstevel@tonic-gate if (hp == NULL && InetMode == AF_INET6) 32227c478bd9Sstevel@tonic-gate { 32237c478bd9Sstevel@tonic-gate /* 32247c478bd9Sstevel@tonic-gate ** It's possible that this IPv6 enabled machine doesn't 32257c478bd9Sstevel@tonic-gate ** actually have any IPv6 interfaces and, therefore, no 32267c478bd9Sstevel@tonic-gate ** IPv6 addresses. Fall back to AF_INET. 32277c478bd9Sstevel@tonic-gate */ 32287c478bd9Sstevel@tonic-gate 32297c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, AF_INET); 32307c478bd9Sstevel@tonic-gate } 32317c478bd9Sstevel@tonic-gate #endif /* NETINET && NETINET6 */ 32327c478bd9Sstevel@tonic-gate if (hp == NULL) 32337c478bd9Sstevel@tonic-gate return NULL; 32347c478bd9Sstevel@tonic-gate if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 32357c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, hp->h_name, size); 32367c478bd9Sstevel@tonic-gate 32377c478bd9Sstevel@tonic-gate #if NETINFO 32387c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 32397c478bd9Sstevel@tonic-gate { 32407c478bd9Sstevel@tonic-gate char *domainname; 32417c478bd9Sstevel@tonic-gate 32427c478bd9Sstevel@tonic-gate domainname = ni_propval("/locations", NULL, "resolver", 32437c478bd9Sstevel@tonic-gate "domain", '\0'); 32447c478bd9Sstevel@tonic-gate if (domainname != NULL && 32457c478bd9Sstevel@tonic-gate strlen(domainname) + strlen(hostbuf) + 1 < size) 32467c478bd9Sstevel@tonic-gate (void) sm_strlcat2(hostbuf, ".", domainname, size); 32477c478bd9Sstevel@tonic-gate } 32487c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 32497c478bd9Sstevel@tonic-gate 32507c478bd9Sstevel@tonic-gate /* 32517c478bd9Sstevel@tonic-gate ** If there is still no dot in the name, try looking for a 32527c478bd9Sstevel@tonic-gate ** dotted alias. 32537c478bd9Sstevel@tonic-gate */ 32547c478bd9Sstevel@tonic-gate 32557c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 32567c478bd9Sstevel@tonic-gate { 32577c478bd9Sstevel@tonic-gate char **ha; 32587c478bd9Sstevel@tonic-gate 32597c478bd9Sstevel@tonic-gate for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 32607c478bd9Sstevel@tonic-gate { 32617c478bd9Sstevel@tonic-gate if (strchr(*ha, '.') != NULL) 32627c478bd9Sstevel@tonic-gate { 32637c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, *ha, size - 1); 32647c478bd9Sstevel@tonic-gate hostbuf[size - 1] = '\0'; 32657c478bd9Sstevel@tonic-gate break; 32667c478bd9Sstevel@tonic-gate } 32677c478bd9Sstevel@tonic-gate } 32687c478bd9Sstevel@tonic-gate } 32697c478bd9Sstevel@tonic-gate 32707c478bd9Sstevel@tonic-gate /* 32717c478bd9Sstevel@tonic-gate ** If _still_ no dot, wait for a while and try again -- it is 32727c478bd9Sstevel@tonic-gate ** possible that some service is starting up. This can result 32737c478bd9Sstevel@tonic-gate ** in excessive delays if the system is badly configured, but 32747c478bd9Sstevel@tonic-gate ** there really isn't a way around that, particularly given that 32757c478bd9Sstevel@tonic-gate ** the config file hasn't been read at this point. 32767c478bd9Sstevel@tonic-gate ** All in all, a bit of a mess. 32777c478bd9Sstevel@tonic-gate */ 32787c478bd9Sstevel@tonic-gate 32797c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL && 32807c478bd9Sstevel@tonic-gate !getcanonname(hostbuf, size, true, NULL)) 32817c478bd9Sstevel@tonic-gate { 3282d4660949Sjbeck sm_syslog(LocalDaemon ? LOG_WARNING : LOG_CRIT, NOQID, 32837c478bd9Sstevel@tonic-gate "My unqualified host name (%s) unknown; sleeping for retry", 32847c478bd9Sstevel@tonic-gate hostbuf); 32857c478bd9Sstevel@tonic-gate message("My unqualified host name (%s) unknown; sleeping for retry", 32867c478bd9Sstevel@tonic-gate hostbuf); 32877c478bd9Sstevel@tonic-gate (void) sleep(60); 32887c478bd9Sstevel@tonic-gate if (!getcanonname(hostbuf, size, true, NULL)) 32897c478bd9Sstevel@tonic-gate { 3290d4660949Sjbeck sm_syslog(LocalDaemon ? LOG_WARNING : LOG_ALERT, NOQID, 32917c478bd9Sstevel@tonic-gate "unable to qualify my own domain name (%s) -- using short name", 32927c478bd9Sstevel@tonic-gate hostbuf); 32937c478bd9Sstevel@tonic-gate message("WARNING: unable to qualify my own domain name (%s) -- using short name", 32947c478bd9Sstevel@tonic-gate hostbuf); 32957c478bd9Sstevel@tonic-gate } 32967c478bd9Sstevel@tonic-gate } 32977c478bd9Sstevel@tonic-gate return hp; 32987c478bd9Sstevel@tonic-gate } 32997c478bd9Sstevel@tonic-gate /* 33007c478bd9Sstevel@tonic-gate ** ADDRCMP -- compare two host addresses 33017c478bd9Sstevel@tonic-gate ** 33027c478bd9Sstevel@tonic-gate ** Parameters: 33037c478bd9Sstevel@tonic-gate ** hp -- hostent structure for the first address 33047c478bd9Sstevel@tonic-gate ** ha -- actual first address 33057c478bd9Sstevel@tonic-gate ** sa -- second address 33067c478bd9Sstevel@tonic-gate ** 33077c478bd9Sstevel@tonic-gate ** Returns: 33087c478bd9Sstevel@tonic-gate ** 0 -- if ha and sa match 33097c478bd9Sstevel@tonic-gate ** else -- they don't match 33107c478bd9Sstevel@tonic-gate */ 33117c478bd9Sstevel@tonic-gate 33127c478bd9Sstevel@tonic-gate static int 33137c478bd9Sstevel@tonic-gate addrcmp(hp, ha, sa) 33147c478bd9Sstevel@tonic-gate struct hostent *hp; 33157c478bd9Sstevel@tonic-gate char *ha; 33167c478bd9Sstevel@tonic-gate SOCKADDR *sa; 33177c478bd9Sstevel@tonic-gate { 33187c478bd9Sstevel@tonic-gate #if NETINET6 33197c478bd9Sstevel@tonic-gate unsigned char *a; 33207c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 33217c478bd9Sstevel@tonic-gate 33227c478bd9Sstevel@tonic-gate switch (sa->sa.sa_family) 33237c478bd9Sstevel@tonic-gate { 33247c478bd9Sstevel@tonic-gate #if NETINET 33257c478bd9Sstevel@tonic-gate case AF_INET: 33267c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET) 33277c478bd9Sstevel@tonic-gate return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 33287c478bd9Sstevel@tonic-gate break; 33297c478bd9Sstevel@tonic-gate #endif /* NETINET */ 33307c478bd9Sstevel@tonic-gate 33317c478bd9Sstevel@tonic-gate #if NETINET6 33327c478bd9Sstevel@tonic-gate case AF_INET6: 33337c478bd9Sstevel@tonic-gate a = (unsigned char *) &sa->sin6.sin6_addr; 33347c478bd9Sstevel@tonic-gate 33357c478bd9Sstevel@tonic-gate /* Straight binary comparison */ 33367c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET6) 33377c478bd9Sstevel@tonic-gate return memcmp(ha, a, IN6ADDRSZ); 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 33407c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET && 33417c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 33427c478bd9Sstevel@tonic-gate return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 33437c478bd9Sstevel@tonic-gate break; 33447c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 33457c478bd9Sstevel@tonic-gate } 33467c478bd9Sstevel@tonic-gate return -1; 33477c478bd9Sstevel@tonic-gate } 33487c478bd9Sstevel@tonic-gate /* 33497c478bd9Sstevel@tonic-gate ** GETAUTHINFO -- get the real host name associated with a file descriptor 33507c478bd9Sstevel@tonic-gate ** 33517c478bd9Sstevel@tonic-gate ** Uses RFC1413 protocol to try to get info from the other end. 33527c478bd9Sstevel@tonic-gate ** 33537c478bd9Sstevel@tonic-gate ** Parameters: 33547c478bd9Sstevel@tonic-gate ** fd -- the descriptor 33557c478bd9Sstevel@tonic-gate ** may_be_forged -- an outage that is set to true if the 33567c478bd9Sstevel@tonic-gate ** forward lookup of RealHostName does not match 33577c478bd9Sstevel@tonic-gate ** RealHostAddr; set to false if they do match. 33587c478bd9Sstevel@tonic-gate ** 33597c478bd9Sstevel@tonic-gate ** Returns: 33607c478bd9Sstevel@tonic-gate ** The user@host information associated with this descriptor. 33617c478bd9Sstevel@tonic-gate */ 33627c478bd9Sstevel@tonic-gate 33637c478bd9Sstevel@tonic-gate static jmp_buf CtxAuthTimeout; 33647c478bd9Sstevel@tonic-gate 33657c478bd9Sstevel@tonic-gate static void 33667c478bd9Sstevel@tonic-gate authtimeout(ignore) 33677c478bd9Sstevel@tonic-gate int ignore; 33687c478bd9Sstevel@tonic-gate { 33697c478bd9Sstevel@tonic-gate /* 33707c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 33717c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 33727c478bd9Sstevel@tonic-gate ** DOING. 33737c478bd9Sstevel@tonic-gate */ 33747c478bd9Sstevel@tonic-gate 33757c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 33767c478bd9Sstevel@tonic-gate longjmp(CtxAuthTimeout, 1); 33777c478bd9Sstevel@tonic-gate } 33787c478bd9Sstevel@tonic-gate 33797c478bd9Sstevel@tonic-gate char * 33807c478bd9Sstevel@tonic-gate getauthinfo(fd, may_be_forged) 33817c478bd9Sstevel@tonic-gate int fd; 33827c478bd9Sstevel@tonic-gate bool *may_be_forged; 33837c478bd9Sstevel@tonic-gate { 33847c478bd9Sstevel@tonic-gate unsigned short SM_NONVOLATILE port = 0; 33857c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T falen; 33867c478bd9Sstevel@tonic-gate register char *volatile p = NULL; 33877c478bd9Sstevel@tonic-gate SOCKADDR la; 33887c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T lalen; 33897c478bd9Sstevel@tonic-gate #ifndef NO_GETSERVBYNAME 33907c478bd9Sstevel@tonic-gate register struct servent *sp; 33917c478bd9Sstevel@tonic-gate # if NETINET 33927c478bd9Sstevel@tonic-gate static unsigned short port4 = 0; 33937c478bd9Sstevel@tonic-gate # endif /* NETINET */ 33947c478bd9Sstevel@tonic-gate # if NETINET6 33957c478bd9Sstevel@tonic-gate static unsigned short port6 = 0; 33967c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 33977c478bd9Sstevel@tonic-gate #endif /* ! NO_GETSERVBYNAME */ 33987c478bd9Sstevel@tonic-gate volatile int s; 33997c478bd9Sstevel@tonic-gate int i = 0; 34007c478bd9Sstevel@tonic-gate size_t len; 34017c478bd9Sstevel@tonic-gate SM_EVENT *ev; 34027c478bd9Sstevel@tonic-gate int nleft; 34037c478bd9Sstevel@tonic-gate struct hostent *hp; 34047c478bd9Sstevel@tonic-gate char *ostype = NULL; 34057c478bd9Sstevel@tonic-gate char **ha; 34067c478bd9Sstevel@tonic-gate char ibuf[MAXNAME + 1]; 34077c478bd9Sstevel@tonic-gate static char hbuf[MAXNAME + MAXAUTHINFO + 11]; 34087c478bd9Sstevel@tonic-gate 34097c478bd9Sstevel@tonic-gate *may_be_forged = false; 3410058561cbSjbeck falen = sizeof(RealHostAddr); 34117c478bd9Sstevel@tonic-gate if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 34127c478bd9Sstevel@tonic-gate falen <= 0 || RealHostAddr.sa.sa_family == 0) 34137c478bd9Sstevel@tonic-gate { 34147c478bd9Sstevel@tonic-gate if (i < 0) 34157c478bd9Sstevel@tonic-gate { 34167c478bd9Sstevel@tonic-gate /* 34177c478bd9Sstevel@tonic-gate ** ENOTSOCK is OK: bail on anything else, but reset 34187c478bd9Sstevel@tonic-gate ** errno in this case, so a mis-report doesn't 34197c478bd9Sstevel@tonic-gate ** happen later. 34207c478bd9Sstevel@tonic-gate */ 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate if (errno != ENOTSOCK) 34237c478bd9Sstevel@tonic-gate return NULL; 34247c478bd9Sstevel@tonic-gate errno = 0; 34257c478bd9Sstevel@tonic-gate } 3426058561cbSjbeck (void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName, 34277c478bd9Sstevel@tonic-gate "@localhost"); 34287c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 34297c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 34307c478bd9Sstevel@tonic-gate return hbuf; 34317c478bd9Sstevel@tonic-gate } 34327c478bd9Sstevel@tonic-gate 34337c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 34347c478bd9Sstevel@tonic-gate { 34357c478bd9Sstevel@tonic-gate /* translate that to a host name */ 34367c478bd9Sstevel@tonic-gate RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 34377c478bd9Sstevel@tonic-gate if (strlen(RealHostName) > MAXNAME) 34387c478bd9Sstevel@tonic-gate RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ 34397c478bd9Sstevel@tonic-gate } 34407c478bd9Sstevel@tonic-gate 34417c478bd9Sstevel@tonic-gate /* cross check RealHostName with forward DNS lookup */ 34427c478bd9Sstevel@tonic-gate if (anynet_ntoa(&RealHostAddr)[0] != '[' && 34437c478bd9Sstevel@tonic-gate RealHostName[0] != '[') 34447c478bd9Sstevel@tonic-gate { 34457c478bd9Sstevel@tonic-gate int family; 34467c478bd9Sstevel@tonic-gate 34477c478bd9Sstevel@tonic-gate family = RealHostAddr.sa.sa_family; 34487c478bd9Sstevel@tonic-gate #if NETINET6 && NEEDSGETIPNODE 34497c478bd9Sstevel@tonic-gate /* 34507c478bd9Sstevel@tonic-gate ** If RealHostAddr is an IPv6 connection with an 34517c478bd9Sstevel@tonic-gate ** IPv4-mapped address, we need RealHostName's IPv4 34527c478bd9Sstevel@tonic-gate ** address(es) for addrcmp() to compare against 34537c478bd9Sstevel@tonic-gate ** RealHostAddr. 34547c478bd9Sstevel@tonic-gate ** 34557c478bd9Sstevel@tonic-gate ** Actually, we only need to do this for systems 34567c478bd9Sstevel@tonic-gate ** which NEEDSGETIPNODE since the real getipnodebyname() 34577c478bd9Sstevel@tonic-gate ** already does V4MAPPED address via the AI_V4MAPPEDCFG 34587c478bd9Sstevel@tonic-gate ** flag. A better fix to this problem is to add this 34597c478bd9Sstevel@tonic-gate ** functionality to our stub getipnodebyname(). 34607c478bd9Sstevel@tonic-gate */ 34617c478bd9Sstevel@tonic-gate 34627c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 34637c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 34647c478bd9Sstevel@tonic-gate family = AF_INET; 34657c478bd9Sstevel@tonic-gate #endif /* NETINET6 && NEEDSGETIPNODE */ 34667c478bd9Sstevel@tonic-gate 34677c478bd9Sstevel@tonic-gate /* try to match the reverse against the forward lookup */ 34687c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(RealHostName, family); 34697c478bd9Sstevel@tonic-gate if (hp == NULL) 34707c478bd9Sstevel@tonic-gate { 34717c478bd9Sstevel@tonic-gate /* XXX: Could be a temporary error on forward lookup */ 34727c478bd9Sstevel@tonic-gate *may_be_forged = true; 34737c478bd9Sstevel@tonic-gate } 34747c478bd9Sstevel@tonic-gate else 34757c478bd9Sstevel@tonic-gate { 34767c478bd9Sstevel@tonic-gate for (ha = hp->h_addr_list; *ha != NULL; ha++) 34777c478bd9Sstevel@tonic-gate { 34787c478bd9Sstevel@tonic-gate if (addrcmp(hp, *ha, &RealHostAddr) == 0) 34797c478bd9Sstevel@tonic-gate break; 34807c478bd9Sstevel@tonic-gate } 34817c478bd9Sstevel@tonic-gate *may_be_forged = *ha == NULL; 34827c478bd9Sstevel@tonic-gate #if NETINET6 34837c478bd9Sstevel@tonic-gate freehostent(hp); 34847c478bd9Sstevel@tonic-gate hp = NULL; 34857c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 34867c478bd9Sstevel@tonic-gate } 34877c478bd9Sstevel@tonic-gate } 34887c478bd9Sstevel@tonic-gate 34897c478bd9Sstevel@tonic-gate if (TimeOuts.to_ident == 0) 34907c478bd9Sstevel@tonic-gate goto noident; 34917c478bd9Sstevel@tonic-gate 3492058561cbSjbeck lalen = sizeof(la); 34937c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 34947c478bd9Sstevel@tonic-gate { 34957c478bd9Sstevel@tonic-gate #if NETINET 34967c478bd9Sstevel@tonic-gate case AF_INET: 34977c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 34987c478bd9Sstevel@tonic-gate lalen <= 0 || 34997c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET) 35007c478bd9Sstevel@tonic-gate { 35017c478bd9Sstevel@tonic-gate /* no ident info */ 35027c478bd9Sstevel@tonic-gate goto noident; 35037c478bd9Sstevel@tonic-gate } 35047c478bd9Sstevel@tonic-gate port = RealHostAddr.sin.sin_port; 35057c478bd9Sstevel@tonic-gate 35067c478bd9Sstevel@tonic-gate /* create ident query */ 3507058561cbSjbeck (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 35087c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin.sin_port), 35097c478bd9Sstevel@tonic-gate ntohs(la.sin.sin_port)); 35107c478bd9Sstevel@tonic-gate 35117c478bd9Sstevel@tonic-gate /* create local address */ 35127c478bd9Sstevel@tonic-gate la.sin.sin_port = 0; 35137c478bd9Sstevel@tonic-gate 35147c478bd9Sstevel@tonic-gate /* create foreign address */ 35157c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 35167c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = htons(113); 35177c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 35187c478bd9Sstevel@tonic-gate 35197c478bd9Sstevel@tonic-gate /* 35207c478bd9Sstevel@tonic-gate ** getservbyname() consumes about 5% of the time 35217c478bd9Sstevel@tonic-gate ** when receiving a small message (almost all of the time 35227c478bd9Sstevel@tonic-gate ** spent in this routine). 35237c478bd9Sstevel@tonic-gate ** Hence we store the port in a static variable 35247c478bd9Sstevel@tonic-gate ** to save this time. 35257c478bd9Sstevel@tonic-gate ** The portnumber shouldn't change very often... 35267c478bd9Sstevel@tonic-gate ** This code makes the assumption that the port number 35277c478bd9Sstevel@tonic-gate ** is not 0. 35287c478bd9Sstevel@tonic-gate */ 35297c478bd9Sstevel@tonic-gate 35307c478bd9Sstevel@tonic-gate if (port4 == 0) 35317c478bd9Sstevel@tonic-gate { 35327c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 35337c478bd9Sstevel@tonic-gate if (sp != NULL) 35347c478bd9Sstevel@tonic-gate port4 = sp->s_port; 35357c478bd9Sstevel@tonic-gate else 35367c478bd9Sstevel@tonic-gate port4 = htons(113); 35377c478bd9Sstevel@tonic-gate } 35387c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port4; 35397c478bd9Sstevel@tonic-gate break; 35407c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 35417c478bd9Sstevel@tonic-gate #endif /* NETINET */ 35427c478bd9Sstevel@tonic-gate 35437c478bd9Sstevel@tonic-gate #if NETINET6 35447c478bd9Sstevel@tonic-gate case AF_INET6: 35457c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 35467c478bd9Sstevel@tonic-gate lalen <= 0 || 35477c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET6) 35487c478bd9Sstevel@tonic-gate { 35497c478bd9Sstevel@tonic-gate /* no ident info */ 35507c478bd9Sstevel@tonic-gate goto noident; 35517c478bd9Sstevel@tonic-gate } 35527c478bd9Sstevel@tonic-gate port = RealHostAddr.sin6.sin6_port; 35537c478bd9Sstevel@tonic-gate 35547c478bd9Sstevel@tonic-gate /* create ident query */ 3555058561cbSjbeck (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 35567c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin6.sin6_port), 35577c478bd9Sstevel@tonic-gate ntohs(la.sin6.sin6_port)); 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate /* create local address */ 35607c478bd9Sstevel@tonic-gate la.sin6.sin6_port = 0; 35617c478bd9Sstevel@tonic-gate 35627c478bd9Sstevel@tonic-gate /* create foreign address */ 35637c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 35647c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = htons(113); 35657c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 35667c478bd9Sstevel@tonic-gate if (port6 == 0) 35677c478bd9Sstevel@tonic-gate { 35687c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 35697c478bd9Sstevel@tonic-gate if (sp != NULL) 35707c478bd9Sstevel@tonic-gate port6 = sp->s_port; 35717c478bd9Sstevel@tonic-gate else 35727c478bd9Sstevel@tonic-gate port6 = htons(113); 35737c478bd9Sstevel@tonic-gate } 35747c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port6; 35757c478bd9Sstevel@tonic-gate break; 35767c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 35777c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 35787c478bd9Sstevel@tonic-gate default: 35797c478bd9Sstevel@tonic-gate /* no ident info */ 35807c478bd9Sstevel@tonic-gate goto noident; 35817c478bd9Sstevel@tonic-gate } 35827c478bd9Sstevel@tonic-gate 35837c478bd9Sstevel@tonic-gate s = -1; 35847c478bd9Sstevel@tonic-gate if (setjmp(CtxAuthTimeout) != 0) 35857c478bd9Sstevel@tonic-gate { 35867c478bd9Sstevel@tonic-gate if (s >= 0) 35877c478bd9Sstevel@tonic-gate (void) close(s); 35887c478bd9Sstevel@tonic-gate goto noident; 35897c478bd9Sstevel@tonic-gate } 35907c478bd9Sstevel@tonic-gate 35917c478bd9Sstevel@tonic-gate /* put a timeout around the whole thing */ 35927c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0); 35937c478bd9Sstevel@tonic-gate 35947c478bd9Sstevel@tonic-gate /* connect to foreign IDENT server using same address as SMTP socket */ 35957c478bd9Sstevel@tonic-gate s = socket(la.sa.sa_family, SOCK_STREAM, 0); 35967c478bd9Sstevel@tonic-gate if (s < 0) 35977c478bd9Sstevel@tonic-gate { 35987c478bd9Sstevel@tonic-gate sm_clrevent(ev); 35997c478bd9Sstevel@tonic-gate goto noident; 36007c478bd9Sstevel@tonic-gate } 36017c478bd9Sstevel@tonic-gate if (bind(s, &la.sa, lalen) < 0 || 36027c478bd9Sstevel@tonic-gate connect(s, &RealHostAddr.sa, lalen) < 0) 36037c478bd9Sstevel@tonic-gate goto closeident; 36047c478bd9Sstevel@tonic-gate 36057c478bd9Sstevel@tonic-gate if (tTd(9, 10)) 36067c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: sent %s", ibuf); 36077c478bd9Sstevel@tonic-gate 36087c478bd9Sstevel@tonic-gate /* send query */ 36097c478bd9Sstevel@tonic-gate if (write(s, ibuf, strlen(ibuf)) < 0) 36107c478bd9Sstevel@tonic-gate goto closeident; 36117c478bd9Sstevel@tonic-gate 36127c478bd9Sstevel@tonic-gate /* get result */ 36137c478bd9Sstevel@tonic-gate p = &ibuf[0]; 3614058561cbSjbeck nleft = sizeof(ibuf) - 1; 36157c478bd9Sstevel@tonic-gate while ((i = read(s, p, nleft)) > 0) 36167c478bd9Sstevel@tonic-gate { 36177c478bd9Sstevel@tonic-gate char *s; 36187c478bd9Sstevel@tonic-gate 36197c478bd9Sstevel@tonic-gate p += i; 36207c478bd9Sstevel@tonic-gate nleft -= i; 36217c478bd9Sstevel@tonic-gate *p = '\0'; 36227c478bd9Sstevel@tonic-gate if ((s = strchr(ibuf, '\n')) != NULL) 36237c478bd9Sstevel@tonic-gate { 36247c478bd9Sstevel@tonic-gate if (p > s + 1) 36257c478bd9Sstevel@tonic-gate { 36267c478bd9Sstevel@tonic-gate p = s + 1; 36277c478bd9Sstevel@tonic-gate *p = '\0'; 36287c478bd9Sstevel@tonic-gate } 36297c478bd9Sstevel@tonic-gate break; 36307c478bd9Sstevel@tonic-gate } 36317c478bd9Sstevel@tonic-gate if (nleft <= 0) 36327c478bd9Sstevel@tonic-gate break; 36337c478bd9Sstevel@tonic-gate } 36347c478bd9Sstevel@tonic-gate (void) close(s); 36357c478bd9Sstevel@tonic-gate sm_clrevent(ev); 36367c478bd9Sstevel@tonic-gate if (i < 0 || p == &ibuf[0]) 36377c478bd9Sstevel@tonic-gate goto noident; 36387c478bd9Sstevel@tonic-gate 36397c478bd9Sstevel@tonic-gate if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r') 36407c478bd9Sstevel@tonic-gate p--; 36417c478bd9Sstevel@tonic-gate *++p = '\0'; 36427c478bd9Sstevel@tonic-gate 36437c478bd9Sstevel@tonic-gate if (tTd(9, 3)) 36447c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: got %s\n", ibuf); 36457c478bd9Sstevel@tonic-gate 36467c478bd9Sstevel@tonic-gate /* parse result */ 36477c478bd9Sstevel@tonic-gate p = strchr(ibuf, ':'); 36487c478bd9Sstevel@tonic-gate if (p == NULL) 36497c478bd9Sstevel@tonic-gate { 36507c478bd9Sstevel@tonic-gate /* malformed response */ 36517c478bd9Sstevel@tonic-gate goto noident; 36527c478bd9Sstevel@tonic-gate } 36537c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 36547c478bd9Sstevel@tonic-gate continue; 36557c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "userid", 6) != 0) 36567c478bd9Sstevel@tonic-gate { 36577c478bd9Sstevel@tonic-gate /* presumably an error string */ 36587c478bd9Sstevel@tonic-gate goto noident; 36597c478bd9Sstevel@tonic-gate } 36607c478bd9Sstevel@tonic-gate p += 6; 36617c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 36627c478bd9Sstevel@tonic-gate p++; 36637c478bd9Sstevel@tonic-gate if (*p++ != ':') 36647c478bd9Sstevel@tonic-gate { 36657c478bd9Sstevel@tonic-gate /* either useridxx or malformed response */ 36667c478bd9Sstevel@tonic-gate goto noident; 36677c478bd9Sstevel@tonic-gate } 36687c478bd9Sstevel@tonic-gate 36697c478bd9Sstevel@tonic-gate /* p now points to the OSTYPE field */ 36707c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 36717c478bd9Sstevel@tonic-gate p++; 36727c478bd9Sstevel@tonic-gate ostype = p; 36737c478bd9Sstevel@tonic-gate p = strchr(p, ':'); 36747c478bd9Sstevel@tonic-gate if (p == NULL) 36757c478bd9Sstevel@tonic-gate { 36767c478bd9Sstevel@tonic-gate /* malformed response */ 36777c478bd9Sstevel@tonic-gate goto noident; 36787c478bd9Sstevel@tonic-gate } 36797c478bd9Sstevel@tonic-gate else 36807c478bd9Sstevel@tonic-gate { 36817c478bd9Sstevel@tonic-gate char *charset; 36827c478bd9Sstevel@tonic-gate 36837c478bd9Sstevel@tonic-gate *p = '\0'; 36847c478bd9Sstevel@tonic-gate charset = strchr(ostype, ','); 36857c478bd9Sstevel@tonic-gate if (charset != NULL) 36867c478bd9Sstevel@tonic-gate *charset = '\0'; 36877c478bd9Sstevel@tonic-gate } 36887c478bd9Sstevel@tonic-gate 36897c478bd9Sstevel@tonic-gate /* 1413 says don't do this -- but it's broken otherwise */ 36907c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 36917c478bd9Sstevel@tonic-gate continue; 36927c478bd9Sstevel@tonic-gate 36937c478bd9Sstevel@tonic-gate /* p now points to the authenticated name -- copy carefully */ 36947c478bd9Sstevel@tonic-gate if (sm_strncasecmp(ostype, "other", 5) == 0 && 36957c478bd9Sstevel@tonic-gate (ostype[5] == ' ' || ostype[5] == '\0')) 36967c478bd9Sstevel@tonic-gate { 3697058561cbSjbeck (void) sm_strlcpy(hbuf, "IDENT:", sizeof(hbuf)); 36987c478bd9Sstevel@tonic-gate cleanstrcpy(&hbuf[6], p, MAXAUTHINFO); 36997c478bd9Sstevel@tonic-gate } 37007c478bd9Sstevel@tonic-gate else 37017c478bd9Sstevel@tonic-gate cleanstrcpy(hbuf, p, MAXAUTHINFO); 37027c478bd9Sstevel@tonic-gate len = strlen(hbuf); 3703058561cbSjbeck (void) sm_strlcpyn(&hbuf[len], sizeof(hbuf) - len, 2, "@", 37047c478bd9Sstevel@tonic-gate RealHostName == NULL ? "localhost" : RealHostName); 37057c478bd9Sstevel@tonic-gate goto postident; 37067c478bd9Sstevel@tonic-gate 37077c478bd9Sstevel@tonic-gate closeident: 37087c478bd9Sstevel@tonic-gate (void) close(s); 37097c478bd9Sstevel@tonic-gate sm_clrevent(ev); 37107c478bd9Sstevel@tonic-gate 37117c478bd9Sstevel@tonic-gate noident: 37127c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 37137c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 37147c478bd9Sstevel@tonic-gate { 37157c478bd9Sstevel@tonic-gate #if NETINET 37167c478bd9Sstevel@tonic-gate case AF_INET: 37177c478bd9Sstevel@tonic-gate if (port > 0) 37187c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 37197c478bd9Sstevel@tonic-gate break; 37207c478bd9Sstevel@tonic-gate #endif /* NETINET */ 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate #if NETINET6 37237c478bd9Sstevel@tonic-gate case AF_INET6: 37247c478bd9Sstevel@tonic-gate if (port > 0) 37257c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 37267c478bd9Sstevel@tonic-gate break; 37277c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 37287c478bd9Sstevel@tonic-gate } 37297c478bd9Sstevel@tonic-gate 37307c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 37317c478bd9Sstevel@tonic-gate { 37327c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 37337c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: NULL\n"); 37347c478bd9Sstevel@tonic-gate return NULL; 37357c478bd9Sstevel@tonic-gate } 3736058561cbSjbeck (void) sm_strlcpy(hbuf, RealHostName, sizeof(hbuf)); 37377c478bd9Sstevel@tonic-gate 37387c478bd9Sstevel@tonic-gate postident: 37397c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 37407c478bd9Sstevel@tonic-gate # ifndef GET_IPOPT_DST 37417c478bd9Sstevel@tonic-gate # define GET_IPOPT_DST(dst) (dst) 37427c478bd9Sstevel@tonic-gate # endif /* ! GET_IPOPT_DST */ 37437c478bd9Sstevel@tonic-gate /* 37447c478bd9Sstevel@tonic-gate ** Extract IP source routing information. 37457c478bd9Sstevel@tonic-gate ** 37467c478bd9Sstevel@tonic-gate ** Format of output for a connection from site a through b 37477c478bd9Sstevel@tonic-gate ** through c to d: 37487c478bd9Sstevel@tonic-gate ** loose: @site-c@site-b:site-a 37497c478bd9Sstevel@tonic-gate ** strict: !@site-c@site-b:site-a 37507c478bd9Sstevel@tonic-gate ** 37517c478bd9Sstevel@tonic-gate ** o - pointer within ipopt_list structure. 37527c478bd9Sstevel@tonic-gate ** q - pointer within ls/ss rr route data 37537c478bd9Sstevel@tonic-gate ** p - pointer to hbuf 37547c478bd9Sstevel@tonic-gate */ 37557c478bd9Sstevel@tonic-gate 37567c478bd9Sstevel@tonic-gate if (RealHostAddr.sa.sa_family == AF_INET) 37577c478bd9Sstevel@tonic-gate { 37587c478bd9Sstevel@tonic-gate SOCKOPT_LEN_T ipoptlen; 37597c478bd9Sstevel@tonic-gate int j; 37607c478bd9Sstevel@tonic-gate unsigned char *q; 37617c478bd9Sstevel@tonic-gate unsigned char *o; 37627c478bd9Sstevel@tonic-gate int l; 37637c478bd9Sstevel@tonic-gate struct IPOPTION ipopt; 37647c478bd9Sstevel@tonic-gate 3765058561cbSjbeck ipoptlen = sizeof(ipopt); 37667c478bd9Sstevel@tonic-gate if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 37677c478bd9Sstevel@tonic-gate (char *) &ipopt, &ipoptlen) < 0) 37687c478bd9Sstevel@tonic-gate goto noipsr; 37697c478bd9Sstevel@tonic-gate if (ipoptlen == 0) 37707c478bd9Sstevel@tonic-gate goto noipsr; 37717c478bd9Sstevel@tonic-gate o = (unsigned char *) ipopt.IP_LIST; 37727c478bd9Sstevel@tonic-gate while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen) 37737c478bd9Sstevel@tonic-gate { 37747c478bd9Sstevel@tonic-gate switch (*o) 37757c478bd9Sstevel@tonic-gate { 37767c478bd9Sstevel@tonic-gate case IPOPT_EOL: 37777c478bd9Sstevel@tonic-gate o = NULL; 37787c478bd9Sstevel@tonic-gate break; 37797c478bd9Sstevel@tonic-gate 37807c478bd9Sstevel@tonic-gate case IPOPT_NOP: 37817c478bd9Sstevel@tonic-gate o++; 37827c478bd9Sstevel@tonic-gate break; 37837c478bd9Sstevel@tonic-gate 37847c478bd9Sstevel@tonic-gate case IPOPT_SSRR: 37857c478bd9Sstevel@tonic-gate case IPOPT_LSRR: 37867c478bd9Sstevel@tonic-gate /* 37877c478bd9Sstevel@tonic-gate ** Source routing. 37887c478bd9Sstevel@tonic-gate ** o[0] is the option type (loose/strict). 37897c478bd9Sstevel@tonic-gate ** o[1] is the length of this option, 37907c478bd9Sstevel@tonic-gate ** including option type and 37917c478bd9Sstevel@tonic-gate ** length. 37927c478bd9Sstevel@tonic-gate ** o[2] is the pointer into the route 37937c478bd9Sstevel@tonic-gate ** data. 37947c478bd9Sstevel@tonic-gate ** o[3] begins the route data. 37957c478bd9Sstevel@tonic-gate */ 37967c478bd9Sstevel@tonic-gate 37977c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 3798058561cbSjbeck l = sizeof(hbuf) - (hbuf - p) - 6; 37997c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), 38007c478bd9Sstevel@tonic-gate " [%s@%.*s", 38017c478bd9Sstevel@tonic-gate *o == IPOPT_SSRR ? "!" : "", 38027c478bd9Sstevel@tonic-gate l > 240 ? 120 : l / 2, 38037c478bd9Sstevel@tonic-gate inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 38047c478bd9Sstevel@tonic-gate i = strlen(p); 38057c478bd9Sstevel@tonic-gate p += i; 38067c478bd9Sstevel@tonic-gate l -= strlen(p); 38077c478bd9Sstevel@tonic-gate 38087c478bd9Sstevel@tonic-gate j = o[1] / sizeof(struct in_addr) - 1; 38097c478bd9Sstevel@tonic-gate 38107c478bd9Sstevel@tonic-gate /* q skips length and router pointer to data */ 38117c478bd9Sstevel@tonic-gate q = &o[3]; 38127c478bd9Sstevel@tonic-gate for ( ; j >= 0; j--) 38137c478bd9Sstevel@tonic-gate { 38147c478bd9Sstevel@tonic-gate struct in_addr addr; 38157c478bd9Sstevel@tonic-gate 38167c478bd9Sstevel@tonic-gate memcpy(&addr, q, sizeof(addr)); 38177c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, 38187c478bd9Sstevel@tonic-gate SPACELEFT(hbuf, p), 38197c478bd9Sstevel@tonic-gate "%c%.*s", 38207c478bd9Sstevel@tonic-gate j != 0 ? '@' : ':', 38217c478bd9Sstevel@tonic-gate l > 240 ? 120 : 38227c478bd9Sstevel@tonic-gate j == 0 ? l : l / 2, 38237c478bd9Sstevel@tonic-gate inet_ntoa(addr)); 38247c478bd9Sstevel@tonic-gate i = strlen(p); 38257c478bd9Sstevel@tonic-gate p += i; 38267c478bd9Sstevel@tonic-gate l -= i + 1; 38277c478bd9Sstevel@tonic-gate q += sizeof(struct in_addr); 38287c478bd9Sstevel@tonic-gate } 38297c478bd9Sstevel@tonic-gate o += o[1]; 38307c478bd9Sstevel@tonic-gate break; 38317c478bd9Sstevel@tonic-gate 38327c478bd9Sstevel@tonic-gate default: 38337c478bd9Sstevel@tonic-gate /* Skip over option */ 38347c478bd9Sstevel@tonic-gate o += o[1]; 38357c478bd9Sstevel@tonic-gate break; 38367c478bd9Sstevel@tonic-gate } 38377c478bd9Sstevel@tonic-gate } 38387c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), "]"); 38397c478bd9Sstevel@tonic-gate goto postipsr; 38407c478bd9Sstevel@tonic-gate } 38417c478bd9Sstevel@tonic-gate 38427c478bd9Sstevel@tonic-gate noipsr: 38437c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 38447c478bd9Sstevel@tonic-gate if (RealHostName != NULL && RealHostName[0] != '[') 38457c478bd9Sstevel@tonic-gate { 38467c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 38477c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 38487c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 38497c478bd9Sstevel@tonic-gate } 38507c478bd9Sstevel@tonic-gate if (*may_be_forged) 38517c478bd9Sstevel@tonic-gate { 38527c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 38537c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p)); 38547c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 38557c478bd9Sstevel@tonic-gate macid("{client_resolve}"), "FORGED"); 38567c478bd9Sstevel@tonic-gate } 38577c478bd9Sstevel@tonic-gate 38587c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 38597c478bd9Sstevel@tonic-gate postipsr: 38607c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 38617c478bd9Sstevel@tonic-gate 38627c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 38637c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 38647c478bd9Sstevel@tonic-gate { 38657c478bd9Sstevel@tonic-gate #if NETINET 38667c478bd9Sstevel@tonic-gate case AF_INET: 38677c478bd9Sstevel@tonic-gate if (port > 0) 38687c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 38697c478bd9Sstevel@tonic-gate break; 38707c478bd9Sstevel@tonic-gate #endif /* NETINET */ 38717c478bd9Sstevel@tonic-gate 38727c478bd9Sstevel@tonic-gate #if NETINET6 38737c478bd9Sstevel@tonic-gate case AF_INET6: 38747c478bd9Sstevel@tonic-gate if (port > 0) 38757c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 38767c478bd9Sstevel@tonic-gate break; 38777c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 38787c478bd9Sstevel@tonic-gate } 38797c478bd9Sstevel@tonic-gate 38807c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 38817c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 38827c478bd9Sstevel@tonic-gate return hbuf; 38837c478bd9Sstevel@tonic-gate } 38847c478bd9Sstevel@tonic-gate /* 38857c478bd9Sstevel@tonic-gate ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 38867c478bd9Sstevel@tonic-gate ** 38877c478bd9Sstevel@tonic-gate ** Parameters: 38887c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 38897c478bd9Sstevel@tonic-gate ** name -- the (presumably unqualified) hostname. 38907c478bd9Sstevel@tonic-gate ** av -- unused -- for compatibility with other mapping 38917c478bd9Sstevel@tonic-gate ** functions. 38927c478bd9Sstevel@tonic-gate ** statp -- an exit status (out parameter) -- set to 38937c478bd9Sstevel@tonic-gate ** EX_TEMPFAIL if the name server is unavailable. 38947c478bd9Sstevel@tonic-gate ** 38957c478bd9Sstevel@tonic-gate ** Returns: 38967c478bd9Sstevel@tonic-gate ** The mapping, if found. 38977c478bd9Sstevel@tonic-gate ** NULL if no mapping found. 38987c478bd9Sstevel@tonic-gate ** 38997c478bd9Sstevel@tonic-gate ** Side Effects: 39007c478bd9Sstevel@tonic-gate ** Looks up the host specified in hbuf. If it is not 39017c478bd9Sstevel@tonic-gate ** the canonical name for that host, return the canonical 39027c478bd9Sstevel@tonic-gate ** name (unless MF_MATCHONLY is set, which will cause the 39037c478bd9Sstevel@tonic-gate ** status only to be returned). 39047c478bd9Sstevel@tonic-gate */ 39057c478bd9Sstevel@tonic-gate 39067c478bd9Sstevel@tonic-gate char * 39077c478bd9Sstevel@tonic-gate host_map_lookup(map, name, av, statp) 39087c478bd9Sstevel@tonic-gate MAP *map; 39097c478bd9Sstevel@tonic-gate char *name; 39107c478bd9Sstevel@tonic-gate char **av; 39117c478bd9Sstevel@tonic-gate int *statp; 39127c478bd9Sstevel@tonic-gate { 39137c478bd9Sstevel@tonic-gate register struct hostent *hp; 39147c478bd9Sstevel@tonic-gate #if NETINET 39157c478bd9Sstevel@tonic-gate struct in_addr in_addr; 39167c478bd9Sstevel@tonic-gate #endif /* NETINET */ 39177c478bd9Sstevel@tonic-gate #if NETINET6 39187c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 39197c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 39207c478bd9Sstevel@tonic-gate char *cp, *ans = NULL; 39217c478bd9Sstevel@tonic-gate register STAB *s; 39227c478bd9Sstevel@tonic-gate time_t now; 39237c478bd9Sstevel@tonic-gate #if NAMED_BIND 39247c478bd9Sstevel@tonic-gate time_t SM_NONVOLATILE retrans = 0; 39257c478bd9Sstevel@tonic-gate int SM_NONVOLATILE retry = 0; 39267c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 39277c478bd9Sstevel@tonic-gate char hbuf[MAXNAME + 1]; 39287c478bd9Sstevel@tonic-gate 39297c478bd9Sstevel@tonic-gate /* 39307c478bd9Sstevel@tonic-gate ** See if we have already looked up this name. If so, just 39317c478bd9Sstevel@tonic-gate ** return it (unless expired). 39327c478bd9Sstevel@tonic-gate */ 39337c478bd9Sstevel@tonic-gate 39347c478bd9Sstevel@tonic-gate now = curtime(); 39357c478bd9Sstevel@tonic-gate s = stab(name, ST_NAMECANON, ST_ENTER); 39367c478bd9Sstevel@tonic-gate if (bitset(NCF_VALID, s->s_namecanon.nc_flags) && 39377c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp >= now) 39387c478bd9Sstevel@tonic-gate { 39397c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39407c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => CACHE %s\n", 39417c478bd9Sstevel@tonic-gate name, 39427c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname == NULL 39437c478bd9Sstevel@tonic-gate ? "NULL" 39447c478bd9Sstevel@tonic-gate : s->s_namecanon.nc_cname); 39457c478bd9Sstevel@tonic-gate errno = s->s_namecanon.nc_errno; 39467c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 39477c478bd9Sstevel@tonic-gate *statp = s->s_namecanon.nc_stat; 39487c478bd9Sstevel@tonic-gate if (*statp == EX_TEMPFAIL) 39497c478bd9Sstevel@tonic-gate { 39507c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 39517c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 39527c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 39537c478bd9Sstevel@tonic-gate } 39547c478bd9Sstevel@tonic-gate if (*statp != EX_OK) 39557c478bd9Sstevel@tonic-gate return NULL; 39567c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname == NULL) 39577c478bd9Sstevel@tonic-gate { 39587c478bd9Sstevel@tonic-gate syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d", 39597c478bd9Sstevel@tonic-gate name, 39607c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno, 39617c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno); 39627c478bd9Sstevel@tonic-gate return NULL; 39637c478bd9Sstevel@tonic-gate } 39647c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 39657c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 39667c478bd9Sstevel@tonic-gate else 39677c478bd9Sstevel@tonic-gate cp = map_rewrite(map, 39687c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname, 39697c478bd9Sstevel@tonic-gate strlen(s->s_namecanon.nc_cname), 39707c478bd9Sstevel@tonic-gate av); 39717c478bd9Sstevel@tonic-gate return cp; 39727c478bd9Sstevel@tonic-gate } 39737c478bd9Sstevel@tonic-gate 39747c478bd9Sstevel@tonic-gate /* 39757c478bd9Sstevel@tonic-gate ** If we are running without a regular network connection (usually 39767c478bd9Sstevel@tonic-gate ** dial-on-demand) and we are just queueing, we want to avoid DNS 39777c478bd9Sstevel@tonic-gate ** lookups because those could try to connect to a server. 39787c478bd9Sstevel@tonic-gate */ 39797c478bd9Sstevel@tonic-gate 39807c478bd9Sstevel@tonic-gate if (CurEnv->e_sendmode == SM_DEFER && 39817c478bd9Sstevel@tonic-gate bitset(MF_DEFER, map->map_mflags)) 39827c478bd9Sstevel@tonic-gate { 39837c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39847c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name); 39857c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 39867c478bd9Sstevel@tonic-gate return NULL; 39877c478bd9Sstevel@tonic-gate } 39887c478bd9Sstevel@tonic-gate 39897c478bd9Sstevel@tonic-gate /* 39907c478bd9Sstevel@tonic-gate ** If first character is a bracket, then it is an address 39917c478bd9Sstevel@tonic-gate ** lookup. Address is copied into a temporary buffer to 39927c478bd9Sstevel@tonic-gate ** strip the brackets and to preserve name if address is 39937c478bd9Sstevel@tonic-gate ** unknown. 39947c478bd9Sstevel@tonic-gate */ 39957c478bd9Sstevel@tonic-gate 39967c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39977c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => ", name); 39987c478bd9Sstevel@tonic-gate #if NAMED_BIND 39997c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 40007c478bd9Sstevel@tonic-gate { 40017c478bd9Sstevel@tonic-gate retrans = _res.retrans; 40027c478bd9Sstevel@tonic-gate _res.retrans = map->map_timeout; 40037c478bd9Sstevel@tonic-gate } 40047c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 40057c478bd9Sstevel@tonic-gate { 40067c478bd9Sstevel@tonic-gate retry = _res.retry; 40077c478bd9Sstevel@tonic-gate _res.retry = map->map_retry; 40087c478bd9Sstevel@tonic-gate } 40097c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 40107c478bd9Sstevel@tonic-gate 40117c478bd9Sstevel@tonic-gate /* set default TTL */ 40127c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL; 40137c478bd9Sstevel@tonic-gate if (*name != '[') 40147c478bd9Sstevel@tonic-gate { 40157c478bd9Sstevel@tonic-gate int ttl; 40167c478bd9Sstevel@tonic-gate 4017058561cbSjbeck (void) sm_strlcpy(hbuf, name, sizeof(hbuf)); 4018058561cbSjbeck if (getcanonname(hbuf, sizeof(hbuf) - 1, !HasWildcardMX, &ttl)) 40197c478bd9Sstevel@tonic-gate { 40207c478bd9Sstevel@tonic-gate ans = hbuf; 40217c478bd9Sstevel@tonic-gate if (ttl > 0) 40227c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_MIN(ttl, 40237c478bd9Sstevel@tonic-gate SM_DEFAULT_TTL); 40247c478bd9Sstevel@tonic-gate } 40257c478bd9Sstevel@tonic-gate } 40267c478bd9Sstevel@tonic-gate else 40277c478bd9Sstevel@tonic-gate { 40287c478bd9Sstevel@tonic-gate if ((cp = strchr(name, ']')) == NULL) 40297c478bd9Sstevel@tonic-gate { 40307c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40317c478bd9Sstevel@tonic-gate sm_dprintf("FAILED\n"); 40327c478bd9Sstevel@tonic-gate return NULL; 40337c478bd9Sstevel@tonic-gate } 40347c478bd9Sstevel@tonic-gate *cp = '\0'; 40357c478bd9Sstevel@tonic-gate 40367c478bd9Sstevel@tonic-gate hp = NULL; 40377c478bd9Sstevel@tonic-gate #if NETINET 40387c478bd9Sstevel@tonic-gate if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 40397c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in_addr, 40407c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 40417c478bd9Sstevel@tonic-gate #endif /* NETINET */ 40427c478bd9Sstevel@tonic-gate #if NETINET6 40437c478bd9Sstevel@tonic-gate if (hp == NULL && 40447c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &name[1], &in6_addr) == 1) 40457c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in6_addr, 40467c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 40477c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 40487c478bd9Sstevel@tonic-gate *cp = ']'; 40497c478bd9Sstevel@tonic-gate 40507c478bd9Sstevel@tonic-gate if (hp != NULL) 40517c478bd9Sstevel@tonic-gate { 40527c478bd9Sstevel@tonic-gate /* found a match -- copy out */ 40537c478bd9Sstevel@tonic-gate ans = denlstring((char *) hp->h_name, true, true); 40547c478bd9Sstevel@tonic-gate #if NETINET6 40557c478bd9Sstevel@tonic-gate if (ans == hp->h_name) 40567c478bd9Sstevel@tonic-gate { 40577c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 40587c478bd9Sstevel@tonic-gate 40597c478bd9Sstevel@tonic-gate /* hp->h_name is about to disappear */ 4060058561cbSjbeck (void) sm_strlcpy(n, ans, sizeof(n)); 40617c478bd9Sstevel@tonic-gate ans = n; 40627c478bd9Sstevel@tonic-gate } 40637c478bd9Sstevel@tonic-gate freehostent(hp); 40647c478bd9Sstevel@tonic-gate hp = NULL; 40657c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 40667c478bd9Sstevel@tonic-gate } 40677c478bd9Sstevel@tonic-gate } 40687c478bd9Sstevel@tonic-gate #if NAMED_BIND 40697c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 40707c478bd9Sstevel@tonic-gate _res.retrans = retrans; 40717c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 40727c478bd9Sstevel@tonic-gate _res.retry = retry; 40737c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 40747c478bd9Sstevel@tonic-gate 40757c478bd9Sstevel@tonic-gate s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 40767c478bd9Sstevel@tonic-gate 40777c478bd9Sstevel@tonic-gate /* Found an answer */ 40787c478bd9Sstevel@tonic-gate if (ans != NULL) 40797c478bd9Sstevel@tonic-gate { 40807c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp = EX_OK; 40817c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname != NULL) 40827c478bd9Sstevel@tonic-gate sm_free(s->s_namecanon.nc_cname); 40837c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname = sm_strdup_x(ans); 40847c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 40857c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 40867c478bd9Sstevel@tonic-gate else 40877c478bd9Sstevel@tonic-gate cp = map_rewrite(map, ans, strlen(ans), av); 40887c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40897c478bd9Sstevel@tonic-gate sm_dprintf("FOUND %s\n", ans); 40907c478bd9Sstevel@tonic-gate return cp; 40917c478bd9Sstevel@tonic-gate } 40927c478bd9Sstevel@tonic-gate 40937c478bd9Sstevel@tonic-gate 40947c478bd9Sstevel@tonic-gate /* No match found */ 40957c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno = errno; 40967c478bd9Sstevel@tonic-gate #if NAMED_BIND 40977c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno = h_errno; 40987c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40997c478bd9Sstevel@tonic-gate sm_dprintf("FAIL (%d)\n", h_errno); 41007c478bd9Sstevel@tonic-gate switch (h_errno) 41017c478bd9Sstevel@tonic-gate { 41027c478bd9Sstevel@tonic-gate case TRY_AGAIN: 41037c478bd9Sstevel@tonic-gate if (UseNameServer) 41047c478bd9Sstevel@tonic-gate { 41057c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 41067c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 41077c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 41087c478bd9Sstevel@tonic-gate } 41097c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 41107c478bd9Sstevel@tonic-gate break; 41117c478bd9Sstevel@tonic-gate 41127c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND: 41137c478bd9Sstevel@tonic-gate case NO_DATA: 41147c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 41157c478bd9Sstevel@tonic-gate break; 41167c478bd9Sstevel@tonic-gate 41177c478bd9Sstevel@tonic-gate case NO_RECOVERY: 41187c478bd9Sstevel@tonic-gate *statp = EX_SOFTWARE; 41197c478bd9Sstevel@tonic-gate break; 41207c478bd9Sstevel@tonic-gate 41217c478bd9Sstevel@tonic-gate default: 41227c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 41237c478bd9Sstevel@tonic-gate break; 41247c478bd9Sstevel@tonic-gate } 41257c478bd9Sstevel@tonic-gate #else /* NAMED_BIND */ 41267c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 41277c478bd9Sstevel@tonic-gate sm_dprintf("FAIL\n"); 41287c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 41297c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 41307c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp; 41317c478bd9Sstevel@tonic-gate return NULL; 41327c478bd9Sstevel@tonic-gate } 41337c478bd9Sstevel@tonic-gate /* 41347c478bd9Sstevel@tonic-gate ** HOST_MAP_INIT -- initialize host class structures 41357c478bd9Sstevel@tonic-gate ** 41367c478bd9Sstevel@tonic-gate ** Parameters: 41377c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 41387c478bd9Sstevel@tonic-gate ** args -- argument string. 41397c478bd9Sstevel@tonic-gate ** 41407c478bd9Sstevel@tonic-gate ** Returns: 41417c478bd9Sstevel@tonic-gate ** true. 41427c478bd9Sstevel@tonic-gate */ 41437c478bd9Sstevel@tonic-gate 41447c478bd9Sstevel@tonic-gate bool 41457c478bd9Sstevel@tonic-gate host_map_init(map, args) 41467c478bd9Sstevel@tonic-gate MAP *map; 41477c478bd9Sstevel@tonic-gate char *args; 41487c478bd9Sstevel@tonic-gate { 41497c478bd9Sstevel@tonic-gate register char *p = args; 41507c478bd9Sstevel@tonic-gate 41517c478bd9Sstevel@tonic-gate for (;;) 41527c478bd9Sstevel@tonic-gate { 41537c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 41547c478bd9Sstevel@tonic-gate p++; 41557c478bd9Sstevel@tonic-gate if (*p != '-') 41567c478bd9Sstevel@tonic-gate break; 41577c478bd9Sstevel@tonic-gate switch (*++p) 41587c478bd9Sstevel@tonic-gate { 41597c478bd9Sstevel@tonic-gate case 'a': 41607c478bd9Sstevel@tonic-gate map->map_app = ++p; 41617c478bd9Sstevel@tonic-gate break; 41627c478bd9Sstevel@tonic-gate 41637c478bd9Sstevel@tonic-gate case 'T': 41647c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 41657c478bd9Sstevel@tonic-gate break; 41667c478bd9Sstevel@tonic-gate 41677c478bd9Sstevel@tonic-gate case 'm': 41687c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 41697c478bd9Sstevel@tonic-gate break; 41707c478bd9Sstevel@tonic-gate 41717c478bd9Sstevel@tonic-gate case 't': 41727c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 41737c478bd9Sstevel@tonic-gate break; 41747c478bd9Sstevel@tonic-gate 41757c478bd9Sstevel@tonic-gate case 'S': /* only for consistency */ 41767c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 41777c478bd9Sstevel@tonic-gate break; 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate case 'D': 41807c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 41817c478bd9Sstevel@tonic-gate break; 41827c478bd9Sstevel@tonic-gate 41837c478bd9Sstevel@tonic-gate case 'd': 41847c478bd9Sstevel@tonic-gate { 41857c478bd9Sstevel@tonic-gate char *h; 41867c478bd9Sstevel@tonic-gate 41877c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41887c478bd9Sstevel@tonic-gate continue; 41897c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 41907c478bd9Sstevel@tonic-gate if (h != NULL) 41917c478bd9Sstevel@tonic-gate *h = '\0'; 41927c478bd9Sstevel@tonic-gate map->map_timeout = convtime(p, 's'); 41937c478bd9Sstevel@tonic-gate if (h != NULL) 41947c478bd9Sstevel@tonic-gate *h = ' '; 41957c478bd9Sstevel@tonic-gate } 41967c478bd9Sstevel@tonic-gate break; 41977c478bd9Sstevel@tonic-gate 41987c478bd9Sstevel@tonic-gate case 'r': 41997c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 42007c478bd9Sstevel@tonic-gate continue; 42017c478bd9Sstevel@tonic-gate map->map_retry = atoi(p); 42027c478bd9Sstevel@tonic-gate break; 42037c478bd9Sstevel@tonic-gate } 42047c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 42057c478bd9Sstevel@tonic-gate p++; 42067c478bd9Sstevel@tonic-gate if (*p != '\0') 42077c478bd9Sstevel@tonic-gate *p++ = '\0'; 42087c478bd9Sstevel@tonic-gate } 42097c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 42107c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 42117c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 42127c478bd9Sstevel@tonic-gate map->map_tapp = newstr(map->map_tapp); 42137c478bd9Sstevel@tonic-gate return true; 42147c478bd9Sstevel@tonic-gate } 42157c478bd9Sstevel@tonic-gate 42167c478bd9Sstevel@tonic-gate #if NETINET6 42177c478bd9Sstevel@tonic-gate /* 42187c478bd9Sstevel@tonic-gate ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 42197c478bd9Sstevel@tonic-gate ** 42207c478bd9Sstevel@tonic-gate ** Parameters: 42217c478bd9Sstevel@tonic-gate ** s6a -- a pointer to an in6_addr structure. 42227c478bd9Sstevel@tonic-gate ** dst -- buffer to store result in 42237c478bd9Sstevel@tonic-gate ** dst_len -- size of dst buffer 42247c478bd9Sstevel@tonic-gate ** 42257c478bd9Sstevel@tonic-gate ** Returns: 42267c478bd9Sstevel@tonic-gate ** A printable version of that structure. 42277c478bd9Sstevel@tonic-gate */ 42287c478bd9Sstevel@tonic-gate 42297c478bd9Sstevel@tonic-gate char * 42307c478bd9Sstevel@tonic-gate anynet_ntop(s6a, dst, dst_len) 42317c478bd9Sstevel@tonic-gate struct in6_addr *s6a; 42327c478bd9Sstevel@tonic-gate char *dst; 42337c478bd9Sstevel@tonic-gate size_t dst_len; 42347c478bd9Sstevel@tonic-gate { 42357c478bd9Sstevel@tonic-gate register char *ap; 42367c478bd9Sstevel@tonic-gate 42377c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(s6a)) 42387c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET, 42397c478bd9Sstevel@tonic-gate &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 42407c478bd9Sstevel@tonic-gate dst, dst_len); 42417c478bd9Sstevel@tonic-gate else 42427c478bd9Sstevel@tonic-gate { 42437c478bd9Sstevel@tonic-gate char *d; 42447c478bd9Sstevel@tonic-gate size_t sz; 42457c478bd9Sstevel@tonic-gate 42467c478bd9Sstevel@tonic-gate /* Save pointer to beginning of string */ 42477c478bd9Sstevel@tonic-gate d = dst; 42487c478bd9Sstevel@tonic-gate 42497c478bd9Sstevel@tonic-gate /* Add IPv6: protocol tag */ 42507c478bd9Sstevel@tonic-gate sz = sm_strlcpy(dst, "IPv6:", dst_len); 42517c478bd9Sstevel@tonic-gate if (sz >= dst_len) 42527c478bd9Sstevel@tonic-gate return NULL; 42537c478bd9Sstevel@tonic-gate dst += sz; 42547c478bd9Sstevel@tonic-gate dst_len -= sz; 42557c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 42567c478bd9Sstevel@tonic-gate 42577c478bd9Sstevel@tonic-gate /* Restore pointer to beginning of string */ 42587c478bd9Sstevel@tonic-gate if (ap != NULL) 42597c478bd9Sstevel@tonic-gate ap = d; 42607c478bd9Sstevel@tonic-gate } 42617c478bd9Sstevel@tonic-gate return ap; 42627c478bd9Sstevel@tonic-gate } 42637c478bd9Sstevel@tonic-gate 42647c478bd9Sstevel@tonic-gate /* 42657c478bd9Sstevel@tonic-gate ** ANYNET_PTON -- convert printed form to network address. 42667c478bd9Sstevel@tonic-gate ** 42677c478bd9Sstevel@tonic-gate ** Wrapper for inet_pton() which handles IPv6: labels. 42687c478bd9Sstevel@tonic-gate ** 42697c478bd9Sstevel@tonic-gate ** Parameters: 42707c478bd9Sstevel@tonic-gate ** family -- address family 42717c478bd9Sstevel@tonic-gate ** src -- string 42727c478bd9Sstevel@tonic-gate ** dst -- destination address structure 42737c478bd9Sstevel@tonic-gate ** 42747c478bd9Sstevel@tonic-gate ** Returns: 42757c478bd9Sstevel@tonic-gate ** 1 if the address was valid 42767c478bd9Sstevel@tonic-gate ** 0 if the address wasn't parseable 42777c478bd9Sstevel@tonic-gate ** -1 if error 42787c478bd9Sstevel@tonic-gate */ 42797c478bd9Sstevel@tonic-gate 42807c478bd9Sstevel@tonic-gate int 42817c478bd9Sstevel@tonic-gate anynet_pton(family, src, dst) 42827c478bd9Sstevel@tonic-gate int family; 42837c478bd9Sstevel@tonic-gate const char *src; 42847c478bd9Sstevel@tonic-gate void *dst; 42857c478bd9Sstevel@tonic-gate { 42867c478bd9Sstevel@tonic-gate if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0) 42877c478bd9Sstevel@tonic-gate src += 5; 42887c478bd9Sstevel@tonic-gate return inet_pton(family, src, dst); 42897c478bd9Sstevel@tonic-gate } 42907c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 42917c478bd9Sstevel@tonic-gate /* 42927c478bd9Sstevel@tonic-gate ** ANYNET_NTOA -- convert a network address to printable form. 42937c478bd9Sstevel@tonic-gate ** 42947c478bd9Sstevel@tonic-gate ** Parameters: 42957c478bd9Sstevel@tonic-gate ** sap -- a pointer to a sockaddr structure. 42967c478bd9Sstevel@tonic-gate ** 42977c478bd9Sstevel@tonic-gate ** Returns: 42987c478bd9Sstevel@tonic-gate ** A printable version of that sockaddr. 42997c478bd9Sstevel@tonic-gate */ 43007c478bd9Sstevel@tonic-gate 43017c478bd9Sstevel@tonic-gate #ifdef USE_SOCK_STREAM 43027c478bd9Sstevel@tonic-gate 43037c478bd9Sstevel@tonic-gate # if NETLINK 43047c478bd9Sstevel@tonic-gate # include <net/if_dl.h> 43057c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 43067c478bd9Sstevel@tonic-gate 43077c478bd9Sstevel@tonic-gate char * 43087c478bd9Sstevel@tonic-gate anynet_ntoa(sap) 43097c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 43107c478bd9Sstevel@tonic-gate { 43117c478bd9Sstevel@tonic-gate register char *bp; 43127c478bd9Sstevel@tonic-gate register char *ap; 43137c478bd9Sstevel@tonic-gate int l; 43147c478bd9Sstevel@tonic-gate static char buf[100]; 43157c478bd9Sstevel@tonic-gate 43167c478bd9Sstevel@tonic-gate /* check for null/zero family */ 43177c478bd9Sstevel@tonic-gate if (sap == NULL) 43187c478bd9Sstevel@tonic-gate return "NULLADDR"; 43197c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == 0) 43207c478bd9Sstevel@tonic-gate return "0"; 43217c478bd9Sstevel@tonic-gate 43227c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 43237c478bd9Sstevel@tonic-gate { 43247c478bd9Sstevel@tonic-gate # if NETUNIX 43257c478bd9Sstevel@tonic-gate case AF_UNIX: 43267c478bd9Sstevel@tonic-gate if (sap->sunix.sun_path[0] != '\0') 4327058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[UNIX: %.64s]", 43287c478bd9Sstevel@tonic-gate sap->sunix.sun_path); 43297c478bd9Sstevel@tonic-gate else 4330058561cbSjbeck (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof(buf)); 43317c478bd9Sstevel@tonic-gate return buf; 43327c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 43337c478bd9Sstevel@tonic-gate 43347c478bd9Sstevel@tonic-gate # if NETINET 43357c478bd9Sstevel@tonic-gate case AF_INET: 43367c478bd9Sstevel@tonic-gate return (char *) inet_ntoa(sap->sin.sin_addr); 43377c478bd9Sstevel@tonic-gate # endif /* NETINET */ 43387c478bd9Sstevel@tonic-gate 43397c478bd9Sstevel@tonic-gate # if NETINET6 43407c478bd9Sstevel@tonic-gate case AF_INET6: 4341058561cbSjbeck ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof(buf)); 43427c478bd9Sstevel@tonic-gate if (ap != NULL) 43437c478bd9Sstevel@tonic-gate return ap; 43447c478bd9Sstevel@tonic-gate break; 43457c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 43467c478bd9Sstevel@tonic-gate 43477c478bd9Sstevel@tonic-gate # if NETLINK 43487c478bd9Sstevel@tonic-gate case AF_LINK: 4349058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[LINK: %s]", 43507c478bd9Sstevel@tonic-gate link_ntoa((struct sockaddr_dl *) &sap->sa)); 43517c478bd9Sstevel@tonic-gate return buf; 43527c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 43537c478bd9Sstevel@tonic-gate default: 43547c478bd9Sstevel@tonic-gate /* this case is needed when nothing is #defined */ 43557c478bd9Sstevel@tonic-gate /* in order to keep the switch syntactically correct */ 43567c478bd9Sstevel@tonic-gate break; 43577c478bd9Sstevel@tonic-gate } 43587c478bd9Sstevel@tonic-gate 43597c478bd9Sstevel@tonic-gate /* unknown family -- just dump bytes */ 4360058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "Family %d: ", sap->sa.sa_family); 43617c478bd9Sstevel@tonic-gate bp = &buf[strlen(buf)]; 43627c478bd9Sstevel@tonic-gate ap = sap->sa.sa_data; 4363058561cbSjbeck for (l = sizeof(sap->sa.sa_data); --l >= 0; ) 43647c478bd9Sstevel@tonic-gate { 43657c478bd9Sstevel@tonic-gate (void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:", 43667c478bd9Sstevel@tonic-gate *ap++ & 0377); 43677c478bd9Sstevel@tonic-gate bp += 3; 43687c478bd9Sstevel@tonic-gate } 43697c478bd9Sstevel@tonic-gate *--bp = '\0'; 43707c478bd9Sstevel@tonic-gate return buf; 43717c478bd9Sstevel@tonic-gate } 43727c478bd9Sstevel@tonic-gate /* 43737c478bd9Sstevel@tonic-gate ** HOSTNAMEBYANYADDR -- return name of host based on address 43747c478bd9Sstevel@tonic-gate ** 43757c478bd9Sstevel@tonic-gate ** Parameters: 43767c478bd9Sstevel@tonic-gate ** sap -- SOCKADDR pointer 43777c478bd9Sstevel@tonic-gate ** 43787c478bd9Sstevel@tonic-gate ** Returns: 43797c478bd9Sstevel@tonic-gate ** text representation of host name. 43807c478bd9Sstevel@tonic-gate ** 43817c478bd9Sstevel@tonic-gate ** Side Effects: 43827c478bd9Sstevel@tonic-gate ** none. 43837c478bd9Sstevel@tonic-gate */ 43847c478bd9Sstevel@tonic-gate 43857c478bd9Sstevel@tonic-gate char * 43867c478bd9Sstevel@tonic-gate hostnamebyanyaddr(sap) 43877c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 43887c478bd9Sstevel@tonic-gate { 43897c478bd9Sstevel@tonic-gate register struct hostent *hp; 43907c478bd9Sstevel@tonic-gate # if NAMED_BIND 43917c478bd9Sstevel@tonic-gate int saveretry; 43927c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 43937c478bd9Sstevel@tonic-gate # if NETINET6 43947c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 43957c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 43967c478bd9Sstevel@tonic-gate 43977c478bd9Sstevel@tonic-gate # if NAMED_BIND 43987c478bd9Sstevel@tonic-gate /* shorten name server timeout to avoid higher level timeouts */ 43997c478bd9Sstevel@tonic-gate saveretry = _res.retry; 44007c478bd9Sstevel@tonic-gate if (_res.retry * _res.retrans > 20) 44017c478bd9Sstevel@tonic-gate _res.retry = 20 / _res.retrans; 44027c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 44037c478bd9Sstevel@tonic-gate 44047c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 44057c478bd9Sstevel@tonic-gate { 44067c478bd9Sstevel@tonic-gate # if NETINET 44077c478bd9Sstevel@tonic-gate case AF_INET: 44087c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 44097c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 44107c478bd9Sstevel@tonic-gate break; 44117c478bd9Sstevel@tonic-gate # endif /* NETINET */ 44127c478bd9Sstevel@tonic-gate 44137c478bd9Sstevel@tonic-gate # if NETINET6 44147c478bd9Sstevel@tonic-gate case AF_INET6: 44157c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 44167c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 44177c478bd9Sstevel@tonic-gate break; 44187c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44197c478bd9Sstevel@tonic-gate 44207c478bd9Sstevel@tonic-gate # if NETISO 44217c478bd9Sstevel@tonic-gate case AF_ISO: 44227c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 4423058561cbSjbeck sizeof(sap->siso.siso_addr), AF_ISO); 44247c478bd9Sstevel@tonic-gate break; 44257c478bd9Sstevel@tonic-gate # endif /* NETISO */ 44267c478bd9Sstevel@tonic-gate 44277c478bd9Sstevel@tonic-gate # if NETUNIX 44287c478bd9Sstevel@tonic-gate case AF_UNIX: 44297c478bd9Sstevel@tonic-gate hp = NULL; 44307c478bd9Sstevel@tonic-gate break; 44317c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 44327c478bd9Sstevel@tonic-gate 44337c478bd9Sstevel@tonic-gate default: 4434058561cbSjbeck hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof(sap->sa.sa_data), 44357c478bd9Sstevel@tonic-gate sap->sa.sa_family); 44367c478bd9Sstevel@tonic-gate break; 44377c478bd9Sstevel@tonic-gate } 44387c478bd9Sstevel@tonic-gate 44397c478bd9Sstevel@tonic-gate # if NAMED_BIND 44407c478bd9Sstevel@tonic-gate _res.retry = saveretry; 44417c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 44427c478bd9Sstevel@tonic-gate 44437c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 44447c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_name[0] != '[' 44457c478bd9Sstevel@tonic-gate # if NETINET6 44467c478bd9Sstevel@tonic-gate && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 44477c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44487c478bd9Sstevel@tonic-gate # if NETINET 44497c478bd9Sstevel@tonic-gate && inet_addr(hp->h_name) == INADDR_NONE 44507c478bd9Sstevel@tonic-gate # endif /* NETINET */ 44517c478bd9Sstevel@tonic-gate ) 44527c478bd9Sstevel@tonic-gate { 44537c478bd9Sstevel@tonic-gate char *name; 44547c478bd9Sstevel@tonic-gate 44557c478bd9Sstevel@tonic-gate name = denlstring((char *) hp->h_name, true, true); 44567c478bd9Sstevel@tonic-gate # if NETINET6 44577c478bd9Sstevel@tonic-gate if (name == hp->h_name) 44587c478bd9Sstevel@tonic-gate { 44597c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 44607c478bd9Sstevel@tonic-gate 44617c478bd9Sstevel@tonic-gate /* Copy the string, hp->h_name is about to disappear */ 4462058561cbSjbeck (void) sm_strlcpy(n, name, sizeof(n)); 44637c478bd9Sstevel@tonic-gate name = n; 44647c478bd9Sstevel@tonic-gate } 44657c478bd9Sstevel@tonic-gate freehostent(hp); 44667c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44677c478bd9Sstevel@tonic-gate return name; 44687c478bd9Sstevel@tonic-gate } 44697c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 44707c478bd9Sstevel@tonic-gate 44717c478bd9Sstevel@tonic-gate # if NETINET6 44727c478bd9Sstevel@tonic-gate if (hp != NULL) 44737c478bd9Sstevel@tonic-gate { 44747c478bd9Sstevel@tonic-gate freehostent(hp); 44757c478bd9Sstevel@tonic-gate hp = NULL; 44767c478bd9Sstevel@tonic-gate } 44777c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44787c478bd9Sstevel@tonic-gate 44797c478bd9Sstevel@tonic-gate # if NETUNIX 44807c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 44817c478bd9Sstevel@tonic-gate return "localhost"; 44827c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 44837c478bd9Sstevel@tonic-gate { 44847c478bd9Sstevel@tonic-gate static char buf[203]; 44857c478bd9Sstevel@tonic-gate 4486058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[%.200s]", 44877c478bd9Sstevel@tonic-gate anynet_ntoa(sap)); 44887c478bd9Sstevel@tonic-gate return buf; 44897c478bd9Sstevel@tonic-gate } 44907c478bd9Sstevel@tonic-gate } 44917c478bd9Sstevel@tonic-gate #endif /* USE_SOCK_STREAM */ 4492