1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers. 3*7c478bd9Sstevel@tonic-gate * All rights reserved. 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5*7c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1993 6*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 7*7c478bd9Sstevel@tonic-gate * 8*7c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 9*7c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 10*7c478bd9Sstevel@tonic-gate * the sendmail distribution. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate */ 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #include <sendmail.h> 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: daemon.c,v 8.658 2005/02/02 18:19:28 ca Exp $") 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) 21*7c478bd9Sstevel@tonic-gate # define USE_SOCK_STREAM 1 22*7c478bd9Sstevel@tonic-gate #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate #if defined(USE_SOCK_STREAM) 25*7c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 26*7c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 27*7c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 28*7c478bd9Sstevel@tonic-gate # if NAMED_BIND 29*7c478bd9Sstevel@tonic-gate # ifndef NO_DATA 30*7c478bd9Sstevel@tonic-gate # define NO_DATA NO_ADDRESS 31*7c478bd9Sstevel@tonic-gate # endif /* ! NO_DATA */ 32*7c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 33*7c478bd9Sstevel@tonic-gate #endif /* defined(USE_SOCK_STREAM) */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate #if STARTTLS 36*7c478bd9Sstevel@tonic-gate # include <openssl/rand.h> 37*7c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #if IP_SRCROUTE && NETINET 42*7c478bd9Sstevel@tonic-gate # include <netinet/in_systm.h> 43*7c478bd9Sstevel@tonic-gate # include <netinet/ip.h> 44*7c478bd9Sstevel@tonic-gate # if HAS_IN_H 45*7c478bd9Sstevel@tonic-gate # include <netinet/in.h> 46*7c478bd9Sstevel@tonic-gate # ifndef IPOPTION 47*7c478bd9Sstevel@tonic-gate # define IPOPTION ip_opts 48*7c478bd9Sstevel@tonic-gate # define IP_LIST ip_opts 49*7c478bd9Sstevel@tonic-gate # define IP_DST ip_dst 50*7c478bd9Sstevel@tonic-gate # endif /* ! IPOPTION */ 51*7c478bd9Sstevel@tonic-gate # else /* HAS_IN_H */ 52*7c478bd9Sstevel@tonic-gate # include <netinet/ip_var.h> 53*7c478bd9Sstevel@tonic-gate # ifndef IPOPTION 54*7c478bd9Sstevel@tonic-gate # define IPOPTION ipoption 55*7c478bd9Sstevel@tonic-gate # define IP_LIST ipopt_list 56*7c478bd9Sstevel@tonic-gate # define IP_DST ipopt_dst 57*7c478bd9Sstevel@tonic-gate # endif /* ! IPOPTION */ 58*7c478bd9Sstevel@tonic-gate # endif /* HAS_IN_H */ 59*7c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE && NETINET */ 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include <sm/fdset.h> 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* structure to describe a daemon or a client */ 64*7c478bd9Sstevel@tonic-gate struct daemon 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate int d_socket; /* fd for socket */ 67*7c478bd9Sstevel@tonic-gate SOCKADDR d_addr; /* socket for incoming */ 68*7c478bd9Sstevel@tonic-gate unsigned short d_port; /* port number */ 69*7c478bd9Sstevel@tonic-gate int d_listenqueue; /* size of listen queue */ 70*7c478bd9Sstevel@tonic-gate int d_tcprcvbufsize; /* size of TCP receive buffer */ 71*7c478bd9Sstevel@tonic-gate int d_tcpsndbufsize; /* size of TCP send buffer */ 72*7c478bd9Sstevel@tonic-gate time_t d_refuse_connections_until; 73*7c478bd9Sstevel@tonic-gate bool d_firsttime; 74*7c478bd9Sstevel@tonic-gate int d_socksize; 75*7c478bd9Sstevel@tonic-gate BITMAP256 d_flags; /* flags; see sendmail.h */ 76*7c478bd9Sstevel@tonic-gate char *d_mflags; /* flags for use in macro */ 77*7c478bd9Sstevel@tonic-gate char *d_name; /* user-supplied name */ 78*7c478bd9Sstevel@tonic-gate #if MILTER 79*7c478bd9Sstevel@tonic-gate char *d_inputfilterlist; 80*7c478bd9Sstevel@tonic-gate struct milter *d_inputfilters[MAXFILTERS]; 81*7c478bd9Sstevel@tonic-gate #endif /* MILTER */ 82*7c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 83*7c478bd9Sstevel@tonic-gate int d_supersafe; 84*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 85*7c478bd9Sstevel@tonic-gate #if _FFR_DM_PER_DAEMON 86*7c478bd9Sstevel@tonic-gate int d_dm; /* DeliveryMode */ 87*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DM_PER_DAEMON */ 88*7c478bd9Sstevel@tonic-gate }; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate typedef struct daemon DAEMON_T; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate #define SAFE_NOTSET (-1) /* SuperSafe (per daemon) option not set */ 93*7c478bd9Sstevel@tonic-gate /* see also sendmail.h: SuperSafe values */ 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate #define DM_NOTSET (-1) /* DeliveryMode (per daemon) option not set */ 96*7c478bd9Sstevel@tonic-gate /* see also sendmail.h: values for e_sendmode -- send modes */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate static void connecttimeout __P((int)); 99*7c478bd9Sstevel@tonic-gate static int opendaemonsocket __P((DAEMON_T *, bool)); 100*7c478bd9Sstevel@tonic-gate static unsigned short setupdaemon __P((SOCKADDR *)); 101*7c478bd9Sstevel@tonic-gate static void getrequests_checkdiskspace __P((ENVELOPE *e)); 102*7c478bd9Sstevel@tonic-gate static void setsockaddroptions __P((char *, DAEMON_T *)); 103*7c478bd9Sstevel@tonic-gate static void printdaemonflags __P((DAEMON_T *)); 104*7c478bd9Sstevel@tonic-gate static int addr_family __P((char *)); 105*7c478bd9Sstevel@tonic-gate static int addrcmp __P((struct hostent *, char *, SOCKADDR *)); 106*7c478bd9Sstevel@tonic-gate static void authtimeout __P((int)); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate ** DAEMON.C -- routines to use when running as a daemon. 110*7c478bd9Sstevel@tonic-gate ** 111*7c478bd9Sstevel@tonic-gate ** This entire file is highly dependent on the 4.2 BSD 112*7c478bd9Sstevel@tonic-gate ** interprocess communication primitives. No attempt has 113*7c478bd9Sstevel@tonic-gate ** been made to make this file portable to Version 7, 114*7c478bd9Sstevel@tonic-gate ** Version 6, MPX files, etc. If you should try such a 115*7c478bd9Sstevel@tonic-gate ** thing yourself, I recommend chucking the entire file 116*7c478bd9Sstevel@tonic-gate ** and starting from scratch. Basic semantics are: 117*7c478bd9Sstevel@tonic-gate ** 118*7c478bd9Sstevel@tonic-gate ** getrequests(e) 119*7c478bd9Sstevel@tonic-gate ** Opens a port and initiates a connection. 120*7c478bd9Sstevel@tonic-gate ** Returns in a child. Must set InChannel and 121*7c478bd9Sstevel@tonic-gate ** OutChannel appropriately. 122*7c478bd9Sstevel@tonic-gate ** clrdaemon() 123*7c478bd9Sstevel@tonic-gate ** Close any open files associated with getting 124*7c478bd9Sstevel@tonic-gate ** the connection; this is used when running the queue, 125*7c478bd9Sstevel@tonic-gate ** etc., to avoid having extra file descriptors during 126*7c478bd9Sstevel@tonic-gate ** the queue run and to avoid confusing the network 127*7c478bd9Sstevel@tonic-gate ** code (if it cares). 128*7c478bd9Sstevel@tonic-gate ** makeconnection(host, port, mci, e, enough) 129*7c478bd9Sstevel@tonic-gate ** Make a connection to the named host on the given 130*7c478bd9Sstevel@tonic-gate ** port. Returns zero on success, else an exit status 131*7c478bd9Sstevel@tonic-gate ** describing the error. 132*7c478bd9Sstevel@tonic-gate ** host_map_lookup(map, hbuf, avp, pstat) 133*7c478bd9Sstevel@tonic-gate ** Convert the entry in hbuf into a canonical form. 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate static DAEMON_T Daemons[MAXDAEMONS]; 137*7c478bd9Sstevel@tonic-gate static int NDaemons = 0; /* actual number of daemons */ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static time_t NextDiskSpaceCheck = 0; 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate ** GETREQUESTS -- open mail IPC port and get requests. 143*7c478bd9Sstevel@tonic-gate ** 144*7c478bd9Sstevel@tonic-gate ** Parameters: 145*7c478bd9Sstevel@tonic-gate ** e -- the current envelope. 146*7c478bd9Sstevel@tonic-gate ** 147*7c478bd9Sstevel@tonic-gate ** Returns: 148*7c478bd9Sstevel@tonic-gate ** pointer to flags. 149*7c478bd9Sstevel@tonic-gate ** 150*7c478bd9Sstevel@tonic-gate ** Side Effects: 151*7c478bd9Sstevel@tonic-gate ** Waits until some interesting activity occurs. When 152*7c478bd9Sstevel@tonic-gate ** it does, a child is created to process it, and the 153*7c478bd9Sstevel@tonic-gate ** parent waits for completion. Return from this 154*7c478bd9Sstevel@tonic-gate ** routine is always in the child. The file pointers 155*7c478bd9Sstevel@tonic-gate ** "InChannel" and "OutChannel" should be set to point 156*7c478bd9Sstevel@tonic-gate ** to the communication channel. 157*7c478bd9Sstevel@tonic-gate ** May restart persistent queue runners if they have ended 158*7c478bd9Sstevel@tonic-gate ** for some reason. 159*7c478bd9Sstevel@tonic-gate */ 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate BITMAP256 * 162*7c478bd9Sstevel@tonic-gate getrequests(e) 163*7c478bd9Sstevel@tonic-gate ENVELOPE *e; 164*7c478bd9Sstevel@tonic-gate { 165*7c478bd9Sstevel@tonic-gate int t; 166*7c478bd9Sstevel@tonic-gate int idx, curdaemon = -1; 167*7c478bd9Sstevel@tonic-gate int i, olddaemon = 0; 168*7c478bd9Sstevel@tonic-gate #if XDEBUG 169*7c478bd9Sstevel@tonic-gate bool j_has_dot; 170*7c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 171*7c478bd9Sstevel@tonic-gate char status[MAXLINE]; 172*7c478bd9Sstevel@tonic-gate SOCKADDR sa; 173*7c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T len = sizeof sa; 174*7c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 175*7c478bd9Sstevel@tonic-gate time_t lastrun; 176*7c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 177*7c478bd9Sstevel@tonic-gate # if NETUNIX 178*7c478bd9Sstevel@tonic-gate extern int ControlSocket; 179*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 180*7c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 181*7c478bd9Sstevel@tonic-gate extern bool refuseconnections __P((char *, ENVELOPE *, int, bool)); 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate /* initialize data for function that generates queue ids */ 185*7c478bd9Sstevel@tonic-gate init_qid_alg(); 186*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); 189*7c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime = true; 190*7c478bd9Sstevel@tonic-gate Daemons[idx].d_refuse_connections_until = (time_t) 0; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate ** Try to actually open the connection. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (tTd(15, 1)) 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 200*7c478bd9Sstevel@tonic-gate { 201*7c478bd9Sstevel@tonic-gate sm_dprintf("getrequests: daemon %s: port %d\n", 202*7c478bd9Sstevel@tonic-gate Daemons[idx].d_name, 203*7c478bd9Sstevel@tonic-gate ntohs(Daemons[idx].d_port)); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate /* get a socket for the SMTP connection */ 208*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 209*7c478bd9Sstevel@tonic-gate Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], true); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (opencontrolsocket() < 0) 212*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 213*7c478bd9Sstevel@tonic-gate "daemon could not open control socket %s: %s", 214*7c478bd9Sstevel@tonic-gate ControlSocketName, sm_errstring(errno)); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* If there are any queue runners released reapchild() co-ord's */ 217*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, reapchild); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* write the pid to file, command line args to syslog */ 220*7c478bd9Sstevel@tonic-gate log_sendmail_pid(e); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate #if XDEBUG 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate expand("\201j", jbuf, sizeof jbuf, e); 227*7c478bd9Sstevel@tonic-gate j_has_dot = strchr(jbuf, '.') != NULL; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* Add parent process as first item */ 232*7c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, "Sendmail daemon", PROC_DAEMON, 0, -1, NULL); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate if (tTd(15, 1)) 235*7c478bd9Sstevel@tonic-gate { 236*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 237*7c478bd9Sstevel@tonic-gate sm_dprintf("getrequests: daemon %s: %d\n", 238*7c478bd9Sstevel@tonic-gate Daemons[idx].d_name, 239*7c478bd9Sstevel@tonic-gate Daemons[idx].d_socket); 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate for (;;) 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate register pid_t pid; 245*7c478bd9Sstevel@tonic-gate auto SOCKADDR_LEN_T lotherend; 246*7c478bd9Sstevel@tonic-gate bool timedout = false; 247*7c478bd9Sstevel@tonic-gate bool control = false; 248*7c478bd9Sstevel@tonic-gate int save_errno; 249*7c478bd9Sstevel@tonic-gate int pipefd[2]; 250*7c478bd9Sstevel@tonic-gate time_t now; 251*7c478bd9Sstevel@tonic-gate #if STARTTLS 252*7c478bd9Sstevel@tonic-gate long seed; 253*7c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate /* see if we are rejecting connections */ 256*7c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGALRM); 257*7c478bd9Sstevel@tonic-gate CHECK_RESTART; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 260*7c478bd9Sstevel@tonic-gate { 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate ** XXX do this call outside the loop? 263*7c478bd9Sstevel@tonic-gate ** no: refuse_connections may sleep(). 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate now = curtime(); 267*7c478bd9Sstevel@tonic-gate if (now < Daemons[idx].d_refuse_connections_until) 268*7c478bd9Sstevel@tonic-gate continue; 269*7c478bd9Sstevel@tonic-gate if (bitnset(D_DISABLE, Daemons[idx].d_flags)) 270*7c478bd9Sstevel@tonic-gate continue; 271*7c478bd9Sstevel@tonic-gate if (refuseconnections(Daemons[idx].d_name, e, idx, 272*7c478bd9Sstevel@tonic-gate curdaemon == idx)) 273*7c478bd9Sstevel@tonic-gate { 274*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 275*7c478bd9Sstevel@tonic-gate { 276*7c478bd9Sstevel@tonic-gate /* close socket so peer fails quickly */ 277*7c478bd9Sstevel@tonic-gate (void) close(Daemons[idx].d_socket); 278*7c478bd9Sstevel@tonic-gate Daemons[idx].d_socket = -1; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* refuse connections for next 15 seconds */ 282*7c478bd9Sstevel@tonic-gate Daemons[idx].d_refuse_connections_until = now + 15; 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate else if (Daemons[idx].d_socket < 0 || 285*7c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime) 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate if (!Daemons[idx].d_firsttime && LogLevel > 8) 288*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 289*7c478bd9Sstevel@tonic-gate "accepting connections again for daemon %s", 290*7c478bd9Sstevel@tonic-gate Daemons[idx].d_name); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate /* arrange to (re)open the socket if needed */ 293*7c478bd9Sstevel@tonic-gate (void) opendaemonsocket(&Daemons[idx], false); 294*7c478bd9Sstevel@tonic-gate Daemons[idx].d_firsttime = false; 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate /* May have been sleeping above, check again */ 299*7c478bd9Sstevel@tonic-gate CHECK_RESTART; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate getrequests_checkdiskspace(e); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate #if XDEBUG 304*7c478bd9Sstevel@tonic-gate /* check for disaster */ 305*7c478bd9Sstevel@tonic-gate { 306*7c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate expand("\201j", jbuf, sizeof jbuf, e); 309*7c478bd9Sstevel@tonic-gate if (!wordinclass(jbuf, 'w')) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate dumpstate("daemon lost $j"); 312*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 313*7c478bd9Sstevel@tonic-gate "daemon process doesn't have $j in $=w; see syslog"); 314*7c478bd9Sstevel@tonic-gate abort(); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate else if (j_has_dot && strchr(jbuf, '.') == NULL) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate dumpstate("daemon $j lost dot"); 319*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 320*7c478bd9Sstevel@tonic-gate "daemon process $j lost dot; see syslog"); 321*7c478bd9Sstevel@tonic-gate abort(); 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate #if 0 327*7c478bd9Sstevel@tonic-gate /* 328*7c478bd9Sstevel@tonic-gate ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will 329*7c478bd9Sstevel@tonic-gate ** fix the SVr4 problem. But it seems to have gone away, 330*7c478bd9Sstevel@tonic-gate ** so is it worth doing this? 331*7c478bd9Sstevel@tonic-gate */ 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate if (DaemonSocket >= 0 && 334*7c478bd9Sstevel@tonic-gate SetNonBlocking(DaemonSocket, false) < 0) 335*7c478bd9Sstevel@tonic-gate log an error here; 336*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 337*7c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate for (;;) 340*7c478bd9Sstevel@tonic-gate { 341*7c478bd9Sstevel@tonic-gate bool setproc = false; 342*7c478bd9Sstevel@tonic-gate int highest = -1; 343*7c478bd9Sstevel@tonic-gate fd_set readfds; 344*7c478bd9Sstevel@tonic-gate struct timeval timeout; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate CHECK_RESTART; 347*7c478bd9Sstevel@tonic-gate FD_ZERO(&readfds); 348*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 349*7c478bd9Sstevel@tonic-gate { 350*7c478bd9Sstevel@tonic-gate /* wait for a connection */ 351*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 352*7c478bd9Sstevel@tonic-gate { 353*7c478bd9Sstevel@tonic-gate if (!setproc && 354*7c478bd9Sstevel@tonic-gate !bitnset(D_ETRNONLY, 355*7c478bd9Sstevel@tonic-gate Daemons[idx].d_flags)) 356*7c478bd9Sstevel@tonic-gate { 357*7c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, 358*7c478bd9Sstevel@tonic-gate "accepting connections"); 359*7c478bd9Sstevel@tonic-gate setproc = true; 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket > highest) 362*7c478bd9Sstevel@tonic-gate highest = Daemons[idx].d_socket; 363*7c478bd9Sstevel@tonic-gate SM_FD_SET(Daemons[idx].d_socket, 364*7c478bd9Sstevel@tonic-gate &readfds); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate #if NETUNIX 369*7c478bd9Sstevel@tonic-gate if (ControlSocket >= 0) 370*7c478bd9Sstevel@tonic-gate { 371*7c478bd9Sstevel@tonic-gate if (ControlSocket > highest) 372*7c478bd9Sstevel@tonic-gate highest = ControlSocket; 373*7c478bd9Sstevel@tonic-gate SM_FD_SET(ControlSocket, &readfds); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate timeout.tv_sec = 5; 378*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate t = select(highest + 1, FDSET_CAST &readfds, 381*7c478bd9Sstevel@tonic-gate NULL, NULL, &timeout); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* Did someone signal while waiting? */ 384*7c478bd9Sstevel@tonic-gate CHECK_RESTART; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate curdaemon = -1; 387*7c478bd9Sstevel@tonic-gate if (doqueuerun()) 388*7c478bd9Sstevel@tonic-gate { 389*7c478bd9Sstevel@tonic-gate (void) runqueue(true, false, false, false); 390*7c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 391*7c478bd9Sstevel@tonic-gate lastrun = now; 392*7c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate #if _FFR_QUEUE_RUN_PARANOIA 395*7c478bd9Sstevel@tonic-gate else if (QueueIntvl > 0 && 396*7c478bd9Sstevel@tonic-gate lastrun + QueueIntvl + 60 < now) 397*7c478bd9Sstevel@tonic-gate { 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* 400*7c478bd9Sstevel@tonic-gate ** set lastrun unconditionally to avoid 401*7c478bd9Sstevel@tonic-gate ** calling checkqueuerunner() all the time. 402*7c478bd9Sstevel@tonic-gate ** That's also why we currently ignore the 403*7c478bd9Sstevel@tonic-gate ** result of the function call. 404*7c478bd9Sstevel@tonic-gate */ 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate (void) checkqueuerunner(); 407*7c478bd9Sstevel@tonic-gate lastrun = now; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate #endif /* _FFR_QUEUE_RUN_PARANOIA */ 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate if (t <= 0) 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate timedout = true; 414*7c478bd9Sstevel@tonic-gate break; 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate control = false; 418*7c478bd9Sstevel@tonic-gate errno = 0; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* look "round-robin" for an active socket */ 421*7c478bd9Sstevel@tonic-gate if ((idx = olddaemon + 1) >= NDaemons) 422*7c478bd9Sstevel@tonic-gate idx = 0; 423*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 424*7c478bd9Sstevel@tonic-gate { 425*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0 && 426*7c478bd9Sstevel@tonic-gate SM_FD_ISSET(Daemons[idx].d_socket, 427*7c478bd9Sstevel@tonic-gate &readfds)) 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate lotherend = Daemons[idx].d_socksize; 430*7c478bd9Sstevel@tonic-gate memset(&RealHostAddr, '\0', 431*7c478bd9Sstevel@tonic-gate sizeof RealHostAddr); 432*7c478bd9Sstevel@tonic-gate t = accept(Daemons[idx].d_socket, 433*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&RealHostAddr, 434*7c478bd9Sstevel@tonic-gate &lotherend); 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* 437*7c478bd9Sstevel@tonic-gate ** If remote side closes before 438*7c478bd9Sstevel@tonic-gate ** accept() finishes, sockaddr 439*7c478bd9Sstevel@tonic-gate ** might not be fully filled in. 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate if (t >= 0 && 443*7c478bd9Sstevel@tonic-gate (lotherend == 0 || 444*7c478bd9Sstevel@tonic-gate # ifdef BSD4_4_SOCKADDR 445*7c478bd9Sstevel@tonic-gate RealHostAddr.sa.sa_len == 0 || 446*7c478bd9Sstevel@tonic-gate # endif /* BSD4_4_SOCKADDR */ 447*7c478bd9Sstevel@tonic-gate RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) 448*7c478bd9Sstevel@tonic-gate { 449*7c478bd9Sstevel@tonic-gate (void) close(t); 450*7c478bd9Sstevel@tonic-gate t = -1; 451*7c478bd9Sstevel@tonic-gate errno = EINVAL; 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate olddaemon = curdaemon = idx; 454*7c478bd9Sstevel@tonic-gate break; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate if (++idx >= NDaemons) 457*7c478bd9Sstevel@tonic-gate idx = 0; 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate #if NETUNIX 460*7c478bd9Sstevel@tonic-gate if (curdaemon == -1 && ControlSocket >= 0 && 461*7c478bd9Sstevel@tonic-gate SM_FD_ISSET(ControlSocket, &readfds)) 462*7c478bd9Sstevel@tonic-gate { 463*7c478bd9Sstevel@tonic-gate struct sockaddr_un sa_un; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate lotherend = sizeof sa_un; 466*7c478bd9Sstevel@tonic-gate memset(&sa_un, '\0', sizeof sa_un); 467*7c478bd9Sstevel@tonic-gate t = accept(ControlSocket, 468*7c478bd9Sstevel@tonic-gate (struct sockaddr *)&sa_un, 469*7c478bd9Sstevel@tonic-gate &lotherend); 470*7c478bd9Sstevel@tonic-gate 471*7c478bd9Sstevel@tonic-gate /* 472*7c478bd9Sstevel@tonic-gate ** If remote side closes before 473*7c478bd9Sstevel@tonic-gate ** accept() finishes, sockaddr 474*7c478bd9Sstevel@tonic-gate ** might not be fully filled in. 475*7c478bd9Sstevel@tonic-gate */ 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate if (t >= 0 && 478*7c478bd9Sstevel@tonic-gate (lotherend == 0 || 479*7c478bd9Sstevel@tonic-gate # ifdef BSD4_4_SOCKADDR 480*7c478bd9Sstevel@tonic-gate sa_un.sun_len == 0 || 481*7c478bd9Sstevel@tonic-gate # endif /* BSD4_4_SOCKADDR */ 482*7c478bd9Sstevel@tonic-gate sa_un.sun_family != AF_UNIX)) 483*7c478bd9Sstevel@tonic-gate { 484*7c478bd9Sstevel@tonic-gate (void) close(t); 485*7c478bd9Sstevel@tonic-gate t = -1; 486*7c478bd9Sstevel@tonic-gate errno = EINVAL; 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate if (t >= 0) 489*7c478bd9Sstevel@tonic-gate control = true; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate #else /* NETUNIX */ 492*7c478bd9Sstevel@tonic-gate if (curdaemon == -1) 493*7c478bd9Sstevel@tonic-gate { 494*7c478bd9Sstevel@tonic-gate /* No daemon to service */ 495*7c478bd9Sstevel@tonic-gate continue; 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 498*7c478bd9Sstevel@tonic-gate if (t >= 0 || errno != EINTR) 499*7c478bd9Sstevel@tonic-gate break; 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate if (timedout) 502*7c478bd9Sstevel@tonic-gate { 503*7c478bd9Sstevel@tonic-gate timedout = false; 504*7c478bd9Sstevel@tonic-gate continue; 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate save_errno = errno; 507*7c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGALRM); 508*7c478bd9Sstevel@tonic-gate if (t < 0) 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate errno = save_errno; 511*7c478bd9Sstevel@tonic-gate 512*7c478bd9Sstevel@tonic-gate /* let's ignore these temporary errors */ 513*7c478bd9Sstevel@tonic-gate if (save_errno == EINTR 514*7c478bd9Sstevel@tonic-gate #ifdef EAGAIN 515*7c478bd9Sstevel@tonic-gate || save_errno == EAGAIN 516*7c478bd9Sstevel@tonic-gate #endif /* EAGAIN */ 517*7c478bd9Sstevel@tonic-gate #ifdef ECONNABORTED 518*7c478bd9Sstevel@tonic-gate || save_errno == ECONNABORTED 519*7c478bd9Sstevel@tonic-gate #endif /* ECONNABORTED */ 520*7c478bd9Sstevel@tonic-gate #ifdef EWOULDBLOCK 521*7c478bd9Sstevel@tonic-gate || save_errno == EWOULDBLOCK 522*7c478bd9Sstevel@tonic-gate #endif /* EWOULDBLOCK */ 523*7c478bd9Sstevel@tonic-gate ) 524*7c478bd9Sstevel@tonic-gate continue; 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate syserr("getrequests: accept"); 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate /* arrange to re-open the socket next time around */ 529*7c478bd9Sstevel@tonic-gate (void) close(Daemons[curdaemon].d_socket); 530*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_socket = -1; 531*7c478bd9Sstevel@tonic-gate #if SO_REUSEADDR_IS_BROKEN 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate ** Give time for bound socket to be released. 534*7c478bd9Sstevel@tonic-gate ** This creates a denial-of-service if you can 535*7c478bd9Sstevel@tonic-gate ** force accept() to fail on affected systems. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_refuse_connections_until = curtime() + 15; 539*7c478bd9Sstevel@tonic-gate #endif /* SO_REUSEADDR_IS_BROKEN */ 540*7c478bd9Sstevel@tonic-gate continue; 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (!control) 544*7c478bd9Sstevel@tonic-gate { 545*7c478bd9Sstevel@tonic-gate /* set some daemon related macros */ 546*7c478bd9Sstevel@tonic-gate switch (Daemons[curdaemon].d_addr.sa.sa_family) 547*7c478bd9Sstevel@tonic-gate { 548*7c478bd9Sstevel@tonic-gate case AF_UNSPEC: 549*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 550*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "unspec"); 551*7c478bd9Sstevel@tonic-gate break; 552*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 553*7c478bd9Sstevel@tonic-gate # if NETUNIX 554*7c478bd9Sstevel@tonic-gate case AF_UNIX: 555*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 556*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "local"); 557*7c478bd9Sstevel@tonic-gate break; 558*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 559*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 560*7c478bd9Sstevel@tonic-gate #if NETINET 561*7c478bd9Sstevel@tonic-gate case AF_INET: 562*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 563*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "inet"); 564*7c478bd9Sstevel@tonic-gate break; 565*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 566*7c478bd9Sstevel@tonic-gate #if NETINET6 567*7c478bd9Sstevel@tonic-gate case AF_INET6: 568*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 569*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "inet6"); 570*7c478bd9Sstevel@tonic-gate break; 571*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 572*7c478bd9Sstevel@tonic-gate #if NETISO 573*7c478bd9Sstevel@tonic-gate case AF_ISO: 574*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 575*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "iso"); 576*7c478bd9Sstevel@tonic-gate break; 577*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 578*7c478bd9Sstevel@tonic-gate #if NETNS 579*7c478bd9Sstevel@tonic-gate case AF_NS: 580*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 581*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "ns"); 582*7c478bd9Sstevel@tonic-gate break; 583*7c478bd9Sstevel@tonic-gate #endif /* NETNS */ 584*7c478bd9Sstevel@tonic-gate #if NETX25 585*7c478bd9Sstevel@tonic-gate case AF_CCITT: 586*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 587*7c478bd9Sstevel@tonic-gate macid("{daemon_family}"), "x.25"); 588*7c478bd9Sstevel@tonic-gate break; 589*7c478bd9Sstevel@tonic-gate #endif /* NETX25 */ 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 592*7c478bd9Sstevel@tonic-gate macid("{daemon_name}"), 593*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_name); 594*7c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_mflags != NULL) 595*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 596*7c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), 597*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_mflags); 598*7c478bd9Sstevel@tonic-gate else 599*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 600*7c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), ""); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate /* 604*7c478bd9Sstevel@tonic-gate ** If connection rate is exceeded here, connection shall be 605*7c478bd9Sstevel@tonic-gate ** refused later by a new call after fork() by the 606*7c478bd9Sstevel@tonic-gate ** validate_connection() function. Closing the connection 607*7c478bd9Sstevel@tonic-gate ** at this point violates RFC 2821. 608*7c478bd9Sstevel@tonic-gate ** Do NOT remove this call, its side effects are needed. 609*7c478bd9Sstevel@tonic-gate */ 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate connection_rate_check(&RealHostAddr, NULL); 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate /* 614*7c478bd9Sstevel@tonic-gate ** Create a subprocess to process the mail. 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 618*7c478bd9Sstevel@tonic-gate sm_dprintf("getrequests: forking (fd = %d)\n", t); 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate /* 621*7c478bd9Sstevel@tonic-gate ** Advance state of PRNG. 622*7c478bd9Sstevel@tonic-gate ** This is necessary because otherwise all child processes 623*7c478bd9Sstevel@tonic-gate ** will produce the same PRN sequence and hence the selection 624*7c478bd9Sstevel@tonic-gate ** of a queue directory (and other things, e.g., MX selection) 625*7c478bd9Sstevel@tonic-gate ** are not "really" random. 626*7c478bd9Sstevel@tonic-gate */ 627*7c478bd9Sstevel@tonic-gate #if STARTTLS 628*7c478bd9Sstevel@tonic-gate /* XXX get some better "random" data? */ 629*7c478bd9Sstevel@tonic-gate seed = get_random(); 630*7c478bd9Sstevel@tonic-gate RAND_seed((void *) &NextDiskSpaceCheck, 631*7c478bd9Sstevel@tonic-gate sizeof NextDiskSpaceCheck); 632*7c478bd9Sstevel@tonic-gate RAND_seed((void *) &now, sizeof now); 633*7c478bd9Sstevel@tonic-gate RAND_seed((void *) &seed, sizeof seed); 634*7c478bd9Sstevel@tonic-gate #else /* STARTTLS */ 635*7c478bd9Sstevel@tonic-gate (void) get_random(); 636*7c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 639*7c478bd9Sstevel@tonic-gate /* 640*7c478bd9Sstevel@tonic-gate ** Update MX records for FallbackMX. 641*7c478bd9Sstevel@tonic-gate ** Let's hope this is fast otherwise we screw up the 642*7c478bd9Sstevel@tonic-gate ** response time. 643*7c478bd9Sstevel@tonic-gate */ 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate if (FallbackMX != NULL) 646*7c478bd9Sstevel@tonic-gate (void) getfallbackmxrr(FallbackMX); 647*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate if (tTd(93, 100)) 650*7c478bd9Sstevel@tonic-gate { 651*7c478bd9Sstevel@tonic-gate /* don't fork, handle connection in this process */ 652*7c478bd9Sstevel@tonic-gate pid = 0; 653*7c478bd9Sstevel@tonic-gate pipefd[0] = pipefd[1] = -1; 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate else 656*7c478bd9Sstevel@tonic-gate { 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate ** Create a pipe to keep the child from writing to 659*7c478bd9Sstevel@tonic-gate ** the socket until after the parent has closed 660*7c478bd9Sstevel@tonic-gate ** it. Otherwise the parent may hang if the child 661*7c478bd9Sstevel@tonic-gate ** has closed it first. 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate if (pipe(pipefd) < 0) 665*7c478bd9Sstevel@tonic-gate pipefd[0] = pipefd[1] = -1; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate (void) sm_blocksignal(SIGCHLD); 668*7c478bd9Sstevel@tonic-gate pid = fork(); 669*7c478bd9Sstevel@tonic-gate if (pid < 0) 670*7c478bd9Sstevel@tonic-gate { 671*7c478bd9Sstevel@tonic-gate syserr("daemon: cannot fork"); 672*7c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 673*7c478bd9Sstevel@tonic-gate { 674*7c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 675*7c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 678*7c478bd9Sstevel@tonic-gate (void) sleep(10); 679*7c478bd9Sstevel@tonic-gate (void) close(t); 680*7c478bd9Sstevel@tonic-gate continue; 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate if (pid == 0) 685*7c478bd9Sstevel@tonic-gate { 686*7c478bd9Sstevel@tonic-gate char *p; 687*7c478bd9Sstevel@tonic-gate SM_FILE_T *inchannel, *outchannel = NULL; 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate ** CHILD -- return to caller. 691*7c478bd9Sstevel@tonic-gate ** Collect verified idea of sending host. 692*7c478bd9Sstevel@tonic-gate ** Verify calling user id if possible here. 693*7c478bd9Sstevel@tonic-gate */ 694*7c478bd9Sstevel@tonic-gate 695*7c478bd9Sstevel@tonic-gate /* Reset global flags */ 696*7c478bd9Sstevel@tonic-gate RestartRequest = NULL; 697*7c478bd9Sstevel@tonic-gate RestartWorkGroup = false; 698*7c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 699*7c478bd9Sstevel@tonic-gate PendingSignal = 0; 700*7c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 701*7c478bd9Sstevel@tonic-gate close_sendmail_pid(); 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 704*7c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 705*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, SIG_DFL); 706*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGHUP, SIG_DFL); 707*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGTERM, intsig); 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate /* turn on profiling */ 710*7c478bd9Sstevel@tonic-gate /* SM_PROF(0); */ 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate /* 713*7c478bd9Sstevel@tonic-gate ** Initialize exception stack and default exception 714*7c478bd9Sstevel@tonic-gate ** handler for child process. 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate sm_exc_newthread(fatal_error); 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate if (!control) 720*7c478bd9Sstevel@tonic-gate { 721*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 722*7c478bd9Sstevel@tonic-gate macid("{daemon_addr}"), 723*7c478bd9Sstevel@tonic-gate anynet_ntoa(&Daemons[curdaemon].d_addr)); 724*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(status, sizeof status, "%d", 725*7c478bd9Sstevel@tonic-gate ntohs(Daemons[curdaemon].d_port)); 726*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 727*7c478bd9Sstevel@tonic-gate macid("{daemon_port}"), status); 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 731*7c478bd9Sstevel@tonic-gate { 732*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_socket >= 0) 733*7c478bd9Sstevel@tonic-gate (void) close(Daemons[idx].d_socket); 734*7c478bd9Sstevel@tonic-gate Daemons[idx].d_socket = -1; 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate clrcontrol(); 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate /* Avoid SMTP daemon actions if control command */ 739*7c478bd9Sstevel@tonic-gate if (control) 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate /* Add control socket process */ 742*7c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, 743*7c478bd9Sstevel@tonic-gate "console socket child", 744*7c478bd9Sstevel@tonic-gate PROC_CONTROL_CHILD, 0, -1, NULL); 745*7c478bd9Sstevel@tonic-gate } 746*7c478bd9Sstevel@tonic-gate else 747*7c478bd9Sstevel@tonic-gate { 748*7c478bd9Sstevel@tonic-gate proc_list_clear(); 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate /* clean up background delivery children */ 751*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, reapchild); 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* Add parent process as first child item */ 754*7c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, "daemon child", 755*7c478bd9Sstevel@tonic-gate PROC_DAEMON_CHILD, 0, -1, NULL); 756*7c478bd9Sstevel@tonic-gate 757*7c478bd9Sstevel@tonic-gate /* don't schedule queue runs if ETRN */ 758*7c478bd9Sstevel@tonic-gate QueueIntvl = 0; 759*7c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 760*7c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_supersafe != 761*7c478bd9Sstevel@tonic-gate SAFE_NOTSET) 762*7c478bd9Sstevel@tonic-gate SuperSafe = Daemons[curdaemon].d_supersafe; 763*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 764*7c478bd9Sstevel@tonic-gate #if _FFR_DM_PER_DAEMON 765*7c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_dm != DM_NOTSET) 766*7c478bd9Sstevel@tonic-gate set_delivery_mode( 767*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_dm, e); 768*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DM_PER_DAEMON */ 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate 771*7c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, "startup with %s", 772*7c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 776*7c478bd9Sstevel@tonic-gate { 777*7c478bd9Sstevel@tonic-gate auto char c; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate /* 780*7c478bd9Sstevel@tonic-gate ** Wait for the parent to close the write end 781*7c478bd9Sstevel@tonic-gate ** of the pipe, which we will see as an EOF. 782*7c478bd9Sstevel@tonic-gate ** This guarantees that we won't write to the 783*7c478bd9Sstevel@tonic-gate ** socket until after the parent has closed 784*7c478bd9Sstevel@tonic-gate ** the pipe. 785*7c478bd9Sstevel@tonic-gate */ 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate /* close the write end of the pipe */ 788*7c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate /* we shouldn't be interrupted, but ... */ 791*7c478bd9Sstevel@tonic-gate while (read(pipefd[0], &c, 1) < 0 && 792*7c478bd9Sstevel@tonic-gate errno == EINTR) 793*7c478bd9Sstevel@tonic-gate continue; 794*7c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 795*7c478bd9Sstevel@tonic-gate } 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate /* control socket processing */ 798*7c478bd9Sstevel@tonic-gate if (control) 799*7c478bd9Sstevel@tonic-gate { 800*7c478bd9Sstevel@tonic-gate control_command(t, e); 801*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 802*7c478bd9Sstevel@tonic-gate exit(EX_SOFTWARE); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate /* determine host name */ 806*7c478bd9Sstevel@tonic-gate p = hostnamebyanyaddr(&RealHostAddr); 807*7c478bd9Sstevel@tonic-gate if (strlen(p) > MAXNAME) /* XXX - 1 ? */ 808*7c478bd9Sstevel@tonic-gate p[MAXNAME] = '\0'; 809*7c478bd9Sstevel@tonic-gate RealHostName = newstr(p); 810*7c478bd9Sstevel@tonic-gate if (RealHostName[0] == '[') 811*7c478bd9Sstevel@tonic-gate { 812*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 813*7c478bd9Sstevel@tonic-gate macid("{client_resolve}"), 814*7c478bd9Sstevel@tonic-gate h_errno == TRY_AGAIN ? "TEMP" : "FAIL"); 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate else 817*7c478bd9Sstevel@tonic-gate { 818*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 819*7c478bd9Sstevel@tonic-gate macid("{client_resolve}"), "OK"); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, "startup with %s", p); 822*7c478bd9Sstevel@tonic-gate markstats(e, NULL, STATS_CONNECT); 823*7c478bd9Sstevel@tonic-gate 824*7c478bd9Sstevel@tonic-gate if ((inchannel = sm_io_open(SmFtStdiofd, 825*7c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 826*7c478bd9Sstevel@tonic-gate (void *) &t, 827*7c478bd9Sstevel@tonic-gate SM_IO_RDONLY_B, 828*7c478bd9Sstevel@tonic-gate NULL)) == NULL || 829*7c478bd9Sstevel@tonic-gate (t = dup(t)) < 0 || 830*7c478bd9Sstevel@tonic-gate (outchannel = sm_io_open(SmFtStdiofd, 831*7c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 832*7c478bd9Sstevel@tonic-gate (void *) &t, 833*7c478bd9Sstevel@tonic-gate SM_IO_WRONLY_B, 834*7c478bd9Sstevel@tonic-gate NULL)) == NULL) 835*7c478bd9Sstevel@tonic-gate { 836*7c478bd9Sstevel@tonic-gate syserr("cannot open SMTP server channel, fd=%d", 837*7c478bd9Sstevel@tonic-gate t); 838*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 839*7c478bd9Sstevel@tonic-gate } 840*7c478bd9Sstevel@tonic-gate sm_io_automode(inchannel, outchannel); 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate InChannel = inchannel; 843*7c478bd9Sstevel@tonic-gate OutChannel = outchannel; 844*7c478bd9Sstevel@tonic-gate DisConnected = false; 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate #if XLA 847*7c478bd9Sstevel@tonic-gate if (!xla_host_ok(RealHostName)) 848*7c478bd9Sstevel@tonic-gate { 849*7c478bd9Sstevel@tonic-gate message("421 4.4.5 Too many SMTP sessions for this host"); 850*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 851*7c478bd9Sstevel@tonic-gate } 852*7c478bd9Sstevel@tonic-gate #endif /* XLA */ 853*7c478bd9Sstevel@tonic-gate /* find out name for interface of connection */ 854*7c478bd9Sstevel@tonic-gate if (getsockname(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 855*7c478bd9Sstevel@tonic-gate NULL), &sa.sa, &len) == 0) 856*7c478bd9Sstevel@tonic-gate { 857*7c478bd9Sstevel@tonic-gate p = hostnamebyanyaddr(&sa); 858*7c478bd9Sstevel@tonic-gate if (tTd(15, 9)) 859*7c478bd9Sstevel@tonic-gate sm_dprintf("getreq: got name %s\n", p); 860*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 861*7c478bd9Sstevel@tonic-gate macid("{if_name}"), p); 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate /* 864*7c478bd9Sstevel@tonic-gate ** Do this only if it is not the loopback 865*7c478bd9Sstevel@tonic-gate ** interface. 866*7c478bd9Sstevel@tonic-gate */ 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate if (!isloopback(sa)) 869*7c478bd9Sstevel@tonic-gate { 870*7c478bd9Sstevel@tonic-gate char *addr; 871*7c478bd9Sstevel@tonic-gate char family[5]; 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate addr = anynet_ntoa(&sa); 874*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(family, 875*7c478bd9Sstevel@tonic-gate sizeof(family), 876*7c478bd9Sstevel@tonic-gate "%d", sa.sa.sa_family); 877*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 878*7c478bd9Sstevel@tonic-gate A_TEMP, 879*7c478bd9Sstevel@tonic-gate macid("{if_addr}"), addr); 880*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 881*7c478bd9Sstevel@tonic-gate A_TEMP, 882*7c478bd9Sstevel@tonic-gate macid("{if_family}"), family); 883*7c478bd9Sstevel@tonic-gate if (tTd(15, 7)) 884*7c478bd9Sstevel@tonic-gate sm_dprintf("getreq: got addr %s and family %s\n", 885*7c478bd9Sstevel@tonic-gate addr, family); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate else 888*7c478bd9Sstevel@tonic-gate { 889*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 890*7c478bd9Sstevel@tonic-gate A_PERM, 891*7c478bd9Sstevel@tonic-gate macid("{if_addr}"), NULL); 892*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 893*7c478bd9Sstevel@tonic-gate A_PERM, 894*7c478bd9Sstevel@tonic-gate macid("{if_family}"), NULL); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate } 897*7c478bd9Sstevel@tonic-gate else 898*7c478bd9Sstevel@tonic-gate { 899*7c478bd9Sstevel@tonic-gate if (tTd(15, 7)) 900*7c478bd9Sstevel@tonic-gate sm_dprintf("getreq: getsockname failed\n"); 901*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 902*7c478bd9Sstevel@tonic-gate macid("{if_name}"), NULL); 903*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 904*7c478bd9Sstevel@tonic-gate macid("{if_addr}"), NULL); 905*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 906*7c478bd9Sstevel@tonic-gate macid("{if_family}"), NULL); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate break; 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate /* parent -- keep track of children */ 912*7c478bd9Sstevel@tonic-gate if (control) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(status, sizeof status, 915*7c478bd9Sstevel@tonic-gate "control socket server child"); 916*7c478bd9Sstevel@tonic-gate proc_list_add(pid, status, PROC_CONTROL, 0, -1, NULL); 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate else 919*7c478bd9Sstevel@tonic-gate { 920*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(status, sizeof status, 921*7c478bd9Sstevel@tonic-gate "SMTP server child for %s", 922*7c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 923*7c478bd9Sstevel@tonic-gate proc_list_add(pid, status, PROC_DAEMON, 0, -1, 924*7c478bd9Sstevel@tonic-gate &RealHostAddr); 925*7c478bd9Sstevel@tonic-gate } 926*7c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGCHLD); 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate /* close the read end of the synchronization pipe */ 929*7c478bd9Sstevel@tonic-gate if (pipefd[0] != -1) 930*7c478bd9Sstevel@tonic-gate { 931*7c478bd9Sstevel@tonic-gate (void) close(pipefd[0]); 932*7c478bd9Sstevel@tonic-gate pipefd[0] = -1; 933*7c478bd9Sstevel@tonic-gate } 934*7c478bd9Sstevel@tonic-gate 935*7c478bd9Sstevel@tonic-gate /* close the port so that others will hang (for a while) */ 936*7c478bd9Sstevel@tonic-gate (void) close(t); 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate /* release the child by closing the read end of the sync pipe */ 939*7c478bd9Sstevel@tonic-gate if (pipefd[1] != -1) 940*7c478bd9Sstevel@tonic-gate { 941*7c478bd9Sstevel@tonic-gate (void) close(pipefd[1]); 942*7c478bd9Sstevel@tonic-gate pipefd[1] = -1; 943*7c478bd9Sstevel@tonic-gate } 944*7c478bd9Sstevel@tonic-gate } 945*7c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 946*7c478bd9Sstevel@tonic-gate sm_dprintf("getreq: returning\n"); 947*7c478bd9Sstevel@tonic-gate 948*7c478bd9Sstevel@tonic-gate #if MILTER 949*7c478bd9Sstevel@tonic-gate /* set the filters for this daemon */ 950*7c478bd9Sstevel@tonic-gate if (Daemons[curdaemon].d_inputfilterlist != NULL) 951*7c478bd9Sstevel@tonic-gate { 952*7c478bd9Sstevel@tonic-gate for (i = 0; 953*7c478bd9Sstevel@tonic-gate (i < MAXFILTERS && 954*7c478bd9Sstevel@tonic-gate Daemons[curdaemon].d_inputfilters[i] != NULL); 955*7c478bd9Sstevel@tonic-gate i++) 956*7c478bd9Sstevel@tonic-gate { 957*7c478bd9Sstevel@tonic-gate InputFilters[i] = Daemons[curdaemon].d_inputfilters[i]; 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate if (i < MAXFILTERS) 960*7c478bd9Sstevel@tonic-gate InputFilters[i] = NULL; 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate #endif /* MILTER */ 963*7c478bd9Sstevel@tonic-gate return &Daemons[curdaemon].d_flags; 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate /* 967*7c478bd9Sstevel@tonic-gate ** GETREQUESTS_CHECKDISKSPACE -- check available diskspace. 968*7c478bd9Sstevel@tonic-gate ** 969*7c478bd9Sstevel@tonic-gate ** Parameters: 970*7c478bd9Sstevel@tonic-gate ** e -- envelope. 971*7c478bd9Sstevel@tonic-gate ** 972*7c478bd9Sstevel@tonic-gate ** Returns: 973*7c478bd9Sstevel@tonic-gate ** none. 974*7c478bd9Sstevel@tonic-gate ** 975*7c478bd9Sstevel@tonic-gate ** Side Effects: 976*7c478bd9Sstevel@tonic-gate ** Modifies Daemon flags (D_ETRNONLY) if not enough disk space. 977*7c478bd9Sstevel@tonic-gate */ 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate static void 980*7c478bd9Sstevel@tonic-gate getrequests_checkdiskspace(e) 981*7c478bd9Sstevel@tonic-gate ENVELOPE *e; 982*7c478bd9Sstevel@tonic-gate { 983*7c478bd9Sstevel@tonic-gate bool logged = false; 984*7c478bd9Sstevel@tonic-gate int idx; 985*7c478bd9Sstevel@tonic-gate time_t now; 986*7c478bd9Sstevel@tonic-gate 987*7c478bd9Sstevel@tonic-gate now = curtime(); 988*7c478bd9Sstevel@tonic-gate if (now < NextDiskSpaceCheck) 989*7c478bd9Sstevel@tonic-gate return; 990*7c478bd9Sstevel@tonic-gate 991*7c478bd9Sstevel@tonic-gate /* Check if there is available disk space in all queue groups. */ 992*7c478bd9Sstevel@tonic-gate if (!enoughdiskspace(0, NULL)) 993*7c478bd9Sstevel@tonic-gate { 994*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; ++idx) 995*7c478bd9Sstevel@tonic-gate { 996*7c478bd9Sstevel@tonic-gate if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 997*7c478bd9Sstevel@tonic-gate continue; 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* log only if not logged before */ 1000*7c478bd9Sstevel@tonic-gate if (!logged) 1001*7c478bd9Sstevel@tonic-gate { 1002*7c478bd9Sstevel@tonic-gate if (LogLevel > 8) 1003*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 1004*7c478bd9Sstevel@tonic-gate "rejecting new messages: min free: %ld", 1005*7c478bd9Sstevel@tonic-gate MinBlocksFree); 1006*7c478bd9Sstevel@tonic-gate sm_setproctitle(true, e, 1007*7c478bd9Sstevel@tonic-gate "rejecting new messages: min free: %ld", 1008*7c478bd9Sstevel@tonic-gate MinBlocksFree); 1009*7c478bd9Sstevel@tonic-gate logged = true; 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate setbitn(D_ETRNONLY, Daemons[idx].d_flags); 1012*7c478bd9Sstevel@tonic-gate } 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate else 1015*7c478bd9Sstevel@tonic-gate { 1016*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; ++idx) 1017*7c478bd9Sstevel@tonic-gate { 1018*7c478bd9Sstevel@tonic-gate if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) 1019*7c478bd9Sstevel@tonic-gate continue; 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate /* log only if not logged before */ 1022*7c478bd9Sstevel@tonic-gate if (!logged) 1023*7c478bd9Sstevel@tonic-gate { 1024*7c478bd9Sstevel@tonic-gate if (LogLevel > 8) 1025*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 1026*7c478bd9Sstevel@tonic-gate "accepting new messages (again)"); 1027*7c478bd9Sstevel@tonic-gate logged = true; 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate /* title will be set later */ 1031*7c478bd9Sstevel@tonic-gate clrbitn(D_ETRNONLY, Daemons[idx].d_flags); 1032*7c478bd9Sstevel@tonic-gate } 1033*7c478bd9Sstevel@tonic-gate } 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate /* only check disk space once a minute */ 1036*7c478bd9Sstevel@tonic-gate NextDiskSpaceCheck = now + 60; 1037*7c478bd9Sstevel@tonic-gate } 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate /* 1040*7c478bd9Sstevel@tonic-gate ** OPENDAEMONSOCKET -- open SMTP socket 1041*7c478bd9Sstevel@tonic-gate ** 1042*7c478bd9Sstevel@tonic-gate ** Deals with setting all appropriate options. 1043*7c478bd9Sstevel@tonic-gate ** 1044*7c478bd9Sstevel@tonic-gate ** Parameters: 1045*7c478bd9Sstevel@tonic-gate ** d -- the structure for the daemon to open. 1046*7c478bd9Sstevel@tonic-gate ** firsttime -- set if this is the initial open. 1047*7c478bd9Sstevel@tonic-gate ** 1048*7c478bd9Sstevel@tonic-gate ** Returns: 1049*7c478bd9Sstevel@tonic-gate ** Size in bytes of the daemon socket addr. 1050*7c478bd9Sstevel@tonic-gate ** 1051*7c478bd9Sstevel@tonic-gate ** Side Effects: 1052*7c478bd9Sstevel@tonic-gate ** Leaves DaemonSocket set to the open socket. 1053*7c478bd9Sstevel@tonic-gate ** Exits if the socket cannot be created. 1054*7c478bd9Sstevel@tonic-gate */ 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate #define MAXOPENTRIES 10 /* maximum number of tries to open connection */ 1057*7c478bd9Sstevel@tonic-gate 1058*7c478bd9Sstevel@tonic-gate static int 1059*7c478bd9Sstevel@tonic-gate opendaemonsocket(d, firsttime) 1060*7c478bd9Sstevel@tonic-gate DAEMON_T *d; 1061*7c478bd9Sstevel@tonic-gate bool firsttime; 1062*7c478bd9Sstevel@tonic-gate { 1063*7c478bd9Sstevel@tonic-gate int on = 1; 1064*7c478bd9Sstevel@tonic-gate int fdflags; 1065*7c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T socksize = 0; 1066*7c478bd9Sstevel@tonic-gate int ntries = 0; 1067*7c478bd9Sstevel@tonic-gate int save_errno; 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate if (tTd(15, 2)) 1070*7c478bd9Sstevel@tonic-gate sm_dprintf("opendaemonsocket(%s)\n", d->d_name); 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate do 1073*7c478bd9Sstevel@tonic-gate { 1074*7c478bd9Sstevel@tonic-gate if (ntries > 0) 1075*7c478bd9Sstevel@tonic-gate (void) sleep(5); 1076*7c478bd9Sstevel@tonic-gate if (firsttime || d->d_socket < 0) 1077*7c478bd9Sstevel@tonic-gate { 1078*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 1079*7c478bd9Sstevel@tonic-gate # if NETUNIX 1080*7c478bd9Sstevel@tonic-gate if (d->d_addr.sa.sa_family == AF_UNIX) 1081*7c478bd9Sstevel@tonic-gate { 1082*7c478bd9Sstevel@tonic-gate int rval; 1083*7c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK|SFF_CREAT; 1084*7c478bd9Sstevel@tonic-gate 1085*7c478bd9Sstevel@tonic-gate /* if not safe, don't use it */ 1086*7c478bd9Sstevel@tonic-gate rval = safefile(d->d_addr.sunix.sun_path, 1087*7c478bd9Sstevel@tonic-gate RunAsUid, RunAsGid, 1088*7c478bd9Sstevel@tonic-gate RunAsUserName, sff, 1089*7c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 1090*7c478bd9Sstevel@tonic-gate if (rval != 0) 1091*7c478bd9Sstevel@tonic-gate { 1092*7c478bd9Sstevel@tonic-gate save_errno = errno; 1093*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: unsafe domain socket %s", 1094*7c478bd9Sstevel@tonic-gate d->d_name, 1095*7c478bd9Sstevel@tonic-gate d->d_addr.sunix.sun_path); 1096*7c478bd9Sstevel@tonic-gate goto fail; 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /* Don't try to overtake an existing socket */ 1100*7c478bd9Sstevel@tonic-gate (void) unlink(d->d_addr.sunix.sun_path); 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1103*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DOMAIN_NETUNIX */ 1104*7c478bd9Sstevel@tonic-gate d->d_socket = socket(d->d_addr.sa.sa_family, 1105*7c478bd9Sstevel@tonic-gate SOCK_STREAM, 0); 1106*7c478bd9Sstevel@tonic-gate if (d->d_socket < 0) 1107*7c478bd9Sstevel@tonic-gate { 1108*7c478bd9Sstevel@tonic-gate save_errno = errno; 1109*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", 1110*7c478bd9Sstevel@tonic-gate d->d_name); 1111*7c478bd9Sstevel@tonic-gate fail: 1112*7c478bd9Sstevel@tonic-gate if (bitnset(D_OPTIONAL, d->d_flags) && 1113*7c478bd9Sstevel@tonic-gate (!transienterror(save_errno) || 1114*7c478bd9Sstevel@tonic-gate ntries >= MAXOPENTRIES - 1)) 1115*7c478bd9Sstevel@tonic-gate { 1116*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: optional socket disabled", 1117*7c478bd9Sstevel@tonic-gate d->d_name); 1118*7c478bd9Sstevel@tonic-gate setbitn(D_DISABLE, d->d_flags); 1119*7c478bd9Sstevel@tonic-gate d->d_socket = -1; 1120*7c478bd9Sstevel@tonic-gate return -1; 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate severe: 1123*7c478bd9Sstevel@tonic-gate if (LogLevel > 0) 1124*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 1125*7c478bd9Sstevel@tonic-gate "daemon %s: problem creating SMTP socket", 1126*7c478bd9Sstevel@tonic-gate d->d_name); 1127*7c478bd9Sstevel@tonic-gate d->d_socket = -1; 1128*7c478bd9Sstevel@tonic-gate continue; 1129*7c478bd9Sstevel@tonic-gate } 1130*7c478bd9Sstevel@tonic-gate 1131*7c478bd9Sstevel@tonic-gate if (SM_FD_SETSIZE > 0 && d->d_socket >= SM_FD_SETSIZE) 1132*7c478bd9Sstevel@tonic-gate { 1133*7c478bd9Sstevel@tonic-gate save_errno = EINVAL; 1134*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: server SMTP socket (%d) too large", 1135*7c478bd9Sstevel@tonic-gate d->d_name, d->d_socket); 1136*7c478bd9Sstevel@tonic-gate goto fail; 1137*7c478bd9Sstevel@tonic-gate } 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate /* turn on network debugging? */ 1140*7c478bd9Sstevel@tonic-gate if (tTd(15, 101)) 1141*7c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1142*7c478bd9Sstevel@tonic-gate SO_DEBUG, (char *)&on, 1143*7c478bd9Sstevel@tonic-gate sizeof on); 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1146*7c478bd9Sstevel@tonic-gate SO_REUSEADDR, (char *)&on, sizeof on); 1147*7c478bd9Sstevel@tonic-gate (void) setsockopt(d->d_socket, SOL_SOCKET, 1148*7c478bd9Sstevel@tonic-gate SO_KEEPALIVE, (char *)&on, sizeof on); 1149*7c478bd9Sstevel@tonic-gate 1150*7c478bd9Sstevel@tonic-gate #ifdef SO_RCVBUF 1151*7c478bd9Sstevel@tonic-gate if (d->d_tcprcvbufsize > 0) 1152*7c478bd9Sstevel@tonic-gate { 1153*7c478bd9Sstevel@tonic-gate if (setsockopt(d->d_socket, SOL_SOCKET, 1154*7c478bd9Sstevel@tonic-gate SO_RCVBUF, 1155*7c478bd9Sstevel@tonic-gate (char *) &d->d_tcprcvbufsize, 1156*7c478bd9Sstevel@tonic-gate sizeof(d->d_tcprcvbufsize)) < 0) 1157*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate #endif /* SO_RCVBUF */ 1160*7c478bd9Sstevel@tonic-gate #ifdef SO_SNDBUF 1161*7c478bd9Sstevel@tonic-gate if (d->d_tcpsndbufsize > 0) 1162*7c478bd9Sstevel@tonic-gate { 1163*7c478bd9Sstevel@tonic-gate if (setsockopt(d->d_socket, SOL_SOCKET, 1164*7c478bd9Sstevel@tonic-gate SO_SNDBUF, 1165*7c478bd9Sstevel@tonic-gate (char *) &d->d_tcpsndbufsize, 1166*7c478bd9Sstevel@tonic-gate sizeof(d->d_tcpsndbufsize)) < 0) 1167*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate #endif /* SO_SNDBUF */ 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || 1172*7c478bd9Sstevel@tonic-gate fcntl(d->d_socket, F_SETFD, 1173*7c478bd9Sstevel@tonic-gate fdflags | FD_CLOEXEC) == -1) 1174*7c478bd9Sstevel@tonic-gate { 1175*7c478bd9Sstevel@tonic-gate save_errno = errno; 1176*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", 1177*7c478bd9Sstevel@tonic-gate d->d_name, 1178*7c478bd9Sstevel@tonic-gate fdflags == -1 ? "get" : "set", 1179*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 1180*7c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 1181*7c478bd9Sstevel@tonic-gate goto severe; 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 1185*7c478bd9Sstevel@tonic-gate { 1186*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 1187*7c478bd9Sstevel@tonic-gate # ifdef NETUNIX 1188*7c478bd9Sstevel@tonic-gate case AF_UNIX: 1189*7c478bd9Sstevel@tonic-gate socksize = sizeof d->d_addr.sunix; 1190*7c478bd9Sstevel@tonic-gate break; 1191*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1192*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 1193*7c478bd9Sstevel@tonic-gate #if NETINET 1194*7c478bd9Sstevel@tonic-gate case AF_INET: 1195*7c478bd9Sstevel@tonic-gate socksize = sizeof d->d_addr.sin; 1196*7c478bd9Sstevel@tonic-gate break; 1197*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate #if NETINET6 1200*7c478bd9Sstevel@tonic-gate case AF_INET6: 1201*7c478bd9Sstevel@tonic-gate socksize = sizeof d->d_addr.sin6; 1202*7c478bd9Sstevel@tonic-gate break; 1203*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate #if NETISO 1206*7c478bd9Sstevel@tonic-gate case AF_ISO: 1207*7c478bd9Sstevel@tonic-gate socksize = sizeof d->d_addr.siso; 1208*7c478bd9Sstevel@tonic-gate break; 1209*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate default: 1212*7c478bd9Sstevel@tonic-gate socksize = sizeof d->d_addr; 1213*7c478bd9Sstevel@tonic-gate break; 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) 1217*7c478bd9Sstevel@tonic-gate { 1218*7c478bd9Sstevel@tonic-gate /* probably another daemon already */ 1219*7c478bd9Sstevel@tonic-gate save_errno = errno; 1220*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: cannot bind", 1221*7c478bd9Sstevel@tonic-gate d->d_name); 1222*7c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 1223*7c478bd9Sstevel@tonic-gate goto fail; 1224*7c478bd9Sstevel@tonic-gate } 1225*7c478bd9Sstevel@tonic-gate } 1226*7c478bd9Sstevel@tonic-gate if (!firsttime && 1227*7c478bd9Sstevel@tonic-gate listen(d->d_socket, d->d_listenqueue) < 0) 1228*7c478bd9Sstevel@tonic-gate { 1229*7c478bd9Sstevel@tonic-gate save_errno = errno; 1230*7c478bd9Sstevel@tonic-gate syserr("opendaemonsocket: daemon %s: cannot listen", 1231*7c478bd9Sstevel@tonic-gate d->d_name); 1232*7c478bd9Sstevel@tonic-gate (void) close(d->d_socket); 1233*7c478bd9Sstevel@tonic-gate goto severe; 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate return socksize; 1236*7c478bd9Sstevel@tonic-gate } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); 1237*7c478bd9Sstevel@tonic-gate syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", 1238*7c478bd9Sstevel@tonic-gate d->d_name); 1239*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1240*7c478bd9Sstevel@tonic-gate return -1; /* avoid compiler warning on IRIX */ 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate /* 1243*7c478bd9Sstevel@tonic-gate ** SETUPDAEMON -- setup socket for daemon 1244*7c478bd9Sstevel@tonic-gate ** 1245*7c478bd9Sstevel@tonic-gate ** Parameters: 1246*7c478bd9Sstevel@tonic-gate ** daemonaddr -- socket for daemon 1247*7c478bd9Sstevel@tonic-gate ** 1248*7c478bd9Sstevel@tonic-gate ** Returns: 1249*7c478bd9Sstevel@tonic-gate ** port number on which daemon should run 1250*7c478bd9Sstevel@tonic-gate ** 1251*7c478bd9Sstevel@tonic-gate */ 1252*7c478bd9Sstevel@tonic-gate 1253*7c478bd9Sstevel@tonic-gate static unsigned short 1254*7c478bd9Sstevel@tonic-gate setupdaemon(daemonaddr) 1255*7c478bd9Sstevel@tonic-gate SOCKADDR *daemonaddr; 1256*7c478bd9Sstevel@tonic-gate { 1257*7c478bd9Sstevel@tonic-gate unsigned short port; 1258*7c478bd9Sstevel@tonic-gate 1259*7c478bd9Sstevel@tonic-gate /* 1260*7c478bd9Sstevel@tonic-gate ** Set up the address for the mailer. 1261*7c478bd9Sstevel@tonic-gate */ 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate if (daemonaddr->sa.sa_family == AF_UNSPEC) 1264*7c478bd9Sstevel@tonic-gate { 1265*7c478bd9Sstevel@tonic-gate memset(daemonaddr, '\0', sizeof *daemonaddr); 1266*7c478bd9Sstevel@tonic-gate #if NETINET 1267*7c478bd9Sstevel@tonic-gate daemonaddr->sa.sa_family = AF_INET; 1268*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1269*7c478bd9Sstevel@tonic-gate } 1270*7c478bd9Sstevel@tonic-gate 1271*7c478bd9Sstevel@tonic-gate switch (daemonaddr->sa.sa_family) 1272*7c478bd9Sstevel@tonic-gate { 1273*7c478bd9Sstevel@tonic-gate #if NETINET 1274*7c478bd9Sstevel@tonic-gate case AF_INET: 1275*7c478bd9Sstevel@tonic-gate if (daemonaddr->sin.sin_addr.s_addr == 0) 1276*7c478bd9Sstevel@tonic-gate daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; 1277*7c478bd9Sstevel@tonic-gate port = daemonaddr->sin.sin_port; 1278*7c478bd9Sstevel@tonic-gate break; 1279*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate #if NETINET6 1282*7c478bd9Sstevel@tonic-gate case AF_INET6: 1283*7c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) 1284*7c478bd9Sstevel@tonic-gate daemonaddr->sin6.sin6_addr = in6addr_any; 1285*7c478bd9Sstevel@tonic-gate port = daemonaddr->sin6.sin6_port; 1286*7c478bd9Sstevel@tonic-gate break; 1287*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1288*7c478bd9Sstevel@tonic-gate 1289*7c478bd9Sstevel@tonic-gate default: 1290*7c478bd9Sstevel@tonic-gate /* unknown protocol */ 1291*7c478bd9Sstevel@tonic-gate port = 0; 1292*7c478bd9Sstevel@tonic-gate break; 1293*7c478bd9Sstevel@tonic-gate } 1294*7c478bd9Sstevel@tonic-gate if (port == 0) 1295*7c478bd9Sstevel@tonic-gate { 1296*7c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 1297*7c478bd9Sstevel@tonic-gate port = htons(25); 1298*7c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 1299*7c478bd9Sstevel@tonic-gate { 1300*7c478bd9Sstevel@tonic-gate register struct servent *sp; 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate sp = getservbyname("smtp", "tcp"); 1303*7c478bd9Sstevel@tonic-gate if (sp == NULL) 1304*7c478bd9Sstevel@tonic-gate { 1305*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"smtp\" unknown"); 1306*7c478bd9Sstevel@tonic-gate port = htons(25); 1307*7c478bd9Sstevel@tonic-gate } 1308*7c478bd9Sstevel@tonic-gate else 1309*7c478bd9Sstevel@tonic-gate port = sp->s_port; 1310*7c478bd9Sstevel@tonic-gate } 1311*7c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 1312*7c478bd9Sstevel@tonic-gate } 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate switch (daemonaddr->sa.sa_family) 1315*7c478bd9Sstevel@tonic-gate { 1316*7c478bd9Sstevel@tonic-gate #if NETINET 1317*7c478bd9Sstevel@tonic-gate case AF_INET: 1318*7c478bd9Sstevel@tonic-gate daemonaddr->sin.sin_port = port; 1319*7c478bd9Sstevel@tonic-gate break; 1320*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1321*7c478bd9Sstevel@tonic-gate 1322*7c478bd9Sstevel@tonic-gate #if NETINET6 1323*7c478bd9Sstevel@tonic-gate case AF_INET6: 1324*7c478bd9Sstevel@tonic-gate daemonaddr->sin6.sin6_port = port; 1325*7c478bd9Sstevel@tonic-gate break; 1326*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate default: 1329*7c478bd9Sstevel@tonic-gate /* unknown protocol */ 1330*7c478bd9Sstevel@tonic-gate break; 1331*7c478bd9Sstevel@tonic-gate } 1332*7c478bd9Sstevel@tonic-gate return port; 1333*7c478bd9Sstevel@tonic-gate } 1334*7c478bd9Sstevel@tonic-gate /* 1335*7c478bd9Sstevel@tonic-gate ** CLRDAEMON -- reset the daemon connection 1336*7c478bd9Sstevel@tonic-gate ** 1337*7c478bd9Sstevel@tonic-gate ** Parameters: 1338*7c478bd9Sstevel@tonic-gate ** none. 1339*7c478bd9Sstevel@tonic-gate ** 1340*7c478bd9Sstevel@tonic-gate ** Returns: 1341*7c478bd9Sstevel@tonic-gate ** none. 1342*7c478bd9Sstevel@tonic-gate ** 1343*7c478bd9Sstevel@tonic-gate ** Side Effects: 1344*7c478bd9Sstevel@tonic-gate ** releases any resources used by the passive daemon. 1345*7c478bd9Sstevel@tonic-gate */ 1346*7c478bd9Sstevel@tonic-gate 1347*7c478bd9Sstevel@tonic-gate void 1348*7c478bd9Sstevel@tonic-gate clrdaemon() 1349*7c478bd9Sstevel@tonic-gate { 1350*7c478bd9Sstevel@tonic-gate int i; 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 1353*7c478bd9Sstevel@tonic-gate { 1354*7c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 1355*7c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 1356*7c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate /* 1361*7c478bd9Sstevel@tonic-gate ** GETMODIFIERS -- get modifier flags 1362*7c478bd9Sstevel@tonic-gate ** 1363*7c478bd9Sstevel@tonic-gate ** Parameters: 1364*7c478bd9Sstevel@tonic-gate ** v -- the modifiers (input text line). 1365*7c478bd9Sstevel@tonic-gate ** modifiers -- pointer to flag field to represent modifiers. 1366*7c478bd9Sstevel@tonic-gate ** 1367*7c478bd9Sstevel@tonic-gate ** Returns: 1368*7c478bd9Sstevel@tonic-gate ** (xallocat()ed) string representation of modifiers. 1369*7c478bd9Sstevel@tonic-gate ** 1370*7c478bd9Sstevel@tonic-gate ** Side Effects: 1371*7c478bd9Sstevel@tonic-gate ** fills in modifiers. 1372*7c478bd9Sstevel@tonic-gate */ 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate char * 1375*7c478bd9Sstevel@tonic-gate getmodifiers(v, modifiers) 1376*7c478bd9Sstevel@tonic-gate char *v; 1377*7c478bd9Sstevel@tonic-gate BITMAP256 modifiers; 1378*7c478bd9Sstevel@tonic-gate { 1379*7c478bd9Sstevel@tonic-gate int l; 1380*7c478bd9Sstevel@tonic-gate char *h, *f, *flags; 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate /* maximum length of flags: upper case Option -> "OO " */ 1383*7c478bd9Sstevel@tonic-gate l = 3 * strlen(v) + 3; 1384*7c478bd9Sstevel@tonic-gate 1385*7c478bd9Sstevel@tonic-gate /* is someone joking? */ 1386*7c478bd9Sstevel@tonic-gate if (l < 0 || l > 256) 1387*7c478bd9Sstevel@tonic-gate { 1388*7c478bd9Sstevel@tonic-gate if (LogLevel > 2) 1389*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 1390*7c478bd9Sstevel@tonic-gate "getmodifiers too long, ignored"); 1391*7c478bd9Sstevel@tonic-gate return NULL; 1392*7c478bd9Sstevel@tonic-gate } 1393*7c478bd9Sstevel@tonic-gate flags = xalloc(l); 1394*7c478bd9Sstevel@tonic-gate f = flags; 1395*7c478bd9Sstevel@tonic-gate clrbitmap(modifiers); 1396*7c478bd9Sstevel@tonic-gate for (h = v; *h != '\0'; h++) 1397*7c478bd9Sstevel@tonic-gate { 1398*7c478bd9Sstevel@tonic-gate if (isascii(*h) && !isspace(*h) && isprint(*h)) 1399*7c478bd9Sstevel@tonic-gate { 1400*7c478bd9Sstevel@tonic-gate setbitn(*h, modifiers); 1401*7c478bd9Sstevel@tonic-gate if (flags != f) 1402*7c478bd9Sstevel@tonic-gate *flags++ = ' '; 1403*7c478bd9Sstevel@tonic-gate *flags++ = *h; 1404*7c478bd9Sstevel@tonic-gate if (isupper(*h)) 1405*7c478bd9Sstevel@tonic-gate *flags++ = *h; 1406*7c478bd9Sstevel@tonic-gate } 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate *flags++ = '\0'; 1409*7c478bd9Sstevel@tonic-gate return f; 1410*7c478bd9Sstevel@tonic-gate } 1411*7c478bd9Sstevel@tonic-gate 1412*7c478bd9Sstevel@tonic-gate /* 1413*7c478bd9Sstevel@tonic-gate ** CHKDAEMONMODIFIERS -- check whether all daemons have set a flag. 1414*7c478bd9Sstevel@tonic-gate ** 1415*7c478bd9Sstevel@tonic-gate ** Parameters: 1416*7c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 1417*7c478bd9Sstevel@tonic-gate ** 1418*7c478bd9Sstevel@tonic-gate ** Returns: 1419*7c478bd9Sstevel@tonic-gate ** true iff all daemons have set flag. 1420*7c478bd9Sstevel@tonic-gate */ 1421*7c478bd9Sstevel@tonic-gate 1422*7c478bd9Sstevel@tonic-gate bool 1423*7c478bd9Sstevel@tonic-gate chkdaemonmodifiers(flag) 1424*7c478bd9Sstevel@tonic-gate int flag; 1425*7c478bd9Sstevel@tonic-gate { 1426*7c478bd9Sstevel@tonic-gate int i; 1427*7c478bd9Sstevel@tonic-gate 1428*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 1429*7c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, Daemons[i].d_flags)) 1430*7c478bd9Sstevel@tonic-gate return false; 1431*7c478bd9Sstevel@tonic-gate return true; 1432*7c478bd9Sstevel@tonic-gate } 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate /* 1435*7c478bd9Sstevel@tonic-gate ** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) 1436*7c478bd9Sstevel@tonic-gate ** 1437*7c478bd9Sstevel@tonic-gate ** Parameters: 1438*7c478bd9Sstevel@tonic-gate ** p -- the options line. 1439*7c478bd9Sstevel@tonic-gate ** d -- the daemon structure to fill in. 1440*7c478bd9Sstevel@tonic-gate ** 1441*7c478bd9Sstevel@tonic-gate ** Returns: 1442*7c478bd9Sstevel@tonic-gate ** none. 1443*7c478bd9Sstevel@tonic-gate */ 1444*7c478bd9Sstevel@tonic-gate 1445*7c478bd9Sstevel@tonic-gate static void 1446*7c478bd9Sstevel@tonic-gate setsockaddroptions(p, d) 1447*7c478bd9Sstevel@tonic-gate char *p; 1448*7c478bd9Sstevel@tonic-gate DAEMON_T *d; 1449*7c478bd9Sstevel@tonic-gate { 1450*7c478bd9Sstevel@tonic-gate #if NETISO 1451*7c478bd9Sstevel@tonic-gate short portno; 1452*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 1453*7c478bd9Sstevel@tonic-gate char *port = NULL; 1454*7c478bd9Sstevel@tonic-gate char *addr = NULL; 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate #if NETINET 1457*7c478bd9Sstevel@tonic-gate if (d->d_addr.sa.sa_family == AF_UNSPEC) 1458*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 1459*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1460*7c478bd9Sstevel@tonic-gate 1461*7c478bd9Sstevel@tonic-gate while (p != NULL) 1462*7c478bd9Sstevel@tonic-gate { 1463*7c478bd9Sstevel@tonic-gate register char *f; 1464*7c478bd9Sstevel@tonic-gate register char *v; 1465*7c478bd9Sstevel@tonic-gate 1466*7c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 1467*7c478bd9Sstevel@tonic-gate p++; 1468*7c478bd9Sstevel@tonic-gate if (*p == '\0') 1469*7c478bd9Sstevel@tonic-gate break; 1470*7c478bd9Sstevel@tonic-gate f = p; 1471*7c478bd9Sstevel@tonic-gate p = strchr(p, ','); 1472*7c478bd9Sstevel@tonic-gate if (p != NULL) 1473*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 1474*7c478bd9Sstevel@tonic-gate v = strchr(f, '='); 1475*7c478bd9Sstevel@tonic-gate if (v == NULL) 1476*7c478bd9Sstevel@tonic-gate continue; 1477*7c478bd9Sstevel@tonic-gate while (isascii(*++v) && isspace(*v)) 1478*7c478bd9Sstevel@tonic-gate continue; 1479*7c478bd9Sstevel@tonic-gate if (isascii(*f) && islower(*f)) 1480*7c478bd9Sstevel@tonic-gate *f = toupper(*f); 1481*7c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 1482*7c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_NOTSET; 1483*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 1484*7c478bd9Sstevel@tonic-gate #if _FFR_DM_PER_DAEMON 1485*7c478bd9Sstevel@tonic-gate d->d_dm = DM_NOTSET; 1486*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DM_PER_DAEMON */ 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate switch (*f) 1489*7c478bd9Sstevel@tonic-gate { 1490*7c478bd9Sstevel@tonic-gate case 'A': /* address */ 1491*7c478bd9Sstevel@tonic-gate addr = v; 1492*7c478bd9Sstevel@tonic-gate break; 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate #if _FFR_DM_PER_DAEMON 1495*7c478bd9Sstevel@tonic-gate case 'D': /* DeliveryMode */ 1496*7c478bd9Sstevel@tonic-gate switch (*v) 1497*7c478bd9Sstevel@tonic-gate { 1498*7c478bd9Sstevel@tonic-gate case SM_QUEUE: 1499*7c478bd9Sstevel@tonic-gate case SM_DEFER: 1500*7c478bd9Sstevel@tonic-gate case SM_DELIVER: 1501*7c478bd9Sstevel@tonic-gate case SM_FORK: 1502*7c478bd9Sstevel@tonic-gate d->d_dm = *v; 1503*7c478bd9Sstevel@tonic-gate break; 1504*7c478bd9Sstevel@tonic-gate default: 1505*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown delivery mode %c", 1506*7c478bd9Sstevel@tonic-gate *v); 1507*7c478bd9Sstevel@tonic-gate break; 1508*7c478bd9Sstevel@tonic-gate } 1509*7c478bd9Sstevel@tonic-gate break; 1510*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DM_PER_DAEMON */ 1511*7c478bd9Sstevel@tonic-gate 1512*7c478bd9Sstevel@tonic-gate case 'F': /* address family */ 1513*7c478bd9Sstevel@tonic-gate if (isascii(*v) && isdigit(*v)) 1514*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = atoi(v); 1515*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 1516*7c478bd9Sstevel@tonic-gate # ifdef NETUNIX 1517*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "unix") == 0 || 1518*7c478bd9Sstevel@tonic-gate sm_strcasecmp(v, "local") == 0) 1519*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_UNIX; 1520*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1521*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 1522*7c478bd9Sstevel@tonic-gate #if NETINET 1523*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet") == 0) 1524*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET; 1525*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1526*7c478bd9Sstevel@tonic-gate #if NETINET6 1527*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "inet6") == 0) 1528*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_INET6; 1529*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1530*7c478bd9Sstevel@tonic-gate #if NETISO 1531*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "iso") == 0) 1532*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_ISO; 1533*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 1534*7c478bd9Sstevel@tonic-gate #if NETNS 1535*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "ns") == 0) 1536*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_NS; 1537*7c478bd9Sstevel@tonic-gate #endif /* NETNS */ 1538*7c478bd9Sstevel@tonic-gate #if NETX25 1539*7c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(v, "x.25") == 0) 1540*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family = AF_CCITT; 1541*7c478bd9Sstevel@tonic-gate #endif /* NETX25 */ 1542*7c478bd9Sstevel@tonic-gate else 1543*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Unknown address family %s in Family=option", 1544*7c478bd9Sstevel@tonic-gate v); 1545*7c478bd9Sstevel@tonic-gate break; 1546*7c478bd9Sstevel@tonic-gate 1547*7c478bd9Sstevel@tonic-gate #if MILTER 1548*7c478bd9Sstevel@tonic-gate case 'I': 1549*7c478bd9Sstevel@tonic-gate d->d_inputfilterlist = v; 1550*7c478bd9Sstevel@tonic-gate break; 1551*7c478bd9Sstevel@tonic-gate #endif /* MILTER */ 1552*7c478bd9Sstevel@tonic-gate 1553*7c478bd9Sstevel@tonic-gate case 'L': /* listen queue size */ 1554*7c478bd9Sstevel@tonic-gate d->d_listenqueue = atoi(v); 1555*7c478bd9Sstevel@tonic-gate break; 1556*7c478bd9Sstevel@tonic-gate 1557*7c478bd9Sstevel@tonic-gate case 'M': /* modifiers (flags) */ 1558*7c478bd9Sstevel@tonic-gate d->d_mflags = getmodifiers(v, d->d_flags); 1559*7c478bd9Sstevel@tonic-gate break; 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate case 'N': /* name */ 1562*7c478bd9Sstevel@tonic-gate d->d_name = v; 1563*7c478bd9Sstevel@tonic-gate break; 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate case 'P': /* port */ 1566*7c478bd9Sstevel@tonic-gate port = v; 1567*7c478bd9Sstevel@tonic-gate break; 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate case 'R': /* receive buffer size */ 1570*7c478bd9Sstevel@tonic-gate d->d_tcprcvbufsize = atoi(v); 1571*7c478bd9Sstevel@tonic-gate break; 1572*7c478bd9Sstevel@tonic-gate 1573*7c478bd9Sstevel@tonic-gate case 'S': /* send buffer size */ 1574*7c478bd9Sstevel@tonic-gate d->d_tcpsndbufsize = atoi(v); 1575*7c478bd9Sstevel@tonic-gate break; 1576*7c478bd9Sstevel@tonic-gate 1577*7c478bd9Sstevel@tonic-gate #if _FFR_SS_PER_DAEMON 1578*7c478bd9Sstevel@tonic-gate case 'T': /* SuperSafe */ 1579*7c478bd9Sstevel@tonic-gate if (tolower(*v) == 'i') 1580*7c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_INTERACTIVE; 1581*7c478bd9Sstevel@tonic-gate else if (tolower(*v) == 'p') 1582*7c478bd9Sstevel@tonic-gate # if MILTER 1583*7c478bd9Sstevel@tonic-gate d->d_supersafe = SAFE_REALLY_POSTMILTER; 1584*7c478bd9Sstevel@tonic-gate # else /* MILTER */ 1585*7c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 1586*7c478bd9Sstevel@tonic-gate "Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n"); 1587*7c478bd9Sstevel@tonic-gate # endif /* MILTER */ 1588*7c478bd9Sstevel@tonic-gate else 1589*7c478bd9Sstevel@tonic-gate d->d_supersafe = atobool(v) ? SAFE_REALLY 1590*7c478bd9Sstevel@tonic-gate : SAFE_NO; 1591*7c478bd9Sstevel@tonic-gate break; 1592*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SS_PER_DAEMON */ 1593*7c478bd9Sstevel@tonic-gate 1594*7c478bd9Sstevel@tonic-gate default: 1595*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", 1596*7c478bd9Sstevel@tonic-gate f); 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate } 1599*7c478bd9Sstevel@tonic-gate 1600*7c478bd9Sstevel@tonic-gate /* Check addr and port after finding family */ 1601*7c478bd9Sstevel@tonic-gate if (addr != NULL) 1602*7c478bd9Sstevel@tonic-gate { 1603*7c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 1604*7c478bd9Sstevel@tonic-gate { 1605*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 1606*7c478bd9Sstevel@tonic-gate # if NETUNIX 1607*7c478bd9Sstevel@tonic-gate case AF_UNIX: 1608*7c478bd9Sstevel@tonic-gate if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path)) 1609*7c478bd9Sstevel@tonic-gate { 1610*7c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 1611*7c478bd9Sstevel@tonic-gate syserr("setsockaddroptions: domain socket name too long: %s > %d", 1612*7c478bd9Sstevel@tonic-gate addr, sizeof(d->d_addr.sunix.sun_path)); 1613*7c478bd9Sstevel@tonic-gate break; 1614*7c478bd9Sstevel@tonic-gate } 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate /* file safety check done in opendaemonsocket() */ 1617*7c478bd9Sstevel@tonic-gate (void) memset(&d->d_addr.sunix.sun_path, '\0', 1618*7c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 1619*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path, 1620*7c478bd9Sstevel@tonic-gate addr, 1621*7c478bd9Sstevel@tonic-gate sizeof(d->d_addr.sunix.sun_path)); 1622*7c478bd9Sstevel@tonic-gate break; 1623*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1624*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 1625*7c478bd9Sstevel@tonic-gate #if NETINET 1626*7c478bd9Sstevel@tonic-gate case AF_INET: 1627*7c478bd9Sstevel@tonic-gate if (!isascii(*addr) || !isdigit(*addr) || 1628*7c478bd9Sstevel@tonic-gate ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) 1629*7c478bd9Sstevel@tonic-gate == INADDR_NONE)) 1630*7c478bd9Sstevel@tonic-gate { 1631*7c478bd9Sstevel@tonic-gate register struct hostent *hp; 1632*7c478bd9Sstevel@tonic-gate 1633*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET); 1634*7c478bd9Sstevel@tonic-gate if (hp == NULL) 1635*7c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 1636*7c478bd9Sstevel@tonic-gate addr); 1637*7c478bd9Sstevel@tonic-gate else 1638*7c478bd9Sstevel@tonic-gate { 1639*7c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 1640*7c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET) 1641*7c478bd9Sstevel@tonic-gate hp->h_addr_list++; 1642*7c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 1643*7c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 1644*7c478bd9Sstevel@tonic-gate addr); 1645*7c478bd9Sstevel@tonic-gate else 1646*7c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin.sin_addr, 1647*7c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 1648*7c478bd9Sstevel@tonic-gate INADDRSZ); 1649*7c478bd9Sstevel@tonic-gate # if NETINET6 1650*7c478bd9Sstevel@tonic-gate freehostent(hp); 1651*7c478bd9Sstevel@tonic-gate hp = NULL; 1652*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 1653*7c478bd9Sstevel@tonic-gate } 1654*7c478bd9Sstevel@tonic-gate } 1655*7c478bd9Sstevel@tonic-gate break; 1656*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate #if NETINET6 1659*7c478bd9Sstevel@tonic-gate case AF_INET6: 1660*7c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, 1661*7c478bd9Sstevel@tonic-gate &d->d_addr.sin6.sin6_addr) != 1) 1662*7c478bd9Sstevel@tonic-gate { 1663*7c478bd9Sstevel@tonic-gate register struct hostent *hp; 1664*7c478bd9Sstevel@tonic-gate 1665*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(addr, AF_INET6); 1666*7c478bd9Sstevel@tonic-gate if (hp == NULL) 1667*7c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 1668*7c478bd9Sstevel@tonic-gate addr); 1669*7c478bd9Sstevel@tonic-gate else 1670*7c478bd9Sstevel@tonic-gate { 1671*7c478bd9Sstevel@tonic-gate while (*(hp->h_addr_list) != NULL && 1672*7c478bd9Sstevel@tonic-gate hp->h_addrtype != AF_INET6) 1673*7c478bd9Sstevel@tonic-gate hp->h_addr_list++; 1674*7c478bd9Sstevel@tonic-gate if (*(hp->h_addr_list) == NULL) 1675*7c478bd9Sstevel@tonic-gate syserr("554 5.3.0 host \"%s\" unknown", 1676*7c478bd9Sstevel@tonic-gate addr); 1677*7c478bd9Sstevel@tonic-gate else 1678*7c478bd9Sstevel@tonic-gate memmove(&d->d_addr.sin6.sin6_addr, 1679*7c478bd9Sstevel@tonic-gate *(hp->h_addr_list), 1680*7c478bd9Sstevel@tonic-gate IN6ADDRSZ); 1681*7c478bd9Sstevel@tonic-gate freehostent(hp); 1682*7c478bd9Sstevel@tonic-gate hp = NULL; 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate } 1685*7c478bd9Sstevel@tonic-gate break; 1686*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1687*7c478bd9Sstevel@tonic-gate 1688*7c478bd9Sstevel@tonic-gate default: 1689*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 address= option unsupported for family %d", 1690*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 1691*7c478bd9Sstevel@tonic-gate break; 1692*7c478bd9Sstevel@tonic-gate } 1693*7c478bd9Sstevel@tonic-gate } 1694*7c478bd9Sstevel@tonic-gate 1695*7c478bd9Sstevel@tonic-gate if (port != NULL) 1696*7c478bd9Sstevel@tonic-gate { 1697*7c478bd9Sstevel@tonic-gate switch (d->d_addr.sa.sa_family) 1698*7c478bd9Sstevel@tonic-gate { 1699*7c478bd9Sstevel@tonic-gate #if NETINET 1700*7c478bd9Sstevel@tonic-gate case AF_INET: 1701*7c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 1702*7c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = htons((unsigned short) 1703*7c478bd9Sstevel@tonic-gate atoi((const char *) port)); 1704*7c478bd9Sstevel@tonic-gate else 1705*7c478bd9Sstevel@tonic-gate { 1706*7c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 1707*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 1708*7c478bd9Sstevel@tonic-gate port); 1709*7c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 1710*7c478bd9Sstevel@tonic-gate register struct servent *sp; 1711*7c478bd9Sstevel@tonic-gate 1712*7c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 1713*7c478bd9Sstevel@tonic-gate if (sp == NULL) 1714*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 1715*7c478bd9Sstevel@tonic-gate port); 1716*7c478bd9Sstevel@tonic-gate else 1717*7c478bd9Sstevel@tonic-gate d->d_addr.sin.sin_port = sp->s_port; 1718*7c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 1719*7c478bd9Sstevel@tonic-gate } 1720*7c478bd9Sstevel@tonic-gate break; 1721*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate #if NETINET6 1724*7c478bd9Sstevel@tonic-gate case AF_INET6: 1725*7c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 1726*7c478bd9Sstevel@tonic-gate d->d_addr.sin6.sin6_port = htons((unsigned short) 1727*7c478bd9Sstevel@tonic-gate atoi(port)); 1728*7c478bd9Sstevel@tonic-gate else 1729*7c478bd9Sstevel@tonic-gate { 1730*7c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 1731*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 1732*7c478bd9Sstevel@tonic-gate port); 1733*7c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 1734*7c478bd9Sstevel@tonic-gate register struct servent *sp; 1735*7c478bd9Sstevel@tonic-gate 1736*7c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 1737*7c478bd9Sstevel@tonic-gate if (sp == NULL) 1738*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 1739*7c478bd9Sstevel@tonic-gate port); 1740*7c478bd9Sstevel@tonic-gate else 1741*7c478bd9Sstevel@tonic-gate d->d_addr.sin6.sin6_port = sp->s_port; 1742*7c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 1743*7c478bd9Sstevel@tonic-gate } 1744*7c478bd9Sstevel@tonic-gate break; 1745*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1746*7c478bd9Sstevel@tonic-gate 1747*7c478bd9Sstevel@tonic-gate #if NETISO 1748*7c478bd9Sstevel@tonic-gate case AF_ISO: 1749*7c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 1750*7c478bd9Sstevel@tonic-gate if (isascii(*port) && isdigit(*port)) 1751*7c478bd9Sstevel@tonic-gate portno = htons((unsigned short) atoi(port)); 1752*7c478bd9Sstevel@tonic-gate else 1753*7c478bd9Sstevel@tonic-gate { 1754*7c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 1755*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 invalid port number: %s", 1756*7c478bd9Sstevel@tonic-gate port); 1757*7c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 1758*7c478bd9Sstevel@tonic-gate register struct servent *sp; 1759*7c478bd9Sstevel@tonic-gate 1760*7c478bd9Sstevel@tonic-gate sp = getservbyname(port, "tcp"); 1761*7c478bd9Sstevel@tonic-gate if (sp == NULL) 1762*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 service \"%s\" unknown", 1763*7c478bd9Sstevel@tonic-gate port); 1764*7c478bd9Sstevel@tonic-gate else 1765*7c478bd9Sstevel@tonic-gate portno = sp->s_port; 1766*7c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 1767*7c478bd9Sstevel@tonic-gate } 1768*7c478bd9Sstevel@tonic-gate memmove(TSEL(&d->d_addr.siso), 1769*7c478bd9Sstevel@tonic-gate (char *) &portno, 2); 1770*7c478bd9Sstevel@tonic-gate break; 1771*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 1772*7c478bd9Sstevel@tonic-gate 1773*7c478bd9Sstevel@tonic-gate default: 1774*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Port= option unsupported for family %d", 1775*7c478bd9Sstevel@tonic-gate d->d_addr.sa.sa_family); 1776*7c478bd9Sstevel@tonic-gate break; 1777*7c478bd9Sstevel@tonic-gate } 1778*7c478bd9Sstevel@tonic-gate } 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate /* 1781*7c478bd9Sstevel@tonic-gate ** SETDAEMONOPTIONS -- set options for running the MTA daemon 1782*7c478bd9Sstevel@tonic-gate ** 1783*7c478bd9Sstevel@tonic-gate ** Parameters: 1784*7c478bd9Sstevel@tonic-gate ** p -- the options line. 1785*7c478bd9Sstevel@tonic-gate ** 1786*7c478bd9Sstevel@tonic-gate ** Returns: 1787*7c478bd9Sstevel@tonic-gate ** true if successful, false otherwise. 1788*7c478bd9Sstevel@tonic-gate ** 1789*7c478bd9Sstevel@tonic-gate ** Side Effects: 1790*7c478bd9Sstevel@tonic-gate ** increments number of daemons. 1791*7c478bd9Sstevel@tonic-gate */ 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate #define DEF_LISTENQUEUE 10 1794*7c478bd9Sstevel@tonic-gate 1795*7c478bd9Sstevel@tonic-gate struct dflags 1796*7c478bd9Sstevel@tonic-gate { 1797*7c478bd9Sstevel@tonic-gate char *d_name; 1798*7c478bd9Sstevel@tonic-gate int d_flag; 1799*7c478bd9Sstevel@tonic-gate }; 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate static struct dflags DaemonFlags[] = 1802*7c478bd9Sstevel@tonic-gate { 1803*7c478bd9Sstevel@tonic-gate { "AUTHREQ", D_AUTHREQ }, 1804*7c478bd9Sstevel@tonic-gate { "BINDIF", D_BINDIF }, 1805*7c478bd9Sstevel@tonic-gate { "CANONREQ", D_CANONREQ }, 1806*7c478bd9Sstevel@tonic-gate { "IFNHELO", D_IFNHELO }, 1807*7c478bd9Sstevel@tonic-gate { "FQMAIL", D_FQMAIL }, 1808*7c478bd9Sstevel@tonic-gate { "FQRCPT", D_FQRCPT }, 1809*7c478bd9Sstevel@tonic-gate { "SMTPS", D_SMTPS }, 1810*7c478bd9Sstevel@tonic-gate { "UNQUALOK", D_UNQUALOK }, 1811*7c478bd9Sstevel@tonic-gate { "NOAUTH", D_NOAUTH }, 1812*7c478bd9Sstevel@tonic-gate { "NOCANON", D_NOCANON }, 1813*7c478bd9Sstevel@tonic-gate { "NOETRN", D_NOETRN }, 1814*7c478bd9Sstevel@tonic-gate { "NOTLS", D_NOTLS }, 1815*7c478bd9Sstevel@tonic-gate { "ETRNONLY", D_ETRNONLY }, 1816*7c478bd9Sstevel@tonic-gate { "OPTIONAL", D_OPTIONAL }, 1817*7c478bd9Sstevel@tonic-gate { "DISABLE", D_DISABLE }, 1818*7c478bd9Sstevel@tonic-gate { "ISSET", D_ISSET }, 1819*7c478bd9Sstevel@tonic-gate { NULL, 0 } 1820*7c478bd9Sstevel@tonic-gate }; 1821*7c478bd9Sstevel@tonic-gate 1822*7c478bd9Sstevel@tonic-gate static void 1823*7c478bd9Sstevel@tonic-gate printdaemonflags(d) 1824*7c478bd9Sstevel@tonic-gate DAEMON_T *d; 1825*7c478bd9Sstevel@tonic-gate { 1826*7c478bd9Sstevel@tonic-gate register struct dflags *df; 1827*7c478bd9Sstevel@tonic-gate bool first = true; 1828*7c478bd9Sstevel@tonic-gate 1829*7c478bd9Sstevel@tonic-gate for (df = DaemonFlags; df->d_name != NULL; df++) 1830*7c478bd9Sstevel@tonic-gate { 1831*7c478bd9Sstevel@tonic-gate if (!bitnset(df->d_flag, d->d_flags)) 1832*7c478bd9Sstevel@tonic-gate continue; 1833*7c478bd9Sstevel@tonic-gate if (first) 1834*7c478bd9Sstevel@tonic-gate sm_dprintf("<%s", df->d_name); 1835*7c478bd9Sstevel@tonic-gate else 1836*7c478bd9Sstevel@tonic-gate sm_dprintf(",%s", df->d_name); 1837*7c478bd9Sstevel@tonic-gate first = false; 1838*7c478bd9Sstevel@tonic-gate } 1839*7c478bd9Sstevel@tonic-gate if (!first) 1840*7c478bd9Sstevel@tonic-gate sm_dprintf(">"); 1841*7c478bd9Sstevel@tonic-gate } 1842*7c478bd9Sstevel@tonic-gate 1843*7c478bd9Sstevel@tonic-gate bool 1844*7c478bd9Sstevel@tonic-gate setdaemonoptions(p) 1845*7c478bd9Sstevel@tonic-gate register char *p; 1846*7c478bd9Sstevel@tonic-gate { 1847*7c478bd9Sstevel@tonic-gate if (NDaemons >= MAXDAEMONS) 1848*7c478bd9Sstevel@tonic-gate return false; 1849*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 1850*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1851*7c478bd9Sstevel@tonic-gate clrbitmap(Daemons[NDaemons].d_flags); 1852*7c478bd9Sstevel@tonic-gate setsockaddroptions(p, &Daemons[NDaemons]); 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate #if MILTER 1855*7c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_inputfilterlist != NULL) 1856*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist); 1857*7c478bd9Sstevel@tonic-gate #endif /* MILTER */ 1858*7c478bd9Sstevel@tonic-gate 1859*7c478bd9Sstevel@tonic-gate if (Daemons[NDaemons].d_name != NULL) 1860*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name); 1861*7c478bd9Sstevel@tonic-gate else 1862*7c478bd9Sstevel@tonic-gate { 1863*7c478bd9Sstevel@tonic-gate char num[30]; 1864*7c478bd9Sstevel@tonic-gate 1865*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(num, sizeof num, "Daemon%d", NDaemons); 1866*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = newstr(num); 1867*7c478bd9Sstevel@tonic-gate } 1868*7c478bd9Sstevel@tonic-gate 1869*7c478bd9Sstevel@tonic-gate if (tTd(37, 1)) 1870*7c478bd9Sstevel@tonic-gate { 1871*7c478bd9Sstevel@tonic-gate sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name); 1872*7c478bd9Sstevel@tonic-gate printdaemonflags(&Daemons[NDaemons]); 1873*7c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 1874*7c478bd9Sstevel@tonic-gate } 1875*7c478bd9Sstevel@tonic-gate ++NDaemons; 1876*7c478bd9Sstevel@tonic-gate return true; 1877*7c478bd9Sstevel@tonic-gate } 1878*7c478bd9Sstevel@tonic-gate /* 1879*7c478bd9Sstevel@tonic-gate ** INITDAEMON -- initialize daemon if not yet done. 1880*7c478bd9Sstevel@tonic-gate ** 1881*7c478bd9Sstevel@tonic-gate ** Parameters: 1882*7c478bd9Sstevel@tonic-gate ** none 1883*7c478bd9Sstevel@tonic-gate ** 1884*7c478bd9Sstevel@tonic-gate ** Returns: 1885*7c478bd9Sstevel@tonic-gate ** none 1886*7c478bd9Sstevel@tonic-gate ** 1887*7c478bd9Sstevel@tonic-gate ** Side Effects: 1888*7c478bd9Sstevel@tonic-gate ** initializes structure for one daemon. 1889*7c478bd9Sstevel@tonic-gate */ 1890*7c478bd9Sstevel@tonic-gate 1891*7c478bd9Sstevel@tonic-gate void 1892*7c478bd9Sstevel@tonic-gate initdaemon() 1893*7c478bd9Sstevel@tonic-gate { 1894*7c478bd9Sstevel@tonic-gate if (NDaemons == 0) 1895*7c478bd9Sstevel@tonic-gate { 1896*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_socket = -1; 1897*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE; 1898*7c478bd9Sstevel@tonic-gate Daemons[NDaemons].d_name = "Daemon0"; 1899*7c478bd9Sstevel@tonic-gate NDaemons = 1; 1900*7c478bd9Sstevel@tonic-gate } 1901*7c478bd9Sstevel@tonic-gate } 1902*7c478bd9Sstevel@tonic-gate /* 1903*7c478bd9Sstevel@tonic-gate ** SETCLIENTOPTIONS -- set options for running the client 1904*7c478bd9Sstevel@tonic-gate ** 1905*7c478bd9Sstevel@tonic-gate ** Parameters: 1906*7c478bd9Sstevel@tonic-gate ** p -- the options line. 1907*7c478bd9Sstevel@tonic-gate ** 1908*7c478bd9Sstevel@tonic-gate ** Returns: 1909*7c478bd9Sstevel@tonic-gate ** none. 1910*7c478bd9Sstevel@tonic-gate */ 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate static DAEMON_T ClientSettings[AF_MAX + 1]; 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate void 1915*7c478bd9Sstevel@tonic-gate setclientoptions(p) 1916*7c478bd9Sstevel@tonic-gate register char *p; 1917*7c478bd9Sstevel@tonic-gate { 1918*7c478bd9Sstevel@tonic-gate int family; 1919*7c478bd9Sstevel@tonic-gate DAEMON_T d; 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate memset(&d, '\0', sizeof d); 1922*7c478bd9Sstevel@tonic-gate setsockaddroptions(p, &d); 1923*7c478bd9Sstevel@tonic-gate 1924*7c478bd9Sstevel@tonic-gate /* grab what we need */ 1925*7c478bd9Sstevel@tonic-gate family = d.d_addr.sa.sa_family; 1926*7c478bd9Sstevel@tonic-gate STRUCTCOPY(d, ClientSettings[family]); 1927*7c478bd9Sstevel@tonic-gate setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */ 1928*7c478bd9Sstevel@tonic-gate if (d.d_name != NULL) 1929*7c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(d.d_name); 1930*7c478bd9Sstevel@tonic-gate else 1931*7c478bd9Sstevel@tonic-gate { 1932*7c478bd9Sstevel@tonic-gate char num[30]; 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(num, sizeof num, "Client%d", family); 1935*7c478bd9Sstevel@tonic-gate ClientSettings[family].d_name = newstr(num); 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate } 1938*7c478bd9Sstevel@tonic-gate /* 1939*7c478bd9Sstevel@tonic-gate ** ADDR_FAMILY -- determine address family from address 1940*7c478bd9Sstevel@tonic-gate ** 1941*7c478bd9Sstevel@tonic-gate ** Parameters: 1942*7c478bd9Sstevel@tonic-gate ** addr -- the string representation of the address 1943*7c478bd9Sstevel@tonic-gate ** 1944*7c478bd9Sstevel@tonic-gate ** Returns: 1945*7c478bd9Sstevel@tonic-gate ** AF_INET, AF_INET6 or AF_UNSPEC 1946*7c478bd9Sstevel@tonic-gate ** 1947*7c478bd9Sstevel@tonic-gate ** Side Effects: 1948*7c478bd9Sstevel@tonic-gate ** none. 1949*7c478bd9Sstevel@tonic-gate */ 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate static int 1952*7c478bd9Sstevel@tonic-gate addr_family(addr) 1953*7c478bd9Sstevel@tonic-gate char *addr; 1954*7c478bd9Sstevel@tonic-gate { 1955*7c478bd9Sstevel@tonic-gate #if NETINET6 1956*7c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 1957*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1958*7c478bd9Sstevel@tonic-gate 1959*7c478bd9Sstevel@tonic-gate #if NETINET 1960*7c478bd9Sstevel@tonic-gate if (inet_addr(addr) != INADDR_NONE) 1961*7c478bd9Sstevel@tonic-gate { 1962*7c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 1963*7c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET\n", addr); 1964*7c478bd9Sstevel@tonic-gate return AF_INET; 1965*7c478bd9Sstevel@tonic-gate } 1966*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 1967*7c478bd9Sstevel@tonic-gate #if NETINET6 1968*7c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) 1969*7c478bd9Sstevel@tonic-gate { 1970*7c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 1971*7c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): INET6\n", addr); 1972*7c478bd9Sstevel@tonic-gate return AF_INET6; 1973*7c478bd9Sstevel@tonic-gate } 1974*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 1975*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 1976*7c478bd9Sstevel@tonic-gate # if NETUNIX 1977*7c478bd9Sstevel@tonic-gate if (*addr == '/') 1978*7c478bd9Sstevel@tonic-gate { 1979*7c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 1980*7c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): LOCAL\n", addr); 1981*7c478bd9Sstevel@tonic-gate return AF_UNIX; 1982*7c478bd9Sstevel@tonic-gate } 1983*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 1984*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 1985*7c478bd9Sstevel@tonic-gate if (tTd(16, 9)) 1986*7c478bd9Sstevel@tonic-gate sm_dprintf("addr_family(%s): UNSPEC\n", addr); 1987*7c478bd9Sstevel@tonic-gate return AF_UNSPEC; 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate 1990*7c478bd9Sstevel@tonic-gate /* 1991*7c478bd9Sstevel@tonic-gate ** CHKCLIENTMODIFIERS -- check whether all clients have set a flag. 1992*7c478bd9Sstevel@tonic-gate ** 1993*7c478bd9Sstevel@tonic-gate ** Parameters: 1994*7c478bd9Sstevel@tonic-gate ** flag -- the flag to test. 1995*7c478bd9Sstevel@tonic-gate ** 1996*7c478bd9Sstevel@tonic-gate ** Returns: 1997*7c478bd9Sstevel@tonic-gate ** true iff all configured clients have set the flag. 1998*7c478bd9Sstevel@tonic-gate */ 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate bool 2001*7c478bd9Sstevel@tonic-gate chkclientmodifiers(flag) 2002*7c478bd9Sstevel@tonic-gate int flag; 2003*7c478bd9Sstevel@tonic-gate { 2004*7c478bd9Sstevel@tonic-gate int i; 2005*7c478bd9Sstevel@tonic-gate bool flagisset; 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate flagisset = false; 2008*7c478bd9Sstevel@tonic-gate for (i = 0; i < AF_MAX; i++) 2009*7c478bd9Sstevel@tonic-gate { 2010*7c478bd9Sstevel@tonic-gate if (bitnset(D_ISSET, ClientSettings[i].d_flags)) 2011*7c478bd9Sstevel@tonic-gate { 2012*7c478bd9Sstevel@tonic-gate if (!bitnset((char) flag, ClientSettings[i].d_flags)) 2013*7c478bd9Sstevel@tonic-gate return false; 2014*7c478bd9Sstevel@tonic-gate flagisset = true; 2015*7c478bd9Sstevel@tonic-gate } 2016*7c478bd9Sstevel@tonic-gate } 2017*7c478bd9Sstevel@tonic-gate return flagisset; 2018*7c478bd9Sstevel@tonic-gate } 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate #if MILTER 2021*7c478bd9Sstevel@tonic-gate /* 2022*7c478bd9Sstevel@tonic-gate ** SETUP_DAEMON_FILTERS -- Parse per-socket filters 2023*7c478bd9Sstevel@tonic-gate ** 2024*7c478bd9Sstevel@tonic-gate ** Parameters: 2025*7c478bd9Sstevel@tonic-gate ** none 2026*7c478bd9Sstevel@tonic-gate ** 2027*7c478bd9Sstevel@tonic-gate ** Returns: 2028*7c478bd9Sstevel@tonic-gate ** none 2029*7c478bd9Sstevel@tonic-gate */ 2030*7c478bd9Sstevel@tonic-gate 2031*7c478bd9Sstevel@tonic-gate void 2032*7c478bd9Sstevel@tonic-gate setup_daemon_milters() 2033*7c478bd9Sstevel@tonic-gate { 2034*7c478bd9Sstevel@tonic-gate int idx; 2035*7c478bd9Sstevel@tonic-gate 2036*7c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP) 2037*7c478bd9Sstevel@tonic-gate { 2038*7c478bd9Sstevel@tonic-gate /* no need to configure the daemons */ 2039*7c478bd9Sstevel@tonic-gate return; 2040*7c478bd9Sstevel@tonic-gate } 2041*7c478bd9Sstevel@tonic-gate 2042*7c478bd9Sstevel@tonic-gate for (idx = 0; idx < NDaemons; idx++) 2043*7c478bd9Sstevel@tonic-gate { 2044*7c478bd9Sstevel@tonic-gate if (Daemons[idx].d_inputfilterlist != NULL) 2045*7c478bd9Sstevel@tonic-gate { 2046*7c478bd9Sstevel@tonic-gate milter_config(Daemons[idx].d_inputfilterlist, 2047*7c478bd9Sstevel@tonic-gate Daemons[idx].d_inputfilters, 2048*7c478bd9Sstevel@tonic-gate MAXFILTERS); 2049*7c478bd9Sstevel@tonic-gate } 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate } 2052*7c478bd9Sstevel@tonic-gate #endif /* MILTER */ 2053*7c478bd9Sstevel@tonic-gate /* 2054*7c478bd9Sstevel@tonic-gate ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. 2055*7c478bd9Sstevel@tonic-gate ** 2056*7c478bd9Sstevel@tonic-gate ** Parameters: 2057*7c478bd9Sstevel@tonic-gate ** host -- the name of the host. 2058*7c478bd9Sstevel@tonic-gate ** port -- the port number to connect to. 2059*7c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 2060*7c478bd9Sstevel@tonic-gate ** structure to be filled in. 2061*7c478bd9Sstevel@tonic-gate ** e -- the current envelope. 2062*7c478bd9Sstevel@tonic-gate ** enough -- time at which to stop further connection attempts. 2063*7c478bd9Sstevel@tonic-gate ** (0 means no limit) 2064*7c478bd9Sstevel@tonic-gate ** 2065*7c478bd9Sstevel@tonic-gate ** Returns: 2066*7c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 2067*7c478bd9Sstevel@tonic-gate ** made and if not why not. 2068*7c478bd9Sstevel@tonic-gate ** 2069*7c478bd9Sstevel@tonic-gate ** Side Effects: 2070*7c478bd9Sstevel@tonic-gate ** none. 2071*7c478bd9Sstevel@tonic-gate */ 2072*7c478bd9Sstevel@tonic-gate 2073*7c478bd9Sstevel@tonic-gate static jmp_buf CtxConnectTimeout; 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate SOCKADDR CurHostAddr; /* address of current host */ 2076*7c478bd9Sstevel@tonic-gate 2077*7c478bd9Sstevel@tonic-gate int 2078*7c478bd9Sstevel@tonic-gate makeconnection(host, port, mci, e, enough) 2079*7c478bd9Sstevel@tonic-gate char *host; 2080*7c478bd9Sstevel@tonic-gate volatile unsigned int port; 2081*7c478bd9Sstevel@tonic-gate register MCI *mci; 2082*7c478bd9Sstevel@tonic-gate ENVELOPE *e; 2083*7c478bd9Sstevel@tonic-gate time_t enough; 2084*7c478bd9Sstevel@tonic-gate { 2085*7c478bd9Sstevel@tonic-gate register volatile int addrno = 0; 2086*7c478bd9Sstevel@tonic-gate volatile int s; 2087*7c478bd9Sstevel@tonic-gate register struct hostent *volatile hp = (struct hostent *) NULL; 2088*7c478bd9Sstevel@tonic-gate SOCKADDR addr; 2089*7c478bd9Sstevel@tonic-gate SOCKADDR clt_addr; 2090*7c478bd9Sstevel@tonic-gate int save_errno = 0; 2091*7c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T addrlen; 2092*7c478bd9Sstevel@tonic-gate volatile bool firstconnect; 2093*7c478bd9Sstevel@tonic-gate SM_EVENT *volatile ev = NULL; 2094*7c478bd9Sstevel@tonic-gate #if NETINET6 2095*7c478bd9Sstevel@tonic-gate volatile bool v6found = false; 2096*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2097*7c478bd9Sstevel@tonic-gate volatile int family = InetMode; 2098*7c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T len; 2099*7c478bd9Sstevel@tonic-gate volatile SOCKADDR_LEN_T socksize = 0; 2100*7c478bd9Sstevel@tonic-gate volatile bool clt_bind; 2101*7c478bd9Sstevel@tonic-gate BITMAP256 d_flags; 2102*7c478bd9Sstevel@tonic-gate char *p; 2103*7c478bd9Sstevel@tonic-gate extern ENVELOPE BlankEnvelope; 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate /* retranslate {daemon_flags} into bitmap */ 2106*7c478bd9Sstevel@tonic-gate clrbitmap(d_flags); 2107*7c478bd9Sstevel@tonic-gate if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL) 2108*7c478bd9Sstevel@tonic-gate { 2109*7c478bd9Sstevel@tonic-gate for (; *p != '\0'; p++) 2110*7c478bd9Sstevel@tonic-gate { 2111*7c478bd9Sstevel@tonic-gate if (!(isascii(*p) && isspace(*p))) 2112*7c478bd9Sstevel@tonic-gate setbitn(bitidx(*p), d_flags); 2113*7c478bd9Sstevel@tonic-gate } 2114*7c478bd9Sstevel@tonic-gate } 2115*7c478bd9Sstevel@tonic-gate 2116*7c478bd9Sstevel@tonic-gate #if NETINET6 2117*7c478bd9Sstevel@tonic-gate v4retry: 2118*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2119*7c478bd9Sstevel@tonic-gate clt_bind = false; 2120*7c478bd9Sstevel@tonic-gate 2121*7c478bd9Sstevel@tonic-gate /* Set up the address for outgoing connection. */ 2122*7c478bd9Sstevel@tonic-gate if (bitnset(D_BINDIF, d_flags) && 2123*7c478bd9Sstevel@tonic-gate (p = macvalue(macid("{if_addr}"), e)) != NULL && 2124*7c478bd9Sstevel@tonic-gate *p != '\0') 2125*7c478bd9Sstevel@tonic-gate { 2126*7c478bd9Sstevel@tonic-gate #if NETINET6 2127*7c478bd9Sstevel@tonic-gate char p6[INET6_ADDRSTRLEN]; 2128*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2129*7c478bd9Sstevel@tonic-gate 2130*7c478bd9Sstevel@tonic-gate memset(&clt_addr, '\0', sizeof clt_addr); 2131*7c478bd9Sstevel@tonic-gate 2132*7c478bd9Sstevel@tonic-gate /* infer the address family from the address itself */ 2133*7c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family = addr_family(p); 2134*7c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 2135*7c478bd9Sstevel@tonic-gate { 2136*7c478bd9Sstevel@tonic-gate #if NETINET 2137*7c478bd9Sstevel@tonic-gate case AF_INET: 2138*7c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr = inet_addr(p); 2139*7c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && 2140*7c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) 2141*7c478bd9Sstevel@tonic-gate { 2142*7c478bd9Sstevel@tonic-gate clt_bind = true; 2143*7c478bd9Sstevel@tonic-gate socksize = sizeof (struct sockaddr_in); 2144*7c478bd9Sstevel@tonic-gate } 2145*7c478bd9Sstevel@tonic-gate break; 2146*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate #if NETINET6 2149*7c478bd9Sstevel@tonic-gate case AF_INET6: 2150*7c478bd9Sstevel@tonic-gate if (inet_addr(p) != INADDR_NONE) 2151*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(p6, sizeof p6, 2152*7c478bd9Sstevel@tonic-gate "IPv6:::ffff:%s", p); 2153*7c478bd9Sstevel@tonic-gate else 2154*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p6, p, sizeof p6); 2155*7c478bd9Sstevel@tonic-gate if (anynet_pton(AF_INET6, p6, 2156*7c478bd9Sstevel@tonic-gate &clt_addr.sin6.sin6_addr) == 1 && 2157*7c478bd9Sstevel@tonic-gate !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) 2158*7c478bd9Sstevel@tonic-gate { 2159*7c478bd9Sstevel@tonic-gate clt_bind = true; 2160*7c478bd9Sstevel@tonic-gate socksize = sizeof (struct sockaddr_in6); 2161*7c478bd9Sstevel@tonic-gate } 2162*7c478bd9Sstevel@tonic-gate break; 2163*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2164*7c478bd9Sstevel@tonic-gate 2165*7c478bd9Sstevel@tonic-gate #if 0 2166*7c478bd9Sstevel@tonic-gate default: 2167*7c478bd9Sstevel@tonic-gate syserr("554 5.3.5 Address= option unsupported for family %d", 2168*7c478bd9Sstevel@tonic-gate clt_addr.sa.sa_family); 2169*7c478bd9Sstevel@tonic-gate break; 2170*7c478bd9Sstevel@tonic-gate #endif /* 0 */ 2171*7c478bd9Sstevel@tonic-gate } 2172*7c478bd9Sstevel@tonic-gate if (clt_bind) 2173*7c478bd9Sstevel@tonic-gate family = clt_addr.sa.sa_family; 2174*7c478bd9Sstevel@tonic-gate } 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate /* D_BINDIF not set or not available, fallback to ClientPortOptions */ 2177*7c478bd9Sstevel@tonic-gate if (!clt_bind) 2178*7c478bd9Sstevel@tonic-gate { 2179*7c478bd9Sstevel@tonic-gate STRUCTCOPY(ClientSettings[family].d_addr, clt_addr); 2180*7c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 2181*7c478bd9Sstevel@tonic-gate { 2182*7c478bd9Sstevel@tonic-gate #if NETINET 2183*7c478bd9Sstevel@tonic-gate case AF_INET: 2184*7c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_addr.s_addr == 0) 2185*7c478bd9Sstevel@tonic-gate clt_addr.sin.sin_addr.s_addr = INADDR_ANY; 2186*7c478bd9Sstevel@tonic-gate else 2187*7c478bd9Sstevel@tonic-gate clt_bind = true; 2188*7c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 2189*7c478bd9Sstevel@tonic-gate clt_bind = true; 2190*7c478bd9Sstevel@tonic-gate socksize = sizeof (struct sockaddr_in); 2191*7c478bd9Sstevel@tonic-gate break; 2192*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2193*7c478bd9Sstevel@tonic-gate #if NETINET6 2194*7c478bd9Sstevel@tonic-gate case AF_INET6: 2195*7c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) 2196*7c478bd9Sstevel@tonic-gate clt_addr.sin6.sin6_addr = in6addr_any; 2197*7c478bd9Sstevel@tonic-gate else 2198*7c478bd9Sstevel@tonic-gate clt_bind = true; 2199*7c478bd9Sstevel@tonic-gate socksize = sizeof (struct sockaddr_in6); 2200*7c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 2201*7c478bd9Sstevel@tonic-gate clt_bind = true; 2202*7c478bd9Sstevel@tonic-gate break; 2203*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2204*7c478bd9Sstevel@tonic-gate #if NETISO 2205*7c478bd9Sstevel@tonic-gate case AF_ISO: 2206*7c478bd9Sstevel@tonic-gate socksize = sizeof clt_addr.siso; 2207*7c478bd9Sstevel@tonic-gate clt_bind = true; 2208*7c478bd9Sstevel@tonic-gate break; 2209*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 2210*7c478bd9Sstevel@tonic-gate default: 2211*7c478bd9Sstevel@tonic-gate break; 2212*7c478bd9Sstevel@tonic-gate } 2213*7c478bd9Sstevel@tonic-gate } 2214*7c478bd9Sstevel@tonic-gate 2215*7c478bd9Sstevel@tonic-gate /* 2216*7c478bd9Sstevel@tonic-gate ** Set up the address for the mailer. 2217*7c478bd9Sstevel@tonic-gate ** Accept "[a.b.c.d]" syntax for host name. 2218*7c478bd9Sstevel@tonic-gate */ 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(0); 2221*7c478bd9Sstevel@tonic-gate errno = 0; 2222*7c478bd9Sstevel@tonic-gate memset(&CurHostAddr, '\0', sizeof CurHostAddr); 2223*7c478bd9Sstevel@tonic-gate memset(&addr, '\0', sizeof addr); 2224*7c478bd9Sstevel@tonic-gate SmtpPhase = mci->mci_phase = "initial connection"; 2225*7c478bd9Sstevel@tonic-gate CurHostName = host; 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate if (host[0] == '[') 2228*7c478bd9Sstevel@tonic-gate { 2229*7c478bd9Sstevel@tonic-gate p = strchr(host, ']'); 2230*7c478bd9Sstevel@tonic-gate if (p != NULL) 2231*7c478bd9Sstevel@tonic-gate { 2232*7c478bd9Sstevel@tonic-gate #if NETINET 2233*7c478bd9Sstevel@tonic-gate unsigned long hid = INADDR_NONE; 2234*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2235*7c478bd9Sstevel@tonic-gate #if NETINET6 2236*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 hid6; 2237*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2238*7c478bd9Sstevel@tonic-gate 2239*7c478bd9Sstevel@tonic-gate *p = '\0'; 2240*7c478bd9Sstevel@tonic-gate #if NETINET6 2241*7c478bd9Sstevel@tonic-gate memset(&hid6, '\0', sizeof hid6); 2242*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2243*7c478bd9Sstevel@tonic-gate #if NETINET 2244*7c478bd9Sstevel@tonic-gate if (family == AF_INET && 2245*7c478bd9Sstevel@tonic-gate (hid = inet_addr(&host[1])) != INADDR_NONE) 2246*7c478bd9Sstevel@tonic-gate { 2247*7c478bd9Sstevel@tonic-gate addr.sin.sin_family = AF_INET; 2248*7c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = hid; 2249*7c478bd9Sstevel@tonic-gate } 2250*7c478bd9Sstevel@tonic-gate else 2251*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2252*7c478bd9Sstevel@tonic-gate #if NETINET6 2253*7c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 2254*7c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &host[1], 2255*7c478bd9Sstevel@tonic-gate &hid6.sin6_addr) == 1) 2256*7c478bd9Sstevel@tonic-gate { 2257*7c478bd9Sstevel@tonic-gate addr.sin6.sin6_family = AF_INET6; 2258*7c478bd9Sstevel@tonic-gate addr.sin6.sin6_addr = hid6.sin6_addr; 2259*7c478bd9Sstevel@tonic-gate } 2260*7c478bd9Sstevel@tonic-gate else 2261*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2262*7c478bd9Sstevel@tonic-gate { 2263*7c478bd9Sstevel@tonic-gate /* try it as a host name (avoid MX lookup) */ 2264*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], family); 2265*7c478bd9Sstevel@tonic-gate if (hp == NULL && p[-1] == '.') 2266*7c478bd9Sstevel@tonic-gate { 2267*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 2268*7c478bd9Sstevel@tonic-gate int oldopts = _res.options; 2269*7c478bd9Sstevel@tonic-gate 2270*7c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2271*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 2272*7c478bd9Sstevel@tonic-gate p[-1] = '\0'; 2273*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(&host[1], 2274*7c478bd9Sstevel@tonic-gate family); 2275*7c478bd9Sstevel@tonic-gate p[-1] = '.'; 2276*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 2277*7c478bd9Sstevel@tonic-gate _res.options = oldopts; 2278*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 2279*7c478bd9Sstevel@tonic-gate } 2280*7c478bd9Sstevel@tonic-gate *p = ']'; 2281*7c478bd9Sstevel@tonic-gate goto gothostent; 2282*7c478bd9Sstevel@tonic-gate } 2283*7c478bd9Sstevel@tonic-gate *p = ']'; 2284*7c478bd9Sstevel@tonic-gate } 2285*7c478bd9Sstevel@tonic-gate if (p == NULL) 2286*7c478bd9Sstevel@tonic-gate { 2287*7c478bd9Sstevel@tonic-gate extern char MsgBuf[]; 2288*7c478bd9Sstevel@tonic-gate 2289*7c478bd9Sstevel@tonic-gate usrerrenh("5.1.2", 2290*7c478bd9Sstevel@tonic-gate "553 Invalid numeric domain spec \"%s\"", 2291*7c478bd9Sstevel@tonic-gate host); 2292*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); 2293*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2294*7c478bd9Sstevel@tonic-gate return EX_NOHOST; 2295*7c478bd9Sstevel@tonic-gate } 2296*7c478bd9Sstevel@tonic-gate } 2297*7c478bd9Sstevel@tonic-gate else 2298*7c478bd9Sstevel@tonic-gate { 2299*7c478bd9Sstevel@tonic-gate /* contortion to get around SGI cc complaints */ 2300*7c478bd9Sstevel@tonic-gate { 2301*7c478bd9Sstevel@tonic-gate p = &host[strlen(host) - 1]; 2302*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 2303*7c478bd9Sstevel@tonic-gate if (hp == NULL && *p == '.') 2304*7c478bd9Sstevel@tonic-gate { 2305*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 2306*7c478bd9Sstevel@tonic-gate int oldopts = _res.options; 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); 2309*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 2310*7c478bd9Sstevel@tonic-gate *p = '\0'; 2311*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(host, family); 2312*7c478bd9Sstevel@tonic-gate *p = '.'; 2313*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 2314*7c478bd9Sstevel@tonic-gate _res.options = oldopts; 2315*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 2316*7c478bd9Sstevel@tonic-gate } 2317*7c478bd9Sstevel@tonic-gate } 2318*7c478bd9Sstevel@tonic-gate gothostent: 2319*7c478bd9Sstevel@tonic-gate if (hp == NULL) 2320*7c478bd9Sstevel@tonic-gate { 2321*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 2322*7c478bd9Sstevel@tonic-gate /* check for name server timeouts */ 2323*7c478bd9Sstevel@tonic-gate # if NETINET6 2324*7c478bd9Sstevel@tonic-gate if (WorkAroundBrokenAAAA && family == AF_INET6 && 2325*7c478bd9Sstevel@tonic-gate errno == ETIMEDOUT) 2326*7c478bd9Sstevel@tonic-gate { 2327*7c478bd9Sstevel@tonic-gate /* 2328*7c478bd9Sstevel@tonic-gate ** An attempt with family AF_INET may 2329*7c478bd9Sstevel@tonic-gate ** succeed By skipping the next section 2330*7c478bd9Sstevel@tonic-gate ** of code, we will try AF_INET before 2331*7c478bd9Sstevel@tonic-gate ** failing. 2332*7c478bd9Sstevel@tonic-gate */ 2333*7c478bd9Sstevel@tonic-gate 2334*7c478bd9Sstevel@tonic-gate if (tTd(16, 10)) 2335*7c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n"); 2336*7c478bd9Sstevel@tonic-gate } 2337*7c478bd9Sstevel@tonic-gate else 2338*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 2339*7c478bd9Sstevel@tonic-gate { 2340*7c478bd9Sstevel@tonic-gate if (errno == ETIMEDOUT || 2341*7c478bd9Sstevel@tonic-gate h_errno == TRY_AGAIN || 2342*7c478bd9Sstevel@tonic-gate (errno == ECONNREFUSED && UseNameServer)) 2343*7c478bd9Sstevel@tonic-gate { 2344*7c478bd9Sstevel@tonic-gate save_errno = errno; 2345*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, 2346*7c478bd9Sstevel@tonic-gate "4.4.3", NULL); 2347*7c478bd9Sstevel@tonic-gate errno = save_errno; 2348*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2349*7c478bd9Sstevel@tonic-gate } 2350*7c478bd9Sstevel@tonic-gate } 2351*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 2352*7c478bd9Sstevel@tonic-gate #if NETINET6 2353*7c478bd9Sstevel@tonic-gate /* 2354*7c478bd9Sstevel@tonic-gate ** Try v6 first, then fall back to v4. 2355*7c478bd9Sstevel@tonic-gate ** If we found a v6 address, but no v4 2356*7c478bd9Sstevel@tonic-gate ** addresses, then TEMPFAIL. 2357*7c478bd9Sstevel@tonic-gate */ 2358*7c478bd9Sstevel@tonic-gate 2359*7c478bd9Sstevel@tonic-gate if (family == AF_INET6) 2360*7c478bd9Sstevel@tonic-gate { 2361*7c478bd9Sstevel@tonic-gate family = AF_INET; 2362*7c478bd9Sstevel@tonic-gate goto v4retry; 2363*7c478bd9Sstevel@tonic-gate } 2364*7c478bd9Sstevel@tonic-gate if (v6found) 2365*7c478bd9Sstevel@tonic-gate goto v6tempfail; 2366*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2367*7c478bd9Sstevel@tonic-gate save_errno = errno; 2368*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2369*7c478bd9Sstevel@tonic-gate errno = save_errno; 2370*7c478bd9Sstevel@tonic-gate return EX_NOHOST; 2371*7c478bd9Sstevel@tonic-gate } 2372*7c478bd9Sstevel@tonic-gate addr.sa.sa_family = hp->h_addrtype; 2373*7c478bd9Sstevel@tonic-gate switch (hp->h_addrtype) 2374*7c478bd9Sstevel@tonic-gate { 2375*7c478bd9Sstevel@tonic-gate #if NETINET 2376*7c478bd9Sstevel@tonic-gate case AF_INET: 2377*7c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 2378*7c478bd9Sstevel@tonic-gate hp->h_addr, 2379*7c478bd9Sstevel@tonic-gate INADDRSZ); 2380*7c478bd9Sstevel@tonic-gate break; 2381*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2382*7c478bd9Sstevel@tonic-gate 2383*7c478bd9Sstevel@tonic-gate #if NETINET6 2384*7c478bd9Sstevel@tonic-gate case AF_INET6: 2385*7c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 2386*7c478bd9Sstevel@tonic-gate hp->h_addr, 2387*7c478bd9Sstevel@tonic-gate IN6ADDRSZ); 2388*7c478bd9Sstevel@tonic-gate break; 2389*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2390*7c478bd9Sstevel@tonic-gate 2391*7c478bd9Sstevel@tonic-gate default: 2392*7c478bd9Sstevel@tonic-gate if (hp->h_length > sizeof addr.sa.sa_data) 2393*7c478bd9Sstevel@tonic-gate { 2394*7c478bd9Sstevel@tonic-gate syserr("makeconnection: long sa_data: family %d len %d", 2395*7c478bd9Sstevel@tonic-gate hp->h_addrtype, hp->h_length); 2396*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2397*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2398*7c478bd9Sstevel@tonic-gate return EX_NOHOST; 2399*7c478bd9Sstevel@tonic-gate } 2400*7c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, hp->h_addr, hp->h_length); 2401*7c478bd9Sstevel@tonic-gate break; 2402*7c478bd9Sstevel@tonic-gate } 2403*7c478bd9Sstevel@tonic-gate addrno = 1; 2404*7c478bd9Sstevel@tonic-gate } 2405*7c478bd9Sstevel@tonic-gate 2406*7c478bd9Sstevel@tonic-gate /* 2407*7c478bd9Sstevel@tonic-gate ** Determine the port number. 2408*7c478bd9Sstevel@tonic-gate */ 2409*7c478bd9Sstevel@tonic-gate 2410*7c478bd9Sstevel@tonic-gate if (port == 0) 2411*7c478bd9Sstevel@tonic-gate { 2412*7c478bd9Sstevel@tonic-gate #ifdef NO_GETSERVBYNAME 2413*7c478bd9Sstevel@tonic-gate port = htons(25); 2414*7c478bd9Sstevel@tonic-gate #else /* NO_GETSERVBYNAME */ 2415*7c478bd9Sstevel@tonic-gate register struct servent *sp = getservbyname("smtp", "tcp"); 2416*7c478bd9Sstevel@tonic-gate 2417*7c478bd9Sstevel@tonic-gate if (sp == NULL) 2418*7c478bd9Sstevel@tonic-gate { 2419*7c478bd9Sstevel@tonic-gate if (LogLevel > 2) 2420*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 2421*7c478bd9Sstevel@tonic-gate "makeconnection: service \"smtp\" unknown"); 2422*7c478bd9Sstevel@tonic-gate port = htons(25); 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate else 2425*7c478bd9Sstevel@tonic-gate port = sp->s_port; 2426*7c478bd9Sstevel@tonic-gate #endif /* NO_GETSERVBYNAME */ 2427*7c478bd9Sstevel@tonic-gate } 2428*7c478bd9Sstevel@tonic-gate 2429*7c478bd9Sstevel@tonic-gate #if NETINET6 2430*7c478bd9Sstevel@tonic-gate if (addr.sa.sa_family == AF_INET6 && 2431*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) && 2432*7c478bd9Sstevel@tonic-gate ClientSettings[AF_INET].d_addr.sa.sa_family != 0) 2433*7c478bd9Sstevel@tonic-gate { 2434*7c478bd9Sstevel@tonic-gate /* 2435*7c478bd9Sstevel@tonic-gate ** Ignore mapped IPv4 address since 2436*7c478bd9Sstevel@tonic-gate ** there is a ClientPortOptions setting 2437*7c478bd9Sstevel@tonic-gate ** for IPv4. 2438*7c478bd9Sstevel@tonic-gate */ 2439*7c478bd9Sstevel@tonic-gate 2440*7c478bd9Sstevel@tonic-gate goto nextaddr; 2441*7c478bd9Sstevel@tonic-gate } 2442*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2443*7c478bd9Sstevel@tonic-gate 2444*7c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 2445*7c478bd9Sstevel@tonic-gate { 2446*7c478bd9Sstevel@tonic-gate #if NETINET 2447*7c478bd9Sstevel@tonic-gate case AF_INET: 2448*7c478bd9Sstevel@tonic-gate addr.sin.sin_port = port; 2449*7c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_in); 2450*7c478bd9Sstevel@tonic-gate break; 2451*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate #if NETINET6 2454*7c478bd9Sstevel@tonic-gate case AF_INET6: 2455*7c478bd9Sstevel@tonic-gate addr.sin6.sin6_port = port; 2456*7c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_in6); 2457*7c478bd9Sstevel@tonic-gate break; 2458*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2459*7c478bd9Sstevel@tonic-gate 2460*7c478bd9Sstevel@tonic-gate #if NETISO 2461*7c478bd9Sstevel@tonic-gate case AF_ISO: 2462*7c478bd9Sstevel@tonic-gate /* assume two byte transport selector */ 2463*7c478bd9Sstevel@tonic-gate memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); 2464*7c478bd9Sstevel@tonic-gate addrlen = sizeof (struct sockaddr_iso); 2465*7c478bd9Sstevel@tonic-gate break; 2466*7c478bd9Sstevel@tonic-gate #endif /* NETISO */ 2467*7c478bd9Sstevel@tonic-gate 2468*7c478bd9Sstevel@tonic-gate default: 2469*7c478bd9Sstevel@tonic-gate syserr("Can't connect to address family %d", addr.sa.sa_family); 2470*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); 2471*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2472*7c478bd9Sstevel@tonic-gate #if NETINET6 2473*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2474*7c478bd9Sstevel@tonic-gate freehostent(hp); 2475*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2476*7c478bd9Sstevel@tonic-gate return EX_NOHOST; 2477*7c478bd9Sstevel@tonic-gate } 2478*7c478bd9Sstevel@tonic-gate 2479*7c478bd9Sstevel@tonic-gate /* 2480*7c478bd9Sstevel@tonic-gate ** Try to actually open the connection. 2481*7c478bd9Sstevel@tonic-gate */ 2482*7c478bd9Sstevel@tonic-gate 2483*7c478bd9Sstevel@tonic-gate #if XLA 2484*7c478bd9Sstevel@tonic-gate /* if too many connections, don't bother trying */ 2485*7c478bd9Sstevel@tonic-gate if (!xla_noqueue_ok(host)) 2486*7c478bd9Sstevel@tonic-gate { 2487*7c478bd9Sstevel@tonic-gate # if NETINET6 2488*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2489*7c478bd9Sstevel@tonic-gate freehostent(hp); 2490*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 2491*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2492*7c478bd9Sstevel@tonic-gate } 2493*7c478bd9Sstevel@tonic-gate #endif /* XLA */ 2494*7c478bd9Sstevel@tonic-gate 2495*7c478bd9Sstevel@tonic-gate firstconnect = true; 2496*7c478bd9Sstevel@tonic-gate for (;;) 2497*7c478bd9Sstevel@tonic-gate { 2498*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2499*7c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection (%s [%s].%d (%d))\n", 2500*7c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), ntohs(port), 2501*7c478bd9Sstevel@tonic-gate (int) addr.sa.sa_family); 2502*7c478bd9Sstevel@tonic-gate 2503*7c478bd9Sstevel@tonic-gate /* save for logging */ 2504*7c478bd9Sstevel@tonic-gate CurHostAddr = addr; 2505*7c478bd9Sstevel@tonic-gate 2506*7c478bd9Sstevel@tonic-gate #if HASRRESVPORT 2507*7c478bd9Sstevel@tonic-gate if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) 2508*7c478bd9Sstevel@tonic-gate { 2509*7c478bd9Sstevel@tonic-gate int rport = IPPORT_RESERVED - 1; 2510*7c478bd9Sstevel@tonic-gate 2511*7c478bd9Sstevel@tonic-gate s = rresvport(&rport); 2512*7c478bd9Sstevel@tonic-gate } 2513*7c478bd9Sstevel@tonic-gate else 2514*7c478bd9Sstevel@tonic-gate #endif /* HASRRESVPORT */ 2515*7c478bd9Sstevel@tonic-gate { 2516*7c478bd9Sstevel@tonic-gate s = socket(addr.sa.sa_family, SOCK_STREAM, 0); 2517*7c478bd9Sstevel@tonic-gate } 2518*7c478bd9Sstevel@tonic-gate if (s < 0) 2519*7c478bd9Sstevel@tonic-gate { 2520*7c478bd9Sstevel@tonic-gate save_errno = errno; 2521*7c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot create socket"); 2522*7c478bd9Sstevel@tonic-gate #if XLA 2523*7c478bd9Sstevel@tonic-gate xla_host_end(host); 2524*7c478bd9Sstevel@tonic-gate #endif /* XLA */ 2525*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2526*7c478bd9Sstevel@tonic-gate #if NETINET6 2527*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2528*7c478bd9Sstevel@tonic-gate freehostent(hp); 2529*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2530*7c478bd9Sstevel@tonic-gate errno = save_errno; 2531*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2532*7c478bd9Sstevel@tonic-gate } 2533*7c478bd9Sstevel@tonic-gate 2534*7c478bd9Sstevel@tonic-gate #ifdef SO_SNDBUF 2535*7c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcpsndbufsize > 0) 2536*7c478bd9Sstevel@tonic-gate { 2537*7c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, 2538*7c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcpsndbufsize, 2539*7c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0) 2540*7c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_SNDBUF)"); 2541*7c478bd9Sstevel@tonic-gate } 2542*7c478bd9Sstevel@tonic-gate #endif /* SO_SNDBUF */ 2543*7c478bd9Sstevel@tonic-gate #ifdef SO_RCVBUF 2544*7c478bd9Sstevel@tonic-gate if (ClientSettings[family].d_tcprcvbufsize > 0) 2545*7c478bd9Sstevel@tonic-gate { 2546*7c478bd9Sstevel@tonic-gate if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, 2547*7c478bd9Sstevel@tonic-gate (char *) &ClientSettings[family].d_tcprcvbufsize, 2548*7c478bd9Sstevel@tonic-gate sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0) 2549*7c478bd9Sstevel@tonic-gate syserr("makeconnection: setsockopt(SO_RCVBUF)"); 2550*7c478bd9Sstevel@tonic-gate } 2551*7c478bd9Sstevel@tonic-gate #endif /* SO_RCVBUF */ 2552*7c478bd9Sstevel@tonic-gate 2553*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2554*7c478bd9Sstevel@tonic-gate sm_dprintf("makeconnection: fd=%d\n", s); 2555*7c478bd9Sstevel@tonic-gate 2556*7c478bd9Sstevel@tonic-gate /* turn on network debugging? */ 2557*7c478bd9Sstevel@tonic-gate if (tTd(16, 101)) 2558*7c478bd9Sstevel@tonic-gate { 2559*7c478bd9Sstevel@tonic-gate int on = 1; 2560*7c478bd9Sstevel@tonic-gate 2561*7c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 2562*7c478bd9Sstevel@tonic-gate (char *)&on, sizeof on); 2563*7c478bd9Sstevel@tonic-gate } 2564*7c478bd9Sstevel@tonic-gate if (e->e_xfp != NULL) /* for debugging */ 2565*7c478bd9Sstevel@tonic-gate (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 2566*7c478bd9Sstevel@tonic-gate errno = 0; /* for debugging */ 2567*7c478bd9Sstevel@tonic-gate 2568*7c478bd9Sstevel@tonic-gate if (clt_bind) 2569*7c478bd9Sstevel@tonic-gate { 2570*7c478bd9Sstevel@tonic-gate int on = 1; 2571*7c478bd9Sstevel@tonic-gate 2572*7c478bd9Sstevel@tonic-gate switch (clt_addr.sa.sa_family) 2573*7c478bd9Sstevel@tonic-gate { 2574*7c478bd9Sstevel@tonic-gate #if NETINET 2575*7c478bd9Sstevel@tonic-gate case AF_INET: 2576*7c478bd9Sstevel@tonic-gate if (clt_addr.sin.sin_port != 0) 2577*7c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 2578*7c478bd9Sstevel@tonic-gate SO_REUSEADDR, 2579*7c478bd9Sstevel@tonic-gate (char *) &on, 2580*7c478bd9Sstevel@tonic-gate sizeof on); 2581*7c478bd9Sstevel@tonic-gate break; 2582*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2583*7c478bd9Sstevel@tonic-gate 2584*7c478bd9Sstevel@tonic-gate #if NETINET6 2585*7c478bd9Sstevel@tonic-gate case AF_INET6: 2586*7c478bd9Sstevel@tonic-gate if (clt_addr.sin6.sin6_port != 0) 2587*7c478bd9Sstevel@tonic-gate (void) setsockopt(s, SOL_SOCKET, 2588*7c478bd9Sstevel@tonic-gate SO_REUSEADDR, 2589*7c478bd9Sstevel@tonic-gate (char *) &on, 2590*7c478bd9Sstevel@tonic-gate sizeof on); 2591*7c478bd9Sstevel@tonic-gate break; 2592*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2593*7c478bd9Sstevel@tonic-gate } 2594*7c478bd9Sstevel@tonic-gate 2595*7c478bd9Sstevel@tonic-gate if (bind(s, &clt_addr.sa, socksize) < 0) 2596*7c478bd9Sstevel@tonic-gate { 2597*7c478bd9Sstevel@tonic-gate save_errno = errno; 2598*7c478bd9Sstevel@tonic-gate (void) close(s); 2599*7c478bd9Sstevel@tonic-gate errno = save_errno; 2600*7c478bd9Sstevel@tonic-gate syserr("makeconnection: cannot bind socket [%s]", 2601*7c478bd9Sstevel@tonic-gate anynet_ntoa(&clt_addr)); 2602*7c478bd9Sstevel@tonic-gate #if NETINET6 2603*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2604*7c478bd9Sstevel@tonic-gate freehostent(hp); 2605*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2606*7c478bd9Sstevel@tonic-gate errno = save_errno; 2607*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2608*7c478bd9Sstevel@tonic-gate } 2609*7c478bd9Sstevel@tonic-gate } 2610*7c478bd9Sstevel@tonic-gate 2611*7c478bd9Sstevel@tonic-gate /* 2612*7c478bd9Sstevel@tonic-gate ** Linux seems to hang in connect for 90 minutes (!!!). 2613*7c478bd9Sstevel@tonic-gate ** Time out the connect to avoid this problem. 2614*7c478bd9Sstevel@tonic-gate */ 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate if (setjmp(CtxConnectTimeout) == 0) 2617*7c478bd9Sstevel@tonic-gate { 2618*7c478bd9Sstevel@tonic-gate int i; 2619*7c478bd9Sstevel@tonic-gate 2620*7c478bd9Sstevel@tonic-gate if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) 2621*7c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_iconnect, 2622*7c478bd9Sstevel@tonic-gate connecttimeout, 0); 2623*7c478bd9Sstevel@tonic-gate else if (TimeOuts.to_connect != 0) 2624*7c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_connect, 2625*7c478bd9Sstevel@tonic-gate connecttimeout, 0); 2626*7c478bd9Sstevel@tonic-gate else 2627*7c478bd9Sstevel@tonic-gate ev = NULL; 2628*7c478bd9Sstevel@tonic-gate 2629*7c478bd9Sstevel@tonic-gate switch (ConnectOnlyTo.sa.sa_family) 2630*7c478bd9Sstevel@tonic-gate { 2631*7c478bd9Sstevel@tonic-gate #if NETINET 2632*7c478bd9Sstevel@tonic-gate case AF_INET: 2633*7c478bd9Sstevel@tonic-gate addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; 2634*7c478bd9Sstevel@tonic-gate break; 2635*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2636*7c478bd9Sstevel@tonic-gate 2637*7c478bd9Sstevel@tonic-gate #if NETINET6 2638*7c478bd9Sstevel@tonic-gate case AF_INET6: 2639*7c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 2640*7c478bd9Sstevel@tonic-gate &ConnectOnlyTo.sin6.sin6_addr, 2641*7c478bd9Sstevel@tonic-gate IN6ADDRSZ); 2642*7c478bd9Sstevel@tonic-gate break; 2643*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2644*7c478bd9Sstevel@tonic-gate } 2645*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2646*7c478bd9Sstevel@tonic-gate sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr)); 2647*7c478bd9Sstevel@tonic-gate i = connect(s, (struct sockaddr *) &addr, addrlen); 2648*7c478bd9Sstevel@tonic-gate save_errno = errno; 2649*7c478bd9Sstevel@tonic-gate if (ev != NULL) 2650*7c478bd9Sstevel@tonic-gate sm_clrevent(ev); 2651*7c478bd9Sstevel@tonic-gate if (i >= 0) 2652*7c478bd9Sstevel@tonic-gate break; 2653*7c478bd9Sstevel@tonic-gate } 2654*7c478bd9Sstevel@tonic-gate else 2655*7c478bd9Sstevel@tonic-gate save_errno = errno; 2656*7c478bd9Sstevel@tonic-gate 2657*7c478bd9Sstevel@tonic-gate /* couldn't connect.... figure out why */ 2658*7c478bd9Sstevel@tonic-gate (void) close(s); 2659*7c478bd9Sstevel@tonic-gate 2660*7c478bd9Sstevel@tonic-gate /* if running demand-dialed connection, try again */ 2661*7c478bd9Sstevel@tonic-gate if (DialDelay > 0 && firstconnect && 2662*7c478bd9Sstevel@tonic-gate bitnset(M_DIALDELAY, mci->mci_mailer->m_flags)) 2663*7c478bd9Sstevel@tonic-gate { 2664*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2665*7c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying again...\n", 2666*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 2667*7c478bd9Sstevel@tonic-gate firstconnect = false; 2668*7c478bd9Sstevel@tonic-gate (void) sleep(DialDelay); 2669*7c478bd9Sstevel@tonic-gate continue; 2670*7c478bd9Sstevel@tonic-gate } 2671*7c478bd9Sstevel@tonic-gate 2672*7c478bd9Sstevel@tonic-gate if (LogLevel > 13) 2673*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 2674*7c478bd9Sstevel@tonic-gate "makeconnection (%s [%s]) failed: %s", 2675*7c478bd9Sstevel@tonic-gate host, anynet_ntoa(&addr), 2676*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 2677*7c478bd9Sstevel@tonic-gate 2678*7c478bd9Sstevel@tonic-gate #if NETINET6 2679*7c478bd9Sstevel@tonic-gate nextaddr: 2680*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2681*7c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_addr_list[addrno] != NULL && 2682*7c478bd9Sstevel@tonic-gate (enough == 0 || curtime() < enough)) 2683*7c478bd9Sstevel@tonic-gate { 2684*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2685*7c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); trying new address....\n", 2686*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 2687*7c478bd9Sstevel@tonic-gate switch (addr.sa.sa_family) 2688*7c478bd9Sstevel@tonic-gate { 2689*7c478bd9Sstevel@tonic-gate #if NETINET 2690*7c478bd9Sstevel@tonic-gate case AF_INET: 2691*7c478bd9Sstevel@tonic-gate memmove(&addr.sin.sin_addr, 2692*7c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 2693*7c478bd9Sstevel@tonic-gate INADDRSZ); 2694*7c478bd9Sstevel@tonic-gate break; 2695*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 2696*7c478bd9Sstevel@tonic-gate 2697*7c478bd9Sstevel@tonic-gate #if NETINET6 2698*7c478bd9Sstevel@tonic-gate case AF_INET6: 2699*7c478bd9Sstevel@tonic-gate memmove(&addr.sin6.sin6_addr, 2700*7c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 2701*7c478bd9Sstevel@tonic-gate IN6ADDRSZ); 2702*7c478bd9Sstevel@tonic-gate break; 2703*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2704*7c478bd9Sstevel@tonic-gate 2705*7c478bd9Sstevel@tonic-gate default: 2706*7c478bd9Sstevel@tonic-gate memmove(addr.sa.sa_data, 2707*7c478bd9Sstevel@tonic-gate hp->h_addr_list[addrno++], 2708*7c478bd9Sstevel@tonic-gate hp->h_length); 2709*7c478bd9Sstevel@tonic-gate break; 2710*7c478bd9Sstevel@tonic-gate } 2711*7c478bd9Sstevel@tonic-gate continue; 2712*7c478bd9Sstevel@tonic-gate } 2713*7c478bd9Sstevel@tonic-gate errno = save_errno; 2714*7c478bd9Sstevel@tonic-gate 2715*7c478bd9Sstevel@tonic-gate #if NETINET6 2716*7c478bd9Sstevel@tonic-gate if (family == AF_INET6) 2717*7c478bd9Sstevel@tonic-gate { 2718*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2719*7c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s); retrying with AF_INET....\n", 2720*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 2721*7c478bd9Sstevel@tonic-gate v6found = true; 2722*7c478bd9Sstevel@tonic-gate family = AF_INET; 2723*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2724*7c478bd9Sstevel@tonic-gate { 2725*7c478bd9Sstevel@tonic-gate freehostent(hp); 2726*7c478bd9Sstevel@tonic-gate hp = NULL; 2727*7c478bd9Sstevel@tonic-gate } 2728*7c478bd9Sstevel@tonic-gate goto v4retry; 2729*7c478bd9Sstevel@tonic-gate } 2730*7c478bd9Sstevel@tonic-gate v6tempfail: 2731*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2732*7c478bd9Sstevel@tonic-gate /* couldn't open connection */ 2733*7c478bd9Sstevel@tonic-gate #if NETINET6 2734*7c478bd9Sstevel@tonic-gate /* Don't clobber an already saved errno from v4retry */ 2735*7c478bd9Sstevel@tonic-gate if (errno > 0) 2736*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2737*7c478bd9Sstevel@tonic-gate save_errno = errno; 2738*7c478bd9Sstevel@tonic-gate if (tTd(16, 1)) 2739*7c478bd9Sstevel@tonic-gate sm_dprintf("Connect failed (%s)\n", 2740*7c478bd9Sstevel@tonic-gate sm_errstring(save_errno)); 2741*7c478bd9Sstevel@tonic-gate #if XLA 2742*7c478bd9Sstevel@tonic-gate xla_host_end(host); 2743*7c478bd9Sstevel@tonic-gate #endif /* XLA */ 2744*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2745*7c478bd9Sstevel@tonic-gate #if NETINET6 2746*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2747*7c478bd9Sstevel@tonic-gate freehostent(hp); 2748*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2749*7c478bd9Sstevel@tonic-gate errno = save_errno; 2750*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2751*7c478bd9Sstevel@tonic-gate } 2752*7c478bd9Sstevel@tonic-gate 2753*7c478bd9Sstevel@tonic-gate #if NETINET6 2754*7c478bd9Sstevel@tonic-gate if (hp != NULL) 2755*7c478bd9Sstevel@tonic-gate { 2756*7c478bd9Sstevel@tonic-gate freehostent(hp); 2757*7c478bd9Sstevel@tonic-gate hp = NULL; 2758*7c478bd9Sstevel@tonic-gate } 2759*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 2760*7c478bd9Sstevel@tonic-gate 2761*7c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 2762*7c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 2763*7c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2764*7c478bd9Sstevel@tonic-gate (void *) &s, 2765*7c478bd9Sstevel@tonic-gate SM_IO_WRONLY_B, NULL)) == NULL || 2766*7c478bd9Sstevel@tonic-gate (s = dup(s)) < 0 || 2767*7c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2768*7c478bd9Sstevel@tonic-gate (void *) &s, 2769*7c478bd9Sstevel@tonic-gate SM_IO_RDONLY_B, NULL)) == NULL) 2770*7c478bd9Sstevel@tonic-gate { 2771*7c478bd9Sstevel@tonic-gate save_errno = errno; 2772*7c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", s); 2773*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2774*7c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 2775*7c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2776*7c478bd9Sstevel@tonic-gate (void) close(s); 2777*7c478bd9Sstevel@tonic-gate errno = save_errno; 2778*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2779*7c478bd9Sstevel@tonic-gate } 2780*7c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 2781*7c478bd9Sstevel@tonic-gate 2782*7c478bd9Sstevel@tonic-gate /* set {client_flags} */ 2783*7c478bd9Sstevel@tonic-gate if (ClientSettings[addr.sa.sa_family].d_mflags != NULL) 2784*7c478bd9Sstevel@tonic-gate { 2785*7c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 2786*7c478bd9Sstevel@tonic-gate macid("{client_flags}"), 2787*7c478bd9Sstevel@tonic-gate ClientSettings[addr.sa.sa_family].d_mflags); 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate else 2790*7c478bd9Sstevel@tonic-gate macdefine(&mci->mci_macro, A_PERM, 2791*7c478bd9Sstevel@tonic-gate macid("{client_flags}"), ""); 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate /* "add" {client_flags} to bitmap */ 2794*7c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags)) 2795*7c478bd9Sstevel@tonic-gate { 2796*7c478bd9Sstevel@tonic-gate /* look for just this one flag */ 2797*7c478bd9Sstevel@tonic-gate setbitn(D_IFNHELO, d_flags); 2798*7c478bd9Sstevel@tonic-gate } 2799*7c478bd9Sstevel@tonic-gate 2800*7c478bd9Sstevel@tonic-gate /* find out name for Interface through which we connect */ 2801*7c478bd9Sstevel@tonic-gate len = sizeof addr; 2802*7c478bd9Sstevel@tonic-gate if (getsockname(s, &addr.sa, &len) == 0) 2803*7c478bd9Sstevel@tonic-gate { 2804*7c478bd9Sstevel@tonic-gate char *name; 2805*7c478bd9Sstevel@tonic-gate char family[5]; 2806*7c478bd9Sstevel@tonic-gate 2807*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 2808*7c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), anynet_ntoa(&addr)); 2809*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(family, sizeof(family), "%d", 2810*7c478bd9Sstevel@tonic-gate addr.sa.sa_family); 2811*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 2812*7c478bd9Sstevel@tonic-gate macid("{if_family_out}"), family); 2813*7c478bd9Sstevel@tonic-gate 2814*7c478bd9Sstevel@tonic-gate name = hostnamebyanyaddr(&addr); 2815*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 2816*7c478bd9Sstevel@tonic-gate macid("{if_name_out}"), name); 2817*7c478bd9Sstevel@tonic-gate if (LogLevel > 11) 2818*7c478bd9Sstevel@tonic-gate { 2819*7c478bd9Sstevel@tonic-gate /* log connection information */ 2820*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 2821*7c478bd9Sstevel@tonic-gate "SMTP outgoing connect on %.40s", name); 2822*7c478bd9Sstevel@tonic-gate } 2823*7c478bd9Sstevel@tonic-gate if (bitnset(D_IFNHELO, d_flags)) 2824*7c478bd9Sstevel@tonic-gate { 2825*7c478bd9Sstevel@tonic-gate if (name[0] != '[' && strchr(name, '.') != NULL) 2826*7c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(name); 2827*7c478bd9Sstevel@tonic-gate } 2828*7c478bd9Sstevel@tonic-gate } 2829*7c478bd9Sstevel@tonic-gate else 2830*7c478bd9Sstevel@tonic-gate { 2831*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 2832*7c478bd9Sstevel@tonic-gate macid("{if_name_out}"), NULL); 2833*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 2834*7c478bd9Sstevel@tonic-gate macid("{if_addr_out}"), NULL); 2835*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 2836*7c478bd9Sstevel@tonic-gate macid("{if_family_out}"), NULL); 2837*7c478bd9Sstevel@tonic-gate } 2838*7c478bd9Sstevel@tonic-gate 2839*7c478bd9Sstevel@tonic-gate #if _FFR_HELONAME 2840*7c478bd9Sstevel@tonic-gate /* Use the configured HeloName as appropriate */ 2841*7c478bd9Sstevel@tonic-gate if (HeloName != NULL && HeloName[0] != '\0') 2842*7c478bd9Sstevel@tonic-gate mci->mci_heloname = newstr(HeloName); 2843*7c478bd9Sstevel@tonic-gate #endif /* _FFR_HELONAME */ 2844*7c478bd9Sstevel@tonic-gate 2845*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 2846*7c478bd9Sstevel@tonic-gate return EX_OK; 2847*7c478bd9Sstevel@tonic-gate } 2848*7c478bd9Sstevel@tonic-gate 2849*7c478bd9Sstevel@tonic-gate static void 2850*7c478bd9Sstevel@tonic-gate connecttimeout(ignore) 2851*7c478bd9Sstevel@tonic-gate int ignore; 2852*7c478bd9Sstevel@tonic-gate { 2853*7c478bd9Sstevel@tonic-gate /* 2854*7c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2855*7c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2856*7c478bd9Sstevel@tonic-gate ** DOING. 2857*7c478bd9Sstevel@tonic-gate */ 2858*7c478bd9Sstevel@tonic-gate 2859*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 2860*7c478bd9Sstevel@tonic-gate longjmp(CtxConnectTimeout, 1); 2861*7c478bd9Sstevel@tonic-gate } 2862*7c478bd9Sstevel@tonic-gate /* 2863*7c478bd9Sstevel@tonic-gate ** MAKECONNECTION_DS -- make a connection to a domain socket. 2864*7c478bd9Sstevel@tonic-gate ** 2865*7c478bd9Sstevel@tonic-gate ** Parameters: 2866*7c478bd9Sstevel@tonic-gate ** mux_path -- the path of the socket to connect to. 2867*7c478bd9Sstevel@tonic-gate ** mci -- a pointer to the mail connection information 2868*7c478bd9Sstevel@tonic-gate ** structure to be filled in. 2869*7c478bd9Sstevel@tonic-gate ** 2870*7c478bd9Sstevel@tonic-gate ** Returns: 2871*7c478bd9Sstevel@tonic-gate ** An exit code telling whether the connection could be 2872*7c478bd9Sstevel@tonic-gate ** made and if not why not. 2873*7c478bd9Sstevel@tonic-gate ** 2874*7c478bd9Sstevel@tonic-gate ** Side Effects: 2875*7c478bd9Sstevel@tonic-gate ** none. 2876*7c478bd9Sstevel@tonic-gate */ 2877*7c478bd9Sstevel@tonic-gate 2878*7c478bd9Sstevel@tonic-gate #if NETUNIX 2879*7c478bd9Sstevel@tonic-gate int 2880*7c478bd9Sstevel@tonic-gate makeconnection_ds(mux_path, mci) 2881*7c478bd9Sstevel@tonic-gate char *mux_path; 2882*7c478bd9Sstevel@tonic-gate register MCI *mci; 2883*7c478bd9Sstevel@tonic-gate { 2884*7c478bd9Sstevel@tonic-gate int sock; 2885*7c478bd9Sstevel@tonic-gate int rval, save_errno; 2886*7c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; 2887*7c478bd9Sstevel@tonic-gate struct sockaddr_un unix_addr; 2888*7c478bd9Sstevel@tonic-gate 2889*7c478bd9Sstevel@tonic-gate /* if not safe, don't connect */ 2890*7c478bd9Sstevel@tonic-gate rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, 2891*7c478bd9Sstevel@tonic-gate sff, S_IRUSR|S_IWUSR, NULL); 2892*7c478bd9Sstevel@tonic-gate 2893*7c478bd9Sstevel@tonic-gate if (rval != 0) 2894*7c478bd9Sstevel@tonic-gate { 2895*7c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: unsafe domain socket %s", 2896*7c478bd9Sstevel@tonic-gate mux_path); 2897*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); 2898*7c478bd9Sstevel@tonic-gate errno = rval; 2899*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2900*7c478bd9Sstevel@tonic-gate } 2901*7c478bd9Sstevel@tonic-gate 2902*7c478bd9Sstevel@tonic-gate /* prepare address structure */ 2903*7c478bd9Sstevel@tonic-gate memset(&unix_addr, '\0', sizeof unix_addr); 2904*7c478bd9Sstevel@tonic-gate unix_addr.sun_family = AF_UNIX; 2905*7c478bd9Sstevel@tonic-gate 2906*7c478bd9Sstevel@tonic-gate if (strlen(mux_path) >= sizeof unix_addr.sun_path) 2907*7c478bd9Sstevel@tonic-gate { 2908*7c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: domain socket name %s too long", 2909*7c478bd9Sstevel@tonic-gate mux_path); 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate /* XXX why TEMPFAIL but 5.x.y ? */ 2912*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); 2913*7c478bd9Sstevel@tonic-gate errno = ENAMETOOLONG; 2914*7c478bd9Sstevel@tonic-gate return EX_UNAVAILABLE; 2915*7c478bd9Sstevel@tonic-gate } 2916*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(unix_addr.sun_path, mux_path, 2917*7c478bd9Sstevel@tonic-gate sizeof unix_addr.sun_path); 2918*7c478bd9Sstevel@tonic-gate 2919*7c478bd9Sstevel@tonic-gate /* initialize domain socket */ 2920*7c478bd9Sstevel@tonic-gate sock = socket(AF_UNIX, SOCK_STREAM, 0); 2921*7c478bd9Sstevel@tonic-gate if (sock == -1) 2922*7c478bd9Sstevel@tonic-gate { 2923*7c478bd9Sstevel@tonic-gate save_errno = errno; 2924*7c478bd9Sstevel@tonic-gate syserr("makeconnection_ds: could not create domain socket %s", 2925*7c478bd9Sstevel@tonic-gate mux_path); 2926*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2927*7c478bd9Sstevel@tonic-gate errno = save_errno; 2928*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2929*7c478bd9Sstevel@tonic-gate } 2930*7c478bd9Sstevel@tonic-gate 2931*7c478bd9Sstevel@tonic-gate /* connect to server */ 2932*7c478bd9Sstevel@tonic-gate if (connect(sock, (struct sockaddr *) &unix_addr, 2933*7c478bd9Sstevel@tonic-gate sizeof(unix_addr)) == -1) 2934*7c478bd9Sstevel@tonic-gate { 2935*7c478bd9Sstevel@tonic-gate save_errno = errno; 2936*7c478bd9Sstevel@tonic-gate syserr("Could not connect to socket %s", mux_path); 2937*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); 2938*7c478bd9Sstevel@tonic-gate (void) close(sock); 2939*7c478bd9Sstevel@tonic-gate errno = save_errno; 2940*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2941*7c478bd9Sstevel@tonic-gate } 2942*7c478bd9Sstevel@tonic-gate 2943*7c478bd9Sstevel@tonic-gate /* connection ok, put it into canonical form */ 2944*7c478bd9Sstevel@tonic-gate mci->mci_out = NULL; 2945*7c478bd9Sstevel@tonic-gate if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2946*7c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_WRONLY_B, NULL)) 2947*7c478bd9Sstevel@tonic-gate == NULL 2948*7c478bd9Sstevel@tonic-gate || (sock = dup(sock)) < 0 || 2949*7c478bd9Sstevel@tonic-gate (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 2950*7c478bd9Sstevel@tonic-gate (void *) &sock, SM_IO_RDONLY_B, NULL)) 2951*7c478bd9Sstevel@tonic-gate == NULL) 2952*7c478bd9Sstevel@tonic-gate { 2953*7c478bd9Sstevel@tonic-gate save_errno = errno; 2954*7c478bd9Sstevel@tonic-gate syserr("cannot open SMTP client channel, fd=%d", sock); 2955*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); 2956*7c478bd9Sstevel@tonic-gate if (mci->mci_out != NULL) 2957*7c478bd9Sstevel@tonic-gate (void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT); 2958*7c478bd9Sstevel@tonic-gate (void) close(sock); 2959*7c478bd9Sstevel@tonic-gate errno = save_errno; 2960*7c478bd9Sstevel@tonic-gate return EX_TEMPFAIL; 2961*7c478bd9Sstevel@tonic-gate } 2962*7c478bd9Sstevel@tonic-gate sm_io_automode(mci->mci_out, mci->mci_in); 2963*7c478bd9Sstevel@tonic-gate 2964*7c478bd9Sstevel@tonic-gate mci_setstat(mci, EX_OK, NULL, NULL); 2965*7c478bd9Sstevel@tonic-gate errno = 0; 2966*7c478bd9Sstevel@tonic-gate return EX_OK; 2967*7c478bd9Sstevel@tonic-gate } 2968*7c478bd9Sstevel@tonic-gate #endif /* NETUNIX */ 2969*7c478bd9Sstevel@tonic-gate /* 2970*7c478bd9Sstevel@tonic-gate ** SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon 2971*7c478bd9Sstevel@tonic-gate ** 2972*7c478bd9Sstevel@tonic-gate ** Parameters: 2973*7c478bd9Sstevel@tonic-gate ** none. 2974*7c478bd9Sstevel@tonic-gate ** 2975*7c478bd9Sstevel@tonic-gate ** Returns: 2976*7c478bd9Sstevel@tonic-gate ** none. 2977*7c478bd9Sstevel@tonic-gate ** 2978*7c478bd9Sstevel@tonic-gate ** Side Effects: 2979*7c478bd9Sstevel@tonic-gate ** closes control socket, exits. 2980*7c478bd9Sstevel@tonic-gate */ 2981*7c478bd9Sstevel@tonic-gate 2982*7c478bd9Sstevel@tonic-gate void 2983*7c478bd9Sstevel@tonic-gate shutdown_daemon() 2984*7c478bd9Sstevel@tonic-gate { 2985*7c478bd9Sstevel@tonic-gate int i; 2986*7c478bd9Sstevel@tonic-gate char *reason; 2987*7c478bd9Sstevel@tonic-gate 2988*7c478bd9Sstevel@tonic-gate sm_allsignals(true); 2989*7c478bd9Sstevel@tonic-gate 2990*7c478bd9Sstevel@tonic-gate reason = ShutdownRequest; 2991*7c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 2992*7c478bd9Sstevel@tonic-gate PendingSignal = 0; 2993*7c478bd9Sstevel@tonic-gate 2994*7c478bd9Sstevel@tonic-gate if (LogLevel > 9) 2995*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s", 2996*7c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 2997*7c478bd9Sstevel@tonic-gate 2998*7c478bd9Sstevel@tonic-gate FileName = NULL; 2999*7c478bd9Sstevel@tonic-gate closecontrolsocket(true); 3000*7c478bd9Sstevel@tonic-gate #if XLA 3001*7c478bd9Sstevel@tonic-gate xla_all_end(); 3002*7c478bd9Sstevel@tonic-gate #endif /* XLA */ 3003*7c478bd9Sstevel@tonic-gate 3004*7c478bd9Sstevel@tonic-gate for (i = 0; i < NDaemons; i++) 3005*7c478bd9Sstevel@tonic-gate { 3006*7c478bd9Sstevel@tonic-gate if (Daemons[i].d_socket >= 0) 3007*7c478bd9Sstevel@tonic-gate { 3008*7c478bd9Sstevel@tonic-gate (void) close(Daemons[i].d_socket); 3009*7c478bd9Sstevel@tonic-gate Daemons[i].d_socket = -1; 3010*7c478bd9Sstevel@tonic-gate 3011*7c478bd9Sstevel@tonic-gate #if _FFR_DAEMON_NETUNIX 3012*7c478bd9Sstevel@tonic-gate # if NETUNIX 3013*7c478bd9Sstevel@tonic-gate /* Remove named sockets */ 3014*7c478bd9Sstevel@tonic-gate if (Daemons[i].d_addr.sa.sa_family == AF_UNIX) 3015*7c478bd9Sstevel@tonic-gate { 3016*7c478bd9Sstevel@tonic-gate int rval; 3017*7c478bd9Sstevel@tonic-gate long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT; 3018*7c478bd9Sstevel@tonic-gate 3019*7c478bd9Sstevel@tonic-gate /* if not safe, don't use it */ 3020*7c478bd9Sstevel@tonic-gate rval = safefile(Daemons[i].d_addr.sunix.sun_path, 3021*7c478bd9Sstevel@tonic-gate RunAsUid, RunAsGid, 3022*7c478bd9Sstevel@tonic-gate RunAsUserName, sff, 3023*7c478bd9Sstevel@tonic-gate S_IRUSR|S_IWUSR, NULL); 3024*7c478bd9Sstevel@tonic-gate if (rval == 0 && 3025*7c478bd9Sstevel@tonic-gate unlink(Daemons[i].d_addr.sunix.sun_path) < 0) 3026*7c478bd9Sstevel@tonic-gate { 3027*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 3028*7c478bd9Sstevel@tonic-gate "Could not remove daemon %s socket: %s: %s", 3029*7c478bd9Sstevel@tonic-gate Daemons[i].d_name, 3030*7c478bd9Sstevel@tonic-gate Daemons[i].d_addr.sunix.sun_path, 3031*7c478bd9Sstevel@tonic-gate sm_errstring(errno)); 3032*7c478bd9Sstevel@tonic-gate } 3033*7c478bd9Sstevel@tonic-gate } 3034*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 3035*7c478bd9Sstevel@tonic-gate #endif /* _FFR_DAEMON_NETUNIX */ 3036*7c478bd9Sstevel@tonic-gate } 3037*7c478bd9Sstevel@tonic-gate } 3038*7c478bd9Sstevel@tonic-gate 3039*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 3040*7c478bd9Sstevel@tonic-gate } 3041*7c478bd9Sstevel@tonic-gate /* 3042*7c478bd9Sstevel@tonic-gate ** RESTART_DAEMON -- Performs a clean restart of the daemon 3043*7c478bd9Sstevel@tonic-gate ** 3044*7c478bd9Sstevel@tonic-gate ** Parameters: 3045*7c478bd9Sstevel@tonic-gate ** none. 3046*7c478bd9Sstevel@tonic-gate ** 3047*7c478bd9Sstevel@tonic-gate ** Returns: 3048*7c478bd9Sstevel@tonic-gate ** none. 3049*7c478bd9Sstevel@tonic-gate ** 3050*7c478bd9Sstevel@tonic-gate ** Side Effects: 3051*7c478bd9Sstevel@tonic-gate ** restarts the daemon or exits if restart fails. 3052*7c478bd9Sstevel@tonic-gate */ 3053*7c478bd9Sstevel@tonic-gate 3054*7c478bd9Sstevel@tonic-gate /* Make a non-DFL/IGN signal a noop */ 3055*7c478bd9Sstevel@tonic-gate #define SM_NOOP_SIGNAL(sig, old) \ 3056*7c478bd9Sstevel@tonic-gate do \ 3057*7c478bd9Sstevel@tonic-gate { \ 3058*7c478bd9Sstevel@tonic-gate (old) = sm_signal((sig), sm_signal_noop); \ 3059*7c478bd9Sstevel@tonic-gate if ((old) == SIG_IGN || (old) == SIG_DFL) \ 3060*7c478bd9Sstevel@tonic-gate (void) sm_signal((sig), (old)); \ 3061*7c478bd9Sstevel@tonic-gate } while (0) 3062*7c478bd9Sstevel@tonic-gate 3063*7c478bd9Sstevel@tonic-gate void 3064*7c478bd9Sstevel@tonic-gate restart_daemon() 3065*7c478bd9Sstevel@tonic-gate { 3066*7c478bd9Sstevel@tonic-gate bool drop; 3067*7c478bd9Sstevel@tonic-gate int save_errno; 3068*7c478bd9Sstevel@tonic-gate char *reason; 3069*7c478bd9Sstevel@tonic-gate sigfunc_t ignore, oalrm, ousr1; 3070*7c478bd9Sstevel@tonic-gate extern int DtableSize; 3071*7c478bd9Sstevel@tonic-gate 3072*7c478bd9Sstevel@tonic-gate /* clear the events to turn off SIGALRMs */ 3073*7c478bd9Sstevel@tonic-gate sm_clear_events(); 3074*7c478bd9Sstevel@tonic-gate sm_allsignals(true); 3075*7c478bd9Sstevel@tonic-gate 3076*7c478bd9Sstevel@tonic-gate reason = RestartRequest; 3077*7c478bd9Sstevel@tonic-gate RestartRequest = NULL; 3078*7c478bd9Sstevel@tonic-gate PendingSignal = 0; 3079*7c478bd9Sstevel@tonic-gate 3080*7c478bd9Sstevel@tonic-gate if (SaveArgv[0][0] != '/') 3081*7c478bd9Sstevel@tonic-gate { 3082*7c478bd9Sstevel@tonic-gate if (LogLevel > 3) 3083*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 3084*7c478bd9Sstevel@tonic-gate "could not restart: need full path"); 3085*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 3086*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3087*7c478bd9Sstevel@tonic-gate } 3088*7c478bd9Sstevel@tonic-gate if (LogLevel > 3) 3089*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", 3090*7c478bd9Sstevel@tonic-gate SaveArgv[0], 3091*7c478bd9Sstevel@tonic-gate reason == NULL ? "implicit call" : reason); 3092*7c478bd9Sstevel@tonic-gate 3093*7c478bd9Sstevel@tonic-gate closecontrolsocket(true); 3094*7c478bd9Sstevel@tonic-gate #if SM_CONF_SHM 3095*7c478bd9Sstevel@tonic-gate cleanup_shm(DaemonPid == getpid()); 3096*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SHM */ 3097*7c478bd9Sstevel@tonic-gate 3098*7c478bd9Sstevel@tonic-gate /* close locked pid file */ 3099*7c478bd9Sstevel@tonic-gate close_sendmail_pid(); 3100*7c478bd9Sstevel@tonic-gate 3101*7c478bd9Sstevel@tonic-gate /* 3102*7c478bd9Sstevel@tonic-gate ** Want to drop to the user who started the process in all cases 3103*7c478bd9Sstevel@tonic-gate ** *but* when running as "smmsp" for the clientmqueue queue run 3104*7c478bd9Sstevel@tonic-gate ** daemon. In that case, UseMSP will be true, RunAsUid should not 3105*7c478bd9Sstevel@tonic-gate ** be root, and RealUid should be either 0 or RunAsUid. 3106*7c478bd9Sstevel@tonic-gate */ 3107*7c478bd9Sstevel@tonic-gate 3108*7c478bd9Sstevel@tonic-gate drop = !(UseMSP && RunAsUid != 0 && 3109*7c478bd9Sstevel@tonic-gate (RealUid == 0 || RealUid == RunAsUid)); 3110*7c478bd9Sstevel@tonic-gate 3111*7c478bd9Sstevel@tonic-gate if (drop_privileges(drop) != EX_OK) 3112*7c478bd9Sstevel@tonic-gate { 3113*7c478bd9Sstevel@tonic-gate if (LogLevel > 0) 3114*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 3115*7c478bd9Sstevel@tonic-gate "could not drop privileges: %s", 3116*7c478bd9Sstevel@tonic-gate sm_errstring(errno)); 3117*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OSERR); 3118*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3119*7c478bd9Sstevel@tonic-gate } 3120*7c478bd9Sstevel@tonic-gate 3121*7c478bd9Sstevel@tonic-gate sm_close_on_exec(STDERR_FILENO + 1, DtableSize); 3122*7c478bd9Sstevel@tonic-gate 3123*7c478bd9Sstevel@tonic-gate /* 3124*7c478bd9Sstevel@tonic-gate ** Need to allow signals before execve() to make them "harmless". 3125*7c478bd9Sstevel@tonic-gate ** However, the default action can be "terminate", so it isn't 3126*7c478bd9Sstevel@tonic-gate ** really harmless. Setting signals to IGN will cause them to be 3127*7c478bd9Sstevel@tonic-gate ** ignored in the new process to, so that isn't a good alternative. 3128*7c478bd9Sstevel@tonic-gate */ 3129*7c478bd9Sstevel@tonic-gate 3130*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGALRM, oalrm); 3131*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGCHLD, ignore); 3132*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGHUP, ignore); 3133*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGINT, ignore); 3134*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGPIPE, ignore); 3135*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGTERM, ignore); 3136*7c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 3137*7c478bd9Sstevel@tonic-gate SM_NOOP_SIGNAL(SIGUSR1, ousr1); 3138*7c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 3139*7c478bd9Sstevel@tonic-gate 3140*7c478bd9Sstevel@tonic-gate /* Turn back on signals */ 3141*7c478bd9Sstevel@tonic-gate sm_allsignals(false); 3142*7c478bd9Sstevel@tonic-gate 3143*7c478bd9Sstevel@tonic-gate (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); 3144*7c478bd9Sstevel@tonic-gate save_errno = errno; 3145*7c478bd9Sstevel@tonic-gate 3146*7c478bd9Sstevel@tonic-gate /* block signals again and restore needed signals */ 3147*7c478bd9Sstevel@tonic-gate sm_allsignals(true); 3148*7c478bd9Sstevel@tonic-gate 3149*7c478bd9Sstevel@tonic-gate /* For finis() events */ 3150*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGALRM, oalrm); 3151*7c478bd9Sstevel@tonic-gate 3152*7c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 3153*7c478bd9Sstevel@tonic-gate /* For debugging finis() */ 3154*7c478bd9Sstevel@tonic-gate (void) sm_signal(SIGUSR1, ousr1); 3155*7c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 3156*7c478bd9Sstevel@tonic-gate 3157*7c478bd9Sstevel@tonic-gate errno = save_errno; 3158*7c478bd9Sstevel@tonic-gate if (LogLevel > 0) 3159*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s", 3160*7c478bd9Sstevel@tonic-gate SaveArgv[0], sm_errstring(errno)); 3161*7c478bd9Sstevel@tonic-gate finis(false, true, EX_OSFILE); 3162*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3163*7c478bd9Sstevel@tonic-gate } 3164*7c478bd9Sstevel@tonic-gate /* 3165*7c478bd9Sstevel@tonic-gate ** MYHOSTNAME -- return the name of this host. 3166*7c478bd9Sstevel@tonic-gate ** 3167*7c478bd9Sstevel@tonic-gate ** Parameters: 3168*7c478bd9Sstevel@tonic-gate ** hostbuf -- a place to return the name of this host. 3169*7c478bd9Sstevel@tonic-gate ** size -- the size of hostbuf. 3170*7c478bd9Sstevel@tonic-gate ** 3171*7c478bd9Sstevel@tonic-gate ** Returns: 3172*7c478bd9Sstevel@tonic-gate ** A list of aliases for this host. 3173*7c478bd9Sstevel@tonic-gate ** 3174*7c478bd9Sstevel@tonic-gate ** Side Effects: 3175*7c478bd9Sstevel@tonic-gate ** Adds numeric codes to $=w. 3176*7c478bd9Sstevel@tonic-gate */ 3177*7c478bd9Sstevel@tonic-gate 3178*7c478bd9Sstevel@tonic-gate struct hostent * 3179*7c478bd9Sstevel@tonic-gate myhostname(hostbuf, size) 3180*7c478bd9Sstevel@tonic-gate char hostbuf[]; 3181*7c478bd9Sstevel@tonic-gate int size; 3182*7c478bd9Sstevel@tonic-gate { 3183*7c478bd9Sstevel@tonic-gate register struct hostent *hp; 3184*7c478bd9Sstevel@tonic-gate 3185*7c478bd9Sstevel@tonic-gate if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') 3186*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hostbuf, "localhost", size); 3187*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, InetMode); 3188*7c478bd9Sstevel@tonic-gate #if NETINET && NETINET6 3189*7c478bd9Sstevel@tonic-gate if (hp == NULL && InetMode == AF_INET6) 3190*7c478bd9Sstevel@tonic-gate { 3191*7c478bd9Sstevel@tonic-gate /* 3192*7c478bd9Sstevel@tonic-gate ** It's possible that this IPv6 enabled machine doesn't 3193*7c478bd9Sstevel@tonic-gate ** actually have any IPv6 interfaces and, therefore, no 3194*7c478bd9Sstevel@tonic-gate ** IPv6 addresses. Fall back to AF_INET. 3195*7c478bd9Sstevel@tonic-gate */ 3196*7c478bd9Sstevel@tonic-gate 3197*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(hostbuf, AF_INET); 3198*7c478bd9Sstevel@tonic-gate } 3199*7c478bd9Sstevel@tonic-gate #endif /* NETINET && NETINET6 */ 3200*7c478bd9Sstevel@tonic-gate if (hp == NULL) 3201*7c478bd9Sstevel@tonic-gate return NULL; 3202*7c478bd9Sstevel@tonic-gate if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) 3203*7c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, hp->h_name, size); 3204*7c478bd9Sstevel@tonic-gate 3205*7c478bd9Sstevel@tonic-gate #if NETINFO 3206*7c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 3207*7c478bd9Sstevel@tonic-gate { 3208*7c478bd9Sstevel@tonic-gate char *domainname; 3209*7c478bd9Sstevel@tonic-gate 3210*7c478bd9Sstevel@tonic-gate domainname = ni_propval("/locations", NULL, "resolver", 3211*7c478bd9Sstevel@tonic-gate "domain", '\0'); 3212*7c478bd9Sstevel@tonic-gate if (domainname != NULL && 3213*7c478bd9Sstevel@tonic-gate strlen(domainname) + strlen(hostbuf) + 1 < size) 3214*7c478bd9Sstevel@tonic-gate (void) sm_strlcat2(hostbuf, ".", domainname, size); 3215*7c478bd9Sstevel@tonic-gate } 3216*7c478bd9Sstevel@tonic-gate #endif /* NETINFO */ 3217*7c478bd9Sstevel@tonic-gate 3218*7c478bd9Sstevel@tonic-gate /* 3219*7c478bd9Sstevel@tonic-gate ** If there is still no dot in the name, try looking for a 3220*7c478bd9Sstevel@tonic-gate ** dotted alias. 3221*7c478bd9Sstevel@tonic-gate */ 3222*7c478bd9Sstevel@tonic-gate 3223*7c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL) 3224*7c478bd9Sstevel@tonic-gate { 3225*7c478bd9Sstevel@tonic-gate char **ha; 3226*7c478bd9Sstevel@tonic-gate 3227*7c478bd9Sstevel@tonic-gate for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 3228*7c478bd9Sstevel@tonic-gate { 3229*7c478bd9Sstevel@tonic-gate if (strchr(*ha, '.') != NULL) 3230*7c478bd9Sstevel@tonic-gate { 3231*7c478bd9Sstevel@tonic-gate (void) cleanstrcpy(hostbuf, *ha, size - 1); 3232*7c478bd9Sstevel@tonic-gate hostbuf[size - 1] = '\0'; 3233*7c478bd9Sstevel@tonic-gate break; 3234*7c478bd9Sstevel@tonic-gate } 3235*7c478bd9Sstevel@tonic-gate } 3236*7c478bd9Sstevel@tonic-gate } 3237*7c478bd9Sstevel@tonic-gate 3238*7c478bd9Sstevel@tonic-gate /* 3239*7c478bd9Sstevel@tonic-gate ** If _still_ no dot, wait for a while and try again -- it is 3240*7c478bd9Sstevel@tonic-gate ** possible that some service is starting up. This can result 3241*7c478bd9Sstevel@tonic-gate ** in excessive delays if the system is badly configured, but 3242*7c478bd9Sstevel@tonic-gate ** there really isn't a way around that, particularly given that 3243*7c478bd9Sstevel@tonic-gate ** the config file hasn't been read at this point. 3244*7c478bd9Sstevel@tonic-gate ** All in all, a bit of a mess. 3245*7c478bd9Sstevel@tonic-gate */ 3246*7c478bd9Sstevel@tonic-gate 3247*7c478bd9Sstevel@tonic-gate if (strchr(hostbuf, '.') == NULL && 3248*7c478bd9Sstevel@tonic-gate !getcanonname(hostbuf, size, true, NULL)) 3249*7c478bd9Sstevel@tonic-gate { 3250*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_CRIT, NOQID, 3251*7c478bd9Sstevel@tonic-gate "My unqualified host name (%s) unknown; sleeping for retry", 3252*7c478bd9Sstevel@tonic-gate hostbuf); 3253*7c478bd9Sstevel@tonic-gate message("My unqualified host name (%s) unknown; sleeping for retry", 3254*7c478bd9Sstevel@tonic-gate hostbuf); 3255*7c478bd9Sstevel@tonic-gate (void) sleep(60); 3256*7c478bd9Sstevel@tonic-gate if (!getcanonname(hostbuf, size, true, NULL)) 3257*7c478bd9Sstevel@tonic-gate { 3258*7c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 3259*7c478bd9Sstevel@tonic-gate "unable to qualify my own domain name (%s) -- using short name", 3260*7c478bd9Sstevel@tonic-gate hostbuf); 3261*7c478bd9Sstevel@tonic-gate message("WARNING: unable to qualify my own domain name (%s) -- using short name", 3262*7c478bd9Sstevel@tonic-gate hostbuf); 3263*7c478bd9Sstevel@tonic-gate } 3264*7c478bd9Sstevel@tonic-gate } 3265*7c478bd9Sstevel@tonic-gate return hp; 3266*7c478bd9Sstevel@tonic-gate } 3267*7c478bd9Sstevel@tonic-gate /* 3268*7c478bd9Sstevel@tonic-gate ** ADDRCMP -- compare two host addresses 3269*7c478bd9Sstevel@tonic-gate ** 3270*7c478bd9Sstevel@tonic-gate ** Parameters: 3271*7c478bd9Sstevel@tonic-gate ** hp -- hostent structure for the first address 3272*7c478bd9Sstevel@tonic-gate ** ha -- actual first address 3273*7c478bd9Sstevel@tonic-gate ** sa -- second address 3274*7c478bd9Sstevel@tonic-gate ** 3275*7c478bd9Sstevel@tonic-gate ** Returns: 3276*7c478bd9Sstevel@tonic-gate ** 0 -- if ha and sa match 3277*7c478bd9Sstevel@tonic-gate ** else -- they don't match 3278*7c478bd9Sstevel@tonic-gate */ 3279*7c478bd9Sstevel@tonic-gate 3280*7c478bd9Sstevel@tonic-gate static int 3281*7c478bd9Sstevel@tonic-gate addrcmp(hp, ha, sa) 3282*7c478bd9Sstevel@tonic-gate struct hostent *hp; 3283*7c478bd9Sstevel@tonic-gate char *ha; 3284*7c478bd9Sstevel@tonic-gate SOCKADDR *sa; 3285*7c478bd9Sstevel@tonic-gate { 3286*7c478bd9Sstevel@tonic-gate #if NETINET6 3287*7c478bd9Sstevel@tonic-gate unsigned char *a; 3288*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3289*7c478bd9Sstevel@tonic-gate 3290*7c478bd9Sstevel@tonic-gate switch (sa->sa.sa_family) 3291*7c478bd9Sstevel@tonic-gate { 3292*7c478bd9Sstevel@tonic-gate #if NETINET 3293*7c478bd9Sstevel@tonic-gate case AF_INET: 3294*7c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET) 3295*7c478bd9Sstevel@tonic-gate return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); 3296*7c478bd9Sstevel@tonic-gate break; 3297*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 3298*7c478bd9Sstevel@tonic-gate 3299*7c478bd9Sstevel@tonic-gate #if NETINET6 3300*7c478bd9Sstevel@tonic-gate case AF_INET6: 3301*7c478bd9Sstevel@tonic-gate a = (unsigned char *) &sa->sin6.sin6_addr; 3302*7c478bd9Sstevel@tonic-gate 3303*7c478bd9Sstevel@tonic-gate /* Straight binary comparison */ 3304*7c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET6) 3305*7c478bd9Sstevel@tonic-gate return memcmp(ha, a, IN6ADDRSZ); 3306*7c478bd9Sstevel@tonic-gate 3307*7c478bd9Sstevel@tonic-gate /* If IPv4-mapped IPv6 address, compare the IPv4 section */ 3308*7c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET && 3309*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) 3310*7c478bd9Sstevel@tonic-gate return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); 3311*7c478bd9Sstevel@tonic-gate break; 3312*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3313*7c478bd9Sstevel@tonic-gate } 3314*7c478bd9Sstevel@tonic-gate return -1; 3315*7c478bd9Sstevel@tonic-gate } 3316*7c478bd9Sstevel@tonic-gate /* 3317*7c478bd9Sstevel@tonic-gate ** GETAUTHINFO -- get the real host name associated with a file descriptor 3318*7c478bd9Sstevel@tonic-gate ** 3319*7c478bd9Sstevel@tonic-gate ** Uses RFC1413 protocol to try to get info from the other end. 3320*7c478bd9Sstevel@tonic-gate ** 3321*7c478bd9Sstevel@tonic-gate ** Parameters: 3322*7c478bd9Sstevel@tonic-gate ** fd -- the descriptor 3323*7c478bd9Sstevel@tonic-gate ** may_be_forged -- an outage that is set to true if the 3324*7c478bd9Sstevel@tonic-gate ** forward lookup of RealHostName does not match 3325*7c478bd9Sstevel@tonic-gate ** RealHostAddr; set to false if they do match. 3326*7c478bd9Sstevel@tonic-gate ** 3327*7c478bd9Sstevel@tonic-gate ** Returns: 3328*7c478bd9Sstevel@tonic-gate ** The user@host information associated with this descriptor. 3329*7c478bd9Sstevel@tonic-gate */ 3330*7c478bd9Sstevel@tonic-gate 3331*7c478bd9Sstevel@tonic-gate static jmp_buf CtxAuthTimeout; 3332*7c478bd9Sstevel@tonic-gate 3333*7c478bd9Sstevel@tonic-gate static void 3334*7c478bd9Sstevel@tonic-gate authtimeout(ignore) 3335*7c478bd9Sstevel@tonic-gate int ignore; 3336*7c478bd9Sstevel@tonic-gate { 3337*7c478bd9Sstevel@tonic-gate /* 3338*7c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 3339*7c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 3340*7c478bd9Sstevel@tonic-gate ** DOING. 3341*7c478bd9Sstevel@tonic-gate */ 3342*7c478bd9Sstevel@tonic-gate 3343*7c478bd9Sstevel@tonic-gate errno = ETIMEDOUT; 3344*7c478bd9Sstevel@tonic-gate longjmp(CtxAuthTimeout, 1); 3345*7c478bd9Sstevel@tonic-gate } 3346*7c478bd9Sstevel@tonic-gate 3347*7c478bd9Sstevel@tonic-gate char * 3348*7c478bd9Sstevel@tonic-gate getauthinfo(fd, may_be_forged) 3349*7c478bd9Sstevel@tonic-gate int fd; 3350*7c478bd9Sstevel@tonic-gate bool *may_be_forged; 3351*7c478bd9Sstevel@tonic-gate { 3352*7c478bd9Sstevel@tonic-gate unsigned short SM_NONVOLATILE port = 0; 3353*7c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T falen; 3354*7c478bd9Sstevel@tonic-gate register char *volatile p = NULL; 3355*7c478bd9Sstevel@tonic-gate SOCKADDR la; 3356*7c478bd9Sstevel@tonic-gate SOCKADDR_LEN_T lalen; 3357*7c478bd9Sstevel@tonic-gate #ifndef NO_GETSERVBYNAME 3358*7c478bd9Sstevel@tonic-gate register struct servent *sp; 3359*7c478bd9Sstevel@tonic-gate # if NETINET 3360*7c478bd9Sstevel@tonic-gate static unsigned short port4 = 0; 3361*7c478bd9Sstevel@tonic-gate # endif /* NETINET */ 3362*7c478bd9Sstevel@tonic-gate # if NETINET6 3363*7c478bd9Sstevel@tonic-gate static unsigned short port6 = 0; 3364*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 3365*7c478bd9Sstevel@tonic-gate #endif /* ! NO_GETSERVBYNAME */ 3366*7c478bd9Sstevel@tonic-gate volatile int s; 3367*7c478bd9Sstevel@tonic-gate int i = 0; 3368*7c478bd9Sstevel@tonic-gate size_t len; 3369*7c478bd9Sstevel@tonic-gate SM_EVENT *ev; 3370*7c478bd9Sstevel@tonic-gate int nleft; 3371*7c478bd9Sstevel@tonic-gate struct hostent *hp; 3372*7c478bd9Sstevel@tonic-gate char *ostype = NULL; 3373*7c478bd9Sstevel@tonic-gate char **ha; 3374*7c478bd9Sstevel@tonic-gate char ibuf[MAXNAME + 1]; 3375*7c478bd9Sstevel@tonic-gate static char hbuf[MAXNAME + MAXAUTHINFO + 11]; 3376*7c478bd9Sstevel@tonic-gate 3377*7c478bd9Sstevel@tonic-gate *may_be_forged = false; 3378*7c478bd9Sstevel@tonic-gate falen = sizeof RealHostAddr; 3379*7c478bd9Sstevel@tonic-gate if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || 3380*7c478bd9Sstevel@tonic-gate falen <= 0 || RealHostAddr.sa.sa_family == 0) 3381*7c478bd9Sstevel@tonic-gate { 3382*7c478bd9Sstevel@tonic-gate if (i < 0) 3383*7c478bd9Sstevel@tonic-gate { 3384*7c478bd9Sstevel@tonic-gate /* 3385*7c478bd9Sstevel@tonic-gate ** ENOTSOCK is OK: bail on anything else, but reset 3386*7c478bd9Sstevel@tonic-gate ** errno in this case, so a mis-report doesn't 3387*7c478bd9Sstevel@tonic-gate ** happen later. 3388*7c478bd9Sstevel@tonic-gate */ 3389*7c478bd9Sstevel@tonic-gate 3390*7c478bd9Sstevel@tonic-gate if (errno != ENOTSOCK) 3391*7c478bd9Sstevel@tonic-gate return NULL; 3392*7c478bd9Sstevel@tonic-gate errno = 0; 3393*7c478bd9Sstevel@tonic-gate } 3394*7c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(hbuf, sizeof hbuf, 2, RealUserName, 3395*7c478bd9Sstevel@tonic-gate "@localhost"); 3396*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3397*7c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 3398*7c478bd9Sstevel@tonic-gate return hbuf; 3399*7c478bd9Sstevel@tonic-gate } 3400*7c478bd9Sstevel@tonic-gate 3401*7c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 3402*7c478bd9Sstevel@tonic-gate { 3403*7c478bd9Sstevel@tonic-gate /* translate that to a host name */ 3404*7c478bd9Sstevel@tonic-gate RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); 3405*7c478bd9Sstevel@tonic-gate if (strlen(RealHostName) > MAXNAME) 3406*7c478bd9Sstevel@tonic-gate RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */ 3407*7c478bd9Sstevel@tonic-gate } 3408*7c478bd9Sstevel@tonic-gate 3409*7c478bd9Sstevel@tonic-gate /* cross check RealHostName with forward DNS lookup */ 3410*7c478bd9Sstevel@tonic-gate if (anynet_ntoa(&RealHostAddr)[0] != '[' && 3411*7c478bd9Sstevel@tonic-gate RealHostName[0] != '[') 3412*7c478bd9Sstevel@tonic-gate { 3413*7c478bd9Sstevel@tonic-gate int family; 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate family = RealHostAddr.sa.sa_family; 3416*7c478bd9Sstevel@tonic-gate #if NETINET6 && NEEDSGETIPNODE 3417*7c478bd9Sstevel@tonic-gate /* 3418*7c478bd9Sstevel@tonic-gate ** If RealHostAddr is an IPv6 connection with an 3419*7c478bd9Sstevel@tonic-gate ** IPv4-mapped address, we need RealHostName's IPv4 3420*7c478bd9Sstevel@tonic-gate ** address(es) for addrcmp() to compare against 3421*7c478bd9Sstevel@tonic-gate ** RealHostAddr. 3422*7c478bd9Sstevel@tonic-gate ** 3423*7c478bd9Sstevel@tonic-gate ** Actually, we only need to do this for systems 3424*7c478bd9Sstevel@tonic-gate ** which NEEDSGETIPNODE since the real getipnodebyname() 3425*7c478bd9Sstevel@tonic-gate ** already does V4MAPPED address via the AI_V4MAPPEDCFG 3426*7c478bd9Sstevel@tonic-gate ** flag. A better fix to this problem is to add this 3427*7c478bd9Sstevel@tonic-gate ** functionality to our stub getipnodebyname(). 3428*7c478bd9Sstevel@tonic-gate */ 3429*7c478bd9Sstevel@tonic-gate 3430*7c478bd9Sstevel@tonic-gate if (family == AF_INET6 && 3431*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr)) 3432*7c478bd9Sstevel@tonic-gate family = AF_INET; 3433*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 && NEEDSGETIPNODE */ 3434*7c478bd9Sstevel@tonic-gate 3435*7c478bd9Sstevel@tonic-gate /* try to match the reverse against the forward lookup */ 3436*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyname(RealHostName, family); 3437*7c478bd9Sstevel@tonic-gate if (hp == NULL) 3438*7c478bd9Sstevel@tonic-gate { 3439*7c478bd9Sstevel@tonic-gate /* XXX: Could be a temporary error on forward lookup */ 3440*7c478bd9Sstevel@tonic-gate *may_be_forged = true; 3441*7c478bd9Sstevel@tonic-gate } 3442*7c478bd9Sstevel@tonic-gate else 3443*7c478bd9Sstevel@tonic-gate { 3444*7c478bd9Sstevel@tonic-gate for (ha = hp->h_addr_list; *ha != NULL; ha++) 3445*7c478bd9Sstevel@tonic-gate { 3446*7c478bd9Sstevel@tonic-gate if (addrcmp(hp, *ha, &RealHostAddr) == 0) 3447*7c478bd9Sstevel@tonic-gate break; 3448*7c478bd9Sstevel@tonic-gate } 3449*7c478bd9Sstevel@tonic-gate *may_be_forged = *ha == NULL; 3450*7c478bd9Sstevel@tonic-gate #if NETINET6 3451*7c478bd9Sstevel@tonic-gate freehostent(hp); 3452*7c478bd9Sstevel@tonic-gate hp = NULL; 3453*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3454*7c478bd9Sstevel@tonic-gate } 3455*7c478bd9Sstevel@tonic-gate } 3456*7c478bd9Sstevel@tonic-gate 3457*7c478bd9Sstevel@tonic-gate if (TimeOuts.to_ident == 0) 3458*7c478bd9Sstevel@tonic-gate goto noident; 3459*7c478bd9Sstevel@tonic-gate 3460*7c478bd9Sstevel@tonic-gate lalen = sizeof la; 3461*7c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 3462*7c478bd9Sstevel@tonic-gate { 3463*7c478bd9Sstevel@tonic-gate #if NETINET 3464*7c478bd9Sstevel@tonic-gate case AF_INET: 3465*7c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 3466*7c478bd9Sstevel@tonic-gate lalen <= 0 || 3467*7c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET) 3468*7c478bd9Sstevel@tonic-gate { 3469*7c478bd9Sstevel@tonic-gate /* no ident info */ 3470*7c478bd9Sstevel@tonic-gate goto noident; 3471*7c478bd9Sstevel@tonic-gate } 3472*7c478bd9Sstevel@tonic-gate port = RealHostAddr.sin.sin_port; 3473*7c478bd9Sstevel@tonic-gate 3474*7c478bd9Sstevel@tonic-gate /* create ident query */ 3475*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 3476*7c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin.sin_port), 3477*7c478bd9Sstevel@tonic-gate ntohs(la.sin.sin_port)); 3478*7c478bd9Sstevel@tonic-gate 3479*7c478bd9Sstevel@tonic-gate /* create local address */ 3480*7c478bd9Sstevel@tonic-gate la.sin.sin_port = 0; 3481*7c478bd9Sstevel@tonic-gate 3482*7c478bd9Sstevel@tonic-gate /* create foreign address */ 3483*7c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 3484*7c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = htons(113); 3485*7c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 3486*7c478bd9Sstevel@tonic-gate 3487*7c478bd9Sstevel@tonic-gate /* 3488*7c478bd9Sstevel@tonic-gate ** getservbyname() consumes about 5% of the time 3489*7c478bd9Sstevel@tonic-gate ** when receiving a small message (almost all of the time 3490*7c478bd9Sstevel@tonic-gate ** spent in this routine). 3491*7c478bd9Sstevel@tonic-gate ** Hence we store the port in a static variable 3492*7c478bd9Sstevel@tonic-gate ** to save this time. 3493*7c478bd9Sstevel@tonic-gate ** The portnumber shouldn't change very often... 3494*7c478bd9Sstevel@tonic-gate ** This code makes the assumption that the port number 3495*7c478bd9Sstevel@tonic-gate ** is not 0. 3496*7c478bd9Sstevel@tonic-gate */ 3497*7c478bd9Sstevel@tonic-gate 3498*7c478bd9Sstevel@tonic-gate if (port4 == 0) 3499*7c478bd9Sstevel@tonic-gate { 3500*7c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 3501*7c478bd9Sstevel@tonic-gate if (sp != NULL) 3502*7c478bd9Sstevel@tonic-gate port4 = sp->s_port; 3503*7c478bd9Sstevel@tonic-gate else 3504*7c478bd9Sstevel@tonic-gate port4 = htons(113); 3505*7c478bd9Sstevel@tonic-gate } 3506*7c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port4; 3507*7c478bd9Sstevel@tonic-gate break; 3508*7c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 3509*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 3510*7c478bd9Sstevel@tonic-gate 3511*7c478bd9Sstevel@tonic-gate #if NETINET6 3512*7c478bd9Sstevel@tonic-gate case AF_INET6: 3513*7c478bd9Sstevel@tonic-gate if (getsockname(fd, &la.sa, &lalen) < 0 || 3514*7c478bd9Sstevel@tonic-gate lalen <= 0 || 3515*7c478bd9Sstevel@tonic-gate la.sa.sa_family != AF_INET6) 3516*7c478bd9Sstevel@tonic-gate { 3517*7c478bd9Sstevel@tonic-gate /* no ident info */ 3518*7c478bd9Sstevel@tonic-gate goto noident; 3519*7c478bd9Sstevel@tonic-gate } 3520*7c478bd9Sstevel@tonic-gate port = RealHostAddr.sin6.sin6_port; 3521*7c478bd9Sstevel@tonic-gate 3522*7c478bd9Sstevel@tonic-gate /* create ident query */ 3523*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", 3524*7c478bd9Sstevel@tonic-gate ntohs(RealHostAddr.sin6.sin6_port), 3525*7c478bd9Sstevel@tonic-gate ntohs(la.sin6.sin6_port)); 3526*7c478bd9Sstevel@tonic-gate 3527*7c478bd9Sstevel@tonic-gate /* create local address */ 3528*7c478bd9Sstevel@tonic-gate la.sin6.sin6_port = 0; 3529*7c478bd9Sstevel@tonic-gate 3530*7c478bd9Sstevel@tonic-gate /* create foreign address */ 3531*7c478bd9Sstevel@tonic-gate # ifdef NO_GETSERVBYNAME 3532*7c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = htons(113); 3533*7c478bd9Sstevel@tonic-gate # else /* NO_GETSERVBYNAME */ 3534*7c478bd9Sstevel@tonic-gate if (port6 == 0) 3535*7c478bd9Sstevel@tonic-gate { 3536*7c478bd9Sstevel@tonic-gate sp = getservbyname("auth", "tcp"); 3537*7c478bd9Sstevel@tonic-gate if (sp != NULL) 3538*7c478bd9Sstevel@tonic-gate port6 = sp->s_port; 3539*7c478bd9Sstevel@tonic-gate else 3540*7c478bd9Sstevel@tonic-gate port6 = htons(113); 3541*7c478bd9Sstevel@tonic-gate } 3542*7c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port6; 3543*7c478bd9Sstevel@tonic-gate break; 3544*7c478bd9Sstevel@tonic-gate # endif /* NO_GETSERVBYNAME */ 3545*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3546*7c478bd9Sstevel@tonic-gate default: 3547*7c478bd9Sstevel@tonic-gate /* no ident info */ 3548*7c478bd9Sstevel@tonic-gate goto noident; 3549*7c478bd9Sstevel@tonic-gate } 3550*7c478bd9Sstevel@tonic-gate 3551*7c478bd9Sstevel@tonic-gate s = -1; 3552*7c478bd9Sstevel@tonic-gate if (setjmp(CtxAuthTimeout) != 0) 3553*7c478bd9Sstevel@tonic-gate { 3554*7c478bd9Sstevel@tonic-gate if (s >= 0) 3555*7c478bd9Sstevel@tonic-gate (void) close(s); 3556*7c478bd9Sstevel@tonic-gate goto noident; 3557*7c478bd9Sstevel@tonic-gate } 3558*7c478bd9Sstevel@tonic-gate 3559*7c478bd9Sstevel@tonic-gate /* put a timeout around the whole thing */ 3560*7c478bd9Sstevel@tonic-gate ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0); 3561*7c478bd9Sstevel@tonic-gate 3562*7c478bd9Sstevel@tonic-gate /* connect to foreign IDENT server using same address as SMTP socket */ 3563*7c478bd9Sstevel@tonic-gate s = socket(la.sa.sa_family, SOCK_STREAM, 0); 3564*7c478bd9Sstevel@tonic-gate if (s < 0) 3565*7c478bd9Sstevel@tonic-gate { 3566*7c478bd9Sstevel@tonic-gate sm_clrevent(ev); 3567*7c478bd9Sstevel@tonic-gate goto noident; 3568*7c478bd9Sstevel@tonic-gate } 3569*7c478bd9Sstevel@tonic-gate if (bind(s, &la.sa, lalen) < 0 || 3570*7c478bd9Sstevel@tonic-gate connect(s, &RealHostAddr.sa, lalen) < 0) 3571*7c478bd9Sstevel@tonic-gate goto closeident; 3572*7c478bd9Sstevel@tonic-gate 3573*7c478bd9Sstevel@tonic-gate if (tTd(9, 10)) 3574*7c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: sent %s", ibuf); 3575*7c478bd9Sstevel@tonic-gate 3576*7c478bd9Sstevel@tonic-gate /* send query */ 3577*7c478bd9Sstevel@tonic-gate if (write(s, ibuf, strlen(ibuf)) < 0) 3578*7c478bd9Sstevel@tonic-gate goto closeident; 3579*7c478bd9Sstevel@tonic-gate 3580*7c478bd9Sstevel@tonic-gate /* get result */ 3581*7c478bd9Sstevel@tonic-gate p = &ibuf[0]; 3582*7c478bd9Sstevel@tonic-gate nleft = sizeof ibuf - 1; 3583*7c478bd9Sstevel@tonic-gate while ((i = read(s, p, nleft)) > 0) 3584*7c478bd9Sstevel@tonic-gate { 3585*7c478bd9Sstevel@tonic-gate char *s; 3586*7c478bd9Sstevel@tonic-gate 3587*7c478bd9Sstevel@tonic-gate p += i; 3588*7c478bd9Sstevel@tonic-gate nleft -= i; 3589*7c478bd9Sstevel@tonic-gate *p = '\0'; 3590*7c478bd9Sstevel@tonic-gate if ((s = strchr(ibuf, '\n')) != NULL) 3591*7c478bd9Sstevel@tonic-gate { 3592*7c478bd9Sstevel@tonic-gate if (p > s + 1) 3593*7c478bd9Sstevel@tonic-gate { 3594*7c478bd9Sstevel@tonic-gate p = s + 1; 3595*7c478bd9Sstevel@tonic-gate *p = '\0'; 3596*7c478bd9Sstevel@tonic-gate } 3597*7c478bd9Sstevel@tonic-gate break; 3598*7c478bd9Sstevel@tonic-gate } 3599*7c478bd9Sstevel@tonic-gate if (nleft <= 0) 3600*7c478bd9Sstevel@tonic-gate break; 3601*7c478bd9Sstevel@tonic-gate } 3602*7c478bd9Sstevel@tonic-gate (void) close(s); 3603*7c478bd9Sstevel@tonic-gate sm_clrevent(ev); 3604*7c478bd9Sstevel@tonic-gate if (i < 0 || p == &ibuf[0]) 3605*7c478bd9Sstevel@tonic-gate goto noident; 3606*7c478bd9Sstevel@tonic-gate 3607*7c478bd9Sstevel@tonic-gate if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r') 3608*7c478bd9Sstevel@tonic-gate p--; 3609*7c478bd9Sstevel@tonic-gate *++p = '\0'; 3610*7c478bd9Sstevel@tonic-gate 3611*7c478bd9Sstevel@tonic-gate if (tTd(9, 3)) 3612*7c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: got %s\n", ibuf); 3613*7c478bd9Sstevel@tonic-gate 3614*7c478bd9Sstevel@tonic-gate /* parse result */ 3615*7c478bd9Sstevel@tonic-gate p = strchr(ibuf, ':'); 3616*7c478bd9Sstevel@tonic-gate if (p == NULL) 3617*7c478bd9Sstevel@tonic-gate { 3618*7c478bd9Sstevel@tonic-gate /* malformed response */ 3619*7c478bd9Sstevel@tonic-gate goto noident; 3620*7c478bd9Sstevel@tonic-gate } 3621*7c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 3622*7c478bd9Sstevel@tonic-gate continue; 3623*7c478bd9Sstevel@tonic-gate if (sm_strncasecmp(p, "userid", 6) != 0) 3624*7c478bd9Sstevel@tonic-gate { 3625*7c478bd9Sstevel@tonic-gate /* presumably an error string */ 3626*7c478bd9Sstevel@tonic-gate goto noident; 3627*7c478bd9Sstevel@tonic-gate } 3628*7c478bd9Sstevel@tonic-gate p += 6; 3629*7c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 3630*7c478bd9Sstevel@tonic-gate p++; 3631*7c478bd9Sstevel@tonic-gate if (*p++ != ':') 3632*7c478bd9Sstevel@tonic-gate { 3633*7c478bd9Sstevel@tonic-gate /* either useridxx or malformed response */ 3634*7c478bd9Sstevel@tonic-gate goto noident; 3635*7c478bd9Sstevel@tonic-gate } 3636*7c478bd9Sstevel@tonic-gate 3637*7c478bd9Sstevel@tonic-gate /* p now points to the OSTYPE field */ 3638*7c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 3639*7c478bd9Sstevel@tonic-gate p++; 3640*7c478bd9Sstevel@tonic-gate ostype = p; 3641*7c478bd9Sstevel@tonic-gate p = strchr(p, ':'); 3642*7c478bd9Sstevel@tonic-gate if (p == NULL) 3643*7c478bd9Sstevel@tonic-gate { 3644*7c478bd9Sstevel@tonic-gate /* malformed response */ 3645*7c478bd9Sstevel@tonic-gate goto noident; 3646*7c478bd9Sstevel@tonic-gate } 3647*7c478bd9Sstevel@tonic-gate else 3648*7c478bd9Sstevel@tonic-gate { 3649*7c478bd9Sstevel@tonic-gate char *charset; 3650*7c478bd9Sstevel@tonic-gate 3651*7c478bd9Sstevel@tonic-gate *p = '\0'; 3652*7c478bd9Sstevel@tonic-gate charset = strchr(ostype, ','); 3653*7c478bd9Sstevel@tonic-gate if (charset != NULL) 3654*7c478bd9Sstevel@tonic-gate *charset = '\0'; 3655*7c478bd9Sstevel@tonic-gate } 3656*7c478bd9Sstevel@tonic-gate 3657*7c478bd9Sstevel@tonic-gate /* 1413 says don't do this -- but it's broken otherwise */ 3658*7c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 3659*7c478bd9Sstevel@tonic-gate continue; 3660*7c478bd9Sstevel@tonic-gate 3661*7c478bd9Sstevel@tonic-gate /* p now points to the authenticated name -- copy carefully */ 3662*7c478bd9Sstevel@tonic-gate if (sm_strncasecmp(ostype, "other", 5) == 0 && 3663*7c478bd9Sstevel@tonic-gate (ostype[5] == ' ' || ostype[5] == '\0')) 3664*7c478bd9Sstevel@tonic-gate { 3665*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hbuf, "IDENT:", sizeof hbuf); 3666*7c478bd9Sstevel@tonic-gate cleanstrcpy(&hbuf[6], p, MAXAUTHINFO); 3667*7c478bd9Sstevel@tonic-gate } 3668*7c478bd9Sstevel@tonic-gate else 3669*7c478bd9Sstevel@tonic-gate cleanstrcpy(hbuf, p, MAXAUTHINFO); 3670*7c478bd9Sstevel@tonic-gate len = strlen(hbuf); 3671*7c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(&hbuf[len], sizeof hbuf - len, 2, "@", 3672*7c478bd9Sstevel@tonic-gate RealHostName == NULL ? "localhost" : RealHostName); 3673*7c478bd9Sstevel@tonic-gate goto postident; 3674*7c478bd9Sstevel@tonic-gate 3675*7c478bd9Sstevel@tonic-gate closeident: 3676*7c478bd9Sstevel@tonic-gate (void) close(s); 3677*7c478bd9Sstevel@tonic-gate sm_clrevent(ev); 3678*7c478bd9Sstevel@tonic-gate 3679*7c478bd9Sstevel@tonic-gate noident: 3680*7c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 3681*7c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 3682*7c478bd9Sstevel@tonic-gate { 3683*7c478bd9Sstevel@tonic-gate #if NETINET 3684*7c478bd9Sstevel@tonic-gate case AF_INET: 3685*7c478bd9Sstevel@tonic-gate if (port > 0) 3686*7c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 3687*7c478bd9Sstevel@tonic-gate break; 3688*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 3689*7c478bd9Sstevel@tonic-gate 3690*7c478bd9Sstevel@tonic-gate #if NETINET6 3691*7c478bd9Sstevel@tonic-gate case AF_INET6: 3692*7c478bd9Sstevel@tonic-gate if (port > 0) 3693*7c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 3694*7c478bd9Sstevel@tonic-gate break; 3695*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3696*7c478bd9Sstevel@tonic-gate } 3697*7c478bd9Sstevel@tonic-gate 3698*7c478bd9Sstevel@tonic-gate if (RealHostName == NULL) 3699*7c478bd9Sstevel@tonic-gate { 3700*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3701*7c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: NULL\n"); 3702*7c478bd9Sstevel@tonic-gate return NULL; 3703*7c478bd9Sstevel@tonic-gate } 3704*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hbuf, RealHostName, sizeof hbuf); 3705*7c478bd9Sstevel@tonic-gate 3706*7c478bd9Sstevel@tonic-gate postident: 3707*7c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 3708*7c478bd9Sstevel@tonic-gate # ifndef GET_IPOPT_DST 3709*7c478bd9Sstevel@tonic-gate # define GET_IPOPT_DST(dst) (dst) 3710*7c478bd9Sstevel@tonic-gate # endif /* ! GET_IPOPT_DST */ 3711*7c478bd9Sstevel@tonic-gate /* 3712*7c478bd9Sstevel@tonic-gate ** Extract IP source routing information. 3713*7c478bd9Sstevel@tonic-gate ** 3714*7c478bd9Sstevel@tonic-gate ** Format of output for a connection from site a through b 3715*7c478bd9Sstevel@tonic-gate ** through c to d: 3716*7c478bd9Sstevel@tonic-gate ** loose: @site-c@site-b:site-a 3717*7c478bd9Sstevel@tonic-gate ** strict: !@site-c@site-b:site-a 3718*7c478bd9Sstevel@tonic-gate ** 3719*7c478bd9Sstevel@tonic-gate ** o - pointer within ipopt_list structure. 3720*7c478bd9Sstevel@tonic-gate ** q - pointer within ls/ss rr route data 3721*7c478bd9Sstevel@tonic-gate ** p - pointer to hbuf 3722*7c478bd9Sstevel@tonic-gate */ 3723*7c478bd9Sstevel@tonic-gate 3724*7c478bd9Sstevel@tonic-gate if (RealHostAddr.sa.sa_family == AF_INET) 3725*7c478bd9Sstevel@tonic-gate { 3726*7c478bd9Sstevel@tonic-gate SOCKOPT_LEN_T ipoptlen; 3727*7c478bd9Sstevel@tonic-gate int j; 3728*7c478bd9Sstevel@tonic-gate unsigned char *q; 3729*7c478bd9Sstevel@tonic-gate unsigned char *o; 3730*7c478bd9Sstevel@tonic-gate int l; 3731*7c478bd9Sstevel@tonic-gate struct IPOPTION ipopt; 3732*7c478bd9Sstevel@tonic-gate 3733*7c478bd9Sstevel@tonic-gate ipoptlen = sizeof ipopt; 3734*7c478bd9Sstevel@tonic-gate if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, 3735*7c478bd9Sstevel@tonic-gate (char *) &ipopt, &ipoptlen) < 0) 3736*7c478bd9Sstevel@tonic-gate goto noipsr; 3737*7c478bd9Sstevel@tonic-gate if (ipoptlen == 0) 3738*7c478bd9Sstevel@tonic-gate goto noipsr; 3739*7c478bd9Sstevel@tonic-gate o = (unsigned char *) ipopt.IP_LIST; 3740*7c478bd9Sstevel@tonic-gate while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen) 3741*7c478bd9Sstevel@tonic-gate { 3742*7c478bd9Sstevel@tonic-gate switch (*o) 3743*7c478bd9Sstevel@tonic-gate { 3744*7c478bd9Sstevel@tonic-gate case IPOPT_EOL: 3745*7c478bd9Sstevel@tonic-gate o = NULL; 3746*7c478bd9Sstevel@tonic-gate break; 3747*7c478bd9Sstevel@tonic-gate 3748*7c478bd9Sstevel@tonic-gate case IPOPT_NOP: 3749*7c478bd9Sstevel@tonic-gate o++; 3750*7c478bd9Sstevel@tonic-gate break; 3751*7c478bd9Sstevel@tonic-gate 3752*7c478bd9Sstevel@tonic-gate case IPOPT_SSRR: 3753*7c478bd9Sstevel@tonic-gate case IPOPT_LSRR: 3754*7c478bd9Sstevel@tonic-gate /* 3755*7c478bd9Sstevel@tonic-gate ** Source routing. 3756*7c478bd9Sstevel@tonic-gate ** o[0] is the option type (loose/strict). 3757*7c478bd9Sstevel@tonic-gate ** o[1] is the length of this option, 3758*7c478bd9Sstevel@tonic-gate ** including option type and 3759*7c478bd9Sstevel@tonic-gate ** length. 3760*7c478bd9Sstevel@tonic-gate ** o[2] is the pointer into the route 3761*7c478bd9Sstevel@tonic-gate ** data. 3762*7c478bd9Sstevel@tonic-gate ** o[3] begins the route data. 3763*7c478bd9Sstevel@tonic-gate */ 3764*7c478bd9Sstevel@tonic-gate 3765*7c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 3766*7c478bd9Sstevel@tonic-gate l = sizeof hbuf - (hbuf - p) - 6; 3767*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), 3768*7c478bd9Sstevel@tonic-gate " [%s@%.*s", 3769*7c478bd9Sstevel@tonic-gate *o == IPOPT_SSRR ? "!" : "", 3770*7c478bd9Sstevel@tonic-gate l > 240 ? 120 : l / 2, 3771*7c478bd9Sstevel@tonic-gate inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); 3772*7c478bd9Sstevel@tonic-gate i = strlen(p); 3773*7c478bd9Sstevel@tonic-gate p += i; 3774*7c478bd9Sstevel@tonic-gate l -= strlen(p); 3775*7c478bd9Sstevel@tonic-gate 3776*7c478bd9Sstevel@tonic-gate j = o[1] / sizeof(struct in_addr) - 1; 3777*7c478bd9Sstevel@tonic-gate 3778*7c478bd9Sstevel@tonic-gate /* q skips length and router pointer to data */ 3779*7c478bd9Sstevel@tonic-gate q = &o[3]; 3780*7c478bd9Sstevel@tonic-gate for ( ; j >= 0; j--) 3781*7c478bd9Sstevel@tonic-gate { 3782*7c478bd9Sstevel@tonic-gate struct in_addr addr; 3783*7c478bd9Sstevel@tonic-gate 3784*7c478bd9Sstevel@tonic-gate memcpy(&addr, q, sizeof(addr)); 3785*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, 3786*7c478bd9Sstevel@tonic-gate SPACELEFT(hbuf, p), 3787*7c478bd9Sstevel@tonic-gate "%c%.*s", 3788*7c478bd9Sstevel@tonic-gate j != 0 ? '@' : ':', 3789*7c478bd9Sstevel@tonic-gate l > 240 ? 120 : 3790*7c478bd9Sstevel@tonic-gate j == 0 ? l : l / 2, 3791*7c478bd9Sstevel@tonic-gate inet_ntoa(addr)); 3792*7c478bd9Sstevel@tonic-gate i = strlen(p); 3793*7c478bd9Sstevel@tonic-gate p += i; 3794*7c478bd9Sstevel@tonic-gate l -= i + 1; 3795*7c478bd9Sstevel@tonic-gate q += sizeof(struct in_addr); 3796*7c478bd9Sstevel@tonic-gate } 3797*7c478bd9Sstevel@tonic-gate o += o[1]; 3798*7c478bd9Sstevel@tonic-gate break; 3799*7c478bd9Sstevel@tonic-gate 3800*7c478bd9Sstevel@tonic-gate default: 3801*7c478bd9Sstevel@tonic-gate /* Skip over option */ 3802*7c478bd9Sstevel@tonic-gate o += o[1]; 3803*7c478bd9Sstevel@tonic-gate break; 3804*7c478bd9Sstevel@tonic-gate } 3805*7c478bd9Sstevel@tonic-gate } 3806*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), "]"); 3807*7c478bd9Sstevel@tonic-gate goto postipsr; 3808*7c478bd9Sstevel@tonic-gate } 3809*7c478bd9Sstevel@tonic-gate 3810*7c478bd9Sstevel@tonic-gate noipsr: 3811*7c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 3812*7c478bd9Sstevel@tonic-gate if (RealHostName != NULL && RealHostName[0] != '[') 3813*7c478bd9Sstevel@tonic-gate { 3814*7c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 3815*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", 3816*7c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 3817*7c478bd9Sstevel@tonic-gate } 3818*7c478bd9Sstevel@tonic-gate if (*may_be_forged) 3819*7c478bd9Sstevel@tonic-gate { 3820*7c478bd9Sstevel@tonic-gate p = &hbuf[strlen(hbuf)]; 3821*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p)); 3822*7c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 3823*7c478bd9Sstevel@tonic-gate macid("{client_resolve}"), "FORGED"); 3824*7c478bd9Sstevel@tonic-gate } 3825*7c478bd9Sstevel@tonic-gate 3826*7c478bd9Sstevel@tonic-gate #if IP_SRCROUTE 3827*7c478bd9Sstevel@tonic-gate postipsr: 3828*7c478bd9Sstevel@tonic-gate #endif /* IP_SRCROUTE */ 3829*7c478bd9Sstevel@tonic-gate 3830*7c478bd9Sstevel@tonic-gate /* put back the original incoming port */ 3831*7c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 3832*7c478bd9Sstevel@tonic-gate { 3833*7c478bd9Sstevel@tonic-gate #if NETINET 3834*7c478bd9Sstevel@tonic-gate case AF_INET: 3835*7c478bd9Sstevel@tonic-gate if (port > 0) 3836*7c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port = port; 3837*7c478bd9Sstevel@tonic-gate break; 3838*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 3839*7c478bd9Sstevel@tonic-gate 3840*7c478bd9Sstevel@tonic-gate #if NETINET6 3841*7c478bd9Sstevel@tonic-gate case AF_INET6: 3842*7c478bd9Sstevel@tonic-gate if (port > 0) 3843*7c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port = port; 3844*7c478bd9Sstevel@tonic-gate break; 3845*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3846*7c478bd9Sstevel@tonic-gate } 3847*7c478bd9Sstevel@tonic-gate 3848*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3849*7c478bd9Sstevel@tonic-gate sm_dprintf("getauthinfo: %s\n", hbuf); 3850*7c478bd9Sstevel@tonic-gate return hbuf; 3851*7c478bd9Sstevel@tonic-gate } 3852*7c478bd9Sstevel@tonic-gate /* 3853*7c478bd9Sstevel@tonic-gate ** HOST_MAP_LOOKUP -- turn a hostname into canonical form 3854*7c478bd9Sstevel@tonic-gate ** 3855*7c478bd9Sstevel@tonic-gate ** Parameters: 3856*7c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 3857*7c478bd9Sstevel@tonic-gate ** name -- the (presumably unqualified) hostname. 3858*7c478bd9Sstevel@tonic-gate ** av -- unused -- for compatibility with other mapping 3859*7c478bd9Sstevel@tonic-gate ** functions. 3860*7c478bd9Sstevel@tonic-gate ** statp -- an exit status (out parameter) -- set to 3861*7c478bd9Sstevel@tonic-gate ** EX_TEMPFAIL if the name server is unavailable. 3862*7c478bd9Sstevel@tonic-gate ** 3863*7c478bd9Sstevel@tonic-gate ** Returns: 3864*7c478bd9Sstevel@tonic-gate ** The mapping, if found. 3865*7c478bd9Sstevel@tonic-gate ** NULL if no mapping found. 3866*7c478bd9Sstevel@tonic-gate ** 3867*7c478bd9Sstevel@tonic-gate ** Side Effects: 3868*7c478bd9Sstevel@tonic-gate ** Looks up the host specified in hbuf. If it is not 3869*7c478bd9Sstevel@tonic-gate ** the canonical name for that host, return the canonical 3870*7c478bd9Sstevel@tonic-gate ** name (unless MF_MATCHONLY is set, which will cause the 3871*7c478bd9Sstevel@tonic-gate ** status only to be returned). 3872*7c478bd9Sstevel@tonic-gate */ 3873*7c478bd9Sstevel@tonic-gate 3874*7c478bd9Sstevel@tonic-gate char * 3875*7c478bd9Sstevel@tonic-gate host_map_lookup(map, name, av, statp) 3876*7c478bd9Sstevel@tonic-gate MAP *map; 3877*7c478bd9Sstevel@tonic-gate char *name; 3878*7c478bd9Sstevel@tonic-gate char **av; 3879*7c478bd9Sstevel@tonic-gate int *statp; 3880*7c478bd9Sstevel@tonic-gate { 3881*7c478bd9Sstevel@tonic-gate register struct hostent *hp; 3882*7c478bd9Sstevel@tonic-gate #if NETINET 3883*7c478bd9Sstevel@tonic-gate struct in_addr in_addr; 3884*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 3885*7c478bd9Sstevel@tonic-gate #if NETINET6 3886*7c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 3887*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 3888*7c478bd9Sstevel@tonic-gate char *cp, *ans = NULL; 3889*7c478bd9Sstevel@tonic-gate register STAB *s; 3890*7c478bd9Sstevel@tonic-gate time_t now; 3891*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 3892*7c478bd9Sstevel@tonic-gate time_t SM_NONVOLATILE retrans = 0; 3893*7c478bd9Sstevel@tonic-gate int SM_NONVOLATILE retry = 0; 3894*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 3895*7c478bd9Sstevel@tonic-gate char hbuf[MAXNAME + 1]; 3896*7c478bd9Sstevel@tonic-gate 3897*7c478bd9Sstevel@tonic-gate /* 3898*7c478bd9Sstevel@tonic-gate ** See if we have already looked up this name. If so, just 3899*7c478bd9Sstevel@tonic-gate ** return it (unless expired). 3900*7c478bd9Sstevel@tonic-gate */ 3901*7c478bd9Sstevel@tonic-gate 3902*7c478bd9Sstevel@tonic-gate now = curtime(); 3903*7c478bd9Sstevel@tonic-gate s = stab(name, ST_NAMECANON, ST_ENTER); 3904*7c478bd9Sstevel@tonic-gate if (bitset(NCF_VALID, s->s_namecanon.nc_flags) && 3905*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp >= now) 3906*7c478bd9Sstevel@tonic-gate { 3907*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3908*7c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => CACHE %s\n", 3909*7c478bd9Sstevel@tonic-gate name, 3910*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname == NULL 3911*7c478bd9Sstevel@tonic-gate ? "NULL" 3912*7c478bd9Sstevel@tonic-gate : s->s_namecanon.nc_cname); 3913*7c478bd9Sstevel@tonic-gate errno = s->s_namecanon.nc_errno; 3914*7c478bd9Sstevel@tonic-gate SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); 3915*7c478bd9Sstevel@tonic-gate *statp = s->s_namecanon.nc_stat; 3916*7c478bd9Sstevel@tonic-gate if (*statp == EX_TEMPFAIL) 3917*7c478bd9Sstevel@tonic-gate { 3918*7c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 3919*7c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 3920*7c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 3921*7c478bd9Sstevel@tonic-gate } 3922*7c478bd9Sstevel@tonic-gate if (*statp != EX_OK) 3923*7c478bd9Sstevel@tonic-gate return NULL; 3924*7c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname == NULL) 3925*7c478bd9Sstevel@tonic-gate { 3926*7c478bd9Sstevel@tonic-gate syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d", 3927*7c478bd9Sstevel@tonic-gate name, 3928*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno, 3929*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno); 3930*7c478bd9Sstevel@tonic-gate return NULL; 3931*7c478bd9Sstevel@tonic-gate } 3932*7c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 3933*7c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 3934*7c478bd9Sstevel@tonic-gate else 3935*7c478bd9Sstevel@tonic-gate cp = map_rewrite(map, 3936*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname, 3937*7c478bd9Sstevel@tonic-gate strlen(s->s_namecanon.nc_cname), 3938*7c478bd9Sstevel@tonic-gate av); 3939*7c478bd9Sstevel@tonic-gate return cp; 3940*7c478bd9Sstevel@tonic-gate } 3941*7c478bd9Sstevel@tonic-gate 3942*7c478bd9Sstevel@tonic-gate /* 3943*7c478bd9Sstevel@tonic-gate ** If we are running without a regular network connection (usually 3944*7c478bd9Sstevel@tonic-gate ** dial-on-demand) and we are just queueing, we want to avoid DNS 3945*7c478bd9Sstevel@tonic-gate ** lookups because those could try to connect to a server. 3946*7c478bd9Sstevel@tonic-gate */ 3947*7c478bd9Sstevel@tonic-gate 3948*7c478bd9Sstevel@tonic-gate if (CurEnv->e_sendmode == SM_DEFER && 3949*7c478bd9Sstevel@tonic-gate bitset(MF_DEFER, map->map_mflags)) 3950*7c478bd9Sstevel@tonic-gate { 3951*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3952*7c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name); 3953*7c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 3954*7c478bd9Sstevel@tonic-gate return NULL; 3955*7c478bd9Sstevel@tonic-gate } 3956*7c478bd9Sstevel@tonic-gate 3957*7c478bd9Sstevel@tonic-gate /* 3958*7c478bd9Sstevel@tonic-gate ** If first character is a bracket, then it is an address 3959*7c478bd9Sstevel@tonic-gate ** lookup. Address is copied into a temporary buffer to 3960*7c478bd9Sstevel@tonic-gate ** strip the brackets and to preserve name if address is 3961*7c478bd9Sstevel@tonic-gate ** unknown. 3962*7c478bd9Sstevel@tonic-gate */ 3963*7c478bd9Sstevel@tonic-gate 3964*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3965*7c478bd9Sstevel@tonic-gate sm_dprintf("host_map_lookup(%s) => ", name); 3966*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 3967*7c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 3968*7c478bd9Sstevel@tonic-gate { 3969*7c478bd9Sstevel@tonic-gate retrans = _res.retrans; 3970*7c478bd9Sstevel@tonic-gate _res.retrans = map->map_timeout; 3971*7c478bd9Sstevel@tonic-gate } 3972*7c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 3973*7c478bd9Sstevel@tonic-gate { 3974*7c478bd9Sstevel@tonic-gate retry = _res.retry; 3975*7c478bd9Sstevel@tonic-gate _res.retry = map->map_retry; 3976*7c478bd9Sstevel@tonic-gate } 3977*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 3978*7c478bd9Sstevel@tonic-gate 3979*7c478bd9Sstevel@tonic-gate /* set default TTL */ 3980*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL; 3981*7c478bd9Sstevel@tonic-gate if (*name != '[') 3982*7c478bd9Sstevel@tonic-gate { 3983*7c478bd9Sstevel@tonic-gate int ttl; 3984*7c478bd9Sstevel@tonic-gate 3985*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(hbuf, name, sizeof hbuf); 3986*7c478bd9Sstevel@tonic-gate if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX, &ttl)) 3987*7c478bd9Sstevel@tonic-gate { 3988*7c478bd9Sstevel@tonic-gate ans = hbuf; 3989*7c478bd9Sstevel@tonic-gate if (ttl > 0) 3990*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_exp = now + SM_MIN(ttl, 3991*7c478bd9Sstevel@tonic-gate SM_DEFAULT_TTL); 3992*7c478bd9Sstevel@tonic-gate } 3993*7c478bd9Sstevel@tonic-gate } 3994*7c478bd9Sstevel@tonic-gate else 3995*7c478bd9Sstevel@tonic-gate { 3996*7c478bd9Sstevel@tonic-gate if ((cp = strchr(name, ']')) == NULL) 3997*7c478bd9Sstevel@tonic-gate { 3998*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 3999*7c478bd9Sstevel@tonic-gate sm_dprintf("FAILED\n"); 4000*7c478bd9Sstevel@tonic-gate return NULL; 4001*7c478bd9Sstevel@tonic-gate } 4002*7c478bd9Sstevel@tonic-gate *cp = '\0'; 4003*7c478bd9Sstevel@tonic-gate 4004*7c478bd9Sstevel@tonic-gate hp = NULL; 4005*7c478bd9Sstevel@tonic-gate #if NETINET 4006*7c478bd9Sstevel@tonic-gate if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) 4007*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in_addr, 4008*7c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 4009*7c478bd9Sstevel@tonic-gate #endif /* NETINET */ 4010*7c478bd9Sstevel@tonic-gate #if NETINET6 4011*7c478bd9Sstevel@tonic-gate if (hp == NULL && 4012*7c478bd9Sstevel@tonic-gate anynet_pton(AF_INET6, &name[1], &in6_addr) == 1) 4013*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *)&in6_addr, 4014*7c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 4015*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 4016*7c478bd9Sstevel@tonic-gate *cp = ']'; 4017*7c478bd9Sstevel@tonic-gate 4018*7c478bd9Sstevel@tonic-gate if (hp != NULL) 4019*7c478bd9Sstevel@tonic-gate { 4020*7c478bd9Sstevel@tonic-gate /* found a match -- copy out */ 4021*7c478bd9Sstevel@tonic-gate ans = denlstring((char *) hp->h_name, true, true); 4022*7c478bd9Sstevel@tonic-gate #if NETINET6 4023*7c478bd9Sstevel@tonic-gate if (ans == hp->h_name) 4024*7c478bd9Sstevel@tonic-gate { 4025*7c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 4026*7c478bd9Sstevel@tonic-gate 4027*7c478bd9Sstevel@tonic-gate /* hp->h_name is about to disappear */ 4028*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(n, ans, sizeof n); 4029*7c478bd9Sstevel@tonic-gate ans = n; 4030*7c478bd9Sstevel@tonic-gate } 4031*7c478bd9Sstevel@tonic-gate freehostent(hp); 4032*7c478bd9Sstevel@tonic-gate hp = NULL; 4033*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 4034*7c478bd9Sstevel@tonic-gate } 4035*7c478bd9Sstevel@tonic-gate } 4036*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 4037*7c478bd9Sstevel@tonic-gate if (map->map_timeout > 0) 4038*7c478bd9Sstevel@tonic-gate _res.retrans = retrans; 4039*7c478bd9Sstevel@tonic-gate if (map->map_retry > 0) 4040*7c478bd9Sstevel@tonic-gate _res.retry = retry; 4041*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 4042*7c478bd9Sstevel@tonic-gate 4043*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ 4044*7c478bd9Sstevel@tonic-gate 4045*7c478bd9Sstevel@tonic-gate /* Found an answer */ 4046*7c478bd9Sstevel@tonic-gate if (ans != NULL) 4047*7c478bd9Sstevel@tonic-gate { 4048*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp = EX_OK; 4049*7c478bd9Sstevel@tonic-gate if (s->s_namecanon.nc_cname != NULL) 4050*7c478bd9Sstevel@tonic-gate sm_free(s->s_namecanon.nc_cname); 4051*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_cname = sm_strdup_x(ans); 4052*7c478bd9Sstevel@tonic-gate if (bitset(MF_MATCHONLY, map->map_mflags)) 4053*7c478bd9Sstevel@tonic-gate cp = map_rewrite(map, name, strlen(name), NULL); 4054*7c478bd9Sstevel@tonic-gate else 4055*7c478bd9Sstevel@tonic-gate cp = map_rewrite(map, ans, strlen(ans), av); 4056*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 4057*7c478bd9Sstevel@tonic-gate sm_dprintf("FOUND %s\n", ans); 4058*7c478bd9Sstevel@tonic-gate return cp; 4059*7c478bd9Sstevel@tonic-gate } 4060*7c478bd9Sstevel@tonic-gate 4061*7c478bd9Sstevel@tonic-gate 4062*7c478bd9Sstevel@tonic-gate /* No match found */ 4063*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_errno = errno; 4064*7c478bd9Sstevel@tonic-gate #if NAMED_BIND 4065*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_herrno = h_errno; 4066*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 4067*7c478bd9Sstevel@tonic-gate sm_dprintf("FAIL (%d)\n", h_errno); 4068*7c478bd9Sstevel@tonic-gate switch (h_errno) 4069*7c478bd9Sstevel@tonic-gate { 4070*7c478bd9Sstevel@tonic-gate case TRY_AGAIN: 4071*7c478bd9Sstevel@tonic-gate if (UseNameServer) 4072*7c478bd9Sstevel@tonic-gate { 4073*7c478bd9Sstevel@tonic-gate CurEnv->e_status = "4.4.3"; 4074*7c478bd9Sstevel@tonic-gate message("851 %s: Name server timeout", 4075*7c478bd9Sstevel@tonic-gate shortenstring(name, 33)); 4076*7c478bd9Sstevel@tonic-gate } 4077*7c478bd9Sstevel@tonic-gate *statp = EX_TEMPFAIL; 4078*7c478bd9Sstevel@tonic-gate break; 4079*7c478bd9Sstevel@tonic-gate 4080*7c478bd9Sstevel@tonic-gate case HOST_NOT_FOUND: 4081*7c478bd9Sstevel@tonic-gate case NO_DATA: 4082*7c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 4083*7c478bd9Sstevel@tonic-gate break; 4084*7c478bd9Sstevel@tonic-gate 4085*7c478bd9Sstevel@tonic-gate case NO_RECOVERY: 4086*7c478bd9Sstevel@tonic-gate *statp = EX_SOFTWARE; 4087*7c478bd9Sstevel@tonic-gate break; 4088*7c478bd9Sstevel@tonic-gate 4089*7c478bd9Sstevel@tonic-gate default: 4090*7c478bd9Sstevel@tonic-gate *statp = EX_UNAVAILABLE; 4091*7c478bd9Sstevel@tonic-gate break; 4092*7c478bd9Sstevel@tonic-gate } 4093*7c478bd9Sstevel@tonic-gate #else /* NAMED_BIND */ 4094*7c478bd9Sstevel@tonic-gate if (tTd(9, 1)) 4095*7c478bd9Sstevel@tonic-gate sm_dprintf("FAIL\n"); 4096*7c478bd9Sstevel@tonic-gate *statp = EX_NOHOST; 4097*7c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 4098*7c478bd9Sstevel@tonic-gate s->s_namecanon.nc_stat = *statp; 4099*7c478bd9Sstevel@tonic-gate return NULL; 4100*7c478bd9Sstevel@tonic-gate } 4101*7c478bd9Sstevel@tonic-gate /* 4102*7c478bd9Sstevel@tonic-gate ** HOST_MAP_INIT -- initialize host class structures 4103*7c478bd9Sstevel@tonic-gate ** 4104*7c478bd9Sstevel@tonic-gate ** Parameters: 4105*7c478bd9Sstevel@tonic-gate ** map -- a pointer to this map. 4106*7c478bd9Sstevel@tonic-gate ** args -- argument string. 4107*7c478bd9Sstevel@tonic-gate ** 4108*7c478bd9Sstevel@tonic-gate ** Returns: 4109*7c478bd9Sstevel@tonic-gate ** true. 4110*7c478bd9Sstevel@tonic-gate */ 4111*7c478bd9Sstevel@tonic-gate 4112*7c478bd9Sstevel@tonic-gate bool 4113*7c478bd9Sstevel@tonic-gate host_map_init(map, args) 4114*7c478bd9Sstevel@tonic-gate MAP *map; 4115*7c478bd9Sstevel@tonic-gate char *args; 4116*7c478bd9Sstevel@tonic-gate { 4117*7c478bd9Sstevel@tonic-gate register char *p = args; 4118*7c478bd9Sstevel@tonic-gate 4119*7c478bd9Sstevel@tonic-gate for (;;) 4120*7c478bd9Sstevel@tonic-gate { 4121*7c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 4122*7c478bd9Sstevel@tonic-gate p++; 4123*7c478bd9Sstevel@tonic-gate if (*p != '-') 4124*7c478bd9Sstevel@tonic-gate break; 4125*7c478bd9Sstevel@tonic-gate switch (*++p) 4126*7c478bd9Sstevel@tonic-gate { 4127*7c478bd9Sstevel@tonic-gate case 'a': 4128*7c478bd9Sstevel@tonic-gate map->map_app = ++p; 4129*7c478bd9Sstevel@tonic-gate break; 4130*7c478bd9Sstevel@tonic-gate 4131*7c478bd9Sstevel@tonic-gate case 'T': 4132*7c478bd9Sstevel@tonic-gate map->map_tapp = ++p; 4133*7c478bd9Sstevel@tonic-gate break; 4134*7c478bd9Sstevel@tonic-gate 4135*7c478bd9Sstevel@tonic-gate case 'm': 4136*7c478bd9Sstevel@tonic-gate map->map_mflags |= MF_MATCHONLY; 4137*7c478bd9Sstevel@tonic-gate break; 4138*7c478bd9Sstevel@tonic-gate 4139*7c478bd9Sstevel@tonic-gate case 't': 4140*7c478bd9Sstevel@tonic-gate map->map_mflags |= MF_NODEFER; 4141*7c478bd9Sstevel@tonic-gate break; 4142*7c478bd9Sstevel@tonic-gate 4143*7c478bd9Sstevel@tonic-gate case 'S': /* only for consistency */ 4144*7c478bd9Sstevel@tonic-gate map->map_spacesub = *++p; 4145*7c478bd9Sstevel@tonic-gate break; 4146*7c478bd9Sstevel@tonic-gate 4147*7c478bd9Sstevel@tonic-gate case 'D': 4148*7c478bd9Sstevel@tonic-gate map->map_mflags |= MF_DEFER; 4149*7c478bd9Sstevel@tonic-gate break; 4150*7c478bd9Sstevel@tonic-gate 4151*7c478bd9Sstevel@tonic-gate case 'd': 4152*7c478bd9Sstevel@tonic-gate { 4153*7c478bd9Sstevel@tonic-gate char *h; 4154*7c478bd9Sstevel@tonic-gate 4155*7c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 4156*7c478bd9Sstevel@tonic-gate continue; 4157*7c478bd9Sstevel@tonic-gate h = strchr(p, ' '); 4158*7c478bd9Sstevel@tonic-gate if (h != NULL) 4159*7c478bd9Sstevel@tonic-gate *h = '\0'; 4160*7c478bd9Sstevel@tonic-gate map->map_timeout = convtime(p, 's'); 4161*7c478bd9Sstevel@tonic-gate if (h != NULL) 4162*7c478bd9Sstevel@tonic-gate *h = ' '; 4163*7c478bd9Sstevel@tonic-gate } 4164*7c478bd9Sstevel@tonic-gate break; 4165*7c478bd9Sstevel@tonic-gate 4166*7c478bd9Sstevel@tonic-gate case 'r': 4167*7c478bd9Sstevel@tonic-gate while (isascii(*++p) && isspace(*p)) 4168*7c478bd9Sstevel@tonic-gate continue; 4169*7c478bd9Sstevel@tonic-gate map->map_retry = atoi(p); 4170*7c478bd9Sstevel@tonic-gate break; 4171*7c478bd9Sstevel@tonic-gate } 4172*7c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 4173*7c478bd9Sstevel@tonic-gate p++; 4174*7c478bd9Sstevel@tonic-gate if (*p != '\0') 4175*7c478bd9Sstevel@tonic-gate *p++ = '\0'; 4176*7c478bd9Sstevel@tonic-gate } 4177*7c478bd9Sstevel@tonic-gate if (map->map_app != NULL) 4178*7c478bd9Sstevel@tonic-gate map->map_app = newstr(map->map_app); 4179*7c478bd9Sstevel@tonic-gate if (map->map_tapp != NULL) 4180*7c478bd9Sstevel@tonic-gate map->map_tapp = newstr(map->map_tapp); 4181*7c478bd9Sstevel@tonic-gate return true; 4182*7c478bd9Sstevel@tonic-gate } 4183*7c478bd9Sstevel@tonic-gate 4184*7c478bd9Sstevel@tonic-gate #if NETINET6 4185*7c478bd9Sstevel@tonic-gate /* 4186*7c478bd9Sstevel@tonic-gate ** ANYNET_NTOP -- convert an IPv6 network address to printable form. 4187*7c478bd9Sstevel@tonic-gate ** 4188*7c478bd9Sstevel@tonic-gate ** Parameters: 4189*7c478bd9Sstevel@tonic-gate ** s6a -- a pointer to an in6_addr structure. 4190*7c478bd9Sstevel@tonic-gate ** dst -- buffer to store result in 4191*7c478bd9Sstevel@tonic-gate ** dst_len -- size of dst buffer 4192*7c478bd9Sstevel@tonic-gate ** 4193*7c478bd9Sstevel@tonic-gate ** Returns: 4194*7c478bd9Sstevel@tonic-gate ** A printable version of that structure. 4195*7c478bd9Sstevel@tonic-gate */ 4196*7c478bd9Sstevel@tonic-gate 4197*7c478bd9Sstevel@tonic-gate char * 4198*7c478bd9Sstevel@tonic-gate anynet_ntop(s6a, dst, dst_len) 4199*7c478bd9Sstevel@tonic-gate struct in6_addr *s6a; 4200*7c478bd9Sstevel@tonic-gate char *dst; 4201*7c478bd9Sstevel@tonic-gate size_t dst_len; 4202*7c478bd9Sstevel@tonic-gate { 4203*7c478bd9Sstevel@tonic-gate register char *ap; 4204*7c478bd9Sstevel@tonic-gate 4205*7c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(s6a)) 4206*7c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET, 4207*7c478bd9Sstevel@tonic-gate &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], 4208*7c478bd9Sstevel@tonic-gate dst, dst_len); 4209*7c478bd9Sstevel@tonic-gate else 4210*7c478bd9Sstevel@tonic-gate { 4211*7c478bd9Sstevel@tonic-gate char *d; 4212*7c478bd9Sstevel@tonic-gate size_t sz; 4213*7c478bd9Sstevel@tonic-gate 4214*7c478bd9Sstevel@tonic-gate /* Save pointer to beginning of string */ 4215*7c478bd9Sstevel@tonic-gate d = dst; 4216*7c478bd9Sstevel@tonic-gate 4217*7c478bd9Sstevel@tonic-gate /* Add IPv6: protocol tag */ 4218*7c478bd9Sstevel@tonic-gate sz = sm_strlcpy(dst, "IPv6:", dst_len); 4219*7c478bd9Sstevel@tonic-gate if (sz >= dst_len) 4220*7c478bd9Sstevel@tonic-gate return NULL; 4221*7c478bd9Sstevel@tonic-gate dst += sz; 4222*7c478bd9Sstevel@tonic-gate dst_len -= sz; 4223*7c478bd9Sstevel@tonic-gate ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); 4224*7c478bd9Sstevel@tonic-gate 4225*7c478bd9Sstevel@tonic-gate /* Restore pointer to beginning of string */ 4226*7c478bd9Sstevel@tonic-gate if (ap != NULL) 4227*7c478bd9Sstevel@tonic-gate ap = d; 4228*7c478bd9Sstevel@tonic-gate } 4229*7c478bd9Sstevel@tonic-gate return ap; 4230*7c478bd9Sstevel@tonic-gate } 4231*7c478bd9Sstevel@tonic-gate 4232*7c478bd9Sstevel@tonic-gate /* 4233*7c478bd9Sstevel@tonic-gate ** ANYNET_PTON -- convert printed form to network address. 4234*7c478bd9Sstevel@tonic-gate ** 4235*7c478bd9Sstevel@tonic-gate ** Wrapper for inet_pton() which handles IPv6: labels. 4236*7c478bd9Sstevel@tonic-gate ** 4237*7c478bd9Sstevel@tonic-gate ** Parameters: 4238*7c478bd9Sstevel@tonic-gate ** family -- address family 4239*7c478bd9Sstevel@tonic-gate ** src -- string 4240*7c478bd9Sstevel@tonic-gate ** dst -- destination address structure 4241*7c478bd9Sstevel@tonic-gate ** 4242*7c478bd9Sstevel@tonic-gate ** Returns: 4243*7c478bd9Sstevel@tonic-gate ** 1 if the address was valid 4244*7c478bd9Sstevel@tonic-gate ** 0 if the address wasn't parseable 4245*7c478bd9Sstevel@tonic-gate ** -1 if error 4246*7c478bd9Sstevel@tonic-gate */ 4247*7c478bd9Sstevel@tonic-gate 4248*7c478bd9Sstevel@tonic-gate int 4249*7c478bd9Sstevel@tonic-gate anynet_pton(family, src, dst) 4250*7c478bd9Sstevel@tonic-gate int family; 4251*7c478bd9Sstevel@tonic-gate const char *src; 4252*7c478bd9Sstevel@tonic-gate void *dst; 4253*7c478bd9Sstevel@tonic-gate { 4254*7c478bd9Sstevel@tonic-gate if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0) 4255*7c478bd9Sstevel@tonic-gate src += 5; 4256*7c478bd9Sstevel@tonic-gate return inet_pton(family, src, dst); 4257*7c478bd9Sstevel@tonic-gate } 4258*7c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 4259*7c478bd9Sstevel@tonic-gate /* 4260*7c478bd9Sstevel@tonic-gate ** ANYNET_NTOA -- convert a network address to printable form. 4261*7c478bd9Sstevel@tonic-gate ** 4262*7c478bd9Sstevel@tonic-gate ** Parameters: 4263*7c478bd9Sstevel@tonic-gate ** sap -- a pointer to a sockaddr structure. 4264*7c478bd9Sstevel@tonic-gate ** 4265*7c478bd9Sstevel@tonic-gate ** Returns: 4266*7c478bd9Sstevel@tonic-gate ** A printable version of that sockaddr. 4267*7c478bd9Sstevel@tonic-gate */ 4268*7c478bd9Sstevel@tonic-gate 4269*7c478bd9Sstevel@tonic-gate #ifdef USE_SOCK_STREAM 4270*7c478bd9Sstevel@tonic-gate 4271*7c478bd9Sstevel@tonic-gate # if NETLINK 4272*7c478bd9Sstevel@tonic-gate # include <net/if_dl.h> 4273*7c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 4274*7c478bd9Sstevel@tonic-gate 4275*7c478bd9Sstevel@tonic-gate char * 4276*7c478bd9Sstevel@tonic-gate anynet_ntoa(sap) 4277*7c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 4278*7c478bd9Sstevel@tonic-gate { 4279*7c478bd9Sstevel@tonic-gate register char *bp; 4280*7c478bd9Sstevel@tonic-gate register char *ap; 4281*7c478bd9Sstevel@tonic-gate int l; 4282*7c478bd9Sstevel@tonic-gate static char buf[100]; 4283*7c478bd9Sstevel@tonic-gate 4284*7c478bd9Sstevel@tonic-gate /* check for null/zero family */ 4285*7c478bd9Sstevel@tonic-gate if (sap == NULL) 4286*7c478bd9Sstevel@tonic-gate return "NULLADDR"; 4287*7c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == 0) 4288*7c478bd9Sstevel@tonic-gate return "0"; 4289*7c478bd9Sstevel@tonic-gate 4290*7c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 4291*7c478bd9Sstevel@tonic-gate { 4292*7c478bd9Sstevel@tonic-gate # if NETUNIX 4293*7c478bd9Sstevel@tonic-gate case AF_UNIX: 4294*7c478bd9Sstevel@tonic-gate if (sap->sunix.sun_path[0] != '\0') 4295*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "[UNIX: %.64s]", 4296*7c478bd9Sstevel@tonic-gate sap->sunix.sun_path); 4297*7c478bd9Sstevel@tonic-gate else 4298*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof buf); 4299*7c478bd9Sstevel@tonic-gate return buf; 4300*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 4301*7c478bd9Sstevel@tonic-gate 4302*7c478bd9Sstevel@tonic-gate # if NETINET 4303*7c478bd9Sstevel@tonic-gate case AF_INET: 4304*7c478bd9Sstevel@tonic-gate return (char *) inet_ntoa(sap->sin.sin_addr); 4305*7c478bd9Sstevel@tonic-gate # endif /* NETINET */ 4306*7c478bd9Sstevel@tonic-gate 4307*7c478bd9Sstevel@tonic-gate # if NETINET6 4308*7c478bd9Sstevel@tonic-gate case AF_INET6: 4309*7c478bd9Sstevel@tonic-gate ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); 4310*7c478bd9Sstevel@tonic-gate if (ap != NULL) 4311*7c478bd9Sstevel@tonic-gate return ap; 4312*7c478bd9Sstevel@tonic-gate break; 4313*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4314*7c478bd9Sstevel@tonic-gate 4315*7c478bd9Sstevel@tonic-gate # if NETLINK 4316*7c478bd9Sstevel@tonic-gate case AF_LINK: 4317*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "[LINK: %s]", 4318*7c478bd9Sstevel@tonic-gate link_ntoa((struct sockaddr_dl *) &sap->sa)); 4319*7c478bd9Sstevel@tonic-gate return buf; 4320*7c478bd9Sstevel@tonic-gate # endif /* NETLINK */ 4321*7c478bd9Sstevel@tonic-gate default: 4322*7c478bd9Sstevel@tonic-gate /* this case is needed when nothing is #defined */ 4323*7c478bd9Sstevel@tonic-gate /* in order to keep the switch syntactically correct */ 4324*7c478bd9Sstevel@tonic-gate break; 4325*7c478bd9Sstevel@tonic-gate } 4326*7c478bd9Sstevel@tonic-gate 4327*7c478bd9Sstevel@tonic-gate /* unknown family -- just dump bytes */ 4328*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family); 4329*7c478bd9Sstevel@tonic-gate bp = &buf[strlen(buf)]; 4330*7c478bd9Sstevel@tonic-gate ap = sap->sa.sa_data; 4331*7c478bd9Sstevel@tonic-gate for (l = sizeof sap->sa.sa_data; --l >= 0; ) 4332*7c478bd9Sstevel@tonic-gate { 4333*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:", 4334*7c478bd9Sstevel@tonic-gate *ap++ & 0377); 4335*7c478bd9Sstevel@tonic-gate bp += 3; 4336*7c478bd9Sstevel@tonic-gate } 4337*7c478bd9Sstevel@tonic-gate *--bp = '\0'; 4338*7c478bd9Sstevel@tonic-gate return buf; 4339*7c478bd9Sstevel@tonic-gate } 4340*7c478bd9Sstevel@tonic-gate /* 4341*7c478bd9Sstevel@tonic-gate ** HOSTNAMEBYANYADDR -- return name of host based on address 4342*7c478bd9Sstevel@tonic-gate ** 4343*7c478bd9Sstevel@tonic-gate ** Parameters: 4344*7c478bd9Sstevel@tonic-gate ** sap -- SOCKADDR pointer 4345*7c478bd9Sstevel@tonic-gate ** 4346*7c478bd9Sstevel@tonic-gate ** Returns: 4347*7c478bd9Sstevel@tonic-gate ** text representation of host name. 4348*7c478bd9Sstevel@tonic-gate ** 4349*7c478bd9Sstevel@tonic-gate ** Side Effects: 4350*7c478bd9Sstevel@tonic-gate ** none. 4351*7c478bd9Sstevel@tonic-gate */ 4352*7c478bd9Sstevel@tonic-gate 4353*7c478bd9Sstevel@tonic-gate char * 4354*7c478bd9Sstevel@tonic-gate hostnamebyanyaddr(sap) 4355*7c478bd9Sstevel@tonic-gate register SOCKADDR *sap; 4356*7c478bd9Sstevel@tonic-gate { 4357*7c478bd9Sstevel@tonic-gate register struct hostent *hp; 4358*7c478bd9Sstevel@tonic-gate # if NAMED_BIND 4359*7c478bd9Sstevel@tonic-gate int saveretry; 4360*7c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 4361*7c478bd9Sstevel@tonic-gate # if NETINET6 4362*7c478bd9Sstevel@tonic-gate struct in6_addr in6_addr; 4363*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4364*7c478bd9Sstevel@tonic-gate 4365*7c478bd9Sstevel@tonic-gate # if NAMED_BIND 4366*7c478bd9Sstevel@tonic-gate /* shorten name server timeout to avoid higher level timeouts */ 4367*7c478bd9Sstevel@tonic-gate saveretry = _res.retry; 4368*7c478bd9Sstevel@tonic-gate if (_res.retry * _res.retrans > 20) 4369*7c478bd9Sstevel@tonic-gate _res.retry = 20 / _res.retrans; 4370*7c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 4371*7c478bd9Sstevel@tonic-gate 4372*7c478bd9Sstevel@tonic-gate switch (sap->sa.sa_family) 4373*7c478bd9Sstevel@tonic-gate { 4374*7c478bd9Sstevel@tonic-gate # if NETINET 4375*7c478bd9Sstevel@tonic-gate case AF_INET: 4376*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, 4377*7c478bd9Sstevel@tonic-gate INADDRSZ, AF_INET); 4378*7c478bd9Sstevel@tonic-gate break; 4379*7c478bd9Sstevel@tonic-gate # endif /* NETINET */ 4380*7c478bd9Sstevel@tonic-gate 4381*7c478bd9Sstevel@tonic-gate # if NETINET6 4382*7c478bd9Sstevel@tonic-gate case AF_INET6: 4383*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, 4384*7c478bd9Sstevel@tonic-gate IN6ADDRSZ, AF_INET6); 4385*7c478bd9Sstevel@tonic-gate break; 4386*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4387*7c478bd9Sstevel@tonic-gate 4388*7c478bd9Sstevel@tonic-gate # if NETISO 4389*7c478bd9Sstevel@tonic-gate case AF_ISO: 4390*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, 4391*7c478bd9Sstevel@tonic-gate sizeof sap->siso.siso_addr, AF_ISO); 4392*7c478bd9Sstevel@tonic-gate break; 4393*7c478bd9Sstevel@tonic-gate # endif /* NETISO */ 4394*7c478bd9Sstevel@tonic-gate 4395*7c478bd9Sstevel@tonic-gate # if NETUNIX 4396*7c478bd9Sstevel@tonic-gate case AF_UNIX: 4397*7c478bd9Sstevel@tonic-gate hp = NULL; 4398*7c478bd9Sstevel@tonic-gate break; 4399*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 4400*7c478bd9Sstevel@tonic-gate 4401*7c478bd9Sstevel@tonic-gate default: 4402*7c478bd9Sstevel@tonic-gate hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof sap->sa.sa_data, 4403*7c478bd9Sstevel@tonic-gate sap->sa.sa_family); 4404*7c478bd9Sstevel@tonic-gate break; 4405*7c478bd9Sstevel@tonic-gate } 4406*7c478bd9Sstevel@tonic-gate 4407*7c478bd9Sstevel@tonic-gate # if NAMED_BIND 4408*7c478bd9Sstevel@tonic-gate _res.retry = saveretry; 4409*7c478bd9Sstevel@tonic-gate # endif /* NAMED_BIND */ 4410*7c478bd9Sstevel@tonic-gate 4411*7c478bd9Sstevel@tonic-gate # if NETINET || NETINET6 4412*7c478bd9Sstevel@tonic-gate if (hp != NULL && hp->h_name[0] != '[' 4413*7c478bd9Sstevel@tonic-gate # if NETINET6 4414*7c478bd9Sstevel@tonic-gate && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 4415*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4416*7c478bd9Sstevel@tonic-gate # if NETINET 4417*7c478bd9Sstevel@tonic-gate && inet_addr(hp->h_name) == INADDR_NONE 4418*7c478bd9Sstevel@tonic-gate # endif /* NETINET */ 4419*7c478bd9Sstevel@tonic-gate ) 4420*7c478bd9Sstevel@tonic-gate { 4421*7c478bd9Sstevel@tonic-gate char *name; 4422*7c478bd9Sstevel@tonic-gate 4423*7c478bd9Sstevel@tonic-gate name = denlstring((char *) hp->h_name, true, true); 4424*7c478bd9Sstevel@tonic-gate # if NETINET6 4425*7c478bd9Sstevel@tonic-gate if (name == hp->h_name) 4426*7c478bd9Sstevel@tonic-gate { 4427*7c478bd9Sstevel@tonic-gate static char n[MAXNAME + 1]; 4428*7c478bd9Sstevel@tonic-gate 4429*7c478bd9Sstevel@tonic-gate /* Copy the string, hp->h_name is about to disappear */ 4430*7c478bd9Sstevel@tonic-gate (void) sm_strlcpy(n, name, sizeof n); 4431*7c478bd9Sstevel@tonic-gate name = n; 4432*7c478bd9Sstevel@tonic-gate } 4433*7c478bd9Sstevel@tonic-gate freehostent(hp); 4434*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4435*7c478bd9Sstevel@tonic-gate return name; 4436*7c478bd9Sstevel@tonic-gate } 4437*7c478bd9Sstevel@tonic-gate # endif /* NETINET || NETINET6 */ 4438*7c478bd9Sstevel@tonic-gate 4439*7c478bd9Sstevel@tonic-gate # if NETINET6 4440*7c478bd9Sstevel@tonic-gate if (hp != NULL) 4441*7c478bd9Sstevel@tonic-gate { 4442*7c478bd9Sstevel@tonic-gate freehostent(hp); 4443*7c478bd9Sstevel@tonic-gate hp = NULL; 4444*7c478bd9Sstevel@tonic-gate } 4445*7c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 4446*7c478bd9Sstevel@tonic-gate 4447*7c478bd9Sstevel@tonic-gate # if NETUNIX 4448*7c478bd9Sstevel@tonic-gate if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') 4449*7c478bd9Sstevel@tonic-gate return "localhost"; 4450*7c478bd9Sstevel@tonic-gate # endif /* NETUNIX */ 4451*7c478bd9Sstevel@tonic-gate { 4452*7c478bd9Sstevel@tonic-gate static char buf[203]; 4453*7c478bd9Sstevel@tonic-gate 4454*7c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "[%.200s]", 4455*7c478bd9Sstevel@tonic-gate anynet_ntoa(sap)); 4456*7c478bd9Sstevel@tonic-gate return buf; 4457*7c478bd9Sstevel@tonic-gate } 4458*7c478bd9Sstevel@tonic-gate } 4459*7c478bd9Sstevel@tonic-gate #endif /* USE_SOCK_STREAM */ 4460