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