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