17c478bd9Sstevel@tonic-gate /* 2445f2479Sjbeck * Copyright (c) 1998-2006 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> 17*058561cbSjbeck #include "map.h" 187c478bd9Sstevel@tonic-gate 19*058561cbSjbeck SM_RCSID("@(#)$Id: daemon.c,v 8.676 2006/12/19 01:15:06 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 64*058561cbSjbeck #define DAEMON_C 1 65*058561cbSjbeck #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; 141*058561cbSjbeck 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 193*058561cbSjbeck 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; 238*058561cbSjbeck 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 274*058561cbSjbeck 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', 397*058561cbSjbeck 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 431*058561cbSjbeck lotherend = sizeof(sa_un); 432*058561cbSjbeck 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, 601*058561cbSjbeck sizeof(NextDiskSpaceCheck)); 602*058561cbSjbeck RAND_seed((void *) &now, sizeof(now)); 603*058561cbSjbeck 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)); 694*058561cbSjbeck (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; 728*058561cbSjbeck 729*058561cbSjbeck /* 730*058561cbSjbeck ** Hack: override global variables if 731*058561cbSjbeck ** the corresponding DaemonPortOption 732*058561cbSjbeck ** is set. 733*058561cbSjbeck */ 7347c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 7357c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_supersafe != 736*058561cbSjbeck DPO_NOTSET) 737*058561cbSjbeck SuperSafe = Daemons[curdaemon]. 738*058561cbSjbeck 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); 743*058561cbSjbeck 744*058561cbSjbeck if (Daemons[curdaemon].d_refuseLA != 745*058561cbSjbeck DPO_NOTSET) 746*058561cbSjbeck RefuseLA = Daemons[curdaemon]. 747*058561cbSjbeck d_refuseLA; 748*058561cbSjbeck if (Daemons[curdaemon].d_queueLA != DPO_NOTSET) 749*058561cbSjbeck QueueLA = Daemons[curdaemon].d_queueLA; 750*058561cbSjbeck if (Daemons[curdaemon].d_delayLA != DPO_NOTSET) 751*058561cbSjbeck DelayLA = Daemons[curdaemon].d_delayLA; 752*058561cbSjbeck if (Daemons[curdaemon].d_maxchildren != 753*058561cbSjbeck DPO_NOTSET) 754*058561cbSjbeck MaxChildren = Daemons[curdaemon]. 755*058561cbSjbeck 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 { 900*058561cbSjbeck (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 { 906*058561cbSjbeck (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, 1129*058561cbSjbeck sizeof(on)); 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1132*058561cbSjbeck SO_REUSEADDR, (char *)&on, sizeof(on)); 11337c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1134*058561cbSjbeck 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: 1175*058561cbSjbeck 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: 1181*058561cbSjbeck 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: 1187*058561cbSjbeck 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: 1193*058561cbSjbeck socksize = sizeof(d->d_addr.siso); 11947c478bd9Sstevel@tonic-gate break; 11957c478bd9Sstevel@tonic-gate #endif /* NETISO */ 11967c478bd9Sstevel@tonic-gate 11977c478bd9Sstevel@tonic-gate default: 1198*058561cbSjbeck 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 { 1251*058561cbSjbeck 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) 12627c478bd9Sstevel@tonic-gate daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 12637c478bd9Sstevel@tonic-gate port = daemonaddr->sin.sin_port; 12647c478bd9Sstevel@tonic-gate break; 12657c478bd9Sstevel@tonic-gate #endif /* NETINET */ 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate #if NETINET6 12687c478bd9Sstevel@tonic-gate case AF_INET6: 12697c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 12707c478bd9Sstevel@tonic-gate daemonaddr->sin6.sin6_addr = in6addr_any; 12717c478bd9Sstevel@tonic-gate port = daemonaddr->sin6.sin6_port; 12727c478bd9Sstevel@tonic-gate break; 12737c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate default: 12767c478bd9Sstevel@tonic-gate /* unknown protocol */ 12777c478bd9Sstevel@tonic-gate port = 0; 12787c478bd9Sstevel@tonic-gate break; 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate if (port == 0) 12817c478bd9Sstevel@tonic-gate { 12827c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 12837c478bd9Sstevel@tonic-gate port = htons(25); 12847c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 12857c478bd9Sstevel@tonic-gate { 12867c478bd9Sstevel@tonic-gate register struct servent *sp; 12877c478bd9Sstevel@tonic-gate 12887c478bd9Sstevel@tonic-gate sp = getservbyname("smtp", "tcp"); 12897c478bd9Sstevel@tonic-gate if (sp == NULL) 12907c478bd9Sstevel@tonic-gate { 12917c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"smtp\" unknown"); 12927c478bd9Sstevel@tonic-gate port = htons(25); 12937c478bd9Sstevel@tonic-gate } 12947c478bd9Sstevel@tonic-gate else 12957c478bd9Sstevel@tonic-gate port = sp->s_port; 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate switch (daemonaddr->sa.sa_family) 13017c478bd9Sstevel@tonic-gate { 13027c478bd9Sstevel@tonic-gate #if NETINET 13037c478bd9Sstevel@tonic-gate case AF_INET: 13047c478bd9Sstevel@tonic-gate daemonaddr->sin.sin_port = port; 13057c478bd9Sstevel@tonic-gate break; 13067c478bd9Sstevel@tonic-gate #endif /* NETINET */ 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate #if NETINET6 13097c478bd9Sstevel@tonic-gate case AF_INET6: 13107c478bd9Sstevel@tonic-gate daemonaddr->sin6.sin6_port = port; 13117c478bd9Sstevel@tonic-gate break; 13127c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate default: 13157c478bd9Sstevel@tonic-gate /* unknown protocol */ 13167c478bd9Sstevel@tonic-gate break; 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate return port; 13197c478bd9Sstevel@tonic-gate } 13207c478bd9Sstevel@tonic-gate /* 13217c478bd9Sstevel@tonic-gate ** CLRDAEMON -- reset the daemon connection 13227c478bd9Sstevel@tonic-gate ** 13237c478bd9Sstevel@tonic-gate ** Parameters: 13247c478bd9Sstevel@tonic-gate ** none. 13257c478bd9Sstevel@tonic-gate ** 13267c478bd9Sstevel@tonic-gate ** Returns: 13277c478bd9Sstevel@tonic-gate ** none. 13287c478bd9Sstevel@tonic-gate ** 13297c478bd9Sstevel@tonic-gate ** Side Effects: 13307c478bd9Sstevel@tonic-gate ** releases any resources used by the passive daemon. 13317c478bd9Sstevel@tonic-gate */ 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate void 13347c478bd9Sstevel@tonic-gate clrdaemon() 13357c478bd9Sstevel@tonic-gate { 13367c478bd9Sstevel@tonic-gate int i; 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 13397c478bd9Sstevel@tonic-gate { 13407c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 13417c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 13427c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 13437c478bd9Sstevel@tonic-gate } 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate /* 13477c478bd9Sstevel@tonic-gate ** GETMODIFIERS -- get modifier flags 13487c478bd9Sstevel@tonic-gate ** 13497c478bd9Sstevel@tonic-gate ** Parameters: 13507c478bd9Sstevel@tonic-gate ** v -- the modifiers (input text line). 13517c478bd9Sstevel@tonic-gate ** modifiers -- pointer to flag field to represent modifiers. 13527c478bd9Sstevel@tonic-gate ** 13537c478bd9Sstevel@tonic-gate ** Returns: 13547c478bd9Sstevel@tonic-gate ** (xallocat()ed) string representation of modifiers. 13557c478bd9Sstevel@tonic-gate ** 13567c478bd9Sstevel@tonic-gate ** Side Effects: 13577c478bd9Sstevel@tonic-gate ** fills in modifiers. 13587c478bd9Sstevel@tonic-gate */ 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate char * 13617c478bd9Sstevel@tonic-gate getmodifiers(v, modifiers) 13627c478bd9Sstevel@tonic-gate char *v; 13637c478bd9Sstevel@tonic-gate BITMAP256 modifiers; 13647c478bd9Sstevel@tonic-gate { 13657c478bd9Sstevel@tonic-gate int l; 13667c478bd9Sstevel@tonic-gate char *h, *f, *flags; 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* maximum length of flags: upper case Option -> "OO " */ 13697c478bd9Sstevel@tonic-gate l = 3 * strlen(v) + 3; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate /* is someone joking? */ 13727c478bd9Sstevel@tonic-gate if (l < 0 || l > 256) 13737c478bd9Sstevel@tonic-gate { 13747c478bd9Sstevel@tonic-gate if (LogLevel > 2) 13757c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 13767c478bd9Sstevel@tonic-gate "getmodifiers too long, ignored"); 13777c478bd9Sstevel@tonic-gate return NULL; 13787c478bd9Sstevel@tonic-gate } 13797c478bd9Sstevel@tonic-gate flags = xalloc(l); 13807c478bd9Sstevel@tonic-gate f = flags; 13817c478bd9Sstevel@tonic-gate clrbitmap(modifiers); 13827c478bd9Sstevel@tonic-gate for (h = v; *h != '\0'; h++) 13837c478bd9Sstevel@tonic-gate { 13847c478bd9Sstevel@tonic-gate if (isascii(*h) && !isspace(*h) && isprint(*h)) 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate setbitn(*h, modifiers); 13877c478bd9Sstevel@tonic-gate if (flags != f) 13887c478bd9Sstevel@tonic-gate *flags++ = ' '; 13897c478bd9Sstevel@tonic-gate *flags++ = *h; 13907c478bd9Sstevel@tonic-gate if (isupper(*h)) 13917c478bd9Sstevel@tonic-gate *flags++ = *h; 13927c478bd9Sstevel@tonic-gate } 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate *flags++ = '\0'; 13957c478bd9Sstevel@tonic-gate return f; 13967c478bd9Sstevel@tonic-gate } 13977c478bd9Sstevel@tonic-gate 13987c478bd9Sstevel@tonic-gate /* 13997c478bd9Sstevel@tonic-gate ** CHKDAEMONMODIFIERS -- check whether all daemons have set a flag. 14007c478bd9Sstevel@tonic-gate ** 14017c478bd9Sstevel@tonic-gate ** Parameters: 14027c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 14037c478bd9Sstevel@tonic-gate ** 14047c478bd9Sstevel@tonic-gate ** Returns: 14057c478bd9Sstevel@tonic-gate ** true iff all daemons have set flag. 14067c478bd9Sstevel@tonic-gate */ 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate bool 14097c478bd9Sstevel@tonic-gate chkdaemonmodifiers(flag) 14107c478bd9Sstevel@tonic-gate int flag; 14117c478bd9Sstevel@tonic-gate { 14127c478bd9Sstevel@tonic-gate int i; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 14157c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, Daemons[i].d_flags)) 14167c478bd9Sstevel@tonic-gate return false; 14177c478bd9Sstevel@tonic-gate return true; 14187c478bd9Sstevel@tonic-gate } 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate /* 14217c478bd9Sstevel@tonic-gate ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 14227c478bd9Sstevel@tonic-gate ** 14237c478bd9Sstevel@tonic-gate ** Parameters: 14247c478bd9Sstevel@tonic-gate ** p -- the options line. 14257c478bd9Sstevel@tonic-gate ** d -- the daemon structure to fill in. 14267c478bd9Sstevel@tonic-gate ** 14277c478bd9Sstevel@tonic-gate ** Returns: 14287c478bd9Sstevel@tonic-gate ** none. 14297c478bd9Sstevel@tonic-gate */ 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate static void 14327c478bd9Sstevel@tonic-gate setsockaddroptions(p, d) 14337c478bd9Sstevel@tonic-gate char *p; 14347c478bd9Sstevel@tonic-gate DAEMON_T *d; 14357c478bd9Sstevel@tonic-gate { 14367c478bd9Sstevel@tonic-gate #if NETISO 14377c478bd9Sstevel@tonic-gate short portno; 14387c478bd9Sstevel@tonic-gate #endif /* NETISO */ 14397c478bd9Sstevel@tonic-gate char *port = NULL; 14407c478bd9Sstevel@tonic-gate char *addr = NULL; 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate #if NETINET 14437c478bd9Sstevel@tonic-gate if (d->d_addr.sa.sa_family == AF_UNSPEC) 14447c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 14457c478bd9Sstevel@tonic-gate #endif /* NETINET */ 144649218d4fSjbeck #if _FFR_SS_PER_DAEMON 1447*058561cbSjbeck d->d_supersafe = DPO_NOTSET; 144849218d4fSjbeck #endif /* _FFR_SS_PER_DAEMON */ 144949218d4fSjbeck d->d_dm = DM_NOTSET; 1450*058561cbSjbeck d->d_refuseLA = DPO_NOTSET; 1451*058561cbSjbeck d->d_queueLA = DPO_NOTSET; 1452*058561cbSjbeck d->d_delayLA = DPO_NOTSET; 1453*058561cbSjbeck d->d_maxchildren = DPO_NOTSET; 14547c478bd9Sstevel@tonic-gate 14557c478bd9Sstevel@tonic-gate while (p != NULL) 14567c478bd9Sstevel@tonic-gate { 14577c478bd9Sstevel@tonic-gate register char *f; 14587c478bd9Sstevel@tonic-gate register char *v; 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 14617c478bd9Sstevel@tonic-gate p++; 14627c478bd9Sstevel@tonic-gate if (*p == '\0') 14637c478bd9Sstevel@tonic-gate break; 14647c478bd9Sstevel@tonic-gate f = p; 14657c478bd9Sstevel@tonic-gate p = strchr(p, ','); 14667c478bd9Sstevel@tonic-gate if (p != NULL) 14677c478bd9Sstevel@tonic-gate *p++ = '\0'; 14687c478bd9Sstevel@tonic-gate v = strchr(f, '='); 14697c478bd9Sstevel@tonic-gate if (v == NULL) 14707c478bd9Sstevel@tonic-gate continue; 14717c478bd9Sstevel@tonic-gate while (isascii(*++v) && isspace(*v)) 14727c478bd9Sstevel@tonic-gate continue; 14737c478bd9Sstevel@tonic-gate if (isascii(*f) && islower(*f)) 14747c478bd9Sstevel@tonic-gate *f = toupper(*f); 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate switch (*f) 14777c478bd9Sstevel@tonic-gate { 14787c478bd9Sstevel@tonic-gate case 'A': /* address */ 14797c478bd9Sstevel@tonic-gate addr = v; 14807c478bd9Sstevel@tonic-gate break; 14817c478bd9Sstevel@tonic-gate 1482*058561cbSjbeck case 'c': 1483*058561cbSjbeck d->d_maxchildren = atoi(v); 1484*058561cbSjbeck break; 1485*058561cbSjbeck 14867c478bd9Sstevel@tonic-gate case 'D': /* DeliveryMode */ 14877c478bd9Sstevel@tonic-gate switch (*v) 14887c478bd9Sstevel@tonic-gate { 14897c478bd9Sstevel@tonic-gate case SM_QUEUE: 14907c478bd9Sstevel@tonic-gate case SM_DEFER: 14917c478bd9Sstevel@tonic-gate case SM_DELIVER: 14927c478bd9Sstevel@tonic-gate case SM_FORK: 14937c478bd9Sstevel@tonic-gate d->d_dm = *v; 14947c478bd9Sstevel@tonic-gate break; 14957c478bd9Sstevel@tonic-gate default: 14967c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown delivery mode %c", 14977c478bd9Sstevel@tonic-gate *v); 14987c478bd9Sstevel@tonic-gate break; 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate break; 1501*058561cbSjbeck 1502*058561cbSjbeck case 'd': /* delayLA */ 1503*058561cbSjbeck d->d_delayLA = atoi(v); 1504*058561cbSjbeck break; 15057c478bd9Sstevel@tonic-gate 15067c478bd9Sstevel@tonic-gate case 'F': /* address family */ 15077c478bd9Sstevel@tonic-gate if (isascii(*v) && isdigit(*v)) 15087c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = atoi(v); 15097c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 15107c478bd9Sstevel@tonic-gate # ifdef NETUNIX 15117c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "unix") == 0 || 15127c478bd9Sstevel@tonic-gate sm_strcasecmp(v, "local") == 0) 15137c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_UNIX; 15147c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 15157c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 15167c478bd9Sstevel@tonic-gate #if NETINET 15177c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet") == 0) 15187c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 15197c478bd9Sstevel@tonic-gate #endif /* NETINET */ 15207c478bd9Sstevel@tonic-gate #if NETINET6 15217c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet6") == 0) 15227c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET6; 15237c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 15247c478bd9Sstevel@tonic-gate #if NETISO 15257c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "iso") == 0) 15267c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_ISO; 15277c478bd9Sstevel@tonic-gate #endif /* NETISO */ 15287c478bd9Sstevel@tonic-gate #if NETNS 15297c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "ns") == 0) 15307c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_NS; 15317c478bd9Sstevel@tonic-gate #endif /* NETNS */ 15327c478bd9Sstevel@tonic-gate #if NETX25 15337c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "x.25") == 0) 15347c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_CCITT; 15357c478bd9Sstevel@tonic-gate #endif /* NETX25 */ 15367c478bd9Sstevel@tonic-gate else 15377c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown address family %s in Family=option", 15387c478bd9Sstevel@tonic-gate v); 15397c478bd9Sstevel@tonic-gate break; 15407c478bd9Sstevel@tonic-gate 15417c478bd9Sstevel@tonic-gate #if MILTER 15427c478bd9Sstevel@tonic-gate case 'I': 15437c478bd9Sstevel@tonic-gate d->d_inputfilterlist = v; 15447c478bd9Sstevel@tonic-gate break; 15457c478bd9Sstevel@tonic-gate #endif /* MILTER */ 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate case 'L': /* listen queue size */ 15487c478bd9Sstevel@tonic-gate d->d_listenqueue = atoi(v); 15497c478bd9Sstevel@tonic-gate break; 15507c478bd9Sstevel@tonic-gate 15517c478bd9Sstevel@tonic-gate case 'M': /* modifiers (flags) */ 15527c478bd9Sstevel@tonic-gate d->d_mflags = getmodifiers(v, d->d_flags); 15537c478bd9Sstevel@tonic-gate break; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate case 'N': /* name */ 15567c478bd9Sstevel@tonic-gate d->d_name = v; 15577c478bd9Sstevel@tonic-gate break; 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate case 'P': /* port */ 15607c478bd9Sstevel@tonic-gate port = v; 15617c478bd9Sstevel@tonic-gate break; 15627c478bd9Sstevel@tonic-gate 1563*058561cbSjbeck case 'q': 1564*058561cbSjbeck d->d_queueLA = atoi(v); 1565*058561cbSjbeck break; 1566*058561cbSjbeck 15677c478bd9Sstevel@tonic-gate case 'R': /* receive buffer size */ 15687c478bd9Sstevel@tonic-gate d->d_tcprcvbufsize = atoi(v); 15697c478bd9Sstevel@tonic-gate break; 15707c478bd9Sstevel@tonic-gate 1571*058561cbSjbeck case 'r': 1572*058561cbSjbeck d->d_refuseLA = atoi(v); 1573*058561cbSjbeck break; 1574*058561cbSjbeck 15757c478bd9Sstevel@tonic-gate case 'S': /* send buffer size */ 15767c478bd9Sstevel@tonic-gate d->d_tcpsndbufsize = atoi(v); 15777c478bd9Sstevel@tonic-gate break; 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 15807c478bd9Sstevel@tonic-gate case 'T': /* SuperSafe */ 15817c478bd9Sstevel@tonic-gate if (tolower(*v) == 'i') 15827c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_INTERACTIVE; 15837c478bd9Sstevel@tonic-gate else if (tolower(*v) == 'p') 15847c478bd9Sstevel@tonic-gate # if MILTER 15857c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_REALLY_POSTMILTER; 15867c478bd9Sstevel@tonic-gate # else /* MILTER */ 15877c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 15887c478bd9Sstevel@tonic-gate "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 15897c478bd9Sstevel@tonic-gate # endif /* MILTER */ 15907c478bd9Sstevel@tonic-gate else 15917c478bd9Sstevel@tonic-gate d->d_supersafe = atobool(v) ? SAFE_REALLY 15927c478bd9Sstevel@tonic-gate : SAFE_NO; 15937c478bd9Sstevel@tonic-gate break; 15947c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate default: 15977c478bd9Sstevel@tonic-gate syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 15987c478bd9Sstevel@tonic-gate f); 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate } 16017c478bd9Sstevel@tonic-gate 16027c478bd9Sstevel@tonic-gate /* Check addr and port after finding family */ 16037c478bd9Sstevel@tonic-gate if (addr != NULL) 16047c478bd9Sstevel@tonic-gate { 16057c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 16067c478bd9Sstevel@tonic-gate { 16077c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 16087c478bd9Sstevel@tonic-gate # if NETUNIX 16097c478bd9Sstevel@tonic-gate case AF_UNIX: 16107c478bd9Sstevel@tonic-gate if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) 16117c478bd9Sstevel@tonic-gate { 16127c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 16137c478bd9Sstevel@tonic-gate syserr("setsockaddroptions: domain socket name too long: %s > %d", 16147c478bd9Sstevel@tonic-gate addr, sizeof(d->d_addr.sunix.sun_path)); 16157c478bd9Sstevel@tonic-gate break; 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate /* file safety check done in opendaemonsocket() */ 16197c478bd9Sstevel@tonic-gate (void) memset(&d->d_addr.sunix.sun_path, '\0', 16207c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 16217c478bd9Sstevel@tonic-gate (void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path, 16227c478bd9Sstevel@tonic-gate addr, 16237c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 16247c478bd9Sstevel@tonic-gate break; 16257c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 16267c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 16277c478bd9Sstevel@tonic-gate #if NETINET 16287c478bd9Sstevel@tonic-gate case AF_INET: 16297c478bd9Sstevel@tonic-gate if (!isascii(*addr) || !isdigit(*addr) || 16307c478bd9Sstevel@tonic-gate ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) 16317c478bd9Sstevel@tonic-gate == INADDR_NONE)) 16327c478bd9Sstevel@tonic-gate { 16337c478bd9Sstevel@tonic-gate register struct hostent *hp; 16347c478bd9Sstevel@tonic-gate 16357c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET); 16367c478bd9Sstevel@tonic-gate if (hp == NULL) 16377c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16387c478bd9Sstevel@tonic-gate addr); 16397c478bd9Sstevel@tonic-gate else 16407c478bd9Sstevel@tonic-gate { 16417c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 16427c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET) 16437c478bd9Sstevel@tonic-gate hp->h_addr_list++; 16447c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 16457c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16467c478bd9Sstevel@tonic-gate addr); 16477c478bd9Sstevel@tonic-gate else 16487c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin.sin_addr, 16497c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 16507c478bd9Sstevel@tonic-gate INADDRSZ); 16517c478bd9Sstevel@tonic-gate # if NETINET6 16527c478bd9Sstevel@tonic-gate freehostent(hp); 16537c478bd9Sstevel@tonic-gate hp = NULL; 16547c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate } 16577c478bd9Sstevel@tonic-gate break; 16587c478bd9Sstevel@tonic-gate #endif /* NETINET */ 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate #if NETINET6 16617c478bd9Sstevel@tonic-gate case AF_INET6: 16627c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, 16637c478bd9Sstevel@tonic-gate &d->d_addr.sin6.sin6_addr) != 1) 16647c478bd9Sstevel@tonic-gate { 16657c478bd9Sstevel@tonic-gate register struct hostent *hp; 16667c478bd9Sstevel@tonic-gate 16677c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET6); 16687c478bd9Sstevel@tonic-gate if (hp == NULL) 16697c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16707c478bd9Sstevel@tonic-gate addr); 16717c478bd9Sstevel@tonic-gate else 16727c478bd9Sstevel@tonic-gate { 16737c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 16747c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET6) 16757c478bd9Sstevel@tonic-gate hp->h_addr_list++; 16767c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 16777c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 16787c478bd9Sstevel@tonic-gate addr); 16797c478bd9Sstevel@tonic-gate else 16807c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin6.sin6_addr, 16817c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 16827c478bd9Sstevel@tonic-gate IN6ADDRSZ); 16837c478bd9Sstevel@tonic-gate freehostent(hp); 16847c478bd9Sstevel@tonic-gate hp = NULL; 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate } 16877c478bd9Sstevel@tonic-gate break; 16887c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 16897c478bd9Sstevel@tonic-gate 16907c478bd9Sstevel@tonic-gate default: 16917c478bd9Sstevel@tonic-gate syserr("554 5.3.5 address= option unsupported for family %d", 16927c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 16937c478bd9Sstevel@tonic-gate break; 16947c478bd9Sstevel@tonic-gate } 16957c478bd9Sstevel@tonic-gate } 16967c478bd9Sstevel@tonic-gate 16977c478bd9Sstevel@tonic-gate if (port != NULL) 16987c478bd9Sstevel@tonic-gate { 16997c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 17007c478bd9Sstevel@tonic-gate { 17017c478bd9Sstevel@tonic-gate #if NETINET 17027c478bd9Sstevel@tonic-gate case AF_INET: 17037c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17047c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = htons((unsigned short) 17057c478bd9Sstevel@tonic-gate atoi((const char *) port)); 17067c478bd9Sstevel@tonic-gate else 17077c478bd9Sstevel@tonic-gate { 17087c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 17097c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 17107c478bd9Sstevel@tonic-gate port); 17117c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 17127c478bd9Sstevel@tonic-gate register struct servent *sp; 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 17157c478bd9Sstevel@tonic-gate if (sp == NULL) 17167c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 17177c478bd9Sstevel@tonic-gate port); 17187c478bd9Sstevel@tonic-gate else 17197c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = sp->s_port; 17207c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17217c478bd9Sstevel@tonic-gate } 17227c478bd9Sstevel@tonic-gate break; 17237c478bd9Sstevel@tonic-gate #endif /* NETINET */ 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate #if NETINET6 17267c478bd9Sstevel@tonic-gate case AF_INET6: 17277c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17287c478bd9Sstevel@tonic-gate d->d_addr.sin6.sin6_port = htons((unsigned short) 17297c478bd9Sstevel@tonic-gate atoi(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.sin6.sin6_port = sp->s_port; 17447c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate break; 17477c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate #if NETISO 17507c478bd9Sstevel@tonic-gate case AF_ISO: 17517c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 17527c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 17537c478bd9Sstevel@tonic-gate portno = htons((unsigned short) 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 portno = sp->s_port; 17687c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 17697c478bd9Sstevel@tonic-gate } 17707c478bd9Sstevel@tonic-gate memmove(TSEL(&d->d_addr.siso), 17717c478bd9Sstevel@tonic-gate (char *) &portno, 2); 17727c478bd9Sstevel@tonic-gate break; 17737c478bd9Sstevel@tonic-gate #endif /* NETISO */ 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate default: 17767c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Port= option unsupported for family %d", 17777c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 17787c478bd9Sstevel@tonic-gate break; 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate } 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate /* 17837c478bd9Sstevel@tonic-gate ** SETDAEMONOPTIONS -- set options for running the MTA daemon 17847c478bd9Sstevel@tonic-gate ** 17857c478bd9Sstevel@tonic-gate ** Parameters: 17867c478bd9Sstevel@tonic-gate ** p -- the options line. 17877c478bd9Sstevel@tonic-gate ** 17887c478bd9Sstevel@tonic-gate ** Returns: 17897c478bd9Sstevel@tonic-gate ** true if successful, false otherwise. 17907c478bd9Sstevel@tonic-gate ** 17917c478bd9Sstevel@tonic-gate ** Side Effects: 17927c478bd9Sstevel@tonic-gate ** increments number of daemons. 17937c478bd9Sstevel@tonic-gate */ 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate #define DEF_LISTENQUEUE 10 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate struct dflags 17987c478bd9Sstevel@tonic-gate { 17997c478bd9Sstevel@tonic-gate char *d_name; 18007c478bd9Sstevel@tonic-gate int d_flag; 18017c478bd9Sstevel@tonic-gate }; 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate static struct dflags DaemonFlags[] = 18047c478bd9Sstevel@tonic-gate { 18057c478bd9Sstevel@tonic-gate { "AUTHREQ", D_AUTHREQ }, 18067c478bd9Sstevel@tonic-gate { "BINDIF", D_BINDIF }, 18077c478bd9Sstevel@tonic-gate { "CANONREQ", D_CANONREQ }, 18087c478bd9Sstevel@tonic-gate { "IFNHELO", D_IFNHELO }, 18097c478bd9Sstevel@tonic-gate { "FQMAIL", D_FQMAIL }, 18107c478bd9Sstevel@tonic-gate { "FQRCPT", D_FQRCPT }, 18117c478bd9Sstevel@tonic-gate { "SMTPS", D_SMTPS }, 18127c478bd9Sstevel@tonic-gate { "UNQUALOK", D_UNQUALOK }, 18137c478bd9Sstevel@tonic-gate { "NOAUTH", D_NOAUTH }, 18147c478bd9Sstevel@tonic-gate { "NOCANON", D_NOCANON }, 18157c478bd9Sstevel@tonic-gate { "NOETRN", D_NOETRN }, 18167c478bd9Sstevel@tonic-gate { "NOTLS", D_NOTLS }, 18177c478bd9Sstevel@tonic-gate { "ETRNONLY", D_ETRNONLY }, 18187c478bd9Sstevel@tonic-gate { "OPTIONAL", D_OPTIONAL }, 18197c478bd9Sstevel@tonic-gate { "DISABLE", D_DISABLE }, 18207c478bd9Sstevel@tonic-gate { "ISSET", D_ISSET }, 18217c478bd9Sstevel@tonic-gate { NULL, 0 } 18227c478bd9Sstevel@tonic-gate }; 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate static void 18257c478bd9Sstevel@tonic-gate printdaemonflags(d) 18267c478bd9Sstevel@tonic-gate DAEMON_T *d; 18277c478bd9Sstevel@tonic-gate { 18287c478bd9Sstevel@tonic-gate register struct dflags *df; 18297c478bd9Sstevel@tonic-gate bool first = true; 18307c478bd9Sstevel@tonic-gate 18317c478bd9Sstevel@tonic-gate for (df = DaemonFlags; df->d_name != NULL; df++) 18327c478bd9Sstevel@tonic-gate { 18337c478bd9Sstevel@tonic-gate if (!bitnset(df->d_flag, d->d_flags)) 18347c478bd9Sstevel@tonic-gate continue; 18357c478bd9Sstevel@tonic-gate if (first) 18367c478bd9Sstevel@tonic-gate sm_dprintf("<%s", df->d_name); 18377c478bd9Sstevel@tonic-gate else 18387c478bd9Sstevel@tonic-gate sm_dprintf(",%s", df->d_name); 18397c478bd9Sstevel@tonic-gate first = false; 18407c478bd9Sstevel@tonic-gate } 18417c478bd9Sstevel@tonic-gate if (!first) 18427c478bd9Sstevel@tonic-gate sm_dprintf(">"); 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate bool 18467c478bd9Sstevel@tonic-gate setdaemonoptions(p) 18477c478bd9Sstevel@tonic-gate register char *p; 18487c478bd9Sstevel@tonic-gate { 18497c478bd9Sstevel@tonic-gate if (NDaemons >= MAXDAEMONS) 18507c478bd9Sstevel@tonic-gate return false; 18517c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 18527c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 18537c478bd9Sstevel@tonic-gate clrbitmap(Daemons[NDaemons].d_flags); 18547c478bd9Sstevel@tonic-gate setsockaddroptions(p, &Daemons[NDaemons]); 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate #if MILTER 18577c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_inputfilterlist != NULL) 18587c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist); 18597c478bd9Sstevel@tonic-gate #endif /* MILTER */ 18607c478bd9Sstevel@tonic-gate 18617c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_name != NULL) 18627c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name); 18637c478bd9Sstevel@tonic-gate else 18647c478bd9Sstevel@tonic-gate { 18657c478bd9Sstevel@tonic-gate char num[30]; 18667c478bd9Sstevel@tonic-gate 1867*058561cbSjbeck (void) sm_snprintf(num, sizeof(num), "Daemon%d", NDaemons); 18687c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(num); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate if (tTd(37, 1)) 18727c478bd9Sstevel@tonic-gate { 18737c478bd9Sstevel@tonic-gate sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name); 18747c478bd9Sstevel@tonic-gate printdaemonflags(&Daemons[NDaemons]); 18757c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate ++NDaemons; 18787c478bd9Sstevel@tonic-gate return true; 18797c478bd9Sstevel@tonic-gate } 18807c478bd9Sstevel@tonic-gate /* 18817c478bd9Sstevel@tonic-gate ** INITDAEMON -- initialize daemon if not yet done. 18827c478bd9Sstevel@tonic-gate ** 18837c478bd9Sstevel@tonic-gate ** Parameters: 18847c478bd9Sstevel@tonic-gate ** none 18857c478bd9Sstevel@tonic-gate ** 18867c478bd9Sstevel@tonic-gate ** Returns: 18877c478bd9Sstevel@tonic-gate ** none 18887c478bd9Sstevel@tonic-gate ** 18897c478bd9Sstevel@tonic-gate ** Side Effects: 18907c478bd9Sstevel@tonic-gate ** initializes structure for one daemon. 18917c478bd9Sstevel@tonic-gate */ 18927c478bd9Sstevel@tonic-gate 18937c478bd9Sstevel@tonic-gate void 18947c478bd9Sstevel@tonic-gate initdaemon() 18957c478bd9Sstevel@tonic-gate { 18967c478bd9Sstevel@tonic-gate if (NDaemons == 0) 18977c478bd9Sstevel@tonic-gate { 18987c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 18997c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 19007c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = "Daemon0"; 19017c478bd9Sstevel@tonic-gate NDaemons = 1; 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate } 19047c478bd9Sstevel@tonic-gate /* 19057c478bd9Sstevel@tonic-gate ** SETCLIENTOPTIONS -- set options for running the client 19067c478bd9Sstevel@tonic-gate ** 19077c478bd9Sstevel@tonic-gate ** Parameters: 19087c478bd9Sstevel@tonic-gate ** p -- the options line. 19097c478bd9Sstevel@tonic-gate ** 19107c478bd9Sstevel@tonic-gate ** Returns: 19117c478bd9Sstevel@tonic-gate ** none. 19127c478bd9Sstevel@tonic-gate */ 19137c478bd9Sstevel@tonic-gate 19147c478bd9Sstevel@tonic-gate static DAEMON_T ClientSettings[AF_MAX + 1]; 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate void 19177c478bd9Sstevel@tonic-gate setclientoptions(p) 19187c478bd9Sstevel@tonic-gate register char *p; 19197c478bd9Sstevel@tonic-gate { 19207c478bd9Sstevel@tonic-gate int family; 19217c478bd9Sstevel@tonic-gate DAEMON_T d; 19227c478bd9Sstevel@tonic-gate 1923*058561cbSjbeck memset(&d, '\0', sizeof(d)); 19247c478bd9Sstevel@tonic-gate setsockaddroptions(p, &d); 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate /* grab what we need */ 19277c478bd9Sstevel@tonic-gate family = d.d_addr.sa.sa_family; 19287c478bd9Sstevel@tonic-gate STRUCTCOPY(d, ClientSettings[family]); 19297c478bd9Sstevel@tonic-gate setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */ 19307c478bd9Sstevel@tonic-gate if (d.d_name != NULL) 19317c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(d.d_name); 19327c478bd9Sstevel@tonic-gate else 19337c478bd9Sstevel@tonic-gate { 19347c478bd9Sstevel@tonic-gate char num[30]; 19357c478bd9Sstevel@tonic-gate 1936*058561cbSjbeck (void) sm_snprintf(num, sizeof(num), "Client%d", family); 19377c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(num); 19387c478bd9Sstevel@tonic-gate } 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate /* 19417c478bd9Sstevel@tonic-gate ** ADDR_FAMILY -- determine address family from address 19427c478bd9Sstevel@tonic-gate ** 19437c478bd9Sstevel@tonic-gate ** Parameters: 19447c478bd9Sstevel@tonic-gate ** addr -- the string representation of the address 19457c478bd9Sstevel@tonic-gate ** 19467c478bd9Sstevel@tonic-gate ** Returns: 19477c478bd9Sstevel@tonic-gate ** AF_INET, AF_INET6 or AF_UNSPEC 19487c478bd9Sstevel@tonic-gate ** 19497c478bd9Sstevel@tonic-gate ** Side Effects: 19507c478bd9Sstevel@tonic-gate ** none. 19517c478bd9Sstevel@tonic-gate */ 19527c478bd9Sstevel@tonic-gate 19537c478bd9Sstevel@tonic-gate static int 19547c478bd9Sstevel@tonic-gate addr_family(addr) 19557c478bd9Sstevel@tonic-gate char *addr; 19567c478bd9Sstevel@tonic-gate { 19577c478bd9Sstevel@tonic-gate #if NETINET6 19587c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 19597c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate #if NETINET 19627c478bd9Sstevel@tonic-gate if (inet_addr(addr) != INADDR_NONE) 19637c478bd9Sstevel@tonic-gate { 19647c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19657c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET\n", addr); 19667c478bd9Sstevel@tonic-gate return AF_INET; 19677c478bd9Sstevel@tonic-gate } 19687c478bd9Sstevel@tonic-gate #endif /* NETINET */ 19697c478bd9Sstevel@tonic-gate #if NETINET6 19707c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 19717c478bd9Sstevel@tonic-gate { 19727c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19737c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET6\n", addr); 19747c478bd9Sstevel@tonic-gate return AF_INET6; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 19777c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 19787c478bd9Sstevel@tonic-gate # if NETUNIX 19797c478bd9Sstevel@tonic-gate if (*addr == '/') 19807c478bd9Sstevel@tonic-gate { 19817c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19827c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): LOCAL\n", addr); 19837c478bd9Sstevel@tonic-gate return AF_UNIX; 19847c478bd9Sstevel@tonic-gate } 19857c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 19867c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 19877c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 19887c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): UNSPEC\n", addr); 19897c478bd9Sstevel@tonic-gate return AF_UNSPEC; 19907c478bd9Sstevel@tonic-gate } 19917c478bd9Sstevel@tonic-gate 19927c478bd9Sstevel@tonic-gate /* 19937c478bd9Sstevel@tonic-gate ** CHKCLIENTMODIFIERS -- check whether all clients have set a flag. 19947c478bd9Sstevel@tonic-gate ** 19957c478bd9Sstevel@tonic-gate ** Parameters: 19967c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 19977c478bd9Sstevel@tonic-gate ** 19987c478bd9Sstevel@tonic-gate ** Returns: 19997c478bd9Sstevel@tonic-gate ** true iff all configured clients have set the flag. 20007c478bd9Sstevel@tonic-gate */ 20017c478bd9Sstevel@tonic-gate 20027c478bd9Sstevel@tonic-gate bool 20037c478bd9Sstevel@tonic-gate chkclientmodifiers(flag) 20047c478bd9Sstevel@tonic-gate int flag; 20057c478bd9Sstevel@tonic-gate { 20067c478bd9Sstevel@tonic-gate int i; 20077c478bd9Sstevel@tonic-gate bool flagisset; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate flagisset = false; 20107c478bd9Sstevel@tonic-gate for (i = 0; i < AF_MAX; i++) 20117c478bd9Sstevel@tonic-gate { 20127c478bd9Sstevel@tonic-gate if (bitnset(D_ISSET, ClientSettings[i].d_flags)) 20137c478bd9Sstevel@tonic-gate { 20147c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, ClientSettings[i].d_flags)) 20157c478bd9Sstevel@tonic-gate return false; 20167c478bd9Sstevel@tonic-gate flagisset = true; 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate } 20197c478bd9Sstevel@tonic-gate return flagisset; 20207c478bd9Sstevel@tonic-gate } 20217c478bd9Sstevel@tonic-gate 20227c478bd9Sstevel@tonic-gate #if MILTER 20237c478bd9Sstevel@tonic-gate /* 20247c478bd9Sstevel@tonic-gate ** SETUP_DAEMON_FILTERS -- Parse per-socket filters 20257c478bd9Sstevel@tonic-gate ** 20267c478bd9Sstevel@tonic-gate ** Parameters: 20277c478bd9Sstevel@tonic-gate ** none 20287c478bd9Sstevel@tonic-gate ** 20297c478bd9Sstevel@tonic-gate ** Returns: 20307c478bd9Sstevel@tonic-gate ** none 20317c478bd9Sstevel@tonic-gate */ 20327c478bd9Sstevel@tonic-gate 20337c478bd9Sstevel@tonic-gate void 20347c478bd9Sstevel@tonic-gate setup_daemon_milters() 20357c478bd9Sstevel@tonic-gate { 20367c478bd9Sstevel@tonic-gate int idx; 20377c478bd9Sstevel@tonic-gate 20387c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP) 20397c478bd9Sstevel@tonic-gate { 20407c478bd9Sstevel@tonic-gate /* no need to configure the daemons */ 20417c478bd9Sstevel@tonic-gate return; 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 20457c478bd9Sstevel@tonic-gate { 20467c478bd9Sstevel@tonic-gate if (Daemons[idx].d_inputfilterlist != NULL) 20477c478bd9Sstevel@tonic-gate { 20487c478bd9Sstevel@tonic-gate milter_config(Daemons[idx].d_inputfilterlist, 20497c478bd9Sstevel@tonic-gate Daemons[idx].d_inputfilters, 20507c478bd9Sstevel@tonic-gate MAXFILTERS); 20517c478bd9Sstevel@tonic-gate } 20527c478bd9Sstevel@tonic-gate } 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate #endif /* MILTER */ 20557c478bd9Sstevel@tonic-gate /* 20567c478bd9Sstevel@tonic-gate ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 20577c478bd9Sstevel@tonic-gate ** 20587c478bd9Sstevel@tonic-gate ** Parameters: 20597c478bd9Sstevel@tonic-gate ** host -- the name of the host. 20607c478bd9Sstevel@tonic-gate ** port -- the port number to connect to. 20617c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 20627c478bd9Sstevel@tonic-gate ** structure to be filled in. 20637c478bd9Sstevel@tonic-gate ** e -- the current envelope. 20647c478bd9Sstevel@tonic-gate ** enough -- time at which to stop further connection attempts. 20657c478bd9Sstevel@tonic-gate ** (0 means no limit) 20667c478bd9Sstevel@tonic-gate ** 20677c478bd9Sstevel@tonic-gate ** Returns: 20687c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 20697c478bd9Sstevel@tonic-gate ** made and if not why not. 20707c478bd9Sstevel@tonic-gate ** 20717c478bd9Sstevel@tonic-gate ** Side Effects: 20727c478bd9Sstevel@tonic-gate ** none. 20737c478bd9Sstevel@tonic-gate */ 20747c478bd9Sstevel@tonic-gate 20757c478bd9Sstevel@tonic-gate static jmp_buf CtxConnectTimeout; 20767c478bd9Sstevel@tonic-gate 20777c478bd9Sstevel@tonic-gate SOCKADDR CurHostAddr; /* address of current host */ 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate int 20807c478bd9Sstevel@tonic-gate makeconnection(host, port, mci, e, enough) 20817c478bd9Sstevel@tonic-gate char *host; 20827c478bd9Sstevel@tonic-gate volatile unsigned int port; 20837c478bd9Sstevel@tonic-gate register MCI *mci; 20847c478bd9Sstevel@tonic-gate ENVELOPE *e; 20857c478bd9Sstevel@tonic-gate time_t enough; 20867c478bd9Sstevel@tonic-gate { 20877c478bd9Sstevel@tonic-gate register volatile int addrno = 0; 20887c478bd9Sstevel@tonic-gate volatile int s; 20897c478bd9Sstevel@tonic-gate register struct hostent *volatile hp = (struct hostent *) NULL; 20907c478bd9Sstevel@tonic-gate SOCKADDR addr; 20917c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 20927c478bd9Sstevel@tonic-gate int save_errno = 0; 20937c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T addrlen; 20943ee0e492Sjbeck volatile bool firstconnect = true; 20957c478bd9Sstevel@tonic-gate SM_EVENT *volatile ev = NULL; 20967c478bd9Sstevel@tonic-gate #if NETINET6 20977c478bd9Sstevel@tonic-gate volatile bool v6found = false; 20987c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 20997c478bd9Sstevel@tonic-gate volatile int family = InetMode; 21007c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T len; 21017c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T socksize = 0; 21027c478bd9Sstevel@tonic-gate volatile bool clt_bind; 21037c478bd9Sstevel@tonic-gate BITMAP256 d_flags; 21047c478bd9Sstevel@tonic-gate char *p; 21057c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate /* retranslate {daemon_flags} into bitmap */ 21087c478bd9Sstevel@tonic-gate clrbitmap(d_flags); 21097c478bd9Sstevel@tonic-gate if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL) 21107c478bd9Sstevel@tonic-gate { 21117c478bd9Sstevel@tonic-gate for (; *p != '\0'; p++) 21127c478bd9Sstevel@tonic-gate { 21137c478bd9Sstevel@tonic-gate if (!(isascii(*p) && isspace(*p))) 21147c478bd9Sstevel@tonic-gate setbitn(bitidx(*p), d_flags); 21157c478bd9Sstevel@tonic-gate } 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate #if NETINET6 21197c478bd9Sstevel@tonic-gate v4retry: 21207c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21217c478bd9Sstevel@tonic-gate clt_bind = false; 21227c478bd9Sstevel@tonic-gate 21237c478bd9Sstevel@tonic-gate /* Set up the address for outgoing connection. */ 21247c478bd9Sstevel@tonic-gate if (bitnset(D_BINDIF, d_flags) && 21257c478bd9Sstevel@tonic-gate (p = macvalue(macid("{if_addr}"), e)) != NULL && 21267c478bd9Sstevel@tonic-gate *p != '\0') 21277c478bd9Sstevel@tonic-gate { 21287c478bd9Sstevel@tonic-gate #if NETINET6 21297c478bd9Sstevel@tonic-gate char p6[INET6_ADDRSTRLEN]; 21307c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21317c478bd9Sstevel@tonic-gate 2132*058561cbSjbeck memset(&clt_addr, '\0', sizeof(clt_addr)); 21337c478bd9Sstevel@tonic-gate 21347c478bd9Sstevel@tonic-gate /* infer the address family from the address itself */ 21357c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family = addr_family(p); 21367c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 21377c478bd9Sstevel@tonic-gate { 21387c478bd9Sstevel@tonic-gate #if NETINET 21397c478bd9Sstevel@tonic-gate case AF_INET: 21407c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr = inet_addr(p); 21417c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 21427c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) 21437c478bd9Sstevel@tonic-gate { 21447c478bd9Sstevel@tonic-gate clt_bind = true; 21457c478bd9Sstevel@tonic-gate socksize = sizeof(struct sockaddr_in); 21467c478bd9Sstevel@tonic-gate } 21477c478bd9Sstevel@tonic-gate break; 21487c478bd9Sstevel@tonic-gate #endif /* NETINET */ 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate #if NETINET6 21517c478bd9Sstevel@tonic-gate case AF_INET6: 21527c478bd9Sstevel@tonic-gate if (inet_addr(p) != INADDR_NONE) 2153*058561cbSjbeck (void) sm_snprintf(p6, sizeof(p6), 21547c478bd9Sstevel@tonic-gate "IPv6:::ffff:%s", p); 21557c478bd9Sstevel@tonic-gate else 2156*058561cbSjbeck (void) sm_strlcpy(p6, p, sizeof(p6)); 21577c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, p6, 21587c478bd9Sstevel@tonic-gate &clt_addr.sin6.sin6_addr) == 1 && 21597c478bd9Sstevel@tonic-gate !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 21607c478bd9Sstevel@tonic-gate { 21617c478bd9Sstevel@tonic-gate clt_bind = true; 21627c478bd9Sstevel@tonic-gate socksize = sizeof(struct sockaddr_in6); 21637c478bd9Sstevel@tonic-gate } 21647c478bd9Sstevel@tonic-gate break; 21657c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate #if 0 21687c478bd9Sstevel@tonic-gate default: 21697c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Address= option unsupported for family %d", 21707c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family); 21717c478bd9Sstevel@tonic-gate break; 21727c478bd9Sstevel@tonic-gate #endif /* 0 */ 21737c478bd9Sstevel@tonic-gate } 21747c478bd9Sstevel@tonic-gate if (clt_bind) 21757c478bd9Sstevel@tonic-gate family = clt_addr.sa.sa_family; 21767c478bd9Sstevel@tonic-gate } 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate /* D_BINDIF not set or not available, fallback to ClientPortOptions */ 21797c478bd9Sstevel@tonic-gate if (!clt_bind) 21807c478bd9Sstevel@tonic-gate { 21817c478bd9Sstevel@tonic-gate STRUCTCOPY(ClientSettings[family].d_addr, clt_addr); 21827c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 21837c478bd9Sstevel@tonic-gate { 21847c478bd9Sstevel@tonic-gate #if NETINET 21857c478bd9Sstevel@tonic-gate case AF_INET: 21867c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr == 0) 21877c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 21887c478bd9Sstevel@tonic-gate else 21897c478bd9Sstevel@tonic-gate clt_bind = true; 21907c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 21917c478bd9Sstevel@tonic-gate clt_bind = true; 21927c478bd9Sstevel@tonic-gate socksize = sizeof(struct sockaddr_in); 21937c478bd9Sstevel@tonic-gate break; 21947c478bd9Sstevel@tonic-gate #endif /* NETINET */ 21957c478bd9Sstevel@tonic-gate #if NETINET6 21967c478bd9Sstevel@tonic-gate case AF_INET6: 21977c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 21987c478bd9Sstevel@tonic-gate clt_addr.sin6.sin6_addr = in6addr_any; 21997c478bd9Sstevel@tonic-gate else 22007c478bd9Sstevel@tonic-gate clt_bind = true; 22017c478bd9Sstevel@tonic-gate socksize = sizeof(struct sockaddr_in6); 22027c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 22037c478bd9Sstevel@tonic-gate clt_bind = true; 22047c478bd9Sstevel@tonic-gate break; 22057c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22067c478bd9Sstevel@tonic-gate #if NETISO 22077c478bd9Sstevel@tonic-gate case AF_ISO: 2208*058561cbSjbeck socksize = sizeof(clt_addr.siso); 22097c478bd9Sstevel@tonic-gate clt_bind = true; 22107c478bd9Sstevel@tonic-gate break; 22117c478bd9Sstevel@tonic-gate #endif /* NETISO */ 22127c478bd9Sstevel@tonic-gate default: 22137c478bd9Sstevel@tonic-gate break; 22147c478bd9Sstevel@tonic-gate } 22157c478bd9Sstevel@tonic-gate } 22167c478bd9Sstevel@tonic-gate 22177c478bd9Sstevel@tonic-gate /* 22187c478bd9Sstevel@tonic-gate ** Set up the address for the mailer. 22197c478bd9Sstevel@tonic-gate ** Accept "[a.b.c.d]" syntax for host name. 22207c478bd9Sstevel@tonic-gate */ 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(0); 22237c478bd9Sstevel@tonic-gate errno = 0; 2224*058561cbSjbeck memset(&CurHostAddr, '\0', sizeof(CurHostAddr)); 2225*058561cbSjbeck memset(&addr, '\0', sizeof(addr)); 22267c478bd9Sstevel@tonic-gate SmtpPhase = mci->mci_phase = "initial connection"; 22277c478bd9Sstevel@tonic-gate CurHostName = host; 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate if (host[0] == '[') 22307c478bd9Sstevel@tonic-gate { 22317c478bd9Sstevel@tonic-gate p = strchr(host, ']'); 22327c478bd9Sstevel@tonic-gate if (p != NULL) 22337c478bd9Sstevel@tonic-gate { 22347c478bd9Sstevel@tonic-gate #if NETINET 22357c478bd9Sstevel@tonic-gate unsigned long hid = INADDR_NONE; 22367c478bd9Sstevel@tonic-gate #endif /* NETINET */ 22377c478bd9Sstevel@tonic-gate #if NETINET6 22387c478bd9Sstevel@tonic-gate struct sockaddr_in6 hid6; 22397c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22407c478bd9Sstevel@tonic-gate 22417c478bd9Sstevel@tonic-gate *p = '\0'; 22427c478bd9Sstevel@tonic-gate #if NETINET6 2243*058561cbSjbeck memset(&hid6, '\0', sizeof(hid6)); 22447c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22457c478bd9Sstevel@tonic-gate #if NETINET 22467c478bd9Sstevel@tonic-gate if (family == AF_INET && 22477c478bd9Sstevel@tonic-gate (hid = inet_addr(&host[1])) != INADDR_NONE) 22487c478bd9Sstevel@tonic-gate { 22497c478bd9Sstevel@tonic-gate addr.sin.sin_family = AF_INET; 22507c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = hid; 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate else 22537c478bd9Sstevel@tonic-gate #endif /* NETINET */ 22547c478bd9Sstevel@tonic-gate #if NETINET6 22557c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 22567c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &host[1], 22577c478bd9Sstevel@tonic-gate &hid6.sin6_addr) == 1) 22587c478bd9Sstevel@tonic-gate { 22597c478bd9Sstevel@tonic-gate addr.sin6.sin6_family = AF_INET6; 22607c478bd9Sstevel@tonic-gate addr.sin6.sin6_addr = hid6.sin6_addr; 22617c478bd9Sstevel@tonic-gate } 22627c478bd9Sstevel@tonic-gate else 22637c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 22647c478bd9Sstevel@tonic-gate { 22657c478bd9Sstevel@tonic-gate /* try it as a host name (avoid MX lookup) */ 22667c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], family); 22677c478bd9Sstevel@tonic-gate if (hp == NULL && p[-1] == '.') 22687c478bd9Sstevel@tonic-gate { 22697c478bd9Sstevel@tonic-gate #if NAMED_BIND 22707c478bd9Sstevel@tonic-gate int oldopts = _res.options; 22717c478bd9Sstevel@tonic-gate 22727c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 22737c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 22747c478bd9Sstevel@tonic-gate p[-1] = '\0'; 22757c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], 22767c478bd9Sstevel@tonic-gate family); 22777c478bd9Sstevel@tonic-gate p[-1] = '.'; 22787c478bd9Sstevel@tonic-gate #if NAMED_BIND 22797c478bd9Sstevel@tonic-gate _res.options = oldopts; 22807c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 22817c478bd9Sstevel@tonic-gate } 22827c478bd9Sstevel@tonic-gate *p = ']'; 22837c478bd9Sstevel@tonic-gate goto gothostent; 22847c478bd9Sstevel@tonic-gate } 22857c478bd9Sstevel@tonic-gate *p = ']'; 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate if (p == NULL) 22887c478bd9Sstevel@tonic-gate { 22897c478bd9Sstevel@tonic-gate extern char MsgBuf[]; 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate usrerrenh("5.1.2", 22927c478bd9Sstevel@tonic-gate "553 Invalid numeric domain spec \"%s\"", 22937c478bd9Sstevel@tonic-gate host); 22947c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 22957c478bd9Sstevel@tonic-gate errno = EINVAL; 22967c478bd9Sstevel@tonic-gate return EX_NOHOST; 22977c478bd9Sstevel@tonic-gate } 22987c478bd9Sstevel@tonic-gate } 22997c478bd9Sstevel@tonic-gate else 23007c478bd9Sstevel@tonic-gate { 23017c478bd9Sstevel@tonic-gate /* contortion to get around SGI cc complaints */ 23027c478bd9Sstevel@tonic-gate { 23037c478bd9Sstevel@tonic-gate p = &host[strlen(host) - 1]; 23047c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 23057c478bd9Sstevel@tonic-gate if (hp == NULL && *p == '.') 23067c478bd9Sstevel@tonic-gate { 23077c478bd9Sstevel@tonic-gate #if NAMED_BIND 23087c478bd9Sstevel@tonic-gate int oldopts = _res.options; 23097c478bd9Sstevel@tonic-gate 23107c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 23117c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23127c478bd9Sstevel@tonic-gate *p = '\0'; 23137c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 23147c478bd9Sstevel@tonic-gate *p = '.'; 23157c478bd9Sstevel@tonic-gate #if NAMED_BIND 23167c478bd9Sstevel@tonic-gate _res.options = oldopts; 23177c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23187c478bd9Sstevel@tonic-gate } 23197c478bd9Sstevel@tonic-gate } 23207c478bd9Sstevel@tonic-gate gothostent: 23217c478bd9Sstevel@tonic-gate if (hp == NULL) 23227c478bd9Sstevel@tonic-gate { 23237c478bd9Sstevel@tonic-gate #if NAMED_BIND 23247c478bd9Sstevel@tonic-gate /* check for name server timeouts */ 23257c478bd9Sstevel@tonic-gate # if NETINET6 23267c478bd9Sstevel@tonic-gate if (WorkAroundBrokenAAAA && family == AF_INET6 && 23277c478bd9Sstevel@tonic-gate errno == ETIMEDOUT) 23287c478bd9Sstevel@tonic-gate { 23297c478bd9Sstevel@tonic-gate /* 23307c478bd9Sstevel@tonic-gate ** An attempt with family AF_INET may 23317c478bd9Sstevel@tonic-gate ** succeed By skipping the next section 23327c478bd9Sstevel@tonic-gate ** of code, we will try AF_INET before 23337c478bd9Sstevel@tonic-gate ** failing. 23347c478bd9Sstevel@tonic-gate */ 23357c478bd9Sstevel@tonic-gate 23367c478bd9Sstevel@tonic-gate if (tTd(16, 10)) 23377c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n"); 23387c478bd9Sstevel@tonic-gate } 23397c478bd9Sstevel@tonic-gate else 23407c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 23417c478bd9Sstevel@tonic-gate { 23427c478bd9Sstevel@tonic-gate if (errno == ETIMEDOUT || 2343*058561cbSjbeck # if _FFR_GETHBN_ExFILE 2344*058561cbSjbeck # ifdef EMFILE 2345*058561cbSjbeck errno == EMFILE || 2346*058561cbSjbeck # endif /* EMFILE */ 2347*058561cbSjbeck # ifdef ENFILE 2348*058561cbSjbeck errno == ENFILE || 2349*058561cbSjbeck # endif /* ENFILE */ 2350*058561cbSjbeck # endif /* _FFR_GETHBN_ExFILE */ 23517c478bd9Sstevel@tonic-gate h_errno == TRY_AGAIN || 23527c478bd9Sstevel@tonic-gate (errno == ECONNREFUSED && UseNameServer)) 23537c478bd9Sstevel@tonic-gate { 23547c478bd9Sstevel@tonic-gate save_errno = errno; 23557c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, 23567c478bd9Sstevel@tonic-gate "4.4.3", NULL); 23577c478bd9Sstevel@tonic-gate errno = save_errno; 23587c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 23597c478bd9Sstevel@tonic-gate } 23607c478bd9Sstevel@tonic-gate } 23617c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 23627c478bd9Sstevel@tonic-gate #if NETINET6 23637c478bd9Sstevel@tonic-gate /* 23647c478bd9Sstevel@tonic-gate ** Try v6 first, then fall back to v4. 23657c478bd9Sstevel@tonic-gate ** If we found a v6 address, but no v4 23667c478bd9Sstevel@tonic-gate ** addresses, then TEMPFAIL. 23677c478bd9Sstevel@tonic-gate */ 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate if (family == AF_INET6) 23707c478bd9Sstevel@tonic-gate { 23717c478bd9Sstevel@tonic-gate family = AF_INET; 23727c478bd9Sstevel@tonic-gate goto v4retry; 23737c478bd9Sstevel@tonic-gate } 23747c478bd9Sstevel@tonic-gate if (v6found) 23757c478bd9Sstevel@tonic-gate goto v6tempfail; 23767c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 23777c478bd9Sstevel@tonic-gate save_errno = errno; 23787c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 23797c478bd9Sstevel@tonic-gate errno = save_errno; 23807c478bd9Sstevel@tonic-gate return EX_NOHOST; 23817c478bd9Sstevel@tonic-gate } 23827c478bd9Sstevel@tonic-gate addr.sa.sa_family = hp->h_addrtype; 23837c478bd9Sstevel@tonic-gate switch (hp->h_addrtype) 23847c478bd9Sstevel@tonic-gate { 23857c478bd9Sstevel@tonic-gate #if NETINET 23867c478bd9Sstevel@tonic-gate case AF_INET: 23877c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 23887c478bd9Sstevel@tonic-gate hp->h_addr, 23897c478bd9Sstevel@tonic-gate INADDRSZ); 23907c478bd9Sstevel@tonic-gate break; 23917c478bd9Sstevel@tonic-gate #endif /* NETINET */ 23927c478bd9Sstevel@tonic-gate 23937c478bd9Sstevel@tonic-gate #if NETINET6 23947c478bd9Sstevel@tonic-gate case AF_INET6: 23957c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 23967c478bd9Sstevel@tonic-gate hp->h_addr, 23977c478bd9Sstevel@tonic-gate IN6ADDRSZ); 23987c478bd9Sstevel@tonic-gate break; 23997c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24007c478bd9Sstevel@tonic-gate 24017c478bd9Sstevel@tonic-gate default: 2402*058561cbSjbeck if (hp->h_length > sizeof(addr.sa.sa_data)) 24037c478bd9Sstevel@tonic-gate { 24047c478bd9Sstevel@tonic-gate syserr("makeconnection: long sa_data: family %d len %d", 24057c478bd9Sstevel@tonic-gate hp->h_addrtype, hp->h_length); 24067c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 24077c478bd9Sstevel@tonic-gate errno = EINVAL; 24087c478bd9Sstevel@tonic-gate return EX_NOHOST; 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, hp->h_addr, hp->h_length); 24117c478bd9Sstevel@tonic-gate break; 24127c478bd9Sstevel@tonic-gate } 24137c478bd9Sstevel@tonic-gate addrno = 1; 24147c478bd9Sstevel@tonic-gate } 24157c478bd9Sstevel@tonic-gate 24167c478bd9Sstevel@tonic-gate /* 24177c478bd9Sstevel@tonic-gate ** Determine the port number. 24187c478bd9Sstevel@tonic-gate */ 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate if (port == 0) 24217c478bd9Sstevel@tonic-gate { 24227c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 24237c478bd9Sstevel@tonic-gate port = htons(25); 24247c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 24257c478bd9Sstevel@tonic-gate register struct servent *sp = getservbyname("smtp", "tcp"); 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate if (sp == NULL) 24287c478bd9Sstevel@tonic-gate { 24297c478bd9Sstevel@tonic-gate if (LogLevel > 2) 24307c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 24317c478bd9Sstevel@tonic-gate "makeconnection: service \"smtp\" unknown"); 24327c478bd9Sstevel@tonic-gate port = htons(25); 24337c478bd9Sstevel@tonic-gate } 24347c478bd9Sstevel@tonic-gate else 24357c478bd9Sstevel@tonic-gate port = sp->s_port; 24367c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 24377c478bd9Sstevel@tonic-gate } 24387c478bd9Sstevel@tonic-gate 24397c478bd9Sstevel@tonic-gate #if NETINET6 24407c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_INET6 && 24417c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) && 24427c478bd9Sstevel@tonic-gate ClientSettings[AF_INET].d_addr.sa.sa_family != 0) 24437c478bd9Sstevel@tonic-gate { 24447c478bd9Sstevel@tonic-gate /* 24457c478bd9Sstevel@tonic-gate ** Ignore mapped IPv4 address since 24467c478bd9Sstevel@tonic-gate ** there is a ClientPortOptions setting 24477c478bd9Sstevel@tonic-gate ** for IPv4. 24487c478bd9Sstevel@tonic-gate */ 24497c478bd9Sstevel@tonic-gate 24507c478bd9Sstevel@tonic-gate goto nextaddr; 24517c478bd9Sstevel@tonic-gate } 24527c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24537c478bd9Sstevel@tonic-gate 24547c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 24557c478bd9Sstevel@tonic-gate { 24567c478bd9Sstevel@tonic-gate #if NETINET 24577c478bd9Sstevel@tonic-gate case AF_INET: 24587c478bd9Sstevel@tonic-gate addr.sin.sin_port = port; 24597c478bd9Sstevel@tonic-gate addrlen = sizeof(struct sockaddr_in); 24607c478bd9Sstevel@tonic-gate break; 24617c478bd9Sstevel@tonic-gate #endif /* NETINET */ 24627c478bd9Sstevel@tonic-gate 24637c478bd9Sstevel@tonic-gate #if NETINET6 24647c478bd9Sstevel@tonic-gate case AF_INET6: 24657c478bd9Sstevel@tonic-gate addr.sin6.sin6_port = port; 24667c478bd9Sstevel@tonic-gate addrlen = sizeof(struct sockaddr_in6); 24677c478bd9Sstevel@tonic-gate break; 24687c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate #if NETISO 24717c478bd9Sstevel@tonic-gate case AF_ISO: 24727c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 24737c478bd9Sstevel@tonic-gate memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 24747c478bd9Sstevel@tonic-gate addrlen = sizeof(struct sockaddr_iso); 24757c478bd9Sstevel@tonic-gate break; 24767c478bd9Sstevel@tonic-gate #endif /* NETISO */ 24777c478bd9Sstevel@tonic-gate 24787c478bd9Sstevel@tonic-gate default: 24797c478bd9Sstevel@tonic-gate syserr("Can't connect to address family %d", addr.sa.sa_family); 24807c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 24817c478bd9Sstevel@tonic-gate errno = EINVAL; 24827c478bd9Sstevel@tonic-gate #if NETINET6 24837c478bd9Sstevel@tonic-gate if (hp != NULL) 24847c478bd9Sstevel@tonic-gate freehostent(hp); 24857c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 24867c478bd9Sstevel@tonic-gate return EX_NOHOST; 24877c478bd9Sstevel@tonic-gate } 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate /* 24907c478bd9Sstevel@tonic-gate ** Try to actually open the connection. 24917c478bd9Sstevel@tonic-gate */ 24927c478bd9Sstevel@tonic-gate 24937c478bd9Sstevel@tonic-gate #if XLA 24947c478bd9Sstevel@tonic-gate /* if too many connections, don't bother trying */ 24957c478bd9Sstevel@tonic-gate if (!xla_noqueue_ok(host)) 24967c478bd9Sstevel@tonic-gate { 24977c478bd9Sstevel@tonic-gate # if NETINET6 24987c478bd9Sstevel@tonic-gate if (hp != NULL) 24997c478bd9Sstevel@tonic-gate freehostent(hp); 25007c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 25017c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 25027c478bd9Sstevel@tonic-gate } 25037c478bd9Sstevel@tonic-gate #endif /* XLA */ 25047c478bd9Sstevel@tonic-gate 25057c478bd9Sstevel@tonic-gate for (;;) 25067c478bd9Sstevel@tonic-gate { 25077c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 25087c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection (%s [%s].%d (%d))\n", 25097c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), ntohs(port), 25107c478bd9Sstevel@tonic-gate (int) addr.sa.sa_family); 25117c478bd9Sstevel@tonic-gate 25127c478bd9Sstevel@tonic-gate /* save for logging */ 25137c478bd9Sstevel@tonic-gate CurHostAddr = addr; 25147c478bd9Sstevel@tonic-gate 25157c478bd9Sstevel@tonic-gate #if HASRRESVPORT 25167c478bd9Sstevel@tonic-gate if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 25177c478bd9Sstevel@tonic-gate { 25187c478bd9Sstevel@tonic-gate int rport = IPPORT_RESERVED - 1; 25197c478bd9Sstevel@tonic-gate 25207c478bd9Sstevel@tonic-gate s = rresvport(&rport); 25217c478bd9Sstevel@tonic-gate } 25227c478bd9Sstevel@tonic-gate else 25237c478bd9Sstevel@tonic-gate #endif /* HASRRESVPORT */ 25247c478bd9Sstevel@tonic-gate { 25257c478bd9Sstevel@tonic-gate s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 25267c478bd9Sstevel@tonic-gate } 25277c478bd9Sstevel@tonic-gate if (s < 0) 25287c478bd9Sstevel@tonic-gate { 25297c478bd9Sstevel@tonic-gate save_errno = errno; 25307c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot create socket"); 25317c478bd9Sstevel@tonic-gate #if XLA 25327c478bd9Sstevel@tonic-gate xla_host_end(host); 25337c478bd9Sstevel@tonic-gate #endif /* XLA */ 25347c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 25357c478bd9Sstevel@tonic-gate #if NETINET6 25367c478bd9Sstevel@tonic-gate if (hp != NULL) 25377c478bd9Sstevel@tonic-gate freehostent(hp); 25387c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 25397c478bd9Sstevel@tonic-gate errno = save_errno; 25407c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 25417c478bd9Sstevel@tonic-gate } 25427c478bd9Sstevel@tonic-gate 25437c478bd9Sstevel@tonic-gate #ifdef SO_SNDBUF 25447c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcpsndbufsize > 0) 25457c478bd9Sstevel@tonic-gate { 25467c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 25477c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcpsndbufsize, 25487c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0) 25497c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_SNDBUF)"); 25507c478bd9Sstevel@tonic-gate } 25517c478bd9Sstevel@tonic-gate #endif /* SO_SNDBUF */ 25527c478bd9Sstevel@tonic-gate #ifdef SO_RCVBUF 25537c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcprcvbufsize > 0) 25547c478bd9Sstevel@tonic-gate { 25557c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 25567c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcprcvbufsize, 25577c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0) 25587c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_RCVBUF)"); 25597c478bd9Sstevel@tonic-gate } 25607c478bd9Sstevel@tonic-gate #endif /* SO_RCVBUF */ 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 25637c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: fd=%d\n", s); 25647c478bd9Sstevel@tonic-gate 25657c478bd9Sstevel@tonic-gate /* turn on network debugging? */ 25667c478bd9Sstevel@tonic-gate if (tTd(16, 101)) 25677c478bd9Sstevel@tonic-gate { 25687c478bd9Sstevel@tonic-gate int on = 1; 25697c478bd9Sstevel@tonic-gate 25707c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2571*058561cbSjbeck (char *)&on, sizeof(on)); 25727c478bd9Sstevel@tonic-gate } 25737c478bd9Sstevel@tonic-gate if (e->e_xfp != NULL) /* for debugging */ 25747c478bd9Sstevel@tonic-gate (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 25757c478bd9Sstevel@tonic-gate errno = 0; /* for debugging */ 25767c478bd9Sstevel@tonic-gate 25777c478bd9Sstevel@tonic-gate if (clt_bind) 25787c478bd9Sstevel@tonic-gate { 25797c478bd9Sstevel@tonic-gate int on = 1; 25807c478bd9Sstevel@tonic-gate 25817c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 25827c478bd9Sstevel@tonic-gate { 25837c478bd9Sstevel@tonic-gate #if NETINET 25847c478bd9Sstevel@tonic-gate case AF_INET: 25857c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 25867c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 25877c478bd9Sstevel@tonic-gate SO_REUSEADDR, 25887c478bd9Sstevel@tonic-gate (char *) &on, 2589*058561cbSjbeck sizeof(on)); 25907c478bd9Sstevel@tonic-gate break; 25917c478bd9Sstevel@tonic-gate #endif /* NETINET */ 25927c478bd9Sstevel@tonic-gate 25937c478bd9Sstevel@tonic-gate #if NETINET6 25947c478bd9Sstevel@tonic-gate case AF_INET6: 25957c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 25967c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 25977c478bd9Sstevel@tonic-gate SO_REUSEADDR, 25987c478bd9Sstevel@tonic-gate (char *) &on, 2599*058561cbSjbeck sizeof(on)); 26007c478bd9Sstevel@tonic-gate break; 26017c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26027c478bd9Sstevel@tonic-gate } 26037c478bd9Sstevel@tonic-gate 26047c478bd9Sstevel@tonic-gate if (bind(s, &clt_addr.sa, socksize) < 0) 26057c478bd9Sstevel@tonic-gate { 26067c478bd9Sstevel@tonic-gate save_errno = errno; 26077c478bd9Sstevel@tonic-gate (void) close(s); 26087c478bd9Sstevel@tonic-gate errno = save_errno; 26097c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot bind socket [%s]", 26107c478bd9Sstevel@tonic-gate anynet_ntoa(&clt_addr)); 26117c478bd9Sstevel@tonic-gate #if NETINET6 26127c478bd9Sstevel@tonic-gate if (hp != NULL) 26137c478bd9Sstevel@tonic-gate freehostent(hp); 26147c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26157c478bd9Sstevel@tonic-gate errno = save_errno; 26167c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 26177c478bd9Sstevel@tonic-gate } 26187c478bd9Sstevel@tonic-gate } 26197c478bd9Sstevel@tonic-gate 26207c478bd9Sstevel@tonic-gate /* 26217c478bd9Sstevel@tonic-gate ** Linux seems to hang in connect for 90 minutes (!!!). 26227c478bd9Sstevel@tonic-gate ** Time out the connect to avoid this problem. 26237c478bd9Sstevel@tonic-gate */ 26247c478bd9Sstevel@tonic-gate 26257c478bd9Sstevel@tonic-gate if (setjmp(CtxConnectTimeout) == 0) 26267c478bd9Sstevel@tonic-gate { 26277c478bd9Sstevel@tonic-gate int i; 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 26307c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_iconnect, 26317c478bd9Sstevel@tonic-gate connecttimeout, 0); 26327c478bd9Sstevel@tonic-gate else if (TimeOuts.to_connect != 0) 26337c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_connect, 26347c478bd9Sstevel@tonic-gate connecttimeout, 0); 26357c478bd9Sstevel@tonic-gate else 26367c478bd9Sstevel@tonic-gate ev = NULL; 26377c478bd9Sstevel@tonic-gate 26387c478bd9Sstevel@tonic-gate switch (ConnectOnlyTo.sa.sa_family) 26397c478bd9Sstevel@tonic-gate { 26407c478bd9Sstevel@tonic-gate #if NETINET 26417c478bd9Sstevel@tonic-gate case AF_INET: 26427c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 26437c478bd9Sstevel@tonic-gate break; 26447c478bd9Sstevel@tonic-gate #endif /* NETINET */ 26457c478bd9Sstevel@tonic-gate 26467c478bd9Sstevel@tonic-gate #if NETINET6 26477c478bd9Sstevel@tonic-gate case AF_INET6: 26487c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 26497c478bd9Sstevel@tonic-gate &ConnectOnlyTo.sin6.sin6_addr, 26507c478bd9Sstevel@tonic-gate IN6ADDRSZ); 26517c478bd9Sstevel@tonic-gate break; 26527c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26537c478bd9Sstevel@tonic-gate } 26547c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 26557c478bd9Sstevel@tonic-gate sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr)); 26567c478bd9Sstevel@tonic-gate i = connect(s, (struct sockaddr *) &addr, addrlen); 26577c478bd9Sstevel@tonic-gate save_errno = errno; 26587c478bd9Sstevel@tonic-gate if (ev != NULL) 26597c478bd9Sstevel@tonic-gate sm_clrevent(ev); 26607c478bd9Sstevel@tonic-gate if (i >= 0) 26617c478bd9Sstevel@tonic-gate break; 26627c478bd9Sstevel@tonic-gate } 26637c478bd9Sstevel@tonic-gate else 26647c478bd9Sstevel@tonic-gate save_errno = errno; 26657c478bd9Sstevel@tonic-gate 26667c478bd9Sstevel@tonic-gate /* couldn't connect.... figure out why */ 26677c478bd9Sstevel@tonic-gate (void) close(s); 26687c478bd9Sstevel@tonic-gate 26697c478bd9Sstevel@tonic-gate /* if running demand-dialed connection, try again */ 26707c478bd9Sstevel@tonic-gate if (DialDelay > 0 && firstconnect && 26717c478bd9Sstevel@tonic-gate bitnset(M_DIALDELAY, mci->mci_mailer->m_flags)) 26727c478bd9Sstevel@tonic-gate { 26737c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 26747c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying again...\n", 26757c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 26767c478bd9Sstevel@tonic-gate firstconnect = false; 26777c478bd9Sstevel@tonic-gate (void) sleep(DialDelay); 26787c478bd9Sstevel@tonic-gate continue; 26797c478bd9Sstevel@tonic-gate } 26807c478bd9Sstevel@tonic-gate 26817c478bd9Sstevel@tonic-gate if (LogLevel > 13) 26827c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 26837c478bd9Sstevel@tonic-gate "makeconnection (%s [%s]) failed: %s", 26847c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), 26857c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 26867c478bd9Sstevel@tonic-gate 26877c478bd9Sstevel@tonic-gate #if NETINET6 26887c478bd9Sstevel@tonic-gate nextaddr: 26897c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 26907c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_addr_list[addrno] != NULL && 26917c478bd9Sstevel@tonic-gate (enough == 0 || curtime() < enough)) 26927c478bd9Sstevel@tonic-gate { 26937c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 26947c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying new address....\n", 26957c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 26967c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 26977c478bd9Sstevel@tonic-gate { 26987c478bd9Sstevel@tonic-gate #if NETINET 26997c478bd9Sstevel@tonic-gate case AF_INET: 27007c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 27017c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27027c478bd9Sstevel@tonic-gate INADDRSZ); 27037c478bd9Sstevel@tonic-gate break; 27047c478bd9Sstevel@tonic-gate #endif /* NETINET */ 27057c478bd9Sstevel@tonic-gate 27067c478bd9Sstevel@tonic-gate #if NETINET6 27077c478bd9Sstevel@tonic-gate case AF_INET6: 27087c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 27097c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27107c478bd9Sstevel@tonic-gate IN6ADDRSZ); 27117c478bd9Sstevel@tonic-gate break; 27127c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27137c478bd9Sstevel@tonic-gate 27147c478bd9Sstevel@tonic-gate default: 27157c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, 27167c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 27177c478bd9Sstevel@tonic-gate hp->h_length); 27187c478bd9Sstevel@tonic-gate break; 27197c478bd9Sstevel@tonic-gate } 27207c478bd9Sstevel@tonic-gate continue; 27217c478bd9Sstevel@tonic-gate } 27227c478bd9Sstevel@tonic-gate errno = save_errno; 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate #if NETINET6 27257c478bd9Sstevel@tonic-gate if (family == AF_INET6) 27267c478bd9Sstevel@tonic-gate { 27277c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 27287c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); retrying with AF_INET....\n", 27297c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27307c478bd9Sstevel@tonic-gate v6found = true; 27317c478bd9Sstevel@tonic-gate family = AF_INET; 27327c478bd9Sstevel@tonic-gate if (hp != NULL) 27337c478bd9Sstevel@tonic-gate { 27347c478bd9Sstevel@tonic-gate freehostent(hp); 27357c478bd9Sstevel@tonic-gate hp = NULL; 27367c478bd9Sstevel@tonic-gate } 27377c478bd9Sstevel@tonic-gate goto v4retry; 27387c478bd9Sstevel@tonic-gate } 27397c478bd9Sstevel@tonic-gate v6tempfail: 27407c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27417c478bd9Sstevel@tonic-gate /* couldn't open connection */ 27427c478bd9Sstevel@tonic-gate #if NETINET6 27437c478bd9Sstevel@tonic-gate /* Don't clobber an already saved errno from v4retry */ 27447c478bd9Sstevel@tonic-gate if (errno > 0) 27457c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27467c478bd9Sstevel@tonic-gate save_errno = errno; 27477c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 27487c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s)\n", 27497c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 27507c478bd9Sstevel@tonic-gate #if XLA 27517c478bd9Sstevel@tonic-gate xla_host_end(host); 27527c478bd9Sstevel@tonic-gate #endif /* XLA */ 27537c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 27547c478bd9Sstevel@tonic-gate #if NETINET6 27557c478bd9Sstevel@tonic-gate if (hp != NULL) 27567c478bd9Sstevel@tonic-gate freehostent(hp); 27577c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27587c478bd9Sstevel@tonic-gate errno = save_errno; 27597c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 27607c478bd9Sstevel@tonic-gate } 27617c478bd9Sstevel@tonic-gate 27627c478bd9Sstevel@tonic-gate #if NETINET6 27637c478bd9Sstevel@tonic-gate if (hp != NULL) 27647c478bd9Sstevel@tonic-gate { 27657c478bd9Sstevel@tonic-gate freehostent(hp); 27667c478bd9Sstevel@tonic-gate hp = NULL; 27677c478bd9Sstevel@tonic-gate } 27687c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 27697c478bd9Sstevel@tonic-gate 27707c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 27717c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 27727c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 27737c478bd9Sstevel@tonic-gate (void *) &s, 27747c478bd9Sstevel@tonic-gate SM_IO_WRONLY_B, NULL)) == NULL || 27757c478bd9Sstevel@tonic-gate (s = dup(s)) < 0 || 27767c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 27777c478bd9Sstevel@tonic-gate (void *) &s, 27787c478bd9Sstevel@tonic-gate SM_IO_RDONLY_B, NULL)) == NULL) 27797c478bd9Sstevel@tonic-gate { 27807c478bd9Sstevel@tonic-gate save_errno = errno; 27817c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", s); 27827c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 27837c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 27847c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 27857c478bd9Sstevel@tonic-gate (void) close(s); 27867c478bd9Sstevel@tonic-gate errno = save_errno; 27877c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 27887c478bd9Sstevel@tonic-gate } 27897c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 27907c478bd9Sstevel@tonic-gate 27917c478bd9Sstevel@tonic-gate /* set {client_flags} */ 27927c478bd9Sstevel@tonic-gate if (ClientSettings[addr.sa.sa_family].d_mflags != NULL) 27937c478bd9Sstevel@tonic-gate { 27947c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 27957c478bd9Sstevel@tonic-gate macid("{client_flags}"), 27967c478bd9Sstevel@tonic-gate ClientSettings[addr.sa.sa_family].d_mflags); 27977c478bd9Sstevel@tonic-gate } 27987c478bd9Sstevel@tonic-gate else 27997c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 28007c478bd9Sstevel@tonic-gate macid("{client_flags}"), ""); 28017c478bd9Sstevel@tonic-gate 28027c478bd9Sstevel@tonic-gate /* "add" {client_flags} to bitmap */ 28037c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags)) 28047c478bd9Sstevel@tonic-gate { 28057c478bd9Sstevel@tonic-gate /* look for just this one flag */ 28067c478bd9Sstevel@tonic-gate setbitn(D_IFNHELO, d_flags); 28077c478bd9Sstevel@tonic-gate } 28087c478bd9Sstevel@tonic-gate 28097c478bd9Sstevel@tonic-gate /* find out name for Interface through which we connect */ 2810*058561cbSjbeck len = sizeof(addr); 28117c478bd9Sstevel@tonic-gate if (getsockname(s, &addr.sa, &len) == 0) 28127c478bd9Sstevel@tonic-gate { 28137c478bd9Sstevel@tonic-gate char *name; 28147c478bd9Sstevel@tonic-gate char family[5]; 28157c478bd9Sstevel@tonic-gate 28167c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28177c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), anynet_ntoa(&addr)); 28187c478bd9Sstevel@tonic-gate (void) sm_snprintf(family, sizeof(family), "%d", 28197c478bd9Sstevel@tonic-gate addr.sa.sa_family); 28207c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28217c478bd9Sstevel@tonic-gate macid("{if_family_out}"), family); 28227c478bd9Sstevel@tonic-gate 28237c478bd9Sstevel@tonic-gate name = hostnamebyanyaddr(&addr); 28247c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 28257c478bd9Sstevel@tonic-gate macid("{if_name_out}"), name); 28267c478bd9Sstevel@tonic-gate if (LogLevel > 11) 28277c478bd9Sstevel@tonic-gate { 28287c478bd9Sstevel@tonic-gate /* log connection information */ 28297c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 28307c478bd9Sstevel@tonic-gate "SMTP outgoing connect on %.40s", name); 28317c478bd9Sstevel@tonic-gate } 28327c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, d_flags)) 28337c478bd9Sstevel@tonic-gate { 28347c478bd9Sstevel@tonic-gate if (name[0] != '[' && strchr(name, '.') != NULL) 28357c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(name); 28367c478bd9Sstevel@tonic-gate } 28377c478bd9Sstevel@tonic-gate } 28387c478bd9Sstevel@tonic-gate else 28397c478bd9Sstevel@tonic-gate { 28407c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28417c478bd9Sstevel@tonic-gate macid("{if_name_out}"), NULL); 28427c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28437c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), NULL); 28447c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 28457c478bd9Sstevel@tonic-gate macid("{if_family_out}"), NULL); 28467c478bd9Sstevel@tonic-gate } 28477c478bd9Sstevel@tonic-gate 28487c478bd9Sstevel@tonic-gate /* Use the configured HeloName as appropriate */ 28497c478bd9Sstevel@tonic-gate if (HeloName != NULL && HeloName[0] != '\0') 28507c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(HeloName); 28517c478bd9Sstevel@tonic-gate 28527c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 28537c478bd9Sstevel@tonic-gate return EX_OK; 28547c478bd9Sstevel@tonic-gate } 28557c478bd9Sstevel@tonic-gate 28567c478bd9Sstevel@tonic-gate static void 28577c478bd9Sstevel@tonic-gate connecttimeout(ignore) 28587c478bd9Sstevel@tonic-gate int ignore; 28597c478bd9Sstevel@tonic-gate { 28607c478bd9Sstevel@tonic-gate /* 28617c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 28627c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 28637c478bd9Sstevel@tonic-gate ** DOING. 28647c478bd9Sstevel@tonic-gate */ 28657c478bd9Sstevel@tonic-gate 28667c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 28677c478bd9Sstevel@tonic-gate longjmp(CtxConnectTimeout, 1); 28687c478bd9Sstevel@tonic-gate } 28697c478bd9Sstevel@tonic-gate /* 28707c478bd9Sstevel@tonic-gate ** MAKECONNECTION_DS -- make a connection to a domain socket. 28717c478bd9Sstevel@tonic-gate ** 28727c478bd9Sstevel@tonic-gate ** Parameters: 28737c478bd9Sstevel@tonic-gate ** mux_path -- the path of the socket to connect to. 28747c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 28757c478bd9Sstevel@tonic-gate ** structure to be filled in. 28767c478bd9Sstevel@tonic-gate ** 28777c478bd9Sstevel@tonic-gate ** Returns: 28787c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 28797c478bd9Sstevel@tonic-gate ** made and if not why not. 28807c478bd9Sstevel@tonic-gate ** 28817c478bd9Sstevel@tonic-gate ** Side Effects: 28827c478bd9Sstevel@tonic-gate ** none. 28837c478bd9Sstevel@tonic-gate */ 28847c478bd9Sstevel@tonic-gate 28857c478bd9Sstevel@tonic-gate #if NETUNIX 28867c478bd9Sstevel@tonic-gate int 28877c478bd9Sstevel@tonic-gate makeconnection_ds(mux_path, mci) 28887c478bd9Sstevel@tonic-gate char *mux_path; 28897c478bd9Sstevel@tonic-gate register MCI *mci; 28907c478bd9Sstevel@tonic-gate { 28917c478bd9Sstevel@tonic-gate int sock; 28927c478bd9Sstevel@tonic-gate int rval, save_errno; 28937c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 28947c478bd9Sstevel@tonic-gate struct sockaddr_un unix_addr; 28957c478bd9Sstevel@tonic-gate 28967c478bd9Sstevel@tonic-gate /* if not safe, don't connect */ 28977c478bd9Sstevel@tonic-gate rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 28987c478bd9Sstevel@tonic-gate sff, S_IRUSR|S_IWUSR, NULL); 28997c478bd9Sstevel@tonic-gate 29007c478bd9Sstevel@tonic-gate if (rval != 0) 29017c478bd9Sstevel@tonic-gate { 29027c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: unsafe domain socket %s", 29037c478bd9Sstevel@tonic-gate mux_path); 29047c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 29057c478bd9Sstevel@tonic-gate errno = rval; 29067c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29077c478bd9Sstevel@tonic-gate } 29087c478bd9Sstevel@tonic-gate 29097c478bd9Sstevel@tonic-gate /* prepare address structure */ 2910*058561cbSjbeck memset(&unix_addr, '\0', sizeof(unix_addr)); 29117c478bd9Sstevel@tonic-gate unix_addr.sun_family = AF_UNIX; 29127c478bd9Sstevel@tonic-gate 2913*058561cbSjbeck if (strlen(mux_path) >= sizeof(unix_addr.sun_path)) 29147c478bd9Sstevel@tonic-gate { 29157c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: domain socket name %s too long", 29167c478bd9Sstevel@tonic-gate mux_path); 29177c478bd9Sstevel@tonic-gate 29187c478bd9Sstevel@tonic-gate /* XXX why TEMPFAIL but 5.x.y ? */ 29197c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 29207c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 29217c478bd9Sstevel@tonic-gate return EX_UNAVAILABLE; 29227c478bd9Sstevel@tonic-gate } 29237c478bd9Sstevel@tonic-gate (void) sm_strlcpy(unix_addr.sun_path, mux_path, 2924*058561cbSjbeck sizeof(unix_addr.sun_path)); 29257c478bd9Sstevel@tonic-gate 29267c478bd9Sstevel@tonic-gate /* initialize domain socket */ 29277c478bd9Sstevel@tonic-gate sock = socket(AF_UNIX, SOCK_STREAM, 0); 29287c478bd9Sstevel@tonic-gate if (sock == -1) 29297c478bd9Sstevel@tonic-gate { 29307c478bd9Sstevel@tonic-gate save_errno = errno; 29317c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: could not create domain socket %s", 29327c478bd9Sstevel@tonic-gate mux_path); 29337c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 29347c478bd9Sstevel@tonic-gate errno = save_errno; 29357c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29367c478bd9Sstevel@tonic-gate } 29377c478bd9Sstevel@tonic-gate 29387c478bd9Sstevel@tonic-gate /* connect to server */ 29397c478bd9Sstevel@tonic-gate if (connect(sock, (struct sockaddr *) &unix_addr, 29407c478bd9Sstevel@tonic-gate sizeof(unix_addr)) == -1) 29417c478bd9Sstevel@tonic-gate { 29427c478bd9Sstevel@tonic-gate save_errno = errno; 29437c478bd9Sstevel@tonic-gate syserr("Could not connect to socket %s", mux_path); 29447c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 29457c478bd9Sstevel@tonic-gate (void) close(sock); 29467c478bd9Sstevel@tonic-gate errno = save_errno; 29477c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29487c478bd9Sstevel@tonic-gate } 29497c478bd9Sstevel@tonic-gate 29507c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 29517c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 29527c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 29537c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_WRONLY_B, NULL)) 29547c478bd9Sstevel@tonic-gate == NULL 29557c478bd9Sstevel@tonic-gate || (sock = dup(sock)) < 0 || 29567c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 29577c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_RDONLY_B, NULL)) 29587c478bd9Sstevel@tonic-gate == NULL) 29597c478bd9Sstevel@tonic-gate { 29607c478bd9Sstevel@tonic-gate save_errno = errno; 29617c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", sock); 29627c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 29637c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 29647c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 29657c478bd9Sstevel@tonic-gate (void) close(sock); 29667c478bd9Sstevel@tonic-gate errno = save_errno; 29677c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 29687c478bd9Sstevel@tonic-gate } 29697c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 29707c478bd9Sstevel@tonic-gate 29717c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 29727c478bd9Sstevel@tonic-gate errno = 0; 29737c478bd9Sstevel@tonic-gate return EX_OK; 29747c478bd9Sstevel@tonic-gate } 29757c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 29767c478bd9Sstevel@tonic-gate /* 29777c478bd9Sstevel@tonic-gate ** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon 29787c478bd9Sstevel@tonic-gate ** 29797c478bd9Sstevel@tonic-gate ** Parameters: 29807c478bd9Sstevel@tonic-gate ** none. 29817c478bd9Sstevel@tonic-gate ** 29827c478bd9Sstevel@tonic-gate ** Returns: 29837c478bd9Sstevel@tonic-gate ** none. 29847c478bd9Sstevel@tonic-gate ** 29857c478bd9Sstevel@tonic-gate ** Side Effects: 29867c478bd9Sstevel@tonic-gate ** closes control socket, exits. 29877c478bd9Sstevel@tonic-gate */ 29887c478bd9Sstevel@tonic-gate 29897c478bd9Sstevel@tonic-gate void 29907c478bd9Sstevel@tonic-gate shutdown_daemon() 29917c478bd9Sstevel@tonic-gate { 29927c478bd9Sstevel@tonic-gate int i; 29937c478bd9Sstevel@tonic-gate char *reason; 29947c478bd9Sstevel@tonic-gate 29957c478bd9Sstevel@tonic-gate sm_allsignals(true); 29967c478bd9Sstevel@tonic-gate 29977c478bd9Sstevel@tonic-gate reason = ShutdownRequest; 29987c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 29997c478bd9Sstevel@tonic-gate PendingSignal = 0; 30007c478bd9Sstevel@tonic-gate 30017c478bd9Sstevel@tonic-gate if (LogLevel > 9) 30027c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s", 30037c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 30047c478bd9Sstevel@tonic-gate 30057c478bd9Sstevel@tonic-gate FileName = NULL; 30067c478bd9Sstevel@tonic-gate closecontrolsocket(true); 30077c478bd9Sstevel@tonic-gate #if XLA 30087c478bd9Sstevel@tonic-gate xla_all_end(); 30097c478bd9Sstevel@tonic-gate #endif /* XLA */ 30107c478bd9Sstevel@tonic-gate 30117c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 30127c478bd9Sstevel@tonic-gate { 30137c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 30147c478bd9Sstevel@tonic-gate { 30157c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 30167c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 30177c478bd9Sstevel@tonic-gate 30187c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 30197c478bd9Sstevel@tonic-gate # if NETUNIX 30207c478bd9Sstevel@tonic-gate /* Remove named sockets */ 30217c478bd9Sstevel@tonic-gate if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) 30227c478bd9Sstevel@tonic-gate { 30237c478bd9Sstevel@tonic-gate int rval; 30247c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT; 30257c478bd9Sstevel@tonic-gate 30267c478bd9Sstevel@tonic-gate /* if not safe, don't use it */ 30277c478bd9Sstevel@tonic-gate rval = safefile(Daemons[i].d_addr.sunix.sun_path, 30287c478bd9Sstevel@tonic-gate RunAsUid, RunAsGid, 30297c478bd9Sstevel@tonic-gate RunAsUserName, sff, 30307c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 30317c478bd9Sstevel@tonic-gate if (rval == 0 && 30327c478bd9Sstevel@tonic-gate unlink(Daemons[i].d_addr.sunix.sun_path) < 0) 30337c478bd9Sstevel@tonic-gate { 30347c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 30357c478bd9Sstevel@tonic-gate "Could not remove daemon %s socket: %s: %s", 30367c478bd9Sstevel@tonic-gate Daemons[i].d_name, 30377c478bd9Sstevel@tonic-gate Daemons[i].d_addr.sunix.sun_path, 30387c478bd9Sstevel@tonic-gate sm_errstring(errno)); 30397c478bd9Sstevel@tonic-gate } 30407c478bd9Sstevel@tonic-gate } 30417c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 30427c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 30437c478bd9Sstevel@tonic-gate } 30447c478bd9Sstevel@tonic-gate } 30457c478bd9Sstevel@tonic-gate 30467c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 30477c478bd9Sstevel@tonic-gate } 30487c478bd9Sstevel@tonic-gate /* 30497c478bd9Sstevel@tonic-gate ** RESTART_DAEMON -- Performs a clean restart of the daemon 30507c478bd9Sstevel@tonic-gate ** 30517c478bd9Sstevel@tonic-gate ** Parameters: 30527c478bd9Sstevel@tonic-gate ** none. 30537c478bd9Sstevel@tonic-gate ** 30547c478bd9Sstevel@tonic-gate ** Returns: 30557c478bd9Sstevel@tonic-gate ** none. 30567c478bd9Sstevel@tonic-gate ** 30577c478bd9Sstevel@tonic-gate ** Side Effects: 30587c478bd9Sstevel@tonic-gate ** restarts the daemon or exits if restart fails. 30597c478bd9Sstevel@tonic-gate */ 30607c478bd9Sstevel@tonic-gate 30617c478bd9Sstevel@tonic-gate /* Make a non-DFL/IGN signal a noop */ 30627c478bd9Sstevel@tonic-gate #define SM_NOOP_SIGNAL(sig, old) \ 30637c478bd9Sstevel@tonic-gate do \ 30647c478bd9Sstevel@tonic-gate { \ 30657c478bd9Sstevel@tonic-gate (old) = sm_signal((sig), sm_signal_noop); \ 30667c478bd9Sstevel@tonic-gate if ((old) == SIG_IGN || (old) == SIG_DFL) \ 30677c478bd9Sstevel@tonic-gate (void) sm_signal((sig), (old)); \ 30687c478bd9Sstevel@tonic-gate } while (0) 30697c478bd9Sstevel@tonic-gate 30707c478bd9Sstevel@tonic-gate void 30717c478bd9Sstevel@tonic-gate restart_daemon() 30727c478bd9Sstevel@tonic-gate { 30737c478bd9Sstevel@tonic-gate bool drop; 30747c478bd9Sstevel@tonic-gate int save_errno; 30757c478bd9Sstevel@tonic-gate char *reason; 30767c478bd9Sstevel@tonic-gate sigfunc_t ignore, oalrm, ousr1; 30777c478bd9Sstevel@tonic-gate extern int DtableSize; 30787c478bd9Sstevel@tonic-gate 30797c478bd9Sstevel@tonic-gate /* clear the events to turn off SIGALRMs */ 30807c478bd9Sstevel@tonic-gate sm_clear_events(); 30817c478bd9Sstevel@tonic-gate sm_allsignals(true); 30827c478bd9Sstevel@tonic-gate 30837c478bd9Sstevel@tonic-gate reason = RestartRequest; 30847c478bd9Sstevel@tonic-gate RestartRequest = NULL; 30857c478bd9Sstevel@tonic-gate PendingSignal = 0; 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate if (SaveArgv[0][0] != '/') 30887c478bd9Sstevel@tonic-gate { 30897c478bd9Sstevel@tonic-gate if (LogLevel > 3) 30907c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 30917c478bd9Sstevel@tonic-gate "could not restart: need full path"); 30927c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 30937c478bd9Sstevel@tonic-gate /* NOTREACHED */ 30947c478bd9Sstevel@tonic-gate } 30957c478bd9Sstevel@tonic-gate if (LogLevel > 3) 30967c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 30977c478bd9Sstevel@tonic-gate SaveArgv[0], 30987c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate closecontrolsocket(true); 31017c478bd9Sstevel@tonic-gate #if SM_CONF_SHM 31027c478bd9Sstevel@tonic-gate cleanup_shm(DaemonPid == getpid()); 31037c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SHM */ 31047c478bd9Sstevel@tonic-gate 31057c478bd9Sstevel@tonic-gate /* close locked pid file */ 31067c478bd9Sstevel@tonic-gate close_sendmail_pid(); 31077c478bd9Sstevel@tonic-gate 31087c478bd9Sstevel@tonic-gate /* 31097c478bd9Sstevel@tonic-gate ** Want to drop to the user who started the process in all cases 31107c478bd9Sstevel@tonic-gate ** *but* when running as "smmsp" for the clientmqueue queue run 31117c478bd9Sstevel@tonic-gate ** daemon. In that case, UseMSP will be true, RunAsUid should not 31127c478bd9Sstevel@tonic-gate ** be root, and RealUid should be either 0 or RunAsUid. 31137c478bd9Sstevel@tonic-gate */ 31147c478bd9Sstevel@tonic-gate 31157c478bd9Sstevel@tonic-gate drop = !(UseMSP && RunAsUid != 0 && 31167c478bd9Sstevel@tonic-gate (RealUid == 0 || RealUid == RunAsUid)); 31177c478bd9Sstevel@tonic-gate 31187c478bd9Sstevel@tonic-gate if (drop_privileges(drop) != EX_OK) 31197c478bd9Sstevel@tonic-gate { 31207c478bd9Sstevel@tonic-gate if (LogLevel > 0) 31217c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 31227c478bd9Sstevel@tonic-gate "could not drop privileges: %s", 31237c478bd9Sstevel@tonic-gate sm_errstring(errno)); 31247c478bd9Sstevel@tonic-gate finis(false, true, EX_OSERR); 31257c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31267c478bd9Sstevel@tonic-gate } 31277c478bd9Sstevel@tonic-gate 31287c478bd9Sstevel@tonic-gate sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 31297c478bd9Sstevel@tonic-gate 31307c478bd9Sstevel@tonic-gate /* 31317c478bd9Sstevel@tonic-gate ** Need to allow signals before execve() to make them "harmless". 31327c478bd9Sstevel@tonic-gate ** However, the default action can be "terminate", so it isn't 31337c478bd9Sstevel@tonic-gate ** really harmless. Setting signals to IGN will cause them to be 31347c478bd9Sstevel@tonic-gate ** ignored in the new process to, so that isn't a good alternative. 31357c478bd9Sstevel@tonic-gate */ 31367c478bd9Sstevel@tonic-gate 31377c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGALRM, oalrm); 31387c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGCHLD, ignore); 31397c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGHUP, ignore); 31407c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGINT, ignore); 31417c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGPIPE, ignore); 31427c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGTERM, ignore); 31437c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 31447c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGUSR1, ousr1); 31457c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate /* Turn back on signals */ 31487c478bd9Sstevel@tonic-gate sm_allsignals(false); 31497c478bd9Sstevel@tonic-gate 31507c478bd9Sstevel@tonic-gate (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 31517c478bd9Sstevel@tonic-gate save_errno = errno; 31527c478bd9Sstevel@tonic-gate 31537c478bd9Sstevel@tonic-gate /* block signals again and restore needed signals */ 31547c478bd9Sstevel@tonic-gate sm_allsignals(true); 31557c478bd9Sstevel@tonic-gate 31567c478bd9Sstevel@tonic-gate /* For finis() events */ 31577c478bd9Sstevel@tonic-gate (void) sm_signal(SIGALRM, oalrm); 31587c478bd9Sstevel@tonic-gate 31597c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 31607c478bd9Sstevel@tonic-gate /* For debugging finis() */ 31617c478bd9Sstevel@tonic-gate (void) sm_signal(SIGUSR1, ousr1); 31627c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 31637c478bd9Sstevel@tonic-gate 31647c478bd9Sstevel@tonic-gate errno = save_errno; 31657c478bd9Sstevel@tonic-gate if (LogLevel > 0) 31667c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s", 31677c478bd9Sstevel@tonic-gate SaveArgv[0], sm_errstring(errno)); 31687c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 31697c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31707c478bd9Sstevel@tonic-gate } 31717c478bd9Sstevel@tonic-gate /* 31727c478bd9Sstevel@tonic-gate ** MYHOSTNAME -- return the name of this host. 31737c478bd9Sstevel@tonic-gate ** 31747c478bd9Sstevel@tonic-gate ** Parameters: 31757c478bd9Sstevel@tonic-gate ** hostbuf -- a place to return the name of this host. 31767c478bd9Sstevel@tonic-gate ** size -- the size of hostbuf. 31777c478bd9Sstevel@tonic-gate ** 31787c478bd9Sstevel@tonic-gate ** Returns: 31797c478bd9Sstevel@tonic-gate ** A list of aliases for this host. 31807c478bd9Sstevel@tonic-gate ** 31817c478bd9Sstevel@tonic-gate ** Side Effects: 31827c478bd9Sstevel@tonic-gate ** Adds numeric codes to $=w. 31837c478bd9Sstevel@tonic-gate */ 31847c478bd9Sstevel@tonic-gate 31857c478bd9Sstevel@tonic-gate struct hostent * 31867c478bd9Sstevel@tonic-gate myhostname(hostbuf, size) 31877c478bd9Sstevel@tonic-gate char hostbuf[]; 31887c478bd9Sstevel@tonic-gate int size; 31897c478bd9Sstevel@tonic-gate { 31907c478bd9Sstevel@tonic-gate register struct hostent *hp; 31917c478bd9Sstevel@tonic-gate 31927c478bd9Sstevel@tonic-gate if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 31937c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hostbuf, "localhost", size); 31947c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, InetMode); 31957c478bd9Sstevel@tonic-gate #if NETINET && NETINET6 31967c478bd9Sstevel@tonic-gate if (hp == NULL && InetMode == AF_INET6) 31977c478bd9Sstevel@tonic-gate { 31987c478bd9Sstevel@tonic-gate /* 31997c478bd9Sstevel@tonic-gate ** It's possible that this IPv6 enabled machine doesn't 32007c478bd9Sstevel@tonic-gate ** actually have any IPv6 interfaces and, therefore, no 32017c478bd9Sstevel@tonic-gate ** IPv6 addresses. Fall back to AF_INET. 32027c478bd9Sstevel@tonic-gate */ 32037c478bd9Sstevel@tonic-gate 32047c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, AF_INET); 32057c478bd9Sstevel@tonic-gate } 32067c478bd9Sstevel@tonic-gate #endif /* NETINET && NETINET6 */ 32077c478bd9Sstevel@tonic-gate if (hp == NULL) 32087c478bd9Sstevel@tonic-gate return NULL; 32097c478bd9Sstevel@tonic-gate if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 32107c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, hp->h_name, size); 32117c478bd9Sstevel@tonic-gate 32127c478bd9Sstevel@tonic-gate #if NETINFO 32137c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 32147c478bd9Sstevel@tonic-gate { 32157c478bd9Sstevel@tonic-gate char *domainname; 32167c478bd9Sstevel@tonic-gate 32177c478bd9Sstevel@tonic-gate domainname = ni_propval("/locations", NULL, "resolver", 32187c478bd9Sstevel@tonic-gate "domain", '\0'); 32197c478bd9Sstevel@tonic-gate if (domainname != NULL && 32207c478bd9Sstevel@tonic-gate strlen(domainname) + strlen(hostbuf) + 1 < size) 32217c478bd9Sstevel@tonic-gate (void) sm_strlcat2(hostbuf, ".", domainname, size); 32227c478bd9Sstevel@tonic-gate } 32237c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 32247c478bd9Sstevel@tonic-gate 32257c478bd9Sstevel@tonic-gate /* 32267c478bd9Sstevel@tonic-gate ** If there is still no dot in the name, try looking for a 32277c478bd9Sstevel@tonic-gate ** dotted alias. 32287c478bd9Sstevel@tonic-gate */ 32297c478bd9Sstevel@tonic-gate 32307c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 32317c478bd9Sstevel@tonic-gate { 32327c478bd9Sstevel@tonic-gate char **ha; 32337c478bd9Sstevel@tonic-gate 32347c478bd9Sstevel@tonic-gate for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 32357c478bd9Sstevel@tonic-gate { 32367c478bd9Sstevel@tonic-gate if (strchr(*ha, '.') != NULL) 32377c478bd9Sstevel@tonic-gate { 32387c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, *ha, size - 1); 32397c478bd9Sstevel@tonic-gate hostbuf[size - 1] = '\0'; 32407c478bd9Sstevel@tonic-gate break; 32417c478bd9Sstevel@tonic-gate } 32427c478bd9Sstevel@tonic-gate } 32437c478bd9Sstevel@tonic-gate } 32447c478bd9Sstevel@tonic-gate 32457c478bd9Sstevel@tonic-gate /* 32467c478bd9Sstevel@tonic-gate ** If _still_ no dot, wait for a while and try again -- it is 32477c478bd9Sstevel@tonic-gate ** possible that some service is starting up. This can result 32487c478bd9Sstevel@tonic-gate ** in excessive delays if the system is badly configured, but 32497c478bd9Sstevel@tonic-gate ** there really isn't a way around that, particularly given that 32507c478bd9Sstevel@tonic-gate ** the config file hasn't been read at this point. 32517c478bd9Sstevel@tonic-gate ** All in all, a bit of a mess. 32527c478bd9Sstevel@tonic-gate */ 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL && 32557c478bd9Sstevel@tonic-gate !getcanonname(hostbuf, size, true, NULL)) 32567c478bd9Sstevel@tonic-gate { 32577c478bd9Sstevel@tonic-gate sm_syslog(LOG_CRIT, NOQID, 32587c478bd9Sstevel@tonic-gate "My unqualified host name (%s) unknown; sleeping for retry", 32597c478bd9Sstevel@tonic-gate hostbuf); 32607c478bd9Sstevel@tonic-gate message("My unqualified host name (%s) unknown; sleeping for retry", 32617c478bd9Sstevel@tonic-gate hostbuf); 32627c478bd9Sstevel@tonic-gate (void) sleep(60); 32637c478bd9Sstevel@tonic-gate if (!getcanonname(hostbuf, size, true, NULL)) 32647c478bd9Sstevel@tonic-gate { 32657c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 32667c478bd9Sstevel@tonic-gate "unable to qualify my own domain name (%s) -- using short name", 32677c478bd9Sstevel@tonic-gate hostbuf); 32687c478bd9Sstevel@tonic-gate message("WARNING: unable to qualify my own domain name (%s) -- using short name", 32697c478bd9Sstevel@tonic-gate hostbuf); 32707c478bd9Sstevel@tonic-gate } 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate return hp; 32737c478bd9Sstevel@tonic-gate } 32747c478bd9Sstevel@tonic-gate /* 32757c478bd9Sstevel@tonic-gate ** ADDRCMP -- compare two host addresses 32767c478bd9Sstevel@tonic-gate ** 32777c478bd9Sstevel@tonic-gate ** Parameters: 32787c478bd9Sstevel@tonic-gate ** hp -- hostent structure for the first address 32797c478bd9Sstevel@tonic-gate ** ha -- actual first address 32807c478bd9Sstevel@tonic-gate ** sa -- second address 32817c478bd9Sstevel@tonic-gate ** 32827c478bd9Sstevel@tonic-gate ** Returns: 32837c478bd9Sstevel@tonic-gate ** 0 -- if ha and sa match 32847c478bd9Sstevel@tonic-gate ** else -- they don't match 32857c478bd9Sstevel@tonic-gate */ 32867c478bd9Sstevel@tonic-gate 32877c478bd9Sstevel@tonic-gate static int 32887c478bd9Sstevel@tonic-gate addrcmp(hp, ha, sa) 32897c478bd9Sstevel@tonic-gate struct hostent *hp; 32907c478bd9Sstevel@tonic-gate char *ha; 32917c478bd9Sstevel@tonic-gate SOCKADDR *sa; 32927c478bd9Sstevel@tonic-gate { 32937c478bd9Sstevel@tonic-gate #if NETINET6 32947c478bd9Sstevel@tonic-gate unsigned char *a; 32957c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 32967c478bd9Sstevel@tonic-gate 32977c478bd9Sstevel@tonic-gate switch (sa->sa.sa_family) 32987c478bd9Sstevel@tonic-gate { 32997c478bd9Sstevel@tonic-gate #if NETINET 33007c478bd9Sstevel@tonic-gate case AF_INET: 33017c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET) 33027c478bd9Sstevel@tonic-gate return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 33037c478bd9Sstevel@tonic-gate break; 33047c478bd9Sstevel@tonic-gate #endif /* NETINET */ 33057c478bd9Sstevel@tonic-gate 33067c478bd9Sstevel@tonic-gate #if NETINET6 33077c478bd9Sstevel@tonic-gate case AF_INET6: 33087c478bd9Sstevel@tonic-gate a = (unsigned char *) &sa->sin6.sin6_addr; 33097c478bd9Sstevel@tonic-gate 33107c478bd9Sstevel@tonic-gate /* Straight binary comparison */ 33117c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET6) 33127c478bd9Sstevel@tonic-gate return memcmp(ha, a, IN6ADDRSZ); 33137c478bd9Sstevel@tonic-gate 33147c478bd9Sstevel@tonic-gate /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 33157c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET && 33167c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 33177c478bd9Sstevel@tonic-gate return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 33187c478bd9Sstevel@tonic-gate break; 33197c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 33207c478bd9Sstevel@tonic-gate } 33217c478bd9Sstevel@tonic-gate return -1; 33227c478bd9Sstevel@tonic-gate } 33237c478bd9Sstevel@tonic-gate /* 33247c478bd9Sstevel@tonic-gate ** GETAUTHINFO -- get the real host name associated with a file descriptor 33257c478bd9Sstevel@tonic-gate ** 33267c478bd9Sstevel@tonic-gate ** Uses RFC1413 protocol to try to get info from the other end. 33277c478bd9Sstevel@tonic-gate ** 33287c478bd9Sstevel@tonic-gate ** Parameters: 33297c478bd9Sstevel@tonic-gate ** fd -- the descriptor 33307c478bd9Sstevel@tonic-gate ** may_be_forged -- an outage that is set to true if the 33317c478bd9Sstevel@tonic-gate ** forward lookup of RealHostName does not match 33327c478bd9Sstevel@tonic-gate ** RealHostAddr; set to false if they do match. 33337c478bd9Sstevel@tonic-gate ** 33347c478bd9Sstevel@tonic-gate ** Returns: 33357c478bd9Sstevel@tonic-gate ** The user@host information associated with this descriptor. 33367c478bd9Sstevel@tonic-gate */ 33377c478bd9Sstevel@tonic-gate 33387c478bd9Sstevel@tonic-gate static jmp_buf CtxAuthTimeout; 33397c478bd9Sstevel@tonic-gate 33407c478bd9Sstevel@tonic-gate static void 33417c478bd9Sstevel@tonic-gate authtimeout(ignore) 33427c478bd9Sstevel@tonic-gate int ignore; 33437c478bd9Sstevel@tonic-gate { 33447c478bd9Sstevel@tonic-gate /* 33457c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 33467c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 33477c478bd9Sstevel@tonic-gate ** DOING. 33487c478bd9Sstevel@tonic-gate */ 33497c478bd9Sstevel@tonic-gate 33507c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 33517c478bd9Sstevel@tonic-gate longjmp(CtxAuthTimeout, 1); 33527c478bd9Sstevel@tonic-gate } 33537c478bd9Sstevel@tonic-gate 33547c478bd9Sstevel@tonic-gate char * 33557c478bd9Sstevel@tonic-gate getauthinfo(fd, may_be_forged) 33567c478bd9Sstevel@tonic-gate int fd; 33577c478bd9Sstevel@tonic-gate bool *may_be_forged; 33587c478bd9Sstevel@tonic-gate { 33597c478bd9Sstevel@tonic-gate unsigned short SM_NONVOLATILE port = 0; 33607c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T falen; 33617c478bd9Sstevel@tonic-gate register char *volatile p = NULL; 33627c478bd9Sstevel@tonic-gate SOCKADDR la; 33637c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T lalen; 33647c478bd9Sstevel@tonic-gate #ifndef NO_GETSERVBYNAME 33657c478bd9Sstevel@tonic-gate register struct servent *sp; 33667c478bd9Sstevel@tonic-gate # if NETINET 33677c478bd9Sstevel@tonic-gate static unsigned short port4 = 0; 33687c478bd9Sstevel@tonic-gate # endif /* NETINET */ 33697c478bd9Sstevel@tonic-gate # if NETINET6 33707c478bd9Sstevel@tonic-gate static unsigned short port6 = 0; 33717c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 33727c478bd9Sstevel@tonic-gate #endif /* ! NO_GETSERVBYNAME */ 33737c478bd9Sstevel@tonic-gate volatile int s; 33747c478bd9Sstevel@tonic-gate int i = 0; 33757c478bd9Sstevel@tonic-gate size_t len; 33767c478bd9Sstevel@tonic-gate SM_EVENT *ev; 33777c478bd9Sstevel@tonic-gate int nleft; 33787c478bd9Sstevel@tonic-gate struct hostent *hp; 33797c478bd9Sstevel@tonic-gate char *ostype = NULL; 33807c478bd9Sstevel@tonic-gate char **ha; 33817c478bd9Sstevel@tonic-gate char ibuf[MAXNAME + 1]; 33827c478bd9Sstevel@tonic-gate static char hbuf[MAXNAME + MAXAUTHINFO + 11]; 33837c478bd9Sstevel@tonic-gate 33847c478bd9Sstevel@tonic-gate *may_be_forged = false; 3385*058561cbSjbeck falen = sizeof(RealHostAddr); 33867c478bd9Sstevel@tonic-gate if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 33877c478bd9Sstevel@tonic-gate falen <= 0 || RealHostAddr.sa.sa_family == 0) 33887c478bd9Sstevel@tonic-gate { 33897c478bd9Sstevel@tonic-gate if (i < 0) 33907c478bd9Sstevel@tonic-gate { 33917c478bd9Sstevel@tonic-gate /* 33927c478bd9Sstevel@tonic-gate ** ENOTSOCK is OK: bail on anything else, but reset 33937c478bd9Sstevel@tonic-gate ** errno in this case, so a mis-report doesn't 33947c478bd9Sstevel@tonic-gate ** happen later. 33957c478bd9Sstevel@tonic-gate */ 33967c478bd9Sstevel@tonic-gate 33977c478bd9Sstevel@tonic-gate if (errno != ENOTSOCK) 33987c478bd9Sstevel@tonic-gate return NULL; 33997c478bd9Sstevel@tonic-gate errno = 0; 34007c478bd9Sstevel@tonic-gate } 3401*058561cbSjbeck (void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName, 34027c478bd9Sstevel@tonic-gate "@localhost"); 34037c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 34047c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 34057c478bd9Sstevel@tonic-gate return hbuf; 34067c478bd9Sstevel@tonic-gate } 34077c478bd9Sstevel@tonic-gate 34087c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 34097c478bd9Sstevel@tonic-gate { 34107c478bd9Sstevel@tonic-gate /* translate that to a host name */ 34117c478bd9Sstevel@tonic-gate RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 34127c478bd9Sstevel@tonic-gate if (strlen(RealHostName) > MAXNAME) 34137c478bd9Sstevel@tonic-gate RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ 34147c478bd9Sstevel@tonic-gate } 34157c478bd9Sstevel@tonic-gate 34167c478bd9Sstevel@tonic-gate /* cross check RealHostName with forward DNS lookup */ 34177c478bd9Sstevel@tonic-gate if (anynet_ntoa(&RealHostAddr)[0] != '[' && 34187c478bd9Sstevel@tonic-gate RealHostName[0] != '[') 34197c478bd9Sstevel@tonic-gate { 34207c478bd9Sstevel@tonic-gate int family; 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate family = RealHostAddr.sa.sa_family; 34237c478bd9Sstevel@tonic-gate #if NETINET6 && NEEDSGETIPNODE 34247c478bd9Sstevel@tonic-gate /* 34257c478bd9Sstevel@tonic-gate ** If RealHostAddr is an IPv6 connection with an 34267c478bd9Sstevel@tonic-gate ** IPv4-mapped address, we need RealHostName's IPv4 34277c478bd9Sstevel@tonic-gate ** address(es) for addrcmp() to compare against 34287c478bd9Sstevel@tonic-gate ** RealHostAddr. 34297c478bd9Sstevel@tonic-gate ** 34307c478bd9Sstevel@tonic-gate ** Actually, we only need to do this for systems 34317c478bd9Sstevel@tonic-gate ** which NEEDSGETIPNODE since the real getipnodebyname() 34327c478bd9Sstevel@tonic-gate ** already does V4MAPPED address via the AI_V4MAPPEDCFG 34337c478bd9Sstevel@tonic-gate ** flag. A better fix to this problem is to add this 34347c478bd9Sstevel@tonic-gate ** functionality to our stub getipnodebyname(). 34357c478bd9Sstevel@tonic-gate */ 34367c478bd9Sstevel@tonic-gate 34377c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 34387c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 34397c478bd9Sstevel@tonic-gate family = AF_INET; 34407c478bd9Sstevel@tonic-gate #endif /* NETINET6 && NEEDSGETIPNODE */ 34417c478bd9Sstevel@tonic-gate 34427c478bd9Sstevel@tonic-gate /* try to match the reverse against the forward lookup */ 34437c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(RealHostName, family); 34447c478bd9Sstevel@tonic-gate if (hp == NULL) 34457c478bd9Sstevel@tonic-gate { 34467c478bd9Sstevel@tonic-gate /* XXX: Could be a temporary error on forward lookup */ 34477c478bd9Sstevel@tonic-gate *may_be_forged = true; 34487c478bd9Sstevel@tonic-gate } 34497c478bd9Sstevel@tonic-gate else 34507c478bd9Sstevel@tonic-gate { 34517c478bd9Sstevel@tonic-gate for (ha = hp->h_addr_list; *ha != NULL; ha++) 34527c478bd9Sstevel@tonic-gate { 34537c478bd9Sstevel@tonic-gate if (addrcmp(hp, *ha, &RealHostAddr) == 0) 34547c478bd9Sstevel@tonic-gate break; 34557c478bd9Sstevel@tonic-gate } 34567c478bd9Sstevel@tonic-gate *may_be_forged = *ha == NULL; 34577c478bd9Sstevel@tonic-gate #if NETINET6 34587c478bd9Sstevel@tonic-gate freehostent(hp); 34597c478bd9Sstevel@tonic-gate hp = NULL; 34607c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 34617c478bd9Sstevel@tonic-gate } 34627c478bd9Sstevel@tonic-gate } 34637c478bd9Sstevel@tonic-gate 34647c478bd9Sstevel@tonic-gate if (TimeOuts.to_ident == 0) 34657c478bd9Sstevel@tonic-gate goto noident; 34667c478bd9Sstevel@tonic-gate 3467*058561cbSjbeck lalen = sizeof(la); 34687c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 34697c478bd9Sstevel@tonic-gate { 34707c478bd9Sstevel@tonic-gate #if NETINET 34717c478bd9Sstevel@tonic-gate case AF_INET: 34727c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 34737c478bd9Sstevel@tonic-gate lalen <= 0 || 34747c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET) 34757c478bd9Sstevel@tonic-gate { 34767c478bd9Sstevel@tonic-gate /* no ident info */ 34777c478bd9Sstevel@tonic-gate goto noident; 34787c478bd9Sstevel@tonic-gate } 34797c478bd9Sstevel@tonic-gate port = RealHostAddr.sin.sin_port; 34807c478bd9Sstevel@tonic-gate 34817c478bd9Sstevel@tonic-gate /* create ident query */ 3482*058561cbSjbeck (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 34837c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin.sin_port), 34847c478bd9Sstevel@tonic-gate ntohs(la.sin.sin_port)); 34857c478bd9Sstevel@tonic-gate 34867c478bd9Sstevel@tonic-gate /* create local address */ 34877c478bd9Sstevel@tonic-gate la.sin.sin_port = 0; 34887c478bd9Sstevel@tonic-gate 34897c478bd9Sstevel@tonic-gate /* create foreign address */ 34907c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 34917c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = htons(113); 34927c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 34937c478bd9Sstevel@tonic-gate 34947c478bd9Sstevel@tonic-gate /* 34957c478bd9Sstevel@tonic-gate ** getservbyname() consumes about 5% of the time 34967c478bd9Sstevel@tonic-gate ** when receiving a small message (almost all of the time 34977c478bd9Sstevel@tonic-gate ** spent in this routine). 34987c478bd9Sstevel@tonic-gate ** Hence we store the port in a static variable 34997c478bd9Sstevel@tonic-gate ** to save this time. 35007c478bd9Sstevel@tonic-gate ** The portnumber shouldn't change very often... 35017c478bd9Sstevel@tonic-gate ** This code makes the assumption that the port number 35027c478bd9Sstevel@tonic-gate ** is not 0. 35037c478bd9Sstevel@tonic-gate */ 35047c478bd9Sstevel@tonic-gate 35057c478bd9Sstevel@tonic-gate if (port4 == 0) 35067c478bd9Sstevel@tonic-gate { 35077c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 35087c478bd9Sstevel@tonic-gate if (sp != NULL) 35097c478bd9Sstevel@tonic-gate port4 = sp->s_port; 35107c478bd9Sstevel@tonic-gate else 35117c478bd9Sstevel@tonic-gate port4 = htons(113); 35127c478bd9Sstevel@tonic-gate } 35137c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port4; 35147c478bd9Sstevel@tonic-gate break; 35157c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 35167c478bd9Sstevel@tonic-gate #endif /* NETINET */ 35177c478bd9Sstevel@tonic-gate 35187c478bd9Sstevel@tonic-gate #if NETINET6 35197c478bd9Sstevel@tonic-gate case AF_INET6: 35207c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 35217c478bd9Sstevel@tonic-gate lalen <= 0 || 35227c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET6) 35237c478bd9Sstevel@tonic-gate { 35247c478bd9Sstevel@tonic-gate /* no ident info */ 35257c478bd9Sstevel@tonic-gate goto noident; 35267c478bd9Sstevel@tonic-gate } 35277c478bd9Sstevel@tonic-gate port = RealHostAddr.sin6.sin6_port; 35287c478bd9Sstevel@tonic-gate 35297c478bd9Sstevel@tonic-gate /* create ident query */ 3530*058561cbSjbeck (void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n", 35317c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin6.sin6_port), 35327c478bd9Sstevel@tonic-gate ntohs(la.sin6.sin6_port)); 35337c478bd9Sstevel@tonic-gate 35347c478bd9Sstevel@tonic-gate /* create local address */ 35357c478bd9Sstevel@tonic-gate la.sin6.sin6_port = 0; 35367c478bd9Sstevel@tonic-gate 35377c478bd9Sstevel@tonic-gate /* create foreign address */ 35387c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 35397c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = htons(113); 35407c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 35417c478bd9Sstevel@tonic-gate if (port6 == 0) 35427c478bd9Sstevel@tonic-gate { 35437c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 35447c478bd9Sstevel@tonic-gate if (sp != NULL) 35457c478bd9Sstevel@tonic-gate port6 = sp->s_port; 35467c478bd9Sstevel@tonic-gate else 35477c478bd9Sstevel@tonic-gate port6 = htons(113); 35487c478bd9Sstevel@tonic-gate } 35497c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port6; 35507c478bd9Sstevel@tonic-gate break; 35517c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 35527c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 35537c478bd9Sstevel@tonic-gate default: 35547c478bd9Sstevel@tonic-gate /* no ident info */ 35557c478bd9Sstevel@tonic-gate goto noident; 35567c478bd9Sstevel@tonic-gate } 35577c478bd9Sstevel@tonic-gate 35587c478bd9Sstevel@tonic-gate s = -1; 35597c478bd9Sstevel@tonic-gate if (setjmp(CtxAuthTimeout) != 0) 35607c478bd9Sstevel@tonic-gate { 35617c478bd9Sstevel@tonic-gate if (s >= 0) 35627c478bd9Sstevel@tonic-gate (void) close(s); 35637c478bd9Sstevel@tonic-gate goto noident; 35647c478bd9Sstevel@tonic-gate } 35657c478bd9Sstevel@tonic-gate 35667c478bd9Sstevel@tonic-gate /* put a timeout around the whole thing */ 35677c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0); 35687c478bd9Sstevel@tonic-gate 35697c478bd9Sstevel@tonic-gate /* connect to foreign IDENT server using same address as SMTP socket */ 35707c478bd9Sstevel@tonic-gate s = socket(la.sa.sa_family, SOCK_STREAM, 0); 35717c478bd9Sstevel@tonic-gate if (s < 0) 35727c478bd9Sstevel@tonic-gate { 35737c478bd9Sstevel@tonic-gate sm_clrevent(ev); 35747c478bd9Sstevel@tonic-gate goto noident; 35757c478bd9Sstevel@tonic-gate } 35767c478bd9Sstevel@tonic-gate if (bind(s, &la.sa, lalen) < 0 || 35777c478bd9Sstevel@tonic-gate connect(s, &RealHostAddr.sa, lalen) < 0) 35787c478bd9Sstevel@tonic-gate goto closeident; 35797c478bd9Sstevel@tonic-gate 35807c478bd9Sstevel@tonic-gate if (tTd(9, 10)) 35817c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: sent %s", ibuf); 35827c478bd9Sstevel@tonic-gate 35837c478bd9Sstevel@tonic-gate /* send query */ 35847c478bd9Sstevel@tonic-gate if (write(s, ibuf, strlen(ibuf)) < 0) 35857c478bd9Sstevel@tonic-gate goto closeident; 35867c478bd9Sstevel@tonic-gate 35877c478bd9Sstevel@tonic-gate /* get result */ 35887c478bd9Sstevel@tonic-gate p = &ibuf[0]; 3589*058561cbSjbeck nleft = sizeof(ibuf) - 1; 35907c478bd9Sstevel@tonic-gate while ((i = read(s, p, nleft)) > 0) 35917c478bd9Sstevel@tonic-gate { 35927c478bd9Sstevel@tonic-gate char *s; 35937c478bd9Sstevel@tonic-gate 35947c478bd9Sstevel@tonic-gate p += i; 35957c478bd9Sstevel@tonic-gate nleft -= i; 35967c478bd9Sstevel@tonic-gate *p = '\0'; 35977c478bd9Sstevel@tonic-gate if ((s = strchr(ibuf, '\n')) != NULL) 35987c478bd9Sstevel@tonic-gate { 35997c478bd9Sstevel@tonic-gate if (p > s + 1) 36007c478bd9Sstevel@tonic-gate { 36017c478bd9Sstevel@tonic-gate p = s + 1; 36027c478bd9Sstevel@tonic-gate *p = '\0'; 36037c478bd9Sstevel@tonic-gate } 36047c478bd9Sstevel@tonic-gate break; 36057c478bd9Sstevel@tonic-gate } 36067c478bd9Sstevel@tonic-gate if (nleft <= 0) 36077c478bd9Sstevel@tonic-gate break; 36087c478bd9Sstevel@tonic-gate } 36097c478bd9Sstevel@tonic-gate (void) close(s); 36107c478bd9Sstevel@tonic-gate sm_clrevent(ev); 36117c478bd9Sstevel@tonic-gate if (i < 0 || p == &ibuf[0]) 36127c478bd9Sstevel@tonic-gate goto noident; 36137c478bd9Sstevel@tonic-gate 36147c478bd9Sstevel@tonic-gate if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r') 36157c478bd9Sstevel@tonic-gate p--; 36167c478bd9Sstevel@tonic-gate *++p = '\0'; 36177c478bd9Sstevel@tonic-gate 36187c478bd9Sstevel@tonic-gate if (tTd(9, 3)) 36197c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: got %s\n", ibuf); 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate /* parse result */ 36227c478bd9Sstevel@tonic-gate p = strchr(ibuf, ':'); 36237c478bd9Sstevel@tonic-gate if (p == NULL) 36247c478bd9Sstevel@tonic-gate { 36257c478bd9Sstevel@tonic-gate /* malformed response */ 36267c478bd9Sstevel@tonic-gate goto noident; 36277c478bd9Sstevel@tonic-gate } 36287c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 36297c478bd9Sstevel@tonic-gate continue; 36307c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "userid", 6) != 0) 36317c478bd9Sstevel@tonic-gate { 36327c478bd9Sstevel@tonic-gate /* presumably an error string */ 36337c478bd9Sstevel@tonic-gate goto noident; 36347c478bd9Sstevel@tonic-gate } 36357c478bd9Sstevel@tonic-gate p += 6; 36367c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 36377c478bd9Sstevel@tonic-gate p++; 36387c478bd9Sstevel@tonic-gate if (*p++ != ':') 36397c478bd9Sstevel@tonic-gate { 36407c478bd9Sstevel@tonic-gate /* either useridxx or malformed response */ 36417c478bd9Sstevel@tonic-gate goto noident; 36427c478bd9Sstevel@tonic-gate } 36437c478bd9Sstevel@tonic-gate 36447c478bd9Sstevel@tonic-gate /* p now points to the OSTYPE field */ 36457c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 36467c478bd9Sstevel@tonic-gate p++; 36477c478bd9Sstevel@tonic-gate ostype = p; 36487c478bd9Sstevel@tonic-gate p = strchr(p, ':'); 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 else 36557c478bd9Sstevel@tonic-gate { 36567c478bd9Sstevel@tonic-gate char *charset; 36577c478bd9Sstevel@tonic-gate 36587c478bd9Sstevel@tonic-gate *p = '\0'; 36597c478bd9Sstevel@tonic-gate charset = strchr(ostype, ','); 36607c478bd9Sstevel@tonic-gate if (charset != NULL) 36617c478bd9Sstevel@tonic-gate *charset = '\0'; 36627c478bd9Sstevel@tonic-gate } 36637c478bd9Sstevel@tonic-gate 36647c478bd9Sstevel@tonic-gate /* 1413 says don't do this -- but it's broken otherwise */ 36657c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 36667c478bd9Sstevel@tonic-gate continue; 36677c478bd9Sstevel@tonic-gate 36687c478bd9Sstevel@tonic-gate /* p now points to the authenticated name -- copy carefully */ 36697c478bd9Sstevel@tonic-gate if (sm_strncasecmp(ostype, "other", 5) == 0 && 36707c478bd9Sstevel@tonic-gate (ostype[5] == ' ' || ostype[5] == '\0')) 36717c478bd9Sstevel@tonic-gate { 3672*058561cbSjbeck (void) sm_strlcpy(hbuf, "IDENT:", sizeof(hbuf)); 36737c478bd9Sstevel@tonic-gate cleanstrcpy(&hbuf[6], p, MAXAUTHINFO); 36747c478bd9Sstevel@tonic-gate } 36757c478bd9Sstevel@tonic-gate else 36767c478bd9Sstevel@tonic-gate cleanstrcpy(hbuf, p, MAXAUTHINFO); 36777c478bd9Sstevel@tonic-gate len = strlen(hbuf); 3678*058561cbSjbeck (void) sm_strlcpyn(&hbuf[len], sizeof(hbuf) - len, 2, "@", 36797c478bd9Sstevel@tonic-gate RealHostName == NULL ? "localhost" : RealHostName); 36807c478bd9Sstevel@tonic-gate goto postident; 36817c478bd9Sstevel@tonic-gate 36827c478bd9Sstevel@tonic-gate closeident: 36837c478bd9Sstevel@tonic-gate (void) close(s); 36847c478bd9Sstevel@tonic-gate sm_clrevent(ev); 36857c478bd9Sstevel@tonic-gate 36867c478bd9Sstevel@tonic-gate noident: 36877c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 36887c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 36897c478bd9Sstevel@tonic-gate { 36907c478bd9Sstevel@tonic-gate #if NETINET 36917c478bd9Sstevel@tonic-gate case AF_INET: 36927c478bd9Sstevel@tonic-gate if (port > 0) 36937c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 36947c478bd9Sstevel@tonic-gate break; 36957c478bd9Sstevel@tonic-gate #endif /* NETINET */ 36967c478bd9Sstevel@tonic-gate 36977c478bd9Sstevel@tonic-gate #if NETINET6 36987c478bd9Sstevel@tonic-gate case AF_INET6: 36997c478bd9Sstevel@tonic-gate if (port > 0) 37007c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 37017c478bd9Sstevel@tonic-gate break; 37027c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 37037c478bd9Sstevel@tonic-gate } 37047c478bd9Sstevel@tonic-gate 37057c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 37067c478bd9Sstevel@tonic-gate { 37077c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 37087c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: NULL\n"); 37097c478bd9Sstevel@tonic-gate return NULL; 37107c478bd9Sstevel@tonic-gate } 3711*058561cbSjbeck (void) sm_strlcpy(hbuf, RealHostName, sizeof(hbuf)); 37127c478bd9Sstevel@tonic-gate 37137c478bd9Sstevel@tonic-gate postident: 37147c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 37157c478bd9Sstevel@tonic-gate # ifndef GET_IPOPT_DST 37167c478bd9Sstevel@tonic-gate # define GET_IPOPT_DST(dst) (dst) 37177c478bd9Sstevel@tonic-gate # endif /* ! GET_IPOPT_DST */ 37187c478bd9Sstevel@tonic-gate /* 37197c478bd9Sstevel@tonic-gate ** Extract IP source routing information. 37207c478bd9Sstevel@tonic-gate ** 37217c478bd9Sstevel@tonic-gate ** Format of output for a connection from site a through b 37227c478bd9Sstevel@tonic-gate ** through c to d: 37237c478bd9Sstevel@tonic-gate ** loose: @site-c@site-b:site-a 37247c478bd9Sstevel@tonic-gate ** strict: !@site-c@site-b:site-a 37257c478bd9Sstevel@tonic-gate ** 37267c478bd9Sstevel@tonic-gate ** o - pointer within ipopt_list structure. 37277c478bd9Sstevel@tonic-gate ** q - pointer within ls/ss rr route data 37287c478bd9Sstevel@tonic-gate ** p - pointer to hbuf 37297c478bd9Sstevel@tonic-gate */ 37307c478bd9Sstevel@tonic-gate 37317c478bd9Sstevel@tonic-gate if (RealHostAddr.sa.sa_family == AF_INET) 37327c478bd9Sstevel@tonic-gate { 37337c478bd9Sstevel@tonic-gate SOCKOPT_LEN_T ipoptlen; 37347c478bd9Sstevel@tonic-gate int j; 37357c478bd9Sstevel@tonic-gate unsigned char *q; 37367c478bd9Sstevel@tonic-gate unsigned char *o; 37377c478bd9Sstevel@tonic-gate int l; 37387c478bd9Sstevel@tonic-gate struct IPOPTION ipopt; 37397c478bd9Sstevel@tonic-gate 3740*058561cbSjbeck ipoptlen = sizeof(ipopt); 37417c478bd9Sstevel@tonic-gate if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 37427c478bd9Sstevel@tonic-gate (char *) &ipopt, &ipoptlen) < 0) 37437c478bd9Sstevel@tonic-gate goto noipsr; 37447c478bd9Sstevel@tonic-gate if (ipoptlen == 0) 37457c478bd9Sstevel@tonic-gate goto noipsr; 37467c478bd9Sstevel@tonic-gate o = (unsigned char *) ipopt.IP_LIST; 37477c478bd9Sstevel@tonic-gate while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen) 37487c478bd9Sstevel@tonic-gate { 37497c478bd9Sstevel@tonic-gate switch (*o) 37507c478bd9Sstevel@tonic-gate { 37517c478bd9Sstevel@tonic-gate case IPOPT_EOL: 37527c478bd9Sstevel@tonic-gate o = NULL; 37537c478bd9Sstevel@tonic-gate break; 37547c478bd9Sstevel@tonic-gate 37557c478bd9Sstevel@tonic-gate case IPOPT_NOP: 37567c478bd9Sstevel@tonic-gate o++; 37577c478bd9Sstevel@tonic-gate break; 37587c478bd9Sstevel@tonic-gate 37597c478bd9Sstevel@tonic-gate case IPOPT_SSRR: 37607c478bd9Sstevel@tonic-gate case IPOPT_LSRR: 37617c478bd9Sstevel@tonic-gate /* 37627c478bd9Sstevel@tonic-gate ** Source routing. 37637c478bd9Sstevel@tonic-gate ** o[0] is the option type (loose/strict). 37647c478bd9Sstevel@tonic-gate ** o[1] is the length of this option, 37657c478bd9Sstevel@tonic-gate ** including option type and 37667c478bd9Sstevel@tonic-gate ** length. 37677c478bd9Sstevel@tonic-gate ** o[2] is the pointer into the route 37687c478bd9Sstevel@tonic-gate ** data. 37697c478bd9Sstevel@tonic-gate ** o[3] begins the route data. 37707c478bd9Sstevel@tonic-gate */ 37717c478bd9Sstevel@tonic-gate 37727c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 3773*058561cbSjbeck l = sizeof(hbuf) - (hbuf - p) - 6; 37747c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), 37757c478bd9Sstevel@tonic-gate " [%s@%.*s", 37767c478bd9Sstevel@tonic-gate *o == IPOPT_SSRR ? "!" : "", 37777c478bd9Sstevel@tonic-gate l > 240 ? 120 : l / 2, 37787c478bd9Sstevel@tonic-gate inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 37797c478bd9Sstevel@tonic-gate i = strlen(p); 37807c478bd9Sstevel@tonic-gate p += i; 37817c478bd9Sstevel@tonic-gate l -= strlen(p); 37827c478bd9Sstevel@tonic-gate 37837c478bd9Sstevel@tonic-gate j = o[1] / sizeof(struct in_addr) - 1; 37847c478bd9Sstevel@tonic-gate 37857c478bd9Sstevel@tonic-gate /* q skips length and router pointer to data */ 37867c478bd9Sstevel@tonic-gate q = &o[3]; 37877c478bd9Sstevel@tonic-gate for ( ; j >= 0; j--) 37887c478bd9Sstevel@tonic-gate { 37897c478bd9Sstevel@tonic-gate struct in_addr addr; 37907c478bd9Sstevel@tonic-gate 37917c478bd9Sstevel@tonic-gate memcpy(&addr, q, sizeof(addr)); 37927c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, 37937c478bd9Sstevel@tonic-gate SPACELEFT(hbuf, p), 37947c478bd9Sstevel@tonic-gate "%c%.*s", 37957c478bd9Sstevel@tonic-gate j != 0 ? '@' : ':', 37967c478bd9Sstevel@tonic-gate l > 240 ? 120 : 37977c478bd9Sstevel@tonic-gate j == 0 ? l : l / 2, 37987c478bd9Sstevel@tonic-gate inet_ntoa(addr)); 37997c478bd9Sstevel@tonic-gate i = strlen(p); 38007c478bd9Sstevel@tonic-gate p += i; 38017c478bd9Sstevel@tonic-gate l -= i + 1; 38027c478bd9Sstevel@tonic-gate q += sizeof(struct in_addr); 38037c478bd9Sstevel@tonic-gate } 38047c478bd9Sstevel@tonic-gate o += o[1]; 38057c478bd9Sstevel@tonic-gate break; 38067c478bd9Sstevel@tonic-gate 38077c478bd9Sstevel@tonic-gate default: 38087c478bd9Sstevel@tonic-gate /* Skip over option */ 38097c478bd9Sstevel@tonic-gate o += o[1]; 38107c478bd9Sstevel@tonic-gate break; 38117c478bd9Sstevel@tonic-gate } 38127c478bd9Sstevel@tonic-gate } 38137c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), "]"); 38147c478bd9Sstevel@tonic-gate goto postipsr; 38157c478bd9Sstevel@tonic-gate } 38167c478bd9Sstevel@tonic-gate 38177c478bd9Sstevel@tonic-gate noipsr: 38187c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 38197c478bd9Sstevel@tonic-gate if (RealHostName != NULL && RealHostName[0] != '[') 38207c478bd9Sstevel@tonic-gate { 38217c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 38227c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 38237c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 38247c478bd9Sstevel@tonic-gate } 38257c478bd9Sstevel@tonic-gate if (*may_be_forged) 38267c478bd9Sstevel@tonic-gate { 38277c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 38287c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p)); 38297c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 38307c478bd9Sstevel@tonic-gate macid("{client_resolve}"), "FORGED"); 38317c478bd9Sstevel@tonic-gate } 38327c478bd9Sstevel@tonic-gate 38337c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 38347c478bd9Sstevel@tonic-gate postipsr: 38357c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 38367c478bd9Sstevel@tonic-gate 38377c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 38387c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 38397c478bd9Sstevel@tonic-gate { 38407c478bd9Sstevel@tonic-gate #if NETINET 38417c478bd9Sstevel@tonic-gate case AF_INET: 38427c478bd9Sstevel@tonic-gate if (port > 0) 38437c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 38447c478bd9Sstevel@tonic-gate break; 38457c478bd9Sstevel@tonic-gate #endif /* NETINET */ 38467c478bd9Sstevel@tonic-gate 38477c478bd9Sstevel@tonic-gate #if NETINET6 38487c478bd9Sstevel@tonic-gate case AF_INET6: 38497c478bd9Sstevel@tonic-gate if (port > 0) 38507c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 38517c478bd9Sstevel@tonic-gate break; 38527c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 38537c478bd9Sstevel@tonic-gate } 38547c478bd9Sstevel@tonic-gate 38557c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 38567c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 38577c478bd9Sstevel@tonic-gate return hbuf; 38587c478bd9Sstevel@tonic-gate } 38597c478bd9Sstevel@tonic-gate /* 38607c478bd9Sstevel@tonic-gate ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 38617c478bd9Sstevel@tonic-gate ** 38627c478bd9Sstevel@tonic-gate ** Parameters: 38637c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 38647c478bd9Sstevel@tonic-gate ** name -- the (presumably unqualified) hostname. 38657c478bd9Sstevel@tonic-gate ** av -- unused -- for compatibility with other mapping 38667c478bd9Sstevel@tonic-gate ** functions. 38677c478bd9Sstevel@tonic-gate ** statp -- an exit status (out parameter) -- set to 38687c478bd9Sstevel@tonic-gate ** EX_TEMPFAIL if the name server is unavailable. 38697c478bd9Sstevel@tonic-gate ** 38707c478bd9Sstevel@tonic-gate ** Returns: 38717c478bd9Sstevel@tonic-gate ** The mapping, if found. 38727c478bd9Sstevel@tonic-gate ** NULL if no mapping found. 38737c478bd9Sstevel@tonic-gate ** 38747c478bd9Sstevel@tonic-gate ** Side Effects: 38757c478bd9Sstevel@tonic-gate ** Looks up the host specified in hbuf. If it is not 38767c478bd9Sstevel@tonic-gate ** the canonical name for that host, return the canonical 38777c478bd9Sstevel@tonic-gate ** name (unless MF_MATCHONLY is set, which will cause the 38787c478bd9Sstevel@tonic-gate ** status only to be returned). 38797c478bd9Sstevel@tonic-gate */ 38807c478bd9Sstevel@tonic-gate 38817c478bd9Sstevel@tonic-gate char * 38827c478bd9Sstevel@tonic-gate host_map_lookup(map, name, av, statp) 38837c478bd9Sstevel@tonic-gate MAP *map; 38847c478bd9Sstevel@tonic-gate char *name; 38857c478bd9Sstevel@tonic-gate char **av; 38867c478bd9Sstevel@tonic-gate int *statp; 38877c478bd9Sstevel@tonic-gate { 38887c478bd9Sstevel@tonic-gate register struct hostent *hp; 38897c478bd9Sstevel@tonic-gate #if NETINET 38907c478bd9Sstevel@tonic-gate struct in_addr in_addr; 38917c478bd9Sstevel@tonic-gate #endif /* NETINET */ 38927c478bd9Sstevel@tonic-gate #if NETINET6 38937c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 38947c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 38957c478bd9Sstevel@tonic-gate char *cp, *ans = NULL; 38967c478bd9Sstevel@tonic-gate register STAB *s; 38977c478bd9Sstevel@tonic-gate time_t now; 38987c478bd9Sstevel@tonic-gate #if NAMED_BIND 38997c478bd9Sstevel@tonic-gate time_t SM_NONVOLATILE retrans = 0; 39007c478bd9Sstevel@tonic-gate int SM_NONVOLATILE retry = 0; 39017c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 39027c478bd9Sstevel@tonic-gate char hbuf[MAXNAME + 1]; 39037c478bd9Sstevel@tonic-gate 39047c478bd9Sstevel@tonic-gate /* 39057c478bd9Sstevel@tonic-gate ** See if we have already looked up this name. If so, just 39067c478bd9Sstevel@tonic-gate ** return it (unless expired). 39077c478bd9Sstevel@tonic-gate */ 39087c478bd9Sstevel@tonic-gate 39097c478bd9Sstevel@tonic-gate now = curtime(); 39107c478bd9Sstevel@tonic-gate s = stab(name, ST_NAMECANON, ST_ENTER); 39117c478bd9Sstevel@tonic-gate if (bitset(NCF_VALID, s->s_namecanon.nc_flags) && 39127c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp >= now) 39137c478bd9Sstevel@tonic-gate { 39147c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39157c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => CACHE %s\n", 39167c478bd9Sstevel@tonic-gate name, 39177c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname == NULL 39187c478bd9Sstevel@tonic-gate ? "NULL" 39197c478bd9Sstevel@tonic-gate : s->s_namecanon.nc_cname); 39207c478bd9Sstevel@tonic-gate errno = s->s_namecanon.nc_errno; 39217c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 39227c478bd9Sstevel@tonic-gate *statp = s->s_namecanon.nc_stat; 39237c478bd9Sstevel@tonic-gate if (*statp == EX_TEMPFAIL) 39247c478bd9Sstevel@tonic-gate { 39257c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 39267c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 39277c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 39287c478bd9Sstevel@tonic-gate } 39297c478bd9Sstevel@tonic-gate if (*statp != EX_OK) 39307c478bd9Sstevel@tonic-gate return NULL; 39317c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname == NULL) 39327c478bd9Sstevel@tonic-gate { 39337c478bd9Sstevel@tonic-gate syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d", 39347c478bd9Sstevel@tonic-gate name, 39357c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno, 39367c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno); 39377c478bd9Sstevel@tonic-gate return NULL; 39387c478bd9Sstevel@tonic-gate } 39397c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 39407c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 39417c478bd9Sstevel@tonic-gate else 39427c478bd9Sstevel@tonic-gate cp = map_rewrite(map, 39437c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname, 39447c478bd9Sstevel@tonic-gate strlen(s->s_namecanon.nc_cname), 39457c478bd9Sstevel@tonic-gate av); 39467c478bd9Sstevel@tonic-gate return cp; 39477c478bd9Sstevel@tonic-gate } 39487c478bd9Sstevel@tonic-gate 39497c478bd9Sstevel@tonic-gate /* 39507c478bd9Sstevel@tonic-gate ** If we are running without a regular network connection (usually 39517c478bd9Sstevel@tonic-gate ** dial-on-demand) and we are just queueing, we want to avoid DNS 39527c478bd9Sstevel@tonic-gate ** lookups because those could try to connect to a server. 39537c478bd9Sstevel@tonic-gate */ 39547c478bd9Sstevel@tonic-gate 39557c478bd9Sstevel@tonic-gate if (CurEnv->e_sendmode == SM_DEFER && 39567c478bd9Sstevel@tonic-gate bitset(MF_DEFER, map->map_mflags)) 39577c478bd9Sstevel@tonic-gate { 39587c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39597c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name); 39607c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 39617c478bd9Sstevel@tonic-gate return NULL; 39627c478bd9Sstevel@tonic-gate } 39637c478bd9Sstevel@tonic-gate 39647c478bd9Sstevel@tonic-gate /* 39657c478bd9Sstevel@tonic-gate ** If first character is a bracket, then it is an address 39667c478bd9Sstevel@tonic-gate ** lookup. Address is copied into a temporary buffer to 39677c478bd9Sstevel@tonic-gate ** strip the brackets and to preserve name if address is 39687c478bd9Sstevel@tonic-gate ** unknown. 39697c478bd9Sstevel@tonic-gate */ 39707c478bd9Sstevel@tonic-gate 39717c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 39727c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => ", name); 39737c478bd9Sstevel@tonic-gate #if NAMED_BIND 39747c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 39757c478bd9Sstevel@tonic-gate { 39767c478bd9Sstevel@tonic-gate retrans = _res.retrans; 39777c478bd9Sstevel@tonic-gate _res.retrans = map->map_timeout; 39787c478bd9Sstevel@tonic-gate } 39797c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 39807c478bd9Sstevel@tonic-gate { 39817c478bd9Sstevel@tonic-gate retry = _res.retry; 39827c478bd9Sstevel@tonic-gate _res.retry = map->map_retry; 39837c478bd9Sstevel@tonic-gate } 39847c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 39857c478bd9Sstevel@tonic-gate 39867c478bd9Sstevel@tonic-gate /* set default TTL */ 39877c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL; 39887c478bd9Sstevel@tonic-gate if (*name != '[') 39897c478bd9Sstevel@tonic-gate { 39907c478bd9Sstevel@tonic-gate int ttl; 39917c478bd9Sstevel@tonic-gate 3992*058561cbSjbeck (void) sm_strlcpy(hbuf, name, sizeof(hbuf)); 3993*058561cbSjbeck if (getcanonname(hbuf, sizeof(hbuf) - 1, !HasWildcardMX, &ttl)) 39947c478bd9Sstevel@tonic-gate { 39957c478bd9Sstevel@tonic-gate ans = hbuf; 39967c478bd9Sstevel@tonic-gate if (ttl > 0) 39977c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_MIN(ttl, 39987c478bd9Sstevel@tonic-gate SM_DEFAULT_TTL); 39997c478bd9Sstevel@tonic-gate } 40007c478bd9Sstevel@tonic-gate } 40017c478bd9Sstevel@tonic-gate else 40027c478bd9Sstevel@tonic-gate { 40037c478bd9Sstevel@tonic-gate if ((cp = strchr(name, ']')) == NULL) 40047c478bd9Sstevel@tonic-gate { 40057c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40067c478bd9Sstevel@tonic-gate sm_dprintf("FAILED\n"); 40077c478bd9Sstevel@tonic-gate return NULL; 40087c478bd9Sstevel@tonic-gate } 40097c478bd9Sstevel@tonic-gate *cp = '\0'; 40107c478bd9Sstevel@tonic-gate 40117c478bd9Sstevel@tonic-gate hp = NULL; 40127c478bd9Sstevel@tonic-gate #if NETINET 40137c478bd9Sstevel@tonic-gate if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 40147c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in_addr, 40157c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 40167c478bd9Sstevel@tonic-gate #endif /* NETINET */ 40177c478bd9Sstevel@tonic-gate #if NETINET6 40187c478bd9Sstevel@tonic-gate if (hp == NULL && 40197c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &name[1], &in6_addr) == 1) 40207c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in6_addr, 40217c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 40227c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 40237c478bd9Sstevel@tonic-gate *cp = ']'; 40247c478bd9Sstevel@tonic-gate 40257c478bd9Sstevel@tonic-gate if (hp != NULL) 40267c478bd9Sstevel@tonic-gate { 40277c478bd9Sstevel@tonic-gate /* found a match -- copy out */ 40287c478bd9Sstevel@tonic-gate ans = denlstring((char *) hp->h_name, true, true); 40297c478bd9Sstevel@tonic-gate #if NETINET6 40307c478bd9Sstevel@tonic-gate if (ans == hp->h_name) 40317c478bd9Sstevel@tonic-gate { 40327c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 40337c478bd9Sstevel@tonic-gate 40347c478bd9Sstevel@tonic-gate /* hp->h_name is about to disappear */ 4035*058561cbSjbeck (void) sm_strlcpy(n, ans, sizeof(n)); 40367c478bd9Sstevel@tonic-gate ans = n; 40377c478bd9Sstevel@tonic-gate } 40387c478bd9Sstevel@tonic-gate freehostent(hp); 40397c478bd9Sstevel@tonic-gate hp = NULL; 40407c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 40417c478bd9Sstevel@tonic-gate } 40427c478bd9Sstevel@tonic-gate } 40437c478bd9Sstevel@tonic-gate #if NAMED_BIND 40447c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 40457c478bd9Sstevel@tonic-gate _res.retrans = retrans; 40467c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 40477c478bd9Sstevel@tonic-gate _res.retry = retry; 40487c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 40497c478bd9Sstevel@tonic-gate 40507c478bd9Sstevel@tonic-gate s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 40517c478bd9Sstevel@tonic-gate 40527c478bd9Sstevel@tonic-gate /* Found an answer */ 40537c478bd9Sstevel@tonic-gate if (ans != NULL) 40547c478bd9Sstevel@tonic-gate { 40557c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp = EX_OK; 40567c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname != NULL) 40577c478bd9Sstevel@tonic-gate sm_free(s->s_namecanon.nc_cname); 40587c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname = sm_strdup_x(ans); 40597c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 40607c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 40617c478bd9Sstevel@tonic-gate else 40627c478bd9Sstevel@tonic-gate cp = map_rewrite(map, ans, strlen(ans), av); 40637c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40647c478bd9Sstevel@tonic-gate sm_dprintf("FOUND %s\n", ans); 40657c478bd9Sstevel@tonic-gate return cp; 40667c478bd9Sstevel@tonic-gate } 40677c478bd9Sstevel@tonic-gate 40687c478bd9Sstevel@tonic-gate 40697c478bd9Sstevel@tonic-gate /* No match found */ 40707c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno = errno; 40717c478bd9Sstevel@tonic-gate #if NAMED_BIND 40727c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno = h_errno; 40737c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 40747c478bd9Sstevel@tonic-gate sm_dprintf("FAIL (%d)\n", h_errno); 40757c478bd9Sstevel@tonic-gate switch (h_errno) 40767c478bd9Sstevel@tonic-gate { 40777c478bd9Sstevel@tonic-gate case TRY_AGAIN: 40787c478bd9Sstevel@tonic-gate if (UseNameServer) 40797c478bd9Sstevel@tonic-gate { 40807c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 40817c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 40827c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 40837c478bd9Sstevel@tonic-gate } 40847c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 40857c478bd9Sstevel@tonic-gate break; 40867c478bd9Sstevel@tonic-gate 40877c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND: 40887c478bd9Sstevel@tonic-gate case NO_DATA: 40897c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 40907c478bd9Sstevel@tonic-gate break; 40917c478bd9Sstevel@tonic-gate 40927c478bd9Sstevel@tonic-gate case NO_RECOVERY: 40937c478bd9Sstevel@tonic-gate *statp = EX_SOFTWARE; 40947c478bd9Sstevel@tonic-gate break; 40957c478bd9Sstevel@tonic-gate 40967c478bd9Sstevel@tonic-gate default: 40977c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 40987c478bd9Sstevel@tonic-gate break; 40997c478bd9Sstevel@tonic-gate } 41007c478bd9Sstevel@tonic-gate #else /* NAMED_BIND */ 41017c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 41027c478bd9Sstevel@tonic-gate sm_dprintf("FAIL\n"); 41037c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 41047c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 41057c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp; 41067c478bd9Sstevel@tonic-gate return NULL; 41077c478bd9Sstevel@tonic-gate } 41087c478bd9Sstevel@tonic-gate /* 41097c478bd9Sstevel@tonic-gate ** HOST_MAP_INIT -- initialize host class structures 41107c478bd9Sstevel@tonic-gate ** 41117c478bd9Sstevel@tonic-gate ** Parameters: 41127c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 41137c478bd9Sstevel@tonic-gate ** args -- argument string. 41147c478bd9Sstevel@tonic-gate ** 41157c478bd9Sstevel@tonic-gate ** Returns: 41167c478bd9Sstevel@tonic-gate ** true. 41177c478bd9Sstevel@tonic-gate */ 41187c478bd9Sstevel@tonic-gate 41197c478bd9Sstevel@tonic-gate bool 41207c478bd9Sstevel@tonic-gate host_map_init(map, args) 41217c478bd9Sstevel@tonic-gate MAP *map; 41227c478bd9Sstevel@tonic-gate char *args; 41237c478bd9Sstevel@tonic-gate { 41247c478bd9Sstevel@tonic-gate register char *p = args; 41257c478bd9Sstevel@tonic-gate 41267c478bd9Sstevel@tonic-gate for (;;) 41277c478bd9Sstevel@tonic-gate { 41287c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 41297c478bd9Sstevel@tonic-gate p++; 41307c478bd9Sstevel@tonic-gate if (*p != '-') 41317c478bd9Sstevel@tonic-gate break; 41327c478bd9Sstevel@tonic-gate switch (*++p) 41337c478bd9Sstevel@tonic-gate { 41347c478bd9Sstevel@tonic-gate case 'a': 41357c478bd9Sstevel@tonic-gate map->map_app = ++p; 41367c478bd9Sstevel@tonic-gate break; 41377c478bd9Sstevel@tonic-gate 41387c478bd9Sstevel@tonic-gate case 'T': 41397c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 41407c478bd9Sstevel@tonic-gate break; 41417c478bd9Sstevel@tonic-gate 41427c478bd9Sstevel@tonic-gate case 'm': 41437c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 41447c478bd9Sstevel@tonic-gate break; 41457c478bd9Sstevel@tonic-gate 41467c478bd9Sstevel@tonic-gate case 't': 41477c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 41487c478bd9Sstevel@tonic-gate break; 41497c478bd9Sstevel@tonic-gate 41507c478bd9Sstevel@tonic-gate case 'S': /* only for consistency */ 41517c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 41527c478bd9Sstevel@tonic-gate break; 41537c478bd9Sstevel@tonic-gate 41547c478bd9Sstevel@tonic-gate case 'D': 41557c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 41567c478bd9Sstevel@tonic-gate break; 41577c478bd9Sstevel@tonic-gate 41587c478bd9Sstevel@tonic-gate case 'd': 41597c478bd9Sstevel@tonic-gate { 41607c478bd9Sstevel@tonic-gate char *h; 41617c478bd9Sstevel@tonic-gate 41627c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41637c478bd9Sstevel@tonic-gate continue; 41647c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 41657c478bd9Sstevel@tonic-gate if (h != NULL) 41667c478bd9Sstevel@tonic-gate *h = '\0'; 41677c478bd9Sstevel@tonic-gate map->map_timeout = convtime(p, 's'); 41687c478bd9Sstevel@tonic-gate if (h != NULL) 41697c478bd9Sstevel@tonic-gate *h = ' '; 41707c478bd9Sstevel@tonic-gate } 41717c478bd9Sstevel@tonic-gate break; 41727c478bd9Sstevel@tonic-gate 41737c478bd9Sstevel@tonic-gate case 'r': 41747c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 41757c478bd9Sstevel@tonic-gate continue; 41767c478bd9Sstevel@tonic-gate map->map_retry = atoi(p); 41777c478bd9Sstevel@tonic-gate break; 41787c478bd9Sstevel@tonic-gate } 41797c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 41807c478bd9Sstevel@tonic-gate p++; 41817c478bd9Sstevel@tonic-gate if (*p != '\0') 41827c478bd9Sstevel@tonic-gate *p++ = '\0'; 41837c478bd9Sstevel@tonic-gate } 41847c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 41857c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 41867c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 41877c478bd9Sstevel@tonic-gate map->map_tapp = newstr(map->map_tapp); 41887c478bd9Sstevel@tonic-gate return true; 41897c478bd9Sstevel@tonic-gate } 41907c478bd9Sstevel@tonic-gate 41917c478bd9Sstevel@tonic-gate #if NETINET6 41927c478bd9Sstevel@tonic-gate /* 41937c478bd9Sstevel@tonic-gate ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 41947c478bd9Sstevel@tonic-gate ** 41957c478bd9Sstevel@tonic-gate ** Parameters: 41967c478bd9Sstevel@tonic-gate ** s6a -- a pointer to an in6_addr structure. 41977c478bd9Sstevel@tonic-gate ** dst -- buffer to store result in 41987c478bd9Sstevel@tonic-gate ** dst_len -- size of dst buffer 41997c478bd9Sstevel@tonic-gate ** 42007c478bd9Sstevel@tonic-gate ** Returns: 42017c478bd9Sstevel@tonic-gate ** A printable version of that structure. 42027c478bd9Sstevel@tonic-gate */ 42037c478bd9Sstevel@tonic-gate 42047c478bd9Sstevel@tonic-gate char * 42057c478bd9Sstevel@tonic-gate anynet_ntop(s6a, dst, dst_len) 42067c478bd9Sstevel@tonic-gate struct in6_addr *s6a; 42077c478bd9Sstevel@tonic-gate char *dst; 42087c478bd9Sstevel@tonic-gate size_t dst_len; 42097c478bd9Sstevel@tonic-gate { 42107c478bd9Sstevel@tonic-gate register char *ap; 42117c478bd9Sstevel@tonic-gate 42127c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(s6a)) 42137c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET, 42147c478bd9Sstevel@tonic-gate &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 42157c478bd9Sstevel@tonic-gate dst, dst_len); 42167c478bd9Sstevel@tonic-gate else 42177c478bd9Sstevel@tonic-gate { 42187c478bd9Sstevel@tonic-gate char *d; 42197c478bd9Sstevel@tonic-gate size_t sz; 42207c478bd9Sstevel@tonic-gate 42217c478bd9Sstevel@tonic-gate /* Save pointer to beginning of string */ 42227c478bd9Sstevel@tonic-gate d = dst; 42237c478bd9Sstevel@tonic-gate 42247c478bd9Sstevel@tonic-gate /* Add IPv6: protocol tag */ 42257c478bd9Sstevel@tonic-gate sz = sm_strlcpy(dst, "IPv6:", dst_len); 42267c478bd9Sstevel@tonic-gate if (sz >= dst_len) 42277c478bd9Sstevel@tonic-gate return NULL; 42287c478bd9Sstevel@tonic-gate dst += sz; 42297c478bd9Sstevel@tonic-gate dst_len -= sz; 42307c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 42317c478bd9Sstevel@tonic-gate 42327c478bd9Sstevel@tonic-gate /* Restore pointer to beginning of string */ 42337c478bd9Sstevel@tonic-gate if (ap != NULL) 42347c478bd9Sstevel@tonic-gate ap = d; 42357c478bd9Sstevel@tonic-gate } 42367c478bd9Sstevel@tonic-gate return ap; 42377c478bd9Sstevel@tonic-gate } 42387c478bd9Sstevel@tonic-gate 42397c478bd9Sstevel@tonic-gate /* 42407c478bd9Sstevel@tonic-gate ** ANYNET_PTON -- convert printed form to network address. 42417c478bd9Sstevel@tonic-gate ** 42427c478bd9Sstevel@tonic-gate ** Wrapper for inet_pton() which handles IPv6: labels. 42437c478bd9Sstevel@tonic-gate ** 42447c478bd9Sstevel@tonic-gate ** Parameters: 42457c478bd9Sstevel@tonic-gate ** family -- address family 42467c478bd9Sstevel@tonic-gate ** src -- string 42477c478bd9Sstevel@tonic-gate ** dst -- destination address structure 42487c478bd9Sstevel@tonic-gate ** 42497c478bd9Sstevel@tonic-gate ** Returns: 42507c478bd9Sstevel@tonic-gate ** 1 if the address was valid 42517c478bd9Sstevel@tonic-gate ** 0 if the address wasn't parseable 42527c478bd9Sstevel@tonic-gate ** -1 if error 42537c478bd9Sstevel@tonic-gate */ 42547c478bd9Sstevel@tonic-gate 42557c478bd9Sstevel@tonic-gate int 42567c478bd9Sstevel@tonic-gate anynet_pton(family, src, dst) 42577c478bd9Sstevel@tonic-gate int family; 42587c478bd9Sstevel@tonic-gate const char *src; 42597c478bd9Sstevel@tonic-gate void *dst; 42607c478bd9Sstevel@tonic-gate { 42617c478bd9Sstevel@tonic-gate if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0) 42627c478bd9Sstevel@tonic-gate src += 5; 42637c478bd9Sstevel@tonic-gate return inet_pton(family, src, dst); 42647c478bd9Sstevel@tonic-gate } 42657c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 42667c478bd9Sstevel@tonic-gate /* 42677c478bd9Sstevel@tonic-gate ** ANYNET_NTOA -- convert a network address to printable form. 42687c478bd9Sstevel@tonic-gate ** 42697c478bd9Sstevel@tonic-gate ** Parameters: 42707c478bd9Sstevel@tonic-gate ** sap -- a pointer to a sockaddr structure. 42717c478bd9Sstevel@tonic-gate ** 42727c478bd9Sstevel@tonic-gate ** Returns: 42737c478bd9Sstevel@tonic-gate ** A printable version of that sockaddr. 42747c478bd9Sstevel@tonic-gate */ 42757c478bd9Sstevel@tonic-gate 42767c478bd9Sstevel@tonic-gate #ifdef USE_SOCK_STREAM 42777c478bd9Sstevel@tonic-gate 42787c478bd9Sstevel@tonic-gate # if NETLINK 42797c478bd9Sstevel@tonic-gate # include <net/if_dl.h> 42807c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 42817c478bd9Sstevel@tonic-gate 42827c478bd9Sstevel@tonic-gate char * 42837c478bd9Sstevel@tonic-gate anynet_ntoa(sap) 42847c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 42857c478bd9Sstevel@tonic-gate { 42867c478bd9Sstevel@tonic-gate register char *bp; 42877c478bd9Sstevel@tonic-gate register char *ap; 42887c478bd9Sstevel@tonic-gate int l; 42897c478bd9Sstevel@tonic-gate static char buf[100]; 42907c478bd9Sstevel@tonic-gate 42917c478bd9Sstevel@tonic-gate /* check for null/zero family */ 42927c478bd9Sstevel@tonic-gate if (sap == NULL) 42937c478bd9Sstevel@tonic-gate return "NULLADDR"; 42947c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == 0) 42957c478bd9Sstevel@tonic-gate return "0"; 42967c478bd9Sstevel@tonic-gate 42977c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 42987c478bd9Sstevel@tonic-gate { 42997c478bd9Sstevel@tonic-gate # if NETUNIX 43007c478bd9Sstevel@tonic-gate case AF_UNIX: 43017c478bd9Sstevel@tonic-gate if (sap->sunix.sun_path[0] != '\0') 4302*058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[UNIX: %.64s]", 43037c478bd9Sstevel@tonic-gate sap->sunix.sun_path); 43047c478bd9Sstevel@tonic-gate else 4305*058561cbSjbeck (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof(buf)); 43067c478bd9Sstevel@tonic-gate return buf; 43077c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 43087c478bd9Sstevel@tonic-gate 43097c478bd9Sstevel@tonic-gate # if NETINET 43107c478bd9Sstevel@tonic-gate case AF_INET: 43117c478bd9Sstevel@tonic-gate return (char *) inet_ntoa(sap->sin.sin_addr); 43127c478bd9Sstevel@tonic-gate # endif /* NETINET */ 43137c478bd9Sstevel@tonic-gate 43147c478bd9Sstevel@tonic-gate # if NETINET6 43157c478bd9Sstevel@tonic-gate case AF_INET6: 4316*058561cbSjbeck ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof(buf)); 43177c478bd9Sstevel@tonic-gate if (ap != NULL) 43187c478bd9Sstevel@tonic-gate return ap; 43197c478bd9Sstevel@tonic-gate break; 43207c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 43217c478bd9Sstevel@tonic-gate 43227c478bd9Sstevel@tonic-gate # if NETLINK 43237c478bd9Sstevel@tonic-gate case AF_LINK: 4324*058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[LINK: %s]", 43257c478bd9Sstevel@tonic-gate link_ntoa((struct sockaddr_dl *) &sap->sa)); 43267c478bd9Sstevel@tonic-gate return buf; 43277c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 43287c478bd9Sstevel@tonic-gate default: 43297c478bd9Sstevel@tonic-gate /* this case is needed when nothing is #defined */ 43307c478bd9Sstevel@tonic-gate /* in order to keep the switch syntactically correct */ 43317c478bd9Sstevel@tonic-gate break; 43327c478bd9Sstevel@tonic-gate } 43337c478bd9Sstevel@tonic-gate 43347c478bd9Sstevel@tonic-gate /* unknown family -- just dump bytes */ 4335*058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "Family %d: ", sap->sa.sa_family); 43367c478bd9Sstevel@tonic-gate bp = &buf[strlen(buf)]; 43377c478bd9Sstevel@tonic-gate ap = sap->sa.sa_data; 4338*058561cbSjbeck for (l = sizeof(sap->sa.sa_data); --l >= 0; ) 43397c478bd9Sstevel@tonic-gate { 43407c478bd9Sstevel@tonic-gate (void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:", 43417c478bd9Sstevel@tonic-gate *ap++ & 0377); 43427c478bd9Sstevel@tonic-gate bp += 3; 43437c478bd9Sstevel@tonic-gate } 43447c478bd9Sstevel@tonic-gate *--bp = '\0'; 43457c478bd9Sstevel@tonic-gate return buf; 43467c478bd9Sstevel@tonic-gate } 43477c478bd9Sstevel@tonic-gate /* 43487c478bd9Sstevel@tonic-gate ** HOSTNAMEBYANYADDR -- return name of host based on address 43497c478bd9Sstevel@tonic-gate ** 43507c478bd9Sstevel@tonic-gate ** Parameters: 43517c478bd9Sstevel@tonic-gate ** sap -- SOCKADDR pointer 43527c478bd9Sstevel@tonic-gate ** 43537c478bd9Sstevel@tonic-gate ** Returns: 43547c478bd9Sstevel@tonic-gate ** text representation of host name. 43557c478bd9Sstevel@tonic-gate ** 43567c478bd9Sstevel@tonic-gate ** Side Effects: 43577c478bd9Sstevel@tonic-gate ** none. 43587c478bd9Sstevel@tonic-gate */ 43597c478bd9Sstevel@tonic-gate 43607c478bd9Sstevel@tonic-gate char * 43617c478bd9Sstevel@tonic-gate hostnamebyanyaddr(sap) 43627c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 43637c478bd9Sstevel@tonic-gate { 43647c478bd9Sstevel@tonic-gate register struct hostent *hp; 43657c478bd9Sstevel@tonic-gate # if NAMED_BIND 43667c478bd9Sstevel@tonic-gate int saveretry; 43677c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 43687c478bd9Sstevel@tonic-gate # if NETINET6 43697c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 43707c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 43717c478bd9Sstevel@tonic-gate 43727c478bd9Sstevel@tonic-gate # if NAMED_BIND 43737c478bd9Sstevel@tonic-gate /* shorten name server timeout to avoid higher level timeouts */ 43747c478bd9Sstevel@tonic-gate saveretry = _res.retry; 43757c478bd9Sstevel@tonic-gate if (_res.retry * _res.retrans > 20) 43767c478bd9Sstevel@tonic-gate _res.retry = 20 / _res.retrans; 43777c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 43787c478bd9Sstevel@tonic-gate 43797c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 43807c478bd9Sstevel@tonic-gate { 43817c478bd9Sstevel@tonic-gate # if NETINET 43827c478bd9Sstevel@tonic-gate case AF_INET: 43837c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 43847c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 43857c478bd9Sstevel@tonic-gate break; 43867c478bd9Sstevel@tonic-gate # endif /* NETINET */ 43877c478bd9Sstevel@tonic-gate 43887c478bd9Sstevel@tonic-gate # if NETINET6 43897c478bd9Sstevel@tonic-gate case AF_INET6: 43907c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 43917c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 43927c478bd9Sstevel@tonic-gate break; 43937c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 43947c478bd9Sstevel@tonic-gate 43957c478bd9Sstevel@tonic-gate # if NETISO 43967c478bd9Sstevel@tonic-gate case AF_ISO: 43977c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 4398*058561cbSjbeck sizeof(sap->siso.siso_addr), AF_ISO); 43997c478bd9Sstevel@tonic-gate break; 44007c478bd9Sstevel@tonic-gate # endif /* NETISO */ 44017c478bd9Sstevel@tonic-gate 44027c478bd9Sstevel@tonic-gate # if NETUNIX 44037c478bd9Sstevel@tonic-gate case AF_UNIX: 44047c478bd9Sstevel@tonic-gate hp = NULL; 44057c478bd9Sstevel@tonic-gate break; 44067c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 44077c478bd9Sstevel@tonic-gate 44087c478bd9Sstevel@tonic-gate default: 4409*058561cbSjbeck hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof(sap->sa.sa_data), 44107c478bd9Sstevel@tonic-gate sap->sa.sa_family); 44117c478bd9Sstevel@tonic-gate break; 44127c478bd9Sstevel@tonic-gate } 44137c478bd9Sstevel@tonic-gate 44147c478bd9Sstevel@tonic-gate # if NAMED_BIND 44157c478bd9Sstevel@tonic-gate _res.retry = saveretry; 44167c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 44177c478bd9Sstevel@tonic-gate 44187c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 44197c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_name[0] != '[' 44207c478bd9Sstevel@tonic-gate # if NETINET6 44217c478bd9Sstevel@tonic-gate && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 44227c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44237c478bd9Sstevel@tonic-gate # if NETINET 44247c478bd9Sstevel@tonic-gate && inet_addr(hp->h_name) == INADDR_NONE 44257c478bd9Sstevel@tonic-gate # endif /* NETINET */ 44267c478bd9Sstevel@tonic-gate ) 44277c478bd9Sstevel@tonic-gate { 44287c478bd9Sstevel@tonic-gate char *name; 44297c478bd9Sstevel@tonic-gate 44307c478bd9Sstevel@tonic-gate name = denlstring((char *) hp->h_name, true, true); 44317c478bd9Sstevel@tonic-gate # if NETINET6 44327c478bd9Sstevel@tonic-gate if (name == hp->h_name) 44337c478bd9Sstevel@tonic-gate { 44347c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 44357c478bd9Sstevel@tonic-gate 44367c478bd9Sstevel@tonic-gate /* Copy the string, hp->h_name is about to disappear */ 4437*058561cbSjbeck (void) sm_strlcpy(n, name, sizeof(n)); 44387c478bd9Sstevel@tonic-gate name = n; 44397c478bd9Sstevel@tonic-gate } 44407c478bd9Sstevel@tonic-gate freehostent(hp); 44417c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44427c478bd9Sstevel@tonic-gate return name; 44437c478bd9Sstevel@tonic-gate } 44447c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 44457c478bd9Sstevel@tonic-gate 44467c478bd9Sstevel@tonic-gate # if NETINET6 44477c478bd9Sstevel@tonic-gate if (hp != NULL) 44487c478bd9Sstevel@tonic-gate { 44497c478bd9Sstevel@tonic-gate freehostent(hp); 44507c478bd9Sstevel@tonic-gate hp = NULL; 44517c478bd9Sstevel@tonic-gate } 44527c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 44537c478bd9Sstevel@tonic-gate 44547c478bd9Sstevel@tonic-gate # if NETUNIX 44557c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 44567c478bd9Sstevel@tonic-gate return "localhost"; 44577c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 44587c478bd9Sstevel@tonic-gate { 44597c478bd9Sstevel@tonic-gate static char buf[203]; 44607c478bd9Sstevel@tonic-gate 4461*058561cbSjbeck (void) sm_snprintf(buf, sizeof(buf), "[%.200s]", 44627c478bd9Sstevel@tonic-gate anynet_ntoa(sap)); 44637c478bd9Sstevel@tonic-gate return buf; 44647c478bd9Sstevel@tonic-gate } 44657c478bd9Sstevel@tonic-gate } 44667c478bd9Sstevel@tonic-gate #endif /* USE_SOCK_STREAM */ 4467