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