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