xref: /freebsd/contrib/sendmail/src/daemon.c (revision 06f25ae9f1d6020a600a10f713046203d1a82570)
1c2aa98e2SPeter Wemm /*
206f25ae9SGregory Neil Shapiro  * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro  *	All rights reserved.
4c2aa98e2SPeter Wemm  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5c2aa98e2SPeter Wemm  * Copyright (c) 1988, 1993
6c2aa98e2SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
7c2aa98e2SPeter Wemm  *
8c2aa98e2SPeter Wemm  * By using this file, you agree to the terms and conditions set
9c2aa98e2SPeter Wemm  * forth in the LICENSE file which can be found at the top level of
10c2aa98e2SPeter Wemm  * the sendmail distribution.
11c2aa98e2SPeter Wemm  *
12c2aa98e2SPeter Wemm  */
13c2aa98e2SPeter Wemm 
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
1506f25ae9SGregory Neil Shapiro 
16c2aa98e2SPeter Wemm 
17c2aa98e2SPeter Wemm #ifndef lint
18c2aa98e2SPeter Wemm # ifdef DAEMON
1906f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: daemon.c,v 8.401.4.14 2000/07/14 04:15:00 gshapiro Exp $ (with daemon mode)";
2006f25ae9SGregory Neil Shapiro # else /* DAEMON */
2106f25ae9SGregory Neil Shapiro static char id[] = "@(#)$Id: daemon.c,v 8.401.4.14 2000/07/14 04:15:00 gshapiro Exp $ (without daemon mode)";
2206f25ae9SGregory Neil Shapiro # endif /* DAEMON */
2306f25ae9SGregory Neil Shapiro #endif /* ! lint */
24c2aa98e2SPeter Wemm 
25c2aa98e2SPeter Wemm #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
26c2aa98e2SPeter Wemm # define USE_SOCK_STREAM	1
2706f25ae9SGregory Neil Shapiro #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */
28c2aa98e2SPeter Wemm 
29c2aa98e2SPeter Wemm #if DAEMON || defined(USE_SOCK_STREAM)
3006f25ae9SGregory Neil Shapiro # if NETINET || NETINET6
31c2aa98e2SPeter Wemm #  include <arpa/inet.h>
3206f25ae9SGregory Neil Shapiro # endif /* NETINET || NETINET6 */
33c2aa98e2SPeter Wemm # if NAMED_BIND
34c2aa98e2SPeter Wemm #  ifndef NO_DATA
35c2aa98e2SPeter Wemm #   define NO_DATA	NO_ADDRESS
3606f25ae9SGregory Neil Shapiro #  endif /* ! NO_DATA */
3706f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
3806f25ae9SGregory Neil Shapiro #endif /* DAEMON || defined(USE_SOCK_STREAM) */
39c2aa98e2SPeter Wemm 
40c2aa98e2SPeter Wemm #if DAEMON
41c2aa98e2SPeter Wemm 
42c2aa98e2SPeter Wemm # include <sys/time.h>
43c2aa98e2SPeter Wemm 
4406f25ae9SGregory Neil Shapiro # if IP_SRCROUTE && NETINET
45c2aa98e2SPeter Wemm #  include <netinet/in_systm.h>
46c2aa98e2SPeter Wemm #  include <netinet/ip.h>
4706f25ae9SGregory Neil Shapiro #  if HAS_IN_H
4806f25ae9SGregory Neil Shapiro #   include <netinet/in.h>
4906f25ae9SGregory Neil Shapiro #   ifndef IPOPTION
5006f25ae9SGregory Neil Shapiro #    define IPOPTION	ip_opts
5106f25ae9SGregory Neil Shapiro #    define IP_LIST	ip_opts
5206f25ae9SGregory Neil Shapiro #    define IP_DST	ip_dst
5306f25ae9SGregory Neil Shapiro #   endif /* ! IPOPTION */
5406f25ae9SGregory Neil Shapiro #  else /* HAS_IN_H */
55c2aa98e2SPeter Wemm #   include <netinet/ip_var.h>
5606f25ae9SGregory Neil Shapiro #   ifndef IPOPTION
5706f25ae9SGregory Neil Shapiro #    define IPOPTION	ipoption
5806f25ae9SGregory Neil Shapiro #    define IP_LIST	ipopt_list
5906f25ae9SGregory Neil Shapiro #    define IP_DST	ipopt_dst
6006f25ae9SGregory Neil Shapiro #   endif /* ! IPOPTION */
6106f25ae9SGregory Neil Shapiro #  endif /* HAS_IN_H */
6206f25ae9SGregory Neil Shapiro # endif /* IP_SRCROUTE && NETINET */
6306f25ae9SGregory Neil Shapiro 
6406f25ae9SGregory Neil Shapiro /* structure to describe a daemon */
6506f25ae9SGregory Neil Shapiro struct daemon
6606f25ae9SGregory Neil Shapiro {
6706f25ae9SGregory Neil Shapiro 	int		d_socket;	/* fd for socket */
6806f25ae9SGregory Neil Shapiro 	SOCKADDR	d_addr;		/* socket for incoming */
6906f25ae9SGregory Neil Shapiro 	u_short		d_port;		/* port number */
7006f25ae9SGregory Neil Shapiro 	int		d_listenqueue;	/* size of listen queue */
7106f25ae9SGregory Neil Shapiro 	int		d_tcprcvbufsize;	/* size of TCP receive buffer */
7206f25ae9SGregory Neil Shapiro 	int		d_tcpsndbufsize;	/* size of TCP send buffer */
7306f25ae9SGregory Neil Shapiro 	time_t		d_refuse_connections_until;
7406f25ae9SGregory Neil Shapiro 	bool		d_firsttime;
7506f25ae9SGregory Neil Shapiro 	int		d_socksize;
7606f25ae9SGregory Neil Shapiro 	BITMAP256	d_flags;	/* flags; see sendmail.h */
7706f25ae9SGregory Neil Shapiro 	char		*d_mflags;	/* flags for use in macro */
7806f25ae9SGregory Neil Shapiro 	char		*d_name;	/* user-supplied name */
7906f25ae9SGregory Neil Shapiro };
8006f25ae9SGregory Neil Shapiro 
8106f25ae9SGregory Neil Shapiro typedef struct daemon DAEMON_T;
8206f25ae9SGregory Neil Shapiro 
8306f25ae9SGregory Neil Shapiro static void	connecttimeout __P((void));
8406f25ae9SGregory Neil Shapiro static int	opendaemonsocket __P((struct daemon *, bool));
8506f25ae9SGregory Neil Shapiro static u_short	setupdaemon __P((SOCKADDR *));
86c2aa98e2SPeter Wemm 
87c2aa98e2SPeter Wemm /*
88c2aa98e2SPeter Wemm **  DAEMON.C -- routines to use when running as a daemon.
89c2aa98e2SPeter Wemm **
90c2aa98e2SPeter Wemm **	This entire file is highly dependent on the 4.2 BSD
91c2aa98e2SPeter Wemm **	interprocess communication primitives.  No attempt has
92c2aa98e2SPeter Wemm **	been made to make this file portable to Version 7,
93c2aa98e2SPeter Wemm **	Version 6, MPX files, etc.  If you should try such a
94c2aa98e2SPeter Wemm **	thing yourself, I recommend chucking the entire file
95c2aa98e2SPeter Wemm **	and starting from scratch.  Basic semantics are:
96c2aa98e2SPeter Wemm **
97c2aa98e2SPeter Wemm **	getrequests(e)
98c2aa98e2SPeter Wemm **		Opens a port and initiates a connection.
99c2aa98e2SPeter Wemm **		Returns in a child.  Must set InChannel and
100c2aa98e2SPeter Wemm **		OutChannel appropriately.
101c2aa98e2SPeter Wemm **	clrdaemon()
102c2aa98e2SPeter Wemm **		Close any open files associated with getting
103c2aa98e2SPeter Wemm **		the connection; this is used when running the queue,
104c2aa98e2SPeter Wemm **		etc., to avoid having extra file descriptors during
105c2aa98e2SPeter Wemm **		the queue run and to avoid confusing the network
106c2aa98e2SPeter Wemm **		code (if it cares).
107c2aa98e2SPeter Wemm **	makeconnection(host, port, outfile, infile, e)
108c2aa98e2SPeter Wemm **		Make a connection to the named host on the given
109c2aa98e2SPeter Wemm **		port.  Set *outfile and *infile to the files
110c2aa98e2SPeter Wemm **		appropriate for communication.  Returns zero on
111c2aa98e2SPeter Wemm **		success, else an exit status describing the
112c2aa98e2SPeter Wemm **		error.
113c2aa98e2SPeter Wemm **	host_map_lookup(map, hbuf, avp, pstat)
114c2aa98e2SPeter Wemm **		Convert the entry in hbuf into a canonical form.
115c2aa98e2SPeter Wemm */
11606f25ae9SGregory Neil Shapiro 
11706f25ae9SGregory Neil Shapiro static DAEMON_T	Daemons[MAXDAEMONS];
11806f25ae9SGregory Neil Shapiro static int	ndaemons = 0;			/* actual number of daemons */
11906f25ae9SGregory Neil Shapiro 
12006f25ae9SGregory Neil Shapiro /* options for client */
12106f25ae9SGregory Neil Shapiro static int	TcpRcvBufferSize = 0;	/* size of TCP receive buffer */
12206f25ae9SGregory Neil Shapiro static int	TcpSndBufferSize = 0;	/* size of TCP send buffer */
12306f25ae9SGregory Neil Shapiro 
124c2aa98e2SPeter Wemm /*
125c2aa98e2SPeter Wemm **  GETREQUESTS -- open mail IPC port and get requests.
126c2aa98e2SPeter Wemm **
127c2aa98e2SPeter Wemm **	Parameters:
128c2aa98e2SPeter Wemm **		e -- the current envelope.
129c2aa98e2SPeter Wemm **
130c2aa98e2SPeter Wemm **	Returns:
13106f25ae9SGregory Neil Shapiro **		pointer to flags.
132c2aa98e2SPeter Wemm **
133c2aa98e2SPeter Wemm **	Side Effects:
134c2aa98e2SPeter Wemm **		Waits until some interesting activity occurs.  When
135c2aa98e2SPeter Wemm **		it does, a child is created to process it, and the
136c2aa98e2SPeter Wemm **		parent waits for completion.  Return from this
137c2aa98e2SPeter Wemm **		routine is always in the child.  The file pointers
138c2aa98e2SPeter Wemm **		"InChannel" and "OutChannel" should be set to point
139c2aa98e2SPeter Wemm **		to the communication channel.
140c2aa98e2SPeter Wemm */
141c2aa98e2SPeter Wemm 
14206f25ae9SGregory Neil Shapiro BITMAP256 *
143c2aa98e2SPeter Wemm getrequests(e)
144c2aa98e2SPeter Wemm 	ENVELOPE *e;
145c2aa98e2SPeter Wemm {
146c2aa98e2SPeter Wemm 	int t;
14706f25ae9SGregory Neil Shapiro 	time_t last_disk_space_check = 0;
14806f25ae9SGregory Neil Shapiro 	int idx, curdaemon = -1;
14906f25ae9SGregory Neil Shapiro 	int i, olddaemon = 0;
150c2aa98e2SPeter Wemm # if XDEBUG
151c2aa98e2SPeter Wemm 	bool j_has_dot;
15206f25ae9SGregory Neil Shapiro # endif /* XDEBUG */
153065a643dSPeter Wemm 	char status[MAXLINE];
15406f25ae9SGregory Neil Shapiro 	SOCKADDR sa;
15506f25ae9SGregory Neil Shapiro 	SOCKADDR_LEN_T len = sizeof sa;
15606f25ae9SGregory Neil Shapiro # if NETUNIX
157065a643dSPeter Wemm 	extern int ControlSocket;
15806f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
15906f25ae9SGregory Neil Shapiro 	extern ENVELOPE BlankEnvelope;
160c2aa98e2SPeter Wemm 
16106f25ae9SGregory Neil Shapiro #define D(x,idx)	x[idx]
162c2aa98e2SPeter Wemm 
16306f25ae9SGregory Neil Shapiro 
16406f25ae9SGregory Neil Shapiro 	for (idx = 0; idx < ndaemons; idx++)
165c2aa98e2SPeter Wemm 	{
16606f25ae9SGregory Neil Shapiro 		Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr));
16706f25ae9SGregory Neil Shapiro 		Daemons[idx].d_firsttime = TRUE;
16806f25ae9SGregory Neil Shapiro 		Daemons[idx].d_refuse_connections_until = (time_t) 0;
169c2aa98e2SPeter Wemm 	}
170c2aa98e2SPeter Wemm 	/*
171c2aa98e2SPeter Wemm 	**  Try to actually open the connection.
172c2aa98e2SPeter Wemm 	*/
173c2aa98e2SPeter Wemm 
174c2aa98e2SPeter Wemm 	if (tTd(15, 1))
17506f25ae9SGregory Neil Shapiro 	{
17606f25ae9SGregory Neil Shapiro 		for (idx = 0; idx < ndaemons; idx++)
17706f25ae9SGregory Neil Shapiro 			dprintf("getrequests: daemon %s: port %d\n",
17806f25ae9SGregory Neil Shapiro 				Daemons[idx].d_name,
17906f25ae9SGregory Neil Shapiro 				ntohs(Daemons[idx].d_port));
18006f25ae9SGregory Neil Shapiro 	}
181c2aa98e2SPeter Wemm 
182c2aa98e2SPeter Wemm 	/* get a socket for the SMTP connection */
18306f25ae9SGregory Neil Shapiro 	for (idx = 0; idx < ndaemons; idx++)
18406f25ae9SGregory Neil Shapiro 		Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE);
185c2aa98e2SPeter Wemm 
186065a643dSPeter Wemm 	if (opencontrolsocket() < 0)
187065a643dSPeter Wemm 		sm_syslog(LOG_WARNING, NOQID,
1882e43090eSPeter Wemm 			  "daemon could not open control socket %s: %s",
1892e43090eSPeter Wemm 			  ControlSocketName, errstring(errno));
190065a643dSPeter Wemm 
191c2aa98e2SPeter Wemm 	(void) setsignal(SIGCHLD, reapchild);
192c2aa98e2SPeter Wemm 
19306f25ae9SGregory Neil Shapiro 	/* write the pid to file */
19406f25ae9SGregory Neil Shapiro 	log_sendmail_pid(e);
195c2aa98e2SPeter Wemm 
196c2aa98e2SPeter Wemm # if XDEBUG
197c2aa98e2SPeter Wemm 	{
198c2aa98e2SPeter Wemm 		char jbuf[MAXHOSTNAMELEN];
199c2aa98e2SPeter Wemm 
200c2aa98e2SPeter Wemm 		expand("\201j", jbuf, sizeof jbuf, e);
201c2aa98e2SPeter Wemm 		j_has_dot = strchr(jbuf, '.') != NULL;
202c2aa98e2SPeter Wemm 	}
20306f25ae9SGregory Neil Shapiro # endif /* XDEBUG */
204c2aa98e2SPeter Wemm 
205065a643dSPeter Wemm 	/* Add parent process as first item */
20606f25ae9SGregory Neil Shapiro 	proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON);
207065a643dSPeter Wemm 
208c2aa98e2SPeter Wemm 	if (tTd(15, 1))
20906f25ae9SGregory Neil Shapiro 	{
21006f25ae9SGregory Neil Shapiro 		for (idx = 0; idx < ndaemons; idx++)
21106f25ae9SGregory Neil Shapiro 			dprintf("getrequests: daemon %s: %d\n",
21206f25ae9SGregory Neil Shapiro 				Daemons[idx].d_name,
21306f25ae9SGregory Neil Shapiro 				Daemons[idx].d_socket);
21406f25ae9SGregory Neil Shapiro 	}
215c2aa98e2SPeter Wemm 
216c2aa98e2SPeter Wemm 	for (;;)
217c2aa98e2SPeter Wemm 	{
218c2aa98e2SPeter Wemm 		register pid_t pid;
219c2aa98e2SPeter Wemm 		auto SOCKADDR_LEN_T lotherend;
220065a643dSPeter Wemm 		bool timedout = FALSE;
221065a643dSPeter Wemm 		bool control = FALSE;
22206f25ae9SGregory Neil Shapiro 		int save_errno;
223c2aa98e2SPeter Wemm 		int pipefd[2];
224c2aa98e2SPeter Wemm 
225c2aa98e2SPeter Wemm 		/* see if we are rejecting connections */
226c2aa98e2SPeter Wemm 		(void) blocksignal(SIGALRM);
22706f25ae9SGregory Neil Shapiro 
22806f25ae9SGregory Neil Shapiro 		for (idx = 0; idx < ndaemons; idx++)
229065a643dSPeter Wemm 		{
23006f25ae9SGregory Neil Shapiro 			if (curtime() < Daemons[idx].d_refuse_connections_until)
23106f25ae9SGregory Neil Shapiro 				continue;
23206f25ae9SGregory Neil Shapiro 			if (refuseconnections(Daemons[idx].d_name, e, idx))
233c2aa98e2SPeter Wemm 			{
23406f25ae9SGregory Neil Shapiro 				if (Daemons[idx].d_socket >= 0)
235c2aa98e2SPeter Wemm 				{
236065a643dSPeter Wemm 				       /* close socket so peer fails quickly */
23706f25ae9SGregory Neil Shapiro 				       (void) close(Daemons[idx].d_socket);
23806f25ae9SGregory Neil Shapiro 				       Daemons[idx].d_socket = -1;
239c2aa98e2SPeter Wemm 				}
240c2aa98e2SPeter Wemm 
241065a643dSPeter Wemm 				/* refuse connections for next 15 seconds */
24206f25ae9SGregory Neil Shapiro 				Daemons[idx].d_refuse_connections_until = curtime() + 15;
243065a643dSPeter Wemm 			}
24406f25ae9SGregory Neil Shapiro 			else if (Daemons[idx].d_socket < 0 ||
24506f25ae9SGregory Neil Shapiro 				 Daemons[idx].d_firsttime)
246c2aa98e2SPeter Wemm 			{
24706f25ae9SGregory Neil Shapiro 			      if (!Daemons[idx].d_firsttime && LogLevel >= 9)
24806f25ae9SGregory Neil Shapiro 				sm_syslog(LOG_INFO, NOQID,
24906f25ae9SGregory Neil Shapiro 					  "accepting connections again for daemon %s",
25006f25ae9SGregory Neil Shapiro 					  Daemons[idx].d_name);
25106f25ae9SGregory Neil Shapiro 
252065a643dSPeter Wemm 			      /* arrange to (re)open the socket if needed */
25306f25ae9SGregory Neil Shapiro 			      (void) opendaemonsocket(&Daemons[idx], FALSE);
25406f25ae9SGregory Neil Shapiro 			      Daemons[idx].d_firsttime = FALSE;
255065a643dSPeter Wemm 			}
256c2aa98e2SPeter Wemm 		}
257c2aa98e2SPeter Wemm 
25806f25ae9SGregory Neil Shapiro 		if (curtime() >= last_disk_space_check)
25906f25ae9SGregory Neil Shapiro 		{
26006f25ae9SGregory Neil Shapiro 			if (!enoughdiskspace(MinBlocksFree + 1, FALSE))
26106f25ae9SGregory Neil Shapiro 			{
26206f25ae9SGregory Neil Shapiro 				if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags))
26306f25ae9SGregory Neil Shapiro 				{
26406f25ae9SGregory Neil Shapiro 					/* log only if not logged before */
26506f25ae9SGregory Neil Shapiro 					if (LogLevel >= 9)
26606f25ae9SGregory Neil Shapiro 						sm_syslog(LOG_INFO, NOQID,
26706f25ae9SGregory Neil Shapiro 							  "rejecting new messages: min free: %d",
26806f25ae9SGregory Neil Shapiro 							  MinBlocksFree);
26906f25ae9SGregory Neil Shapiro 					sm_setproctitle(TRUE, e,
27006f25ae9SGregory Neil Shapiro 							"rejecting new messages: min free: %d",
27106f25ae9SGregory Neil Shapiro 							 MinBlocksFree);
27206f25ae9SGregory Neil Shapiro 					setbitn(D_ETRNONLY, Daemons[idx].d_flags);
27306f25ae9SGregory Neil Shapiro 				}
27406f25ae9SGregory Neil Shapiro 			}
27506f25ae9SGregory Neil Shapiro 			else if (bitnset(D_ETRNONLY, Daemons[idx].d_flags))
27606f25ae9SGregory Neil Shapiro 			{
27706f25ae9SGregory Neil Shapiro 				/* log only if not logged before */
27806f25ae9SGregory Neil Shapiro 				if (LogLevel >= 9)
27906f25ae9SGregory Neil Shapiro 					sm_syslog(LOG_INFO, NOQID,
28006f25ae9SGregory Neil Shapiro 						  "accepting new messages (again)");
28106f25ae9SGregory Neil Shapiro 				/* title will be set below */
28206f25ae9SGregory Neil Shapiro 				clrbitn(D_ETRNONLY, Daemons[idx].d_flags);
28306f25ae9SGregory Neil Shapiro 			}
28406f25ae9SGregory Neil Shapiro 			/* only check disk space once a minute */
28506f25ae9SGregory Neil Shapiro 			last_disk_space_check = curtime() + 60;
28606f25ae9SGregory Neil Shapiro 		}
28706f25ae9SGregory Neil Shapiro 
288c2aa98e2SPeter Wemm # if XDEBUG
289c2aa98e2SPeter Wemm 		/* check for disaster */
290c2aa98e2SPeter Wemm 		{
291c2aa98e2SPeter Wemm 			char jbuf[MAXHOSTNAMELEN];
292c2aa98e2SPeter Wemm 
293c2aa98e2SPeter Wemm 			expand("\201j", jbuf, sizeof jbuf, e);
294c2aa98e2SPeter Wemm 			if (!wordinclass(jbuf, 'w'))
295c2aa98e2SPeter Wemm 			{
296c2aa98e2SPeter Wemm 				dumpstate("daemon lost $j");
297c2aa98e2SPeter Wemm 				sm_syslog(LOG_ALERT, NOQID,
298c2aa98e2SPeter Wemm 					  "daemon process doesn't have $j in $=w; see syslog");
299c2aa98e2SPeter Wemm 				abort();
300c2aa98e2SPeter Wemm 			}
301c2aa98e2SPeter Wemm 			else if (j_has_dot && strchr(jbuf, '.') == NULL)
302c2aa98e2SPeter Wemm 			{
303c2aa98e2SPeter Wemm 				dumpstate("daemon $j lost dot");
304c2aa98e2SPeter Wemm 				sm_syslog(LOG_ALERT, NOQID,
305c2aa98e2SPeter Wemm 					  "daemon process $j lost dot; see syslog");
306c2aa98e2SPeter Wemm 				abort();
307c2aa98e2SPeter Wemm 			}
308c2aa98e2SPeter Wemm 		}
30906f25ae9SGregory Neil Shapiro # endif /* XDEBUG */
310c2aa98e2SPeter Wemm 
311c2aa98e2SPeter Wemm # if 0
312c2aa98e2SPeter Wemm 		/*
313c2aa98e2SPeter Wemm 		**  Andrew Sun <asun@ieps-sun.ml.com> claims that this will
314c2aa98e2SPeter Wemm 		**  fix the SVr4 problem.  But it seems to have gone away,
315c2aa98e2SPeter Wemm 		**  so is it worth doing this?
316c2aa98e2SPeter Wemm 		*/
317c2aa98e2SPeter Wemm 
318065a643dSPeter Wemm 		if (DaemonSocket >= 0 &&
319065a643dSPeter Wemm 		    SetNonBlocking(DaemonSocket, FALSE) < 0)
320c2aa98e2SPeter Wemm 			log an error here;
32106f25ae9SGregory Neil Shapiro # endif /* 0 */
322c2aa98e2SPeter Wemm 		(void) releasesignal(SIGALRM);
32306f25ae9SGregory Neil Shapiro 
324c2aa98e2SPeter Wemm 		for (;;)
325c2aa98e2SPeter Wemm 		{
326065a643dSPeter Wemm 			int highest = -1;
327c2aa98e2SPeter Wemm 			fd_set readfds;
328c2aa98e2SPeter Wemm 			struct timeval timeout;
329c2aa98e2SPeter Wemm 
330c2aa98e2SPeter Wemm 			FD_ZERO(&readfds);
331065a643dSPeter Wemm 
33206f25ae9SGregory Neil Shapiro 			for (idx = 0; idx < ndaemons; idx++)
333065a643dSPeter Wemm 			{
33406f25ae9SGregory Neil Shapiro 				/* wait for a connection */
33506f25ae9SGregory Neil Shapiro 				if (Daemons[idx].d_socket >= 0)
33606f25ae9SGregory Neil Shapiro 				{
33706f25ae9SGregory Neil Shapiro 					if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags))
33806f25ae9SGregory Neil Shapiro 					{
33906f25ae9SGregory Neil Shapiro 						sm_setproctitle(TRUE, e,
34006f25ae9SGregory Neil Shapiro 								"accepting connections");
341065a643dSPeter Wemm 					}
34206f25ae9SGregory Neil Shapiro 					if (Daemons[idx].d_socket > highest)
34306f25ae9SGregory Neil Shapiro 						highest = Daemons[idx].d_socket;
34406f25ae9SGregory Neil Shapiro 					FD_SET((u_int)Daemons[idx].d_socket, &readfds);
34506f25ae9SGregory Neil Shapiro 				}
34606f25ae9SGregory Neil Shapiro 			}
34706f25ae9SGregory Neil Shapiro 
34806f25ae9SGregory Neil Shapiro # if NETUNIX
349065a643dSPeter Wemm 			if (ControlSocket >= 0)
350065a643dSPeter Wemm 			{
351065a643dSPeter Wemm 				if (ControlSocket > highest)
352065a643dSPeter Wemm 					highest = ControlSocket;
353065a643dSPeter Wemm 				FD_SET(ControlSocket, &readfds);
354065a643dSPeter Wemm 			}
35506f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
35606f25ae9SGregory Neil Shapiro 
35706f25ae9SGregory Neil Shapiro 			/*
35806f25ae9SGregory Neil Shapiro 			**  if one socket is closed, set the timeout
35906f25ae9SGregory Neil Shapiro 			**  to 5 seconds (so it might get reopened soon),
36006f25ae9SGregory Neil Shapiro 			**  otherwise (all sockets open) 60.
36106f25ae9SGregory Neil Shapiro 			*/
36206f25ae9SGregory Neil Shapiro 			idx = 0;
36306f25ae9SGregory Neil Shapiro 			while (idx < ndaemons && Daemons[idx].d_socket >= 0)
36406f25ae9SGregory Neil Shapiro 				idx++;
36506f25ae9SGregory Neil Shapiro 			if (idx < ndaemons)
366065a643dSPeter Wemm 				timeout.tv_sec = 5;
36706f25ae9SGregory Neil Shapiro 			else
36806f25ae9SGregory Neil Shapiro 				timeout.tv_sec = 60;
369c2aa98e2SPeter Wemm 			timeout.tv_usec = 0;
370c2aa98e2SPeter Wemm 
371065a643dSPeter Wemm 			t = select(highest + 1, FDSET_CAST &readfds,
372c2aa98e2SPeter Wemm 				   NULL, NULL, &timeout);
373065a643dSPeter Wemm 
374c2aa98e2SPeter Wemm 			if (DoQueueRun)
375c2aa98e2SPeter Wemm 				(void) runqueue(TRUE, FALSE);
376065a643dSPeter Wemm 			if (t <= 0)
377065a643dSPeter Wemm 			{
378065a643dSPeter Wemm 				timedout = TRUE;
379065a643dSPeter Wemm 				break;
380065a643dSPeter Wemm 			}
381c2aa98e2SPeter Wemm 
382065a643dSPeter Wemm 			control = FALSE;
383c2aa98e2SPeter Wemm 			errno = 0;
38406f25ae9SGregory Neil Shapiro 			curdaemon = -1;
38506f25ae9SGregory Neil Shapiro 
38606f25ae9SGregory Neil Shapiro 			/* look "round-robin" for an active socket */
38706f25ae9SGregory Neil Shapiro 			if ((idx = olddaemon + 1) >= ndaemons)
38806f25ae9SGregory Neil Shapiro 				idx = 0;
38906f25ae9SGregory Neil Shapiro 			for (i = 0; i < ndaemons; i++)
390065a643dSPeter Wemm 			{
39106f25ae9SGregory Neil Shapiro 				if (Daemons[idx].d_socket >= 0 &&
39206f25ae9SGregory Neil Shapiro 				    FD_ISSET(Daemons[idx].d_socket, &readfds))
39306f25ae9SGregory Neil Shapiro 				{
39406f25ae9SGregory Neil Shapiro 					lotherend = Daemons[idx].d_socksize;
39506f25ae9SGregory Neil Shapiro 					t = accept(Daemons[idx].d_socket,
396065a643dSPeter Wemm 						   (struct sockaddr *)&RealHostAddr,
397065a643dSPeter Wemm 						   &lotherend);
39806f25ae9SGregory Neil Shapiro 					olddaemon = curdaemon = idx;
39906f25ae9SGregory Neil Shapiro 					break;
400065a643dSPeter Wemm 				}
40106f25ae9SGregory Neil Shapiro 				if (++idx >= ndaemons)
40206f25ae9SGregory Neil Shapiro 					idx = 0;
40306f25ae9SGregory Neil Shapiro 			}
40406f25ae9SGregory Neil Shapiro # if NETUNIX
40506f25ae9SGregory Neil Shapiro 			if (curdaemon == -1 && ControlSocket >= 0 &&
406065a643dSPeter Wemm 				 FD_ISSET(ControlSocket, &readfds))
407065a643dSPeter Wemm 			{
408065a643dSPeter Wemm 				struct sockaddr_un sa_un;
409065a643dSPeter Wemm 
410065a643dSPeter Wemm 				lotherend = sizeof sa_un;
411065a643dSPeter Wemm 				t = accept(ControlSocket,
412065a643dSPeter Wemm 					   (struct sockaddr *)&sa_un,
413065a643dSPeter Wemm 					   &lotherend);
414065a643dSPeter Wemm 				control = TRUE;
415065a643dSPeter Wemm 			}
41606f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
417c2aa98e2SPeter Wemm 			if (t >= 0 || errno != EINTR)
418c2aa98e2SPeter Wemm 				break;
419c2aa98e2SPeter Wemm 		}
420065a643dSPeter Wemm 		if (timedout)
421065a643dSPeter Wemm 		{
422065a643dSPeter Wemm 			timedout = FALSE;
423065a643dSPeter Wemm 			continue;
424065a643dSPeter Wemm 		}
42506f25ae9SGregory Neil Shapiro 		save_errno = errno;
426c2aa98e2SPeter Wemm 		(void) blocksignal(SIGALRM);
427c2aa98e2SPeter Wemm 		if (t < 0)
428c2aa98e2SPeter Wemm 		{
42906f25ae9SGregory Neil Shapiro 			errno = save_errno;
430c2aa98e2SPeter Wemm 			syserr("getrequests: accept");
431c2aa98e2SPeter Wemm 
432c2aa98e2SPeter Wemm 			/* arrange to re-open the socket next time around */
43306f25ae9SGregory Neil Shapiro 			(void) close(Daemons[curdaemon].d_socket);
43406f25ae9SGregory Neil Shapiro 			Daemons[curdaemon].d_socket = -1;
43506f25ae9SGregory Neil Shapiro # if SO_REUSEADDR_IS_BROKEN
43606f25ae9SGregory Neil Shapiro 			/*
43706f25ae9SGregory Neil Shapiro 			**  Give time for bound socket to be released.
43806f25ae9SGregory Neil Shapiro 			**  This creates a denial-of-service if you can
43906f25ae9SGregory Neil Shapiro 			**  force accept() to fail on affected systems.
44006f25ae9SGregory Neil Shapiro 			*/
44106f25ae9SGregory Neil Shapiro 
44206f25ae9SGregory Neil Shapiro 			Daemons[curdaemon].d_refuse_connections_until = curtime() + 15;
44306f25ae9SGregory Neil Shapiro # endif /* SO_REUSEADDR_IS_BROKEN */
444c2aa98e2SPeter Wemm 			continue;
445c2aa98e2SPeter Wemm 		}
446c2aa98e2SPeter Wemm 
44706f25ae9SGregory Neil Shapiro 		if (!control)
44806f25ae9SGregory Neil Shapiro 		{
44906f25ae9SGregory Neil Shapiro 			/* set some daemon related macros */
45006f25ae9SGregory Neil Shapiro 			switch (Daemons[curdaemon].d_addr.sa.sa_family)
45106f25ae9SGregory Neil Shapiro 			{
45206f25ae9SGregory Neil Shapiro 			  case AF_UNSPEC:
45306f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
45406f25ae9SGregory Neil Shapiro 				       "unspec", &BlankEnvelope);
45506f25ae9SGregory Neil Shapiro 				break;
45606f25ae9SGregory Neil Shapiro # if NETINET
45706f25ae9SGregory Neil Shapiro 			  case AF_INET:
45806f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
45906f25ae9SGregory Neil Shapiro 				       "inet", &BlankEnvelope);
46006f25ae9SGregory Neil Shapiro 				break;
46106f25ae9SGregory Neil Shapiro # endif /* NETINET */
46206f25ae9SGregory Neil Shapiro # if NETINET6
46306f25ae9SGregory Neil Shapiro 			  case AF_INET6:
46406f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
46506f25ae9SGregory Neil Shapiro 				       "inet6", &BlankEnvelope);
46606f25ae9SGregory Neil Shapiro 				break;
46706f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
46806f25ae9SGregory Neil Shapiro # if NETISO
46906f25ae9SGregory Neil Shapiro 			  case AF_ISO:
47006f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
47106f25ae9SGregory Neil Shapiro 				       "iso", &BlankEnvelope);
47206f25ae9SGregory Neil Shapiro 				break;
47306f25ae9SGregory Neil Shapiro # endif /* NETISO */
47406f25ae9SGregory Neil Shapiro # if NETNS
47506f25ae9SGregory Neil Shapiro 			  case AF_NS:
47606f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
47706f25ae9SGregory Neil Shapiro 				       "ns", &BlankEnvelope);
47806f25ae9SGregory Neil Shapiro 				break;
47906f25ae9SGregory Neil Shapiro # endif /* NETNS */
48006f25ae9SGregory Neil Shapiro # if NETX25
48106f25ae9SGregory Neil Shapiro 			  case AF_CCITT:
48206f25ae9SGregory Neil Shapiro 				define(macid("{daemon_family}", NULL),
48306f25ae9SGregory Neil Shapiro 				       "x.25", &BlankEnvelope);
48406f25ae9SGregory Neil Shapiro 				break;
48506f25ae9SGregory Neil Shapiro # endif /* NETX25 */
48606f25ae9SGregory Neil Shapiro 			}
48706f25ae9SGregory Neil Shapiro 			define(macid("{daemon_name}", NULL),
48806f25ae9SGregory Neil Shapiro 			       Daemons[curdaemon].d_name, &BlankEnvelope);
48906f25ae9SGregory Neil Shapiro 			if (Daemons[curdaemon].d_mflags != NULL)
49006f25ae9SGregory Neil Shapiro 				define(macid("{daemon_flags}", NULL),
49106f25ae9SGregory Neil Shapiro 				       Daemons[curdaemon].d_mflags,
49206f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
49306f25ae9SGregory Neil Shapiro 			else
49406f25ae9SGregory Neil Shapiro 				define(macid("{daemon_flags}", NULL),
49506f25ae9SGregory Neil Shapiro 				       "", &BlankEnvelope);
49606f25ae9SGregory Neil Shapiro 		}
49706f25ae9SGregory Neil Shapiro 
498c2aa98e2SPeter Wemm 		/*
499c2aa98e2SPeter Wemm 		**  Create a subprocess to process the mail.
500c2aa98e2SPeter Wemm 		*/
501c2aa98e2SPeter Wemm 
502c2aa98e2SPeter Wemm 		if (tTd(15, 2))
50306f25ae9SGregory Neil Shapiro 			dprintf("getrequests: forking (fd = %d)\n", t);
50406f25ae9SGregory Neil Shapiro 
50506f25ae9SGregory Neil Shapiro 		/*
50606f25ae9SGregory Neil Shapiro 		**  advance state of PRNG
50706f25ae9SGregory Neil Shapiro 		**  this is necessary because otherwise all child processes
50806f25ae9SGregory Neil Shapiro 		**  will produce the same PRN sequence and hence the selection
50906f25ae9SGregory Neil Shapiro 		**  of a queue directory (and other things, e.g., MX selection)
51006f25ae9SGregory Neil Shapiro 		**  are not "really" random.
51106f25ae9SGregory Neil Shapiro 		*/
51206f25ae9SGregory Neil Shapiro 		(void) get_random();
513c2aa98e2SPeter Wemm 
514c2aa98e2SPeter Wemm 		/*
515c2aa98e2SPeter Wemm 		**  Create a pipe to keep the child from writing to the
516c2aa98e2SPeter Wemm 		**  socket until after the parent has closed it.  Otherwise
517c2aa98e2SPeter Wemm 		**  the parent may hang if the child has closed it first.
518c2aa98e2SPeter Wemm 		*/
519c2aa98e2SPeter Wemm 
520c2aa98e2SPeter Wemm 		if (pipe(pipefd) < 0)
521c2aa98e2SPeter Wemm 			pipefd[0] = pipefd[1] = -1;
522c2aa98e2SPeter Wemm 
52306f25ae9SGregory Neil Shapiro 		(void) blocksignal(SIGCHLD);
524c2aa98e2SPeter Wemm 		pid = fork();
525c2aa98e2SPeter Wemm 		if (pid < 0)
526c2aa98e2SPeter Wemm 		{
527c2aa98e2SPeter Wemm 			syserr("daemon: cannot fork");
528c2aa98e2SPeter Wemm 			if (pipefd[0] != -1)
529c2aa98e2SPeter Wemm 			{
530c2aa98e2SPeter Wemm 				(void) close(pipefd[0]);
531c2aa98e2SPeter Wemm 				(void) close(pipefd[1]);
532c2aa98e2SPeter Wemm 			}
533c2aa98e2SPeter Wemm 			(void) releasesignal(SIGCHLD);
53406f25ae9SGregory Neil Shapiro 			(void) sleep(10);
535c2aa98e2SPeter Wemm 			(void) close(t);
536c2aa98e2SPeter Wemm 			continue;
537c2aa98e2SPeter Wemm 		}
538c2aa98e2SPeter Wemm 
539c2aa98e2SPeter Wemm 		if (pid == 0)
540c2aa98e2SPeter Wemm 		{
541c2aa98e2SPeter Wemm 			char *p;
54206f25ae9SGregory Neil Shapiro 			FILE *inchannel, *outchannel = NULL;
543c2aa98e2SPeter Wemm 
544c2aa98e2SPeter Wemm 			/*
545c2aa98e2SPeter Wemm 			**  CHILD -- return to caller.
546c2aa98e2SPeter Wemm 			**	Collect verified idea of sending host.
547c2aa98e2SPeter Wemm 			**	Verify calling user id if possible here.
548c2aa98e2SPeter Wemm 			*/
549c2aa98e2SPeter Wemm 
55006f25ae9SGregory Neil Shapiro 			if (!control)
55106f25ae9SGregory Neil Shapiro 			{
55206f25ae9SGregory Neil Shapiro 				define(macid("{daemon_addr}", NULL),
55306f25ae9SGregory Neil Shapiro 				       newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)),
55406f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
55506f25ae9SGregory Neil Shapiro 				(void) snprintf(status, sizeof status, "%d",
55606f25ae9SGregory Neil Shapiro 						ntohs(Daemons[curdaemon].d_port));
55706f25ae9SGregory Neil Shapiro 				define(macid("{daemon_port}", NULL),
55806f25ae9SGregory Neil Shapiro 				       newstr(status), &BlankEnvelope);
55906f25ae9SGregory Neil Shapiro 			}
56006f25ae9SGregory Neil Shapiro 
561c2aa98e2SPeter Wemm 			(void) releasesignal(SIGALRM);
562c2aa98e2SPeter Wemm 			(void) releasesignal(SIGCHLD);
563c2aa98e2SPeter Wemm 			(void) setsignal(SIGCHLD, SIG_DFL);
564c2aa98e2SPeter Wemm 			(void) setsignal(SIGHUP, intsig);
56506f25ae9SGregory Neil Shapiro 			for (idx = 0; idx < ndaemons; idx++)
56606f25ae9SGregory Neil Shapiro 			{
56706f25ae9SGregory Neil Shapiro 				if (Daemons[idx].d_socket >= 0)
56806f25ae9SGregory Neil Shapiro 					(void) close(Daemons[idx].d_socket);
56906f25ae9SGregory Neil Shapiro 			}
570065a643dSPeter Wemm 			clrcontrol();
57106f25ae9SGregory Neil Shapiro 
57206f25ae9SGregory Neil Shapiro 			/* Avoid SMTP daemon actions if control command */
57306f25ae9SGregory Neil Shapiro 			if (control)
57406f25ae9SGregory Neil Shapiro 			{
57506f25ae9SGregory Neil Shapiro 				/* Add control socket process */
57606f25ae9SGregory Neil Shapiro 				proc_list_add(getpid(), "console socket child",
57706f25ae9SGregory Neil Shapiro 					PROC_CONTROL_CHILD);
57806f25ae9SGregory Neil Shapiro 			}
57906f25ae9SGregory Neil Shapiro 			else
58006f25ae9SGregory Neil Shapiro 			{
581c2aa98e2SPeter Wemm 				proc_list_clear();
582c2aa98e2SPeter Wemm 
583065a643dSPeter Wemm 				/* Add parent process as first child item */
58406f25ae9SGregory Neil Shapiro 				proc_list_add(getpid(), "daemon child",
58506f25ae9SGregory Neil Shapiro 					      PROC_DAEMON_CHILD);
586065a643dSPeter Wemm 
58706f25ae9SGregory Neil Shapiro 				/* don't schedule queue runs if ETRN */
588c2aa98e2SPeter Wemm 				QueueIntvl = 0;
589c2aa98e2SPeter Wemm 
59006f25ae9SGregory Neil Shapiro 				sm_setproctitle(TRUE, e, "startup with %s",
591c2aa98e2SPeter Wemm 						anynet_ntoa(&RealHostAddr));
59206f25ae9SGregory Neil Shapiro 			}
593c2aa98e2SPeter Wemm 
594c2aa98e2SPeter Wemm 			if (pipefd[0] != -1)
595c2aa98e2SPeter Wemm 			{
596c2aa98e2SPeter Wemm 				auto char c;
597c2aa98e2SPeter Wemm 
598c2aa98e2SPeter Wemm 				/*
599c2aa98e2SPeter Wemm 				**  Wait for the parent to close the write end
600c2aa98e2SPeter Wemm 				**  of the pipe, which we will see as an EOF.
601c2aa98e2SPeter Wemm 				**  This guarantees that we won't write to the
602c2aa98e2SPeter Wemm 				**  socket until after the parent has closed
603c2aa98e2SPeter Wemm 				**  the pipe.
604c2aa98e2SPeter Wemm 				*/
605c2aa98e2SPeter Wemm 
606c2aa98e2SPeter Wemm 				/* close the write end of the pipe */
607c2aa98e2SPeter Wemm 				(void) close(pipefd[1]);
608c2aa98e2SPeter Wemm 
609c2aa98e2SPeter Wemm 				/* we shouldn't be interrupted, but ... */
610c2aa98e2SPeter Wemm 				while (read(pipefd[0], &c, 1) < 0 &&
611c2aa98e2SPeter Wemm 				       errno == EINTR)
612c2aa98e2SPeter Wemm 					continue;
613c2aa98e2SPeter Wemm 				(void) close(pipefd[0]);
614c2aa98e2SPeter Wemm 			}
615c2aa98e2SPeter Wemm 
61606f25ae9SGregory Neil Shapiro 			/* control socket processing */
61706f25ae9SGregory Neil Shapiro 			if (control)
61806f25ae9SGregory Neil Shapiro 			{
61906f25ae9SGregory Neil Shapiro 				control_command(t, e);
62006f25ae9SGregory Neil Shapiro 
62106f25ae9SGregory Neil Shapiro 				/* NOTREACHED */
62206f25ae9SGregory Neil Shapiro 				exit(EX_SOFTWARE);
62306f25ae9SGregory Neil Shapiro 			}
62406f25ae9SGregory Neil Shapiro 
625c2aa98e2SPeter Wemm 			/* determine host name */
626c2aa98e2SPeter Wemm 			p = hostnamebyanyaddr(&RealHostAddr);
627c2aa98e2SPeter Wemm 			if (strlen(p) > (SIZE_T) MAXNAME)
628c2aa98e2SPeter Wemm 				p[MAXNAME] = '\0';
629c2aa98e2SPeter Wemm 			RealHostName = newstr(p);
63006f25ae9SGregory Neil Shapiro 			if (RealHostName[0] == '[')
63106f25ae9SGregory Neil Shapiro 			{
63206f25ae9SGregory Neil Shapiro 				/* TEMP, FAIL: which one? */
63306f25ae9SGregory Neil Shapiro 				define(macid("{client_resolve}", NULL),
63406f25ae9SGregory Neil Shapiro 				       (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL",
63506f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
63606f25ae9SGregory Neil Shapiro 			}
63706f25ae9SGregory Neil Shapiro 			else
63806f25ae9SGregory Neil Shapiro 				define(macid("{client_resolve}", NULL), "OK",
63906f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
64006f25ae9SGregory Neil Shapiro 			sm_setproctitle(TRUE, e, "startup with %s", p);
641c2aa98e2SPeter Wemm 
642c2aa98e2SPeter Wemm 			if ((inchannel = fdopen(t, "r")) == NULL ||
643c2aa98e2SPeter Wemm 			    (t = dup(t)) < 0 ||
644c2aa98e2SPeter Wemm 			    (outchannel = fdopen(t, "w")) == NULL)
645c2aa98e2SPeter Wemm 			{
646c2aa98e2SPeter Wemm 				syserr("cannot open SMTP server channel, fd=%d", t);
647065a643dSPeter Wemm 				finis(FALSE, EX_OK);
648c2aa98e2SPeter Wemm 			}
649c2aa98e2SPeter Wemm 
650c2aa98e2SPeter Wemm 			InChannel = inchannel;
651c2aa98e2SPeter Wemm 			OutChannel = outchannel;
652c2aa98e2SPeter Wemm 			DisConnected = FALSE;
653c2aa98e2SPeter Wemm 
654c2aa98e2SPeter Wemm # ifdef XLA
655c2aa98e2SPeter Wemm 			if (!xla_host_ok(RealHostName))
656c2aa98e2SPeter Wemm 			{
65706f25ae9SGregory Neil Shapiro 				message("421 4.4.5 Too many SMTP sessions for this host");
658065a643dSPeter Wemm 				finis(FALSE, EX_OK);
659c2aa98e2SPeter Wemm 			}
66006f25ae9SGregory Neil Shapiro # endif /* XLA */
66106f25ae9SGregory Neil Shapiro 			/* find out name for interface of connection */
66206f25ae9SGregory Neil Shapiro 			if (getsockname(fileno(InChannel), &sa.sa,
66306f25ae9SGregory Neil Shapiro 					&len) == 0)
66406f25ae9SGregory Neil Shapiro 			{
66506f25ae9SGregory Neil Shapiro 				p = hostnamebyanyaddr(&sa);
66606f25ae9SGregory Neil Shapiro 				if (tTd(15, 9))
66706f25ae9SGregory Neil Shapiro 					dprintf("getreq: got name %s\n", p);
66806f25ae9SGregory Neil Shapiro 				define(macid("{if_name}", NULL),
66906f25ae9SGregory Neil Shapiro 				       newstr(p), &BlankEnvelope);
67006f25ae9SGregory Neil Shapiro 
67106f25ae9SGregory Neil Shapiro 				/* do this only if it is not the loopback */
67206f25ae9SGregory Neil Shapiro 				/* interface: how to figure out? XXX */
67306f25ae9SGregory Neil Shapiro 				if (!isloopback(sa))
67406f25ae9SGregory Neil Shapiro 				{
67506f25ae9SGregory Neil Shapiro 					define(macid("{if_addr}", NULL),
67606f25ae9SGregory Neil Shapiro 					       newstr(anynet_ntoa(&sa)),
67706f25ae9SGregory Neil Shapiro 					       &BlankEnvelope);
67806f25ae9SGregory Neil Shapiro 					p = xalloc(5);
67906f25ae9SGregory Neil Shapiro 					snprintf(p, 4, "%d", sa.sa.sa_family);
68006f25ae9SGregory Neil Shapiro 					define(macid("{if_family}", NULL), p,
68106f25ae9SGregory Neil Shapiro 					       &BlankEnvelope);
68206f25ae9SGregory Neil Shapiro 					if (tTd(15, 7))
68306f25ae9SGregory Neil Shapiro 						dprintf("getreq: got addr %s and family %s\n",
68406f25ae9SGregory Neil Shapiro 							macvalue(macid("{if_addr}", NULL),
68506f25ae9SGregory Neil Shapiro 								 &BlankEnvelope),
68606f25ae9SGregory Neil Shapiro 							macvalue(macid("{if_addr}", NULL),
68706f25ae9SGregory Neil Shapiro 								 &BlankEnvelope));
68806f25ae9SGregory Neil Shapiro 				}
68906f25ae9SGregory Neil Shapiro 				else
69006f25ae9SGregory Neil Shapiro 				{
69106f25ae9SGregory Neil Shapiro 					define(macid("{if_addr}", NULL), NULL,
69206f25ae9SGregory Neil Shapiro 					       &BlankEnvelope);
69306f25ae9SGregory Neil Shapiro 					define(macid("{if_family}", NULL), NULL,
69406f25ae9SGregory Neil Shapiro 					       &BlankEnvelope);
69506f25ae9SGregory Neil Shapiro 				}
69606f25ae9SGregory Neil Shapiro 			}
69706f25ae9SGregory Neil Shapiro 			else
69806f25ae9SGregory Neil Shapiro 			{
69906f25ae9SGregory Neil Shapiro 				if (tTd(15, 7))
70006f25ae9SGregory Neil Shapiro 					dprintf("getreq: getsockname failed\n");
70106f25ae9SGregory Neil Shapiro 				define(macid("{if_name}", NULL), NULL,
70206f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
70306f25ae9SGregory Neil Shapiro 				define(macid("{if_addr}", NULL), NULL,
70406f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
70506f25ae9SGregory Neil Shapiro 				define(macid("{if_family}", NULL), NULL,
70606f25ae9SGregory Neil Shapiro 				       &BlankEnvelope);
70706f25ae9SGregory Neil Shapiro 			}
708c2aa98e2SPeter Wemm 			break;
709c2aa98e2SPeter Wemm 		}
710c2aa98e2SPeter Wemm 
711c2aa98e2SPeter Wemm 		/* parent -- keep track of children */
71206f25ae9SGregory Neil Shapiro 		if (control)
71306f25ae9SGregory Neil Shapiro 		{
71406f25ae9SGregory Neil Shapiro 			snprintf(status, sizeof status, "control socket server child");
71506f25ae9SGregory Neil Shapiro 			proc_list_add(pid, status, PROC_CONTROL);
71606f25ae9SGregory Neil Shapiro 		}
71706f25ae9SGregory Neil Shapiro 		else
71806f25ae9SGregory Neil Shapiro 		{
71906f25ae9SGregory Neil Shapiro 			snprintf(status, sizeof status,
72006f25ae9SGregory Neil Shapiro 				 "SMTP server child for %s",
721065a643dSPeter Wemm 				 anynet_ntoa(&RealHostAddr));
72206f25ae9SGregory Neil Shapiro 			proc_list_add(pid, status, PROC_DAEMON);
72306f25ae9SGregory Neil Shapiro 		}
724c2aa98e2SPeter Wemm 		(void) releasesignal(SIGCHLD);
725c2aa98e2SPeter Wemm 
726c2aa98e2SPeter Wemm 		/* close the read end of the synchronization pipe */
727c2aa98e2SPeter Wemm 		if (pipefd[0] != -1)
72806f25ae9SGregory Neil Shapiro 		{
729c2aa98e2SPeter Wemm 			(void) close(pipefd[0]);
73006f25ae9SGregory Neil Shapiro 			pipefd[0] = -1;
73106f25ae9SGregory Neil Shapiro 		}
732c2aa98e2SPeter Wemm 
733c2aa98e2SPeter Wemm 		/* close the port so that others will hang (for a while) */
734c2aa98e2SPeter Wemm 		(void) close(t);
735c2aa98e2SPeter Wemm 
736c2aa98e2SPeter Wemm 		/* release the child by closing the read end of the sync pipe */
737c2aa98e2SPeter Wemm 		if (pipefd[1] != -1)
73806f25ae9SGregory Neil Shapiro 		{
739c2aa98e2SPeter Wemm 			(void) close(pipefd[1]);
74006f25ae9SGregory Neil Shapiro 			pipefd[1] = -1;
741c2aa98e2SPeter Wemm 		}
74206f25ae9SGregory Neil Shapiro 	}
74306f25ae9SGregory Neil Shapiro 
744c2aa98e2SPeter Wemm 	if (tTd(15, 2))
74506f25ae9SGregory Neil Shapiro 		dprintf("getreq: returning\n");
74606f25ae9SGregory Neil Shapiro 	return &Daemons[curdaemon].d_flags;
747c2aa98e2SPeter Wemm }
748c2aa98e2SPeter Wemm /*
74906f25ae9SGregory Neil Shapiro **  OPENDAEMONSOCKET -- open SMTP socket
750c2aa98e2SPeter Wemm **
75106f25ae9SGregory Neil Shapiro **	Deals with setting all appropriate options.
752c2aa98e2SPeter Wemm **
753c2aa98e2SPeter Wemm **	Parameters:
75406f25ae9SGregory Neil Shapiro **		d -- the structure for the daemon to open.
755c2aa98e2SPeter Wemm **		firsttime -- set if this is the initial open.
756c2aa98e2SPeter Wemm **
757c2aa98e2SPeter Wemm **	Returns:
758c2aa98e2SPeter Wemm **		Size in bytes of the daemon socket addr.
759c2aa98e2SPeter Wemm **
760c2aa98e2SPeter Wemm **	Side Effects:
761c2aa98e2SPeter Wemm **		Leaves DaemonSocket set to the open socket.
762c2aa98e2SPeter Wemm **		Exits if the socket cannot be created.
763c2aa98e2SPeter Wemm */
764c2aa98e2SPeter Wemm 
765c2aa98e2SPeter Wemm # define MAXOPENTRIES	10	/* maximum number of tries to open connection */
766c2aa98e2SPeter Wemm 
76706f25ae9SGregory Neil Shapiro static int
76806f25ae9SGregory Neil Shapiro opendaemonsocket(d, firsttime)
76906f25ae9SGregory Neil Shapiro 	struct daemon *d;
770c2aa98e2SPeter Wemm 	bool firsttime;
771c2aa98e2SPeter Wemm {
772c2aa98e2SPeter Wemm 	int on = 1;
77306f25ae9SGregory Neil Shapiro 	int fdflags;
77406f25ae9SGregory Neil Shapiro 	SOCKADDR_LEN_T socksize = 0;
775c2aa98e2SPeter Wemm 	int ntries = 0;
77606f25ae9SGregory Neil Shapiro 	int save_errno;
777c2aa98e2SPeter Wemm 
778c2aa98e2SPeter Wemm 	if (tTd(15, 2))
77906f25ae9SGregory Neil Shapiro 		dprintf("opendaemonsocket(%s)\n", d->d_name);
780c2aa98e2SPeter Wemm 
781c2aa98e2SPeter Wemm 	do
782c2aa98e2SPeter Wemm 	{
783c2aa98e2SPeter Wemm 		if (ntries > 0)
78406f25ae9SGregory Neil Shapiro 			(void) sleep(5);
78506f25ae9SGregory Neil Shapiro 		if (firsttime || d->d_socket < 0)
786c2aa98e2SPeter Wemm 		{
78706f25ae9SGregory Neil Shapiro 			d->d_socket = socket(d->d_addr.sa.sa_family,
78806f25ae9SGregory Neil Shapiro 					     SOCK_STREAM, 0);
78906f25ae9SGregory Neil Shapiro 			if (d->d_socket < 0)
790c2aa98e2SPeter Wemm 			{
79106f25ae9SGregory Neil Shapiro 				save_errno = errno;
79206f25ae9SGregory Neil Shapiro 				syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name);
793c2aa98e2SPeter Wemm 			  severe:
794c2aa98e2SPeter Wemm 				if (LogLevel > 0)
795c2aa98e2SPeter Wemm 					sm_syslog(LOG_ALERT, NOQID,
79606f25ae9SGregory Neil Shapiro 						  "daemon %s: problem creating SMTP socket", d->d_name);
79706f25ae9SGregory Neil Shapiro 				d->d_socket = -1;
798c2aa98e2SPeter Wemm 				continue;
799c2aa98e2SPeter Wemm 			}
800c2aa98e2SPeter Wemm 
801c2aa98e2SPeter Wemm 			/* turn on network debugging? */
802c2aa98e2SPeter Wemm 			if (tTd(15, 101))
80306f25ae9SGregory Neil Shapiro 				(void) setsockopt(d->d_socket, SOL_SOCKET,
804c2aa98e2SPeter Wemm 						  SO_DEBUG, (char *)&on,
805c2aa98e2SPeter Wemm 						  sizeof on);
806c2aa98e2SPeter Wemm 
80706f25ae9SGregory Neil Shapiro 			(void) setsockopt(d->d_socket, SOL_SOCKET,
808c2aa98e2SPeter Wemm 					  SO_REUSEADDR, (char *)&on, sizeof on);
80906f25ae9SGregory Neil Shapiro 			(void) setsockopt(d->d_socket, SOL_SOCKET,
810c2aa98e2SPeter Wemm 					  SO_KEEPALIVE, (char *)&on, sizeof on);
811c2aa98e2SPeter Wemm 
812c2aa98e2SPeter Wemm # ifdef SO_RCVBUF
81306f25ae9SGregory Neil Shapiro 			if (d->d_tcprcvbufsize > 0)
814c2aa98e2SPeter Wemm 			{
81506f25ae9SGregory Neil Shapiro 				if (setsockopt(d->d_socket, SOL_SOCKET,
816c2aa98e2SPeter Wemm 					       SO_RCVBUF,
81706f25ae9SGregory Neil Shapiro 					       (char *) &d->d_tcprcvbufsize,
81806f25ae9SGregory Neil Shapiro 					       sizeof(d->d_tcprcvbufsize)) < 0)
81906f25ae9SGregory Neil Shapiro 					syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name);
820c2aa98e2SPeter Wemm 			}
82106f25ae9SGregory Neil Shapiro # endif /* SO_RCVBUF */
82206f25ae9SGregory Neil Shapiro # ifdef SO_SNDBUF
82306f25ae9SGregory Neil Shapiro 			if (d->d_tcpsndbufsize > 0)
82406f25ae9SGregory Neil Shapiro 			{
82506f25ae9SGregory Neil Shapiro 				if (setsockopt(d->d_socket, SOL_SOCKET,
82606f25ae9SGregory Neil Shapiro 					       SO_SNDBUF,
82706f25ae9SGregory Neil Shapiro 					       (char *) &d->d_tcpsndbufsize,
82806f25ae9SGregory Neil Shapiro 					       sizeof(d->d_tcpsndbufsize)) < 0)
82906f25ae9SGregory Neil Shapiro 					syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name);
83006f25ae9SGregory Neil Shapiro 			}
83106f25ae9SGregory Neil Shapiro # endif /* SO_SNDBUF */
832c2aa98e2SPeter Wemm 
83306f25ae9SGregory Neil Shapiro 			if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 ||
83406f25ae9SGregory Neil Shapiro 			    fcntl(d->d_socket, F_SETFD,
83506f25ae9SGregory Neil Shapiro 				  fdflags | FD_CLOEXEC) == -1)
83606f25ae9SGregory Neil Shapiro 			{
83706f25ae9SGregory Neil Shapiro 				save_errno = errno;
83806f25ae9SGregory Neil Shapiro 				syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s",
83906f25ae9SGregory Neil Shapiro 				       d->d_name,
84006f25ae9SGregory Neil Shapiro 				       fdflags == -1 ? "get" : "set",
84106f25ae9SGregory Neil Shapiro 				       errstring(save_errno));
84206f25ae9SGregory Neil Shapiro 				(void) close(d->d_socket);
84306f25ae9SGregory Neil Shapiro 				goto severe;
84406f25ae9SGregory Neil Shapiro 			}
84506f25ae9SGregory Neil Shapiro 
84606f25ae9SGregory Neil Shapiro 			switch (d->d_addr.sa.sa_family)
847c2aa98e2SPeter Wemm 			{
848c2aa98e2SPeter Wemm # if NETINET
849c2aa98e2SPeter Wemm 			  case AF_INET:
85006f25ae9SGregory Neil Shapiro 				socksize = sizeof d->d_addr.sin;
851c2aa98e2SPeter Wemm 				break;
85206f25ae9SGregory Neil Shapiro # endif /* NETINET */
85306f25ae9SGregory Neil Shapiro 
85406f25ae9SGregory Neil Shapiro # if NETINET6
85506f25ae9SGregory Neil Shapiro 			  case AF_INET6:
85606f25ae9SGregory Neil Shapiro 				socksize = sizeof d->d_addr.sin6;
85706f25ae9SGregory Neil Shapiro 				break;
85806f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
859c2aa98e2SPeter Wemm 
860c2aa98e2SPeter Wemm # if NETISO
861c2aa98e2SPeter Wemm 			  case AF_ISO:
86206f25ae9SGregory Neil Shapiro 				socksize = sizeof d->d_addr.siso;
863c2aa98e2SPeter Wemm 				break;
86406f25ae9SGregory Neil Shapiro # endif /* NETISO */
865c2aa98e2SPeter Wemm 
866c2aa98e2SPeter Wemm 			  default:
86706f25ae9SGregory Neil Shapiro 				socksize = sizeof d->d_addr;
868c2aa98e2SPeter Wemm 				break;
869c2aa98e2SPeter Wemm 			}
870c2aa98e2SPeter Wemm 
87106f25ae9SGregory Neil Shapiro 			if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0)
872c2aa98e2SPeter Wemm 			{
873c2aa98e2SPeter Wemm 				/* probably another daemon already */
87406f25ae9SGregory Neil Shapiro 				save_errno = errno;
87506f25ae9SGregory Neil Shapiro 				syserr("opendaemonsocket: daemon %s: cannot bind",
87606f25ae9SGregory Neil Shapiro 				       d->d_name);
87706f25ae9SGregory Neil Shapiro 				(void) close(d->d_socket);
878c2aa98e2SPeter Wemm 				goto severe;
879c2aa98e2SPeter Wemm 			}
880c2aa98e2SPeter Wemm 		}
88106f25ae9SGregory Neil Shapiro 		if (!firsttime &&
88206f25ae9SGregory Neil Shapiro 		    listen(d->d_socket, d->d_listenqueue) < 0)
883c2aa98e2SPeter Wemm 		{
88406f25ae9SGregory Neil Shapiro 			save_errno = errno;
88506f25ae9SGregory Neil Shapiro 			syserr("opendaemonsocket: daemon %s: cannot listen",
88606f25ae9SGregory Neil Shapiro 			       d->d_name);
88706f25ae9SGregory Neil Shapiro 			(void) close(d->d_socket);
888c2aa98e2SPeter Wemm 			goto severe;
889c2aa98e2SPeter Wemm 		}
890c2aa98e2SPeter Wemm 		return socksize;
89106f25ae9SGregory Neil Shapiro 	} while (ntries++ < MAXOPENTRIES && transienterror(save_errno));
89206f25ae9SGregory Neil Shapiro 	syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting",
89306f25ae9SGregory Neil Shapiro 	       d->d_name);
894065a643dSPeter Wemm 	/* NOTREACHED */
895c2aa98e2SPeter Wemm 	return -1;  /* avoid compiler warning on IRIX */
896c2aa98e2SPeter Wemm }
897c2aa98e2SPeter Wemm /*
89806f25ae9SGregory Neil Shapiro **  SETUPDAEMON -- setup socket for daemon
89906f25ae9SGregory Neil Shapiro **
90006f25ae9SGregory Neil Shapiro **	Parameters:
90106f25ae9SGregory Neil Shapiro **		daemonaddr -- socket for daemon
90206f25ae9SGregory Neil Shapiro **		daemon -- number of daemon
90306f25ae9SGregory Neil Shapiro **
90406f25ae9SGregory Neil Shapiro **	Returns:
90506f25ae9SGregory Neil Shapiro **		port number on which daemon should run
90606f25ae9SGregory Neil Shapiro **
90706f25ae9SGregory Neil Shapiro */
90806f25ae9SGregory Neil Shapiro static u_short
90906f25ae9SGregory Neil Shapiro setupdaemon(daemonaddr)
91006f25ae9SGregory Neil Shapiro 	SOCKADDR *daemonaddr;
91106f25ae9SGregory Neil Shapiro {
91206f25ae9SGregory Neil Shapiro 	u_short port;
91306f25ae9SGregory Neil Shapiro 
91406f25ae9SGregory Neil Shapiro 	/*
91506f25ae9SGregory Neil Shapiro 	**  Set up the address for the mailer.
91606f25ae9SGregory Neil Shapiro 	*/
91706f25ae9SGregory Neil Shapiro 
91806f25ae9SGregory Neil Shapiro 	if (daemonaddr->sa.sa_family == AF_UNSPEC)
91906f25ae9SGregory Neil Shapiro 	{
92006f25ae9SGregory Neil Shapiro 		memset(daemonaddr, '\0', sizeof *daemonaddr);
92106f25ae9SGregory Neil Shapiro # if NETINET
92206f25ae9SGregory Neil Shapiro 		daemonaddr->sa.sa_family = AF_INET;
92306f25ae9SGregory Neil Shapiro # endif /* NETINET */
92406f25ae9SGregory Neil Shapiro 	}
92506f25ae9SGregory Neil Shapiro 
92606f25ae9SGregory Neil Shapiro 	switch (daemonaddr->sa.sa_family)
92706f25ae9SGregory Neil Shapiro 	{
92806f25ae9SGregory Neil Shapiro # if NETINET
92906f25ae9SGregory Neil Shapiro 	  case AF_INET:
93006f25ae9SGregory Neil Shapiro 		if (daemonaddr->sin.sin_addr.s_addr == 0)
93106f25ae9SGregory Neil Shapiro 			daemonaddr->sin.sin_addr.s_addr = INADDR_ANY;
93206f25ae9SGregory Neil Shapiro 		port = daemonaddr->sin.sin_port;
93306f25ae9SGregory Neil Shapiro 		break;
93406f25ae9SGregory Neil Shapiro # endif /* NETINET */
93506f25ae9SGregory Neil Shapiro 
93606f25ae9SGregory Neil Shapiro # if NETINET6
93706f25ae9SGregory Neil Shapiro 	  case AF_INET6:
93806f25ae9SGregory Neil Shapiro 		if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr))
93906f25ae9SGregory Neil Shapiro 			daemonaddr->sin6.sin6_addr = in6addr_any;
94006f25ae9SGregory Neil Shapiro 		port = daemonaddr->sin6.sin6_port;
94106f25ae9SGregory Neil Shapiro 		break;
94206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
94306f25ae9SGregory Neil Shapiro 
94406f25ae9SGregory Neil Shapiro 	  default:
94506f25ae9SGregory Neil Shapiro 		/* unknown protocol */
94606f25ae9SGregory Neil Shapiro 		port = 0;
94706f25ae9SGregory Neil Shapiro 		break;
94806f25ae9SGregory Neil Shapiro 	}
94906f25ae9SGregory Neil Shapiro 	if (port == 0)
95006f25ae9SGregory Neil Shapiro 	{
95106f25ae9SGregory Neil Shapiro # ifdef NO_GETSERVBYNAME
95206f25ae9SGregory Neil Shapiro 		port = htons(25);
95306f25ae9SGregory Neil Shapiro # else /* NO_GETSERVBYNAME */
95406f25ae9SGregory Neil Shapiro 		{
95506f25ae9SGregory Neil Shapiro 			register struct servent *sp;
95606f25ae9SGregory Neil Shapiro 
95706f25ae9SGregory Neil Shapiro 			sp = getservbyname("smtp", "tcp");
95806f25ae9SGregory Neil Shapiro 			if (sp == NULL)
95906f25ae9SGregory Neil Shapiro 			{
96006f25ae9SGregory Neil Shapiro 				syserr("554 5.3.5 service \"smtp\" unknown");
96106f25ae9SGregory Neil Shapiro 				port = htons(25);
96206f25ae9SGregory Neil Shapiro 			}
96306f25ae9SGregory Neil Shapiro 			else
96406f25ae9SGregory Neil Shapiro 				port = sp->s_port;
96506f25ae9SGregory Neil Shapiro 		}
96606f25ae9SGregory Neil Shapiro # endif /* NO_GETSERVBYNAME */
96706f25ae9SGregory Neil Shapiro 	}
96806f25ae9SGregory Neil Shapiro 
96906f25ae9SGregory Neil Shapiro 	switch (daemonaddr->sa.sa_family)
97006f25ae9SGregory Neil Shapiro 	{
97106f25ae9SGregory Neil Shapiro # if NETINET
97206f25ae9SGregory Neil Shapiro 	  case AF_INET:
97306f25ae9SGregory Neil Shapiro 		daemonaddr->sin.sin_port = port;
97406f25ae9SGregory Neil Shapiro 		break;
97506f25ae9SGregory Neil Shapiro # endif /* NETINET */
97606f25ae9SGregory Neil Shapiro 
97706f25ae9SGregory Neil Shapiro # if NETINET6
97806f25ae9SGregory Neil Shapiro 	  case AF_INET6:
97906f25ae9SGregory Neil Shapiro 		daemonaddr->sin6.sin6_port = port;
98006f25ae9SGregory Neil Shapiro 		break;
98106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
98206f25ae9SGregory Neil Shapiro 
98306f25ae9SGregory Neil Shapiro 	  default:
98406f25ae9SGregory Neil Shapiro 		/* unknown protocol */
98506f25ae9SGregory Neil Shapiro 		break;
98606f25ae9SGregory Neil Shapiro 	}
98706f25ae9SGregory Neil Shapiro 	return(port);
98806f25ae9SGregory Neil Shapiro }
98906f25ae9SGregory Neil Shapiro /*
990c2aa98e2SPeter Wemm **  CLRDAEMON -- reset the daemon connection
991c2aa98e2SPeter Wemm **
992c2aa98e2SPeter Wemm **	Parameters:
993c2aa98e2SPeter Wemm **		none.
994c2aa98e2SPeter Wemm **
995c2aa98e2SPeter Wemm **	Returns:
996c2aa98e2SPeter Wemm **		none.
997c2aa98e2SPeter Wemm **
998c2aa98e2SPeter Wemm **	Side Effects:
999c2aa98e2SPeter Wemm **		releases any resources used by the passive daemon.
1000c2aa98e2SPeter Wemm */
1001c2aa98e2SPeter Wemm 
1002c2aa98e2SPeter Wemm void
1003c2aa98e2SPeter Wemm clrdaemon()
1004c2aa98e2SPeter Wemm {
100506f25ae9SGregory Neil Shapiro 	int i;
100606f25ae9SGregory Neil Shapiro 
100706f25ae9SGregory Neil Shapiro 	for (i = 0; i < ndaemons; i++)
100806f25ae9SGregory Neil Shapiro 	{
100906f25ae9SGregory Neil Shapiro 		if (Daemons[i].d_socket >= 0)
101006f25ae9SGregory Neil Shapiro 			(void) close(Daemons[i].d_socket);
101106f25ae9SGregory Neil Shapiro 		Daemons[i].d_socket = -1;
101206f25ae9SGregory Neil Shapiro 	}
1013c2aa98e2SPeter Wemm }
1014c2aa98e2SPeter Wemm /*
101506f25ae9SGregory Neil Shapiro **  SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client)
1016c2aa98e2SPeter Wemm **
1017c2aa98e2SPeter Wemm **	Parameters:
1018c2aa98e2SPeter Wemm **		p -- the options line.
101906f25ae9SGregory Neil Shapiro **		d -- the daemon structure to fill in.
1020c2aa98e2SPeter Wemm **
1021c2aa98e2SPeter Wemm **	Returns:
1022c2aa98e2SPeter Wemm **		none.
1023c2aa98e2SPeter Wemm */
1024c2aa98e2SPeter Wemm 
102506f25ae9SGregory Neil Shapiro static void
102606f25ae9SGregory Neil Shapiro setsockaddroptions(p, d)
1027c2aa98e2SPeter Wemm 	register char *p;
102806f25ae9SGregory Neil Shapiro 	struct daemon *d;
1029c2aa98e2SPeter Wemm {
103006f25ae9SGregory Neil Shapiro # if NETISO
103106f25ae9SGregory Neil Shapiro 	short port;
103206f25ae9SGregory Neil Shapiro # endif /* NETISO */
103306f25ae9SGregory Neil Shapiro 	int l;
103406f25ae9SGregory Neil Shapiro 	char *h, *flags;
103506f25ae9SGregory Neil Shapiro 
103606f25ae9SGregory Neil Shapiro # if NETINET
103706f25ae9SGregory Neil Shapiro 	if (d->d_addr.sa.sa_family == AF_UNSPEC)
103806f25ae9SGregory Neil Shapiro 		d->d_addr.sa.sa_family = AF_INET;
103906f25ae9SGregory Neil Shapiro # endif /* NETINET */
1040c2aa98e2SPeter Wemm 
1041c2aa98e2SPeter Wemm 	while (p != NULL)
1042c2aa98e2SPeter Wemm 	{
1043c2aa98e2SPeter Wemm 		register char *f;
1044c2aa98e2SPeter Wemm 		register char *v;
1045c2aa98e2SPeter Wemm 
1046c2aa98e2SPeter Wemm 		while (isascii(*p) && isspace(*p))
1047c2aa98e2SPeter Wemm 			p++;
1048c2aa98e2SPeter Wemm 		if (*p == '\0')
1049c2aa98e2SPeter Wemm 			break;
1050c2aa98e2SPeter Wemm 		f = p;
1051c2aa98e2SPeter Wemm 		p = strchr(p, ',');
1052c2aa98e2SPeter Wemm 		if (p != NULL)
1053c2aa98e2SPeter Wemm 			*p++ = '\0';
1054c2aa98e2SPeter Wemm 		v = strchr(f, '=');
1055c2aa98e2SPeter Wemm 		if (v == NULL)
1056c2aa98e2SPeter Wemm 			continue;
1057c2aa98e2SPeter Wemm 		while (isascii(*++v) && isspace(*v))
1058c2aa98e2SPeter Wemm 			continue;
1059c2aa98e2SPeter Wemm 		if (isascii(*f) && islower(*f))
1060c2aa98e2SPeter Wemm 			*f = toupper(*f);
1061c2aa98e2SPeter Wemm 
1062c2aa98e2SPeter Wemm 		switch (*f)
1063c2aa98e2SPeter Wemm 		{
1064c2aa98e2SPeter Wemm 		  case 'F':		/* address family */
1065c2aa98e2SPeter Wemm 			if (isascii(*v) && isdigit(*v))
106606f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = atoi(v);
1067c2aa98e2SPeter Wemm # if NETINET
1068c2aa98e2SPeter Wemm 			else if (strcasecmp(v, "inet") == 0)
106906f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = AF_INET;
107006f25ae9SGregory Neil Shapiro # endif /* NETINET */
107106f25ae9SGregory Neil Shapiro # if NETINET6
107206f25ae9SGregory Neil Shapiro 			else if (strcasecmp(v, "inet6") == 0)
107306f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = AF_INET6;
107406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1075c2aa98e2SPeter Wemm # if NETISO
1076c2aa98e2SPeter Wemm 			else if (strcasecmp(v, "iso") == 0)
107706f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = AF_ISO;
107806f25ae9SGregory Neil Shapiro # endif /* NETISO */
1079c2aa98e2SPeter Wemm # if NETNS
1080c2aa98e2SPeter Wemm 			else if (strcasecmp(v, "ns") == 0)
108106f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = AF_NS;
108206f25ae9SGregory Neil Shapiro # endif /* NETNS */
1083c2aa98e2SPeter Wemm # if NETX25
1084c2aa98e2SPeter Wemm 			else if (strcasecmp(v, "x.25") == 0)
108506f25ae9SGregory Neil Shapiro 				d->d_addr.sa.sa_family = AF_CCITT;
108606f25ae9SGregory Neil Shapiro # endif /* NETX25 */
1087c2aa98e2SPeter Wemm 			else
108806f25ae9SGregory Neil Shapiro 				syserr("554 5.3.5 Unknown address family %s in Family=option",
108906f25ae9SGregory Neil Shapiro 				       v);
1090c2aa98e2SPeter Wemm 			break;
1091c2aa98e2SPeter Wemm 
1092c2aa98e2SPeter Wemm 		  case 'A':		/* address */
109306f25ae9SGregory Neil Shapiro 			switch (d->d_addr.sa.sa_family)
1094c2aa98e2SPeter Wemm 			{
1095c2aa98e2SPeter Wemm # if NETINET
1096c2aa98e2SPeter Wemm 			  case AF_INET:
109706f25ae9SGregory Neil Shapiro 				if (!isascii(*v) || !isdigit(*v) ||
109806f25ae9SGregory Neil Shapiro 				    ((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE))
1099c2aa98e2SPeter Wemm 				{
1100c2aa98e2SPeter Wemm 					register struct hostent *hp;
1101c2aa98e2SPeter Wemm 
110206f25ae9SGregory Neil Shapiro 					hp = sm_gethostbyname(v, AF_INET);
1103c2aa98e2SPeter Wemm 					if (hp == NULL)
110406f25ae9SGregory Neil Shapiro 						syserr("554 5.3.0 host \"%s\" unknown",
110506f25ae9SGregory Neil Shapiro 						       v);
1106c2aa98e2SPeter Wemm 					else
110706f25ae9SGregory Neil Shapiro 					{
110806f25ae9SGregory Neil Shapiro 						while (*(hp->h_addr_list) &&
110906f25ae9SGregory Neil Shapiro 						       hp->h_addrtype != AF_INET)
111006f25ae9SGregory Neil Shapiro 							hp->h_addr_list++;
111106f25ae9SGregory Neil Shapiro 						if (*(hp->h_addr_list) == NULL)
111206f25ae9SGregory Neil Shapiro 							syserr("554 5.3.0 host \"%s\" unknown",
111306f25ae9SGregory Neil Shapiro 							       v);
111406f25ae9SGregory Neil Shapiro 						else
111506f25ae9SGregory Neil Shapiro 							memmove(&d->d_addr.sin.sin_addr,
111606f25ae9SGregory Neil Shapiro 								*(hp->h_addr_list),
111706f25ae9SGregory Neil Shapiro 								INADDRSZ);
111806f25ae9SGregory Neil Shapiro 					}
1119c2aa98e2SPeter Wemm 				}
1120c2aa98e2SPeter Wemm 				break;
112106f25ae9SGregory Neil Shapiro # endif /* NETINET */
112206f25ae9SGregory Neil Shapiro 
112306f25ae9SGregory Neil Shapiro # if NETINET6
112406f25ae9SGregory Neil Shapiro 			  case AF_INET6:
112506f25ae9SGregory Neil Shapiro 				if (!isascii(*v) || !isxdigit(*v) ||
112606f25ae9SGregory Neil Shapiro 				    inet_pton(AF_INET6, v,
112706f25ae9SGregory Neil Shapiro 					      &d->d_addr.sin6.sin6_addr) != 1)
112806f25ae9SGregory Neil Shapiro 				{
112906f25ae9SGregory Neil Shapiro 					register struct hostent *hp;
113006f25ae9SGregory Neil Shapiro 
113106f25ae9SGregory Neil Shapiro 					hp = sm_gethostbyname(v, AF_INET6);
113206f25ae9SGregory Neil Shapiro 					if (hp == NULL)
113306f25ae9SGregory Neil Shapiro 						syserr("554 5.3.0 host \"%s\" unknown",
113406f25ae9SGregory Neil Shapiro 						       v);
113506f25ae9SGregory Neil Shapiro 					else
113606f25ae9SGregory Neil Shapiro 					{
113706f25ae9SGregory Neil Shapiro 						while (*(hp->h_addr_list) &&
113806f25ae9SGregory Neil Shapiro 						       hp->h_addrtype != AF_INET6)
113906f25ae9SGregory Neil Shapiro 							hp->h_addr_list++;
114006f25ae9SGregory Neil Shapiro 						if (*(hp->h_addr_list) == NULL)
114106f25ae9SGregory Neil Shapiro 							syserr("554 5.3.0 host \"%s\" unknown",
114206f25ae9SGregory Neil Shapiro 							       v);
114306f25ae9SGregory Neil Shapiro 						else
114406f25ae9SGregory Neil Shapiro 							memmove(&d->d_addr.sin6.sin6_addr,
114506f25ae9SGregory Neil Shapiro 								*(hp->h_addr_list),
114606f25ae9SGregory Neil Shapiro 								IN6ADDRSZ);
114706f25ae9SGregory Neil Shapiro 					}
114806f25ae9SGregory Neil Shapiro 				}
114906f25ae9SGregory Neil Shapiro 				break;
115006f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1151c2aa98e2SPeter Wemm 
1152c2aa98e2SPeter Wemm 			  default:
115306f25ae9SGregory Neil Shapiro 				syserr("554 5.3.5 address= option unsupported for family %d",
115406f25ae9SGregory Neil Shapiro 				       d->d_addr.sa.sa_family);
1155c2aa98e2SPeter Wemm 				break;
1156c2aa98e2SPeter Wemm 			}
1157c2aa98e2SPeter Wemm 			break;
1158c2aa98e2SPeter Wemm 
1159c2aa98e2SPeter Wemm 		  case 'P':		/* port */
116006f25ae9SGregory Neil Shapiro 			switch (d->d_addr.sa.sa_family)
1161c2aa98e2SPeter Wemm 			{
1162c2aa98e2SPeter Wemm # if NETINET
1163c2aa98e2SPeter Wemm 			  case AF_INET:
1164c2aa98e2SPeter Wemm 				if (isascii(*v) && isdigit(*v))
116506f25ae9SGregory Neil Shapiro 					d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)v));
1166c2aa98e2SPeter Wemm 				else
1167c2aa98e2SPeter Wemm 				{
116806f25ae9SGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
116906f25ae9SGregory Neil Shapiro 					syserr("554 5.3.5 invalid port number: %s",
117006f25ae9SGregory Neil Shapiro 					       v);
117106f25ae9SGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
1172c2aa98e2SPeter Wemm 					register struct servent *sp;
1173c2aa98e2SPeter Wemm 
1174c2aa98e2SPeter Wemm 					sp = getservbyname(v, "tcp");
1175c2aa98e2SPeter Wemm 					if (sp == NULL)
117606f25ae9SGregory Neil Shapiro 						syserr("554 5.3.5 service \"%s\" unknown",
117706f25ae9SGregory Neil Shapiro 						       v);
1178c2aa98e2SPeter Wemm 					else
117906f25ae9SGregory Neil Shapiro 						d->d_addr.sin.sin_port = sp->s_port;
118006f25ae9SGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
1181c2aa98e2SPeter Wemm 				}
1182c2aa98e2SPeter Wemm 				break;
118306f25ae9SGregory Neil Shapiro # endif /* NETINET */
118406f25ae9SGregory Neil Shapiro 
118506f25ae9SGregory Neil Shapiro # if NETINET6
118606f25ae9SGregory Neil Shapiro 			  case AF_INET6:
118706f25ae9SGregory Neil Shapiro 				if (isascii(*v) && isdigit(*v))
118806f25ae9SGregory Neil Shapiro 					d->d_addr.sin6.sin6_port = htons((u_short)atoi(v));
118906f25ae9SGregory Neil Shapiro 				else
119006f25ae9SGregory Neil Shapiro 				{
119106f25ae9SGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
119206f25ae9SGregory Neil Shapiro 					syserr("554 5.3.5 invalid port number: %s",
119306f25ae9SGregory Neil Shapiro 					       v);
119406f25ae9SGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
119506f25ae9SGregory Neil Shapiro 					register struct servent *sp;
119606f25ae9SGregory Neil Shapiro 
119706f25ae9SGregory Neil Shapiro 					sp = getservbyname(v, "tcp");
119806f25ae9SGregory Neil Shapiro 					if (sp == NULL)
119906f25ae9SGregory Neil Shapiro 						syserr("554 5.3.5 service \"%s\" unknown",
120006f25ae9SGregory Neil Shapiro 						       v);
120106f25ae9SGregory Neil Shapiro 					else
120206f25ae9SGregory Neil Shapiro 						d->d_addr.sin6.sin6_port = sp->s_port;
120306f25ae9SGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
120406f25ae9SGregory Neil Shapiro 				}
120506f25ae9SGregory Neil Shapiro 				break;
120606f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1207c2aa98e2SPeter Wemm 
1208c2aa98e2SPeter Wemm # if NETISO
1209c2aa98e2SPeter Wemm 			  case AF_ISO:
1210c2aa98e2SPeter Wemm 				/* assume two byte transport selector */
1211c2aa98e2SPeter Wemm 				if (isascii(*v) && isdigit(*v))
121206f25ae9SGregory Neil Shapiro 					port = htons((u_short)atoi(v));
1213c2aa98e2SPeter Wemm 				else
1214c2aa98e2SPeter Wemm 				{
121506f25ae9SGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
121606f25ae9SGregory Neil Shapiro 					syserr("554 5.3.5 invalid port number: %s",
121706f25ae9SGregory Neil Shapiro 					       v);
121806f25ae9SGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
1219c2aa98e2SPeter Wemm 					register struct servent *sp;
1220c2aa98e2SPeter Wemm 
1221c2aa98e2SPeter Wemm 					sp = getservbyname(v, "tcp");
1222c2aa98e2SPeter Wemm 					if (sp == NULL)
122306f25ae9SGregory Neil Shapiro 						syserr("554 5.3.5 service \"%s\" unknown",
122406f25ae9SGregory Neil Shapiro 						       v);
1225c2aa98e2SPeter Wemm 					else
1226c2aa98e2SPeter Wemm 						port = sp->s_port;
122706f25ae9SGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
1228c2aa98e2SPeter Wemm 				}
122906f25ae9SGregory Neil Shapiro 				memmove(TSEL(&d->d_addr.siso),
123006f25ae9SGregory Neil Shapiro 					(char *) &port, 2);
1231c2aa98e2SPeter Wemm 				break;
123206f25ae9SGregory Neil Shapiro # endif /* NETISO */
1233c2aa98e2SPeter Wemm 
1234c2aa98e2SPeter Wemm 			  default:
123506f25ae9SGregory Neil Shapiro 				syserr("554 5.3.5 Port= option unsupported for family %d",
123606f25ae9SGregory Neil Shapiro 				       d->d_addr.sa.sa_family);
1237c2aa98e2SPeter Wemm 				break;
1238c2aa98e2SPeter Wemm 			}
1239c2aa98e2SPeter Wemm 			break;
1240c2aa98e2SPeter Wemm 
1241c2aa98e2SPeter Wemm 		  case 'L':		/* listen queue size */
124206f25ae9SGregory Neil Shapiro 			d->d_listenqueue = atoi(v);
124306f25ae9SGregory Neil Shapiro 			break;
124406f25ae9SGregory Neil Shapiro 
124506f25ae9SGregory Neil Shapiro 		  case 'M':		/* modifiers (flags) */
124606f25ae9SGregory Neil Shapiro 			l = 3 * strlen(v) + 3;
124706f25ae9SGregory Neil Shapiro 			h = v;
124806f25ae9SGregory Neil Shapiro 			flags = xalloc(l);
124906f25ae9SGregory Neil Shapiro 			d->d_mflags = flags;
125006f25ae9SGregory Neil Shapiro 			for (; *h != '\0'; h++)
125106f25ae9SGregory Neil Shapiro 			{
125206f25ae9SGregory Neil Shapiro 				if (!(isascii(*h) && isspace(*h)))
125306f25ae9SGregory Neil Shapiro 				{
125406f25ae9SGregory Neil Shapiro 					if (flags != d->d_mflags)
125506f25ae9SGregory Neil Shapiro 						*f++ = ' ';
125606f25ae9SGregory Neil Shapiro 					*flags++ = *h;
125706f25ae9SGregory Neil Shapiro 					if (isupper(*h))
125806f25ae9SGregory Neil Shapiro 						*flags++ = *h;
125906f25ae9SGregory Neil Shapiro 				}
126006f25ae9SGregory Neil Shapiro 			}
126106f25ae9SGregory Neil Shapiro 			*flags++ = '\0';
126206f25ae9SGregory Neil Shapiro 			for (; *v != '\0'; v++)
126306f25ae9SGregory Neil Shapiro 				if (!(isascii(*v) && isspace(*v)))
126406f25ae9SGregory Neil Shapiro 					setbitn(*v, d->d_flags);
1265c2aa98e2SPeter Wemm 			break;
1266c2aa98e2SPeter Wemm 
1267c2aa98e2SPeter Wemm 		  case 'S':		/* send buffer size */
126806f25ae9SGregory Neil Shapiro 			d->d_tcpsndbufsize = atoi(v);
1269c2aa98e2SPeter Wemm 			break;
1270c2aa98e2SPeter Wemm 
1271c2aa98e2SPeter Wemm 		  case 'R':		/* receive buffer size */
127206f25ae9SGregory Neil Shapiro 			d->d_tcprcvbufsize = atoi(v);
127306f25ae9SGregory Neil Shapiro 			break;
127406f25ae9SGregory Neil Shapiro 
127506f25ae9SGregory Neil Shapiro 		  case 'N':		/* name */
127606f25ae9SGregory Neil Shapiro 			d->d_name = v;
1277c2aa98e2SPeter Wemm 			break;
1278c2aa98e2SPeter Wemm 
1279c2aa98e2SPeter Wemm 		  default:
128006f25ae9SGregory Neil Shapiro 			syserr("554 5.3.5 PortOptions parameter \"%s\" unknown",
128106f25ae9SGregory Neil Shapiro 			       f);
1282c2aa98e2SPeter Wemm 		}
1283c2aa98e2SPeter Wemm 	}
1284c2aa98e2SPeter Wemm }
1285c2aa98e2SPeter Wemm /*
128606f25ae9SGregory Neil Shapiro **  SETDAEMONOPTIONS -- set options for running the MTA daemon
128706f25ae9SGregory Neil Shapiro **
128806f25ae9SGregory Neil Shapiro **	Parameters:
128906f25ae9SGregory Neil Shapiro **		p -- the options line.
129006f25ae9SGregory Neil Shapiro **
129106f25ae9SGregory Neil Shapiro **	Returns:
129206f25ae9SGregory Neil Shapiro **		TRUE if successful, FALSE otherwise.
129306f25ae9SGregory Neil Shapiro */
129406f25ae9SGregory Neil Shapiro 
129506f25ae9SGregory Neil Shapiro bool
129606f25ae9SGregory Neil Shapiro setdaemonoptions(p)
129706f25ae9SGregory Neil Shapiro 	register char *p;
129806f25ae9SGregory Neil Shapiro {
129906f25ae9SGregory Neil Shapiro 	if (ndaemons >= MAXDAEMONS)
130006f25ae9SGregory Neil Shapiro 		return FALSE;
130106f25ae9SGregory Neil Shapiro 	Daemons[ndaemons].d_socket = -1;
130206f25ae9SGregory Neil Shapiro 	Daemons[ndaemons].d_listenqueue = 10;
130306f25ae9SGregory Neil Shapiro 	clrbitmap(Daemons[ndaemons].d_flags);
130406f25ae9SGregory Neil Shapiro 	setsockaddroptions(p, &Daemons[ndaemons]);
130506f25ae9SGregory Neil Shapiro 
130606f25ae9SGregory Neil Shapiro 	if (Daemons[ndaemons].d_name != NULL)
130706f25ae9SGregory Neil Shapiro 		Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name);
130806f25ae9SGregory Neil Shapiro 	else
130906f25ae9SGregory Neil Shapiro 	{
131006f25ae9SGregory Neil Shapiro 		char num[30];
131106f25ae9SGregory Neil Shapiro 
131206f25ae9SGregory Neil Shapiro 		snprintf(num, sizeof num, "Daemon%d", ndaemons);
131306f25ae9SGregory Neil Shapiro 		Daemons[ndaemons].d_name = newstr(num);
131406f25ae9SGregory Neil Shapiro 	}
131506f25ae9SGregory Neil Shapiro 
131606f25ae9SGregory Neil Shapiro 	if (tTd(37, 1))
131706f25ae9SGregory Neil Shapiro 	{
131806f25ae9SGregory Neil Shapiro 		dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name);
131906f25ae9SGregory Neil Shapiro 		if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags))
132006f25ae9SGregory Neil Shapiro 			dprintf("ETRNONLY ");
132106f25ae9SGregory Neil Shapiro 		if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags))
132206f25ae9SGregory Neil Shapiro 			dprintf("NOETRN ");
132306f25ae9SGregory Neil Shapiro 		dprintf("\n");
132406f25ae9SGregory Neil Shapiro 	}
132506f25ae9SGregory Neil Shapiro 	++ndaemons;
132606f25ae9SGregory Neil Shapiro 	return TRUE;
132706f25ae9SGregory Neil Shapiro }
132806f25ae9SGregory Neil Shapiro /*
132906f25ae9SGregory Neil Shapiro **  INITDAEMON -- initialize daemon if not yet done.
133006f25ae9SGregory Neil Shapiro **
133106f25ae9SGregory Neil Shapiro **	Parameters:
133206f25ae9SGregory Neil Shapiro **		none
133306f25ae9SGregory Neil Shapiro **
133406f25ae9SGregory Neil Shapiro **	Returns:
133506f25ae9SGregory Neil Shapiro **		none
133606f25ae9SGregory Neil Shapiro **
133706f25ae9SGregory Neil Shapiro **	Side Effects:
133806f25ae9SGregory Neil Shapiro **		initializes structure for one daemon.
133906f25ae9SGregory Neil Shapiro */
134006f25ae9SGregory Neil Shapiro void
134106f25ae9SGregory Neil Shapiro initdaemon()
134206f25ae9SGregory Neil Shapiro {
134306f25ae9SGregory Neil Shapiro 	if (ndaemons == 0)
134406f25ae9SGregory Neil Shapiro 	{
134506f25ae9SGregory Neil Shapiro 		Daemons[ndaemons].d_socket = -1;
134606f25ae9SGregory Neil Shapiro 		Daemons[ndaemons].d_listenqueue = 10;
134706f25ae9SGregory Neil Shapiro 		Daemons[ndaemons].d_name = "Daemon0";
134806f25ae9SGregory Neil Shapiro 		ndaemons = 1;
134906f25ae9SGregory Neil Shapiro 	}
135006f25ae9SGregory Neil Shapiro }
135106f25ae9SGregory Neil Shapiro /*
135206f25ae9SGregory Neil Shapiro **  SETCLIENTOPTIONS -- set options for running the client
135306f25ae9SGregory Neil Shapiro **
135406f25ae9SGregory Neil Shapiro **	Parameters:
135506f25ae9SGregory Neil Shapiro **		p -- the options line.
135606f25ae9SGregory Neil Shapiro **
135706f25ae9SGregory Neil Shapiro **	Returns:
135806f25ae9SGregory Neil Shapiro **		none.
135906f25ae9SGregory Neil Shapiro */
136006f25ae9SGregory Neil Shapiro 
136106f25ae9SGregory Neil Shapiro static SOCKADDR	ClientAddr;		/* address for client */
136206f25ae9SGregory Neil Shapiro 
136306f25ae9SGregory Neil Shapiro void
136406f25ae9SGregory Neil Shapiro setclientoptions(p)
136506f25ae9SGregory Neil Shapiro 	register char *p;
136606f25ae9SGregory Neil Shapiro {
136706f25ae9SGregory Neil Shapiro 	struct daemon d;
136806f25ae9SGregory Neil Shapiro 	extern ENVELOPE BlankEnvelope;
136906f25ae9SGregory Neil Shapiro 
137006f25ae9SGregory Neil Shapiro 	memset(&d, '\0', sizeof d);
137106f25ae9SGregory Neil Shapiro 	setsockaddroptions(p, &d);
137206f25ae9SGregory Neil Shapiro 
137306f25ae9SGregory Neil Shapiro 	/* grab what we need */
137406f25ae9SGregory Neil Shapiro 	memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr);
137506f25ae9SGregory Neil Shapiro 	TcpSndBufferSize = d.d_tcpsndbufsize;
137606f25ae9SGregory Neil Shapiro 	TcpRcvBufferSize = d.d_tcprcvbufsize;
137706f25ae9SGregory Neil Shapiro 	if (d.d_mflags != NULL)
137806f25ae9SGregory Neil Shapiro 		define(macid("{client_flags}", NULL), d.d_mflags,
137906f25ae9SGregory Neil Shapiro 		       &BlankEnvelope);
138006f25ae9SGregory Neil Shapiro 	else
138106f25ae9SGregory Neil Shapiro 		define(macid("{client_flags}", NULL), "", &BlankEnvelope);
138206f25ae9SGregory Neil Shapiro }
138306f25ae9SGregory Neil Shapiro /*
138406f25ae9SGregory Neil Shapiro **  ADDR_FAMILY -- determine address family from address
138506f25ae9SGregory Neil Shapiro **
138606f25ae9SGregory Neil Shapiro **	Parameters:
138706f25ae9SGregory Neil Shapiro **		addr -- the string representation of the address
138806f25ae9SGregory Neil Shapiro **
138906f25ae9SGregory Neil Shapiro **	Returns:
139006f25ae9SGregory Neil Shapiro **		AF_INET, AF_INET6 or AF_UNSPEC
139106f25ae9SGregory Neil Shapiro **
139206f25ae9SGregory Neil Shapiro **	Side Effects:
139306f25ae9SGregory Neil Shapiro **		none.
139406f25ae9SGregory Neil Shapiro */
139506f25ae9SGregory Neil Shapiro 
139606f25ae9SGregory Neil Shapiro static int
139706f25ae9SGregory Neil Shapiro addr_family(addr)
139806f25ae9SGregory Neil Shapiro 	char *addr;
139906f25ae9SGregory Neil Shapiro {
140006f25ae9SGregory Neil Shapiro # if NETINET6
140106f25ae9SGregory Neil Shapiro 	SOCKADDR clt_addr;
140206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
140306f25ae9SGregory Neil Shapiro 
140406f25ae9SGregory Neil Shapiro # if NETINET
140506f25ae9SGregory Neil Shapiro 	if (inet_addr(addr) != INADDR_NONE)
140606f25ae9SGregory Neil Shapiro 	{
140706f25ae9SGregory Neil Shapiro 		if (tTd(16, 9))
140806f25ae9SGregory Neil Shapiro 			printf("addr_family(%s): INET\n", addr);
140906f25ae9SGregory Neil Shapiro 		return AF_INET;
141006f25ae9SGregory Neil Shapiro 	}
141106f25ae9SGregory Neil Shapiro # endif /* NETINET */
141206f25ae9SGregory Neil Shapiro # if NETINET6
141306f25ae9SGregory Neil Shapiro 	if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1)
141406f25ae9SGregory Neil Shapiro 	{
141506f25ae9SGregory Neil Shapiro 		if (tTd(16, 9))
141606f25ae9SGregory Neil Shapiro 			printf("addr_family(%s): INET6\n", addr);
141706f25ae9SGregory Neil Shapiro 		return AF_INET6;
141806f25ae9SGregory Neil Shapiro 	}
141906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
142006f25ae9SGregory Neil Shapiro 	if (tTd(16, 9))
142106f25ae9SGregory Neil Shapiro 		printf("addr_family(%s): UNSPEC\n", addr);
142206f25ae9SGregory Neil Shapiro 	return AF_UNSPEC;
142306f25ae9SGregory Neil Shapiro }
142406f25ae9SGregory Neil Shapiro /*
142506f25ae9SGregory Neil Shapiro **  MAKECONNECTION -- make a connection to an SMTP socket on a machine.
1426c2aa98e2SPeter Wemm **
1427c2aa98e2SPeter Wemm **	Parameters:
1428c2aa98e2SPeter Wemm **		host -- the name of the host.
1429c2aa98e2SPeter Wemm **		port -- the port number to connect to.
1430c2aa98e2SPeter Wemm **		mci -- a pointer to the mail connection information
1431c2aa98e2SPeter Wemm **			structure to be filled in.
1432c2aa98e2SPeter Wemm **		e -- the current envelope.
1433c2aa98e2SPeter Wemm **
1434c2aa98e2SPeter Wemm **	Returns:
1435c2aa98e2SPeter Wemm **		An exit code telling whether the connection could be
1436c2aa98e2SPeter Wemm **			made and if not why not.
1437c2aa98e2SPeter Wemm **
1438c2aa98e2SPeter Wemm **	Side Effects:
1439c2aa98e2SPeter Wemm **		none.
1440c2aa98e2SPeter Wemm */
1441c2aa98e2SPeter Wemm 
1442c2aa98e2SPeter Wemm static jmp_buf	CtxConnectTimeout;
1443c2aa98e2SPeter Wemm 
1444c2aa98e2SPeter Wemm SOCKADDR	CurHostAddr;		/* address of current host */
1445c2aa98e2SPeter Wemm 
1446c2aa98e2SPeter Wemm int
1447c2aa98e2SPeter Wemm makeconnection(host, port, mci, e)
1448c2aa98e2SPeter Wemm 	char *host;
144906f25ae9SGregory Neil Shapiro 	volatile u_int port;
1450c2aa98e2SPeter Wemm 	register MCI *mci;
1451c2aa98e2SPeter Wemm 	ENVELOPE *e;
1452c2aa98e2SPeter Wemm {
1453c2aa98e2SPeter Wemm 	register volatile int addrno = 0;
1454c2aa98e2SPeter Wemm 	register volatile int s;
1455c2aa98e2SPeter Wemm 	register struct hostent *volatile hp = (struct hostent *)NULL;
1456c2aa98e2SPeter Wemm 	SOCKADDR addr;
145706f25ae9SGregory Neil Shapiro 	SOCKADDR clt_addr;
145806f25ae9SGregory Neil Shapiro 	int save_errno = 0;
145906f25ae9SGregory Neil Shapiro 	volatile SOCKADDR_LEN_T addrlen;
1460c2aa98e2SPeter Wemm 	volatile bool firstconnect;
1461c2aa98e2SPeter Wemm 	EVENT *volatile ev = NULL;
146206f25ae9SGregory Neil Shapiro # if NETINET6
146306f25ae9SGregory Neil Shapiro 	volatile bool v6found = FALSE;
146406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
146506f25ae9SGregory Neil Shapiro 	volatile int family = InetMode;
146606f25ae9SGregory Neil Shapiro 	SOCKADDR_LEN_T len;
146706f25ae9SGregory Neil Shapiro 	volatile SOCKADDR_LEN_T socksize = 0;
146806f25ae9SGregory Neil Shapiro 	volatile bool clt_bind;
146906f25ae9SGregory Neil Shapiro 	BITMAP256 d_flags;
147006f25ae9SGregory Neil Shapiro 	char *p;
147106f25ae9SGregory Neil Shapiro 	extern ENVELOPE BlankEnvelope;
147206f25ae9SGregory Neil Shapiro 
147306f25ae9SGregory Neil Shapiro 	/* retranslate ${daemon_flags} into bitmap */
147406f25ae9SGregory Neil Shapiro 	clrbitmap(d_flags);
147506f25ae9SGregory Neil Shapiro 	if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL)
147606f25ae9SGregory Neil Shapiro 	{
147706f25ae9SGregory Neil Shapiro 		for (; *p != '\0'; p++)
147806f25ae9SGregory Neil Shapiro 		{
147906f25ae9SGregory Neil Shapiro 			if (!(isascii(*p) && isspace(*p)))
148006f25ae9SGregory Neil Shapiro 				setbitn(*p, d_flags);
148106f25ae9SGregory Neil Shapiro 		}
148206f25ae9SGregory Neil Shapiro 	}
148306f25ae9SGregory Neil Shapiro 
148406f25ae9SGregory Neil Shapiro 	/* "add" ${client_flags} to bitmap */
148506f25ae9SGregory Neil Shapiro 	if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL)
148606f25ae9SGregory Neil Shapiro 	{
148706f25ae9SGregory Neil Shapiro 		for (; *p != '\0'; p++)
148806f25ae9SGregory Neil Shapiro 		{
148906f25ae9SGregory Neil Shapiro 			/* look for just this one flag */
149006f25ae9SGregory Neil Shapiro 			if (*p == D_IFNHELO)
149106f25ae9SGregory Neil Shapiro 			{
149206f25ae9SGregory Neil Shapiro 				setbitn(*p, d_flags);
149306f25ae9SGregory Neil Shapiro 				break;
149406f25ae9SGregory Neil Shapiro 			}
149506f25ae9SGregory Neil Shapiro 		}
149606f25ae9SGregory Neil Shapiro 	}
149706f25ae9SGregory Neil Shapiro 
149806f25ae9SGregory Neil Shapiro # if NETINET6
149906f25ae9SGregory Neil Shapiro  v4retry:
150006f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
150106f25ae9SGregory Neil Shapiro 	clt_bind = FALSE;
150206f25ae9SGregory Neil Shapiro 
150306f25ae9SGregory Neil Shapiro 	/* Set up the address for outgoing connection. */
150406f25ae9SGregory Neil Shapiro 	if (bitnset(D_BINDIF, d_flags) &&
150506f25ae9SGregory Neil Shapiro 	    (p = macvalue(macid("{if_addr}", NULL), e)) != NULL)
150606f25ae9SGregory Neil Shapiro 	{
150706f25ae9SGregory Neil Shapiro # if NETINET6
150806f25ae9SGregory Neil Shapiro 		char p6[INET6_ADDRSTRLEN];
150906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
151006f25ae9SGregory Neil Shapiro 
151106f25ae9SGregory Neil Shapiro 		memset(&clt_addr, '\0', sizeof clt_addr);
151206f25ae9SGregory Neil Shapiro 
151306f25ae9SGregory Neil Shapiro 		/* infer the address family from the address itself */
151406f25ae9SGregory Neil Shapiro 		clt_addr.sa.sa_family = addr_family(p);
151506f25ae9SGregory Neil Shapiro 		switch (clt_addr.sa.sa_family)
151606f25ae9SGregory Neil Shapiro 		{
151706f25ae9SGregory Neil Shapiro # if NETINET
151806f25ae9SGregory Neil Shapiro 		  case AF_INET:
151906f25ae9SGregory Neil Shapiro 			if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p))
152006f25ae9SGregory Neil Shapiro 			    != INADDR_NONE)
152106f25ae9SGregory Neil Shapiro 			{
152206f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
152306f25ae9SGregory Neil Shapiro 				socksize = sizeof (struct sockaddr_in);
152406f25ae9SGregory Neil Shapiro 			}
152506f25ae9SGregory Neil Shapiro 			else if (clt_addr.sin.sin_port != 0)
152606f25ae9SGregory Neil Shapiro 			{
152706f25ae9SGregory Neil Shapiro 				clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
152806f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
152906f25ae9SGregory Neil Shapiro 				socksize = sizeof (struct sockaddr_in);
153006f25ae9SGregory Neil Shapiro 			}
153106f25ae9SGregory Neil Shapiro 			break;
153206f25ae9SGregory Neil Shapiro # endif /* NETINET */
153306f25ae9SGregory Neil Shapiro 
153406f25ae9SGregory Neil Shapiro # if NETINET6
153506f25ae9SGregory Neil Shapiro 		  case AF_INET6:
153606f25ae9SGregory Neil Shapiro 			if (inet_addr(p) != INADDR_NONE)
153706f25ae9SGregory Neil Shapiro 				snprintf(p6, sizeof p6, "::ffff:%s", p);
153806f25ae9SGregory Neil Shapiro 			else
153906f25ae9SGregory Neil Shapiro 				strlcpy(p6, p, sizeof p6);
154006f25ae9SGregory Neil Shapiro 			if (inet_pton(AF_INET6, p6,
154106f25ae9SGregory Neil Shapiro 				      &clt_addr.sin6.sin6_addr) == 1)
154206f25ae9SGregory Neil Shapiro 			{
154306f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
154406f25ae9SGregory Neil Shapiro 				socksize = sizeof (struct sockaddr_in6);
154506f25ae9SGregory Neil Shapiro 			}
154606f25ae9SGregory Neil Shapiro 			else if (clt_addr.sin6.sin6_port != 0)
154706f25ae9SGregory Neil Shapiro 			{
154806f25ae9SGregory Neil Shapiro 				if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
154906f25ae9SGregory Neil Shapiro 					clt_addr.sin6.sin6_addr = in6addr_any;
155006f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
155106f25ae9SGregory Neil Shapiro 				socksize = sizeof (struct sockaddr_in6);
155206f25ae9SGregory Neil Shapiro 			}
155306f25ae9SGregory Neil Shapiro 			break;
155406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
155506f25ae9SGregory Neil Shapiro 
155606f25ae9SGregory Neil Shapiro # if 0
155706f25ae9SGregory Neil Shapiro 		  default:
155806f25ae9SGregory Neil Shapiro 			syserr("554 5.3.5 Address= option unsupported for family %d",
155906f25ae9SGregory Neil Shapiro 			       clt_addr.sa.sa_family);
156006f25ae9SGregory Neil Shapiro 			break;
156106f25ae9SGregory Neil Shapiro # endif /* 0 */
156206f25ae9SGregory Neil Shapiro 		}
156306f25ae9SGregory Neil Shapiro 		if (clt_bind)
156406f25ae9SGregory Neil Shapiro 			family = clt_addr.sa.sa_family;
156506f25ae9SGregory Neil Shapiro 	}
156606f25ae9SGregory Neil Shapiro 	else
156706f25ae9SGregory Neil Shapiro 	{
156806f25ae9SGregory Neil Shapiro 		STRUCTCOPY(ClientAddr, clt_addr);
156906f25ae9SGregory Neil Shapiro 		if (clt_addr.sa.sa_family == AF_UNSPEC)
157006f25ae9SGregory Neil Shapiro 			clt_addr.sa.sa_family = InetMode;
157106f25ae9SGregory Neil Shapiro 		switch (clt_addr.sa.sa_family)
157206f25ae9SGregory Neil Shapiro 		{
157306f25ae9SGregory Neil Shapiro # if NETINET
157406f25ae9SGregory Neil Shapiro 		  case AF_INET:
157506f25ae9SGregory Neil Shapiro 			if (clt_addr.sin.sin_addr.s_addr == 0)
157606f25ae9SGregory Neil Shapiro 				clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
157706f25ae9SGregory Neil Shapiro 			else
157806f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
157906f25ae9SGregory Neil Shapiro 			if (clt_addr.sin.sin_port != 0)
158006f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
158106f25ae9SGregory Neil Shapiro 			socksize = sizeof (struct sockaddr_in);
158206f25ae9SGregory Neil Shapiro 			break;
158306f25ae9SGregory Neil Shapiro # endif /* NETINET */
158406f25ae9SGregory Neil Shapiro # if NETINET6
158506f25ae9SGregory Neil Shapiro 		  case AF_INET6:
158606f25ae9SGregory Neil Shapiro 			if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
158706f25ae9SGregory Neil Shapiro 				clt_addr.sin6.sin6_addr = in6addr_any;
158806f25ae9SGregory Neil Shapiro 			else
158906f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
159006f25ae9SGregory Neil Shapiro 			socksize = sizeof (struct sockaddr_in6);
159106f25ae9SGregory Neil Shapiro 			if (clt_addr.sin6.sin6_port != 0)
159206f25ae9SGregory Neil Shapiro 				clt_bind = TRUE;
159306f25ae9SGregory Neil Shapiro 			break;
159406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
159506f25ae9SGregory Neil Shapiro # if NETISO
159606f25ae9SGregory Neil Shapiro 		  case AF_ISO:
159706f25ae9SGregory Neil Shapiro 			socksize = sizeof clt_addr.siso;
159806f25ae9SGregory Neil Shapiro 			clt_bind = TRUE;
159906f25ae9SGregory Neil Shapiro 			break;
160006f25ae9SGregory Neil Shapiro # endif /* NETISO */
160106f25ae9SGregory Neil Shapiro 		  default:
160206f25ae9SGregory Neil Shapiro 			break;
160306f25ae9SGregory Neil Shapiro 		}
160406f25ae9SGregory Neil Shapiro 	}
1605c2aa98e2SPeter Wemm 
1606c2aa98e2SPeter Wemm 	/*
1607c2aa98e2SPeter Wemm 	**  Set up the address for the mailer.
1608c2aa98e2SPeter Wemm 	**	Accept "[a.b.c.d]" syntax for host name.
1609c2aa98e2SPeter Wemm 	*/
1610c2aa98e2SPeter Wemm 
1611c2aa98e2SPeter Wemm # if NAMED_BIND
1612c2aa98e2SPeter Wemm 	h_errno = 0;
161306f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
1614c2aa98e2SPeter Wemm 	errno = 0;
161506f25ae9SGregory Neil Shapiro 	memset(&CurHostAddr, '\0', sizeof CurHostAddr);
161606f25ae9SGregory Neil Shapiro 	memset(&addr, '\0', sizeof addr);
1617c2aa98e2SPeter Wemm 	SmtpPhase = mci->mci_phase = "initial connection";
1618c2aa98e2SPeter Wemm 	CurHostName = host;
1619c2aa98e2SPeter Wemm 
1620c2aa98e2SPeter Wemm 	if (host[0] == '[')
1621c2aa98e2SPeter Wemm 	{
162206f25ae9SGregory Neil Shapiro 		p = strchr(host, ']');
1623c2aa98e2SPeter Wemm 		if (p != NULL)
1624c2aa98e2SPeter Wemm 		{
1625c2aa98e2SPeter Wemm # if NETINET
162606f25ae9SGregory Neil Shapiro 			unsigned long hid = INADDR_NONE;
162706f25ae9SGregory Neil Shapiro # endif /* NETINET */
162806f25ae9SGregory Neil Shapiro # if NETINET6
162906f25ae9SGregory Neil Shapiro 			struct sockaddr_in6 hid6;
163006f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
163106f25ae9SGregory Neil Shapiro 
163206f25ae9SGregory Neil Shapiro 			*p = '\0';
163306f25ae9SGregory Neil Shapiro # if NETINET6
163406f25ae9SGregory Neil Shapiro 			memset(&hid6, '\0', sizeof hid6);
163506f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
163606f25ae9SGregory Neil Shapiro # if NETINET
163706f25ae9SGregory Neil Shapiro 			if (family == AF_INET &&
163806f25ae9SGregory Neil Shapiro 			    (hid = inet_addr(&host[1])) != INADDR_NONE)
163906f25ae9SGregory Neil Shapiro 			{
164006f25ae9SGregory Neil Shapiro 				addr.sin.sin_family = AF_INET;
164106f25ae9SGregory Neil Shapiro 				addr.sin.sin_addr.s_addr = hid;
164206f25ae9SGregory Neil Shapiro 			}
164306f25ae9SGregory Neil Shapiro 			else
164406f25ae9SGregory Neil Shapiro # endif /* NETINET */
164506f25ae9SGregory Neil Shapiro # if NETINET6
164606f25ae9SGregory Neil Shapiro 			if (family == AF_INET6 &&
164706f25ae9SGregory Neil Shapiro 			    inet_pton(AF_INET6, &host[1],
164806f25ae9SGregory Neil Shapiro 				      &hid6.sin6_addr) == 1)
164906f25ae9SGregory Neil Shapiro 			{
165006f25ae9SGregory Neil Shapiro 				addr.sin6.sin6_family = AF_INET6;
165106f25ae9SGregory Neil Shapiro 				addr.sin6.sin6_addr = hid6.sin6_addr;
165206f25ae9SGregory Neil Shapiro 			}
165306f25ae9SGregory Neil Shapiro 			else
165406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1655c2aa98e2SPeter Wemm 			{
1656c2aa98e2SPeter Wemm 				/* try it as a host name (avoid MX lookup) */
165706f25ae9SGregory Neil Shapiro 				hp = sm_gethostbyname(&host[1], family);
1658c2aa98e2SPeter Wemm 				if (hp == NULL && p[-1] == '.')
1659c2aa98e2SPeter Wemm 				{
1660c2aa98e2SPeter Wemm # if NAMED_BIND
1661c2aa98e2SPeter Wemm 					int oldopts = _res.options;
1662c2aa98e2SPeter Wemm 
1663c2aa98e2SPeter Wemm 					_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
166406f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
1665c2aa98e2SPeter Wemm 					p[-1] = '\0';
166606f25ae9SGregory Neil Shapiro 					hp = sm_gethostbyname(&host[1],
166706f25ae9SGregory Neil Shapiro 							      family);
1668c2aa98e2SPeter Wemm 					p[-1] = '.';
1669c2aa98e2SPeter Wemm # if NAMED_BIND
1670c2aa98e2SPeter Wemm 					_res.options = oldopts;
167106f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
1672c2aa98e2SPeter Wemm 				}
1673c2aa98e2SPeter Wemm 				*p = ']';
1674c2aa98e2SPeter Wemm 				goto gothostent;
1675c2aa98e2SPeter Wemm 			}
1676c2aa98e2SPeter Wemm 			*p = ']';
1677c2aa98e2SPeter Wemm 		}
1678c2aa98e2SPeter Wemm 		if (p == NULL)
1679c2aa98e2SPeter Wemm 		{
1680c2aa98e2SPeter Wemm 			extern char MsgBuf[];
1681c2aa98e2SPeter Wemm 
168206f25ae9SGregory Neil Shapiro 			usrerrenh("5.1.2",
168306f25ae9SGregory Neil Shapiro 				  "553 Invalid numeric domain spec \"%s\"",
168406f25ae9SGregory Neil Shapiro 				  host);
1685c2aa98e2SPeter Wemm 			mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
168606f25ae9SGregory Neil Shapiro 			errno = EINVAL;
1687c2aa98e2SPeter Wemm 			return EX_NOHOST;
1688c2aa98e2SPeter Wemm 		}
1689c2aa98e2SPeter Wemm 	}
1690c2aa98e2SPeter Wemm 	else
1691c2aa98e2SPeter Wemm 	{
1692c2aa98e2SPeter Wemm 		/* contortion to get around SGI cc complaints */
1693c2aa98e2SPeter Wemm 		{
169406f25ae9SGregory Neil Shapiro 			p = &host[strlen(host) - 1];
169506f25ae9SGregory Neil Shapiro 			hp = sm_gethostbyname(host, family);
1696c2aa98e2SPeter Wemm 			if (hp == NULL && *p == '.')
1697c2aa98e2SPeter Wemm 			{
1698c2aa98e2SPeter Wemm # if NAMED_BIND
1699c2aa98e2SPeter Wemm 				int oldopts = _res.options;
1700c2aa98e2SPeter Wemm 
1701c2aa98e2SPeter Wemm 				_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
170206f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
1703c2aa98e2SPeter Wemm 				*p = '\0';
170406f25ae9SGregory Neil Shapiro 				hp = sm_gethostbyname(host, family);
1705c2aa98e2SPeter Wemm 				*p = '.';
1706c2aa98e2SPeter Wemm # if NAMED_BIND
1707c2aa98e2SPeter Wemm 				_res.options = oldopts;
170806f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
1709c2aa98e2SPeter Wemm 			}
1710c2aa98e2SPeter Wemm 		}
1711c2aa98e2SPeter Wemm gothostent:
1712c2aa98e2SPeter Wemm 		if (hp == NULL)
1713c2aa98e2SPeter Wemm 		{
1714c2aa98e2SPeter Wemm # if NAMED_BIND
1715c2aa98e2SPeter Wemm 			/* check for name server timeouts */
1716c2aa98e2SPeter Wemm 			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
1717c2aa98e2SPeter Wemm 			    (errno == ECONNREFUSED && UseNameServer))
1718c2aa98e2SPeter Wemm 			{
171906f25ae9SGregory Neil Shapiro 				save_errno = errno;
1720c2aa98e2SPeter Wemm 				mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
172106f25ae9SGregory Neil Shapiro 				errno = save_errno;
1722c2aa98e2SPeter Wemm 				return EX_TEMPFAIL;
1723c2aa98e2SPeter Wemm 			}
172406f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
172506f25ae9SGregory Neil Shapiro # if NETINET6
172606f25ae9SGregory Neil Shapiro 			/*
172706f25ae9SGregory Neil Shapiro 			**  Try v6 first, then fall back to v4.
172806f25ae9SGregory Neil Shapiro 			**  If we found a v6 address, but no v4
172906f25ae9SGregory Neil Shapiro 			**  addresses, then TEMPFAIL.
173006f25ae9SGregory Neil Shapiro 			*/
173106f25ae9SGregory Neil Shapiro 
173206f25ae9SGregory Neil Shapiro 			if (family == AF_INET6)
173306f25ae9SGregory Neil Shapiro 			{
173406f25ae9SGregory Neil Shapiro 				family = AF_INET;
173506f25ae9SGregory Neil Shapiro 				goto v4retry;
173606f25ae9SGregory Neil Shapiro 			}
173706f25ae9SGregory Neil Shapiro 			if (v6found)
173806f25ae9SGregory Neil Shapiro 				goto v6tempfail;
173906f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
174006f25ae9SGregory Neil Shapiro 			save_errno = errno;
1741c2aa98e2SPeter Wemm 			mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
174206f25ae9SGregory Neil Shapiro 			errno = save_errno;
174306f25ae9SGregory Neil Shapiro 			return EX_NOHOST;
1744c2aa98e2SPeter Wemm 		}
1745c2aa98e2SPeter Wemm 		addr.sa.sa_family = hp->h_addrtype;
1746c2aa98e2SPeter Wemm 		switch (hp->h_addrtype)
1747c2aa98e2SPeter Wemm 		{
1748c2aa98e2SPeter Wemm # if NETINET
1749c2aa98e2SPeter Wemm 		  case AF_INET:
175006f25ae9SGregory Neil Shapiro 			memmove(&addr.sin.sin_addr,
175106f25ae9SGregory Neil Shapiro 				hp->h_addr,
1752c2aa98e2SPeter Wemm 				INADDRSZ);
1753c2aa98e2SPeter Wemm 			break;
175406f25ae9SGregory Neil Shapiro # endif /* NETINET */
175506f25ae9SGregory Neil Shapiro 
175606f25ae9SGregory Neil Shapiro # if NETINET6
175706f25ae9SGregory Neil Shapiro 		  case AF_INET6:
175806f25ae9SGregory Neil Shapiro 			memmove(&addr.sin6.sin6_addr,
175906f25ae9SGregory Neil Shapiro 				hp->h_addr,
176006f25ae9SGregory Neil Shapiro 				IN6ADDRSZ);
176106f25ae9SGregory Neil Shapiro 			break;
176206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1763c2aa98e2SPeter Wemm 
1764c2aa98e2SPeter Wemm 		  default:
1765c2aa98e2SPeter Wemm 			if (hp->h_length > sizeof addr.sa.sa_data)
1766c2aa98e2SPeter Wemm 			{
1767c2aa98e2SPeter Wemm 				syserr("makeconnection: long sa_data: family %d len %d",
1768c2aa98e2SPeter Wemm 					hp->h_addrtype, hp->h_length);
1769c2aa98e2SPeter Wemm 				mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
177006f25ae9SGregory Neil Shapiro 				errno = EINVAL;
1771c2aa98e2SPeter Wemm 				return EX_NOHOST;
1772c2aa98e2SPeter Wemm 			}
177306f25ae9SGregory Neil Shapiro 			memmove(addr.sa.sa_data,
177406f25ae9SGregory Neil Shapiro 				hp->h_addr,
1775c2aa98e2SPeter Wemm 				hp->h_length);
1776c2aa98e2SPeter Wemm 			break;
1777c2aa98e2SPeter Wemm 		}
1778c2aa98e2SPeter Wemm 		addrno = 1;
1779c2aa98e2SPeter Wemm 	}
1780c2aa98e2SPeter Wemm 
1781c2aa98e2SPeter Wemm 	/*
1782c2aa98e2SPeter Wemm 	**  Determine the port number.
1783c2aa98e2SPeter Wemm 	*/
1784c2aa98e2SPeter Wemm 
1785c2aa98e2SPeter Wemm 	if (port == 0)
1786c2aa98e2SPeter Wemm 	{
178706f25ae9SGregory Neil Shapiro # ifdef NO_GETSERVBYNAME
178806f25ae9SGregory Neil Shapiro 		port = htons(25);
178906f25ae9SGregory Neil Shapiro # else /* NO_GETSERVBYNAME */
1790c2aa98e2SPeter Wemm 		register struct servent *sp = getservbyname("smtp", "tcp");
1791c2aa98e2SPeter Wemm 
1792c2aa98e2SPeter Wemm 		if (sp == NULL)
1793c2aa98e2SPeter Wemm 		{
1794c2aa98e2SPeter Wemm 			if (LogLevel > 2)
1795c2aa98e2SPeter Wemm 				sm_syslog(LOG_ERR, NOQID,
1796c2aa98e2SPeter Wemm 					  "makeconnection: service \"smtp\" unknown");
1797c2aa98e2SPeter Wemm 			port = htons(25);
1798c2aa98e2SPeter Wemm 		}
1799c2aa98e2SPeter Wemm 		else
1800c2aa98e2SPeter Wemm 			port = sp->s_port;
180106f25ae9SGregory Neil Shapiro # endif /* NO_GETSERVBYNAME */
1802c2aa98e2SPeter Wemm 	}
1803c2aa98e2SPeter Wemm 
1804c2aa98e2SPeter Wemm 	switch (addr.sa.sa_family)
1805c2aa98e2SPeter Wemm 	{
1806c2aa98e2SPeter Wemm # if NETINET
1807c2aa98e2SPeter Wemm 	  case AF_INET:
1808c2aa98e2SPeter Wemm 		addr.sin.sin_port = port;
1809c2aa98e2SPeter Wemm 		addrlen = sizeof (struct sockaddr_in);
1810c2aa98e2SPeter Wemm 		break;
181106f25ae9SGregory Neil Shapiro # endif /* NETINET */
181206f25ae9SGregory Neil Shapiro 
181306f25ae9SGregory Neil Shapiro # if NETINET6
181406f25ae9SGregory Neil Shapiro 	  case AF_INET6:
181506f25ae9SGregory Neil Shapiro 		addr.sin6.sin6_port = port;
181606f25ae9SGregory Neil Shapiro 		addrlen = sizeof (struct sockaddr_in6);
181706f25ae9SGregory Neil Shapiro 		break;
181806f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
1819c2aa98e2SPeter Wemm 
1820c2aa98e2SPeter Wemm # if NETISO
1821c2aa98e2SPeter Wemm 	  case AF_ISO:
1822c2aa98e2SPeter Wemm 		/* assume two byte transport selector */
182306f25ae9SGregory Neil Shapiro 		memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
1824c2aa98e2SPeter Wemm 		addrlen = sizeof (struct sockaddr_iso);
1825c2aa98e2SPeter Wemm 		break;
182606f25ae9SGregory Neil Shapiro # endif /* NETISO */
1827c2aa98e2SPeter Wemm 
1828c2aa98e2SPeter Wemm 	  default:
1829c2aa98e2SPeter Wemm 		syserr("Can't connect to address family %d", addr.sa.sa_family);
1830c2aa98e2SPeter Wemm 		mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
183106f25ae9SGregory Neil Shapiro 		errno = EINVAL;
183206f25ae9SGregory Neil Shapiro 		return EX_NOHOST;
1833c2aa98e2SPeter Wemm 	}
1834c2aa98e2SPeter Wemm 
1835c2aa98e2SPeter Wemm 	/*
1836c2aa98e2SPeter Wemm 	**  Try to actually open the connection.
1837c2aa98e2SPeter Wemm 	*/
1838c2aa98e2SPeter Wemm 
1839c2aa98e2SPeter Wemm # ifdef XLA
1840c2aa98e2SPeter Wemm 	/* if too many connections, don't bother trying */
1841c2aa98e2SPeter Wemm 	if (!xla_noqueue_ok(host))
1842c2aa98e2SPeter Wemm 		return EX_TEMPFAIL;
184306f25ae9SGregory Neil Shapiro # endif /* XLA */
1844c2aa98e2SPeter Wemm 
1845c2aa98e2SPeter Wemm 	firstconnect = TRUE;
1846c2aa98e2SPeter Wemm 	for (;;)
1847c2aa98e2SPeter Wemm 	{
1848c2aa98e2SPeter Wemm 		if (tTd(16, 1))
184906f25ae9SGregory Neil Shapiro 			dprintf("makeconnection (%s [%s])\n",
1850c2aa98e2SPeter Wemm 				host, anynet_ntoa(&addr));
1851c2aa98e2SPeter Wemm 
1852c2aa98e2SPeter Wemm 		/* save for logging */
1853c2aa98e2SPeter Wemm 		CurHostAddr = addr;
1854c2aa98e2SPeter Wemm 
1855c2aa98e2SPeter Wemm 		if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
1856c2aa98e2SPeter Wemm 		{
1857c2aa98e2SPeter Wemm 			int rport = IPPORT_RESERVED - 1;
1858c2aa98e2SPeter Wemm 
1859c2aa98e2SPeter Wemm 			s = rresvport(&rport);
1860c2aa98e2SPeter Wemm 		}
1861c2aa98e2SPeter Wemm 		else
1862c2aa98e2SPeter Wemm 		{
1863c2aa98e2SPeter Wemm 			s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
1864c2aa98e2SPeter Wemm 		}
1865c2aa98e2SPeter Wemm 		if (s < 0)
1866c2aa98e2SPeter Wemm 		{
186706f25ae9SGregory Neil Shapiro 			save_errno = errno;
1868c2aa98e2SPeter Wemm 			syserr("makeconnection: cannot create socket");
1869c2aa98e2SPeter Wemm # ifdef XLA
1870c2aa98e2SPeter Wemm 			xla_host_end(host);
187106f25ae9SGregory Neil Shapiro # endif /* XLA */
1872c2aa98e2SPeter Wemm 			mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
187306f25ae9SGregory Neil Shapiro 			errno = save_errno;
1874c2aa98e2SPeter Wemm 			return EX_TEMPFAIL;
1875c2aa98e2SPeter Wemm 		}
1876c2aa98e2SPeter Wemm 
1877c2aa98e2SPeter Wemm # ifdef SO_SNDBUF
1878c2aa98e2SPeter Wemm 		if (TcpSndBufferSize > 0)
1879c2aa98e2SPeter Wemm 		{
1880c2aa98e2SPeter Wemm 			if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1881c2aa98e2SPeter Wemm 				       (char *) &TcpSndBufferSize,
1882c2aa98e2SPeter Wemm 				       sizeof(TcpSndBufferSize)) < 0)
1883c2aa98e2SPeter Wemm 				syserr("makeconnection: setsockopt(SO_SNDBUF)");
1884c2aa98e2SPeter Wemm 		}
188506f25ae9SGregory Neil Shapiro # endif /* SO_SNDBUF */
188606f25ae9SGregory Neil Shapiro # ifdef SO_RCVBUF
188706f25ae9SGregory Neil Shapiro 		if (TcpRcvBufferSize > 0)
188806f25ae9SGregory Neil Shapiro 		{
188906f25ae9SGregory Neil Shapiro 			if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
189006f25ae9SGregory Neil Shapiro 				       (char *) &TcpRcvBufferSize,
189106f25ae9SGregory Neil Shapiro 				       sizeof(TcpRcvBufferSize)) < 0)
189206f25ae9SGregory Neil Shapiro 				syserr("makeconnection: setsockopt(SO_RCVBUF)");
189306f25ae9SGregory Neil Shapiro 		}
189406f25ae9SGregory Neil Shapiro # endif /* SO_RCVBUF */
189506f25ae9SGregory Neil Shapiro 
1896c2aa98e2SPeter Wemm 
1897c2aa98e2SPeter Wemm 		if (tTd(16, 1))
189806f25ae9SGregory Neil Shapiro 			dprintf("makeconnection: fd=%d\n", s);
1899c2aa98e2SPeter Wemm 
1900c2aa98e2SPeter Wemm 		/* turn on network debugging? */
1901c2aa98e2SPeter Wemm 		if (tTd(16, 101))
1902c2aa98e2SPeter Wemm 		{
1903c2aa98e2SPeter Wemm 			int on = 1;
190406f25ae9SGregory Neil Shapiro 
1905c2aa98e2SPeter Wemm 			(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
1906c2aa98e2SPeter Wemm 					  (char *)&on, sizeof on);
1907c2aa98e2SPeter Wemm 		}
1908c2aa98e2SPeter Wemm 		if (e->e_xfp != NULL)
1909c2aa98e2SPeter Wemm 			(void) fflush(e->e_xfp);	/* for debugging */
1910c2aa98e2SPeter Wemm 		errno = 0;				/* for debugging */
1911c2aa98e2SPeter Wemm 
191206f25ae9SGregory Neil Shapiro 		if (clt_bind)
191306f25ae9SGregory Neil Shapiro 		{
191406f25ae9SGregory Neil Shapiro 			int on = 1;
191506f25ae9SGregory Neil Shapiro 
191606f25ae9SGregory Neil Shapiro 			switch (clt_addr.sa.sa_family)
191706f25ae9SGregory Neil Shapiro 			{
191806f25ae9SGregory Neil Shapiro # if NETINET
191906f25ae9SGregory Neil Shapiro 			  case AF_INET:
192006f25ae9SGregory Neil Shapiro 				if (clt_addr.sin.sin_port != 0)
192106f25ae9SGregory Neil Shapiro 					(void) setsockopt(s, SOL_SOCKET,
192206f25ae9SGregory Neil Shapiro 							  SO_REUSEADDR,
192306f25ae9SGregory Neil Shapiro 							  (char *) &on,
192406f25ae9SGregory Neil Shapiro 							  sizeof on);
192506f25ae9SGregory Neil Shapiro 				break;
192606f25ae9SGregory Neil Shapiro # endif /* NETINET */
192706f25ae9SGregory Neil Shapiro 
192806f25ae9SGregory Neil Shapiro # if NETINET6
192906f25ae9SGregory Neil Shapiro 			  case AF_INET6:
193006f25ae9SGregory Neil Shapiro 				if (clt_addr.sin6.sin6_port != 0)
193106f25ae9SGregory Neil Shapiro 					(void) setsockopt(s, SOL_SOCKET,
193206f25ae9SGregory Neil Shapiro 							  SO_REUSEADDR,
193306f25ae9SGregory Neil Shapiro 							  (char *) &on,
193406f25ae9SGregory Neil Shapiro 							  sizeof on);
193506f25ae9SGregory Neil Shapiro 				break;
193606f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
193706f25ae9SGregory Neil Shapiro 			}
193806f25ae9SGregory Neil Shapiro 
193906f25ae9SGregory Neil Shapiro 			if (bind(s, &clt_addr.sa, socksize) < 0)
194006f25ae9SGregory Neil Shapiro 			{
194106f25ae9SGregory Neil Shapiro 				save_errno = errno;
194206f25ae9SGregory Neil Shapiro 				(void) close(s);
194306f25ae9SGregory Neil Shapiro 				errno = save_errno;
194406f25ae9SGregory Neil Shapiro 				syserr("makeconnection: cannot bind socket [%s]",
194506f25ae9SGregory Neil Shapiro 				       anynet_ntoa(&clt_addr));
194606f25ae9SGregory Neil Shapiro 				errno = save_errno;
194706f25ae9SGregory Neil Shapiro 				return EX_TEMPFAIL;
194806f25ae9SGregory Neil Shapiro 			}
194906f25ae9SGregory Neil Shapiro 		}
195006f25ae9SGregory Neil Shapiro 
1951c2aa98e2SPeter Wemm 		/*
1952c2aa98e2SPeter Wemm 		**  Linux seems to hang in connect for 90 minutes (!!!).
1953c2aa98e2SPeter Wemm 		**  Time out the connect to avoid this problem.
1954c2aa98e2SPeter Wemm 		*/
1955c2aa98e2SPeter Wemm 
1956c2aa98e2SPeter Wemm 		if (setjmp(CtxConnectTimeout) == 0)
1957c2aa98e2SPeter Wemm 		{
1958c2aa98e2SPeter Wemm 			int i;
1959c2aa98e2SPeter Wemm 
1960c2aa98e2SPeter Wemm 			if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
1961c2aa98e2SPeter Wemm 				ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
1962c2aa98e2SPeter Wemm 			else if (TimeOuts.to_connect != 0)
1963c2aa98e2SPeter Wemm 				ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
1964c2aa98e2SPeter Wemm 			else
1965c2aa98e2SPeter Wemm 				ev = NULL;
1966c2aa98e2SPeter Wemm 
196706f25ae9SGregory Neil Shapiro 			switch (ConnectOnlyTo.sa.sa_family)
196806f25ae9SGregory Neil Shapiro 			{
196906f25ae9SGregory Neil Shapiro # if NETINET
197006f25ae9SGregory Neil Shapiro 			  case AF_INET:
197106f25ae9SGregory Neil Shapiro 				addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr;
197206f25ae9SGregory Neil Shapiro 				break;
197306f25ae9SGregory Neil Shapiro # endif /* NETINET */
197406f25ae9SGregory Neil Shapiro 
197506f25ae9SGregory Neil Shapiro # if NETINET6
197606f25ae9SGregory Neil Shapiro 			  case AF_INET6:
197706f25ae9SGregory Neil Shapiro 				memmove(&addr.sin6.sin6_addr,
197806f25ae9SGregory Neil Shapiro 					&ConnectOnlyTo.sin6.sin6_addr,
197906f25ae9SGregory Neil Shapiro 					IN6ADDRSZ);
198006f25ae9SGregory Neil Shapiro 				break;
198106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
198206f25ae9SGregory Neil Shapiro 			}
1983c2aa98e2SPeter Wemm 			i = connect(s, (struct sockaddr *) &addr, addrlen);
198406f25ae9SGregory Neil Shapiro 			save_errno = errno;
1985c2aa98e2SPeter Wemm 			if (ev != NULL)
1986c2aa98e2SPeter Wemm 				clrevent(ev);
1987c2aa98e2SPeter Wemm 			if (i >= 0)
1988c2aa98e2SPeter Wemm 				break;
1989c2aa98e2SPeter Wemm 		}
1990c2aa98e2SPeter Wemm 		else
199106f25ae9SGregory Neil Shapiro 			save_errno = errno;
1992c2aa98e2SPeter Wemm 
1993c2aa98e2SPeter Wemm 		/* if running demand-dialed connection, try again */
1994c2aa98e2SPeter Wemm 		if (DialDelay > 0 && firstconnect)
1995c2aa98e2SPeter Wemm 		{
1996c2aa98e2SPeter Wemm 			if (tTd(16, 1))
199706f25ae9SGregory Neil Shapiro 				dprintf("Connect failed (%s); trying again...\n",
199806f25ae9SGregory Neil Shapiro 					errstring(save_errno));
1999c2aa98e2SPeter Wemm 			firstconnect = FALSE;
200006f25ae9SGregory Neil Shapiro 			(void) sleep(DialDelay);
2001c2aa98e2SPeter Wemm 			continue;
2002c2aa98e2SPeter Wemm 		}
2003c2aa98e2SPeter Wemm 
2004c2aa98e2SPeter Wemm 		/* couldn't connect.... figure out why */
2005c2aa98e2SPeter Wemm 		(void) close(s);
2006c2aa98e2SPeter Wemm 
2007c2aa98e2SPeter Wemm 		if (LogLevel >= 14)
2008c2aa98e2SPeter Wemm 			sm_syslog(LOG_INFO, e->e_id,
2009c2aa98e2SPeter Wemm 				  "makeconnection (%s [%s]) failed: %s",
2010c2aa98e2SPeter Wemm 				  host, anynet_ntoa(&addr),
201106f25ae9SGregory Neil Shapiro 				  errstring(save_errno));
2012c2aa98e2SPeter Wemm 
2013c2aa98e2SPeter Wemm 		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
2014c2aa98e2SPeter Wemm 		{
2015c2aa98e2SPeter Wemm 			if (tTd(16, 1))
201606f25ae9SGregory Neil Shapiro 				dprintf("Connect failed (%s); trying new address....\n",
201706f25ae9SGregory Neil Shapiro 					errstring(save_errno));
2018c2aa98e2SPeter Wemm 			switch (addr.sa.sa_family)
2019c2aa98e2SPeter Wemm 			{
2020c2aa98e2SPeter Wemm # if NETINET
2021c2aa98e2SPeter Wemm 			  case AF_INET:
202206f25ae9SGregory Neil Shapiro 				memmove(&addr.sin.sin_addr,
202306f25ae9SGregory Neil Shapiro 					hp->h_addr_list[addrno++],
2024c2aa98e2SPeter Wemm 					INADDRSZ);
2025c2aa98e2SPeter Wemm 				break;
202606f25ae9SGregory Neil Shapiro # endif /* NETINET */
202706f25ae9SGregory Neil Shapiro 
202806f25ae9SGregory Neil Shapiro # if NETINET6
202906f25ae9SGregory Neil Shapiro 			  case AF_INET6:
203006f25ae9SGregory Neil Shapiro 				memmove(&addr.sin6.sin6_addr,
203106f25ae9SGregory Neil Shapiro 					hp->h_addr_list[addrno++],
203206f25ae9SGregory Neil Shapiro 					IN6ADDRSZ);
203306f25ae9SGregory Neil Shapiro 				break;
203406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
2035c2aa98e2SPeter Wemm 
2036c2aa98e2SPeter Wemm 			  default:
203706f25ae9SGregory Neil Shapiro 				memmove(addr.sa.sa_data,
203806f25ae9SGregory Neil Shapiro 					hp->h_addr_list[addrno++],
2039c2aa98e2SPeter Wemm 					hp->h_length);
2040c2aa98e2SPeter Wemm 				break;
2041c2aa98e2SPeter Wemm 			}
2042c2aa98e2SPeter Wemm 			continue;
2043c2aa98e2SPeter Wemm 		}
204406f25ae9SGregory Neil Shapiro 		errno = save_errno;
2045c2aa98e2SPeter Wemm 
204606f25ae9SGregory Neil Shapiro # if NETINET6
204706f25ae9SGregory Neil Shapiro 		if (family == AF_INET6)
204806f25ae9SGregory Neil Shapiro 		{
204906f25ae9SGregory Neil Shapiro 			if (tTd(16, 1))
205006f25ae9SGregory Neil Shapiro 				dprintf("Connect failed (%s); retrying with AF_INET....\n",
205106f25ae9SGregory Neil Shapiro 					errstring(save_errno));
205206f25ae9SGregory Neil Shapiro 			v6found = TRUE;
205306f25ae9SGregory Neil Shapiro 			family = AF_INET;
205406f25ae9SGregory Neil Shapiro 			goto v4retry;
205506f25ae9SGregory Neil Shapiro 		}
205606f25ae9SGregory Neil Shapiro 	v6tempfail:
205706f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
2058c2aa98e2SPeter Wemm 		/* couldn't open connection */
205906f25ae9SGregory Neil Shapiro # if NETINET6
206006f25ae9SGregory Neil Shapiro 		/* Don't clobber an already saved errno from v4retry */
206106f25ae9SGregory Neil Shapiro 		if (errno > 0)
206206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
206306f25ae9SGregory Neil Shapiro 			save_errno = errno;
206406f25ae9SGregory Neil Shapiro 		if (tTd(16, 1))
206506f25ae9SGregory Neil Shapiro 			dprintf("Connect failed (%s)\n", errstring(save_errno));
2066c2aa98e2SPeter Wemm # ifdef XLA
2067c2aa98e2SPeter Wemm 		xla_host_end(host);
206806f25ae9SGregory Neil Shapiro # endif /* XLA */
2069c2aa98e2SPeter Wemm 		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
207006f25ae9SGregory Neil Shapiro 		errno = save_errno;
2071c2aa98e2SPeter Wemm 		return EX_TEMPFAIL;
2072c2aa98e2SPeter Wemm 	}
2073c2aa98e2SPeter Wemm 
2074c2aa98e2SPeter Wemm 	/* connection ok, put it into canonical form */
207506f25ae9SGregory Neil Shapiro 	mci->mci_out = NULL;
2076c2aa98e2SPeter Wemm 	if ((mci->mci_out = fdopen(s, "w")) == NULL ||
2077c2aa98e2SPeter Wemm 	    (s = dup(s)) < 0 ||
2078c2aa98e2SPeter Wemm 	    (mci->mci_in = fdopen(s, "r")) == NULL)
2079c2aa98e2SPeter Wemm 	{
208006f25ae9SGregory Neil Shapiro 		save_errno = errno;
2081c2aa98e2SPeter Wemm 		syserr("cannot open SMTP client channel, fd=%d", s);
2082c2aa98e2SPeter Wemm 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
208306f25ae9SGregory Neil Shapiro 		if (mci->mci_out != NULL)
208406f25ae9SGregory Neil Shapiro 			(void) fclose(mci->mci_out);
208506f25ae9SGregory Neil Shapiro 		(void) close(s);
208606f25ae9SGregory Neil Shapiro 		errno = save_errno;
208706f25ae9SGregory Neil Shapiro 		return EX_TEMPFAIL;
208806f25ae9SGregory Neil Shapiro 	}
208906f25ae9SGregory Neil Shapiro 
209006f25ae9SGregory Neil Shapiro 	/* find out name for Interface through which we connect */
209106f25ae9SGregory Neil Shapiro 	len = sizeof addr;
209206f25ae9SGregory Neil Shapiro 	if (getsockname(s, &addr.sa, &len) == 0)
209306f25ae9SGregory Neil Shapiro 	{
209406f25ae9SGregory Neil Shapiro 		char *name;
209506f25ae9SGregory Neil Shapiro 		char *p;
209606f25ae9SGregory Neil Shapiro 
209706f25ae9SGregory Neil Shapiro 		define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)),
209806f25ae9SGregory Neil Shapiro 		       &BlankEnvelope);
209906f25ae9SGregory Neil Shapiro 		p = xalloc(5);
210006f25ae9SGregory Neil Shapiro 		snprintf(p, 4, "%d", addr.sa.sa_family);
210106f25ae9SGregory Neil Shapiro 		define(macid("{if_family}", NULL), p, &BlankEnvelope);
210206f25ae9SGregory Neil Shapiro 
210306f25ae9SGregory Neil Shapiro 		name = hostnamebyanyaddr(&addr);
210406f25ae9SGregory Neil Shapiro 		define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope);
210506f25ae9SGregory Neil Shapiro 		if (LogLevel > 11)
210606f25ae9SGregory Neil Shapiro 		{
210706f25ae9SGregory Neil Shapiro 			/* log connection information */
210806f25ae9SGregory Neil Shapiro 			sm_syslog(LOG_INFO, e->e_id,
210906f25ae9SGregory Neil Shapiro 				  "SMTP outgoing connect on %.40s", name);
211006f25ae9SGregory Neil Shapiro 		}
211106f25ae9SGregory Neil Shapiro 		if (bitnset(D_IFNHELO, d_flags))
211206f25ae9SGregory Neil Shapiro 		{
211306f25ae9SGregory Neil Shapiro 			if (name[0] != '[' && strchr(name, '.') != NULL)
211406f25ae9SGregory Neil Shapiro 				mci->mci_heloname = newstr(name);
211506f25ae9SGregory Neil Shapiro 		}
211606f25ae9SGregory Neil Shapiro 	}
211706f25ae9SGregory Neil Shapiro 	else
211806f25ae9SGregory Neil Shapiro 	{
211906f25ae9SGregory Neil Shapiro 		define(macid("{if_name}", NULL), NULL, &BlankEnvelope);
212006f25ae9SGregory Neil Shapiro 		define(macid("{if_addr}", NULL), NULL, &BlankEnvelope);
212106f25ae9SGregory Neil Shapiro 		define(macid("{if_family}", NULL), NULL, &BlankEnvelope);
212206f25ae9SGregory Neil Shapiro 	}
212306f25ae9SGregory Neil Shapiro 	mci_setstat(mci, EX_OK, NULL, NULL);
212406f25ae9SGregory Neil Shapiro 	return EX_OK;
212506f25ae9SGregory Neil Shapiro }
212606f25ae9SGregory Neil Shapiro 
212706f25ae9SGregory Neil Shapiro static void
212806f25ae9SGregory Neil Shapiro connecttimeout()
212906f25ae9SGregory Neil Shapiro {
213006f25ae9SGregory Neil Shapiro 	errno = ETIMEDOUT;
213106f25ae9SGregory Neil Shapiro 	longjmp(CtxConnectTimeout, 1);
213206f25ae9SGregory Neil Shapiro }
213306f25ae9SGregory Neil Shapiro /*
213406f25ae9SGregory Neil Shapiro **  MAKECONNECTION_DS -- make a connection to a domain socket.
213506f25ae9SGregory Neil Shapiro **
213606f25ae9SGregory Neil Shapiro **	Parameters:
213706f25ae9SGregory Neil Shapiro **		mux_path -- the path of the socket to connect to.
213806f25ae9SGregory Neil Shapiro **		mci -- a pointer to the mail connection information
213906f25ae9SGregory Neil Shapiro **			structure to be filled in.
214006f25ae9SGregory Neil Shapiro **
214106f25ae9SGregory Neil Shapiro **	Returns:
214206f25ae9SGregory Neil Shapiro **		An exit code telling whether the connection could be
214306f25ae9SGregory Neil Shapiro **			made and if not why not.
214406f25ae9SGregory Neil Shapiro **
214506f25ae9SGregory Neil Shapiro **	Side Effects:
214606f25ae9SGregory Neil Shapiro **		none.
214706f25ae9SGregory Neil Shapiro */
214806f25ae9SGregory Neil Shapiro 
214906f25ae9SGregory Neil Shapiro # if NETUNIX
215006f25ae9SGregory Neil Shapiro int makeconnection_ds(mux_path, mci)
215106f25ae9SGregory Neil Shapiro 	char *mux_path;
215206f25ae9SGregory Neil Shapiro 	register MCI *mci;
215306f25ae9SGregory Neil Shapiro {
215406f25ae9SGregory Neil Shapiro 	int sock;
215506f25ae9SGregory Neil Shapiro 	int rval, save_errno;
215606f25ae9SGregory Neil Shapiro 	long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK;
215706f25ae9SGregory Neil Shapiro 	struct sockaddr_un unix_addr;
215806f25ae9SGregory Neil Shapiro 
215906f25ae9SGregory Neil Shapiro 	/* if not safe, don't connect */
216006f25ae9SGregory Neil Shapiro 	rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName,
216106f25ae9SGregory Neil Shapiro 			sff, S_IRUSR|S_IWUSR, NULL);
216206f25ae9SGregory Neil Shapiro 
216306f25ae9SGregory Neil Shapiro 	if (rval != 0)
216406f25ae9SGregory Neil Shapiro 	{
216506f25ae9SGregory Neil Shapiro 		syserr("makeconnection_ds: unsafe domain socket");
216606f25ae9SGregory Neil Shapiro 		mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
216706f25ae9SGregory Neil Shapiro 		errno = rval;
216806f25ae9SGregory Neil Shapiro 		return EX_TEMPFAIL;
216906f25ae9SGregory Neil Shapiro 	}
217006f25ae9SGregory Neil Shapiro 
217106f25ae9SGregory Neil Shapiro 	/* prepare address structure */
217206f25ae9SGregory Neil Shapiro 	memset(&unix_addr, '\0', sizeof unix_addr);
217306f25ae9SGregory Neil Shapiro 	unix_addr.sun_family = AF_UNIX;
217406f25ae9SGregory Neil Shapiro 
217506f25ae9SGregory Neil Shapiro 	if (strlen(mux_path) >= sizeof unix_addr.sun_path)
217606f25ae9SGregory Neil Shapiro 	{
217706f25ae9SGregory Neil Shapiro 		syserr("makeconnection_ds: domain socket name too long");
217806f25ae9SGregory Neil Shapiro 		/* XXX why TEMPFAIL ? */
217906f25ae9SGregory Neil Shapiro 		mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
218006f25ae9SGregory Neil Shapiro 		errno = ENAMETOOLONG;
218106f25ae9SGregory Neil Shapiro 		return EX_UNAVAILABLE;
218206f25ae9SGregory Neil Shapiro 	}
218306f25ae9SGregory Neil Shapiro 	(void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path);
218406f25ae9SGregory Neil Shapiro 
218506f25ae9SGregory Neil Shapiro 	/* initialize domain socket */
218606f25ae9SGregory Neil Shapiro 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
218706f25ae9SGregory Neil Shapiro 	if (sock == -1)
218806f25ae9SGregory Neil Shapiro 	{
218906f25ae9SGregory Neil Shapiro 		save_errno = errno;
219006f25ae9SGregory Neil Shapiro 		syserr("makeconnection_ds: could not create domain socket");
219106f25ae9SGregory Neil Shapiro 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
219206f25ae9SGregory Neil Shapiro 		errno = save_errno;
219306f25ae9SGregory Neil Shapiro 		return EX_TEMPFAIL;
219406f25ae9SGregory Neil Shapiro 	}
219506f25ae9SGregory Neil Shapiro 
219606f25ae9SGregory Neil Shapiro 	/* connect to server */
219706f25ae9SGregory Neil Shapiro 	if (connect(sock, (struct sockaddr *) &unix_addr,
219806f25ae9SGregory Neil Shapiro 		    sizeof(unix_addr)) == -1)
219906f25ae9SGregory Neil Shapiro 	{
220006f25ae9SGregory Neil Shapiro 		save_errno = errno;
220106f25ae9SGregory Neil Shapiro 		syserr("Could not connect to socket %s", mux_path);
220206f25ae9SGregory Neil Shapiro 		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
220306f25ae9SGregory Neil Shapiro 		(void) close(sock);
220406f25ae9SGregory Neil Shapiro 		errno = save_errno;
220506f25ae9SGregory Neil Shapiro 		return EX_TEMPFAIL;
220606f25ae9SGregory Neil Shapiro 	}
220706f25ae9SGregory Neil Shapiro 
220806f25ae9SGregory Neil Shapiro 	/* connection ok, put it into canonical form */
220906f25ae9SGregory Neil Shapiro 	mci->mci_out = NULL;
221006f25ae9SGregory Neil Shapiro 	if ((mci->mci_out = fdopen(sock, "w")) == NULL ||
221106f25ae9SGregory Neil Shapiro 	    (sock = dup(sock)) < 0 ||
221206f25ae9SGregory Neil Shapiro 	    (mci->mci_in = fdopen(sock, "r")) == NULL)
221306f25ae9SGregory Neil Shapiro 	{
221406f25ae9SGregory Neil Shapiro 		save_errno = errno;
221506f25ae9SGregory Neil Shapiro 		syserr("cannot open SMTP client channel, fd=%d", sock);
221606f25ae9SGregory Neil Shapiro 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
221706f25ae9SGregory Neil Shapiro 		if (mci->mci_out != NULL)
221806f25ae9SGregory Neil Shapiro 			(void) fclose(mci->mci_out);
221906f25ae9SGregory Neil Shapiro 		(void) close(sock);
222006f25ae9SGregory Neil Shapiro 		errno = save_errno;
2221c2aa98e2SPeter Wemm 		return EX_TEMPFAIL;
2222c2aa98e2SPeter Wemm 	}
2223c2aa98e2SPeter Wemm 
2224c2aa98e2SPeter Wemm 	mci_setstat(mci, EX_OK, NULL, NULL);
222506f25ae9SGregory Neil Shapiro 	errno = 0;
222606f25ae9SGregory Neil Shapiro 	return EX_OK;
2227c2aa98e2SPeter Wemm }
222806f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
2229c2aa98e2SPeter Wemm /*
2230c2aa98e2SPeter Wemm **  MYHOSTNAME -- return the name of this host.
2231c2aa98e2SPeter Wemm **
2232c2aa98e2SPeter Wemm **	Parameters:
2233c2aa98e2SPeter Wemm **		hostbuf -- a place to return the name of this host.
2234c2aa98e2SPeter Wemm **		size -- the size of hostbuf.
2235c2aa98e2SPeter Wemm **
2236c2aa98e2SPeter Wemm **	Returns:
2237c2aa98e2SPeter Wemm **		A list of aliases for this host.
2238c2aa98e2SPeter Wemm **
2239c2aa98e2SPeter Wemm **	Side Effects:
2240c2aa98e2SPeter Wemm **		Adds numeric codes to $=w.
2241c2aa98e2SPeter Wemm */
2242c2aa98e2SPeter Wemm 
2243c2aa98e2SPeter Wemm struct hostent *
2244c2aa98e2SPeter Wemm myhostname(hostbuf, size)
2245c2aa98e2SPeter Wemm 	char hostbuf[];
2246c2aa98e2SPeter Wemm 	int size;
2247c2aa98e2SPeter Wemm {
2248c2aa98e2SPeter Wemm 	register struct hostent *hp;
2249c2aa98e2SPeter Wemm 
2250c2aa98e2SPeter Wemm 	if (gethostname(hostbuf, size) < 0)
2251c2aa98e2SPeter Wemm 	{
225206f25ae9SGregory Neil Shapiro 		(void) strlcpy(hostbuf, "localhost", size);
2253c2aa98e2SPeter Wemm 	}
225406f25ae9SGregory Neil Shapiro 	hp = sm_gethostbyname(hostbuf, InetMode);
2255c2aa98e2SPeter Wemm 	if (hp == NULL)
2256c2aa98e2SPeter Wemm 		return NULL;
2257c2aa98e2SPeter Wemm 	if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
225806f25ae9SGregory Neil Shapiro 		(void) cleanstrcpy(hostbuf, hp->h_name, size);
225906f25ae9SGregory Neil Shapiro 
226006f25ae9SGregory Neil Shapiro # if NETINFO
226106f25ae9SGregory Neil Shapiro 	if (strchr(hostbuf, '.') == NULL)
2262c2aa98e2SPeter Wemm 	{
226306f25ae9SGregory Neil Shapiro 		char *domainname;
226406f25ae9SGregory Neil Shapiro 
226506f25ae9SGregory Neil Shapiro 		domainname = ni_propval("/locations", NULL, "resolver",
226606f25ae9SGregory Neil Shapiro 					"domain", '\0');
226706f25ae9SGregory Neil Shapiro 		if (domainname != NULL &&
226806f25ae9SGregory Neil Shapiro 		    strlen(domainname) + strlen(hostbuf) + 1 < size)
226906f25ae9SGregory Neil Shapiro 		{
227006f25ae9SGregory Neil Shapiro 			(void) strlcat(hostbuf, ".", size);
227106f25ae9SGregory Neil Shapiro 			(void) strlcat(hostbuf, domainname, size);
2272c2aa98e2SPeter Wemm 		}
227306f25ae9SGregory Neil Shapiro 	}
227406f25ae9SGregory Neil Shapiro # endif /* NETINFO */
2275c2aa98e2SPeter Wemm 
2276c2aa98e2SPeter Wemm 	/*
2277c2aa98e2SPeter Wemm 	**  If there is still no dot in the name, try looking for a
2278c2aa98e2SPeter Wemm 	**  dotted alias.
2279c2aa98e2SPeter Wemm 	*/
2280c2aa98e2SPeter Wemm 
2281c2aa98e2SPeter Wemm 	if (strchr(hostbuf, '.') == NULL)
2282c2aa98e2SPeter Wemm 	{
2283c2aa98e2SPeter Wemm 		char **ha;
2284c2aa98e2SPeter Wemm 
228506f25ae9SGregory Neil Shapiro 		for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
2286c2aa98e2SPeter Wemm 		{
2287c2aa98e2SPeter Wemm 			if (strchr(*ha, '.') != NULL)
2288c2aa98e2SPeter Wemm 			{
228906f25ae9SGregory Neil Shapiro 				(void) cleanstrcpy(hostbuf, *ha, size - 1);
2290c2aa98e2SPeter Wemm 				hostbuf[size - 1] = '\0';
2291c2aa98e2SPeter Wemm 				break;
2292c2aa98e2SPeter Wemm 			}
2293c2aa98e2SPeter Wemm 		}
2294c2aa98e2SPeter Wemm 	}
2295c2aa98e2SPeter Wemm 
2296c2aa98e2SPeter Wemm 	/*
2297c2aa98e2SPeter Wemm 	**  If _still_ no dot, wait for a while and try again -- it is
2298c2aa98e2SPeter Wemm 	**  possible that some service is starting up.  This can result
2299c2aa98e2SPeter Wemm 	**  in excessive delays if the system is badly configured, but
2300c2aa98e2SPeter Wemm 	**  there really isn't a way around that, particularly given that
2301c2aa98e2SPeter Wemm 	**  the config file hasn't been read at this point.
2302c2aa98e2SPeter Wemm 	**  All in all, a bit of a mess.
2303c2aa98e2SPeter Wemm 	*/
2304c2aa98e2SPeter Wemm 
2305c2aa98e2SPeter Wemm 	if (strchr(hostbuf, '.') == NULL &&
2306c2aa98e2SPeter Wemm 	    !getcanonname(hostbuf, size, TRUE))
2307c2aa98e2SPeter Wemm 	{
2308c2aa98e2SPeter Wemm 		sm_syslog(LOG_CRIT, NOQID,
2309c2aa98e2SPeter Wemm 			  "My unqualified host name (%s) unknown; sleeping for retry",
2310c2aa98e2SPeter Wemm 			  hostbuf);
2311c2aa98e2SPeter Wemm 		message("My unqualified host name (%s) unknown; sleeping for retry",
2312c2aa98e2SPeter Wemm 			hostbuf);
231306f25ae9SGregory Neil Shapiro 		(void) sleep(60);
2314c2aa98e2SPeter Wemm 		if (!getcanonname(hostbuf, size, TRUE))
2315c2aa98e2SPeter Wemm 		{
2316c2aa98e2SPeter Wemm 			sm_syslog(LOG_ALERT, NOQID,
2317c2aa98e2SPeter Wemm 				  "unable to qualify my own domain name (%s) -- using short name",
2318c2aa98e2SPeter Wemm 				  hostbuf);
2319c2aa98e2SPeter Wemm 			message("WARNING: unable to qualify my own domain name (%s) -- using short name",
2320c2aa98e2SPeter Wemm 				hostbuf);
2321c2aa98e2SPeter Wemm 		}
2322c2aa98e2SPeter Wemm 	}
232306f25ae9SGregory Neil Shapiro 	return hp;
2324c2aa98e2SPeter Wemm }
2325c2aa98e2SPeter Wemm /*
2326c2aa98e2SPeter Wemm **  ADDRCMP -- compare two host addresses
2327c2aa98e2SPeter Wemm **
2328c2aa98e2SPeter Wemm **	Parameters:
2329c2aa98e2SPeter Wemm **		hp -- hostent structure for the first address
2330c2aa98e2SPeter Wemm **		ha -- actual first address
2331c2aa98e2SPeter Wemm **		sa -- second address
2332c2aa98e2SPeter Wemm **
2333c2aa98e2SPeter Wemm **	Returns:
2334c2aa98e2SPeter Wemm **		0 -- if ha and sa match
2335c2aa98e2SPeter Wemm **		else -- they don't match
2336c2aa98e2SPeter Wemm */
2337c2aa98e2SPeter Wemm 
233806f25ae9SGregory Neil Shapiro static int
2339c2aa98e2SPeter Wemm addrcmp(hp, ha, sa)
2340c2aa98e2SPeter Wemm 	struct hostent *hp;
2341c2aa98e2SPeter Wemm 	char *ha;
2342c2aa98e2SPeter Wemm 	SOCKADDR *sa;
2343c2aa98e2SPeter Wemm {
234406f25ae9SGregory Neil Shapiro # if NETINET6
234506f25ae9SGregory Neil Shapiro 	u_char *a;
234606f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
234706f25ae9SGregory Neil Shapiro 
2348c2aa98e2SPeter Wemm 	switch (sa->sa.sa_family)
2349c2aa98e2SPeter Wemm 	{
235006f25ae9SGregory Neil Shapiro # if NETINET
2351c2aa98e2SPeter Wemm 	  case AF_INET:
2352c2aa98e2SPeter Wemm 		if (hp->h_addrtype == AF_INET)
235306f25ae9SGregory Neil Shapiro 			return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ);
2354c2aa98e2SPeter Wemm 		break;
235506f25ae9SGregory Neil Shapiro # endif /* NETINET */
2356c2aa98e2SPeter Wemm 
235706f25ae9SGregory Neil Shapiro # if NETINET6
235806f25ae9SGregory Neil Shapiro 	  case AF_INET6:
235906f25ae9SGregory Neil Shapiro 		a = (u_char *) &sa->sin6.sin6_addr;
236006f25ae9SGregory Neil Shapiro 
236106f25ae9SGregory Neil Shapiro 		/* Straight binary comparison */
236206f25ae9SGregory Neil Shapiro 		if (hp->h_addrtype == AF_INET6)
236306f25ae9SGregory Neil Shapiro 			return memcmp(ha, a, IN6ADDRSZ);
236406f25ae9SGregory Neil Shapiro 
236506f25ae9SGregory Neil Shapiro 		/* If IPv4-mapped IPv6 address, compare the IPv4 section */
236606f25ae9SGregory Neil Shapiro 		if (hp->h_addrtype == AF_INET &&
236706f25ae9SGregory Neil Shapiro 		    IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr))
236806f25ae9SGregory Neil Shapiro 			return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ);
236906f25ae9SGregory Neil Shapiro 		break;
237006f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
2371c2aa98e2SPeter Wemm 	}
2372c2aa98e2SPeter Wemm 	return -1;
2373c2aa98e2SPeter Wemm }
2374c2aa98e2SPeter Wemm /*
237506f25ae9SGregory Neil Shapiro **  GETAUTHINFO -- get the real host name associated with a file descriptor
2376c2aa98e2SPeter Wemm **
2377c2aa98e2SPeter Wemm **	Uses RFC1413 protocol to try to get info from the other end.
2378c2aa98e2SPeter Wemm **
2379c2aa98e2SPeter Wemm **	Parameters:
2380c2aa98e2SPeter Wemm **		fd -- the descriptor
2381c2aa98e2SPeter Wemm **		may_be_forged -- an outage that is set to TRUE if the
2382c2aa98e2SPeter Wemm **			forward lookup of RealHostName does not match
2383c2aa98e2SPeter Wemm **			RealHostAddr; set to FALSE if they do match.
2384c2aa98e2SPeter Wemm **
2385c2aa98e2SPeter Wemm **	Returns:
2386c2aa98e2SPeter Wemm **		The user@host information associated with this descriptor.
2387c2aa98e2SPeter Wemm */
2388c2aa98e2SPeter Wemm 
2389c2aa98e2SPeter Wemm static jmp_buf	CtxAuthTimeout;
2390c2aa98e2SPeter Wemm 
2391c2aa98e2SPeter Wemm static void
2392c2aa98e2SPeter Wemm authtimeout()
2393c2aa98e2SPeter Wemm {
2394c2aa98e2SPeter Wemm 	longjmp(CtxAuthTimeout, 1);
2395c2aa98e2SPeter Wemm }
2396c2aa98e2SPeter Wemm 
2397c2aa98e2SPeter Wemm char *
2398c2aa98e2SPeter Wemm getauthinfo(fd, may_be_forged)
2399c2aa98e2SPeter Wemm 	int fd;
2400c2aa98e2SPeter Wemm 	bool *may_be_forged;
2401c2aa98e2SPeter Wemm {
240206f25ae9SGregory Neil Shapiro 	u_short port = 0;
2403c2aa98e2SPeter Wemm 	SOCKADDR_LEN_T falen;
2404c2aa98e2SPeter Wemm 	register char *volatile p = NULL;
2405c2aa98e2SPeter Wemm 	SOCKADDR la;
2406c2aa98e2SPeter Wemm 	SOCKADDR_LEN_T lalen;
2407c2aa98e2SPeter Wemm 	register struct servent *sp;
2408c2aa98e2SPeter Wemm 	volatile int s;
2409c2aa98e2SPeter Wemm 	int i = 0;
2410c2aa98e2SPeter Wemm 	EVENT *ev;
2411c2aa98e2SPeter Wemm 	int nleft;
2412c2aa98e2SPeter Wemm 	struct hostent *hp;
2413c2aa98e2SPeter Wemm 	char *ostype = NULL;
2414c2aa98e2SPeter Wemm 	char **ha;
2415c2aa98e2SPeter Wemm 	char ibuf[MAXNAME + 1];
2416c2aa98e2SPeter Wemm 	static char hbuf[MAXNAME * 2 + 11];
2417c2aa98e2SPeter Wemm 
2418c2aa98e2SPeter Wemm 	*may_be_forged = FALSE;
2419c2aa98e2SPeter Wemm 	falen = sizeof RealHostAddr;
2420c2aa98e2SPeter Wemm 	if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
2421c2aa98e2SPeter Wemm 	    falen <= 0 || RealHostAddr.sa.sa_family == 0)
2422c2aa98e2SPeter Wemm 	{
242306f25ae9SGregory Neil Shapiro 		if (i < 0)
242406f25ae9SGregory Neil Shapiro 		{
242506f25ae9SGregory Neil Shapiro 			/*
242606f25ae9SGregory Neil Shapiro 			**  ENOTSOCK is OK: bail on anything else, but reset
242706f25ae9SGregory Neil Shapiro 			**  errno in this case, so a mis-report doesn't
242806f25ae9SGregory Neil Shapiro 			**  happen later.
242906f25ae9SGregory Neil Shapiro 			*/
243006f25ae9SGregory Neil Shapiro 			if (errno != ENOTSOCK)
2431c2aa98e2SPeter Wemm 				return NULL;
243206f25ae9SGregory Neil Shapiro 			errno = 0;
243306f25ae9SGregory Neil Shapiro 		}
2434c2aa98e2SPeter Wemm 		(void) snprintf(hbuf, sizeof hbuf, "%s@localhost",
2435c2aa98e2SPeter Wemm 			RealUserName);
2436c2aa98e2SPeter Wemm 		if (tTd(9, 1))
243706f25ae9SGregory Neil Shapiro 			dprintf("getauthinfo: %s\n", hbuf);
2438c2aa98e2SPeter Wemm 		return hbuf;
2439c2aa98e2SPeter Wemm 	}
2440c2aa98e2SPeter Wemm 
2441c2aa98e2SPeter Wemm 	if (RealHostName == NULL)
2442c2aa98e2SPeter Wemm 	{
2443c2aa98e2SPeter Wemm 		/* translate that to a host name */
2444c2aa98e2SPeter Wemm 		RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
2445c2aa98e2SPeter Wemm 		if (strlen(RealHostName) > MAXNAME)
2446065a643dSPeter Wemm 			RealHostName[MAXNAME] = '\0';
2447c2aa98e2SPeter Wemm 	}
2448c2aa98e2SPeter Wemm 
2449c2aa98e2SPeter Wemm 	/* cross check RealHostName with forward DNS lookup */
2450c2aa98e2SPeter Wemm 	if (anynet_ntoa(&RealHostAddr)[0] == '[' ||
2451c2aa98e2SPeter Wemm 	    RealHostName[0] == '[')
2452c2aa98e2SPeter Wemm 	{
2453c2aa98e2SPeter Wemm 		/*
2454c2aa98e2SPeter Wemm 		**  address is not a socket or have an
2455c2aa98e2SPeter Wemm 		**  IP address with no forward lookup
2456c2aa98e2SPeter Wemm 		*/
2457c2aa98e2SPeter Wemm 		*may_be_forged = FALSE;
2458c2aa98e2SPeter Wemm 	}
2459c2aa98e2SPeter Wemm 	else
2460c2aa98e2SPeter Wemm 	{
2461c2aa98e2SPeter Wemm 		/* try to match the reverse against the forward lookup */
246206f25ae9SGregory Neil Shapiro 		hp = sm_gethostbyname(RealHostName,
246306f25ae9SGregory Neil Shapiro 				      RealHostAddr.sa.sa_family);
2464c2aa98e2SPeter Wemm 
2465c2aa98e2SPeter Wemm 		if (hp == NULL)
2466c2aa98e2SPeter Wemm 			*may_be_forged = TRUE;
2467c2aa98e2SPeter Wemm 		else
2468c2aa98e2SPeter Wemm 		{
2469c2aa98e2SPeter Wemm 			for (ha = hp->h_addr_list; *ha != NULL; ha++)
2470c2aa98e2SPeter Wemm 				if (addrcmp(hp, *ha, &RealHostAddr) == 0)
2471c2aa98e2SPeter Wemm 					break;
2472c2aa98e2SPeter Wemm 			*may_be_forged = *ha == NULL;
2473c2aa98e2SPeter Wemm 		}
2474c2aa98e2SPeter Wemm 	}
2475c2aa98e2SPeter Wemm 
2476c2aa98e2SPeter Wemm 	if (TimeOuts.to_ident == 0)
2477c2aa98e2SPeter Wemm 		goto noident;
2478c2aa98e2SPeter Wemm 
2479c2aa98e2SPeter Wemm 	lalen = sizeof la;
248006f25ae9SGregory Neil Shapiro 	switch (RealHostAddr.sa.sa_family)
248106f25ae9SGregory Neil Shapiro 	{
248206f25ae9SGregory Neil Shapiro # if NETINET
248306f25ae9SGregory Neil Shapiro 	  case AF_INET:
248406f25ae9SGregory Neil Shapiro 		if (getsockname(fd, &la.sa, &lalen) < 0 ||
248506f25ae9SGregory Neil Shapiro 		    lalen <= 0 ||
2486c2aa98e2SPeter Wemm 		    la.sa.sa_family != AF_INET)
2487c2aa98e2SPeter Wemm 		{
2488c2aa98e2SPeter Wemm 			/* no ident info */
2489c2aa98e2SPeter Wemm 			goto noident;
2490c2aa98e2SPeter Wemm 		}
249106f25ae9SGregory Neil Shapiro 		port = RealHostAddr.sin.sin_port;
2492c2aa98e2SPeter Wemm 
2493c2aa98e2SPeter Wemm 		/* create ident query */
2494c2aa98e2SPeter Wemm 		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
249506f25ae9SGregory Neil Shapiro 				ntohs(RealHostAddr.sin.sin_port),
249606f25ae9SGregory Neil Shapiro 				ntohs(la.sin.sin_port));
2497c2aa98e2SPeter Wemm 
2498c2aa98e2SPeter Wemm 		/* create local address */
2499c2aa98e2SPeter Wemm 		la.sin.sin_port = 0;
2500c2aa98e2SPeter Wemm 
2501c2aa98e2SPeter Wemm 		/* create foreign address */
250206f25ae9SGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
250306f25ae9SGregory Neil Shapiro 		RealHostAddr.sin.sin_port = htons(113);
250406f25ae9SGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
2505c2aa98e2SPeter Wemm 		sp = getservbyname("auth", "tcp");
2506c2aa98e2SPeter Wemm 		if (sp != NULL)
2507c2aa98e2SPeter Wemm 			RealHostAddr.sin.sin_port = sp->s_port;
2508c2aa98e2SPeter Wemm 		else
2509c2aa98e2SPeter Wemm 			RealHostAddr.sin.sin_port = htons(113);
251006f25ae9SGregory Neil Shapiro 		break;
251106f25ae9SGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
251206f25ae9SGregory Neil Shapiro # endif /* NETINET */
251306f25ae9SGregory Neil Shapiro 
251406f25ae9SGregory Neil Shapiro # if NETINET6
251506f25ae9SGregory Neil Shapiro 	  case AF_INET6:
251606f25ae9SGregory Neil Shapiro 		if (getsockname(fd, &la.sa, &lalen) < 0 ||
251706f25ae9SGregory Neil Shapiro 		    lalen <= 0 ||
251806f25ae9SGregory Neil Shapiro 		    la.sa.sa_family != AF_INET6)
251906f25ae9SGregory Neil Shapiro 		{
252006f25ae9SGregory Neil Shapiro 			/* no ident info */
252106f25ae9SGregory Neil Shapiro 			goto noident;
252206f25ae9SGregory Neil Shapiro 		}
252306f25ae9SGregory Neil Shapiro 		port = RealHostAddr.sin6.sin6_port;
252406f25ae9SGregory Neil Shapiro 
252506f25ae9SGregory Neil Shapiro 		/* create ident query */
252606f25ae9SGregory Neil Shapiro 		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
252706f25ae9SGregory Neil Shapiro 				ntohs(RealHostAddr.sin6.sin6_port),
252806f25ae9SGregory Neil Shapiro 				ntohs(la.sin6.sin6_port));
252906f25ae9SGregory Neil Shapiro 
253006f25ae9SGregory Neil Shapiro 		/* create local address */
253106f25ae9SGregory Neil Shapiro 		la.sin6.sin6_port = 0;
253206f25ae9SGregory Neil Shapiro 
253306f25ae9SGregory Neil Shapiro 		/* create foreign address */
253406f25ae9SGregory Neil Shapiro #  ifdef NO_GETSERVBYNAME
253506f25ae9SGregory Neil Shapiro 		RealHostAddr.sin6.sin6_port = htons(113);
253606f25ae9SGregory Neil Shapiro #  else /* NO_GETSERVBYNAME */
253706f25ae9SGregory Neil Shapiro 		sp = getservbyname("auth", "tcp");
253806f25ae9SGregory Neil Shapiro 		if (sp != NULL)
253906f25ae9SGregory Neil Shapiro 			RealHostAddr.sin6.sin6_port = sp->s_port;
254006f25ae9SGregory Neil Shapiro 		else
254106f25ae9SGregory Neil Shapiro 			RealHostAddr.sin6.sin6_port = htons(113);
254206f25ae9SGregory Neil Shapiro 		break;
254306f25ae9SGregory Neil Shapiro #  endif /* NO_GETSERVBYNAME */
254406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
254506f25ae9SGregory Neil Shapiro 	  default:
254606f25ae9SGregory Neil Shapiro 		/* no ident info */
254706f25ae9SGregory Neil Shapiro 		goto noident;
254806f25ae9SGregory Neil Shapiro 	}
2549c2aa98e2SPeter Wemm 
2550c2aa98e2SPeter Wemm 	s = -1;
2551c2aa98e2SPeter Wemm 	if (setjmp(CtxAuthTimeout) != 0)
2552c2aa98e2SPeter Wemm 	{
2553c2aa98e2SPeter Wemm 		if (s >= 0)
2554c2aa98e2SPeter Wemm 			(void) close(s);
2555c2aa98e2SPeter Wemm 		goto noident;
2556c2aa98e2SPeter Wemm 	}
2557c2aa98e2SPeter Wemm 
2558c2aa98e2SPeter Wemm 	/* put a timeout around the whole thing */
2559c2aa98e2SPeter Wemm 	ev = setevent(TimeOuts.to_ident, authtimeout, 0);
2560c2aa98e2SPeter Wemm 
256106f25ae9SGregory Neil Shapiro 
2562c2aa98e2SPeter Wemm 	/* connect to foreign IDENT server using same address as SMTP socket */
256306f25ae9SGregory Neil Shapiro 	s = socket(la.sa.sa_family, SOCK_STREAM, 0);
2564c2aa98e2SPeter Wemm 	if (s < 0)
2565c2aa98e2SPeter Wemm 	{
2566c2aa98e2SPeter Wemm 		clrevent(ev);
2567c2aa98e2SPeter Wemm 		goto noident;
2568c2aa98e2SPeter Wemm 	}
256906f25ae9SGregory Neil Shapiro 	if (bind(s, &la.sa, lalen) < 0 ||
257006f25ae9SGregory Neil Shapiro 	    connect(s, &RealHostAddr.sa, lalen) < 0)
2571c2aa98e2SPeter Wemm 	{
2572c2aa98e2SPeter Wemm 		goto closeident;
2573c2aa98e2SPeter Wemm 	}
2574c2aa98e2SPeter Wemm 
2575c2aa98e2SPeter Wemm 	if (tTd(9, 10))
257606f25ae9SGregory Neil Shapiro 		dprintf("getauthinfo: sent %s", ibuf);
2577c2aa98e2SPeter Wemm 
2578c2aa98e2SPeter Wemm 	/* send query */
2579c2aa98e2SPeter Wemm 	if (write(s, ibuf, strlen(ibuf)) < 0)
2580c2aa98e2SPeter Wemm 		goto closeident;
2581c2aa98e2SPeter Wemm 
2582c2aa98e2SPeter Wemm 	/* get result */
2583c2aa98e2SPeter Wemm 	p = &ibuf[0];
2584c2aa98e2SPeter Wemm 	nleft = sizeof ibuf - 1;
2585c2aa98e2SPeter Wemm 	while ((i = read(s, p, nleft)) > 0)
2586c2aa98e2SPeter Wemm 	{
2587c2aa98e2SPeter Wemm 		p += i;
2588c2aa98e2SPeter Wemm 		nleft -= i;
2589c2aa98e2SPeter Wemm 		*p = '\0';
2590c2aa98e2SPeter Wemm 		if (strchr(ibuf, '\n') != NULL)
2591c2aa98e2SPeter Wemm 			break;
2592c2aa98e2SPeter Wemm 	}
2593c2aa98e2SPeter Wemm 	(void) close(s);
2594c2aa98e2SPeter Wemm 	clrevent(ev);
2595c2aa98e2SPeter Wemm 	if (i < 0 || p == &ibuf[0])
2596c2aa98e2SPeter Wemm 		goto noident;
2597c2aa98e2SPeter Wemm 
2598c2aa98e2SPeter Wemm 	if (*--p == '\n' && *--p == '\r')
2599c2aa98e2SPeter Wemm 		p--;
2600c2aa98e2SPeter Wemm 	*++p = '\0';
2601c2aa98e2SPeter Wemm 
2602c2aa98e2SPeter Wemm 	if (tTd(9, 3))
260306f25ae9SGregory Neil Shapiro 		dprintf("getauthinfo:  got %s\n", ibuf);
2604c2aa98e2SPeter Wemm 
2605c2aa98e2SPeter Wemm 	/* parse result */
2606c2aa98e2SPeter Wemm 	p = strchr(ibuf, ':');
2607c2aa98e2SPeter Wemm 	if (p == NULL)
2608c2aa98e2SPeter Wemm 	{
2609c2aa98e2SPeter Wemm 		/* malformed response */
2610c2aa98e2SPeter Wemm 		goto noident;
2611c2aa98e2SPeter Wemm 	}
2612c2aa98e2SPeter Wemm 	while (isascii(*++p) && isspace(*p))
2613c2aa98e2SPeter Wemm 		continue;
2614c2aa98e2SPeter Wemm 	if (strncasecmp(p, "userid", 6) != 0)
2615c2aa98e2SPeter Wemm 	{
2616c2aa98e2SPeter Wemm 		/* presumably an error string */
2617c2aa98e2SPeter Wemm 		goto noident;
2618c2aa98e2SPeter Wemm 	}
2619c2aa98e2SPeter Wemm 	p += 6;
2620c2aa98e2SPeter Wemm 	while (isascii(*p) && isspace(*p))
2621c2aa98e2SPeter Wemm 		p++;
2622c2aa98e2SPeter Wemm 	if (*p++ != ':')
2623c2aa98e2SPeter Wemm 	{
2624c2aa98e2SPeter Wemm 		/* either useridxx or malformed response */
2625c2aa98e2SPeter Wemm 		goto noident;
2626c2aa98e2SPeter Wemm 	}
2627c2aa98e2SPeter Wemm 
2628c2aa98e2SPeter Wemm 	/* p now points to the OSTYPE field */
2629c2aa98e2SPeter Wemm 	while (isascii(*p) && isspace(*p))
2630c2aa98e2SPeter Wemm 		p++;
2631c2aa98e2SPeter Wemm 	ostype = p;
2632c2aa98e2SPeter Wemm 	p = strchr(p, ':');
2633c2aa98e2SPeter Wemm 	if (p == NULL)
2634c2aa98e2SPeter Wemm 	{
2635c2aa98e2SPeter Wemm 		/* malformed response */
2636c2aa98e2SPeter Wemm 		goto noident;
2637c2aa98e2SPeter Wemm 	}
2638c2aa98e2SPeter Wemm 	else
2639c2aa98e2SPeter Wemm 	{
2640c2aa98e2SPeter Wemm 		char *charset;
2641c2aa98e2SPeter Wemm 
2642c2aa98e2SPeter Wemm 		*p = '\0';
2643c2aa98e2SPeter Wemm 		charset = strchr(ostype, ',');
2644c2aa98e2SPeter Wemm 		if (charset != NULL)
2645c2aa98e2SPeter Wemm 			*charset = '\0';
2646c2aa98e2SPeter Wemm 	}
2647c2aa98e2SPeter Wemm 
2648c2aa98e2SPeter Wemm 	/* 1413 says don't do this -- but it's broken otherwise */
2649c2aa98e2SPeter Wemm 	while (isascii(*++p) && isspace(*p))
2650c2aa98e2SPeter Wemm 		continue;
2651c2aa98e2SPeter Wemm 
2652c2aa98e2SPeter Wemm 	/* p now points to the authenticated name -- copy carefully */
2653c2aa98e2SPeter Wemm 	if (strncasecmp(ostype, "other", 5) == 0 &&
2654c2aa98e2SPeter Wemm 	    (ostype[5] == ' ' || ostype[5] == '\0'))
2655c2aa98e2SPeter Wemm 	{
2656c2aa98e2SPeter Wemm 		snprintf(hbuf, sizeof hbuf, "IDENT:");
2657c2aa98e2SPeter Wemm 		cleanstrcpy(&hbuf[6], p, MAXNAME);
2658c2aa98e2SPeter Wemm 	}
2659c2aa98e2SPeter Wemm 	else
2660c2aa98e2SPeter Wemm 		cleanstrcpy(hbuf, p, MAXNAME);
2661c2aa98e2SPeter Wemm 	i = strlen(hbuf);
2662c2aa98e2SPeter Wemm 	snprintf(&hbuf[i], sizeof hbuf - i, "@%s",
2663c2aa98e2SPeter Wemm 		 RealHostName == NULL ? "localhost" : RealHostName);
2664c2aa98e2SPeter Wemm 	goto postident;
2665c2aa98e2SPeter Wemm 
2666c2aa98e2SPeter Wemm closeident:
2667c2aa98e2SPeter Wemm 	(void) close(s);
2668c2aa98e2SPeter Wemm 	clrevent(ev);
2669c2aa98e2SPeter Wemm 
2670c2aa98e2SPeter Wemm noident:
267106f25ae9SGregory Neil Shapiro 	/* put back the original incoming port */
267206f25ae9SGregory Neil Shapiro 	switch (RealHostAddr.sa.sa_family)
267306f25ae9SGregory Neil Shapiro 	{
267406f25ae9SGregory Neil Shapiro # if NETINET
267506f25ae9SGregory Neil Shapiro 	  case AF_INET:
267606f25ae9SGregory Neil Shapiro 		if (port > 0)
267706f25ae9SGregory Neil Shapiro 			RealHostAddr.sin.sin_port = port;
267806f25ae9SGregory Neil Shapiro 		break;
267906f25ae9SGregory Neil Shapiro # endif /* NETINET */
268006f25ae9SGregory Neil Shapiro 
268106f25ae9SGregory Neil Shapiro # if NETINET6
268206f25ae9SGregory Neil Shapiro 	  case AF_INET6:
268306f25ae9SGregory Neil Shapiro 		if (port > 0)
268406f25ae9SGregory Neil Shapiro 			RealHostAddr.sin6.sin6_port = port;
268506f25ae9SGregory Neil Shapiro 		break;
268606f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
268706f25ae9SGregory Neil Shapiro 	}
268806f25ae9SGregory Neil Shapiro 
2689c2aa98e2SPeter Wemm 	if (RealHostName == NULL)
2690c2aa98e2SPeter Wemm 	{
2691c2aa98e2SPeter Wemm 		if (tTd(9, 1))
269206f25ae9SGregory Neil Shapiro 			dprintf("getauthinfo: NULL\n");
2693c2aa98e2SPeter Wemm 		return NULL;
2694c2aa98e2SPeter Wemm 	}
2695c2aa98e2SPeter Wemm 	snprintf(hbuf, sizeof hbuf, "%s", RealHostName);
2696c2aa98e2SPeter Wemm 
2697c2aa98e2SPeter Wemm postident:
2698c2aa98e2SPeter Wemm # if IP_SRCROUTE
2699c2aa98e2SPeter Wemm #  ifndef GET_IPOPT_DST
2700c2aa98e2SPeter Wemm #   define GET_IPOPT_DST(dst)	(dst)
270106f25ae9SGregory Neil Shapiro #  endif /* ! GET_IPOPT_DST */
2702c2aa98e2SPeter Wemm 	/*
2703c2aa98e2SPeter Wemm 	**  Extract IP source routing information.
2704c2aa98e2SPeter Wemm 	**
2705c2aa98e2SPeter Wemm 	**	Format of output for a connection from site a through b
2706c2aa98e2SPeter Wemm 	**	through c to d:
2707c2aa98e2SPeter Wemm 	**		loose:      @site-c@site-b:site-a
2708c2aa98e2SPeter Wemm 	**		strict:	   !@site-c@site-b:site-a
2709c2aa98e2SPeter Wemm 	**
2710c2aa98e2SPeter Wemm 	**	o - pointer within ipopt_list structure.
2711c2aa98e2SPeter Wemm 	**	q - pointer within ls/ss rr route data
2712c2aa98e2SPeter Wemm 	**	p - pointer to hbuf
2713c2aa98e2SPeter Wemm 	*/
2714c2aa98e2SPeter Wemm 
2715c2aa98e2SPeter Wemm 	if (RealHostAddr.sa.sa_family == AF_INET)
2716c2aa98e2SPeter Wemm 	{
2717c2aa98e2SPeter Wemm 		SOCKOPT_LEN_T ipoptlen;
2718c2aa98e2SPeter Wemm 		int j;
2719c2aa98e2SPeter Wemm 		u_char *q;
2720c2aa98e2SPeter Wemm 		u_char *o;
2721c2aa98e2SPeter Wemm 		int l;
272206f25ae9SGregory Neil Shapiro 		struct IPOPTION ipopt;
2723c2aa98e2SPeter Wemm 
2724c2aa98e2SPeter Wemm 		ipoptlen = sizeof ipopt;
2725c2aa98e2SPeter Wemm 		if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
2726c2aa98e2SPeter Wemm 			       (char *) &ipopt, &ipoptlen) < 0)
2727c2aa98e2SPeter Wemm 			goto noipsr;
2728c2aa98e2SPeter Wemm 		if (ipoptlen == 0)
2729c2aa98e2SPeter Wemm 			goto noipsr;
273006f25ae9SGregory Neil Shapiro 		o = (u_char *) ipopt.IP_LIST;
2731c2aa98e2SPeter Wemm 		while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
2732c2aa98e2SPeter Wemm 		{
2733c2aa98e2SPeter Wemm 			switch (*o)
2734c2aa98e2SPeter Wemm 			{
2735c2aa98e2SPeter Wemm 			  case IPOPT_EOL:
2736c2aa98e2SPeter Wemm 				o = NULL;
2737c2aa98e2SPeter Wemm 				break;
2738c2aa98e2SPeter Wemm 
2739c2aa98e2SPeter Wemm 			  case IPOPT_NOP:
2740c2aa98e2SPeter Wemm 				o++;
2741c2aa98e2SPeter Wemm 				break;
2742c2aa98e2SPeter Wemm 
2743c2aa98e2SPeter Wemm 			  case IPOPT_SSRR:
2744c2aa98e2SPeter Wemm 			  case IPOPT_LSRR:
2745c2aa98e2SPeter Wemm 				/*
2746c2aa98e2SPeter Wemm 				**  Source routing.
2747c2aa98e2SPeter Wemm 				**	o[0] is the option type (loose/strict).
2748c2aa98e2SPeter Wemm 				**	o[1] is the length of this option,
2749c2aa98e2SPeter Wemm 				**		including option type and
2750c2aa98e2SPeter Wemm 				**		length.
2751c2aa98e2SPeter Wemm 				**	o[2] is the pointer into the route
2752c2aa98e2SPeter Wemm 				**		data.
2753c2aa98e2SPeter Wemm 				**	o[3] begins the route data.
2754c2aa98e2SPeter Wemm 				*/
2755c2aa98e2SPeter Wemm 
2756c2aa98e2SPeter Wemm 				p = &hbuf[strlen(hbuf)];
2757c2aa98e2SPeter Wemm 				l = sizeof hbuf - (hbuf - p) - 6;
2758c2aa98e2SPeter Wemm 				snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
2759c2aa98e2SPeter Wemm 				    *o == IPOPT_SSRR ? "!" : "",
2760c2aa98e2SPeter Wemm 				    l > 240 ? 120 : l / 2,
276106f25ae9SGregory Neil Shapiro 				    inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST)));
2762c2aa98e2SPeter Wemm 				i = strlen(p);
2763c2aa98e2SPeter Wemm 				p += i;
2764c2aa98e2SPeter Wemm 				l -= strlen(p);
2765c2aa98e2SPeter Wemm 
2766c2aa98e2SPeter Wemm 				j = o[1] / sizeof(struct in_addr) - 1;
2767c2aa98e2SPeter Wemm 
2768c2aa98e2SPeter Wemm 				/* q skips length and router pointer to data */
2769c2aa98e2SPeter Wemm 				q = &o[3];
2770c2aa98e2SPeter Wemm 				for ( ; j >= 0; j--)
2771c2aa98e2SPeter Wemm 				{
277206f25ae9SGregory Neil Shapiro 					struct in_addr addr;
277306f25ae9SGregory Neil Shapiro 
2774c2aa98e2SPeter Wemm 					memcpy(&addr, q, sizeof(addr));
2775c2aa98e2SPeter Wemm 					snprintf(p, SPACELEFT(hbuf, p),
2776c2aa98e2SPeter Wemm 						 "%c%.*s",
2777c2aa98e2SPeter Wemm 						 j != 0 ? '@' : ':',
2778c2aa98e2SPeter Wemm 						 l > 240 ? 120 :
2779c2aa98e2SPeter Wemm 						 j == 0 ? l : l / 2,
2780c2aa98e2SPeter Wemm 						 inet_ntoa(addr));
2781c2aa98e2SPeter Wemm 					i = strlen(p);
2782c2aa98e2SPeter Wemm 					p += i;
2783c2aa98e2SPeter Wemm 					l -= i + 1;
2784c2aa98e2SPeter Wemm 					q += sizeof(struct in_addr);
2785c2aa98e2SPeter Wemm 				}
2786c2aa98e2SPeter Wemm 				o += o[1];
2787c2aa98e2SPeter Wemm 				break;
2788c2aa98e2SPeter Wemm 
2789c2aa98e2SPeter Wemm 			  default:
2790c2aa98e2SPeter Wemm 				/* Skip over option */
2791c2aa98e2SPeter Wemm 				o += o[1];
2792c2aa98e2SPeter Wemm 				break;
2793c2aa98e2SPeter Wemm 			}
2794c2aa98e2SPeter Wemm 		}
2795c2aa98e2SPeter Wemm 		snprintf(p, SPACELEFT(hbuf, p), "]");
2796c2aa98e2SPeter Wemm 		goto postipsr;
2797c2aa98e2SPeter Wemm 	}
2798c2aa98e2SPeter Wemm 
2799c2aa98e2SPeter Wemm noipsr:
280006f25ae9SGregory Neil Shapiro # endif /* IP_SRCROUTE */
2801c2aa98e2SPeter Wemm 	if (RealHostName != NULL && RealHostName[0] != '[')
2802c2aa98e2SPeter Wemm 	{
2803c2aa98e2SPeter Wemm 		p = &hbuf[strlen(hbuf)];
2804c2aa98e2SPeter Wemm 		(void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
2805c2aa98e2SPeter Wemm 			anynet_ntoa(&RealHostAddr));
2806c2aa98e2SPeter Wemm 	}
2807c2aa98e2SPeter Wemm 	if (*may_be_forged)
2808c2aa98e2SPeter Wemm 	{
2809c2aa98e2SPeter Wemm 		p = &hbuf[strlen(hbuf)];
2810c2aa98e2SPeter Wemm 		(void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
2811c2aa98e2SPeter Wemm 	}
2812c2aa98e2SPeter Wemm 
2813c2aa98e2SPeter Wemm # if IP_SRCROUTE
2814c2aa98e2SPeter Wemm postipsr:
281506f25ae9SGregory Neil Shapiro # endif /* IP_SRCROUTE */
2816c2aa98e2SPeter Wemm 	if (tTd(9, 1))
281706f25ae9SGregory Neil Shapiro 		dprintf("getauthinfo: %s\n", hbuf);
281806f25ae9SGregory Neil Shapiro 
281906f25ae9SGregory Neil Shapiro 	/* put back the original incoming port */
282006f25ae9SGregory Neil Shapiro 	switch (RealHostAddr.sa.sa_family)
282106f25ae9SGregory Neil Shapiro 	{
282206f25ae9SGregory Neil Shapiro # if NETINET
282306f25ae9SGregory Neil Shapiro 	  case AF_INET:
282406f25ae9SGregory Neil Shapiro 		if (port > 0)
282506f25ae9SGregory Neil Shapiro 			RealHostAddr.sin.sin_port = port;
282606f25ae9SGregory Neil Shapiro 		break;
282706f25ae9SGregory Neil Shapiro # endif /* NETINET */
282806f25ae9SGregory Neil Shapiro 
282906f25ae9SGregory Neil Shapiro # if NETINET6
283006f25ae9SGregory Neil Shapiro 	  case AF_INET6:
283106f25ae9SGregory Neil Shapiro 		if (port > 0)
283206f25ae9SGregory Neil Shapiro 			RealHostAddr.sin6.sin6_port = port;
283306f25ae9SGregory Neil Shapiro 		break;
283406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
283506f25ae9SGregory Neil Shapiro 	}
283606f25ae9SGregory Neil Shapiro 
2837c2aa98e2SPeter Wemm 	return hbuf;
2838c2aa98e2SPeter Wemm }
2839c2aa98e2SPeter Wemm /*
2840c2aa98e2SPeter Wemm **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
2841c2aa98e2SPeter Wemm **
2842c2aa98e2SPeter Wemm **	Parameters:
2843c2aa98e2SPeter Wemm **		map -- a pointer to this map.
2844c2aa98e2SPeter Wemm **		name -- the (presumably unqualified) hostname.
2845c2aa98e2SPeter Wemm **		av -- unused -- for compatibility with other mapping
2846c2aa98e2SPeter Wemm **			functions.
2847c2aa98e2SPeter Wemm **		statp -- an exit status (out parameter) -- set to
2848c2aa98e2SPeter Wemm **			EX_TEMPFAIL if the name server is unavailable.
2849c2aa98e2SPeter Wemm **
2850c2aa98e2SPeter Wemm **	Returns:
2851c2aa98e2SPeter Wemm **		The mapping, if found.
2852c2aa98e2SPeter Wemm **		NULL if no mapping found.
2853c2aa98e2SPeter Wemm **
2854c2aa98e2SPeter Wemm **	Side Effects:
2855c2aa98e2SPeter Wemm **		Looks up the host specified in hbuf.  If it is not
2856c2aa98e2SPeter Wemm **		the canonical name for that host, return the canonical
2857c2aa98e2SPeter Wemm **		name (unless MF_MATCHONLY is set, which will cause the
2858c2aa98e2SPeter Wemm **		status only to be returned).
2859c2aa98e2SPeter Wemm */
2860c2aa98e2SPeter Wemm 
2861c2aa98e2SPeter Wemm char *
2862c2aa98e2SPeter Wemm host_map_lookup(map, name, av, statp)
2863c2aa98e2SPeter Wemm 	MAP *map;
2864c2aa98e2SPeter Wemm 	char *name;
2865c2aa98e2SPeter Wemm 	char **av;
2866c2aa98e2SPeter Wemm 	int *statp;
2867c2aa98e2SPeter Wemm {
2868c2aa98e2SPeter Wemm 	register struct hostent *hp;
286906f25ae9SGregory Neil Shapiro # if NETINET
2870c2aa98e2SPeter Wemm 	struct in_addr in_addr;
287106f25ae9SGregory Neil Shapiro # endif /* NETINET */
287206f25ae9SGregory Neil Shapiro # if NETINET6
287306f25ae9SGregory Neil Shapiro 	struct in6_addr in6_addr;
287406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
287506f25ae9SGregory Neil Shapiro 	char *cp, *ans = NULL;
2876c2aa98e2SPeter Wemm 	register STAB *s;
2877c2aa98e2SPeter Wemm 	char hbuf[MAXNAME + 1];
2878c2aa98e2SPeter Wemm 
2879c2aa98e2SPeter Wemm 	/*
2880c2aa98e2SPeter Wemm 	**  See if we have already looked up this name.  If so, just
2881c2aa98e2SPeter Wemm 	**  return it.
2882c2aa98e2SPeter Wemm 	*/
2883c2aa98e2SPeter Wemm 
2884c2aa98e2SPeter Wemm 	s = stab(name, ST_NAMECANON, ST_ENTER);
2885c2aa98e2SPeter Wemm 	if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
2886c2aa98e2SPeter Wemm 	{
2887c2aa98e2SPeter Wemm 		if (tTd(9, 1))
288806f25ae9SGregory Neil Shapiro 			dprintf("host_map_lookup(%s) => CACHE %s\n",
2889c2aa98e2SPeter Wemm 				name,
2890c2aa98e2SPeter Wemm 				s->s_namecanon.nc_cname == NULL
2891c2aa98e2SPeter Wemm 					? "NULL"
2892c2aa98e2SPeter Wemm 					: s->s_namecanon.nc_cname);
2893c2aa98e2SPeter Wemm 		errno = s->s_namecanon.nc_errno;
2894c2aa98e2SPeter Wemm # if NAMED_BIND
2895c2aa98e2SPeter Wemm 		h_errno = s->s_namecanon.nc_herrno;
289606f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
2897c2aa98e2SPeter Wemm 		*statp = s->s_namecanon.nc_stat;
2898c2aa98e2SPeter Wemm 		if (*statp == EX_TEMPFAIL)
2899c2aa98e2SPeter Wemm 		{
2900c2aa98e2SPeter Wemm 			CurEnv->e_status = "4.4.3";
2901c2aa98e2SPeter Wemm 			message("851 %s: Name server timeout",
2902c2aa98e2SPeter Wemm 				shortenstring(name, 33));
2903c2aa98e2SPeter Wemm 		}
2904c2aa98e2SPeter Wemm 		if (*statp != EX_OK)
2905c2aa98e2SPeter Wemm 			return NULL;
2906c2aa98e2SPeter Wemm 		if (s->s_namecanon.nc_cname == NULL)
2907c2aa98e2SPeter Wemm 		{
2908c2aa98e2SPeter Wemm 			syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d",
2909c2aa98e2SPeter Wemm 			       name,
2910c2aa98e2SPeter Wemm 			       s->s_namecanon.nc_errno,
2911c2aa98e2SPeter Wemm 			       s->s_namecanon.nc_herrno);
2912c2aa98e2SPeter Wemm 			return NULL;
2913c2aa98e2SPeter Wemm 		}
2914c2aa98e2SPeter Wemm 		if (bitset(MF_MATCHONLY, map->map_mflags))
2915c2aa98e2SPeter Wemm 			cp = map_rewrite(map, name, strlen(name), NULL);
2916c2aa98e2SPeter Wemm 		else
2917c2aa98e2SPeter Wemm 			cp = map_rewrite(map,
2918c2aa98e2SPeter Wemm 					 s->s_namecanon.nc_cname,
2919c2aa98e2SPeter Wemm 					 strlen(s->s_namecanon.nc_cname),
2920c2aa98e2SPeter Wemm 					 av);
2921c2aa98e2SPeter Wemm 		return cp;
2922c2aa98e2SPeter Wemm 	}
2923c2aa98e2SPeter Wemm 
2924c2aa98e2SPeter Wemm 	/*
2925c2aa98e2SPeter Wemm 	**  If we are running without a regular network connection (usually
2926c2aa98e2SPeter Wemm 	**  dial-on-demand) and we are just queueing, we want to avoid DNS
2927c2aa98e2SPeter Wemm 	**  lookups because those could try to connect to a server.
2928c2aa98e2SPeter Wemm 	*/
2929c2aa98e2SPeter Wemm 
293006f25ae9SGregory Neil Shapiro 	if (CurEnv->e_sendmode == SM_DEFER &&
293106f25ae9SGregory Neil Shapiro 	    bitset(MF_DEFER, map->map_mflags))
2932c2aa98e2SPeter Wemm 	{
2933c2aa98e2SPeter Wemm 		if (tTd(9, 1))
293406f25ae9SGregory Neil Shapiro 			dprintf("host_map_lookup(%s) => DEFERRED\n", name);
2935c2aa98e2SPeter Wemm 		*statp = EX_TEMPFAIL;
2936c2aa98e2SPeter Wemm 		return NULL;
2937c2aa98e2SPeter Wemm 	}
2938c2aa98e2SPeter Wemm 
2939c2aa98e2SPeter Wemm 	/*
2940c2aa98e2SPeter Wemm 	**  If first character is a bracket, then it is an address
2941c2aa98e2SPeter Wemm 	**  lookup.  Address is copied into a temporary buffer to
2942c2aa98e2SPeter Wemm 	**  strip the brackets and to preserve name if address is
2943c2aa98e2SPeter Wemm 	**  unknown.
2944c2aa98e2SPeter Wemm 	*/
2945c2aa98e2SPeter Wemm 
294606f25ae9SGregory Neil Shapiro 	if (tTd(9, 1))
294706f25ae9SGregory Neil Shapiro 		dprintf("host_map_lookup(%s) => ", name);
2948c2aa98e2SPeter Wemm 	if (*name != '[')
2949c2aa98e2SPeter Wemm 	{
2950c2aa98e2SPeter Wemm 		snprintf(hbuf, sizeof hbuf, "%s", name);
2951c2aa98e2SPeter Wemm 		if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
295206f25ae9SGregory Neil Shapiro 			ans = hbuf;
2953c2aa98e2SPeter Wemm 	}
2954c2aa98e2SPeter Wemm 	else
2955c2aa98e2SPeter Wemm 	{
295606f25ae9SGregory Neil Shapiro 		if ((cp = strchr(name, ']')) == NULL)
295706f25ae9SGregory Neil Shapiro 			return NULL;
295806f25ae9SGregory Neil Shapiro 		*cp = '\0';
295906f25ae9SGregory Neil Shapiro 
296006f25ae9SGregory Neil Shapiro 		hp = NULL;
296106f25ae9SGregory Neil Shapiro # if NETINET
296206f25ae9SGregory Neil Shapiro 		if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE)
296306f25ae9SGregory Neil Shapiro 			hp = sm_gethostbyaddr((char *)&in_addr,
296406f25ae9SGregory Neil Shapiro 					      INADDRSZ, AF_INET);
296506f25ae9SGregory Neil Shapiro # endif /* NETINET */
296606f25ae9SGregory Neil Shapiro # if NETINET6
296706f25ae9SGregory Neil Shapiro 		if (hp == NULL &&
296806f25ae9SGregory Neil Shapiro 		    inet_pton(AF_INET6, &name[1], &in6_addr) == 1)
296906f25ae9SGregory Neil Shapiro 			hp = sm_gethostbyaddr((char *)&in6_addr,
297006f25ae9SGregory Neil Shapiro 					      IN6ADDRSZ, AF_INET6);
297106f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
297206f25ae9SGregory Neil Shapiro 		*cp = ']';
297306f25ae9SGregory Neil Shapiro 
297406f25ae9SGregory Neil Shapiro 		if (hp != NULL)
297506f25ae9SGregory Neil Shapiro 		{
297606f25ae9SGregory Neil Shapiro 			/* found a match -- copy out */
297706f25ae9SGregory Neil Shapiro 			ans = denlstring((char *) hp->h_name, TRUE, TRUE);
297806f25ae9SGregory Neil Shapiro 		}
297906f25ae9SGregory Neil Shapiro 	}
298006f25ae9SGregory Neil Shapiro 
298106f25ae9SGregory Neil Shapiro 	s->s_namecanon.nc_flags |= NCF_VALID;	/* will be soon */
298206f25ae9SGregory Neil Shapiro 
298306f25ae9SGregory Neil Shapiro 	/* Found an answer */
298406f25ae9SGregory Neil Shapiro 	if (ans != NULL)
298506f25ae9SGregory Neil Shapiro 	{
298606f25ae9SGregory Neil Shapiro 		s->s_namecanon.nc_stat = *statp = EX_OK;
298706f25ae9SGregory Neil Shapiro 		s->s_namecanon.nc_cname = newstr(ans);
298806f25ae9SGregory Neil Shapiro 		if (bitset(MF_MATCHONLY, map->map_mflags))
298906f25ae9SGregory Neil Shapiro 			cp = map_rewrite(map, name, strlen(name), NULL);
299006f25ae9SGregory Neil Shapiro 		else
299106f25ae9SGregory Neil Shapiro 			cp = map_rewrite(map, ans, strlen(ans), av);
299206f25ae9SGregory Neil Shapiro 		return cp;
299306f25ae9SGregory Neil Shapiro 	}
299406f25ae9SGregory Neil Shapiro 
299506f25ae9SGregory Neil Shapiro 
299606f25ae9SGregory Neil Shapiro 	/* No match found */
2997c2aa98e2SPeter Wemm 	s->s_namecanon.nc_errno = errno;
2998c2aa98e2SPeter Wemm # if NAMED_BIND
2999c2aa98e2SPeter Wemm 	s->s_namecanon.nc_herrno = h_errno;
3000c2aa98e2SPeter Wemm 	if (tTd(9, 1))
300106f25ae9SGregory Neil Shapiro 		dprintf("FAIL (%d)\n", h_errno);
3002c2aa98e2SPeter Wemm 	switch (h_errno)
3003c2aa98e2SPeter Wemm 	{
3004c2aa98e2SPeter Wemm 	  case TRY_AGAIN:
3005c2aa98e2SPeter Wemm 		if (UseNameServer)
3006c2aa98e2SPeter Wemm 		{
3007c2aa98e2SPeter Wemm 			CurEnv->e_status = "4.4.3";
3008c2aa98e2SPeter Wemm 			message("851 %s: Name server timeout",
3009c2aa98e2SPeter Wemm 				shortenstring(name, 33));
3010c2aa98e2SPeter Wemm 		}
3011c2aa98e2SPeter Wemm 		*statp = EX_TEMPFAIL;
3012c2aa98e2SPeter Wemm 		break;
3013c2aa98e2SPeter Wemm 
3014c2aa98e2SPeter Wemm 	  case HOST_NOT_FOUND:
3015c2aa98e2SPeter Wemm 	  case NO_DATA:
3016c2aa98e2SPeter Wemm 		*statp = EX_NOHOST;
3017c2aa98e2SPeter Wemm 		break;
3018c2aa98e2SPeter Wemm 
3019c2aa98e2SPeter Wemm 	  case NO_RECOVERY:
3020c2aa98e2SPeter Wemm 		*statp = EX_SOFTWARE;
3021c2aa98e2SPeter Wemm 		break;
3022c2aa98e2SPeter Wemm 
3023c2aa98e2SPeter Wemm 	  default:
3024c2aa98e2SPeter Wemm 		*statp = EX_UNAVAILABLE;
3025c2aa98e2SPeter Wemm 		break;
3026c2aa98e2SPeter Wemm 	}
302706f25ae9SGregory Neil Shapiro # else /* NAMED_BIND */
3028c2aa98e2SPeter Wemm 	if (tTd(9, 1))
302906f25ae9SGregory Neil Shapiro 		dprintf("FAIL\n");
3030c2aa98e2SPeter Wemm 	*statp = EX_NOHOST;
303106f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
3032c2aa98e2SPeter Wemm 	s->s_namecanon.nc_stat = *statp;
3033c2aa98e2SPeter Wemm 	return NULL;
3034c2aa98e2SPeter Wemm }
3035c2aa98e2SPeter Wemm #else /* DAEMON */
3036c2aa98e2SPeter Wemm /* code for systems without sophisticated networking */
3037c2aa98e2SPeter Wemm 
3038c2aa98e2SPeter Wemm /*
3039c2aa98e2SPeter Wemm **  MYHOSTNAME -- stub version for case of no daemon code.
3040c2aa98e2SPeter Wemm **
3041c2aa98e2SPeter Wemm **	Can't convert to upper case here because might be a UUCP name.
3042c2aa98e2SPeter Wemm **
3043c2aa98e2SPeter Wemm **	Mark, you can change this to be anything you want......
3044c2aa98e2SPeter Wemm */
3045c2aa98e2SPeter Wemm 
3046c2aa98e2SPeter Wemm char **
3047c2aa98e2SPeter Wemm myhostname(hostbuf, size)
3048c2aa98e2SPeter Wemm 	char hostbuf[];
3049c2aa98e2SPeter Wemm 	int size;
3050c2aa98e2SPeter Wemm {
3051c2aa98e2SPeter Wemm 	register FILE *f;
3052c2aa98e2SPeter Wemm 
3053c2aa98e2SPeter Wemm 	hostbuf[0] = '\0';
3054c2aa98e2SPeter Wemm 	f = fopen("/usr/include/whoami", "r");
3055c2aa98e2SPeter Wemm 	if (f != NULL)
3056c2aa98e2SPeter Wemm 	{
3057c2aa98e2SPeter Wemm 		(void) fgets(hostbuf, size, f);
3058c2aa98e2SPeter Wemm 		fixcrlf(hostbuf, TRUE);
3059c2aa98e2SPeter Wemm 		(void) fclose(f);
3060c2aa98e2SPeter Wemm 	}
306106f25ae9SGregory Neil Shapiro 	return NULL;
3062c2aa98e2SPeter Wemm }
3063c2aa98e2SPeter Wemm /*
306406f25ae9SGregory Neil Shapiro **  GETAUTHINFO -- get the real host name associated with a file descriptor
3065c2aa98e2SPeter Wemm **
3066c2aa98e2SPeter Wemm **	Parameters:
3067c2aa98e2SPeter Wemm **		fd -- the descriptor
3068c2aa98e2SPeter Wemm **		may_be_forged -- an outage that is set to TRUE if the
3069c2aa98e2SPeter Wemm **			forward lookup of RealHostName does not match
3070c2aa98e2SPeter Wemm **			RealHostAddr; set to FALSE if they do match.
3071c2aa98e2SPeter Wemm **
3072c2aa98e2SPeter Wemm **	Returns:
3073c2aa98e2SPeter Wemm **		The host name associated with this descriptor, if it can
3074c2aa98e2SPeter Wemm **			be determined.
3075c2aa98e2SPeter Wemm **		NULL otherwise.
3076c2aa98e2SPeter Wemm **
3077c2aa98e2SPeter Wemm **	Side Effects:
3078c2aa98e2SPeter Wemm **		none
3079c2aa98e2SPeter Wemm */
3080c2aa98e2SPeter Wemm 
3081c2aa98e2SPeter Wemm char *
3082c2aa98e2SPeter Wemm getauthinfo(fd, may_be_forged)
3083c2aa98e2SPeter Wemm 	int fd;
3084c2aa98e2SPeter Wemm 	bool *may_be_forged;
3085c2aa98e2SPeter Wemm {
3086c2aa98e2SPeter Wemm 	*may_be_forged = FALSE;
3087c2aa98e2SPeter Wemm 	return NULL;
3088c2aa98e2SPeter Wemm }
3089c2aa98e2SPeter Wemm /*
309006f25ae9SGregory Neil Shapiro **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
3091c2aa98e2SPeter Wemm **
3092c2aa98e2SPeter Wemm **	Parameters:
3093c2aa98e2SPeter Wemm **		map -- a pointer to the database map.
3094c2aa98e2SPeter Wemm **		name -- a buffer containing a hostname.
3095c2aa98e2SPeter Wemm **		avp -- a pointer to a (cf file defined) argument vector.
3096c2aa98e2SPeter Wemm **		statp -- an exit status (out parameter).
3097c2aa98e2SPeter Wemm **
3098c2aa98e2SPeter Wemm **	Returns:
3099c2aa98e2SPeter Wemm **		mapped host name
3100c2aa98e2SPeter Wemm **		FALSE otherwise.
3101c2aa98e2SPeter Wemm **
3102c2aa98e2SPeter Wemm **	Side Effects:
3103c2aa98e2SPeter Wemm **		Looks up the host specified in name.  If it is not
3104c2aa98e2SPeter Wemm **		the canonical name for that host, replace it with
3105c2aa98e2SPeter Wemm **		the canonical name.  If the name is unknown, or it
3106c2aa98e2SPeter Wemm **		is already the canonical name, leave it unchanged.
3107c2aa98e2SPeter Wemm */
3108c2aa98e2SPeter Wemm 
3109c2aa98e2SPeter Wemm /*ARGSUSED*/
3110c2aa98e2SPeter Wemm char *
3111c2aa98e2SPeter Wemm host_map_lookup(map, name, avp, statp)
3112c2aa98e2SPeter Wemm 	MAP *map;
3113c2aa98e2SPeter Wemm 	char *name;
3114c2aa98e2SPeter Wemm 	char **avp;
3115c2aa98e2SPeter Wemm 	char *statp;
3116c2aa98e2SPeter Wemm {
311706f25ae9SGregory Neil Shapiro 	register struct hostent *hp = NULL;
3118c2aa98e2SPeter Wemm 	char *cp;
3119c2aa98e2SPeter Wemm 
312006f25ae9SGregory Neil Shapiro 	hp = sm_gethostbyname(name, InetMode);
312106f25ae9SGregory Neil Shapiro 	if (hp == NULL && InetMode != AF_INET)
312206f25ae9SGregory Neil Shapiro 		hp = sm_gethostbyname(name, AF_INET);
3123c2aa98e2SPeter Wemm 	if (hp == NULL)
3124c2aa98e2SPeter Wemm 	{
312506f25ae9SGregory Neil Shapiro # if NAMED_BIND
312606f25ae9SGregory Neil Shapiro 		if (tTd(9, 1))
312706f25ae9SGregory Neil Shapiro 			dprintf("FAIL (%d)\n", h_errno);
312806f25ae9SGregory Neil Shapiro 		switch (h_errno)
312906f25ae9SGregory Neil Shapiro 		{
313006f25ae9SGregory Neil Shapiro 		  case TRY_AGAIN:
313106f25ae9SGregory Neil Shapiro 			if (UseNameServer)
313206f25ae9SGregory Neil Shapiro 			{
313306f25ae9SGregory Neil Shapiro 				CurEnv->e_status = "4.4.3";
313406f25ae9SGregory Neil Shapiro 				message("851 %s: Name server timeout",
313506f25ae9SGregory Neil Shapiro 					shortenstring(name, 33));
313606f25ae9SGregory Neil Shapiro 			}
313706f25ae9SGregory Neil Shapiro 			*statp = EX_TEMPFAIL;
313806f25ae9SGregory Neil Shapiro 			break;
313906f25ae9SGregory Neil Shapiro 
314006f25ae9SGregory Neil Shapiro 		  case HOST_NOT_FOUND:
314106f25ae9SGregory Neil Shapiro 		  case NO_DATA:
3142c2aa98e2SPeter Wemm 			*statp = EX_NOHOST;
314306f25ae9SGregory Neil Shapiro 			break;
314406f25ae9SGregory Neil Shapiro 
314506f25ae9SGregory Neil Shapiro 		  case NO_RECOVERY:
314606f25ae9SGregory Neil Shapiro 			*statp = EX_SOFTWARE;
314706f25ae9SGregory Neil Shapiro 			break;
314806f25ae9SGregory Neil Shapiro 
314906f25ae9SGregory Neil Shapiro 		  default:
315006f25ae9SGregory Neil Shapiro 			*statp = EX_UNAVAILABLE;
315106f25ae9SGregory Neil Shapiro 			break;
315206f25ae9SGregory Neil Shapiro 		}
315306f25ae9SGregory Neil Shapiro #else /* NAMED_BIND */
315406f25ae9SGregory Neil Shapiro 		*statp = EX_NOHOST;
315506f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */
3156c2aa98e2SPeter Wemm 		return NULL;
3157c2aa98e2SPeter Wemm 	}
3158c2aa98e2SPeter Wemm 	if (bitset(MF_MATCHONLY, map->map_mflags))
3159c2aa98e2SPeter Wemm 		cp = map_rewrite(map, name, strlen(name), NULL);
3160c2aa98e2SPeter Wemm 	else
3161c2aa98e2SPeter Wemm 		cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp);
3162c2aa98e2SPeter Wemm 	return cp;
3163c2aa98e2SPeter Wemm }
3164c2aa98e2SPeter Wemm 
3165c2aa98e2SPeter Wemm #endif /* DAEMON */
3166c2aa98e2SPeter Wemm /*
3167c2aa98e2SPeter Wemm **  HOST_MAP_INIT -- initialize host class structures
3168c2aa98e2SPeter Wemm */
3169c2aa98e2SPeter Wemm 
3170c2aa98e2SPeter Wemm bool
3171c2aa98e2SPeter Wemm host_map_init(map, args)
3172c2aa98e2SPeter Wemm 	MAP *map;
3173c2aa98e2SPeter Wemm 	char *args;
3174c2aa98e2SPeter Wemm {
3175c2aa98e2SPeter Wemm 	register char *p = args;
3176c2aa98e2SPeter Wemm 
3177c2aa98e2SPeter Wemm 	for (;;)
3178c2aa98e2SPeter Wemm 	{
3179c2aa98e2SPeter Wemm 		while (isascii(*p) && isspace(*p))
3180c2aa98e2SPeter Wemm 			p++;
3181c2aa98e2SPeter Wemm 		if (*p != '-')
3182c2aa98e2SPeter Wemm 			break;
3183c2aa98e2SPeter Wemm 		switch (*++p)
3184c2aa98e2SPeter Wemm 		{
3185c2aa98e2SPeter Wemm 		  case 'a':
3186c2aa98e2SPeter Wemm 			map->map_app = ++p;
3187c2aa98e2SPeter Wemm 			break;
3188c2aa98e2SPeter Wemm 
3189c2aa98e2SPeter Wemm 		  case 'T':
3190c2aa98e2SPeter Wemm 			map->map_tapp = ++p;
3191c2aa98e2SPeter Wemm 			break;
3192c2aa98e2SPeter Wemm 
3193c2aa98e2SPeter Wemm 		  case 'm':
3194c2aa98e2SPeter Wemm 			map->map_mflags |= MF_MATCHONLY;
3195c2aa98e2SPeter Wemm 			break;
3196c2aa98e2SPeter Wemm 
3197c2aa98e2SPeter Wemm 		  case 't':
3198c2aa98e2SPeter Wemm 			map->map_mflags |= MF_NODEFER;
3199c2aa98e2SPeter Wemm 			break;
320006f25ae9SGregory Neil Shapiro 
320106f25ae9SGregory Neil Shapiro 		  case 'S':	/* only for consistency */
320206f25ae9SGregory Neil Shapiro 			map->map_spacesub = *++p;
320306f25ae9SGregory Neil Shapiro 			break;
320406f25ae9SGregory Neil Shapiro 
320506f25ae9SGregory Neil Shapiro 		  case 'D':
320606f25ae9SGregory Neil Shapiro 			map->map_mflags |= MF_DEFER;
320706f25ae9SGregory Neil Shapiro 			break;
3208c2aa98e2SPeter Wemm 		}
3209c2aa98e2SPeter Wemm 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
3210c2aa98e2SPeter Wemm 			p++;
3211c2aa98e2SPeter Wemm 		if (*p != '\0')
3212c2aa98e2SPeter Wemm 			*p++ = '\0';
3213c2aa98e2SPeter Wemm 	}
3214c2aa98e2SPeter Wemm 	if (map->map_app != NULL)
3215c2aa98e2SPeter Wemm 		map->map_app = newstr(map->map_app);
3216c2aa98e2SPeter Wemm 	if (map->map_tapp != NULL)
3217c2aa98e2SPeter Wemm 		map->map_tapp = newstr(map->map_tapp);
3218c2aa98e2SPeter Wemm 	return TRUE;
3219c2aa98e2SPeter Wemm }
322006f25ae9SGregory Neil Shapiro 
322106f25ae9SGregory Neil Shapiro #if NETINET6
322206f25ae9SGregory Neil Shapiro /*
322306f25ae9SGregory Neil Shapiro **  ANYNET_NTOP -- convert an IPv6 network address to printable form.
322406f25ae9SGregory Neil Shapiro **
322506f25ae9SGregory Neil Shapiro **	Parameters:
322606f25ae9SGregory Neil Shapiro **		s6a -- a pointer to an in6_addr structure.
322706f25ae9SGregory Neil Shapiro **		dst -- buffer to store result in
322806f25ae9SGregory Neil Shapiro **		dst_len -- size of dst buffer
322906f25ae9SGregory Neil Shapiro **
323006f25ae9SGregory Neil Shapiro **	Returns:
323106f25ae9SGregory Neil Shapiro **		A printable version of that structure.
323206f25ae9SGregory Neil Shapiro */
323306f25ae9SGregory Neil Shapiro char *
323406f25ae9SGregory Neil Shapiro anynet_ntop(s6a, dst, dst_len)
323506f25ae9SGregory Neil Shapiro 	struct in6_addr *s6a;
323606f25ae9SGregory Neil Shapiro 	char *dst;
323706f25ae9SGregory Neil Shapiro 	size_t dst_len;
323806f25ae9SGregory Neil Shapiro {
323906f25ae9SGregory Neil Shapiro 	register char *ap;
324006f25ae9SGregory Neil Shapiro 
324106f25ae9SGregory Neil Shapiro 	if (IN6_IS_ADDR_V4MAPPED(s6a))
324206f25ae9SGregory Neil Shapiro 		ap = (char *) inet_ntop(AF_INET,
324306f25ae9SGregory Neil Shapiro 					&s6a->s6_addr[IN6ADDRSZ - INADDRSZ],
324406f25ae9SGregory Neil Shapiro 					dst, dst_len);
324506f25ae9SGregory Neil Shapiro 	else
324606f25ae9SGregory Neil Shapiro 		ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len);
324706f25ae9SGregory Neil Shapiro 	return ap;
324806f25ae9SGregory Neil Shapiro }
324906f25ae9SGregory Neil Shapiro #endif /* NETINET6 */
3250c2aa98e2SPeter Wemm /*
3251c2aa98e2SPeter Wemm **  ANYNET_NTOA -- convert a network address to printable form.
3252c2aa98e2SPeter Wemm **
3253c2aa98e2SPeter Wemm **	Parameters:
3254c2aa98e2SPeter Wemm **		sap -- a pointer to a sockaddr structure.
3255c2aa98e2SPeter Wemm **
3256c2aa98e2SPeter Wemm **	Returns:
3257c2aa98e2SPeter Wemm **		A printable version of that sockaddr.
3258c2aa98e2SPeter Wemm */
3259c2aa98e2SPeter Wemm 
3260c2aa98e2SPeter Wemm #ifdef USE_SOCK_STREAM
3261c2aa98e2SPeter Wemm 
3262c2aa98e2SPeter Wemm # if NETLINK
3263c2aa98e2SPeter Wemm #  include <net/if_dl.h>
326406f25ae9SGregory Neil Shapiro # endif /* NETLINK */
3265c2aa98e2SPeter Wemm 
3266c2aa98e2SPeter Wemm char *
3267c2aa98e2SPeter Wemm anynet_ntoa(sap)
3268c2aa98e2SPeter Wemm 	register SOCKADDR *sap;
3269c2aa98e2SPeter Wemm {
3270c2aa98e2SPeter Wemm 	register char *bp;
3271c2aa98e2SPeter Wemm 	register char *ap;
3272c2aa98e2SPeter Wemm 	int l;
3273c2aa98e2SPeter Wemm 	static char buf[100];
3274c2aa98e2SPeter Wemm 
3275c2aa98e2SPeter Wemm 	/* check for null/zero family */
3276c2aa98e2SPeter Wemm 	if (sap == NULL)
3277c2aa98e2SPeter Wemm 		return "NULLADDR";
3278c2aa98e2SPeter Wemm 	if (sap->sa.sa_family == 0)
3279c2aa98e2SPeter Wemm 		return "0";
3280c2aa98e2SPeter Wemm 
3281c2aa98e2SPeter Wemm 	switch (sap->sa.sa_family)
3282c2aa98e2SPeter Wemm 	{
3283c2aa98e2SPeter Wemm # if NETUNIX
3284c2aa98e2SPeter Wemm 	  case AF_UNIX:
3285c2aa98e2SPeter Wemm 		if (sap->sunix.sun_path[0] != '\0')
3286c2aa98e2SPeter Wemm 			snprintf(buf, sizeof buf, "[UNIX: %.64s]",
3287c2aa98e2SPeter Wemm 				sap->sunix.sun_path);
3288c2aa98e2SPeter Wemm 		else
3289c2aa98e2SPeter Wemm 			snprintf(buf, sizeof buf, "[UNIX: localhost]");
3290c2aa98e2SPeter Wemm 		return buf;
329106f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
3292c2aa98e2SPeter Wemm 
3293c2aa98e2SPeter Wemm # if NETINET
3294c2aa98e2SPeter Wemm 	  case AF_INET:
329506f25ae9SGregory Neil Shapiro 		return (char *) inet_ntoa(sap->sin.sin_addr);
329606f25ae9SGregory Neil Shapiro # endif /* NETINET */
329706f25ae9SGregory Neil Shapiro 
329806f25ae9SGregory Neil Shapiro # if NETINET6
329906f25ae9SGregory Neil Shapiro 	  case AF_INET6:
330006f25ae9SGregory Neil Shapiro 		ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf);
330106f25ae9SGregory Neil Shapiro 		if (ap != NULL)
330206f25ae9SGregory Neil Shapiro 			return ap;
330306f25ae9SGregory Neil Shapiro 		break;
330406f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
3305c2aa98e2SPeter Wemm 
3306c2aa98e2SPeter Wemm # if NETLINK
3307c2aa98e2SPeter Wemm 	  case AF_LINK:
3308c2aa98e2SPeter Wemm 		snprintf(buf, sizeof buf, "[LINK: %s]",
3309c2aa98e2SPeter Wemm 			link_ntoa((struct sockaddr_dl *) &sap->sa));
3310c2aa98e2SPeter Wemm 		return buf;
331106f25ae9SGregory Neil Shapiro # endif /* NETLINK */
3312c2aa98e2SPeter Wemm 	  default:
3313c2aa98e2SPeter Wemm 		/* this case is needed when nothing is #defined */
3314c2aa98e2SPeter Wemm 		/* in order to keep the switch syntactically correct */
3315c2aa98e2SPeter Wemm 		break;
3316c2aa98e2SPeter Wemm 	}
3317c2aa98e2SPeter Wemm 
3318c2aa98e2SPeter Wemm 	/* unknown family -- just dump bytes */
3319c2aa98e2SPeter Wemm 	(void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family);
3320c2aa98e2SPeter Wemm 	bp = &buf[strlen(buf)];
3321c2aa98e2SPeter Wemm 	ap = sap->sa.sa_data;
3322c2aa98e2SPeter Wemm 	for (l = sizeof sap->sa.sa_data; --l >= 0; )
3323c2aa98e2SPeter Wemm 	{
3324c2aa98e2SPeter Wemm 		(void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377);
3325c2aa98e2SPeter Wemm 		bp += 3;
3326c2aa98e2SPeter Wemm 	}
3327c2aa98e2SPeter Wemm 	*--bp = '\0';
3328c2aa98e2SPeter Wemm 	return buf;
3329c2aa98e2SPeter Wemm }
3330c2aa98e2SPeter Wemm /*
3331c2aa98e2SPeter Wemm **  HOSTNAMEBYANYADDR -- return name of host based on address
3332c2aa98e2SPeter Wemm **
3333c2aa98e2SPeter Wemm **	Parameters:
3334c2aa98e2SPeter Wemm **		sap -- SOCKADDR pointer
3335c2aa98e2SPeter Wemm **
3336c2aa98e2SPeter Wemm **	Returns:
3337c2aa98e2SPeter Wemm **		text representation of host name.
3338c2aa98e2SPeter Wemm **
3339c2aa98e2SPeter Wemm **	Side Effects:
3340c2aa98e2SPeter Wemm **		none.
3341c2aa98e2SPeter Wemm */
3342c2aa98e2SPeter Wemm 
3343c2aa98e2SPeter Wemm char *
3344c2aa98e2SPeter Wemm hostnamebyanyaddr(sap)
3345c2aa98e2SPeter Wemm 	register SOCKADDR *sap;
3346c2aa98e2SPeter Wemm {
3347c2aa98e2SPeter Wemm 	register struct hostent *hp;
334806f25ae9SGregory Neil Shapiro # if NAMED_BIND
3349c2aa98e2SPeter Wemm 	int saveretry;
335006f25ae9SGregory Neil Shapiro # endif /* NAMED_BIND */
335106f25ae9SGregory Neil Shapiro # if NETINET6
335206f25ae9SGregory Neil Shapiro 	struct in6_addr in6_addr;
335306f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
3354c2aa98e2SPeter Wemm 
3355c2aa98e2SPeter Wemm # if NAMED_BIND
3356c2aa98e2SPeter Wemm 	/* shorten name server timeout to avoid higher level timeouts */
3357c2aa98e2SPeter Wemm 	saveretry = _res.retry;
335806f25ae9SGregory Neil Shapiro 	if (_res.retry * _res.retrans > 20)
335906f25ae9SGregory Neil Shapiro 		_res.retry = 20 / _res.retrans;
3360c2aa98e2SPeter Wemm # endif /* NAMED_BIND */
3361c2aa98e2SPeter Wemm 
3362c2aa98e2SPeter Wemm 	switch (sap->sa.sa_family)
3363c2aa98e2SPeter Wemm 	{
3364c2aa98e2SPeter Wemm # if NETINET
3365c2aa98e2SPeter Wemm 	  case AF_INET:
3366c2aa98e2SPeter Wemm 		hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
3367c2aa98e2SPeter Wemm 			INADDRSZ,
3368c2aa98e2SPeter Wemm 			AF_INET);
3369c2aa98e2SPeter Wemm 		break;
337006f25ae9SGregory Neil Shapiro # endif /* NETINET */
337106f25ae9SGregory Neil Shapiro 
337206f25ae9SGregory Neil Shapiro # if NETINET6
337306f25ae9SGregory Neil Shapiro 	  case AF_INET6:
337406f25ae9SGregory Neil Shapiro 		hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr,
337506f25ae9SGregory Neil Shapiro 				      IN6ADDRSZ,
337606f25ae9SGregory Neil Shapiro 				      AF_INET6);
337706f25ae9SGregory Neil Shapiro 		break;
337806f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
3379c2aa98e2SPeter Wemm 
3380c2aa98e2SPeter Wemm # if NETISO
3381c2aa98e2SPeter Wemm 	  case AF_ISO:
3382c2aa98e2SPeter Wemm 		hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
3383c2aa98e2SPeter Wemm 			sizeof sap->siso.siso_addr,
3384c2aa98e2SPeter Wemm 			AF_ISO);
3385c2aa98e2SPeter Wemm 		break;
338606f25ae9SGregory Neil Shapiro # endif /* NETISO */
3387c2aa98e2SPeter Wemm 
3388c2aa98e2SPeter Wemm # if NETUNIX
3389c2aa98e2SPeter Wemm 	  case AF_UNIX:
3390c2aa98e2SPeter Wemm 		hp = NULL;
3391c2aa98e2SPeter Wemm 		break;
339206f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
3393c2aa98e2SPeter Wemm 
3394c2aa98e2SPeter Wemm 	  default:
3395c2aa98e2SPeter Wemm 		hp = sm_gethostbyaddr(sap->sa.sa_data,
3396c2aa98e2SPeter Wemm 			   sizeof sap->sa.sa_data,
3397c2aa98e2SPeter Wemm 			   sap->sa.sa_family);
3398c2aa98e2SPeter Wemm 		break;
3399c2aa98e2SPeter Wemm 	}
3400c2aa98e2SPeter Wemm 
3401c2aa98e2SPeter Wemm # if NAMED_BIND
3402c2aa98e2SPeter Wemm 	_res.retry = saveretry;
3403c2aa98e2SPeter Wemm # endif /* NAMED_BIND */
3404c2aa98e2SPeter Wemm 
340506f25ae9SGregory Neil Shapiro # if NETINET || NETINET6
340606f25ae9SGregory Neil Shapiro 	if (hp != NULL && hp->h_name[0] != '['
340706f25ae9SGregory Neil Shapiro #  if NETINET6
340806f25ae9SGregory Neil Shapiro 	    && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1
340906f25ae9SGregory Neil Shapiro #  endif /* NETINET6 */
341006f25ae9SGregory Neil Shapiro #  if NETINET
341106f25ae9SGregory Neil Shapiro 	    && inet_addr(hp->h_name) == INADDR_NONE
341206f25ae9SGregory Neil Shapiro #  endif /* NETINET */
341306f25ae9SGregory Neil Shapiro 	    )
3414c2aa98e2SPeter Wemm 		return denlstring((char *) hp->h_name, TRUE, TRUE);
341506f25ae9SGregory Neil Shapiro # endif /* NETINET || NETINET6 */
3416c2aa98e2SPeter Wemm # if NETUNIX
341706f25ae9SGregory Neil Shapiro 	if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0')
3418c2aa98e2SPeter Wemm 		return "localhost";
341906f25ae9SGregory Neil Shapiro # endif /* NETUNIX */
3420c2aa98e2SPeter Wemm 	{
3421c2aa98e2SPeter Wemm 		static char buf[203];
3422c2aa98e2SPeter Wemm 
3423c2aa98e2SPeter Wemm 		(void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap));
3424c2aa98e2SPeter Wemm 		return buf;
3425c2aa98e2SPeter Wemm 	}
3426c2aa98e2SPeter Wemm }
342706f25ae9SGregory Neil Shapiro #endif /* USE_SOCK_STREAM */
3428