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