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