xref: /freebsd/contrib/sendmail/src/daemon.c (revision 5069714534cba67f1985e6dfe23b145178372b5f)
1 /*
2  * Copyright (c) 1998-2000 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 
17 #ifndef lint
18 # ifdef DAEMON
19 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.41 2000/12/28 23:46:43 gshapiro Exp $ (with daemon mode)";
20 # else /* DAEMON */
21 static char id[] = "@(#)$Id: daemon.c,v 8.401.4.41 2000/12/28 23:46:43 gshapiro Exp $ (without daemon mode)";
22 # endif /* DAEMON */
23 #endif /* ! lint */
24 
25 #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
26 # define USE_SOCK_STREAM	1
27 #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */
28 
29 #if DAEMON || defined(USE_SOCK_STREAM)
30 # if NETINET || NETINET6
31 #  include <arpa/inet.h>
32 # endif /* NETINET || NETINET6 */
33 # if NAMED_BIND
34 #  ifndef NO_DATA
35 #   define NO_DATA	NO_ADDRESS
36 #  endif /* ! NO_DATA */
37 # endif /* NAMED_BIND */
38 #endif /* DAEMON || defined(USE_SOCK_STREAM) */
39 
40 #if DAEMON
41 
42 # if STARTTLS
43 #    include <openssl/rand.h>
44 # endif /* STARTTLS */
45 
46 # include <sys/time.h>
47 
48 # if IP_SRCROUTE && NETINET
49 #  include <netinet/in_systm.h>
50 #  include <netinet/ip.h>
51 #  if HAS_IN_H
52 #   include <netinet/in.h>
53 #   ifndef IPOPTION
54 #    define IPOPTION	ip_opts
55 #    define IP_LIST	ip_opts
56 #    define IP_DST	ip_dst
57 #   endif /* ! IPOPTION */
58 #  else /* HAS_IN_H */
59 #   include <netinet/ip_var.h>
60 #   ifndef IPOPTION
61 #    define IPOPTION	ipoption
62 #    define IP_LIST	ipopt_list
63 #    define IP_DST	ipopt_dst
64 #   endif /* ! IPOPTION */
65 #  endif /* HAS_IN_H */
66 # endif /* IP_SRCROUTE && NETINET */
67 
68 /* structure to describe a daemon */
69 struct daemon
70 {
71 	int		d_socket;	/* fd for socket */
72 	SOCKADDR	d_addr;		/* socket for incoming */
73 	u_short		d_port;		/* port number */
74 	int		d_listenqueue;	/* size of listen queue */
75 	int		d_tcprcvbufsize;	/* size of TCP receive buffer */
76 	int		d_tcpsndbufsize;	/* size of TCP send buffer */
77 	time_t		d_refuse_connections_until;
78 	bool		d_firsttime;
79 	int		d_socksize;
80 	BITMAP256	d_flags;	/* flags; see sendmail.h */
81 	char		*d_mflags;	/* flags for use in macro */
82 	char		*d_name;	/* user-supplied name */
83 };
84 
85 typedef struct daemon DAEMON_T;
86 
87 static void	connecttimeout __P((void));
88 static int	opendaemonsocket __P((struct daemon *, bool));
89 static u_short	setupdaemon __P((SOCKADDR *));
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, outfile, infile, e)
112 **		Make a connection to the named host on the given
113 **		port.  Set *outfile and *infile to the files
114 **		appropriate for communication.  Returns zero on
115 **		success, else an exit status describing the
116 **		error.
117 **	host_map_lookup(map, hbuf, avp, pstat)
118 **		Convert the entry in hbuf into a canonical form.
119 */
120 
121 static DAEMON_T	Daemons[MAXDAEMONS];
122 static int	ndaemons = 0;			/* actual number of daemons */
123 
124 /* options for client */
125 static int	TcpRcvBufferSize = 0;	/* size of TCP receive buffer */
126 static int	TcpSndBufferSize = 0;	/* size of TCP send buffer */
127 
128 /*
129 **  GETREQUESTS -- open mail IPC port and get requests.
130 **
131 **	Parameters:
132 **		e -- the current envelope.
133 **
134 **	Returns:
135 **		pointer to flags.
136 **
137 **	Side Effects:
138 **		Waits until some interesting activity occurs.  When
139 **		it does, a child is created to process it, and the
140 **		parent waits for completion.  Return from this
141 **		routine is always in the child.  The file pointers
142 **		"InChannel" and "OutChannel" should be set to point
143 **		to the communication channel.
144 */
145 
146 BITMAP256 *
147 getrequests(e)
148 	ENVELOPE *e;
149 {
150 	int t;
151 	time_t last_disk_space_check = 0;
152 	int idx, curdaemon = -1;
153 	int i, olddaemon = 0;
154 # if XDEBUG
155 	bool j_has_dot;
156 # endif /* XDEBUG */
157 	char status[MAXLINE];
158 	SOCKADDR sa;
159 	SOCKADDR_LEN_T len = sizeof sa;
160 # if NETUNIX
161 	extern int ControlSocket;
162 # endif /* NETUNIX */
163 	extern ENVELOPE BlankEnvelope;
164 
165 
166 	for (idx = 0; idx < ndaemons; idx++)
167 	{
168 		Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr));
169 		Daemons[idx].d_firsttime = TRUE;
170 		Daemons[idx].d_refuse_connections_until = (time_t) 0;
171 	}
172 
173 	/*
174 	**  Try to actually open the connection.
175 	*/
176 
177 	if (tTd(15, 1))
178 	{
179 		for (idx = 0; idx < ndaemons; idx++)
180 		{
181 			dprintf("getrequests: daemon %s: port %d\n",
182 				Daemons[idx].d_name,
183 				ntohs(Daemons[idx].d_port));
184 		}
185 	}
186 
187 	/* get a socket for the SMTP connection */
188 	for (idx = 0; idx < ndaemons; idx++)
189 		Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE);
190 
191 	if (opencontrolsocket() < 0)
192 		sm_syslog(LOG_WARNING, NOQID,
193 			  "daemon could not open control socket %s: %s",
194 			  ControlSocketName, errstring(errno));
195 
196 	(void) setsignal(SIGCHLD, reapchild);
197 
198 	/* write the pid to file */
199 	log_sendmail_pid(e);
200 
201 # if XDEBUG
202 	{
203 		char jbuf[MAXHOSTNAMELEN];
204 
205 		expand("\201j", jbuf, sizeof jbuf, e);
206 		j_has_dot = strchr(jbuf, '.') != NULL;
207 	}
208 # endif /* XDEBUG */
209 
210 	/* Add parent process as first item */
211 	proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON);
212 
213 	if (tTd(15, 1))
214 	{
215 		for (idx = 0; idx < ndaemons; idx++)
216 			dprintf("getrequests: daemon %s: %d\n",
217 				Daemons[idx].d_name,
218 				Daemons[idx].d_socket);
219 	}
220 
221 	for (;;)
222 	{
223 		register pid_t pid;
224 		auto SOCKADDR_LEN_T lotherend;
225 		bool timedout = FALSE;
226 		bool control = FALSE;
227 		int save_errno;
228 		int pipefd[2];
229 		time_t timenow;
230 # if STARTTLS
231 		long seed;
232 # endif /* STARTTLS */
233 		extern bool refuseconnections __P((char *, ENVELOPE *, int));
234 
235 		/* see if we are rejecting connections */
236 		(void) blocksignal(SIGALRM);
237 
238 		timenow = curtime();
239 
240 		/*
241 		**  Use ConnRateThrottle only if the
242 		**  last pass was for a connection
243 		*/
244 
245 		if (ConnRateThrottle > 0 && curdaemon >= 0)
246 		{
247 			static int conncnt = 0;
248 			static time_t lastconn = 0;
249 
250 			if (timenow != lastconn)
251 			{
252 				lastconn = timenow;
253 				conncnt = 1;
254 			}
255 			else if (++conncnt > ConnRateThrottle)
256 			{
257 				/* sleep to flatten out connection load */
258 				sm_setproctitle(TRUE, e,
259 						"deferring connections: %d per second",
260 						ConnRateThrottle);
261 				if (LogLevel >= 9)
262 					sm_syslog(LOG_INFO, NOQID,
263 						  "deferring connections: %d per second",
264 						  ConnRateThrottle);
265 				(void) sleep(1);
266 			}
267 		}
268 
269 		for (idx = 0; idx < ndaemons; idx++)
270 		{
271 			if (timenow < Daemons[idx].d_refuse_connections_until)
272 				continue;
273 			if (refuseconnections(Daemons[idx].d_name, e, idx))
274 			{
275 				if (Daemons[idx].d_socket >= 0)
276 				{
277 					/* close socket so peer fails quickly */
278 					(void) close(Daemons[idx].d_socket);
279 					Daemons[idx].d_socket = -1;
280 				}
281 
282 				/* refuse connections for next 15 seconds */
283 				Daemons[idx].d_refuse_connections_until = timenow + 15;
284 			}
285 			else if (Daemons[idx].d_socket < 0 ||
286 				 Daemons[idx].d_firsttime)
287 			{
288 				if (!Daemons[idx].d_firsttime && LogLevel >= 9)
289 					sm_syslog(LOG_INFO, NOQID,
290 						"accepting connections again for daemon %s",
291 						Daemons[idx].d_name);
292 
293 				/* arrange to (re)open the socket if needed */
294 				(void) opendaemonsocket(&Daemons[idx], FALSE);
295 				Daemons[idx].d_firsttime = FALSE;
296 			}
297 		}
298 
299 		if (timenow >= last_disk_space_check)
300 		{
301 			bool logged = FALSE;
302 
303 			if (!enoughdiskspace(MinBlocksFree + 1, FALSE))
304 			{
305 				for (idx = 0; idx < ndaemons; idx++)
306 				{
307 					if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags))
308 					{
309 						/* log only if not logged before */
310 						if (!logged)
311 						{
312 							if (LogLevel >= 9)
313 								sm_syslog(LOG_INFO, NOQID,
314 									  "rejecting new messages: min free: %ld",
315 									  MinBlocksFree);
316 							logged = TRUE;
317 							sm_setproctitle(TRUE, e,
318 									"rejecting new messages: min free: %ld",
319 									MinBlocksFree);
320 						}
321 						setbitn(D_ETRNONLY, Daemons[idx].d_flags);
322 					}
323 				}
324 			}
325 			else
326 			{
327 				for (idx = 0; idx < ndaemons; idx++)
328 				{
329 					if (bitnset(D_ETRNONLY, Daemons[idx].d_flags))
330 					{
331 						/* log only if not logged before */
332 						if (!logged)
333 						{
334 							if (LogLevel >= 9)
335 								sm_syslog(LOG_INFO, NOQID,
336 									  "accepting new messages (again)");
337 							logged = TRUE;
338 						}
339 
340 						/* title will be set below */
341 						clrbitn(D_ETRNONLY, Daemons[idx].d_flags);
342 					}
343 				}
344 			}
345 			/* only check disk space once a minute */
346 			last_disk_space_check = timenow + 60;
347 		}
348 
349 # if XDEBUG
350 		/* check for disaster */
351 		{
352 			char jbuf[MAXHOSTNAMELEN];
353 
354 			expand("\201j", jbuf, sizeof jbuf, e);
355 			if (!wordinclass(jbuf, 'w'))
356 			{
357 				dumpstate("daemon lost $j");
358 				sm_syslog(LOG_ALERT, NOQID,
359 					  "daemon process doesn't have $j in $=w; see syslog");
360 				abort();
361 			}
362 			else if (j_has_dot && strchr(jbuf, '.') == NULL)
363 			{
364 				dumpstate("daemon $j lost dot");
365 				sm_syslog(LOG_ALERT, NOQID,
366 					  "daemon process $j lost dot; see syslog");
367 				abort();
368 			}
369 		}
370 # endif /* XDEBUG */
371 
372 # if 0
373 		/*
374 		**  Andrew Sun <asun@ieps-sun.ml.com> claims that this will
375 		**  fix the SVr4 problem.  But it seems to have gone away,
376 		**  so is it worth doing this?
377 		*/
378 
379 		if (DaemonSocket >= 0 &&
380 		    SetNonBlocking(DaemonSocket, FALSE) < 0)
381 			log an error here;
382 # endif /* 0 */
383 		(void) releasesignal(SIGALRM);
384 
385 		for (;;)
386 		{
387 			bool setproc = FALSE;
388 			int highest = -1;
389 			fd_set readfds;
390 			struct timeval timeout;
391 
392 			FD_ZERO(&readfds);
393 
394 			for (idx = 0; idx < ndaemons; idx++)
395 			{
396 				/* wait for a connection */
397 				if (Daemons[idx].d_socket >= 0)
398 				{
399 					if (!setproc &&
400 					    !bitnset(D_ETRNONLY,
401 						     Daemons[idx].d_flags))
402 					{
403 						sm_setproctitle(TRUE, e,
404 								"accepting connections");
405 						setproc = TRUE;
406 					}
407 					if (Daemons[idx].d_socket > highest)
408 						highest = Daemons[idx].d_socket;
409 					FD_SET((u_int)Daemons[idx].d_socket, &readfds);
410 				}
411 			}
412 
413 # if NETUNIX
414 			if (ControlSocket >= 0)
415 			{
416 				if (ControlSocket > highest)
417 					highest = ControlSocket;
418 				FD_SET(ControlSocket, &readfds);
419 			}
420 # endif /* NETUNIX */
421 
422 			/*
423 			**  if one socket is closed, set the timeout
424 			**  to 5 seconds (so it might get reopened soon),
425 			**  otherwise (all sockets open) 60.
426 			*/
427 
428 			idx = 0;
429 			while (idx < ndaemons && Daemons[idx].d_socket >= 0)
430 				idx++;
431 			if (idx < ndaemons)
432 				timeout.tv_sec = 5;
433 			else
434 				timeout.tv_sec = 60;
435 			timeout.tv_usec = 0;
436 
437 			t = select(highest + 1, FDSET_CAST &readfds,
438 				   NULL, NULL, &timeout);
439 
440 
441 
442 			if (DoQueueRun)
443 				(void) runqueue(TRUE, FALSE);
444 
445 			curdaemon = -1;
446 			if (t <= 0)
447 			{
448 				timedout = TRUE;
449 				break;
450 			}
451 
452 			control = FALSE;
453 			errno = 0;
454 
455 			/* look "round-robin" for an active socket */
456 			if ((idx = olddaemon + 1) >= ndaemons)
457 				idx = 0;
458 			for (i = 0; i < ndaemons; i++)
459 			{
460 				if (Daemons[idx].d_socket >= 0 &&
461 				    FD_ISSET(Daemons[idx].d_socket, &readfds))
462 				{
463 					lotherend = Daemons[idx].d_socksize;
464 					t = accept(Daemons[idx].d_socket,
465 						   (struct sockaddr *)&RealHostAddr,
466 						   &lotherend);
467 					olddaemon = curdaemon = idx;
468 					break;
469 				}
470 				if (++idx >= ndaemons)
471 					idx = 0;
472 			}
473 # if NETUNIX
474 			if (curdaemon == -1 && ControlSocket >= 0 &&
475 			    FD_ISSET(ControlSocket, &readfds))
476 			{
477 				struct sockaddr_un sa_un;
478 
479 				lotherend = sizeof sa_un;
480 				t = accept(ControlSocket,
481 					   (struct sockaddr *)&sa_un,
482 					   &lotherend);
483 				control = TRUE;
484 			}
485 # else /* NETUNIX */
486 			if (curdaemon == -1)
487 			{
488 				/* No daemon to service */
489 				continue;
490 			}
491 # endif /* NETUNIX */
492 			if (t >= 0 || errno != EINTR)
493 				break;
494 		}
495 		if (timedout)
496 		{
497 			timedout = FALSE;
498 			continue;
499 		}
500 		save_errno = errno;
501 		timenow = curtime();
502 		(void) blocksignal(SIGALRM);
503 		if (t < 0)
504 		{
505 			errno = save_errno;
506 			syserr("getrequests: accept");
507 
508 			/* arrange to re-open the socket next time around */
509 			(void) close(Daemons[curdaemon].d_socket);
510 			Daemons[curdaemon].d_socket = -1;
511 # if SO_REUSEADDR_IS_BROKEN
512 			/*
513 			**  Give time for bound socket to be released.
514 			**  This creates a denial-of-service if you can
515 			**  force accept() to fail on affected systems.
516 			*/
517 
518 			Daemons[curdaemon].d_refuse_connections_until = timenow + 15;
519 # endif /* SO_REUSEADDR_IS_BROKEN */
520 			continue;
521 		}
522 
523 		if (!control)
524 		{
525 			/* set some daemon related macros */
526 			switch (Daemons[curdaemon].d_addr.sa.sa_family)
527 			{
528 			  case AF_UNSPEC:
529 				define(macid("{daemon_family}", NULL),
530 				       "unspec", &BlankEnvelope);
531 				break;
532 # if NETINET
533 			  case AF_INET:
534 				define(macid("{daemon_family}", NULL),
535 				       "inet", &BlankEnvelope);
536 				break;
537 # endif /* NETINET */
538 # if NETINET6
539 			  case AF_INET6:
540 				define(macid("{daemon_family}", NULL),
541 				       "inet6", &BlankEnvelope);
542 				break;
543 # endif /* NETINET6 */
544 # if NETISO
545 			  case AF_ISO:
546 				define(macid("{daemon_family}", NULL),
547 				       "iso", &BlankEnvelope);
548 				break;
549 # endif /* NETISO */
550 # if NETNS
551 			  case AF_NS:
552 				define(macid("{daemon_family}", NULL),
553 				       "ns", &BlankEnvelope);
554 				break;
555 # endif /* NETNS */
556 # if NETX25
557 			  case AF_CCITT:
558 				define(macid("{daemon_family}", NULL),
559 				       "x.25", &BlankEnvelope);
560 				break;
561 # endif /* NETX25 */
562 			}
563 			define(macid("{daemon_name}", NULL),
564 			       Daemons[curdaemon].d_name, &BlankEnvelope);
565 			if (Daemons[curdaemon].d_mflags != NULL)
566 				define(macid("{daemon_flags}", NULL),
567 				       Daemons[curdaemon].d_mflags,
568 				       &BlankEnvelope);
569 			else
570 				define(macid("{daemon_flags}", NULL),
571 				       "", &BlankEnvelope);
572 		}
573 
574 		/*
575 		**  Create a subprocess to process the mail.
576 		*/
577 
578 		if (tTd(15, 2))
579 			dprintf("getrequests: forking (fd = %d)\n", t);
580 
581 		/*
582 		**  advance state of PRNG
583 		**  this is necessary because otherwise all child processes
584 		**  will produce the same PRN sequence and hence the selection
585 		**  of a queue directory (and other things, e.g., MX selection)
586 		**  are not "really" random.
587 		*/
588 # if STARTTLS
589 		seed = get_random();
590 		RAND_seed((void *) &last_disk_space_check,
591 			sizeof last_disk_space_check);
592 		RAND_seed((void *) &timenow, sizeof timenow);
593 		RAND_seed((void *) &seed, sizeof seed);
594 # else /* STARTTLS */
595 		(void) get_random();
596 # endif /* STARTTLS */
597 
598 #ifndef DEBUG_NO_FORK
599 		/*
600 		**  Create a pipe to keep the child from writing to the
601 		**  socket until after the parent has closed it.  Otherwise
602 		**  the parent may hang if the child has closed it first.
603 		*/
604 
605 		if (pipe(pipefd) < 0)
606 			pipefd[0] = pipefd[1] = -1;
607 
608 		(void) blocksignal(SIGCHLD);
609 		pid = fork();
610 		if (pid < 0)
611 		{
612 			syserr("daemon: cannot fork");
613 			if (pipefd[0] != -1)
614 			{
615 				(void) close(pipefd[0]);
616 				(void) close(pipefd[1]);
617 			}
618 			(void) releasesignal(SIGCHLD);
619 			(void) sleep(10);
620 			(void) close(t);
621 			continue;
622 		}
623 #else /* ! DEBUG_NO_FORK */
624 		pid = 0;
625 #endif /* ! DEBUG_NO_FORK */
626 
627 		if (pid == 0)
628 		{
629 			char *p;
630 			FILE *inchannel, *outchannel = NULL;
631 
632 			/*
633 			**  CHILD -- return to caller.
634 			**	Collect verified idea of sending host.
635 			**	Verify calling user id if possible here.
636 			*/
637 
638 			if (!control)
639 			{
640 				define(macid("{daemon_addr}", NULL),
641 				       newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)),
642 				       &BlankEnvelope);
643 				(void) snprintf(status, sizeof status, "%d",
644 						ntohs(Daemons[curdaemon].d_port));
645 				define(macid("{daemon_port}", NULL),
646 				       newstr(status), &BlankEnvelope);
647 			}
648 
649 			(void) releasesignal(SIGALRM);
650 			(void) releasesignal(SIGCHLD);
651 			(void) setsignal(SIGCHLD, SIG_DFL);
652 			(void) setsignal(SIGHUP, intsig);
653 			for (idx = 0; idx < ndaemons; idx++)
654 			{
655 				if (Daemons[idx].d_socket >= 0)
656 					(void) close(Daemons[idx].d_socket);
657 			}
658 			clrcontrol();
659 
660 			/* Avoid SMTP daemon actions if control command */
661 			if (control)
662 			{
663 				/* Add control socket process */
664 				proc_list_add(getpid(), "console socket child",
665 					PROC_CONTROL_CHILD);
666 			}
667 			else
668 			{
669 				proc_list_clear();
670 
671 				/* Add parent process as first child item */
672 				proc_list_add(getpid(), "daemon child",
673 					      PROC_DAEMON_CHILD);
674 
675 				/* don't schedule queue runs if ETRN */
676 				QueueIntvl = 0;
677 
678 				sm_setproctitle(TRUE, e, "startup with %s",
679 						anynet_ntoa(&RealHostAddr));
680 			}
681 
682 #ifndef DEBUG_NO_FORK
683 			if (pipefd[0] != -1)
684 			{
685 				auto char c;
686 
687 				/*
688 				**  Wait for the parent to close the write end
689 				**  of the pipe, which we will see as an EOF.
690 				**  This guarantees that we won't write to the
691 				**  socket until after the parent has closed
692 				**  the pipe.
693 				*/
694 
695 				/* close the write end of the pipe */
696 				(void) close(pipefd[1]);
697 
698 				/* we shouldn't be interrupted, but ... */
699 				while (read(pipefd[0], &c, 1) < 0 &&
700 				       errno == EINTR)
701 					continue;
702 				(void) close(pipefd[0]);
703 			}
704 #endif /* ! DEBUG_NO_FORK */
705 
706 			/* control socket processing */
707 			if (control)
708 			{
709 				control_command(t, e);
710 
711 				/* NOTREACHED */
712 				exit(EX_SOFTWARE);
713 			}
714 
715 			/* determine host name */
716 			p = hostnamebyanyaddr(&RealHostAddr);
717 			if (strlen(p) > (SIZE_T) MAXNAME)
718 				p[MAXNAME] = '\0';
719 			RealHostName = newstr(p);
720 			if (RealHostName[0] == '[')
721 			{
722 				/* TEMP, FAIL: which one? */
723 				define(macid("{client_resolve}", NULL),
724 				       (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL",
725 				       &BlankEnvelope);
726 			}
727 			else
728 				define(macid("{client_resolve}", NULL), "OK",
729 				       &BlankEnvelope);
730 			sm_setproctitle(TRUE, e, "startup with %s", p);
731 
732 			if ((inchannel = fdopen(t, "r")) == NULL ||
733 			    (t = dup(t)) < 0 ||
734 			    (outchannel = fdopen(t, "w")) == NULL)
735 			{
736 				syserr("cannot open SMTP server channel, fd=%d", t);
737 				finis(FALSE, EX_OK);
738 			}
739 
740 			InChannel = inchannel;
741 			OutChannel = outchannel;
742 			DisConnected = FALSE;
743 
744 # ifdef XLA
745 			if (!xla_host_ok(RealHostName))
746 			{
747 				message("421 4.4.5 Too many SMTP sessions for this host");
748 				finis(FALSE, EX_OK);
749 			}
750 # endif /* XLA */
751 			/* find out name for interface of connection */
752 			if (getsockname(fileno(InChannel), &sa.sa,
753 					&len) == 0)
754 			{
755 				p = hostnamebyanyaddr(&sa);
756 				if (tTd(15, 9))
757 					dprintf("getreq: got name %s\n", p);
758 				define(macid("{if_name}", NULL),
759 				       newstr(p), &BlankEnvelope);
760 
761 				/* do this only if it is not the loopback */
762 				/* interface: how to figure out? XXX */
763 				if (!isloopback(sa))
764 				{
765 					define(macid("{if_addr}", NULL),
766 					       newstr(anynet_ntoa(&sa)),
767 					       &BlankEnvelope);
768 					p = xalloc(5);
769 					snprintf(p, 4, "%d", sa.sa.sa_family);
770 					define(macid("{if_family}", NULL), p,
771 					       &BlankEnvelope);
772 					if (tTd(15, 7))
773 						dprintf("getreq: got addr %s and family %s\n",
774 							macvalue(macid("{if_addr}", NULL),
775 								 &BlankEnvelope),
776 							macvalue(macid("{if_addr}", NULL),
777 								 &BlankEnvelope));
778 				}
779 				else
780 				{
781 					define(macid("{if_addr}", NULL), NULL,
782 					       &BlankEnvelope);
783 					define(macid("{if_family}", NULL), NULL,
784 					       &BlankEnvelope);
785 				}
786 			}
787 			else
788 			{
789 				if (tTd(15, 7))
790 					dprintf("getreq: getsockname failed\n");
791 				define(macid("{if_name}", NULL), NULL,
792 				       &BlankEnvelope);
793 				define(macid("{if_addr}", NULL), NULL,
794 				       &BlankEnvelope);
795 				define(macid("{if_family}", NULL), NULL,
796 				       &BlankEnvelope);
797 			}
798 			break;
799 		}
800 
801 		/* parent -- keep track of children */
802 		if (control)
803 		{
804 			snprintf(status, sizeof status, "control socket server child");
805 			proc_list_add(pid, status, PROC_CONTROL);
806 		}
807 		else
808 		{
809 			snprintf(status, sizeof status,
810 				 "SMTP server child for %s",
811 				 anynet_ntoa(&RealHostAddr));
812 			proc_list_add(pid, status, PROC_DAEMON);
813 		}
814 		(void) releasesignal(SIGCHLD);
815 
816 		/* close the read end of the synchronization pipe */
817 		if (pipefd[0] != -1)
818 		{
819 			(void) close(pipefd[0]);
820 			pipefd[0] = -1;
821 		}
822 
823 		/* close the port so that others will hang (for a while) */
824 		(void) close(t);
825 
826 		/* release the child by closing the read end of the sync pipe */
827 		if (pipefd[1] != -1)
828 		{
829 			(void) close(pipefd[1]);
830 			pipefd[1] = -1;
831 		}
832 	}
833 
834 	if (tTd(15, 2))
835 		dprintf("getreq: returning\n");
836 	return &Daemons[curdaemon].d_flags;
837 }
838 /*
839 **  OPENDAEMONSOCKET -- open SMTP socket
840 **
841 **	Deals with setting all appropriate options.
842 **
843 **	Parameters:
844 **		d -- the structure for the daemon to open.
845 **		firsttime -- set if this is the initial open.
846 **
847 **	Returns:
848 **		Size in bytes of the daemon socket addr.
849 **
850 **	Side Effects:
851 **		Leaves DaemonSocket set to the open socket.
852 **		Exits if the socket cannot be created.
853 */
854 
855 # define MAXOPENTRIES	10	/* maximum number of tries to open connection */
856 
857 static int
858 opendaemonsocket(d, firsttime)
859 	struct daemon *d;
860 	bool firsttime;
861 {
862 	int on = 1;
863 	int fdflags;
864 	SOCKADDR_LEN_T socksize = 0;
865 	int ntries = 0;
866 	int save_errno;
867 
868 	if (tTd(15, 2))
869 		dprintf("opendaemonsocket(%s)\n", d->d_name);
870 
871 	do
872 	{
873 		if (ntries > 0)
874 			(void) sleep(5);
875 		if (firsttime || d->d_socket < 0)
876 		{
877 			d->d_socket = socket(d->d_addr.sa.sa_family,
878 					     SOCK_STREAM, 0);
879 			if (d->d_socket < 0)
880 			{
881 				save_errno = errno;
882 				syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name);
883 			  severe:
884 				if (LogLevel > 0)
885 					sm_syslog(LOG_ALERT, NOQID,
886 						  "daemon %s: problem creating SMTP socket", d->d_name);
887 				d->d_socket = -1;
888 				continue;
889 			}
890 
891 			/* turn on network debugging? */
892 			if (tTd(15, 101))
893 				(void) setsockopt(d->d_socket, SOL_SOCKET,
894 						  SO_DEBUG, (char *)&on,
895 						  sizeof on);
896 
897 			(void) setsockopt(d->d_socket, SOL_SOCKET,
898 					  SO_REUSEADDR, (char *)&on, sizeof on);
899 			(void) setsockopt(d->d_socket, SOL_SOCKET,
900 					  SO_KEEPALIVE, (char *)&on, sizeof on);
901 
902 # ifdef SO_RCVBUF
903 			if (d->d_tcprcvbufsize > 0)
904 			{
905 				if (setsockopt(d->d_socket, SOL_SOCKET,
906 					       SO_RCVBUF,
907 					       (char *) &d->d_tcprcvbufsize,
908 					       sizeof(d->d_tcprcvbufsize)) < 0)
909 					syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name);
910 			}
911 # endif /* SO_RCVBUF */
912 # ifdef SO_SNDBUF
913 			if (d->d_tcpsndbufsize > 0)
914 			{
915 				if (setsockopt(d->d_socket, SOL_SOCKET,
916 					       SO_SNDBUF,
917 					       (char *) &d->d_tcpsndbufsize,
918 					       sizeof(d->d_tcpsndbufsize)) < 0)
919 					syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name);
920 			}
921 # endif /* SO_SNDBUF */
922 
923 			if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 ||
924 			    fcntl(d->d_socket, F_SETFD,
925 				  fdflags | FD_CLOEXEC) == -1)
926 			{
927 				save_errno = errno;
928 				syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s",
929 				       d->d_name,
930 				       fdflags == -1 ? "get" : "set",
931 				       errstring(save_errno));
932 				(void) close(d->d_socket);
933 				goto severe;
934 			}
935 
936 			switch (d->d_addr.sa.sa_family)
937 			{
938 # if NETINET
939 			  case AF_INET:
940 				socksize = sizeof d->d_addr.sin;
941 				break;
942 # endif /* NETINET */
943 
944 # if NETINET6
945 			  case AF_INET6:
946 				socksize = sizeof d->d_addr.sin6;
947 				break;
948 # endif /* NETINET6 */
949 
950 # if NETISO
951 			  case AF_ISO:
952 				socksize = sizeof d->d_addr.siso;
953 				break;
954 # endif /* NETISO */
955 
956 			  default:
957 				socksize = sizeof d->d_addr;
958 				break;
959 			}
960 
961 			if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0)
962 			{
963 				/* probably another daemon already */
964 				save_errno = errno;
965 				syserr("opendaemonsocket: daemon %s: cannot bind",
966 				       d->d_name);
967 				(void) close(d->d_socket);
968 				goto severe;
969 			}
970 		}
971 		if (!firsttime &&
972 		    listen(d->d_socket, d->d_listenqueue) < 0)
973 		{
974 			save_errno = errno;
975 			syserr("opendaemonsocket: daemon %s: cannot listen",
976 			       d->d_name);
977 			(void) close(d->d_socket);
978 			goto severe;
979 		}
980 		return socksize;
981 	} while (ntries++ < MAXOPENTRIES && transienterror(save_errno));
982 	syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting",
983 	       d->d_name);
984 	/* NOTREACHED */
985 	return -1;  /* avoid compiler warning on IRIX */
986 }
987 /*
988 **  SETUPDAEMON -- setup socket for daemon
989 **
990 **	Parameters:
991 **		daemonaddr -- socket for daemon
992 **		daemon -- number of daemon
993 **
994 **	Returns:
995 **		port number on which daemon should run
996 **
997 */
998 static u_short
999 setupdaemon(daemonaddr)
1000 	SOCKADDR *daemonaddr;
1001 {
1002 	u_short port;
1003 
1004 	/*
1005 	**  Set up the address for the mailer.
1006 	*/
1007 
1008 	if (daemonaddr->sa.sa_family == AF_UNSPEC)
1009 	{
1010 		memset(daemonaddr, '\0', sizeof *daemonaddr);
1011 # if NETINET
1012 		daemonaddr->sa.sa_family = AF_INET;
1013 # endif /* NETINET */
1014 	}
1015 
1016 	switch (daemonaddr->sa.sa_family)
1017 	{
1018 # if NETINET
1019 	  case AF_INET:
1020 		if (daemonaddr->sin.sin_addr.s_addr == 0)
1021 			daemonaddr->sin.sin_addr.s_addr = INADDR_ANY;
1022 		port = daemonaddr->sin.sin_port;
1023 		break;
1024 # endif /* NETINET */
1025 
1026 # if NETINET6
1027 	  case AF_INET6:
1028 		if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr))
1029 			daemonaddr->sin6.sin6_addr = in6addr_any;
1030 		port = daemonaddr->sin6.sin6_port;
1031 		break;
1032 # endif /* NETINET6 */
1033 
1034 	  default:
1035 		/* unknown protocol */
1036 		port = 0;
1037 		break;
1038 	}
1039 	if (port == 0)
1040 	{
1041 # ifdef NO_GETSERVBYNAME
1042 		port = htons(25);
1043 # else /* NO_GETSERVBYNAME */
1044 		{
1045 			register struct servent *sp;
1046 
1047 			sp = getservbyname("smtp", "tcp");
1048 			if (sp == NULL)
1049 			{
1050 				syserr("554 5.3.5 service \"smtp\" unknown");
1051 				port = htons(25);
1052 			}
1053 			else
1054 				port = sp->s_port;
1055 		}
1056 # endif /* NO_GETSERVBYNAME */
1057 	}
1058 
1059 	switch (daemonaddr->sa.sa_family)
1060 	{
1061 # if NETINET
1062 	  case AF_INET:
1063 		daemonaddr->sin.sin_port = port;
1064 		break;
1065 # endif /* NETINET */
1066 
1067 # if NETINET6
1068 	  case AF_INET6:
1069 		daemonaddr->sin6.sin6_port = port;
1070 		break;
1071 # endif /* NETINET6 */
1072 
1073 	  default:
1074 		/* unknown protocol */
1075 		break;
1076 	}
1077 	return(port);
1078 }
1079 /*
1080 **  CLRDAEMON -- reset the daemon connection
1081 **
1082 **	Parameters:
1083 **		none.
1084 **
1085 **	Returns:
1086 **		none.
1087 **
1088 **	Side Effects:
1089 **		releases any resources used by the passive daemon.
1090 */
1091 
1092 void
1093 clrdaemon()
1094 {
1095 	int i;
1096 
1097 	for (i = 0; i < ndaemons; i++)
1098 	{
1099 		if (Daemons[i].d_socket >= 0)
1100 			(void) close(Daemons[i].d_socket);
1101 		Daemons[i].d_socket = -1;
1102 	}
1103 }
1104 /*
1105 **  SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client)
1106 **
1107 **	Parameters:
1108 **		p -- the options line.
1109 **		d -- the daemon structure to fill in.
1110 **
1111 **	Returns:
1112 **		none.
1113 */
1114 
1115 static void
1116 setsockaddroptions(p, d)
1117 	register char *p;
1118 	struct daemon *d;
1119 {
1120 # if NETISO
1121 	short portno;
1122 # endif /* NETISO */
1123 	int l;
1124 	char *h, *flags;
1125 	char *port = NULL;
1126 	char *addr = NULL;
1127 
1128 # if NETINET
1129 	if (d->d_addr.sa.sa_family == AF_UNSPEC)
1130 		d->d_addr.sa.sa_family = AF_INET;
1131 # endif /* NETINET */
1132 
1133 	while (p != NULL)
1134 	{
1135 		register char *f;
1136 		register char *v;
1137 
1138 		while (isascii(*p) && isspace(*p))
1139 			p++;
1140 		if (*p == '\0')
1141 			break;
1142 		f = p;
1143 		p = strchr(p, ',');
1144 		if (p != NULL)
1145 			*p++ = '\0';
1146 		v = strchr(f, '=');
1147 		if (v == NULL)
1148 			continue;
1149 		while (isascii(*++v) && isspace(*v))
1150 			continue;
1151 		if (isascii(*f) && islower(*f))
1152 			*f = toupper(*f);
1153 
1154 		switch (*f)
1155 		{
1156 		  case 'F':		/* address family */
1157 			if (isascii(*v) && isdigit(*v))
1158 				d->d_addr.sa.sa_family = atoi(v);
1159 # if NETINET
1160 			else if (strcasecmp(v, "inet") == 0)
1161 				d->d_addr.sa.sa_family = AF_INET;
1162 # endif /* NETINET */
1163 # if NETINET6
1164 			else if (strcasecmp(v, "inet6") == 0)
1165 				d->d_addr.sa.sa_family = AF_INET6;
1166 # endif /* NETINET6 */
1167 # if NETISO
1168 			else if (strcasecmp(v, "iso") == 0)
1169 				d->d_addr.sa.sa_family = AF_ISO;
1170 # endif /* NETISO */
1171 # if NETNS
1172 			else if (strcasecmp(v, "ns") == 0)
1173 				d->d_addr.sa.sa_family = AF_NS;
1174 # endif /* NETNS */
1175 # if NETX25
1176 			else if (strcasecmp(v, "x.25") == 0)
1177 				d->d_addr.sa.sa_family = AF_CCITT;
1178 # endif /* NETX25 */
1179 			else
1180 				syserr("554 5.3.5 Unknown address family %s in Family=option",
1181 				       v);
1182 			break;
1183 
1184 		  case 'A':		/* address */
1185 			addr = v;
1186 			break;
1187 
1188 		  case 'P':		/* port */
1189 			port = v;
1190 			break;
1191 
1192 		  case 'L':		/* listen queue size */
1193 			d->d_listenqueue = atoi(v);
1194 			break;
1195 
1196 		  case 'M':		/* modifiers (flags) */
1197 			l = 3 * strlen(v) + 3;
1198 			h = v;
1199 			flags = xalloc(l);
1200 			d->d_mflags = flags;
1201 			for (; *h != '\0'; h++)
1202 			{
1203 				if (!(isascii(*h) && isspace(*h)))
1204 				{
1205 					if (flags != d->d_mflags)
1206 						*flags++ = ' ';
1207 					*flags++ = *h;
1208 					if (isupper(*h))
1209 						*flags++ = *h;
1210 				}
1211 			}
1212 			*flags++ = '\0';
1213 			for (; *v != '\0'; v++)
1214 				if (!(isascii(*v) && isspace(*v)))
1215 					setbitn(bitidx(*v), d->d_flags);
1216 			break;
1217 
1218 		  case 'S':		/* send buffer size */
1219 			d->d_tcpsndbufsize = atoi(v);
1220 			break;
1221 
1222 		  case 'R':		/* receive buffer size */
1223 			d->d_tcprcvbufsize = atoi(v);
1224 			break;
1225 
1226 		  case 'N':		/* name */
1227 			d->d_name = v;
1228 			break;
1229 
1230 		  default:
1231 			syserr("554 5.3.5 PortOptions parameter \"%s\" unknown",
1232 			       f);
1233 		}
1234 	}
1235 
1236 	/* Check addr and port after finding family */
1237 	if (addr != NULL)
1238 	{
1239 		switch (d->d_addr.sa.sa_family)
1240 		{
1241 # if NETINET
1242 		  case AF_INET:
1243 			if (!isascii(*addr) || !isdigit(*addr) ||
1244 			    ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) == INADDR_NONE))
1245 			{
1246 				register struct hostent *hp;
1247 
1248 				hp = sm_gethostbyname(addr, AF_INET);
1249 				if (hp == NULL)
1250 					syserr("554 5.3.0 host \"%s\" unknown",
1251 					       addr);
1252 				else
1253 				{
1254 					while (*(hp->h_addr_list) != NULL &&
1255 					       hp->h_addrtype != AF_INET)
1256 						hp->h_addr_list++;
1257 					if (*(hp->h_addr_list) == NULL)
1258 						syserr("554 5.3.0 host \"%s\" unknown",
1259 						       addr);
1260 					else
1261 						memmove(&d->d_addr.sin.sin_addr,
1262 							*(hp->h_addr_list),
1263 							INADDRSZ);
1264 #  if _FFR_FREEHOSTENT && NETINET6
1265 					freehostent(hp);
1266 					hp = NULL;
1267 #  endif /* _FFR_FREEHOSTENT && NETINET6 */
1268 				}
1269 			}
1270 			break;
1271 # endif /* NETINET */
1272 
1273 # if NETINET6
1274 		  case AF_INET6:
1275 			if (!isascii(*addr) ||
1276 			    (!isxdigit(*addr) && *addr != ':') ||
1277 			    inet_pton(AF_INET6, addr,
1278 				      &d->d_addr.sin6.sin6_addr) != 1)
1279 			{
1280 				register struct hostent *hp;
1281 
1282 				hp = sm_gethostbyname(addr, AF_INET6);
1283 				if (hp == NULL)
1284 					syserr("554 5.3.0 host \"%s\" unknown",
1285 					       addr);
1286 				else
1287 				{
1288 					while (*(hp->h_addr_list) != NULL &&
1289 					       hp->h_addrtype != AF_INET6)
1290 						hp->h_addr_list++;
1291 					if (*(hp->h_addr_list) == NULL)
1292 						syserr("554 5.3.0 host \"%s\" unknown",
1293 						       addr);
1294 					else
1295 						memmove(&d->d_addr.sin6.sin6_addr,
1296 							*(hp->h_addr_list),
1297 							IN6ADDRSZ);
1298 #  if _FFR_FREEHOSTENT
1299 					freehostent(hp);
1300 					hp = NULL;
1301 #  endif /* _FFR_FREEHOSTENT */
1302 				}
1303 			}
1304 			break;
1305 # endif /* NETINET6 */
1306 
1307 		  default:
1308 			syserr("554 5.3.5 address= option unsupported for family %d",
1309 			       d->d_addr.sa.sa_family);
1310 			break;
1311 		}
1312 	}
1313 
1314 	if (port != NULL)
1315 	{
1316 		switch (d->d_addr.sa.sa_family)
1317 		{
1318 # if NETINET
1319 		  case AF_INET:
1320 			if (isascii(*port) && isdigit(*port))
1321 				d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)port));
1322 			else
1323 			{
1324 #  ifdef NO_GETSERVBYNAME
1325 				syserr("554 5.3.5 invalid port number: %s",
1326 				       port);
1327 #  else /* NO_GETSERVBYNAME */
1328 				register struct servent *sp;
1329 
1330 				sp = getservbyname(port, "tcp");
1331 				if (sp == NULL)
1332 					syserr("554 5.3.5 service \"%s\" unknown",
1333 					       port);
1334 				else
1335 					d->d_addr.sin.sin_port = sp->s_port;
1336 #  endif /* NO_GETSERVBYNAME */
1337 			}
1338 			break;
1339 # endif /* NETINET */
1340 
1341 # if NETINET6
1342 		  case AF_INET6:
1343 			if (isascii(*port) && isdigit(*port))
1344 				d->d_addr.sin6.sin6_port = htons((u_short)atoi(port));
1345 			else
1346 			{
1347 #  ifdef NO_GETSERVBYNAME
1348 				syserr("554 5.3.5 invalid port number: %s",
1349 				       port);
1350 #  else /* NO_GETSERVBYNAME */
1351 				register struct servent *sp;
1352 
1353 				sp = getservbyname(port, "tcp");
1354 				if (sp == NULL)
1355 					syserr("554 5.3.5 service \"%s\" unknown",
1356 					       port);
1357 				else
1358 					d->d_addr.sin6.sin6_port = sp->s_port;
1359 #  endif /* NO_GETSERVBYNAME */
1360 			}
1361 			break;
1362 # endif /* NETINET6 */
1363 
1364 # if NETISO
1365 		  case AF_ISO:
1366 			/* assume two byte transport selector */
1367 			if (isascii(*port) && isdigit(*port))
1368 				portno = htons((u_short)atoi(port));
1369 			else
1370 			{
1371 #  ifdef NO_GETSERVBYNAME
1372 				syserr("554 5.3.5 invalid port number: %s",
1373 				       port);
1374 #  else /* NO_GETSERVBYNAME */
1375 				register struct servent *sp;
1376 
1377 				sp = getservbyname(port, "tcp");
1378 				if (sp == NULL)
1379 					syserr("554 5.3.5 service \"%s\" unknown",
1380 					       port);
1381 				else
1382 					portno = sp->s_port;
1383 #  endif /* NO_GETSERVBYNAME */
1384 			}
1385 			memmove(TSEL(&d->d_addr.siso),
1386 				(char *) &portno, 2);
1387 			break;
1388 # endif /* NETISO */
1389 
1390 		  default:
1391 			syserr("554 5.3.5 Port= option unsupported for family %d",
1392 			       d->d_addr.sa.sa_family);
1393 			break;
1394 		}
1395 	}
1396 }
1397 /*
1398 **  SETDAEMONOPTIONS -- set options for running the MTA daemon
1399 **
1400 **	Parameters:
1401 **		p -- the options line.
1402 **
1403 **	Returns:
1404 **		TRUE if successful, FALSE otherwise.
1405 */
1406 
1407 bool
1408 setdaemonoptions(p)
1409 	register char *p;
1410 {
1411 	if (ndaemons >= MAXDAEMONS)
1412 		return FALSE;
1413 	Daemons[ndaemons].d_socket = -1;
1414 	Daemons[ndaemons].d_listenqueue = 10;
1415 	clrbitmap(Daemons[ndaemons].d_flags);
1416 	setsockaddroptions(p, &Daemons[ndaemons]);
1417 
1418 	if (Daemons[ndaemons].d_name != NULL)
1419 		Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name);
1420 	else
1421 	{
1422 		char num[30];
1423 
1424 		snprintf(num, sizeof num, "Daemon%d", ndaemons);
1425 		Daemons[ndaemons].d_name = newstr(num);
1426 	}
1427 
1428 	if (tTd(37, 1))
1429 	{
1430 		dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name);
1431 		if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags))
1432 			dprintf("ETRNONLY ");
1433 		if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags))
1434 			dprintf("NOETRN ");
1435 		dprintf("\n");
1436 	}
1437 	++ndaemons;
1438 	return TRUE;
1439 }
1440 /*
1441 **  INITDAEMON -- initialize daemon if not yet done.
1442 **
1443 **	Parameters:
1444 **		none
1445 **
1446 **	Returns:
1447 **		none
1448 **
1449 **	Side Effects:
1450 **		initializes structure for one daemon.
1451 */
1452 void
1453 initdaemon()
1454 {
1455 	if (ndaemons == 0)
1456 	{
1457 		Daemons[ndaemons].d_socket = -1;
1458 		Daemons[ndaemons].d_listenqueue = 10;
1459 		Daemons[ndaemons].d_name = "Daemon0";
1460 		ndaemons = 1;
1461 	}
1462 }
1463 /*
1464 **  SETCLIENTOPTIONS -- set options for running the client
1465 **
1466 **	Parameters:
1467 **		p -- the options line.
1468 **
1469 **	Returns:
1470 **		none.
1471 */
1472 
1473 static SOCKADDR	ClientAddr;		/* address for client */
1474 
1475 void
1476 setclientoptions(p)
1477 	register char *p;
1478 {
1479 	struct daemon d;
1480 	extern ENVELOPE BlankEnvelope;
1481 
1482 	memset(&d, '\0', sizeof d);
1483 	setsockaddroptions(p, &d);
1484 
1485 	/* grab what we need */
1486 	memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr);
1487 	TcpSndBufferSize = d.d_tcpsndbufsize;
1488 	TcpRcvBufferSize = d.d_tcprcvbufsize;
1489 	if (d.d_mflags != NULL)
1490 		define(macid("{client_flags}", NULL), d.d_mflags,
1491 		       &BlankEnvelope);
1492 	else
1493 		define(macid("{client_flags}", NULL), "", &BlankEnvelope);
1494 }
1495 /*
1496 **  ADDR_FAMILY -- determine address family from address
1497 **
1498 **	Parameters:
1499 **		addr -- the string representation of the address
1500 **
1501 **	Returns:
1502 **		AF_INET, AF_INET6 or AF_UNSPEC
1503 **
1504 **	Side Effects:
1505 **		none.
1506 */
1507 
1508 static int
1509 addr_family(addr)
1510 	char *addr;
1511 {
1512 # if NETINET6
1513 	SOCKADDR clt_addr;
1514 # endif /* NETINET6 */
1515 
1516 # if NETINET
1517 	if (inet_addr(addr) != INADDR_NONE)
1518 	{
1519 		if (tTd(16, 9))
1520 			printf("addr_family(%s): INET\n", addr);
1521 		return AF_INET;
1522 	}
1523 # endif /* NETINET */
1524 # if NETINET6
1525 	if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1)
1526 	{
1527 		if (tTd(16, 9))
1528 			printf("addr_family(%s): INET6\n", addr);
1529 		return AF_INET6;
1530 	}
1531 # endif /* NETINET6 */
1532 	if (tTd(16, 9))
1533 		printf("addr_family(%s): UNSPEC\n", addr);
1534 	return AF_UNSPEC;
1535 }
1536 /*
1537 **  MAKECONNECTION -- make a connection to an SMTP socket on a machine.
1538 **
1539 **	Parameters:
1540 **		host -- the name of the host.
1541 **		port -- the port number to connect to.
1542 **		mci -- a pointer to the mail connection information
1543 **			structure to be filled in.
1544 **		e -- the current envelope.
1545 **
1546 **	Returns:
1547 **		An exit code telling whether the connection could be
1548 **			made and if not why not.
1549 **
1550 **	Side Effects:
1551 **		none.
1552 */
1553 
1554 static jmp_buf	CtxConnectTimeout;
1555 
1556 SOCKADDR	CurHostAddr;		/* address of current host */
1557 
1558 int
1559 makeconnection(host, port, mci, e)
1560 	char *host;
1561 	volatile u_int port;
1562 	register MCI *mci;
1563 	ENVELOPE *e;
1564 {
1565 	register volatile int addrno = 0;
1566 	register volatile int s;
1567 	register struct hostent *volatile hp = (struct hostent *)NULL;
1568 	SOCKADDR addr;
1569 	SOCKADDR clt_addr;
1570 	int save_errno = 0;
1571 	volatile SOCKADDR_LEN_T addrlen;
1572 	volatile bool firstconnect;
1573 	EVENT *volatile ev = NULL;
1574 # if NETINET6
1575 	volatile bool v6found = FALSE;
1576 # endif /* NETINET6 */
1577 	volatile int family = InetMode;
1578 	SOCKADDR_LEN_T len;
1579 	volatile SOCKADDR_LEN_T socksize = 0;
1580 	volatile bool clt_bind;
1581 	BITMAP256 d_flags;
1582 	char *p;
1583 	extern ENVELOPE BlankEnvelope;
1584 
1585 	/* retranslate ${daemon_flags} into bitmap */
1586 	clrbitmap(d_flags);
1587 	if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL)
1588 	{
1589 		for (; *p != '\0'; p++)
1590 		{
1591 			if (!(isascii(*p) && isspace(*p)))
1592 				setbitn(bitidx(*p), d_flags);
1593 		}
1594 	}
1595 
1596 	/* "add" ${client_flags} to bitmap */
1597 	if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL)
1598 	{
1599 		for (; *p != '\0'; p++)
1600 		{
1601 			/* look for just this one flag */
1602 			if (*p == D_IFNHELO)
1603 			{
1604 				setbitn(bitidx(*p), d_flags);
1605 				break;
1606 			}
1607 		}
1608 	}
1609 
1610 # if NETINET6
1611  v4retry:
1612 # endif /* NETINET6 */
1613 	clt_bind = FALSE;
1614 
1615 	/* Set up the address for outgoing connection. */
1616 	if (bitnset(D_BINDIF, d_flags) &&
1617 	    (p = macvalue(macid("{if_addr}", NULL), e)) != NULL)
1618 	{
1619 # if NETINET6
1620 		char p6[INET6_ADDRSTRLEN];
1621 # endif /* NETINET6 */
1622 
1623 		memset(&clt_addr, '\0', sizeof clt_addr);
1624 
1625 		/* infer the address family from the address itself */
1626 		clt_addr.sa.sa_family = addr_family(p);
1627 		switch (clt_addr.sa.sa_family)
1628 		{
1629 # if NETINET
1630 		  case AF_INET:
1631 			if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p))
1632 			    != INADDR_NONE)
1633 			{
1634 				clt_bind = TRUE;
1635 				socksize = sizeof (struct sockaddr_in);
1636 			}
1637 			else if (clt_addr.sin.sin_port != 0)
1638 			{
1639 				clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
1640 				clt_bind = TRUE;
1641 				socksize = sizeof (struct sockaddr_in);
1642 			}
1643 			break;
1644 # endif /* NETINET */
1645 
1646 # if NETINET6
1647 		  case AF_INET6:
1648 			if (inet_addr(p) != INADDR_NONE)
1649 				snprintf(p6, sizeof p6, "::ffff:%s", p);
1650 			else
1651 				strlcpy(p6, p, sizeof p6);
1652 			if (inet_pton(AF_INET6, p6,
1653 				      &clt_addr.sin6.sin6_addr) == 1)
1654 			{
1655 				clt_bind = TRUE;
1656 				socksize = sizeof (struct sockaddr_in6);
1657 			}
1658 			else if (clt_addr.sin6.sin6_port != 0)
1659 			{
1660 				if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
1661 					clt_addr.sin6.sin6_addr = in6addr_any;
1662 				clt_bind = TRUE;
1663 				socksize = sizeof (struct sockaddr_in6);
1664 			}
1665 			break;
1666 # endif /* NETINET6 */
1667 
1668 # if 0
1669 		  default:
1670 			syserr("554 5.3.5 Address= option unsupported for family %d",
1671 			       clt_addr.sa.sa_family);
1672 			break;
1673 # endif /* 0 */
1674 		}
1675 		if (clt_bind)
1676 			family = clt_addr.sa.sa_family;
1677 	}
1678 	else
1679 	{
1680 		STRUCTCOPY(ClientAddr, clt_addr);
1681 		if (clt_addr.sa.sa_family == AF_UNSPEC)
1682 			clt_addr.sa.sa_family = InetMode;
1683 		switch (clt_addr.sa.sa_family)
1684 		{
1685 # if NETINET
1686 		  case AF_INET:
1687 			if (clt_addr.sin.sin_addr.s_addr == 0)
1688 				clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
1689 			else
1690 				clt_bind = TRUE;
1691 			if (clt_addr.sin.sin_port != 0)
1692 				clt_bind = TRUE;
1693 			socksize = sizeof (struct sockaddr_in);
1694 			break;
1695 # endif /* NETINET */
1696 # if NETINET6
1697 		  case AF_INET6:
1698 			if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
1699 				clt_addr.sin6.sin6_addr = in6addr_any;
1700 			else
1701 				clt_bind = TRUE;
1702 			socksize = sizeof (struct sockaddr_in6);
1703 			if (clt_addr.sin6.sin6_port != 0)
1704 				clt_bind = TRUE;
1705 			break;
1706 # endif /* NETINET6 */
1707 # if NETISO
1708 		  case AF_ISO:
1709 			socksize = sizeof clt_addr.siso;
1710 			clt_bind = TRUE;
1711 			break;
1712 # endif /* NETISO */
1713 		  default:
1714 			break;
1715 		}
1716 	}
1717 
1718 	/*
1719 	**  Set up the address for the mailer.
1720 	**	Accept "[a.b.c.d]" syntax for host name.
1721 	*/
1722 
1723 # if NAMED_BIND
1724 	h_errno = 0;
1725 # endif /* NAMED_BIND */
1726 	errno = 0;
1727 	memset(&CurHostAddr, '\0', sizeof CurHostAddr);
1728 	memset(&addr, '\0', sizeof addr);
1729 	SmtpPhase = mci->mci_phase = "initial connection";
1730 	CurHostName = host;
1731 
1732 	if (host[0] == '[')
1733 	{
1734 		p = strchr(host, ']');
1735 		if (p != NULL)
1736 		{
1737 # if NETINET
1738 			unsigned long hid = INADDR_NONE;
1739 # endif /* NETINET */
1740 # if NETINET6
1741 			struct sockaddr_in6 hid6;
1742 # endif /* NETINET6 */
1743 
1744 			*p = '\0';
1745 # if NETINET6
1746 			memset(&hid6, '\0', sizeof hid6);
1747 # endif /* NETINET6 */
1748 # if NETINET
1749 			if (family == AF_INET &&
1750 			    (hid = inet_addr(&host[1])) != INADDR_NONE)
1751 			{
1752 				addr.sin.sin_family = AF_INET;
1753 				addr.sin.sin_addr.s_addr = hid;
1754 			}
1755 			else
1756 # endif /* NETINET */
1757 # if NETINET6
1758 			if (family == AF_INET6 &&
1759 			    inet_pton(AF_INET6, &host[1],
1760 				      &hid6.sin6_addr) == 1)
1761 			{
1762 				addr.sin6.sin6_family = AF_INET6;
1763 				addr.sin6.sin6_addr = hid6.sin6_addr;
1764 			}
1765 			else
1766 # endif /* NETINET6 */
1767 			{
1768 				/* try it as a host name (avoid MX lookup) */
1769 				hp = sm_gethostbyname(&host[1], family);
1770 				if (hp == NULL && p[-1] == '.')
1771 				{
1772 # if NAMED_BIND
1773 					int oldopts = _res.options;
1774 
1775 					_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
1776 # endif /* NAMED_BIND */
1777 					p[-1] = '\0';
1778 					hp = sm_gethostbyname(&host[1],
1779 							      family);
1780 					p[-1] = '.';
1781 # if NAMED_BIND
1782 					_res.options = oldopts;
1783 # endif /* NAMED_BIND */
1784 				}
1785 				*p = ']';
1786 				goto gothostent;
1787 			}
1788 			*p = ']';
1789 		}
1790 		if (p == NULL)
1791 		{
1792 			extern char MsgBuf[];
1793 
1794 			usrerrenh("5.1.2",
1795 				  "553 Invalid numeric domain spec \"%s\"",
1796 				  host);
1797 			mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
1798 			errno = EINVAL;
1799 			return EX_NOHOST;
1800 		}
1801 	}
1802 	else
1803 	{
1804 		/* contortion to get around SGI cc complaints */
1805 		{
1806 			p = &host[strlen(host) - 1];
1807 			hp = sm_gethostbyname(host, family);
1808 			if (hp == NULL && *p == '.')
1809 			{
1810 # if NAMED_BIND
1811 				int oldopts = _res.options;
1812 
1813 				_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
1814 # endif /* NAMED_BIND */
1815 				*p = '\0';
1816 				hp = sm_gethostbyname(host, family);
1817 				*p = '.';
1818 # if NAMED_BIND
1819 				_res.options = oldopts;
1820 # endif /* NAMED_BIND */
1821 			}
1822 		}
1823 gothostent:
1824 		if (hp == NULL)
1825 		{
1826 # if NAMED_BIND
1827 			/* check for name server timeouts */
1828 			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
1829 			    (errno == ECONNREFUSED && UseNameServer))
1830 			{
1831 				save_errno = errno;
1832 				mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
1833 				errno = save_errno;
1834 				return EX_TEMPFAIL;
1835 			}
1836 # endif /* NAMED_BIND */
1837 # if NETINET6
1838 			/*
1839 			**  Try v6 first, then fall back to v4.
1840 			**  If we found a v6 address, but no v4
1841 			**  addresses, then TEMPFAIL.
1842 			*/
1843 
1844 			if (family == AF_INET6)
1845 			{
1846 				family = AF_INET;
1847 				goto v4retry;
1848 			}
1849 			if (v6found)
1850 				goto v6tempfail;
1851 # endif /* NETINET6 */
1852 			save_errno = errno;
1853 			mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
1854 			errno = save_errno;
1855 			return EX_NOHOST;
1856 		}
1857 		addr.sa.sa_family = hp->h_addrtype;
1858 		switch (hp->h_addrtype)
1859 		{
1860 # if NETINET
1861 		  case AF_INET:
1862 			memmove(&addr.sin.sin_addr,
1863 				hp->h_addr,
1864 				INADDRSZ);
1865 			break;
1866 # endif /* NETINET */
1867 
1868 # if NETINET6
1869 		  case AF_INET6:
1870 			memmove(&addr.sin6.sin6_addr,
1871 				hp->h_addr,
1872 				IN6ADDRSZ);
1873 			break;
1874 # endif /* NETINET6 */
1875 
1876 		  default:
1877 			if (hp->h_length > sizeof addr.sa.sa_data)
1878 			{
1879 				syserr("makeconnection: long sa_data: family %d len %d",
1880 					hp->h_addrtype, hp->h_length);
1881 				mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
1882 				errno = EINVAL;
1883 				return EX_NOHOST;
1884 			}
1885 			memmove(addr.sa.sa_data,
1886 				hp->h_addr,
1887 				hp->h_length);
1888 			break;
1889 		}
1890 		addrno = 1;
1891 	}
1892 
1893 	/*
1894 	**  Determine the port number.
1895 	*/
1896 
1897 	if (port == 0)
1898 	{
1899 # ifdef NO_GETSERVBYNAME
1900 		port = htons(25);
1901 # else /* NO_GETSERVBYNAME */
1902 		register struct servent *sp = getservbyname("smtp", "tcp");
1903 
1904 		if (sp == NULL)
1905 		{
1906 			if (LogLevel > 2)
1907 				sm_syslog(LOG_ERR, NOQID,
1908 					  "makeconnection: service \"smtp\" unknown");
1909 			port = htons(25);
1910 		}
1911 		else
1912 			port = sp->s_port;
1913 # endif /* NO_GETSERVBYNAME */
1914 	}
1915 
1916 	switch (addr.sa.sa_family)
1917 	{
1918 # if NETINET
1919 	  case AF_INET:
1920 		addr.sin.sin_port = port;
1921 		addrlen = sizeof (struct sockaddr_in);
1922 		break;
1923 # endif /* NETINET */
1924 
1925 # if NETINET6
1926 	  case AF_INET6:
1927 		addr.sin6.sin6_port = port;
1928 		addrlen = sizeof (struct sockaddr_in6);
1929 		break;
1930 # endif /* NETINET6 */
1931 
1932 # if NETISO
1933 	  case AF_ISO:
1934 		/* assume two byte transport selector */
1935 		memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
1936 		addrlen = sizeof (struct sockaddr_iso);
1937 		break;
1938 # endif /* NETISO */
1939 
1940 	  default:
1941 		syserr("Can't connect to address family %d", addr.sa.sa_family);
1942 		mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
1943 		errno = EINVAL;
1944 # if _FFR_FREEHOSTENT && NETINET6
1945 		if (hp != NULL)
1946 			freehostent(hp);
1947 # endif /* _FFR_FREEHOSTENT && NETINET6 */
1948 		return EX_NOHOST;
1949 	}
1950 
1951 	/*
1952 	**  Try to actually open the connection.
1953 	*/
1954 
1955 # ifdef XLA
1956 	/* if too many connections, don't bother trying */
1957 	if (!xla_noqueue_ok(host))
1958 	{
1959 #  if _FFR_FREEHOSTENT && NETINET6
1960 		if (hp != NULL)
1961 			freehostent(hp);
1962 #  endif /* _FFR_FREEHOSTENT && NETINET6 */
1963 		return EX_TEMPFAIL;
1964 	}
1965 # endif /* XLA */
1966 
1967 	firstconnect = TRUE;
1968 	for (;;)
1969 	{
1970 		if (tTd(16, 1))
1971 			dprintf("makeconnection (%s [%s])\n",
1972 				host, anynet_ntoa(&addr));
1973 
1974 		/* save for logging */
1975 		CurHostAddr = addr;
1976 
1977 		if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
1978 		{
1979 			int rport = IPPORT_RESERVED - 1;
1980 
1981 			s = rresvport(&rport);
1982 		}
1983 		else
1984 		{
1985 			s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
1986 		}
1987 		if (s < 0)
1988 		{
1989 			save_errno = errno;
1990 			syserr("makeconnection: cannot create socket");
1991 # ifdef XLA
1992 			xla_host_end(host);
1993 # endif /* XLA */
1994 			mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
1995 # if _FFR_FREEHOSTENT && NETINET6
1996 			if (hp != NULL)
1997 				freehostent(hp);
1998 # endif /* _FFR_FREEHOSTENT && NETINET6 */
1999 			errno = save_errno;
2000 			return EX_TEMPFAIL;
2001 		}
2002 
2003 # ifdef SO_SNDBUF
2004 		if (TcpSndBufferSize > 0)
2005 		{
2006 			if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
2007 				       (char *) &TcpSndBufferSize,
2008 				       sizeof(TcpSndBufferSize)) < 0)
2009 				syserr("makeconnection: setsockopt(SO_SNDBUF)");
2010 		}
2011 # endif /* SO_SNDBUF */
2012 # ifdef SO_RCVBUF
2013 		if (TcpRcvBufferSize > 0)
2014 		{
2015 			if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
2016 				       (char *) &TcpRcvBufferSize,
2017 				       sizeof(TcpRcvBufferSize)) < 0)
2018 				syserr("makeconnection: setsockopt(SO_RCVBUF)");
2019 		}
2020 # endif /* SO_RCVBUF */
2021 
2022 
2023 		if (tTd(16, 1))
2024 			dprintf("makeconnection: fd=%d\n", s);
2025 
2026 		/* turn on network debugging? */
2027 		if (tTd(16, 101))
2028 		{
2029 			int on = 1;
2030 
2031 			(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
2032 					  (char *)&on, sizeof on);
2033 		}
2034 		if (e->e_xfp != NULL)
2035 			(void) fflush(e->e_xfp);	/* for debugging */
2036 		errno = 0;				/* for debugging */
2037 
2038 		if (clt_bind)
2039 		{
2040 			int on = 1;
2041 
2042 			switch (clt_addr.sa.sa_family)
2043 			{
2044 # if NETINET
2045 			  case AF_INET:
2046 				if (clt_addr.sin.sin_port != 0)
2047 					(void) setsockopt(s, SOL_SOCKET,
2048 							  SO_REUSEADDR,
2049 							  (char *) &on,
2050 							  sizeof on);
2051 				break;
2052 # endif /* NETINET */
2053 
2054 # if NETINET6
2055 			  case AF_INET6:
2056 				if (clt_addr.sin6.sin6_port != 0)
2057 					(void) setsockopt(s, SOL_SOCKET,
2058 							  SO_REUSEADDR,
2059 							  (char *) &on,
2060 							  sizeof on);
2061 				break;
2062 # endif /* NETINET6 */
2063 			}
2064 
2065 			if (bind(s, &clt_addr.sa, socksize) < 0)
2066 			{
2067 				save_errno = errno;
2068 				(void) close(s);
2069 				errno = save_errno;
2070 				syserr("makeconnection: cannot bind socket [%s]",
2071 				       anynet_ntoa(&clt_addr));
2072 # if _FFR_FREEHOSTENT && NETINET6
2073 				if (hp != NULL)
2074 					freehostent(hp);
2075 # endif /* _FFR_FREEHOSTENT && NETINET6 */
2076 				errno = save_errno;
2077 				return EX_TEMPFAIL;
2078 			}
2079 		}
2080 
2081 		/*
2082 		**  Linux seems to hang in connect for 90 minutes (!!!).
2083 		**  Time out the connect to avoid this problem.
2084 		*/
2085 
2086 		if (setjmp(CtxConnectTimeout) == 0)
2087 		{
2088 			int i;
2089 
2090 			if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
2091 				ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
2092 			else if (TimeOuts.to_connect != 0)
2093 				ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
2094 			else
2095 				ev = NULL;
2096 
2097 			switch (ConnectOnlyTo.sa.sa_family)
2098 			{
2099 # if NETINET
2100 			  case AF_INET:
2101 				addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr;
2102 				break;
2103 # endif /* NETINET */
2104 
2105 # if NETINET6
2106 			  case AF_INET6:
2107 				memmove(&addr.sin6.sin6_addr,
2108 					&ConnectOnlyTo.sin6.sin6_addr,
2109 					IN6ADDRSZ);
2110 				break;
2111 # endif /* NETINET6 */
2112 			}
2113 			i = connect(s, (struct sockaddr *) &addr, addrlen);
2114 			save_errno = errno;
2115 			if (ev != NULL)
2116 				clrevent(ev);
2117 			if (i >= 0)
2118 				break;
2119 		}
2120 		else
2121 			save_errno = errno;
2122 
2123 		/* if running demand-dialed connection, try again */
2124 		if (DialDelay > 0 && firstconnect)
2125 		{
2126 			if (tTd(16, 1))
2127 				dprintf("Connect failed (%s); trying again...\n",
2128 					errstring(save_errno));
2129 			firstconnect = FALSE;
2130 			(void) sleep(DialDelay);
2131 			continue;
2132 		}
2133 
2134 		/* couldn't connect.... figure out why */
2135 		(void) close(s);
2136 
2137 		if (LogLevel >= 14)
2138 			sm_syslog(LOG_INFO, e->e_id,
2139 				  "makeconnection (%s [%s]) failed: %s",
2140 				  host, anynet_ntoa(&addr),
2141 				  errstring(save_errno));
2142 
2143 		if (hp != NULL && hp->h_addr_list[addrno] != NULL)
2144 		{
2145 			if (tTd(16, 1))
2146 				dprintf("Connect failed (%s); trying new address....\n",
2147 					errstring(save_errno));
2148 			switch (addr.sa.sa_family)
2149 			{
2150 # if NETINET
2151 			  case AF_INET:
2152 				memmove(&addr.sin.sin_addr,
2153 					hp->h_addr_list[addrno++],
2154 					INADDRSZ);
2155 				break;
2156 # endif /* NETINET */
2157 
2158 # if NETINET6
2159 			  case AF_INET6:
2160 				memmove(&addr.sin6.sin6_addr,
2161 					hp->h_addr_list[addrno++],
2162 					IN6ADDRSZ);
2163 				break;
2164 # endif /* NETINET6 */
2165 
2166 			  default:
2167 				memmove(addr.sa.sa_data,
2168 					hp->h_addr_list[addrno++],
2169 					hp->h_length);
2170 				break;
2171 			}
2172 			continue;
2173 		}
2174 		errno = save_errno;
2175 
2176 # if NETINET6
2177 		if (family == AF_INET6)
2178 		{
2179 			if (tTd(16, 1))
2180 				dprintf("Connect failed (%s); retrying with AF_INET....\n",
2181 					errstring(save_errno));
2182 			v6found = TRUE;
2183 			family = AF_INET;
2184 #  if _FFR_FREEHOSTENT
2185 			if (hp != NULL)
2186 			{
2187 				freehostent(hp);
2188 				hp = NULL;
2189 			}
2190 #  endif /* _FFR_FREEHOSTENT */
2191 			goto v4retry;
2192 		}
2193 	v6tempfail:
2194 # endif /* NETINET6 */
2195 		/* couldn't open connection */
2196 # if NETINET6
2197 		/* Don't clobber an already saved errno from v4retry */
2198 		if (errno > 0)
2199 # endif /* NETINET6 */
2200 			save_errno = errno;
2201 		if (tTd(16, 1))
2202 			dprintf("Connect failed (%s)\n", errstring(save_errno));
2203 # ifdef XLA
2204 		xla_host_end(host);
2205 # endif /* XLA */
2206 		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
2207 # if _FFR_FREEHOSTENT && NETINET6
2208 		if (hp != NULL)
2209 			freehostent(hp);
2210 # endif /* _FFR_FREEHOSTENT && NETINET6 */
2211 		errno = save_errno;
2212 		return EX_TEMPFAIL;
2213 	}
2214 
2215 # if _FFR_FREEHOSTENT && NETINET6
2216 	if (hp != NULL)
2217 	{
2218 		freehostent(hp);
2219 		hp = NULL;
2220 	}
2221 # endif /* _FFR_FREEHOSTENT && NETINET6 */
2222 
2223 	/* connection ok, put it into canonical form */
2224 	mci->mci_out = NULL;
2225 	if ((mci->mci_out = fdopen(s, "w")) == NULL ||
2226 	    (s = dup(s)) < 0 ||
2227 	    (mci->mci_in = fdopen(s, "r")) == NULL)
2228 	{
2229 		save_errno = errno;
2230 		syserr("cannot open SMTP client channel, fd=%d", s);
2231 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2232 		if (mci->mci_out != NULL)
2233 			(void) fclose(mci->mci_out);
2234 		(void) close(s);
2235 		errno = save_errno;
2236 		return EX_TEMPFAIL;
2237 	}
2238 
2239 	/* find out name for Interface through which we connect */
2240 	len = sizeof addr;
2241 	if (getsockname(s, &addr.sa, &len) == 0)
2242 	{
2243 		char *name;
2244 		char *p;
2245 
2246 		define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)),
2247 		       &BlankEnvelope);
2248 		p = xalloc(5);
2249 		snprintf(p, 4, "%d", addr.sa.sa_family);
2250 		define(macid("{if_family}", NULL), p, &BlankEnvelope);
2251 
2252 		name = hostnamebyanyaddr(&addr);
2253 		define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope);
2254 		if (LogLevel > 11)
2255 		{
2256 			/* log connection information */
2257 			sm_syslog(LOG_INFO, e->e_id,
2258 				  "SMTP outgoing connect on %.40s", name);
2259 		}
2260 		if (bitnset(D_IFNHELO, d_flags))
2261 		{
2262 			if (name[0] != '[' && strchr(name, '.') != NULL)
2263 				mci->mci_heloname = newstr(name);
2264 		}
2265 	}
2266 	else
2267 	{
2268 		define(macid("{if_name}", NULL), NULL, &BlankEnvelope);
2269 		define(macid("{if_addr}", NULL), NULL, &BlankEnvelope);
2270 		define(macid("{if_family}", NULL), NULL, &BlankEnvelope);
2271 	}
2272 	mci_setstat(mci, EX_OK, NULL, NULL);
2273 	return EX_OK;
2274 }
2275 
2276 static void
2277 connecttimeout()
2278 {
2279 	errno = ETIMEDOUT;
2280 	longjmp(CtxConnectTimeout, 1);
2281 }
2282 /*
2283 **  MAKECONNECTION_DS -- make a connection to a domain socket.
2284 **
2285 **	Parameters:
2286 **		mux_path -- the path of the socket to connect to.
2287 **		mci -- a pointer to the mail connection information
2288 **			structure to be filled in.
2289 **
2290 **	Returns:
2291 **		An exit code telling whether the connection could be
2292 **			made and if not why not.
2293 **
2294 **	Side Effects:
2295 **		none.
2296 */
2297 
2298 # if NETUNIX
2299 int makeconnection_ds(mux_path, mci)
2300 	char *mux_path;
2301 	register MCI *mci;
2302 {
2303 	int sock;
2304 	int rval, save_errno;
2305 	long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK;
2306 	struct sockaddr_un unix_addr;
2307 
2308 	/* if not safe, don't connect */
2309 	rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName,
2310 			sff, S_IRUSR|S_IWUSR, NULL);
2311 
2312 	if (rval != 0)
2313 	{
2314 		syserr("makeconnection_ds: unsafe domain socket");
2315 		mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
2316 		errno = rval;
2317 		return EX_TEMPFAIL;
2318 	}
2319 
2320 	/* prepare address structure */
2321 	memset(&unix_addr, '\0', sizeof unix_addr);
2322 	unix_addr.sun_family = AF_UNIX;
2323 
2324 	if (strlen(mux_path) >= sizeof unix_addr.sun_path)
2325 	{
2326 		syserr("makeconnection_ds: domain socket name too long");
2327 		/* XXX why TEMPFAIL ? */
2328 		mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
2329 		errno = ENAMETOOLONG;
2330 		return EX_UNAVAILABLE;
2331 	}
2332 	(void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path);
2333 
2334 	/* initialize domain socket */
2335 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2336 	if (sock == -1)
2337 	{
2338 		save_errno = errno;
2339 		syserr("makeconnection_ds: could not create domain socket");
2340 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2341 		errno = save_errno;
2342 		return EX_TEMPFAIL;
2343 	}
2344 
2345 	/* connect to server */
2346 	if (connect(sock, (struct sockaddr *) &unix_addr,
2347 		    sizeof(unix_addr)) == -1)
2348 	{
2349 		save_errno = errno;
2350 		syserr("Could not connect to socket %s", mux_path);
2351 		mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
2352 		(void) close(sock);
2353 		errno = save_errno;
2354 		return EX_TEMPFAIL;
2355 	}
2356 
2357 	/* connection ok, put it into canonical form */
2358 	mci->mci_out = NULL;
2359 	if ((mci->mci_out = fdopen(sock, "w")) == NULL ||
2360 	    (sock = dup(sock)) < 0 ||
2361 	    (mci->mci_in = fdopen(sock, "r")) == NULL)
2362 	{
2363 		save_errno = errno;
2364 		syserr("cannot open SMTP client channel, fd=%d", sock);
2365 		mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
2366 		if (mci->mci_out != NULL)
2367 			(void) fclose(mci->mci_out);
2368 		(void) close(sock);
2369 		errno = save_errno;
2370 		return EX_TEMPFAIL;
2371 	}
2372 
2373 	mci_setstat(mci, EX_OK, NULL, NULL);
2374 	errno = 0;
2375 	return EX_OK;
2376 }
2377 # endif /* NETUNIX */
2378 /*
2379 **  MYHOSTNAME -- return the name of this host.
2380 **
2381 **	Parameters:
2382 **		hostbuf -- a place to return the name of this host.
2383 **		size -- the size of hostbuf.
2384 **
2385 **	Returns:
2386 **		A list of aliases for this host.
2387 **
2388 **	Side Effects:
2389 **		Adds numeric codes to $=w.
2390 */
2391 
2392 struct hostent *
2393 myhostname(hostbuf, size)
2394 	char hostbuf[];
2395 	int size;
2396 {
2397 	register struct hostent *hp;
2398 
2399 	if (gethostname(hostbuf, size) < 0)
2400 	{
2401 		(void) strlcpy(hostbuf, "localhost", size);
2402 	}
2403 	hp = sm_gethostbyname(hostbuf, InetMode);
2404 	if (hp == NULL)
2405 		return NULL;
2406 	if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
2407 		(void) cleanstrcpy(hostbuf, hp->h_name, size);
2408 
2409 # if NETINFO
2410 	if (strchr(hostbuf, '.') == NULL)
2411 	{
2412 		char *domainname;
2413 
2414 		domainname = ni_propval("/locations", NULL, "resolver",
2415 					"domain", '\0');
2416 		if (domainname != NULL &&
2417 		    strlen(domainname) + strlen(hostbuf) + 1 < size)
2418 		{
2419 			(void) strlcat(hostbuf, ".", size);
2420 			(void) strlcat(hostbuf, domainname, size);
2421 		}
2422 	}
2423 # endif /* NETINFO */
2424 
2425 	/*
2426 	**  If there is still no dot in the name, try looking for a
2427 	**  dotted alias.
2428 	*/
2429 
2430 	if (strchr(hostbuf, '.') == NULL)
2431 	{
2432 		char **ha;
2433 
2434 		for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
2435 		{
2436 			if (strchr(*ha, '.') != NULL)
2437 			{
2438 				(void) cleanstrcpy(hostbuf, *ha, size - 1);
2439 				hostbuf[size - 1] = '\0';
2440 				break;
2441 			}
2442 		}
2443 	}
2444 
2445 	/*
2446 	**  If _still_ no dot, wait for a while and try again -- it is
2447 	**  possible that some service is starting up.  This can result
2448 	**  in excessive delays if the system is badly configured, but
2449 	**  there really isn't a way around that, particularly given that
2450 	**  the config file hasn't been read at this point.
2451 	**  All in all, a bit of a mess.
2452 	*/
2453 
2454 	if (strchr(hostbuf, '.') == NULL &&
2455 	    !getcanonname(hostbuf, size, TRUE))
2456 	{
2457 		sm_syslog(LOG_CRIT, NOQID,
2458 			  "My unqualified host name (%s) unknown; sleeping for retry",
2459 			  hostbuf);
2460 		message("My unqualified host name (%s) unknown; sleeping for retry",
2461 			hostbuf);
2462 		(void) sleep(60);
2463 		if (!getcanonname(hostbuf, size, TRUE))
2464 		{
2465 			sm_syslog(LOG_ALERT, NOQID,
2466 				  "unable to qualify my own domain name (%s) -- using short name",
2467 				  hostbuf);
2468 			message("WARNING: unable to qualify my own domain name (%s) -- using short name",
2469 				hostbuf);
2470 		}
2471 	}
2472 	return hp;
2473 }
2474 /*
2475 **  ADDRCMP -- compare two host addresses
2476 **
2477 **	Parameters:
2478 **		hp -- hostent structure for the first address
2479 **		ha -- actual first address
2480 **		sa -- second address
2481 **
2482 **	Returns:
2483 **		0 -- if ha and sa match
2484 **		else -- they don't match
2485 */
2486 
2487 static int
2488 addrcmp(hp, ha, sa)
2489 	struct hostent *hp;
2490 	char *ha;
2491 	SOCKADDR *sa;
2492 {
2493 # if NETINET6
2494 	u_char *a;
2495 # endif /* NETINET6 */
2496 
2497 	switch (sa->sa.sa_family)
2498 	{
2499 # if NETINET
2500 	  case AF_INET:
2501 		if (hp->h_addrtype == AF_INET)
2502 			return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ);
2503 		break;
2504 # endif /* NETINET */
2505 
2506 # if NETINET6
2507 	  case AF_INET6:
2508 		a = (u_char *) &sa->sin6.sin6_addr;
2509 
2510 		/* Straight binary comparison */
2511 		if (hp->h_addrtype == AF_INET6)
2512 			return memcmp(ha, a, IN6ADDRSZ);
2513 
2514 		/* If IPv4-mapped IPv6 address, compare the IPv4 section */
2515 		if (hp->h_addrtype == AF_INET &&
2516 		    IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr))
2517 			return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ);
2518 		break;
2519 # endif /* NETINET6 */
2520 	}
2521 	return -1;
2522 }
2523 /*
2524 **  GETAUTHINFO -- get the real host name associated with a file descriptor
2525 **
2526 **	Uses RFC1413 protocol to try to get info from the other end.
2527 **
2528 **	Parameters:
2529 **		fd -- the descriptor
2530 **		may_be_forged -- an outage that is set to TRUE if the
2531 **			forward lookup of RealHostName does not match
2532 **			RealHostAddr; set to FALSE if they do match.
2533 **
2534 **	Returns:
2535 **		The user@host information associated with this descriptor.
2536 */
2537 
2538 static jmp_buf	CtxAuthTimeout;
2539 
2540 static void
2541 authtimeout()
2542 {
2543 	longjmp(CtxAuthTimeout, 1);
2544 }
2545 
2546 char *
2547 getauthinfo(fd, may_be_forged)
2548 	int fd;
2549 	bool *may_be_forged;
2550 {
2551 	volatile u_short port = 0;
2552 	SOCKADDR_LEN_T falen;
2553 	register char *volatile p = NULL;
2554 	SOCKADDR la;
2555 	SOCKADDR_LEN_T lalen;
2556 	register struct servent *sp;
2557 	volatile int s;
2558 	int i = 0;
2559 	EVENT *ev;
2560 	int nleft;
2561 	struct hostent *hp;
2562 	char *ostype = NULL;
2563 	char **ha;
2564 	char ibuf[MAXNAME + 1];
2565 	static char hbuf[MAXNAME * 2 + 11];
2566 
2567 	*may_be_forged = FALSE;
2568 	falen = sizeof RealHostAddr;
2569 	if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
2570 	    falen <= 0 || RealHostAddr.sa.sa_family == 0)
2571 	{
2572 		if (i < 0)
2573 		{
2574 			/*
2575 			**  ENOTSOCK is OK: bail on anything else, but reset
2576 			**  errno in this case, so a mis-report doesn't
2577 			**  happen later.
2578 			*/
2579 			if (errno != ENOTSOCK)
2580 				return NULL;
2581 			errno = 0;
2582 		}
2583 		(void) snprintf(hbuf, sizeof hbuf, "%s@localhost",
2584 				RealUserName);
2585 		if (tTd(9, 1))
2586 			dprintf("getauthinfo: %s\n", hbuf);
2587 		return hbuf;
2588 	}
2589 
2590 	if (RealHostName == NULL)
2591 	{
2592 		/* translate that to a host name */
2593 		RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
2594 		if (strlen(RealHostName) > MAXNAME)
2595 			RealHostName[MAXNAME] = '\0';
2596 	}
2597 
2598 	/* cross check RealHostName with forward DNS lookup */
2599 	if (anynet_ntoa(&RealHostAddr)[0] == '[' ||
2600 	    RealHostName[0] == '[')
2601 	{
2602 		/*
2603 		**  address is not a socket or have an
2604 		**  IP address with no forward lookup
2605 		*/
2606 		*may_be_forged = FALSE;
2607 	}
2608 	else
2609 	{
2610 		/* try to match the reverse against the forward lookup */
2611 		hp = sm_gethostbyname(RealHostName,
2612 				      RealHostAddr.sa.sa_family);
2613 
2614 		if (hp == NULL)
2615 			*may_be_forged = TRUE;
2616 		else
2617 		{
2618 			for (ha = hp->h_addr_list; *ha != NULL; ha++)
2619 				if (addrcmp(hp, *ha, &RealHostAddr) == 0)
2620 					break;
2621 			*may_be_forged = *ha == NULL;
2622 # if _FFR_FREEHOSTENT && NETINET6
2623 			freehostent(hp);
2624 			hp = NULL;
2625 # endif /* _FFR_FREEHOSTENT && NETINET6 */
2626 		}
2627 	}
2628 
2629 	if (TimeOuts.to_ident == 0)
2630 		goto noident;
2631 
2632 	lalen = sizeof la;
2633 	switch (RealHostAddr.sa.sa_family)
2634 	{
2635 # if NETINET
2636 	  case AF_INET:
2637 		if (getsockname(fd, &la.sa, &lalen) < 0 ||
2638 		    lalen <= 0 ||
2639 		    la.sa.sa_family != AF_INET)
2640 		{
2641 			/* no ident info */
2642 			goto noident;
2643 		}
2644 		port = RealHostAddr.sin.sin_port;
2645 
2646 		/* create ident query */
2647 		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
2648 				ntohs(RealHostAddr.sin.sin_port),
2649 				ntohs(la.sin.sin_port));
2650 
2651 		/* create local address */
2652 		la.sin.sin_port = 0;
2653 
2654 		/* create foreign address */
2655 #  ifdef NO_GETSERVBYNAME
2656 		RealHostAddr.sin.sin_port = htons(113);
2657 #  else /* NO_GETSERVBYNAME */
2658 		sp = getservbyname("auth", "tcp");
2659 		if (sp != NULL)
2660 			RealHostAddr.sin.sin_port = sp->s_port;
2661 		else
2662 			RealHostAddr.sin.sin_port = htons(113);
2663 		break;
2664 #  endif /* NO_GETSERVBYNAME */
2665 # endif /* NETINET */
2666 
2667 # if NETINET6
2668 	  case AF_INET6:
2669 		if (getsockname(fd, &la.sa, &lalen) < 0 ||
2670 		    lalen <= 0 ||
2671 		    la.sa.sa_family != AF_INET6)
2672 		{
2673 			/* no ident info */
2674 			goto noident;
2675 		}
2676 		port = RealHostAddr.sin6.sin6_port;
2677 
2678 		/* create ident query */
2679 		(void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
2680 				ntohs(RealHostAddr.sin6.sin6_port),
2681 				ntohs(la.sin6.sin6_port));
2682 
2683 		/* create local address */
2684 		la.sin6.sin6_port = 0;
2685 
2686 		/* create foreign address */
2687 #  ifdef NO_GETSERVBYNAME
2688 		RealHostAddr.sin6.sin6_port = htons(113);
2689 #  else /* NO_GETSERVBYNAME */
2690 		sp = getservbyname("auth", "tcp");
2691 		if (sp != NULL)
2692 			RealHostAddr.sin6.sin6_port = sp->s_port;
2693 		else
2694 			RealHostAddr.sin6.sin6_port = htons(113);
2695 		break;
2696 #  endif /* NO_GETSERVBYNAME */
2697 # endif /* NETINET6 */
2698 	  default:
2699 		/* no ident info */
2700 		goto noident;
2701 	}
2702 
2703 	s = -1;
2704 	if (setjmp(CtxAuthTimeout) != 0)
2705 	{
2706 		if (s >= 0)
2707 			(void) close(s);
2708 		goto noident;
2709 	}
2710 
2711 	/* put a timeout around the whole thing */
2712 	ev = setevent(TimeOuts.to_ident, authtimeout, 0);
2713 
2714 
2715 	/* connect to foreign IDENT server using same address as SMTP socket */
2716 	s = socket(la.sa.sa_family, SOCK_STREAM, 0);
2717 	if (s < 0)
2718 	{
2719 		clrevent(ev);
2720 		goto noident;
2721 	}
2722 	if (bind(s, &la.sa, lalen) < 0 ||
2723 	    connect(s, &RealHostAddr.sa, lalen) < 0)
2724 	{
2725 		goto closeident;
2726 	}
2727 
2728 	if (tTd(9, 10))
2729 		dprintf("getauthinfo: sent %s", ibuf);
2730 
2731 	/* send query */
2732 	if (write(s, ibuf, strlen(ibuf)) < 0)
2733 		goto closeident;
2734 
2735 	/* get result */
2736 	p = &ibuf[0];
2737 	nleft = sizeof ibuf - 1;
2738 	while ((i = read(s, p, nleft)) > 0)
2739 	{
2740 		p += i;
2741 		nleft -= i;
2742 		*p = '\0';
2743 		if (strchr(ibuf, '\n') != NULL)
2744 			break;
2745 	}
2746 	(void) close(s);
2747 	clrevent(ev);
2748 	if (i < 0 || p == &ibuf[0])
2749 		goto noident;
2750 
2751 	if (*--p == '\n' && *--p == '\r')
2752 		p--;
2753 	*++p = '\0';
2754 
2755 	if (tTd(9, 3))
2756 		dprintf("getauthinfo:  got %s\n", ibuf);
2757 
2758 	/* parse result */
2759 	p = strchr(ibuf, ':');
2760 	if (p == NULL)
2761 	{
2762 		/* malformed response */
2763 		goto noident;
2764 	}
2765 	while (isascii(*++p) && isspace(*p))
2766 		continue;
2767 	if (strncasecmp(p, "userid", 6) != 0)
2768 	{
2769 		/* presumably an error string */
2770 		goto noident;
2771 	}
2772 	p += 6;
2773 	while (isascii(*p) && isspace(*p))
2774 		p++;
2775 	if (*p++ != ':')
2776 	{
2777 		/* either useridxx or malformed response */
2778 		goto noident;
2779 	}
2780 
2781 	/* p now points to the OSTYPE field */
2782 	while (isascii(*p) && isspace(*p))
2783 		p++;
2784 	ostype = p;
2785 	p = strchr(p, ':');
2786 	if (p == NULL)
2787 	{
2788 		/* malformed response */
2789 		goto noident;
2790 	}
2791 	else
2792 	{
2793 		char *charset;
2794 
2795 		*p = '\0';
2796 		charset = strchr(ostype, ',');
2797 		if (charset != NULL)
2798 			*charset = '\0';
2799 	}
2800 
2801 	/* 1413 says don't do this -- but it's broken otherwise */
2802 	while (isascii(*++p) && isspace(*p))
2803 		continue;
2804 
2805 	/* p now points to the authenticated name -- copy carefully */
2806 	if (strncasecmp(ostype, "other", 5) == 0 &&
2807 	    (ostype[5] == ' ' || ostype[5] == '\0'))
2808 	{
2809 		snprintf(hbuf, sizeof hbuf, "IDENT:");
2810 		cleanstrcpy(&hbuf[6], p, MAXNAME);
2811 	}
2812 	else
2813 		cleanstrcpy(hbuf, p, MAXNAME);
2814 	i = strlen(hbuf);
2815 	snprintf(&hbuf[i], sizeof hbuf - i, "@%s",
2816 		 RealHostName == NULL ? "localhost" : RealHostName);
2817 	goto postident;
2818 
2819 closeident:
2820 	(void) close(s);
2821 	clrevent(ev);
2822 
2823 noident:
2824 	/* put back the original incoming port */
2825 	switch (RealHostAddr.sa.sa_family)
2826 	{
2827 # if NETINET
2828 	  case AF_INET:
2829 		if (port > 0)
2830 			RealHostAddr.sin.sin_port = port;
2831 		break;
2832 # endif /* NETINET */
2833 
2834 # if NETINET6
2835 	  case AF_INET6:
2836 		if (port > 0)
2837 			RealHostAddr.sin6.sin6_port = port;
2838 		break;
2839 # endif /* NETINET6 */
2840 	}
2841 
2842 	if (RealHostName == NULL)
2843 	{
2844 		if (tTd(9, 1))
2845 			dprintf("getauthinfo: NULL\n");
2846 		return NULL;
2847 	}
2848 	snprintf(hbuf, sizeof hbuf, "%s", RealHostName);
2849 
2850 postident:
2851 # if IP_SRCROUTE
2852 #  ifndef GET_IPOPT_DST
2853 #   define GET_IPOPT_DST(dst)	(dst)
2854 #  endif /* ! GET_IPOPT_DST */
2855 	/*
2856 	**  Extract IP source routing information.
2857 	**
2858 	**	Format of output for a connection from site a through b
2859 	**	through c to d:
2860 	**		loose:      @site-c@site-b:site-a
2861 	**		strict:	   !@site-c@site-b:site-a
2862 	**
2863 	**	o - pointer within ipopt_list structure.
2864 	**	q - pointer within ls/ss rr route data
2865 	**	p - pointer to hbuf
2866 	*/
2867 
2868 	if (RealHostAddr.sa.sa_family == AF_INET)
2869 	{
2870 		SOCKOPT_LEN_T ipoptlen;
2871 		int j;
2872 		u_char *q;
2873 		u_char *o;
2874 		int l;
2875 		struct IPOPTION ipopt;
2876 
2877 		ipoptlen = sizeof ipopt;
2878 		if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
2879 			       (char *) &ipopt, &ipoptlen) < 0)
2880 			goto noipsr;
2881 		if (ipoptlen == 0)
2882 			goto noipsr;
2883 		o = (u_char *) ipopt.IP_LIST;
2884 		while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
2885 		{
2886 			switch (*o)
2887 			{
2888 			  case IPOPT_EOL:
2889 				o = NULL;
2890 				break;
2891 
2892 			  case IPOPT_NOP:
2893 				o++;
2894 				break;
2895 
2896 			  case IPOPT_SSRR:
2897 			  case IPOPT_LSRR:
2898 				/*
2899 				**  Source routing.
2900 				**	o[0] is the option type (loose/strict).
2901 				**	o[1] is the length of this option,
2902 				**		including option type and
2903 				**		length.
2904 				**	o[2] is the pointer into the route
2905 				**		data.
2906 				**	o[3] begins the route data.
2907 				*/
2908 
2909 				p = &hbuf[strlen(hbuf)];
2910 				l = sizeof hbuf - (hbuf - p) - 6;
2911 				snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
2912 				    *o == IPOPT_SSRR ? "!" : "",
2913 				    l > 240 ? 120 : l / 2,
2914 				    inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST)));
2915 				i = strlen(p);
2916 				p += i;
2917 				l -= strlen(p);
2918 
2919 				j = o[1] / sizeof(struct in_addr) - 1;
2920 
2921 				/* q skips length and router pointer to data */
2922 				q = &o[3];
2923 				for ( ; j >= 0; j--)
2924 				{
2925 					struct in_addr addr;
2926 
2927 					memcpy(&addr, q, sizeof(addr));
2928 					snprintf(p, SPACELEFT(hbuf, p),
2929 						 "%c%.*s",
2930 						 j != 0 ? '@' : ':',
2931 						 l > 240 ? 120 :
2932 						 j == 0 ? l : l / 2,
2933 						 inet_ntoa(addr));
2934 					i = strlen(p);
2935 					p += i;
2936 					l -= i + 1;
2937 					q += sizeof(struct in_addr);
2938 				}
2939 				o += o[1];
2940 				break;
2941 
2942 			  default:
2943 				/* Skip over option */
2944 				o += o[1];
2945 				break;
2946 			}
2947 		}
2948 		snprintf(p, SPACELEFT(hbuf, p), "]");
2949 		goto postipsr;
2950 	}
2951 
2952 noipsr:
2953 # endif /* IP_SRCROUTE */
2954 	if (RealHostName != NULL && RealHostName[0] != '[')
2955 	{
2956 		p = &hbuf[strlen(hbuf)];
2957 		(void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
2958 			anynet_ntoa(&RealHostAddr));
2959 	}
2960 	if (*may_be_forged)
2961 	{
2962 		p = &hbuf[strlen(hbuf)];
2963 		(void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
2964 	}
2965 
2966 # if IP_SRCROUTE
2967 postipsr:
2968 # endif /* IP_SRCROUTE */
2969 	if (tTd(9, 1))
2970 		dprintf("getauthinfo: %s\n", hbuf);
2971 
2972 	/* put back the original incoming port */
2973 	switch (RealHostAddr.sa.sa_family)
2974 	{
2975 # if NETINET
2976 	  case AF_INET:
2977 		if (port > 0)
2978 			RealHostAddr.sin.sin_port = port;
2979 		break;
2980 # endif /* NETINET */
2981 
2982 # if NETINET6
2983 	  case AF_INET6:
2984 		if (port > 0)
2985 			RealHostAddr.sin6.sin6_port = port;
2986 		break;
2987 # endif /* NETINET6 */
2988 	}
2989 
2990 	return hbuf;
2991 }
2992 /*
2993 **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
2994 **
2995 **	Parameters:
2996 **		map -- a pointer to this map.
2997 **		name -- the (presumably unqualified) hostname.
2998 **		av -- unused -- for compatibility with other mapping
2999 **			functions.
3000 **		statp -- an exit status (out parameter) -- set to
3001 **			EX_TEMPFAIL if the name server is unavailable.
3002 **
3003 **	Returns:
3004 **		The mapping, if found.
3005 **		NULL if no mapping found.
3006 **
3007 **	Side Effects:
3008 **		Looks up the host specified in hbuf.  If it is not
3009 **		the canonical name for that host, return the canonical
3010 **		name (unless MF_MATCHONLY is set, which will cause the
3011 **		status only to be returned).
3012 */
3013 
3014 char *
3015 host_map_lookup(map, name, av, statp)
3016 	MAP *map;
3017 	char *name;
3018 	char **av;
3019 	int *statp;
3020 {
3021 	register struct hostent *hp;
3022 # if NETINET
3023 	struct in_addr in_addr;
3024 # endif /* NETINET */
3025 # if NETINET6
3026 	struct in6_addr in6_addr;
3027 # endif /* NETINET6 */
3028 	char *cp, *ans = NULL;
3029 	register STAB *s;
3030 	char hbuf[MAXNAME + 1];
3031 
3032 	/*
3033 	**  See if we have already looked up this name.  If so, just
3034 	**  return it.
3035 	*/
3036 
3037 	s = stab(name, ST_NAMECANON, ST_ENTER);
3038 	if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
3039 	{
3040 		if (tTd(9, 1))
3041 			dprintf("host_map_lookup(%s) => CACHE %s\n",
3042 				name,
3043 				s->s_namecanon.nc_cname == NULL
3044 					? "NULL"
3045 					: s->s_namecanon.nc_cname);
3046 		errno = s->s_namecanon.nc_errno;
3047 # if NAMED_BIND
3048 		h_errno = s->s_namecanon.nc_herrno;
3049 # endif /* NAMED_BIND */
3050 		*statp = s->s_namecanon.nc_stat;
3051 		if (*statp == EX_TEMPFAIL)
3052 		{
3053 			CurEnv->e_status = "4.4.3";
3054 			message("851 %s: Name server timeout",
3055 				shortenstring(name, 33));
3056 		}
3057 		if (*statp != EX_OK)
3058 			return NULL;
3059 		if (s->s_namecanon.nc_cname == NULL)
3060 		{
3061 			syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d",
3062 			       name,
3063 			       s->s_namecanon.nc_errno,
3064 			       s->s_namecanon.nc_herrno);
3065 			return NULL;
3066 		}
3067 		if (bitset(MF_MATCHONLY, map->map_mflags))
3068 			cp = map_rewrite(map, name, strlen(name), NULL);
3069 		else
3070 			cp = map_rewrite(map,
3071 					 s->s_namecanon.nc_cname,
3072 					 strlen(s->s_namecanon.nc_cname),
3073 					 av);
3074 		return cp;
3075 	}
3076 
3077 	/*
3078 	**  If we are running without a regular network connection (usually
3079 	**  dial-on-demand) and we are just queueing, we want to avoid DNS
3080 	**  lookups because those could try to connect to a server.
3081 	*/
3082 
3083 	if (CurEnv->e_sendmode == SM_DEFER &&
3084 	    bitset(MF_DEFER, map->map_mflags))
3085 	{
3086 		if (tTd(9, 1))
3087 			dprintf("host_map_lookup(%s) => DEFERRED\n", name);
3088 		*statp = EX_TEMPFAIL;
3089 		return NULL;
3090 	}
3091 
3092 	/*
3093 	**  If first character is a bracket, then it is an address
3094 	**  lookup.  Address is copied into a temporary buffer to
3095 	**  strip the brackets and to preserve name if address is
3096 	**  unknown.
3097 	*/
3098 
3099 	if (tTd(9, 1))
3100 		dprintf("host_map_lookup(%s) => ", name);
3101 	if (*name != '[')
3102 	{
3103 		snprintf(hbuf, sizeof hbuf, "%s", name);
3104 		if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
3105 			ans = hbuf;
3106 	}
3107 	else
3108 	{
3109 		if ((cp = strchr(name, ']')) == NULL)
3110 		{
3111 			if (tTd(9, 1))
3112 				dprintf("FAILED\n");
3113 			return NULL;
3114 		}
3115 		*cp = '\0';
3116 
3117 		hp = NULL;
3118 # if NETINET
3119 		if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE)
3120 			hp = sm_gethostbyaddr((char *)&in_addr,
3121 					      INADDRSZ, AF_INET);
3122 # endif /* NETINET */
3123 # if NETINET6
3124 		if (hp == NULL &&
3125 		    inet_pton(AF_INET6, &name[1], &in6_addr) == 1)
3126 			hp = sm_gethostbyaddr((char *)&in6_addr,
3127 					      IN6ADDRSZ, AF_INET6);
3128 # endif /* NETINET6 */
3129 		*cp = ']';
3130 
3131 		if (hp != NULL)
3132 		{
3133 			/* found a match -- copy out */
3134 			ans = denlstring((char *) hp->h_name, TRUE, TRUE);
3135 # if _FFR_FREEHOSTENT && NETINET6
3136 			freehostent(hp);
3137 			hp = NULL;
3138 # endif /* _FFR_FREEHOSTENT && NETINET6 */
3139 		}
3140 	}
3141 
3142 	s->s_namecanon.nc_flags |= NCF_VALID;	/* will be soon */
3143 
3144 	/* Found an answer */
3145 	if (ans != NULL)
3146 	{
3147 		s->s_namecanon.nc_stat = *statp = EX_OK;
3148 		s->s_namecanon.nc_cname = newstr(ans);
3149 		if (bitset(MF_MATCHONLY, map->map_mflags))
3150 			cp = map_rewrite(map, name, strlen(name), NULL);
3151 		else
3152 			cp = map_rewrite(map, ans, strlen(ans), av);
3153 		if (tTd(9, 1))
3154 			dprintf("FOUND %s\n", ans);
3155 		return cp;
3156 	}
3157 
3158 
3159 	/* No match found */
3160 	s->s_namecanon.nc_errno = errno;
3161 # if NAMED_BIND
3162 	s->s_namecanon.nc_herrno = h_errno;
3163 	if (tTd(9, 1))
3164 		dprintf("FAIL (%d)\n", h_errno);
3165 	switch (h_errno)
3166 	{
3167 	  case TRY_AGAIN:
3168 		if (UseNameServer)
3169 		{
3170 			CurEnv->e_status = "4.4.3";
3171 			message("851 %s: Name server timeout",
3172 				shortenstring(name, 33));
3173 		}
3174 		*statp = EX_TEMPFAIL;
3175 		break;
3176 
3177 	  case HOST_NOT_FOUND:
3178 	  case NO_DATA:
3179 		*statp = EX_NOHOST;
3180 		break;
3181 
3182 	  case NO_RECOVERY:
3183 		*statp = EX_SOFTWARE;
3184 		break;
3185 
3186 	  default:
3187 		*statp = EX_UNAVAILABLE;
3188 		break;
3189 	}
3190 # else /* NAMED_BIND */
3191 	if (tTd(9, 1))
3192 		dprintf("FAIL\n");
3193 	*statp = EX_NOHOST;
3194 # endif /* NAMED_BIND */
3195 	s->s_namecanon.nc_stat = *statp;
3196 	return NULL;
3197 }
3198 #else /* DAEMON */
3199 /* code for systems without sophisticated networking */
3200 
3201 /*
3202 **  MYHOSTNAME -- stub version for case of no daemon code.
3203 **
3204 **	Can't convert to upper case here because might be a UUCP name.
3205 **
3206 **	Mark, you can change this to be anything you want......
3207 */
3208 
3209 char **
3210 myhostname(hostbuf, size)
3211 	char hostbuf[];
3212 	int size;
3213 {
3214 	register FILE *f;
3215 
3216 	hostbuf[0] = '\0';
3217 	f = fopen("/usr/include/whoami", "r");
3218 	if (f != NULL)
3219 	{
3220 		(void) fgets(hostbuf, size, f);
3221 		fixcrlf(hostbuf, TRUE);
3222 		(void) fclose(f);
3223 	}
3224 	return NULL;
3225 }
3226 /*
3227 **  GETAUTHINFO -- get the real host name associated with a file descriptor
3228 **
3229 **	Parameters:
3230 **		fd -- the descriptor
3231 **		may_be_forged -- an outage that is set to TRUE if the
3232 **			forward lookup of RealHostName does not match
3233 **			RealHostAddr; set to FALSE if they do match.
3234 **
3235 **	Returns:
3236 **		The host name associated with this descriptor, if it can
3237 **			be determined.
3238 **		NULL otherwise.
3239 **
3240 **	Side Effects:
3241 **		none
3242 */
3243 
3244 char *
3245 getauthinfo(fd, may_be_forged)
3246 	int fd;
3247 	bool *may_be_forged;
3248 {
3249 	*may_be_forged = FALSE;
3250 	return NULL;
3251 }
3252 /*
3253 **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
3254 **
3255 **	Parameters:
3256 **		map -- a pointer to the database map.
3257 **		name -- a buffer containing a hostname.
3258 **		avp -- a pointer to a (cf file defined) argument vector.
3259 **		statp -- an exit status (out parameter).
3260 **
3261 **	Returns:
3262 **		mapped host name
3263 **		FALSE otherwise.
3264 **
3265 **	Side Effects:
3266 **		Looks up the host specified in name.  If it is not
3267 **		the canonical name for that host, replace it with
3268 **		the canonical name.  If the name is unknown, or it
3269 **		is already the canonical name, leave it unchanged.
3270 */
3271 
3272 /*ARGSUSED*/
3273 char *
3274 host_map_lookup(map, name, avp, statp)
3275 	MAP *map;
3276 	char *name;
3277 	char **avp;
3278 	char *statp;
3279 {
3280 	register struct hostent *hp = NULL;
3281 	char *cp;
3282 
3283 	hp = sm_gethostbyname(name, InetMode);
3284 	if (hp == NULL && InetMode != AF_INET)
3285 		hp = sm_gethostbyname(name, AF_INET);
3286 	if (hp == NULL)
3287 	{
3288 # if NAMED_BIND
3289 		if (tTd(9, 1))
3290 			dprintf("FAIL (%d)\n", h_errno);
3291 		switch (h_errno)
3292 		{
3293 		  case TRY_AGAIN:
3294 			if (UseNameServer)
3295 			{
3296 				CurEnv->e_status = "4.4.3";
3297 				message("851 %s: Name server timeout",
3298 					shortenstring(name, 33));
3299 			}
3300 			*statp = EX_TEMPFAIL;
3301 			break;
3302 
3303 		  case HOST_NOT_FOUND:
3304 		  case NO_DATA:
3305 			*statp = EX_NOHOST;
3306 			break;
3307 
3308 		  case NO_RECOVERY:
3309 			*statp = EX_SOFTWARE;
3310 			break;
3311 
3312 		  default:
3313 			*statp = EX_UNAVAILABLE;
3314 			break;
3315 		}
3316 #else /* NAMED_BIND */
3317 		*statp = EX_NOHOST;
3318 #endif /* NAMED_BIND */
3319 		return NULL;
3320 	}
3321 	if (bitset(MF_MATCHONLY, map->map_mflags))
3322 		cp = map_rewrite(map, name, strlen(name), NULL);
3323 	else
3324 		cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp);
3325 # if _FFR_FREEHOSTENT && NETINET6
3326 	freehostent(hp);
3327 # endif /* _FFR_FREEHOSTENT && NETINET6 */
3328 	return cp;
3329 }
3330 
3331 #endif /* DAEMON */
3332 /*
3333 **  HOST_MAP_INIT -- initialize host class structures
3334 */
3335 
3336 bool
3337 host_map_init(map, args)
3338 	MAP *map;
3339 	char *args;
3340 {
3341 	register char *p = args;
3342 
3343 	for (;;)
3344 	{
3345 		while (isascii(*p) && isspace(*p))
3346 			p++;
3347 		if (*p != '-')
3348 			break;
3349 		switch (*++p)
3350 		{
3351 		  case 'a':
3352 			map->map_app = ++p;
3353 			break;
3354 
3355 		  case 'T':
3356 			map->map_tapp = ++p;
3357 			break;
3358 
3359 		  case 'm':
3360 			map->map_mflags |= MF_MATCHONLY;
3361 			break;
3362 
3363 		  case 't':
3364 			map->map_mflags |= MF_NODEFER;
3365 			break;
3366 
3367 		  case 'S':	/* only for consistency */
3368 			map->map_spacesub = *++p;
3369 			break;
3370 
3371 		  case 'D':
3372 			map->map_mflags |= MF_DEFER;
3373 			break;
3374 		}
3375 		while (*p != '\0' && !(isascii(*p) && isspace(*p)))
3376 			p++;
3377 		if (*p != '\0')
3378 			*p++ = '\0';
3379 	}
3380 	if (map->map_app != NULL)
3381 		map->map_app = newstr(map->map_app);
3382 	if (map->map_tapp != NULL)
3383 		map->map_tapp = newstr(map->map_tapp);
3384 	return TRUE;
3385 }
3386 
3387 #if NETINET6
3388 /*
3389 **  ANYNET_NTOP -- convert an IPv6 network address to printable form.
3390 **
3391 **	Parameters:
3392 **		s6a -- a pointer to an in6_addr structure.
3393 **		dst -- buffer to store result in
3394 **		dst_len -- size of dst buffer
3395 **
3396 **	Returns:
3397 **		A printable version of that structure.
3398 */
3399 char *
3400 anynet_ntop(s6a, dst, dst_len)
3401 	struct in6_addr *s6a;
3402 	char *dst;
3403 	size_t dst_len;
3404 {
3405 	register char *ap;
3406 
3407 	if (IN6_IS_ADDR_V4MAPPED(s6a))
3408 		ap = (char *) inet_ntop(AF_INET,
3409 					&s6a->s6_addr[IN6ADDRSZ - INADDRSZ],
3410 					dst, dst_len);
3411 	else
3412 		ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len);
3413 	return ap;
3414 }
3415 #endif /* NETINET6 */
3416 /*
3417 **  ANYNET_NTOA -- convert a network address to printable form.
3418 **
3419 **	Parameters:
3420 **		sap -- a pointer to a sockaddr structure.
3421 **
3422 **	Returns:
3423 **		A printable version of that sockaddr.
3424 */
3425 
3426 #ifdef USE_SOCK_STREAM
3427 
3428 # if NETLINK
3429 #  include <net/if_dl.h>
3430 # endif /* NETLINK */
3431 
3432 char *
3433 anynet_ntoa(sap)
3434 	register SOCKADDR *sap;
3435 {
3436 	register char *bp;
3437 	register char *ap;
3438 	int l;
3439 	static char buf[100];
3440 
3441 	/* check for null/zero family */
3442 	if (sap == NULL)
3443 		return "NULLADDR";
3444 	if (sap->sa.sa_family == 0)
3445 		return "0";
3446 
3447 	switch (sap->sa.sa_family)
3448 	{
3449 # if NETUNIX
3450 	  case AF_UNIX:
3451 		if (sap->sunix.sun_path[0] != '\0')
3452 			snprintf(buf, sizeof buf, "[UNIX: %.64s]",
3453 				sap->sunix.sun_path);
3454 		else
3455 			snprintf(buf, sizeof buf, "[UNIX: localhost]");
3456 		return buf;
3457 # endif /* NETUNIX */
3458 
3459 # if NETINET
3460 	  case AF_INET:
3461 		return (char *) inet_ntoa(sap->sin.sin_addr);
3462 # endif /* NETINET */
3463 
3464 # if NETINET6
3465 	  case AF_INET6:
3466 		ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf);
3467 		if (ap != NULL)
3468 			return ap;
3469 		break;
3470 # endif /* NETINET6 */
3471 
3472 # if NETLINK
3473 	  case AF_LINK:
3474 		snprintf(buf, sizeof buf, "[LINK: %s]",
3475 			link_ntoa((struct sockaddr_dl *) &sap->sa));
3476 		return buf;
3477 # endif /* NETLINK */
3478 	  default:
3479 		/* this case is needed when nothing is #defined */
3480 		/* in order to keep the switch syntactically correct */
3481 		break;
3482 	}
3483 
3484 	/* unknown family -- just dump bytes */
3485 	(void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family);
3486 	bp = &buf[strlen(buf)];
3487 	ap = sap->sa.sa_data;
3488 	for (l = sizeof sap->sa.sa_data; --l >= 0; )
3489 	{
3490 		(void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377);
3491 		bp += 3;
3492 	}
3493 	*--bp = '\0';
3494 	return buf;
3495 }
3496 /*
3497 **  HOSTNAMEBYANYADDR -- return name of host based on address
3498 **
3499 **	Parameters:
3500 **		sap -- SOCKADDR pointer
3501 **
3502 **	Returns:
3503 **		text representation of host name.
3504 **
3505 **	Side Effects:
3506 **		none.
3507 */
3508 
3509 char *
3510 hostnamebyanyaddr(sap)
3511 	register SOCKADDR *sap;
3512 {
3513 	register struct hostent *hp;
3514 # if NAMED_BIND
3515 	int saveretry;
3516 # endif /* NAMED_BIND */
3517 # if NETINET6
3518 	struct in6_addr in6_addr;
3519 # endif /* NETINET6 */
3520 
3521 # if NAMED_BIND
3522 	/* shorten name server timeout to avoid higher level timeouts */
3523 	saveretry = _res.retry;
3524 	if (_res.retry * _res.retrans > 20)
3525 		_res.retry = 20 / _res.retrans;
3526 # endif /* NAMED_BIND */
3527 
3528 	switch (sap->sa.sa_family)
3529 	{
3530 # if NETINET
3531 	  case AF_INET:
3532 		hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
3533 			INADDRSZ,
3534 			AF_INET);
3535 		break;
3536 # endif /* NETINET */
3537 
3538 # if NETINET6
3539 	  case AF_INET6:
3540 		hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr,
3541 				      IN6ADDRSZ,
3542 				      AF_INET6);
3543 		break;
3544 # endif /* NETINET6 */
3545 
3546 # if NETISO
3547 	  case AF_ISO:
3548 		hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
3549 			sizeof sap->siso.siso_addr,
3550 			AF_ISO);
3551 		break;
3552 # endif /* NETISO */
3553 
3554 # if NETUNIX
3555 	  case AF_UNIX:
3556 		hp = NULL;
3557 		break;
3558 # endif /* NETUNIX */
3559 
3560 	  default:
3561 		hp = sm_gethostbyaddr(sap->sa.sa_data,
3562 			   sizeof sap->sa.sa_data,
3563 			   sap->sa.sa_family);
3564 		break;
3565 	}
3566 
3567 # if NAMED_BIND
3568 	_res.retry = saveretry;
3569 # endif /* NAMED_BIND */
3570 
3571 # if NETINET || NETINET6
3572 	if (hp != NULL && hp->h_name[0] != '['
3573 #  if NETINET6
3574 	    && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1
3575 #  endif /* NETINET6 */
3576 #  if NETINET
3577 	    && inet_addr(hp->h_name) == INADDR_NONE
3578 #  endif /* NETINET */
3579 	    )
3580 	{
3581 		char *name;
3582 
3583 		name = denlstring((char *) hp->h_name, TRUE, TRUE);
3584 
3585 #  if _FFR_FREEHOSTENT && NETINET6
3586 		if (name == hp->h_name)
3587 		{
3588 			static char n[MAXNAME + 1];
3589 
3590 			/* Copy the string, hp->h_name is about to disappear */
3591 			strlcpy(n, name, sizeof n);
3592 			name = n;
3593 		}
3594 
3595 		freehostent(hp);
3596 #  endif /* _FFR_FREEHOSTENT && NETINET6 */
3597 		return name;
3598 	}
3599 # endif /* NETINET || NETINET6 */
3600 
3601 # if _FFR_FREEHOSTENT && NETINET6
3602 	if (hp != NULL)
3603 	{
3604 		freehostent(hp);
3605 		hp = NULL;
3606 	}
3607 # endif /* _FFR_FREEHOSTENT && NETINET6 */
3608 
3609 # if NETUNIX
3610 	if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0')
3611 		return "localhost";
3612 # endif /* NETUNIX */
3613 	{
3614 		static char buf[203];
3615 
3616 		(void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap));
3617 		return buf;
3618 	}
3619 }
3620 #endif /* USE_SOCK_STREAM */
3621