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