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