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