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