daemon.c revision 168515
1/*
2 * Copyright (c) 1998-2007 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.678 2007/03/08 00:33:40 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: %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 = INADDR_ANY;
1261		port = daemonaddr->sin.sin_port;
1262		break;
1263#endif /* NETINET */
1264
1265#if NETINET6
1266	  case AF_INET6:
1267		if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr))
1268			daemonaddr->sin6.sin6_addr = in6addr_any;
1269		port = daemonaddr->sin6.sin6_port;
1270		break;
1271#endif /* NETINET6 */
1272
1273	  default:
1274		/* unknown protocol */
1275		port = 0;
1276		break;
1277	}
1278	if (port == 0)
1279	{
1280#ifdef NO_GETSERVBYNAME
1281		port = htons(25);
1282#else /* NO_GETSERVBYNAME */
1283		{
1284			register struct servent *sp;
1285
1286			sp = getservbyname("smtp", "tcp");
1287			if (sp == NULL)
1288			{
1289				syserr("554 5.3.5 service \"smtp\" unknown");
1290				port = htons(25);
1291			}
1292			else
1293				port = sp->s_port;
1294		}
1295#endif /* NO_GETSERVBYNAME */
1296	}
1297
1298	switch (daemonaddr->sa.sa_family)
1299	{
1300#if NETINET
1301	  case AF_INET:
1302		daemonaddr->sin.sin_port = port;
1303		break;
1304#endif /* NETINET */
1305
1306#if NETINET6
1307	  case AF_INET6:
1308		daemonaddr->sin6.sin6_port = port;
1309		break;
1310#endif /* NETINET6 */
1311
1312	  default:
1313		/* unknown protocol */
1314		break;
1315	}
1316	return port;
1317}
1318/*
1319**  CLRDAEMON -- reset the daemon connection
1320**
1321**	Parameters:
1322**		none.
1323**
1324**	Returns:
1325**		none.
1326**
1327**	Side Effects:
1328**		releases any resources used by the passive daemon.
1329*/
1330
1331void
1332clrdaemon()
1333{
1334	int i;
1335
1336	for (i = 0; i < NDaemons; i++)
1337	{
1338		if (Daemons[i].d_socket >= 0)
1339			(void) close(Daemons[i].d_socket);
1340		Daemons[i].d_socket = -1;
1341	}
1342}
1343
1344/*
1345**  GETMODIFIERS -- get modifier flags
1346**
1347**	Parameters:
1348**		v -- the modifiers (input text line).
1349**		modifiers -- pointer to flag field to represent modifiers.
1350**
1351**	Returns:
1352**		(xallocat()ed) string representation of modifiers.
1353**
1354**	Side Effects:
1355**		fills in modifiers.
1356*/
1357
1358char *
1359getmodifiers(v, modifiers)
1360	char *v;
1361	BITMAP256 modifiers;
1362{
1363	int l;
1364	char *h, *f, *flags;
1365
1366	/* maximum length of flags: upper case Option -> "OO " */
1367	l = 3 * strlen(v) + 3;
1368
1369	/* is someone joking? */
1370	if (l < 0 || l > 256)
1371	{
1372		if (LogLevel > 2)
1373			sm_syslog(LOG_ERR, NOQID,
1374				  "getmodifiers too long, ignored");
1375		return NULL;
1376	}
1377	flags = xalloc(l);
1378	f = flags;
1379	clrbitmap(modifiers);
1380	for (h = v; *h != '\0'; h++)
1381	{
1382		if (isascii(*h) && !isspace(*h) && isprint(*h))
1383		{
1384			setbitn(*h, modifiers);
1385			if (flags != f)
1386				*flags++ = ' ';
1387			*flags++ = *h;
1388			if (isupper(*h))
1389				*flags++ = *h;
1390		}
1391	}
1392	*flags++ = '\0';
1393	return f;
1394}
1395
1396/*
1397**  CHKDAEMONMODIFIERS -- check whether all daemons have set a flag.
1398**
1399**	Parameters:
1400**		flag -- the flag to test.
1401**
1402**	Returns:
1403**		true iff all daemons have set flag.
1404*/
1405
1406bool
1407chkdaemonmodifiers(flag)
1408	int flag;
1409{
1410	int i;
1411
1412	for (i = 0; i < NDaemons; i++)
1413		if (!bitnset((char) flag, Daemons[i].d_flags))
1414			return false;
1415	return true;
1416}
1417
1418/*
1419**  SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client)
1420**
1421**	Parameters:
1422**		p -- the options line.
1423**		d -- the daemon structure to fill in.
1424**
1425**	Returns:
1426**		none.
1427*/
1428
1429static void
1430setsockaddroptions(p, d)
1431	char *p;
1432	DAEMON_T *d;
1433{
1434#if NETISO
1435	short portno;
1436#endif /* NETISO */
1437	char *port = NULL;
1438	char *addr = NULL;
1439
1440#if NETINET
1441	if (d->d_addr.sa.sa_family == AF_UNSPEC)
1442		d->d_addr.sa.sa_family = AF_INET;
1443#endif /* NETINET */
1444#if _FFR_SS_PER_DAEMON
1445	d->d_supersafe = DPO_NOTSET;
1446#endif /* _FFR_SS_PER_DAEMON */
1447	d->d_dm = DM_NOTSET;
1448	d->d_refuseLA = DPO_NOTSET;
1449	d->d_queueLA = DPO_NOTSET;
1450	d->d_delayLA = DPO_NOTSET;
1451	d->d_maxchildren = DPO_NOTSET;
1452
1453	while (p != NULL)
1454	{
1455		register char *f;
1456		register char *v;
1457
1458		while (isascii(*p) && isspace(*p))
1459			p++;
1460		if (*p == '\0')
1461			break;
1462		f = p;
1463		p = strchr(p, ',');
1464		if (p != NULL)
1465			*p++ = '\0';
1466		v = strchr(f, '=');
1467		if (v == NULL)
1468			continue;
1469		while (isascii(*++v) && isspace(*v))
1470			continue;
1471
1472		switch (*f)
1473		{
1474		  case 'A':		/* address */
1475#if !_FFR_DPO_CS
1476		  case 'a':
1477#endif /* !_FFR_DPO_CS */
1478			addr = v;
1479			break;
1480
1481		  case 'c':
1482			d->d_maxchildren = atoi(v);
1483			break;
1484
1485		  case 'D':		/* DeliveryMode */
1486			switch (*v)
1487			{
1488			  case SM_QUEUE:
1489			  case SM_DEFER:
1490			  case SM_DELIVER:
1491			  case SM_FORK:
1492				d->d_dm = *v;
1493				break;
1494			  default:
1495				syserr("554 5.3.5 Unknown delivery mode %c",
1496					*v);
1497				break;
1498			}
1499			break;
1500
1501		  case 'd':		/* delayLA */
1502			d->d_delayLA = atoi(v);
1503			break;
1504
1505		  case 'F':		/* address family */
1506#if !_FFR_DPO_CS
1507		  case 'f':
1508#endif /* !_FFR_DPO_CS */
1509			if (isascii(*v) && isdigit(*v))
1510				d->d_addr.sa.sa_family = atoi(v);
1511#if _FFR_DAEMON_NETUNIX
1512# ifdef NETUNIX
1513			else if (sm_strcasecmp(v, "unix") == 0 ||
1514				 sm_strcasecmp(v, "local") == 0)
1515				d->d_addr.sa.sa_family = AF_UNIX;
1516# endif /* NETUNIX */
1517#endif /* _FFR_DAEMON_NETUNIX */
1518#if NETINET
1519			else if (sm_strcasecmp(v, "inet") == 0)
1520				d->d_addr.sa.sa_family = AF_INET;
1521#endif /* NETINET */
1522#if NETINET6
1523			else if (sm_strcasecmp(v, "inet6") == 0)
1524				d->d_addr.sa.sa_family = AF_INET6;
1525#endif /* NETINET6 */
1526#if NETISO
1527			else if (sm_strcasecmp(v, "iso") == 0)
1528				d->d_addr.sa.sa_family = AF_ISO;
1529#endif /* NETISO */
1530#if NETNS
1531			else if (sm_strcasecmp(v, "ns") == 0)
1532				d->d_addr.sa.sa_family = AF_NS;
1533#endif /* NETNS */
1534#if NETX25
1535			else if (sm_strcasecmp(v, "x.25") == 0)
1536				d->d_addr.sa.sa_family = AF_CCITT;
1537#endif /* NETX25 */
1538			else
1539				syserr("554 5.3.5 Unknown address family %s in Family=option",
1540				       v);
1541			break;
1542
1543#if MILTER
1544		  case 'I':
1545# if !_FFR_DPO_CS
1546		  case 'i':
1547# endif /* !_FFR_DPO_CS */
1548			d->d_inputfilterlist = v;
1549			break;
1550#endif /* MILTER */
1551
1552		  case 'L':		/* listen queue size */
1553#if !_FFR_DPO_CS
1554		  case 'l':
1555#endif /* !_FFR_DPO_CS */
1556			d->d_listenqueue = atoi(v);
1557			break;
1558
1559		  case 'M':		/* modifiers (flags) */
1560#if !_FFR_DPO_CS
1561		  case 'm':
1562#endif /* !_FFR_DPO_CS */
1563			d->d_mflags = getmodifiers(v, d->d_flags);
1564			break;
1565
1566		  case 'N':		/* name */
1567#if !_FFR_DPO_CS
1568		  case 'n':
1569#endif /* !_FFR_DPO_CS */
1570			d->d_name = v;
1571			break;
1572
1573		  case 'P':		/* port */
1574#if !_FFR_DPO_CS
1575		  case 'p':
1576#endif /* !_FFR_DPO_CS */
1577			port = v;
1578			break;
1579
1580		  case 'q':
1581			d->d_queueLA = atoi(v);
1582			break;
1583
1584		  case 'R':		/* receive buffer size */
1585			d->d_tcprcvbufsize = atoi(v);
1586			break;
1587
1588		  case 'r':
1589			d->d_refuseLA = atoi(v);
1590			break;
1591
1592		  case 'S':		/* send buffer size */
1593#if !_FFR_DPO_CS
1594		  case 's':
1595#endif /* !_FFR_DPO_CS */
1596			d->d_tcpsndbufsize = atoi(v);
1597			break;
1598
1599#if _FFR_SS_PER_DAEMON
1600		  case 'T':		/* SuperSafe */
1601			if (tolower(*v) == 'i')
1602				d->d_supersafe = SAFE_INTERACTIVE;
1603			else if (tolower(*v) == 'p')
1604# if MILTER
1605				d->d_supersafe = SAFE_REALLY_POSTMILTER;
1606# else /* MILTER */
1607				(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
1608					"Warning: SuperSafe=PostMilter requires Milter support (-DMILTER)\n");
1609# endif /* MILTER */
1610			else
1611				d->d_supersafe = atobool(v) ? SAFE_REALLY
1612							: SAFE_NO;
1613			break;
1614#endif /* _FFR_SS_PER_DAEMON */
1615
1616		  default:
1617			syserr("554 5.3.5 PortOptions parameter \"%s\" unknown",
1618			       f);
1619		}
1620	}
1621
1622	/* Check addr and port after finding family */
1623	if (addr != NULL)
1624	{
1625		switch (d->d_addr.sa.sa_family)
1626		{
1627#if _FFR_DAEMON_NETUNIX
1628# if NETUNIX
1629		  case AF_UNIX:
1630			if (strlen(addr) >= sizeof(d->d_addr.sunix.sun_path))
1631			{
1632				errno = ENAMETOOLONG;
1633				syserr("setsockaddroptions: domain socket name too long: %s > %d",
1634				       addr, sizeof(d->d_addr.sunix.sun_path));
1635				break;
1636			}
1637
1638			/* file safety check done in opendaemonsocket() */
1639			(void) memset(&d->d_addr.sunix.sun_path, '\0',
1640				      sizeof(d->d_addr.sunix.sun_path));
1641			(void) sm_strlcpy((char *)&d->d_addr.sunix.sun_path,
1642					  addr,
1643					  sizeof(d->d_addr.sunix.sun_path));
1644			break;
1645# endif /* NETUNIX */
1646#endif	/* _FFR_DAEMON_NETUNIX */
1647#if NETINET
1648		  case AF_INET:
1649			if (!isascii(*addr) || !isdigit(*addr) ||
1650			    ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr))
1651			     == INADDR_NONE))
1652			{
1653				register struct hostent *hp;
1654
1655				hp = sm_gethostbyname(addr, AF_INET);
1656				if (hp == NULL)
1657					syserr("554 5.3.0 host \"%s\" unknown",
1658					       addr);
1659				else
1660				{
1661					while (*(hp->h_addr_list) != NULL &&
1662					       hp->h_addrtype != AF_INET)
1663						hp->h_addr_list++;
1664					if (*(hp->h_addr_list) == NULL)
1665						syserr("554 5.3.0 host \"%s\" unknown",
1666						       addr);
1667					else
1668						memmove(&d->d_addr.sin.sin_addr,
1669							*(hp->h_addr_list),
1670							INADDRSZ);
1671# if NETINET6
1672					freehostent(hp);
1673					hp = NULL;
1674# endif /* NETINET6 */
1675				}
1676			}
1677			break;
1678#endif /* NETINET */
1679
1680#if NETINET6
1681		  case AF_INET6:
1682			if (anynet_pton(AF_INET6, addr,
1683					&d->d_addr.sin6.sin6_addr) != 1)
1684			{
1685				register struct hostent *hp;
1686
1687				hp = sm_gethostbyname(addr, AF_INET6);
1688				if (hp == NULL)
1689					syserr("554 5.3.0 host \"%s\" unknown",
1690					       addr);
1691				else
1692				{
1693					while (*(hp->h_addr_list) != NULL &&
1694					       hp->h_addrtype != AF_INET6)
1695						hp->h_addr_list++;
1696					if (*(hp->h_addr_list) == NULL)
1697						syserr("554 5.3.0 host \"%s\" unknown",
1698						       addr);
1699					else
1700						memmove(&d->d_addr.sin6.sin6_addr,
1701							*(hp->h_addr_list),
1702							IN6ADDRSZ);
1703					freehostent(hp);
1704					hp = NULL;
1705				}
1706			}
1707			break;
1708#endif /* NETINET6 */
1709
1710		  default:
1711			syserr("554 5.3.5 address= option unsupported for family %d",
1712			       d->d_addr.sa.sa_family);
1713			break;
1714		}
1715	}
1716
1717	if (port != NULL)
1718	{
1719		switch (d->d_addr.sa.sa_family)
1720		{
1721#if NETINET
1722		  case AF_INET:
1723			if (isascii(*port) && isdigit(*port))
1724				d->d_addr.sin.sin_port = htons((unsigned short)
1725						     atoi((const char *) port));
1726			else
1727			{
1728# ifdef NO_GETSERVBYNAME
1729				syserr("554 5.3.5 invalid port number: %s",
1730				       port);
1731# else /* NO_GETSERVBYNAME */
1732				register struct servent *sp;
1733
1734				sp = getservbyname(port, "tcp");
1735				if (sp == NULL)
1736					syserr("554 5.3.5 service \"%s\" unknown",
1737					       port);
1738				else
1739					d->d_addr.sin.sin_port = sp->s_port;
1740# endif /* NO_GETSERVBYNAME */
1741			}
1742			break;
1743#endif /* NETINET */
1744
1745#if NETINET6
1746		  case AF_INET6:
1747			if (isascii(*port) && isdigit(*port))
1748				d->d_addr.sin6.sin6_port = htons((unsigned short)
1749								  atoi(port));
1750			else
1751			{
1752# ifdef NO_GETSERVBYNAME
1753				syserr("554 5.3.5 invalid port number: %s",
1754				       port);
1755# else /* NO_GETSERVBYNAME */
1756				register struct servent *sp;
1757
1758				sp = getservbyname(port, "tcp");
1759				if (sp == NULL)
1760					syserr("554 5.3.5 service \"%s\" unknown",
1761					       port);
1762				else
1763					d->d_addr.sin6.sin6_port = sp->s_port;
1764# endif /* NO_GETSERVBYNAME */
1765			}
1766			break;
1767#endif /* NETINET6 */
1768
1769#if NETISO
1770		  case AF_ISO:
1771			/* assume two byte transport selector */
1772			if (isascii(*port) && isdigit(*port))
1773				portno = htons((unsigned short) atoi(port));
1774			else
1775			{
1776# ifdef NO_GETSERVBYNAME
1777				syserr("554 5.3.5 invalid port number: %s",
1778				       port);
1779# else /* NO_GETSERVBYNAME */
1780				register struct servent *sp;
1781
1782				sp = getservbyname(port, "tcp");
1783				if (sp == NULL)
1784					syserr("554 5.3.5 service \"%s\" unknown",
1785					       port);
1786				else
1787					portno = sp->s_port;
1788# endif /* NO_GETSERVBYNAME */
1789			}
1790			memmove(TSEL(&d->d_addr.siso),
1791				(char *) &portno, 2);
1792			break;
1793#endif /* NETISO */
1794
1795		  default:
1796			syserr("554 5.3.5 Port= option unsupported for family %d",
1797			       d->d_addr.sa.sa_family);
1798			break;
1799		}
1800	}
1801}
1802/*
1803**  SETDAEMONOPTIONS -- set options for running the MTA daemon
1804**
1805**	Parameters:
1806**		p -- the options line.
1807**
1808**	Returns:
1809**		true if successful, false otherwise.
1810**
1811**	Side Effects:
1812**		increments number of daemons.
1813*/
1814
1815#define DEF_LISTENQUEUE	10
1816
1817struct dflags
1818{
1819	char	*d_name;
1820	int	d_flag;
1821};
1822
1823static struct dflags	DaemonFlags[] =
1824{
1825	{ "AUTHREQ",		D_AUTHREQ	},
1826	{ "BINDIF",		D_BINDIF	},
1827	{ "CANONREQ",		D_CANONREQ	},
1828	{ "IFNHELO",		D_IFNHELO	},
1829	{ "FQMAIL",		D_FQMAIL	},
1830	{ "FQRCPT",		D_FQRCPT	},
1831	{ "SMTPS",		D_SMTPS		},
1832	{ "UNQUALOK",		D_UNQUALOK	},
1833	{ "NOAUTH",		D_NOAUTH	},
1834	{ "NOCANON",		D_NOCANON	},
1835	{ "NOETRN",		D_NOETRN	},
1836	{ "NOTLS",		D_NOTLS		},
1837	{ "ETRNONLY",		D_ETRNONLY	},
1838	{ "OPTIONAL",		D_OPTIONAL	},
1839	{ "DISABLE",		D_DISABLE	},
1840	{ "ISSET",		D_ISSET		},
1841	{ NULL,			0		}
1842};
1843
1844static void
1845printdaemonflags(d)
1846	DAEMON_T *d;
1847{
1848	register struct dflags *df;
1849	bool first = true;
1850
1851	for (df = DaemonFlags; df->d_name != NULL; df++)
1852	{
1853		if (!bitnset(df->d_flag, d->d_flags))
1854			continue;
1855		if (first)
1856			sm_dprintf("<%s", df->d_name);
1857		else
1858			sm_dprintf(",%s", df->d_name);
1859		first = false;
1860	}
1861	if (!first)
1862		sm_dprintf(">");
1863}
1864
1865bool
1866setdaemonoptions(p)
1867	register char *p;
1868{
1869	if (NDaemons >= MAXDAEMONS)
1870		return false;
1871	Daemons[NDaemons].d_socket = -1;
1872	Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE;
1873	clrbitmap(Daemons[NDaemons].d_flags);
1874	setsockaddroptions(p, &Daemons[NDaemons]);
1875
1876#if MILTER
1877	if (Daemons[NDaemons].d_inputfilterlist != NULL)
1878		Daemons[NDaemons].d_inputfilterlist = newstr(Daemons[NDaemons].d_inputfilterlist);
1879#endif /* MILTER */
1880
1881	if (Daemons[NDaemons].d_name != NULL)
1882		Daemons[NDaemons].d_name = newstr(Daemons[NDaemons].d_name);
1883	else
1884	{
1885		char num[30];
1886
1887		(void) sm_snprintf(num, sizeof(num), "Daemon%d", NDaemons);
1888		Daemons[NDaemons].d_name = newstr(num);
1889	}
1890
1891	if (tTd(37, 1))
1892	{
1893		sm_dprintf("Daemon %s flags: ", Daemons[NDaemons].d_name);
1894		printdaemonflags(&Daemons[NDaemons]);
1895		sm_dprintf("\n");
1896	}
1897	++NDaemons;
1898	return true;
1899}
1900/*
1901**  INITDAEMON -- initialize daemon if not yet done.
1902**
1903**	Parameters:
1904**		none
1905**
1906**	Returns:
1907**		none
1908**
1909**	Side Effects:
1910**		initializes structure for one daemon.
1911*/
1912
1913void
1914initdaemon()
1915{
1916	if (NDaemons == 0)
1917	{
1918		Daemons[NDaemons].d_socket = -1;
1919		Daemons[NDaemons].d_listenqueue = DEF_LISTENQUEUE;
1920		Daemons[NDaemons].d_name = "Daemon0";
1921		NDaemons = 1;
1922	}
1923}
1924/*
1925**  SETCLIENTOPTIONS -- set options for running the client
1926**
1927**	Parameters:
1928**		p -- the options line.
1929**
1930**	Returns:
1931**		none.
1932*/
1933
1934static DAEMON_T	ClientSettings[AF_MAX + 1];
1935
1936void
1937setclientoptions(p)
1938	register char *p;
1939{
1940	int family;
1941	DAEMON_T d;
1942
1943	memset(&d, '\0', sizeof(d));
1944	setsockaddroptions(p, &d);
1945
1946	/* grab what we need */
1947	family = d.d_addr.sa.sa_family;
1948	STRUCTCOPY(d, ClientSettings[family]);
1949	setbitn(D_ISSET, ClientSettings[family].d_flags); /* mark as set */
1950	if (d.d_name != NULL)
1951		ClientSettings[family].d_name = newstr(d.d_name);
1952	else
1953	{
1954		char num[30];
1955
1956		(void) sm_snprintf(num, sizeof(num), "Client%d", family);
1957		ClientSettings[family].d_name = newstr(num);
1958	}
1959}
1960/*
1961**  ADDR_FAMILY -- determine address family from address
1962**
1963**	Parameters:
1964**		addr -- the string representation of the address
1965**
1966**	Returns:
1967**		AF_INET, AF_INET6 or AF_UNSPEC
1968**
1969**	Side Effects:
1970**		none.
1971*/
1972
1973static int
1974addr_family(addr)
1975	char *addr;
1976{
1977#if NETINET6
1978	SOCKADDR clt_addr;
1979#endif /* NETINET6 */
1980
1981#if NETINET
1982	if (inet_addr(addr) != INADDR_NONE)
1983	{
1984		if (tTd(16, 9))
1985			sm_dprintf("addr_family(%s): INET\n", addr);
1986		return AF_INET;
1987	}
1988#endif /* NETINET */
1989#if NETINET6
1990	if (anynet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1)
1991	{
1992		if (tTd(16, 9))
1993			sm_dprintf("addr_family(%s): INET6\n", addr);
1994		return AF_INET6;
1995	}
1996#endif /* NETINET6 */
1997#if _FFR_DAEMON_NETUNIX
1998# if NETUNIX
1999	if (*addr == '/')
2000	{
2001		if (tTd(16, 9))
2002			sm_dprintf("addr_family(%s): LOCAL\n", addr);
2003		return AF_UNIX;
2004	}
2005# endif /* NETUNIX */
2006#endif	/* _FFR_DAEMON_NETUNIX */
2007	if (tTd(16, 9))
2008		sm_dprintf("addr_family(%s): UNSPEC\n", addr);
2009	return AF_UNSPEC;
2010}
2011
2012/*
2013**  CHKCLIENTMODIFIERS -- check whether all clients have set a flag.
2014**
2015**	Parameters:
2016**		flag -- the flag to test.
2017**
2018**	Returns:
2019**		true iff all configured clients have set the flag.
2020*/
2021
2022bool
2023chkclientmodifiers(flag)
2024	int flag;
2025{
2026	int i;
2027	bool flagisset;
2028
2029	flagisset = false;
2030	for (i = 0; i < AF_MAX; i++)
2031	{
2032		if (bitnset(D_ISSET, ClientSettings[i].d_flags))
2033		{
2034			if (!bitnset((char) flag, ClientSettings[i].d_flags))
2035				return false;
2036			flagisset = true;
2037		}
2038	}
2039	return flagisset;
2040}
2041
2042#if MILTER
2043/*
2044**  SETUP_DAEMON_FILTERS -- Parse per-socket filters
2045**
2046**	Parameters:
2047**		none
2048**
2049**	Returns:
2050**		none
2051*/
2052
2053void
2054setup_daemon_milters()
2055{
2056	int idx;
2057
2058	if (OpMode == MD_SMTP)
2059	{
2060		/* no need to configure the daemons */
2061		return;
2062	}
2063
2064	for (idx = 0; idx < NDaemons; idx++)
2065	{
2066		if (Daemons[idx].d_inputfilterlist != NULL)
2067		{
2068			milter_config(Daemons[idx].d_inputfilterlist,
2069				      Daemons[idx].d_inputfilters,
2070				      MAXFILTERS);
2071		}
2072	}
2073}
2074#endif /* MILTER */
2075/*
2076**  MAKECONNECTION -- make a connection to an SMTP socket on a machine.
2077**
2078**	Parameters:
2079**		host -- the name of the host.
2080**		port -- the port number to connect to.
2081**		mci -- a pointer to the mail connection information
2082**			structure to be filled in.
2083**		e -- the current envelope.
2084**		enough -- time at which to stop further connection attempts.
2085**			(0 means no limit)
2086**
2087**	Returns:
2088**		An exit code telling whether the connection could be
2089**			made and if not why not.
2090**
2091**	Side Effects:
2092**		none.
2093*/
2094
2095static jmp_buf	CtxConnectTimeout;
2096
2097SOCKADDR	CurHostAddr;		/* address of current host */
2098
2099int
2100makeconnection(host, port, mci, e, enough)
2101	char *host;
2102	volatile unsigned int port;
2103	register MCI *mci;
2104	ENVELOPE *e;
2105	time_t enough;
2106{
2107	register volatile int addrno = 0;
2108	volatile int s;
2109	register struct hostent *volatile hp = (struct hostent *) NULL;
2110	SOCKADDR addr;
2111	SOCKADDR clt_addr;
2112	int save_errno = 0;
2113	volatile SOCKADDR_LEN_T addrlen;
2114	volatile bool firstconnect = true;
2115	SM_EVENT *volatile ev = NULL;
2116#if NETINET6
2117	volatile bool v6found = false;
2118#endif /* NETINET6 */
2119	volatile int family = InetMode;
2120	SOCKADDR_LEN_T len;
2121	volatile SOCKADDR_LEN_T socksize = 0;
2122	volatile bool clt_bind;
2123	BITMAP256 d_flags;
2124	char *p;
2125	extern ENVELOPE BlankEnvelope;
2126
2127	/* retranslate {daemon_flags} into bitmap */
2128	clrbitmap(d_flags);
2129	if ((p = macvalue(macid("{daemon_flags}"), e)) != NULL)
2130	{
2131		for (; *p != '\0'; p++)
2132		{
2133			if (!(isascii(*p) && isspace(*p)))
2134				setbitn(bitidx(*p), d_flags);
2135		}
2136	}
2137
2138#if NETINET6
2139 v4retry:
2140#endif /* NETINET6 */
2141	clt_bind = false;
2142
2143	/* Set up the address for outgoing connection. */
2144	if (bitnset(D_BINDIF, d_flags) &&
2145	    (p = macvalue(macid("{if_addr}"), e)) != NULL &&
2146	    *p != '\0')
2147	{
2148#if NETINET6
2149		char p6[INET6_ADDRSTRLEN];
2150#endif /* NETINET6 */
2151
2152		memset(&clt_addr, '\0', sizeof(clt_addr));
2153
2154		/* infer the address family from the address itself */
2155		clt_addr.sa.sa_family = addr_family(p);
2156		switch (clt_addr.sa.sa_family)
2157		{
2158#if NETINET
2159		  case AF_INET:
2160			clt_addr.sin.sin_addr.s_addr = inet_addr(p);
2161			if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE &&
2162			    clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK)
2163			{
2164				clt_bind = true;
2165				socksize = sizeof(struct sockaddr_in);
2166			}
2167			break;
2168#endif /* NETINET */
2169
2170#if NETINET6
2171		  case AF_INET6:
2172			if (inet_addr(p) != INADDR_NONE)
2173				(void) sm_snprintf(p6, sizeof(p6),
2174						   "IPv6:::ffff:%s", p);
2175			else
2176				(void) sm_strlcpy(p6, p, sizeof(p6));
2177			if (anynet_pton(AF_INET6, p6,
2178					&clt_addr.sin6.sin6_addr) == 1 &&
2179			    !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr))
2180			{
2181				clt_bind = true;
2182				socksize = sizeof(struct sockaddr_in6);
2183			}
2184			break;
2185#endif /* NETINET6 */
2186
2187#if 0
2188		  default:
2189			syserr("554 5.3.5 Address= option unsupported for family %d",
2190			       clt_addr.sa.sa_family);
2191			break;
2192#endif /* 0 */
2193		}
2194		if (clt_bind)
2195			family = clt_addr.sa.sa_family;
2196	}
2197
2198	/* D_BINDIF not set or not available, fallback to ClientPortOptions */
2199	if (!clt_bind)
2200	{
2201		STRUCTCOPY(ClientSettings[family].d_addr, clt_addr);
2202		switch (clt_addr.sa.sa_family)
2203		{
2204#if NETINET
2205		  case AF_INET:
2206			if (clt_addr.sin.sin_addr.s_addr == 0)
2207				clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
2208			else
2209				clt_bind = true;
2210			if (clt_addr.sin.sin_port != 0)
2211				clt_bind = true;
2212			socksize = sizeof(struct sockaddr_in);
2213			break;
2214#endif /* NETINET */
2215#if NETINET6
2216		  case AF_INET6:
2217			if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
2218				clt_addr.sin6.sin6_addr = in6addr_any;
2219			else
2220				clt_bind = true;
2221			socksize = sizeof(struct sockaddr_in6);
2222			if (clt_addr.sin6.sin6_port != 0)
2223				clt_bind = true;
2224			break;
2225#endif /* NETINET6 */
2226#if NETISO
2227		  case AF_ISO:
2228			socksize = sizeof(clt_addr.siso);
2229			clt_bind = true;
2230			break;
2231#endif /* NETISO */
2232		  default:
2233			break;
2234		}
2235	}
2236
2237	/*
2238	**  Set up the address for the mailer.
2239	**	Accept "[a.b.c.d]" syntax for host name.
2240	*/
2241
2242	SM_SET_H_ERRNO(0);
2243	errno = 0;
2244	memset(&CurHostAddr, '\0', sizeof(CurHostAddr));
2245	memset(&addr, '\0', sizeof(addr));
2246	SmtpPhase = mci->mci_phase = "initial connection";
2247	CurHostName = host;
2248
2249	if (host[0] == '[')
2250	{
2251		p = strchr(host, ']');
2252		if (p != NULL)
2253		{
2254#if NETINET
2255			unsigned long hid = INADDR_NONE;
2256#endif /* NETINET */
2257#if NETINET6
2258			struct sockaddr_in6 hid6;
2259#endif /* NETINET6 */
2260
2261			*p = '\0';
2262#if NETINET6
2263			memset(&hid6, '\0', sizeof(hid6));
2264#endif /* NETINET6 */
2265#if NETINET
2266			if (family == AF_INET &&
2267			    (hid = inet_addr(&host[1])) != INADDR_NONE)
2268			{
2269				addr.sin.sin_family = AF_INET;
2270				addr.sin.sin_addr.s_addr = hid;
2271			}
2272			else
2273#endif /* NETINET */
2274#if NETINET6
2275			if (family == AF_INET6 &&
2276			    anynet_pton(AF_INET6, &host[1],
2277					&hid6.sin6_addr) == 1)
2278			{
2279				addr.sin6.sin6_family = AF_INET6;
2280				addr.sin6.sin6_addr = hid6.sin6_addr;
2281			}
2282			else
2283#endif /* NETINET6 */
2284			{
2285				/* try it as a host name (avoid MX lookup) */
2286				hp = sm_gethostbyname(&host[1], family);
2287				if (hp == NULL && p[-1] == '.')
2288				{
2289#if NAMED_BIND
2290					int oldopts = _res.options;
2291
2292					_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
2293#endif /* NAMED_BIND */
2294					p[-1] = '\0';
2295					hp = sm_gethostbyname(&host[1],
2296							      family);
2297					p[-1] = '.';
2298#if NAMED_BIND
2299					_res.options = oldopts;
2300#endif /* NAMED_BIND */
2301				}
2302				*p = ']';
2303				goto gothostent;
2304			}
2305			*p = ']';
2306		}
2307		if (p == NULL)
2308		{
2309			extern char MsgBuf[];
2310
2311			usrerrenh("5.1.2",
2312				  "553 Invalid numeric domain spec \"%s\"",
2313				  host);
2314			mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
2315			errno = EINVAL;
2316			return EX_NOHOST;
2317		}
2318	}
2319	else
2320	{
2321		/* contortion to get around SGI cc complaints */
2322		{
2323			p = &host[strlen(host) - 1];
2324			hp = sm_gethostbyname(host, family);
2325			if (hp == NULL && *p == '.')
2326			{
2327#if NAMED_BIND
2328				int oldopts = _res.options;
2329
2330				_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
2331#endif /* NAMED_BIND */
2332				*p = '\0';
2333				hp = sm_gethostbyname(host, family);
2334				*p = '.';
2335#if NAMED_BIND
2336				_res.options = oldopts;
2337#endif /* NAMED_BIND */
2338			}
2339		}
2340gothostent:
2341		if (hp == NULL)
2342		{
2343#if NAMED_BIND
2344			/* check for name server timeouts */
2345# if NETINET6
2346			if (WorkAroundBrokenAAAA && family == AF_INET6 &&
2347			    errno == ETIMEDOUT)
2348			{
2349				/*
2350				**  An attempt with family AF_INET may
2351				**  succeed By skipping the next section
2352				**  of code, we will try AF_INET before
2353				**  failing.
2354				*/
2355
2356				if (tTd(16, 10))
2357					sm_dprintf("makeconnection: WorkAroundBrokenAAAA: Trying AF_INET lookup (AF_INET6 failed)\n");
2358			}
2359			else
2360# endif /* NETINET6 */
2361			{
2362				if (errno == ETIMEDOUT ||
2363# if _FFR_GETHBN_ExFILE
2364#  ifdef EMFILE
2365				   errno == EMFILE ||
2366#  endif /* EMFILE */
2367#  ifdef ENFILE
2368				   errno == ENFILE ||
2369#  endif /* ENFILE */
2370# endif /* _FFR_GETHBN_ExFILE */
2371				    h_errno == TRY_AGAIN ||
2372				    (errno == ECONNREFUSED && UseNameServer))
2373				{
2374					save_errno = errno;
2375					mci_setstat(mci, EX_TEMPFAIL,
2376						    "4.4.3", NULL);
2377					errno = save_errno;
2378					return EX_TEMPFAIL;
2379				}
2380			}
2381#endif /* NAMED_BIND */
2382#if NETINET6
2383			/*
2384			**  Try v6 first, then fall back to v4.
2385			**  If we found a v6 address, but no v4
2386			**  addresses, then TEMPFAIL.
2387			*/
2388
2389			if (family == AF_INET6)
2390			{
2391				family = AF_INET;
2392				goto v4retry;
2393			}
2394			if (v6found)
2395				goto v6tempfail;
2396#endif /* NETINET6 */
2397			save_errno = errno;
2398			mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
2399			errno = save_errno;
2400			return EX_NOHOST;
2401		}
2402		addr.sa.sa_family = hp->h_addrtype;
2403		switch (hp->h_addrtype)
2404		{
2405#if NETINET
2406		  case AF_INET:
2407			memmove(&addr.sin.sin_addr,
2408				hp->h_addr,
2409				INADDRSZ);
2410			break;
2411#endif /* NETINET */
2412
2413#if NETINET6
2414		  case AF_INET6:
2415			memmove(&addr.sin6.sin6_addr,
2416				hp->h_addr,
2417				IN6ADDRSZ);
2418			break;
2419#endif /* NETINET6 */
2420
2421		  default:
2422			if (hp->h_length > sizeof(addr.sa.sa_data))
2423			{
2424				syserr("makeconnection: long sa_data: family %d len %d",
2425					hp->h_addrtype, hp->h_length);
2426				mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
2427				errno = EINVAL;
2428				return EX_NOHOST;
2429			}
2430			memmove(addr.sa.sa_data, hp->h_addr, hp->h_length);
2431			break;
2432		}
2433		addrno = 1;
2434	}
2435
2436	/*
2437	**  Determine the port number.
2438	*/
2439
2440	if (port == 0)
2441	{
2442#ifdef NO_GETSERVBYNAME
2443		port = htons(25);
2444#else /* NO_GETSERVBYNAME */
2445		register struct servent *sp = getservbyname("smtp", "tcp");
2446
2447		if (sp == NULL)
2448		{
2449			if (LogLevel > 2)
2450				sm_syslog(LOG_ERR, NOQID,
2451					  "makeconnection: service \"smtp\" unknown");
2452			port = htons(25);
2453		}
2454		else
2455			port = sp->s_port;
2456#endif /* NO_GETSERVBYNAME */
2457	}
2458
2459#if NETINET6
2460	if (addr.sa.sa_family == AF_INET6 &&
2461	    IN6_IS_ADDR_V4MAPPED(&addr.sin6.sin6_addr) &&
2462	    ClientSettings[AF_INET].d_addr.sa.sa_family != 0)
2463	{
2464		/*
2465		**  Ignore mapped IPv4 address since
2466		**  there is a ClientPortOptions setting
2467		**  for IPv4.
2468		*/
2469
2470		goto nextaddr;
2471	}
2472#endif /* NETINET6 */
2473
2474	switch (addr.sa.sa_family)
2475	{
2476#if NETINET
2477	  case AF_INET:
2478		addr.sin.sin_port = port;
2479		addrlen = sizeof(struct sockaddr_in);
2480		break;
2481#endif /* NETINET */
2482
2483#if NETINET6
2484	  case AF_INET6:
2485		addr.sin6.sin6_port = port;
2486		addrlen = sizeof(struct sockaddr_in6);
2487		break;
2488#endif /* NETINET6 */
2489
2490#if NETISO
2491	  case AF_ISO:
2492		/* assume two byte transport selector */
2493		memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
2494		addrlen = sizeof(struct sockaddr_iso);
2495		break;
2496#endif /* NETISO */
2497
2498	  default:
2499		syserr("Can't connect to address family %d", addr.sa.sa_family);
2500		mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
2501		errno = EINVAL;
2502#if NETINET6
2503		if (hp != NULL)
2504			freehostent(hp);
2505#endif /* NETINET6 */
2506		return EX_NOHOST;
2507	}
2508
2509	/*
2510	**  Try to actually open the connection.
2511	*/
2512
2513#if XLA
2514	/* if too many connections, don't bother trying */
2515	if (!xla_noqueue_ok(host))
2516	{
2517# if NETINET6
2518		if (hp != NULL)
2519			freehostent(hp);
2520# endif /* NETINET6 */
2521		return EX_TEMPFAIL;
2522	}
2523#endif /* XLA */
2524
2525	for (;;)
2526	{
2527		if (tTd(16, 1))
2528			sm_dprintf("makeconnection (%s [%s].%d (%d))\n",
2529				   host, anynet_ntoa(&addr), ntohs(port),
2530				   (int) addr.sa.sa_family);
2531
2532		/* save for logging */
2533		CurHostAddr = addr;
2534
2535#if HASRRESVPORT
2536		if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
2537		{
2538			int rport = IPPORT_RESERVED - 1;
2539
2540			s = rresvport(&rport);
2541		}
2542		else
2543#endif /* HASRRESVPORT */
2544		{
2545			s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
2546		}
2547		if (s < 0)
2548		{
2549			save_errno = errno;
2550			syserr("makeconnection: cannot create socket");
2551#if XLA
2552			xla_host_end(host);
2553#endif /* XLA */
2554			mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2555#if NETINET6
2556			if (hp != NULL)
2557				freehostent(hp);
2558#endif /* NETINET6 */
2559			errno = save_errno;
2560			return EX_TEMPFAIL;
2561		}
2562
2563#ifdef SO_SNDBUF
2564		if (ClientSettings[family].d_tcpsndbufsize > 0)
2565		{
2566			if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
2567				       (char *) &ClientSettings[family].d_tcpsndbufsize,
2568				       sizeof(ClientSettings[family].d_tcpsndbufsize)) < 0)
2569				syserr("makeconnection: setsockopt(SO_SNDBUF)");
2570		}
2571#endif /* SO_SNDBUF */
2572#ifdef SO_RCVBUF
2573		if (ClientSettings[family].d_tcprcvbufsize > 0)
2574		{
2575			if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
2576				       (char *) &ClientSettings[family].d_tcprcvbufsize,
2577				       sizeof(ClientSettings[family].d_tcprcvbufsize)) < 0)
2578				syserr("makeconnection: setsockopt(SO_RCVBUF)");
2579		}
2580#endif /* SO_RCVBUF */
2581
2582		if (tTd(16, 1))
2583			sm_dprintf("makeconnection: fd=%d\n", s);
2584
2585		/* turn on network debugging? */
2586		if (tTd(16, 101))
2587		{
2588			int on = 1;
2589
2590			(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
2591					  (char *)&on, sizeof(on));
2592		}
2593		if (e->e_xfp != NULL)	/* for debugging */
2594			(void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT);
2595		errno = 0;		/* for debugging */
2596
2597		if (clt_bind)
2598		{
2599			int on = 1;
2600
2601			switch (clt_addr.sa.sa_family)
2602			{
2603#if NETINET
2604			  case AF_INET:
2605				if (clt_addr.sin.sin_port != 0)
2606					(void) setsockopt(s, SOL_SOCKET,
2607							  SO_REUSEADDR,
2608							  (char *) &on,
2609							  sizeof(on));
2610				break;
2611#endif /* NETINET */
2612
2613#if NETINET6
2614			  case AF_INET6:
2615				if (clt_addr.sin6.sin6_port != 0)
2616					(void) setsockopt(s, SOL_SOCKET,
2617							  SO_REUSEADDR,
2618							  (char *) &on,
2619							  sizeof(on));
2620				break;
2621#endif /* NETINET6 */
2622			}
2623
2624			if (bind(s, &clt_addr.sa, socksize) < 0)
2625			{
2626				save_errno = errno;
2627				(void) close(s);
2628				errno = save_errno;
2629				syserr("makeconnection: cannot bind socket [%s]",
2630				       anynet_ntoa(&clt_addr));
2631#if NETINET6
2632				if (hp != NULL)
2633					freehostent(hp);
2634#endif /* NETINET6 */
2635				errno = save_errno;
2636				return EX_TEMPFAIL;
2637			}
2638		}
2639
2640		/*
2641		**  Linux seems to hang in connect for 90 minutes (!!!).
2642		**  Time out the connect to avoid this problem.
2643		*/
2644
2645		if (setjmp(CtxConnectTimeout) == 0)
2646		{
2647			int i;
2648
2649			if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
2650				ev = sm_setevent(TimeOuts.to_iconnect,
2651						 connecttimeout, 0);
2652			else if (TimeOuts.to_connect != 0)
2653				ev = sm_setevent(TimeOuts.to_connect,
2654						 connecttimeout, 0);
2655			else
2656				ev = NULL;
2657
2658			switch (ConnectOnlyTo.sa.sa_family)
2659			{
2660#if NETINET
2661			  case AF_INET:
2662				addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr;
2663				break;
2664#endif /* NETINET */
2665
2666#if NETINET6
2667			  case AF_INET6:
2668				memmove(&addr.sin6.sin6_addr,
2669					&ConnectOnlyTo.sin6.sin6_addr,
2670					IN6ADDRSZ);
2671				break;
2672#endif /* NETINET6 */
2673			}
2674			if (tTd(16, 1))
2675				sm_dprintf("Connecting to [%s]...\n", anynet_ntoa(&addr));
2676			i = connect(s, (struct sockaddr *) &addr, addrlen);
2677			save_errno = errno;
2678			if (ev != NULL)
2679				sm_clrevent(ev);
2680			if (i >= 0)
2681				break;
2682		}
2683		else
2684			save_errno = errno;
2685
2686		/* couldn't connect.... figure out why */
2687		(void) close(s);
2688
2689		/* if running demand-dialed connection, try again */
2690		if (DialDelay > 0 && firstconnect &&
2691		    bitnset(M_DIALDELAY, mci->mci_mailer->m_flags))
2692		{
2693			if (tTd(16, 1))
2694				sm_dprintf("Connect failed (%s); trying again...\n",
2695					   sm_errstring(save_errno));
2696			firstconnect = false;
2697			(void) sleep(DialDelay);
2698			continue;
2699		}
2700
2701		if (LogLevel > 13)
2702			sm_syslog(LOG_INFO, e->e_id,
2703				  "makeconnection (%s [%s]) failed: %s",
2704				  host, anynet_ntoa(&addr),
2705				  sm_errstring(save_errno));
2706
2707#if NETINET6
2708nextaddr:
2709#endif /* NETINET6 */
2710		if (hp != NULL && hp->h_addr_list[addrno] != NULL &&
2711		    (enough == 0 || curtime() < enough))
2712		{
2713			if (tTd(16, 1))
2714				sm_dprintf("Connect failed (%s); trying new address....\n",
2715					   sm_errstring(save_errno));
2716			switch (addr.sa.sa_family)
2717			{
2718#if NETINET
2719			  case AF_INET:
2720				memmove(&addr.sin.sin_addr,
2721					hp->h_addr_list[addrno++],
2722					INADDRSZ);
2723				break;
2724#endif /* NETINET */
2725
2726#if NETINET6
2727			  case AF_INET6:
2728				memmove(&addr.sin6.sin6_addr,
2729					hp->h_addr_list[addrno++],
2730					IN6ADDRSZ);
2731				break;
2732#endif /* NETINET6 */
2733
2734			  default:
2735				memmove(addr.sa.sa_data,
2736					hp->h_addr_list[addrno++],
2737					hp->h_length);
2738				break;
2739			}
2740			continue;
2741		}
2742		errno = save_errno;
2743
2744#if NETINET6
2745		if (family == AF_INET6)
2746		{
2747			if (tTd(16, 1))
2748				sm_dprintf("Connect failed (%s); retrying with AF_INET....\n",
2749					   sm_errstring(save_errno));
2750			v6found = true;
2751			family = AF_INET;
2752			if (hp != NULL)
2753			{
2754				freehostent(hp);
2755				hp = NULL;
2756			}
2757			goto v4retry;
2758		}
2759	v6tempfail:
2760#endif /* NETINET6 */
2761		/* couldn't open connection */
2762#if NETINET6
2763		/* Don't clobber an already saved errno from v4retry */
2764		if (errno > 0)
2765#endif /* NETINET6 */
2766			save_errno = errno;
2767		if (tTd(16, 1))
2768			sm_dprintf("Connect failed (%s)\n",
2769				   sm_errstring(save_errno));
2770#if XLA
2771		xla_host_end(host);
2772#endif /* XLA */
2773		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
2774#if NETINET6
2775		if (hp != NULL)
2776			freehostent(hp);
2777#endif /* NETINET6 */
2778		errno = save_errno;
2779		return EX_TEMPFAIL;
2780	}
2781
2782#if NETINET6
2783	if (hp != NULL)
2784	{
2785		freehostent(hp);
2786		hp = NULL;
2787	}
2788#endif /* NETINET6 */
2789
2790	/* connection ok, put it into canonical form */
2791	mci->mci_out = NULL;
2792	if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
2793				       (void *) &s,
2794				       SM_IO_WRONLY_B, NULL)) == NULL ||
2795	    (s = dup(s)) < 0 ||
2796	    (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
2797				      (void *) &s,
2798				      SM_IO_RDONLY_B, NULL)) == NULL)
2799	{
2800		save_errno = errno;
2801		syserr("cannot open SMTP client channel, fd=%d", s);
2802		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2803		if (mci->mci_out != NULL)
2804			(void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT);
2805		(void) close(s);
2806		errno = save_errno;
2807		return EX_TEMPFAIL;
2808	}
2809	sm_io_automode(mci->mci_out, mci->mci_in);
2810
2811	/* set {client_flags} */
2812	if (ClientSettings[addr.sa.sa_family].d_mflags != NULL)
2813	{
2814		macdefine(&mci->mci_macro, A_PERM,
2815			  macid("{client_flags}"),
2816			  ClientSettings[addr.sa.sa_family].d_mflags);
2817	}
2818	else
2819		macdefine(&mci->mci_macro, A_PERM,
2820			  macid("{client_flags}"), "");
2821
2822	/* "add" {client_flags} to bitmap */
2823	if (bitnset(D_IFNHELO, ClientSettings[addr.sa.sa_family].d_flags))
2824	{
2825		/* look for just this one flag */
2826		setbitn(D_IFNHELO, d_flags);
2827	}
2828
2829	/* find out name for Interface through which we connect */
2830	len = sizeof(addr);
2831	if (getsockname(s, &addr.sa, &len) == 0)
2832	{
2833		char *name;
2834		char family[5];
2835
2836		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2837			macid("{if_addr_out}"), anynet_ntoa(&addr));
2838		(void) sm_snprintf(family, sizeof(family), "%d",
2839			addr.sa.sa_family);
2840		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2841			macid("{if_family_out}"), family);
2842
2843		name = hostnamebyanyaddr(&addr);
2844		macdefine(&BlankEnvelope.e_macro, A_TEMP,
2845			macid("{if_name_out}"), name);
2846		if (LogLevel > 11)
2847		{
2848			/* log connection information */
2849			sm_syslog(LOG_INFO, e->e_id,
2850				  "SMTP outgoing connect on %.40s", name);
2851		}
2852		if (bitnset(D_IFNHELO, d_flags))
2853		{
2854			if (name[0] != '[' && strchr(name, '.') != NULL)
2855				mci->mci_heloname = newstr(name);
2856		}
2857	}
2858	else
2859	{
2860		macdefine(&BlankEnvelope.e_macro, A_PERM,
2861			macid("{if_name_out}"), NULL);
2862		macdefine(&BlankEnvelope.e_macro, A_PERM,
2863			macid("{if_addr_out}"), NULL);
2864		macdefine(&BlankEnvelope.e_macro, A_PERM,
2865			macid("{if_family_out}"), NULL);
2866	}
2867
2868	/* Use the configured HeloName as appropriate */
2869	if (HeloName != NULL && HeloName[0] != '\0')
2870		mci->mci_heloname = newstr(HeloName);
2871
2872	mci_setstat(mci, EX_OK, NULL, NULL);
2873	return EX_OK;
2874}
2875
2876static void
2877connecttimeout(ignore)
2878	int ignore;
2879{
2880	/*
2881	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2882	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2883	**	DOING.
2884	*/
2885
2886	errno = ETIMEDOUT;
2887	longjmp(CtxConnectTimeout, 1);
2888}
2889/*
2890**  MAKECONNECTION_DS -- make a connection to a domain socket.
2891**
2892**	Parameters:
2893**		mux_path -- the path of the socket to connect to.
2894**		mci -- a pointer to the mail connection information
2895**			structure to be filled in.
2896**
2897**	Returns:
2898**		An exit code telling whether the connection could be
2899**			made and if not why not.
2900**
2901**	Side Effects:
2902**		none.
2903*/
2904
2905#if NETUNIX
2906int
2907makeconnection_ds(mux_path, mci)
2908	char *mux_path;
2909	register MCI *mci;
2910{
2911	int sock;
2912	int rval, save_errno;
2913	long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK;
2914	struct sockaddr_un unix_addr;
2915
2916	/* if not safe, don't connect */
2917	rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName,
2918			sff, S_IRUSR|S_IWUSR, NULL);
2919
2920	if (rval != 0)
2921	{
2922		syserr("makeconnection_ds: unsafe domain socket %s",
2923			mux_path);
2924		mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
2925		errno = rval;
2926		return EX_TEMPFAIL;
2927	}
2928
2929	/* prepare address structure */
2930	memset(&unix_addr, '\0', sizeof(unix_addr));
2931	unix_addr.sun_family = AF_UNIX;
2932
2933	if (strlen(mux_path) >= sizeof(unix_addr.sun_path))
2934	{
2935		syserr("makeconnection_ds: domain socket name %s too long",
2936			mux_path);
2937
2938		/* XXX why TEMPFAIL but 5.x.y ? */
2939		mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
2940		errno = ENAMETOOLONG;
2941		return EX_UNAVAILABLE;
2942	}
2943	(void) sm_strlcpy(unix_addr.sun_path, mux_path,
2944			  sizeof(unix_addr.sun_path));
2945
2946	/* initialize domain socket */
2947	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2948	if (sock == -1)
2949	{
2950		save_errno = errno;
2951		syserr("makeconnection_ds: could not create domain socket %s",
2952			mux_path);
2953		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2954		errno = save_errno;
2955		return EX_TEMPFAIL;
2956	}
2957
2958	/* connect to server */
2959	if (connect(sock, (struct sockaddr *) &unix_addr,
2960		    sizeof(unix_addr)) == -1)
2961	{
2962		save_errno = errno;
2963		syserr("Could not connect to socket %s", mux_path);
2964		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
2965		(void) close(sock);
2966		errno = save_errno;
2967		return EX_TEMPFAIL;
2968	}
2969
2970	/* connection ok, put it into canonical form */
2971	mci->mci_out = NULL;
2972	if ((mci->mci_out = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
2973				       (void *) &sock, SM_IO_WRONLY_B, NULL))
2974					== NULL
2975	    || (sock = dup(sock)) < 0 ||
2976	    (mci->mci_in = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
2977				      (void *) &sock, SM_IO_RDONLY_B, NULL))
2978					== NULL)
2979	{
2980		save_errno = errno;
2981		syserr("cannot open SMTP client channel, fd=%d", sock);
2982		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2983		if (mci->mci_out != NULL)
2984			(void) sm_io_close(mci->mci_out, SM_TIME_DEFAULT);
2985		(void) close(sock);
2986		errno = save_errno;
2987		return EX_TEMPFAIL;
2988	}
2989	sm_io_automode(mci->mci_out, mci->mci_in);
2990
2991	mci_setstat(mci, EX_OK, NULL, NULL);
2992	errno = 0;
2993	return EX_OK;
2994}
2995#endif /* NETUNIX */
2996/*
2997**  SHUTDOWN_DAEMON -- Performs a clean shutdown of the daemon
2998**
2999**	Parameters:
3000**		none.
3001**
3002**	Returns:
3003**		none.
3004**
3005**	Side Effects:
3006**		closes control socket, exits.
3007*/
3008
3009void
3010shutdown_daemon()
3011{
3012	int i;
3013	char *reason;
3014
3015	sm_allsignals(true);
3016
3017	reason = ShutdownRequest;
3018	ShutdownRequest = NULL;
3019	PendingSignal = 0;
3020
3021	if (LogLevel > 9)
3022		sm_syslog(LOG_INFO, CurEnv->e_id, "stopping daemon, reason=%s",
3023			  reason == NULL ? "implicit call" : reason);
3024
3025	FileName = NULL;
3026	closecontrolsocket(true);
3027#if XLA
3028	xla_all_end();
3029#endif /* XLA */
3030
3031	for (i = 0; i < NDaemons; i++)
3032	{
3033		if (Daemons[i].d_socket >= 0)
3034		{
3035			(void) close(Daemons[i].d_socket);
3036			Daemons[i].d_socket = -1;
3037
3038#if _FFR_DAEMON_NETUNIX
3039# if NETUNIX
3040			/* Remove named sockets */
3041			if (Daemons[i].d_addr.sa.sa_family == AF_UNIX)
3042			{
3043				int rval;
3044				long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_MUSTOWN|SFF_EXECOK|SFF_CREAT;
3045
3046				/* if not safe, don't use it */
3047				rval = safefile(Daemons[i].d_addr.sunix.sun_path,
3048						RunAsUid, RunAsGid,
3049						RunAsUserName, sff,
3050						S_IRUSR|S_IWUSR, NULL);
3051				if (rval == 0 &&
3052				    unlink(Daemons[i].d_addr.sunix.sun_path) < 0)
3053				{
3054					sm_syslog(LOG_WARNING, NOQID,
3055						  "Could not remove daemon %s socket: %s: %s",
3056						  Daemons[i].d_name,
3057						  Daemons[i].d_addr.sunix.sun_path,
3058						  sm_errstring(errno));
3059				}
3060			}
3061# endif /* NETUNIX */
3062#endif	/* _FFR_DAEMON_NETUNIX */
3063		}
3064	}
3065
3066	finis(false, true, EX_OK);
3067}
3068/*
3069**  RESTART_DAEMON -- Performs a clean restart of the daemon
3070**
3071**	Parameters:
3072**		none.
3073**
3074**	Returns:
3075**		none.
3076**
3077**	Side Effects:
3078**		restarts the daemon or exits if restart fails.
3079*/
3080
3081/* Make a non-DFL/IGN signal a noop */
3082#define SM_NOOP_SIGNAL(sig, old)				\
3083do								\
3084{								\
3085	(old) = sm_signal((sig), sm_signal_noop);		\
3086	if ((old) == SIG_IGN || (old) == SIG_DFL)		\
3087		(void) sm_signal((sig), (old));			\
3088} while (0)
3089
3090void
3091restart_daemon()
3092{
3093	bool drop;
3094	int save_errno;
3095	char *reason;
3096	sigfunc_t ignore, oalrm, ousr1;
3097	extern int DtableSize;
3098
3099	/* clear the events to turn off SIGALRMs */
3100	sm_clear_events();
3101	sm_allsignals(true);
3102
3103	reason = RestartRequest;
3104	RestartRequest = NULL;
3105	PendingSignal = 0;
3106
3107	if (SaveArgv[0][0] != '/')
3108	{
3109		if (LogLevel > 3)
3110			sm_syslog(LOG_INFO, NOQID,
3111				  "could not restart: need full path");
3112		finis(false, true, EX_OSFILE);
3113		/* NOTREACHED */
3114	}
3115	if (LogLevel > 3)
3116		sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s",
3117			  SaveArgv[0],
3118			  reason == NULL ? "implicit call" : reason);
3119
3120	closecontrolsocket(true);
3121#if SM_CONF_SHM
3122	cleanup_shm(DaemonPid == getpid());
3123#endif /* SM_CONF_SHM */
3124
3125	/* close locked pid file */
3126	close_sendmail_pid();
3127
3128	/*
3129	**  Want to drop to the user who started the process in all cases
3130	**  *but* when running as "smmsp" for the clientmqueue queue run
3131	**  daemon.  In that case, UseMSP will be true, RunAsUid should not
3132	**  be root, and RealUid should be either 0 or RunAsUid.
3133	*/
3134
3135	drop = !(UseMSP && RunAsUid != 0 &&
3136		 (RealUid == 0 || RealUid == RunAsUid));
3137
3138	if (drop_privileges(drop) != EX_OK)
3139	{
3140		if (LogLevel > 0)
3141			sm_syslog(LOG_ALERT, NOQID,
3142				  "could not drop privileges: %s",
3143				  sm_errstring(errno));
3144		finis(false, true, EX_OSERR);
3145		/* NOTREACHED */
3146	}
3147
3148	sm_close_on_exec(STDERR_FILENO + 1, DtableSize);
3149
3150	/*
3151	**  Need to allow signals before execve() to make them "harmless".
3152	**  However, the default action can be "terminate", so it isn't
3153	**  really harmless.  Setting signals to IGN will cause them to be
3154	**  ignored in the new process to, so that isn't a good alternative.
3155	*/
3156
3157	SM_NOOP_SIGNAL(SIGALRM, oalrm);
3158	SM_NOOP_SIGNAL(SIGCHLD, ignore);
3159	SM_NOOP_SIGNAL(SIGHUP, ignore);
3160	SM_NOOP_SIGNAL(SIGINT, ignore);
3161	SM_NOOP_SIGNAL(SIGPIPE, ignore);
3162	SM_NOOP_SIGNAL(SIGTERM, ignore);
3163#ifdef SIGUSR1
3164	SM_NOOP_SIGNAL(SIGUSR1, ousr1);
3165#endif /* SIGUSR1 */
3166
3167	/* Turn back on signals */
3168	sm_allsignals(false);
3169
3170	(void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron);
3171	save_errno = errno;
3172
3173	/* block signals again and restore needed signals */
3174	sm_allsignals(true);
3175
3176	/* For finis() events */
3177	(void) sm_signal(SIGALRM, oalrm);
3178
3179#ifdef SIGUSR1
3180	/* For debugging finis() */
3181	(void) sm_signal(SIGUSR1, ousr1);
3182#endif /* SIGUSR1 */
3183
3184	errno = save_errno;
3185	if (LogLevel > 0)
3186		sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %s",
3187			  SaveArgv[0], sm_errstring(errno));
3188	finis(false, true, EX_OSFILE);
3189	/* NOTREACHED */
3190}
3191/*
3192**  MYHOSTNAME -- return the name of this host.
3193**
3194**	Parameters:
3195**		hostbuf -- a place to return the name of this host.
3196**		size -- the size of hostbuf.
3197**
3198**	Returns:
3199**		A list of aliases for this host.
3200**
3201**	Side Effects:
3202**		Adds numeric codes to $=w.
3203*/
3204
3205struct hostent *
3206myhostname(hostbuf, size)
3207	char hostbuf[];
3208	int size;
3209{
3210	register struct hostent *hp;
3211
3212	if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0')
3213		(void) sm_strlcpy(hostbuf, "localhost", size);
3214	hp = sm_gethostbyname(hostbuf, InetMode);
3215#if NETINET && NETINET6
3216	if (hp == NULL && InetMode == AF_INET6)
3217	{
3218		/*
3219		**  It's possible that this IPv6 enabled machine doesn't
3220		**  actually have any IPv6 interfaces and, therefore, no
3221		**  IPv6 addresses.  Fall back to AF_INET.
3222		*/
3223
3224		hp = sm_gethostbyname(hostbuf, AF_INET);
3225	}
3226#endif /* NETINET && NETINET6 */
3227	if (hp == NULL)
3228		return NULL;
3229	if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
3230		(void) cleanstrcpy(hostbuf, hp->h_name, size);
3231
3232#if NETINFO
3233	if (strchr(hostbuf, '.') == NULL)
3234	{
3235		char *domainname;
3236
3237		domainname = ni_propval("/locations", NULL, "resolver",
3238					"domain", '\0');
3239		if (domainname != NULL &&
3240		    strlen(domainname) + strlen(hostbuf) + 1 < size)
3241			(void) sm_strlcat2(hostbuf, ".", domainname, size);
3242	}
3243#endif /* NETINFO */
3244
3245	/*
3246	**  If there is still no dot in the name, try looking for a
3247	**  dotted alias.
3248	*/
3249
3250	if (strchr(hostbuf, '.') == NULL)
3251	{
3252		char **ha;
3253
3254		for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
3255		{
3256			if (strchr(*ha, '.') != NULL)
3257			{
3258				(void) cleanstrcpy(hostbuf, *ha, size - 1);
3259				hostbuf[size - 1] = '\0';
3260				break;
3261			}
3262		}
3263	}
3264
3265	/*
3266	**  If _still_ no dot, wait for a while and try again -- it is
3267	**  possible that some service is starting up.  This can result
3268	**  in excessive delays if the system is badly configured, but
3269	**  there really isn't a way around that, particularly given that
3270	**  the config file hasn't been read at this point.
3271	**  All in all, a bit of a mess.
3272	*/
3273
3274	if (strchr(hostbuf, '.') == NULL &&
3275	    !getcanonname(hostbuf, size, true, NULL))
3276	{
3277		sm_syslog(LOG_CRIT, NOQID,
3278			  "My unqualified host name (%s) unknown; sleeping for retry",
3279			  hostbuf);
3280		message("My unqualified host name (%s) unknown; sleeping for retry",
3281			hostbuf);
3282		(void) sleep(60);
3283		if (!getcanonname(hostbuf, size, true, NULL))
3284		{
3285			sm_syslog(LOG_ALERT, NOQID,
3286				  "unable to qualify my own domain name (%s) -- using short name",
3287				  hostbuf);
3288			message("WARNING: unable to qualify my own domain name (%s) -- using short name",
3289				hostbuf);
3290		}
3291	}
3292	return hp;
3293}
3294/*
3295**  ADDRCMP -- compare two host addresses
3296**
3297**	Parameters:
3298**		hp -- hostent structure for the first address
3299**		ha -- actual first address
3300**		sa -- second address
3301**
3302**	Returns:
3303**		0 -- if ha and sa match
3304**		else -- they don't match
3305*/
3306
3307static int
3308addrcmp(hp, ha, sa)
3309	struct hostent *hp;
3310	char *ha;
3311	SOCKADDR *sa;
3312{
3313#if NETINET6
3314	unsigned char *a;
3315#endif /* NETINET6 */
3316
3317	switch (sa->sa.sa_family)
3318	{
3319#if NETINET
3320	  case AF_INET:
3321		if (hp->h_addrtype == AF_INET)
3322			return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ);
3323		break;
3324#endif /* NETINET */
3325
3326#if NETINET6
3327	  case AF_INET6:
3328		a = (unsigned char *) &sa->sin6.sin6_addr;
3329
3330		/* Straight binary comparison */
3331		if (hp->h_addrtype == AF_INET6)
3332			return memcmp(ha, a, IN6ADDRSZ);
3333
3334		/* If IPv4-mapped IPv6 address, compare the IPv4 section */
3335		if (hp->h_addrtype == AF_INET &&
3336		    IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr))
3337			return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ);
3338		break;
3339#endif /* NETINET6 */
3340	}
3341	return -1;
3342}
3343/*
3344**  GETAUTHINFO -- get the real host name associated with a file descriptor
3345**
3346**	Uses RFC1413 protocol to try to get info from the other end.
3347**
3348**	Parameters:
3349**		fd -- the descriptor
3350**		may_be_forged -- an outage that is set to true if the
3351**			forward lookup of RealHostName does not match
3352**			RealHostAddr; set to false if they do match.
3353**
3354**	Returns:
3355**		The user@host information associated with this descriptor.
3356*/
3357
3358static jmp_buf	CtxAuthTimeout;
3359
3360static void
3361authtimeout(ignore)
3362	int ignore;
3363{
3364	/*
3365	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3366	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3367	**	DOING.
3368	*/
3369
3370	errno = ETIMEDOUT;
3371	longjmp(CtxAuthTimeout, 1);
3372}
3373
3374char *
3375getauthinfo(fd, may_be_forged)
3376	int fd;
3377	bool *may_be_forged;
3378{
3379	unsigned short SM_NONVOLATILE port = 0;
3380	SOCKADDR_LEN_T falen;
3381	register char *volatile p = NULL;
3382	SOCKADDR la;
3383	SOCKADDR_LEN_T lalen;
3384#ifndef NO_GETSERVBYNAME
3385	register struct servent *sp;
3386# if NETINET
3387	static unsigned short port4 = 0;
3388# endif /* NETINET */
3389# if NETINET6
3390	static unsigned short port6 = 0;
3391# endif /* NETINET6 */
3392#endif /* ! NO_GETSERVBYNAME */
3393	volatile int s;
3394	int i = 0;
3395	size_t len;
3396	SM_EVENT *ev;
3397	int nleft;
3398	struct hostent *hp;
3399	char *ostype = NULL;
3400	char **ha;
3401	char ibuf[MAXNAME + 1];
3402	static char hbuf[MAXNAME + MAXAUTHINFO + 11];
3403
3404	*may_be_forged = false;
3405	falen = sizeof(RealHostAddr);
3406	if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
3407	    falen <= 0 || RealHostAddr.sa.sa_family == 0)
3408	{
3409		if (i < 0)
3410		{
3411			/*
3412			**  ENOTSOCK is OK: bail on anything else, but reset
3413			**  errno in this case, so a mis-report doesn't
3414			**  happen later.
3415			*/
3416
3417			if (errno != ENOTSOCK)
3418				return NULL;
3419			errno = 0;
3420		}
3421		(void) sm_strlcpyn(hbuf, sizeof(hbuf), 2, RealUserName,
3422				   "@localhost");
3423		if (tTd(9, 1))
3424			sm_dprintf("getauthinfo: %s\n", hbuf);
3425		return hbuf;
3426	}
3427
3428	if (RealHostName == NULL)
3429	{
3430		/* translate that to a host name */
3431		RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
3432		if (strlen(RealHostName) > MAXNAME)
3433			RealHostName[MAXNAME] = '\0'; /* XXX - 1 ? */
3434	}
3435
3436	/* cross check RealHostName with forward DNS lookup */
3437	if (anynet_ntoa(&RealHostAddr)[0] != '[' &&
3438	    RealHostName[0] != '[')
3439	{
3440		int family;
3441
3442		family = RealHostAddr.sa.sa_family;
3443#if NETINET6 && NEEDSGETIPNODE
3444		/*
3445		**  If RealHostAddr is an IPv6 connection with an
3446		**  IPv4-mapped address, we need RealHostName's IPv4
3447		**  address(es) for addrcmp() to compare against
3448		**  RealHostAddr.
3449		**
3450		**  Actually, we only need to do this for systems
3451		**  which NEEDSGETIPNODE since the real getipnodebyname()
3452		**  already does V4MAPPED address via the AI_V4MAPPEDCFG
3453		**  flag.  A better fix to this problem is to add this
3454		**  functionality to our stub getipnodebyname().
3455		*/
3456
3457		if (family == AF_INET6 &&
3458		    IN6_IS_ADDR_V4MAPPED(&RealHostAddr.sin6.sin6_addr))
3459			family = AF_INET;
3460#endif /* NETINET6 && NEEDSGETIPNODE */
3461
3462		/* try to match the reverse against the forward lookup */
3463		hp = sm_gethostbyname(RealHostName, family);
3464		if (hp == NULL)
3465		{
3466			/* XXX: Could be a temporary error on forward lookup */
3467			*may_be_forged = true;
3468		}
3469		else
3470		{
3471			for (ha = hp->h_addr_list; *ha != NULL; ha++)
3472			{
3473				if (addrcmp(hp, *ha, &RealHostAddr) == 0)
3474					break;
3475			}
3476			*may_be_forged = *ha == NULL;
3477#if NETINET6
3478			freehostent(hp);
3479			hp = NULL;
3480#endif /* NETINET6 */
3481		}
3482	}
3483
3484	if (TimeOuts.to_ident == 0)
3485		goto noident;
3486
3487	lalen = sizeof(la);
3488	switch (RealHostAddr.sa.sa_family)
3489	{
3490#if NETINET
3491	  case AF_INET:
3492		if (getsockname(fd, &la.sa, &lalen) < 0 ||
3493		    lalen <= 0 ||
3494		    la.sa.sa_family != AF_INET)
3495		{
3496			/* no ident info */
3497			goto noident;
3498		}
3499		port = RealHostAddr.sin.sin_port;
3500
3501		/* create ident query */
3502		(void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n",
3503				ntohs(RealHostAddr.sin.sin_port),
3504				ntohs(la.sin.sin_port));
3505
3506		/* create local address */
3507		la.sin.sin_port = 0;
3508
3509		/* create foreign address */
3510# ifdef NO_GETSERVBYNAME
3511		RealHostAddr.sin.sin_port = htons(113);
3512# else /* NO_GETSERVBYNAME */
3513
3514		/*
3515		**  getservbyname() consumes about 5% of the time
3516		**  when receiving a small message (almost all of the time
3517		**  spent in this routine).
3518		**  Hence we store the port in a static variable
3519		**  to save this time.
3520		**  The portnumber shouldn't change very often...
3521		**  This code makes the assumption that the port number
3522		**  is not 0.
3523		*/
3524
3525		if (port4 == 0)
3526		{
3527			sp = getservbyname("auth", "tcp");
3528			if (sp != NULL)
3529				port4 = sp->s_port;
3530			else
3531				port4 = htons(113);
3532		}
3533		RealHostAddr.sin.sin_port = port4;
3534		break;
3535# endif /* NO_GETSERVBYNAME */
3536#endif /* NETINET */
3537
3538#if NETINET6
3539	  case AF_INET6:
3540		if (getsockname(fd, &la.sa, &lalen) < 0 ||
3541		    lalen <= 0 ||
3542		    la.sa.sa_family != AF_INET6)
3543		{
3544			/* no ident info */
3545			goto noident;
3546		}
3547		port = RealHostAddr.sin6.sin6_port;
3548
3549		/* create ident query */
3550		(void) sm_snprintf(ibuf, sizeof(ibuf), "%d,%d\r\n",
3551				ntohs(RealHostAddr.sin6.sin6_port),
3552				ntohs(la.sin6.sin6_port));
3553
3554		/* create local address */
3555		la.sin6.sin6_port = 0;
3556
3557		/* create foreign address */
3558# ifdef NO_GETSERVBYNAME
3559		RealHostAddr.sin6.sin6_port = htons(113);
3560# else /* NO_GETSERVBYNAME */
3561		if (port6 == 0)
3562		{
3563			sp = getservbyname("auth", "tcp");
3564			if (sp != NULL)
3565				port6 = sp->s_port;
3566			else
3567				port6 = htons(113);
3568		}
3569		RealHostAddr.sin6.sin6_port = port6;
3570		break;
3571# endif /* NO_GETSERVBYNAME */
3572#endif /* NETINET6 */
3573	  default:
3574		/* no ident info */
3575		goto noident;
3576	}
3577
3578	s = -1;
3579	if (setjmp(CtxAuthTimeout) != 0)
3580	{
3581		if (s >= 0)
3582			(void) close(s);
3583		goto noident;
3584	}
3585
3586	/* put a timeout around the whole thing */
3587	ev = sm_setevent(TimeOuts.to_ident, authtimeout, 0);
3588
3589	/* connect to foreign IDENT server using same address as SMTP socket */
3590	s = socket(la.sa.sa_family, SOCK_STREAM, 0);
3591	if (s < 0)
3592	{
3593		sm_clrevent(ev);
3594		goto noident;
3595	}
3596	if (bind(s, &la.sa, lalen) < 0 ||
3597	    connect(s, &RealHostAddr.sa, lalen) < 0)
3598		goto closeident;
3599
3600	if (tTd(9, 10))
3601		sm_dprintf("getauthinfo: sent %s", ibuf);
3602
3603	/* send query */
3604	if (write(s, ibuf, strlen(ibuf)) < 0)
3605		goto closeident;
3606
3607	/* get result */
3608	p = &ibuf[0];
3609	nleft = sizeof(ibuf) - 1;
3610	while ((i = read(s, p, nleft)) > 0)
3611	{
3612		char *s;
3613
3614		p += i;
3615		nleft -= i;
3616		*p = '\0';
3617		if ((s = strchr(ibuf, '\n')) != NULL)
3618		{
3619			if (p > s + 1)
3620			{
3621				p = s + 1;
3622				*p = '\0';
3623			}
3624			break;
3625		}
3626		if (nleft <= 0)
3627			break;
3628	}
3629	(void) close(s);
3630	sm_clrevent(ev);
3631	if (i < 0 || p == &ibuf[0])
3632		goto noident;
3633
3634	if (p >= &ibuf[2] && *--p == '\n' && *--p == '\r')
3635		p--;
3636	*++p = '\0';
3637
3638	if (tTd(9, 3))
3639		sm_dprintf("getauthinfo:  got %s\n", ibuf);
3640
3641	/* parse result */
3642	p = strchr(ibuf, ':');
3643	if (p == NULL)
3644	{
3645		/* malformed response */
3646		goto noident;
3647	}
3648	while (isascii(*++p) && isspace(*p))
3649		continue;
3650	if (sm_strncasecmp(p, "userid", 6) != 0)
3651	{
3652		/* presumably an error string */
3653		goto noident;
3654	}
3655	p += 6;
3656	while (isascii(*p) && isspace(*p))
3657		p++;
3658	if (*p++ != ':')
3659	{
3660		/* either useridxx or malformed response */
3661		goto noident;
3662	}
3663
3664	/* p now points to the OSTYPE field */
3665	while (isascii(*p) && isspace(*p))
3666		p++;
3667	ostype = p;
3668	p = strchr(p, ':');
3669	if (p == NULL)
3670	{
3671		/* malformed response */
3672		goto noident;
3673	}
3674	else
3675	{
3676		char *charset;
3677
3678		*p = '\0';
3679		charset = strchr(ostype, ',');
3680		if (charset != NULL)
3681			*charset = '\0';
3682	}
3683
3684	/* 1413 says don't do this -- but it's broken otherwise */
3685	while (isascii(*++p) && isspace(*p))
3686		continue;
3687
3688	/* p now points to the authenticated name -- copy carefully */
3689	if (sm_strncasecmp(ostype, "other", 5) == 0 &&
3690	    (ostype[5] == ' ' || ostype[5] == '\0'))
3691	{
3692		(void) sm_strlcpy(hbuf, "IDENT:", sizeof(hbuf));
3693		cleanstrcpy(&hbuf[6], p, MAXAUTHINFO);
3694	}
3695	else
3696		cleanstrcpy(hbuf, p, MAXAUTHINFO);
3697	len = strlen(hbuf);
3698	(void) sm_strlcpyn(&hbuf[len], sizeof(hbuf) - len, 2, "@",
3699			   RealHostName == NULL ? "localhost" : RealHostName);
3700	goto postident;
3701
3702closeident:
3703	(void) close(s);
3704	sm_clrevent(ev);
3705
3706noident:
3707	/* put back the original incoming port */
3708	switch (RealHostAddr.sa.sa_family)
3709	{
3710#if NETINET
3711	  case AF_INET:
3712		if (port > 0)
3713			RealHostAddr.sin.sin_port = port;
3714		break;
3715#endif /* NETINET */
3716
3717#if NETINET6
3718	  case AF_INET6:
3719		if (port > 0)
3720			RealHostAddr.sin6.sin6_port = port;
3721		break;
3722#endif /* NETINET6 */
3723	}
3724
3725	if (RealHostName == NULL)
3726	{
3727		if (tTd(9, 1))
3728			sm_dprintf("getauthinfo: NULL\n");
3729		return NULL;
3730	}
3731	(void) sm_strlcpy(hbuf, RealHostName, sizeof(hbuf));
3732
3733postident:
3734#if IP_SRCROUTE
3735# ifndef GET_IPOPT_DST
3736#  define GET_IPOPT_DST(dst)	(dst)
3737# endif /* ! GET_IPOPT_DST */
3738	/*
3739	**  Extract IP source routing information.
3740	**
3741	**	Format of output for a connection from site a through b
3742	**	through c to d:
3743	**		loose:      @site-c@site-b:site-a
3744	**		strict:	   !@site-c@site-b:site-a
3745	**
3746	**	o - pointer within ipopt_list structure.
3747	**	q - pointer within ls/ss rr route data
3748	**	p - pointer to hbuf
3749	*/
3750
3751	if (RealHostAddr.sa.sa_family == AF_INET)
3752	{
3753		SOCKOPT_LEN_T ipoptlen;
3754		int j;
3755		unsigned char *q;
3756		unsigned char *o;
3757		int l;
3758		struct IPOPTION ipopt;
3759
3760		ipoptlen = sizeof(ipopt);
3761		if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
3762			       (char *) &ipopt, &ipoptlen) < 0)
3763			goto noipsr;
3764		if (ipoptlen == 0)
3765			goto noipsr;
3766		o = (unsigned char *) ipopt.IP_LIST;
3767		while (o != NULL && o < (unsigned char *) &ipopt + ipoptlen)
3768		{
3769			switch (*o)
3770			{
3771			  case IPOPT_EOL:
3772				o = NULL;
3773				break;
3774
3775			  case IPOPT_NOP:
3776				o++;
3777				break;
3778
3779			  case IPOPT_SSRR:
3780			  case IPOPT_LSRR:
3781				/*
3782				**  Source routing.
3783				**	o[0] is the option type (loose/strict).
3784				**	o[1] is the length of this option,
3785				**		including option type and
3786				**		length.
3787				**	o[2] is the pointer into the route
3788				**		data.
3789				**	o[3] begins the route data.
3790				*/
3791
3792				p = &hbuf[strlen(hbuf)];
3793				l = sizeof(hbuf) - (hbuf - p) - 6;
3794				(void) sm_snprintf(p, SPACELEFT(hbuf, p),
3795					" [%s@%.*s",
3796					*o == IPOPT_SSRR ? "!" : "",
3797					l > 240 ? 120 : l / 2,
3798					inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST)));
3799				i = strlen(p);
3800				p += i;
3801				l -= strlen(p);
3802
3803				j = o[1] / sizeof(struct in_addr) - 1;
3804
3805				/* q skips length and router pointer to data */
3806				q = &o[3];
3807				for ( ; j >= 0; j--)
3808				{
3809					struct in_addr addr;
3810
3811					memcpy(&addr, q, sizeof(addr));
3812					(void) sm_snprintf(p,
3813						SPACELEFT(hbuf, p),
3814						"%c%.*s",
3815						j != 0 ? '@' : ':',
3816						l > 240 ? 120 :
3817							j == 0 ? l : l / 2,
3818						inet_ntoa(addr));
3819					i = strlen(p);
3820					p += i;
3821					l -= i + 1;
3822					q += sizeof(struct in_addr);
3823				}
3824				o += o[1];
3825				break;
3826
3827			  default:
3828				/* Skip over option */
3829				o += o[1];
3830				break;
3831			}
3832		}
3833		(void) sm_snprintf(p, SPACELEFT(hbuf, p), "]");
3834		goto postipsr;
3835	}
3836
3837noipsr:
3838#endif /* IP_SRCROUTE */
3839	if (RealHostName != NULL && RealHostName[0] != '[')
3840	{
3841		p = &hbuf[strlen(hbuf)];
3842		(void) sm_snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
3843				   anynet_ntoa(&RealHostAddr));
3844	}
3845	if (*may_be_forged)
3846	{
3847		p = &hbuf[strlen(hbuf)];
3848		(void) sm_strlcpy(p, " (may be forged)", SPACELEFT(hbuf, p));
3849		macdefine(&BlankEnvelope.e_macro, A_PERM,
3850			  macid("{client_resolve}"), "FORGED");
3851	}
3852
3853#if IP_SRCROUTE
3854postipsr:
3855#endif /* IP_SRCROUTE */
3856
3857	/* put back the original incoming port */
3858	switch (RealHostAddr.sa.sa_family)
3859	{
3860#if NETINET
3861	  case AF_INET:
3862		if (port > 0)
3863			RealHostAddr.sin.sin_port = port;
3864		break;
3865#endif /* NETINET */
3866
3867#if NETINET6
3868	  case AF_INET6:
3869		if (port > 0)
3870			RealHostAddr.sin6.sin6_port = port;
3871		break;
3872#endif /* NETINET6 */
3873	}
3874
3875	if (tTd(9, 1))
3876		sm_dprintf("getauthinfo: %s\n", hbuf);
3877	return hbuf;
3878}
3879/*
3880**  HOST_MAP_LOOKUP -- turn a hostname into canonical form
3881**
3882**	Parameters:
3883**		map -- a pointer to this map.
3884**		name -- the (presumably unqualified) hostname.
3885**		av -- unused -- for compatibility with other mapping
3886**			functions.
3887**		statp -- an exit status (out parameter) -- set to
3888**			EX_TEMPFAIL if the name server is unavailable.
3889**
3890**	Returns:
3891**		The mapping, if found.
3892**		NULL if no mapping found.
3893**
3894**	Side Effects:
3895**		Looks up the host specified in hbuf.  If it is not
3896**		the canonical name for that host, return the canonical
3897**		name (unless MF_MATCHONLY is set, which will cause the
3898**		status only to be returned).
3899*/
3900
3901char *
3902host_map_lookup(map, name, av, statp)
3903	MAP *map;
3904	char *name;
3905	char **av;
3906	int *statp;
3907{
3908	register struct hostent *hp;
3909#if NETINET
3910	struct in_addr in_addr;
3911#endif /* NETINET */
3912#if NETINET6
3913	struct in6_addr in6_addr;
3914#endif /* NETINET6 */
3915	char *cp, *ans = NULL;
3916	register STAB *s;
3917	time_t now;
3918#if NAMED_BIND
3919	time_t SM_NONVOLATILE retrans = 0;
3920	int SM_NONVOLATILE retry = 0;
3921#endif /* NAMED_BIND */
3922	char hbuf[MAXNAME + 1];
3923
3924	/*
3925	**  See if we have already looked up this name.  If so, just
3926	**  return it (unless expired).
3927	*/
3928
3929	now = curtime();
3930	s = stab(name, ST_NAMECANON, ST_ENTER);
3931	if (bitset(NCF_VALID, s->s_namecanon.nc_flags) &&
3932	    s->s_namecanon.nc_exp >= now)
3933	{
3934		if (tTd(9, 1))
3935			sm_dprintf("host_map_lookup(%s) => CACHE %s\n",
3936				    name,
3937				    s->s_namecanon.nc_cname == NULL
3938					? "NULL"
3939					: s->s_namecanon.nc_cname);
3940		errno = s->s_namecanon.nc_errno;
3941		SM_SET_H_ERRNO(s->s_namecanon.nc_herrno);
3942		*statp = s->s_namecanon.nc_stat;
3943		if (*statp == EX_TEMPFAIL)
3944		{
3945			CurEnv->e_status = "4.4.3";
3946			message("851 %s: Name server timeout",
3947				shortenstring(name, 33));
3948		}
3949		if (*statp != EX_OK)
3950			return NULL;
3951		if (s->s_namecanon.nc_cname == NULL)
3952		{
3953			syserr("host_map_lookup(%s): bogus NULL cache entry, errno=%d, h_errno=%d",
3954			       name,
3955			       s->s_namecanon.nc_errno,
3956			       s->s_namecanon.nc_herrno);
3957			return NULL;
3958		}
3959		if (bitset(MF_MATCHONLY, map->map_mflags))
3960			cp = map_rewrite(map, name, strlen(name), NULL);
3961		else
3962			cp = map_rewrite(map,
3963					 s->s_namecanon.nc_cname,
3964					 strlen(s->s_namecanon.nc_cname),
3965					 av);
3966		return cp;
3967	}
3968
3969	/*
3970	**  If we are running without a regular network connection (usually
3971	**  dial-on-demand) and we are just queueing, we want to avoid DNS
3972	**  lookups because those could try to connect to a server.
3973	*/
3974
3975	if (CurEnv->e_sendmode == SM_DEFER &&
3976	    bitset(MF_DEFER, map->map_mflags))
3977	{
3978		if (tTd(9, 1))
3979			sm_dprintf("host_map_lookup(%s) => DEFERRED\n", name);
3980		*statp = EX_TEMPFAIL;
3981		return NULL;
3982	}
3983
3984	/*
3985	**  If first character is a bracket, then it is an address
3986	**  lookup.  Address is copied into a temporary buffer to
3987	**  strip the brackets and to preserve name if address is
3988	**  unknown.
3989	*/
3990
3991	if (tTd(9, 1))
3992		sm_dprintf("host_map_lookup(%s) => ", name);
3993#if NAMED_BIND
3994	if (map->map_timeout > 0)
3995	{
3996		retrans = _res.retrans;
3997		_res.retrans = map->map_timeout;
3998	}
3999	if (map->map_retry > 0)
4000	{
4001		retry = _res.retry;
4002		_res.retry = map->map_retry;
4003	}
4004#endif /* NAMED_BIND */
4005
4006	/* set default TTL */
4007	s->s_namecanon.nc_exp = now + SM_DEFAULT_TTL;
4008	if (*name != '[')
4009	{
4010		int ttl;
4011
4012		(void) sm_strlcpy(hbuf, name, sizeof(hbuf));
4013		if (getcanonname(hbuf, sizeof(hbuf) - 1, !HasWildcardMX, &ttl))
4014		{
4015			ans = hbuf;
4016			if (ttl > 0)
4017				s->s_namecanon.nc_exp = now + SM_MIN(ttl,
4018								SM_DEFAULT_TTL);
4019		}
4020	}
4021	else
4022	{
4023		if ((cp = strchr(name, ']')) == NULL)
4024		{
4025			if (tTd(9, 1))
4026				sm_dprintf("FAILED\n");
4027			return NULL;
4028		}
4029		*cp = '\0';
4030
4031		hp = NULL;
4032#if NETINET
4033		if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE)
4034			hp = sm_gethostbyaddr((char *)&in_addr,
4035					      INADDRSZ, AF_INET);
4036#endif /* NETINET */
4037#if NETINET6
4038		if (hp == NULL &&
4039		    anynet_pton(AF_INET6, &name[1], &in6_addr) == 1)
4040			hp = sm_gethostbyaddr((char *)&in6_addr,
4041					      IN6ADDRSZ, AF_INET6);
4042#endif /* NETINET6 */
4043		*cp = ']';
4044
4045		if (hp != NULL)
4046		{
4047			/* found a match -- copy out */
4048			ans = denlstring((char *) hp->h_name, true, true);
4049#if NETINET6
4050			if (ans == hp->h_name)
4051			{
4052				static char n[MAXNAME + 1];
4053
4054				/* hp->h_name is about to disappear */
4055				(void) sm_strlcpy(n, ans, sizeof(n));
4056				ans = n;
4057			}
4058			freehostent(hp);
4059			hp = NULL;
4060#endif /* NETINET6 */
4061		}
4062	}
4063#if NAMED_BIND
4064	if (map->map_timeout > 0)
4065		_res.retrans = retrans;
4066	if (map->map_retry > 0)
4067		_res.retry = retry;
4068#endif /* NAMED_BIND */
4069
4070	s->s_namecanon.nc_flags |= NCF_VALID;	/* will be soon */
4071
4072	/* Found an answer */
4073	if (ans != NULL)
4074	{
4075		s->s_namecanon.nc_stat = *statp = EX_OK;
4076		if (s->s_namecanon.nc_cname != NULL)
4077			sm_free(s->s_namecanon.nc_cname);
4078		s->s_namecanon.nc_cname = sm_strdup_x(ans);
4079		if (bitset(MF_MATCHONLY, map->map_mflags))
4080			cp = map_rewrite(map, name, strlen(name), NULL);
4081		else
4082			cp = map_rewrite(map, ans, strlen(ans), av);
4083		if (tTd(9, 1))
4084			sm_dprintf("FOUND %s\n", ans);
4085		return cp;
4086	}
4087
4088
4089	/* No match found */
4090	s->s_namecanon.nc_errno = errno;
4091#if NAMED_BIND
4092	s->s_namecanon.nc_herrno = h_errno;
4093	if (tTd(9, 1))
4094		sm_dprintf("FAIL (%d)\n", h_errno);
4095	switch (h_errno)
4096	{
4097	  case TRY_AGAIN:
4098		if (UseNameServer)
4099		{
4100			CurEnv->e_status = "4.4.3";
4101			message("851 %s: Name server timeout",
4102				shortenstring(name, 33));
4103		}
4104		*statp = EX_TEMPFAIL;
4105		break;
4106
4107	  case HOST_NOT_FOUND:
4108	  case NO_DATA:
4109		*statp = EX_NOHOST;
4110		break;
4111
4112	  case NO_RECOVERY:
4113		*statp = EX_SOFTWARE;
4114		break;
4115
4116	  default:
4117		*statp = EX_UNAVAILABLE;
4118		break;
4119	}
4120#else /* NAMED_BIND */
4121	if (tTd(9, 1))
4122		sm_dprintf("FAIL\n");
4123	*statp = EX_NOHOST;
4124#endif /* NAMED_BIND */
4125	s->s_namecanon.nc_stat = *statp;
4126	return NULL;
4127}
4128/*
4129**  HOST_MAP_INIT -- initialize host class structures
4130**
4131**	Parameters:
4132**		map -- a pointer to this map.
4133**		args -- argument string.
4134**
4135**	Returns:
4136**		true.
4137*/
4138
4139bool
4140host_map_init(map, args)
4141	MAP *map;
4142	char *args;
4143{
4144	register char *p = args;
4145
4146	for (;;)
4147	{
4148		while (isascii(*p) && isspace(*p))
4149			p++;
4150		if (*p != '-')
4151			break;
4152		switch (*++p)
4153		{
4154		  case 'a':
4155			map->map_app = ++p;
4156			break;
4157
4158		  case 'T':
4159			map->map_tapp = ++p;
4160			break;
4161
4162		  case 'm':
4163			map->map_mflags |= MF_MATCHONLY;
4164			break;
4165
4166		  case 't':
4167			map->map_mflags |= MF_NODEFER;
4168			break;
4169
4170		  case 'S':	/* only for consistency */
4171			map->map_spacesub = *++p;
4172			break;
4173
4174		  case 'D':
4175			map->map_mflags |= MF_DEFER;
4176			break;
4177
4178		  case 'd':
4179			{
4180				char *h;
4181
4182				while (isascii(*++p) && isspace(*p))
4183					continue;
4184				h = strchr(p, ' ');
4185				if (h != NULL)
4186					*h = '\0';
4187				map->map_timeout = convtime(p, 's');
4188				if (h != NULL)
4189					*h = ' ';
4190			}
4191			break;
4192
4193		  case 'r':
4194			while (isascii(*++p) && isspace(*p))
4195				continue;
4196			map->map_retry = atoi(p);
4197			break;
4198		}
4199		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
4200			p++;
4201		if (*p != '\0')
4202			*p++ = '\0';
4203	}
4204	if (map->map_app != NULL)
4205		map->map_app = newstr(map->map_app);
4206	if (map->map_tapp != NULL)
4207		map->map_tapp = newstr(map->map_tapp);
4208	return true;
4209}
4210
4211#if NETINET6
4212/*
4213**  ANYNET_NTOP -- convert an IPv6 network address to printable form.
4214**
4215**	Parameters:
4216**		s6a -- a pointer to an in6_addr structure.
4217**		dst -- buffer to store result in
4218**		dst_len -- size of dst buffer
4219**
4220**	Returns:
4221**		A printable version of that structure.
4222*/
4223
4224char *
4225anynet_ntop(s6a, dst, dst_len)
4226	struct in6_addr *s6a;
4227	char *dst;
4228	size_t dst_len;
4229{
4230	register char *ap;
4231
4232	if (IN6_IS_ADDR_V4MAPPED(s6a))
4233		ap = (char *) inet_ntop(AF_INET,
4234					&s6a->s6_addr[IN6ADDRSZ - INADDRSZ],
4235					dst, dst_len);
4236	else
4237	{
4238		char *d;
4239		size_t sz;
4240
4241		/* Save pointer to beginning of string */
4242		d = dst;
4243
4244		/* Add IPv6: protocol tag */
4245		sz = sm_strlcpy(dst, "IPv6:", dst_len);
4246		if (sz >= dst_len)
4247			return NULL;
4248		dst += sz;
4249		dst_len -= sz;
4250		ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len);
4251
4252		/* Restore pointer to beginning of string */
4253		if (ap != NULL)
4254			ap = d;
4255	}
4256	return ap;
4257}
4258
4259/*
4260**  ANYNET_PTON -- convert printed form to network address.
4261**
4262**	Wrapper for inet_pton() which handles IPv6: labels.
4263**
4264**	Parameters:
4265**		family -- address family
4266**		src -- string
4267**		dst -- destination address structure
4268**
4269**	Returns:
4270**		1 if the address was valid
4271**		0 if the address wasn't parseable
4272**		-1 if error
4273*/
4274
4275int
4276anynet_pton(family, src, dst)
4277	int family;
4278	const char *src;
4279	void *dst;
4280{
4281	if (family == AF_INET6 && sm_strncasecmp(src, "IPv6:", 5) == 0)
4282		src += 5;
4283	return inet_pton(family, src, dst);
4284}
4285#endif /* NETINET6 */
4286/*
4287**  ANYNET_NTOA -- convert a network address to printable form.
4288**
4289**	Parameters:
4290**		sap -- a pointer to a sockaddr structure.
4291**
4292**	Returns:
4293**		A printable version of that sockaddr.
4294*/
4295
4296#ifdef USE_SOCK_STREAM
4297
4298# if NETLINK
4299#  include <net/if_dl.h>
4300# endif /* NETLINK */
4301
4302char *
4303anynet_ntoa(sap)
4304	register SOCKADDR *sap;
4305{
4306	register char *bp;
4307	register char *ap;
4308	int l;
4309	static char buf[100];
4310
4311	/* check for null/zero family */
4312	if (sap == NULL)
4313		return "NULLADDR";
4314	if (sap->sa.sa_family == 0)
4315		return "0";
4316
4317	switch (sap->sa.sa_family)
4318	{
4319# if NETUNIX
4320	  case AF_UNIX:
4321		if (sap->sunix.sun_path[0] != '\0')
4322			(void) sm_snprintf(buf, sizeof(buf), "[UNIX: %.64s]",
4323					   sap->sunix.sun_path);
4324		else
4325			(void) sm_strlcpy(buf, "[UNIX: localhost]", sizeof(buf));
4326		return buf;
4327# endif /* NETUNIX */
4328
4329# if NETINET
4330	  case AF_INET:
4331		return (char *) inet_ntoa(sap->sin.sin_addr);
4332# endif /* NETINET */
4333
4334# if NETINET6
4335	  case AF_INET6:
4336		ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof(buf));
4337		if (ap != NULL)
4338			return ap;
4339		break;
4340# endif /* NETINET6 */
4341
4342# if NETLINK
4343	  case AF_LINK:
4344		(void) sm_snprintf(buf, sizeof(buf), "[LINK: %s]",
4345				   link_ntoa((struct sockaddr_dl *) &sap->sa));
4346		return buf;
4347# endif /* NETLINK */
4348	  default:
4349		/* this case is needed when nothing is #defined */
4350		/* in order to keep the switch syntactically correct */
4351		break;
4352	}
4353
4354	/* unknown family -- just dump bytes */
4355	(void) sm_snprintf(buf, sizeof(buf), "Family %d: ", sap->sa.sa_family);
4356	bp = &buf[strlen(buf)];
4357	ap = sap->sa.sa_data;
4358	for (l = sizeof(sap->sa.sa_data); --l >= 0; )
4359	{
4360		(void) sm_snprintf(bp, SPACELEFT(buf, bp), "%02x:",
4361				   *ap++ & 0377);
4362		bp += 3;
4363	}
4364	*--bp = '\0';
4365	return buf;
4366}
4367/*
4368**  HOSTNAMEBYANYADDR -- return name of host based on address
4369**
4370**	Parameters:
4371**		sap -- SOCKADDR pointer
4372**
4373**	Returns:
4374**		text representation of host name.
4375**
4376**	Side Effects:
4377**		none.
4378*/
4379
4380char *
4381hostnamebyanyaddr(sap)
4382	register SOCKADDR *sap;
4383{
4384	register struct hostent *hp;
4385# if NAMED_BIND
4386	int saveretry;
4387# endif /* NAMED_BIND */
4388# if NETINET6
4389	struct in6_addr in6_addr;
4390# endif /* NETINET6 */
4391
4392# if NAMED_BIND
4393	/* shorten name server timeout to avoid higher level timeouts */
4394	saveretry = _res.retry;
4395	if (_res.retry * _res.retrans > 20)
4396		_res.retry = 20 / _res.retrans;
4397# endif /* NAMED_BIND */
4398
4399	switch (sap->sa.sa_family)
4400	{
4401# if NETINET
4402	  case AF_INET:
4403		hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
4404				      INADDRSZ, AF_INET);
4405		break;
4406# endif /* NETINET */
4407
4408# if NETINET6
4409	  case AF_INET6:
4410		hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr,
4411				      IN6ADDRSZ, AF_INET6);
4412		break;
4413# endif /* NETINET6 */
4414
4415# if NETISO
4416	  case AF_ISO:
4417		hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
4418				      sizeof(sap->siso.siso_addr), AF_ISO);
4419		break;
4420# endif /* NETISO */
4421
4422# if NETUNIX
4423	  case AF_UNIX:
4424		hp = NULL;
4425		break;
4426# endif /* NETUNIX */
4427
4428	  default:
4429		hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof(sap->sa.sa_data),
4430				      sap->sa.sa_family);
4431		break;
4432	}
4433
4434# if NAMED_BIND
4435	_res.retry = saveretry;
4436# endif /* NAMED_BIND */
4437
4438# if NETINET || NETINET6
4439	if (hp != NULL && hp->h_name[0] != '['
4440#  if NETINET6
4441	    && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1
4442#  endif /* NETINET6 */
4443#  if NETINET
4444	    && inet_addr(hp->h_name) == INADDR_NONE
4445#  endif /* NETINET */
4446	    )
4447	{
4448		char *name;
4449
4450		name = denlstring((char *) hp->h_name, true, true);
4451#  if NETINET6
4452		if (name == hp->h_name)
4453		{
4454			static char n[MAXNAME + 1];
4455
4456			/* Copy the string, hp->h_name is about to disappear */
4457			(void) sm_strlcpy(n, name, sizeof(n));
4458			name = n;
4459		}
4460		freehostent(hp);
4461#  endif /* NETINET6 */
4462		return name;
4463	}
4464# endif /* NETINET || NETINET6 */
4465
4466# if NETINET6
4467	if (hp != NULL)
4468	{
4469		freehostent(hp);
4470		hp = NULL;
4471	}
4472# endif /* NETINET6 */
4473
4474# if NETUNIX
4475	if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0')
4476		return "localhost";
4477# endif /* NETUNIX */
4478	{
4479		static char buf[203];
4480
4481		(void) sm_snprintf(buf, sizeof(buf), "[%.200s]",
4482				   anynet_ntoa(sap));
4483		return buf;
4484	}
4485}
4486#endif /* USE_SOCK_STREAM */
4487