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