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