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