xref: /original-bsd/usr.sbin/sendmail/src/daemon.c (revision eea91d78)
1939f5b94Sdist /*
20942ea6aSbostic  * Copyright (c) 1983 Eric P. Allman
3da1c6175Sbostic  * Copyright (c) 1988 Regents of the University of California.
4da1c6175Sbostic  * All rights reserved.
5da1c6175Sbostic  *
63bc94712Sbostic  * %sccs.include.redist.c%
7939f5b94Sdist  */
8939f5b94Sdist 
97aa493c5Seric #include <errno.h>
10a8c080f0Seric #include <signal.h>
116c05f684Sbostic #include "sendmail.h"
127fa39d90Seric 
13af5e902cSeric #ifndef lint
14da1c6175Sbostic #ifdef DAEMON
15*eea91d78Seric static char sccsid[] = "@(#)daemon.c	6.43 (Berkeley) 05/03/93 (with daemon mode)";
16d0a9e852Seric #else
17*eea91d78Seric static char sccsid[] = "@(#)daemon.c	6.43 (Berkeley) 05/03/93 (without daemon mode)";
18da1c6175Sbostic #endif
19da1c6175Sbostic #endif /* not lint */
20da1c6175Sbostic 
21da1c6175Sbostic #ifdef DAEMON
22d0a9e852Seric 
231c71e510Seric # include <netdb.h>
241e1663f7Swnj # include <sys/wait.h>
25af5e902cSeric # include <sys/time.h>
26d0a9e852Seric 
273490b9dfSeric #ifdef NAMED_BIND
283490b9dfSeric # include <arpa/nameser.h>
293490b9dfSeric # include <resolv.h>
303490b9dfSeric #endif
313490b9dfSeric 
327fa39d90Seric /*
337fa39d90Seric **  DAEMON.C -- routines to use when running as a daemon.
3447b12ae1Seric **
3547b12ae1Seric **	This entire file is highly dependent on the 4.2 BSD
3647b12ae1Seric **	interprocess communication primitives.  No attempt has
3747b12ae1Seric **	been made to make this file portable to Version 7,
3847b12ae1Seric **	Version 6, MPX files, etc.  If you should try such a
3947b12ae1Seric **	thing yourself, I recommend chucking the entire file
4047b12ae1Seric **	and starting from scratch.  Basic semantics are:
4147b12ae1Seric **
4247b12ae1Seric **	getrequests()
4347b12ae1Seric **		Opens a port and initiates a connection.
4447b12ae1Seric **		Returns in a child.  Must set InChannel and
4547b12ae1Seric **		OutChannel appropriately.
46b7d7afcbSeric **	clrdaemon()
47b7d7afcbSeric **		Close any open files associated with getting
48b7d7afcbSeric **		the connection; this is used when running the queue,
49b7d7afcbSeric **		etc., to avoid having extra file descriptors during
50b7d7afcbSeric **		the queue run and to avoid confusing the network
51b7d7afcbSeric **		code (if it cares).
52914346b1Seric **	makeconnection(host, port, outfile, infile, usesecureport)
5347b12ae1Seric **		Make a connection to the named host on the given
5447b12ae1Seric **		port.  Set *outfile and *infile to the files
5547b12ae1Seric **		appropriate for communication.  Returns zero on
5647b12ae1Seric **		success, else an exit status describing the
5747b12ae1Seric **		error.
5805b57da8Seric **	maphostname(map, hbuf, hbufsiz, avp)
5905b57da8Seric **		Convert the entry in hbuf into a canonical form.
607fa39d90Seric */
61e2f2f828Seric 
62e2f2f828Seric extern char	*anynet_ntoa();
637fa39d90Seric /*
647fa39d90Seric **  GETREQUESTS -- open mail IPC port and get requests.
657fa39d90Seric **
667fa39d90Seric **	Parameters:
677fa39d90Seric **		none.
687fa39d90Seric **
697fa39d90Seric **	Returns:
707fa39d90Seric **		none.
717fa39d90Seric **
727fa39d90Seric **	Side Effects:
737fa39d90Seric **		Waits until some interesting activity occurs.  When
747fa39d90Seric **		it does, a child is created to process it, and the
757fa39d90Seric **		parent waits for completion.  Return from this
76147303b1Seric **		routine is always in the child.  The file pointers
77147303b1Seric **		"InChannel" and "OutChannel" should be set to point
78147303b1Seric **		to the communication channel.
797fa39d90Seric */
807fa39d90Seric 
81b7d7afcbSeric int		DaemonSocket	= -1;		/* fd describing socket */
82bfb80540Seric SOCKADDR	DaemonAddr;			/* socket for incoming */
831c71e510Seric 
847fa39d90Seric getrequests()
857fa39d90Seric {
861c71e510Seric 	int t;
871c71e510Seric 	register struct servent *sp;
887868dfc2Seric 	int on = 1;
8915d084d5Seric 	bool refusingconnections = TRUE;
900aae1086Seric 	FILE *pidf;
919b100374Sbostic 	extern void reapchild();
92eb889047Seric 
93a8268164Seric 	/*
941c71e510Seric 	**  Set up the address for the mailer.
95eb889047Seric 	*/
96eb889047Seric 
97bfb80540Seric 	if (DaemonAddr.sin.sin_family == 0)
98bfb80540Seric 		DaemonAddr.sin.sin_family = AF_INET;
99bfb80540Seric 	if (DaemonAddr.sin.sin_addr.s_addr == 0)
100bfb80540Seric 		DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY;
101bfb80540Seric 	if (DaemonAddr.sin.sin_port == 0)
102bfb80540Seric 	{
1031c71e510Seric 		sp = getservbyname("smtp", "tcp");
1041c71e510Seric 		if (sp == NULL)
105d0a9e852Seric 		{
106ad977999Seric 			syserr("554 service \"smtp\" unknown");
107a1961f2aSeric 			goto severe;
1081c71e510Seric 		}
109bfb80540Seric 		DaemonAddr.sin.sin_port = sp->s_port;
110bfb80540Seric 	}
1111c71e510Seric 
1121c71e510Seric 	/*
1131c71e510Seric 	**  Try to actually open the connection.
1141c71e510Seric 	*/
1151c71e510Seric 
1161c71e510Seric 	if (tTd(15, 1))
117bfb80540Seric 		printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port);
1181c71e510Seric 
1191c71e510Seric 	/* get a socket for the SMTP connection */
12098e28903Seric 	DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0);
121b7d7afcbSeric 	if (DaemonSocket < 0)
1221c71e510Seric 	{
1231c71e510Seric 		/* probably another daemon already */
1241c71e510Seric 		syserr("getrequests: can't create socket");
1251c71e510Seric 	  severe:
126b0ba8827Seric # ifdef LOG
127b0ba8827Seric 		if (LogLevel > 0)
1280c034190Seric 			syslog(LOG_ALERT, "problem creating SMTP socket");
1296c2c3107Seric # endif /* LOG */
13047b12ae1Seric 		finis();
131d0a9e852Seric 	}
1321b6e4a15Seric 
1331b6e4a15Seric 	/* turn on network debugging? */
134a2ef5fa4Seric 	if (tTd(15, 101))
13552308a50Seric 		(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
1361b6e4a15Seric 
1377868dfc2Seric 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
1387868dfc2Seric 	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
1397868dfc2Seric 
14098e28903Seric 	switch (DaemonAddr.sa.sa_family)
14198e28903Seric 	{
14298e28903Seric # ifdef NETINET
14398e28903Seric 	  case AF_INET:
14498e28903Seric 		t = sizeof DaemonAddr.sin;
14598e28903Seric 		break;
14698e28903Seric # endif
14798e28903Seric 
14898e28903Seric # ifdef NETISO
14998e28903Seric 	  case AF_ISO:
15098e28903Seric 		t = sizeof DaemonAddr.siso;
15198e28903Seric 		break;
15298e28903Seric # endif
15398e28903Seric 
15498e28903Seric 	  default:
15598e28903Seric 		t = sizeof DaemonAddr;
15698e28903Seric 		break;
15798e28903Seric 	}
15898e28903Seric 
15998e28903Seric 	if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0)
1601c71e510Seric 	{
1611c71e510Seric 		syserr("getrequests: cannot bind");
162b7d7afcbSeric 		(void) close(DaemonSocket);
1631c71e510Seric 		goto severe;
1641c71e510Seric 	}
1651c71e510Seric 
1661cd247eeSeric 	(void) signal(SIGCHLD, reapchild);
16752308a50Seric 
1680aae1086Seric 	/* write the pid to the log file for posterity */
1690aae1086Seric 	pidf = fopen(PidFile, "w");
1700aae1086Seric 	if (pidf != NULL)
1710aae1086Seric 	{
1720aae1086Seric 		fprintf(pidf, "%d\n", getpid());
1730aae1086Seric 		fclose(pidf);
1740aae1086Seric 	}
1750aae1086Seric 
1760aae1086Seric 
1771c71e510Seric 	if (tTd(15, 1))
178b7d7afcbSeric 		printf("getrequests: %d\n", DaemonSocket);
1791c71e510Seric 
1801c71e510Seric 	for (;;)
1811c71e510Seric 	{
1823a099713Seric 		register int pid;
183a44d5a5eSeric 		auto int lotherend;
18415d084d5Seric 		extern bool refuseconnections();
1853a099713Seric 
1863a099713Seric 		/* see if we are rejecting connections */
18715d084d5Seric 		CurrentLA = getla();
18815d084d5Seric 		if (refuseconnections())
1896775ec03Sbostic 		{
19015d084d5Seric 			if (!refusingconnections)
19115d084d5Seric 			{
19215d084d5Seric 				/* don't queue so peer will fail quickly */
19315d084d5Seric 				(void) listen(DaemonSocket, 0);
19415d084d5Seric 				refusingconnections = TRUE;
19515d084d5Seric 			}
19671e5e267Seric 			setproctitle("rejecting connections: load average: %d",
19771e5e267Seric 				CurrentLA);
1983a099713Seric 			sleep(5);
19915d084d5Seric 			continue;
20015d084d5Seric 		}
20115d084d5Seric 
20215d084d5Seric 		if (refusingconnections)
20315d084d5Seric 		{
20415d084d5Seric 			/* start listening again */
20515d084d5Seric 			if (listen(DaemonSocket, 10) < 0)
20615d084d5Seric 			{
20715d084d5Seric 				syserr("getrequests: cannot listen");
20815d084d5Seric 				(void) close(DaemonSocket);
20915d084d5Seric 				goto severe;
21015d084d5Seric 			}
21115d084d5Seric 			setproctitle("accepting connections");
21215d084d5Seric 			refusingconnections = FALSE;
2136775ec03Sbostic 		}
214a44d5a5eSeric 
2151c71e510Seric 		/* wait for a connection */
2161c71e510Seric 		do
2171c71e510Seric 		{
2181c71e510Seric 			errno = 0;
2199f9a15b6Skarels 			lotherend = sizeof RealHostAddr;
2209b100374Sbostic 			t = accept(DaemonSocket,
2219b100374Sbostic 			    (struct sockaddr *)&RealHostAddr, &lotherend);
2221c71e510Seric 		} while (t < 0 && errno == EINTR);
2231c71e510Seric 		if (t < 0)
2241c71e510Seric 		{
2251c71e510Seric 			syserr("getrequests: accept");
2261c71e510Seric 			sleep(5);
2271c71e510Seric 			continue;
2281c71e510Seric 		}
229d0a9e852Seric 
230d0a9e852Seric 		/*
231d0a9e852Seric 		**  Create a subprocess to process the mail.
232d0a9e852Seric 		*/
233d0a9e852Seric 
23461e4310fSeric 		if (tTd(15, 2))
2351c71e510Seric 			printf("getrequests: forking (fd = %d)\n", t);
236eb889047Seric 
237a8268164Seric 		pid = fork();
238a8268164Seric 		if (pid < 0)
239a8268164Seric 		{
240a8268164Seric 			syserr("daemon: cannot fork");
241a8268164Seric 			sleep(10);
2421c71e510Seric 			(void) close(t);
243a8268164Seric 			continue;
244a8268164Seric 		}
245a8268164Seric 
246a8268164Seric 		if (pid == 0)
247a8268164Seric 		{
2489f8b0eadSeric 			extern char *hostnamebyanyaddr();
249a44d5a5eSeric 
250a8268164Seric 			/*
251a8268164Seric 			**  CHILD -- return to caller.
252a44d5a5eSeric 			**	Collect verified idea of sending host.
253a8268164Seric 			**	Verify calling user id if possible here.
254a8268164Seric 			*/
255a8268164Seric 
2561cd247eeSeric 			(void) signal(SIGCHLD, SIG_DFL);
257e17a3a5aSeric 			OpMode = MD_SMTP;
258779ac194Seric 
259a44d5a5eSeric 			/* determine host name */
2609f8b0eadSeric 			RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
26129dcf4baSeric 
2622a6bc25bSeric #ifdef LOG
263845e533cSeric 			if (LogLevel > 10)
2642a6bc25bSeric 			{
2652a6bc25bSeric 				/* log connection information */
2662a6bc25bSeric 				syslog(LOG_INFO, "connect from %s (%s)",
2679f8b0eadSeric 					RealHostName, anynet_ntoa(&RealHostAddr));
2682a6bc25bSeric 			}
2692a6bc25bSeric #endif
2702a6bc25bSeric 
271244b09d1Seric 			(void) close(DaemonSocket);
272244b09d1Seric 			InChannel = fdopen(t, "r");
273244b09d1Seric 			OutChannel = fdopen(dup(t), "w");
274244b09d1Seric 
27529dcf4baSeric 			/* should we check for illegal connection here? XXX */
276e17a3a5aSeric #ifdef XLA
277e17a3a5aSeric 			if (!xla_host_ok(RealHostName))
278e17a3a5aSeric 			{
279244b09d1Seric 				message("421 Too many SMTP sessions for this host");
280e17a3a5aSeric 				exit(0);
281e17a3a5aSeric 			}
282e17a3a5aSeric #endif
283a44d5a5eSeric 
28461e4310fSeric 			if (tTd(15, 2))
285d0a9e852Seric 				printf("getreq: returning\n");
286a8268164Seric 			return;
287a8268164Seric 		}
288a8268164Seric 
2893c154354Seric 		/* close the port so that others will hang (for a while) */
2903c154354Seric 		(void) close(t);
2918e3e4b17Seric 	}
2923c154354Seric 	/*NOTREACHED*/
2933c154354Seric }
2948e3e4b17Seric /*
295b7d7afcbSeric **  CLRDAEMON -- reset the daemon connection
296b7d7afcbSeric **
297b7d7afcbSeric **	Parameters:
298b7d7afcbSeric **		none.
299b7d7afcbSeric **
300b7d7afcbSeric **	Returns:
301b7d7afcbSeric **		none.
302b7d7afcbSeric **
303b7d7afcbSeric **	Side Effects:
304b7d7afcbSeric **		releases any resources used by the passive daemon.
305b7d7afcbSeric */
306b7d7afcbSeric 
307b7d7afcbSeric clrdaemon()
308b7d7afcbSeric {
309b7d7afcbSeric 	if (DaemonSocket >= 0)
310b7d7afcbSeric 		(void) close(DaemonSocket);
311b7d7afcbSeric 	DaemonSocket = -1;
312b7d7afcbSeric }
313b7d7afcbSeric /*
314bfb80540Seric **  SETDAEMONOPTIONS -- set options for running the daemon
315bfb80540Seric **
316bfb80540Seric **	Parameters:
317bfb80540Seric **		p -- the options line.
318bfb80540Seric **
319bfb80540Seric **	Returns:
320bfb80540Seric **		none.
321bfb80540Seric */
322bfb80540Seric 
323bfb80540Seric setdaemonoptions(p)
324bfb80540Seric 	register char *p;
325bfb80540Seric {
326850144caSeric 	if (DaemonAddr.sa.sa_family == AF_UNSPEC)
327850144caSeric 		DaemonAddr.sa.sa_family = AF_INET;
328850144caSeric 
329bfb80540Seric 	while (p != NULL)
330bfb80540Seric 	{
331bfb80540Seric 		register char *f;
332bfb80540Seric 		register char *v;
333bfb80540Seric 
334bfb80540Seric 		while (isascii(*p) && isspace(*p))
335bfb80540Seric 			p++;
336bfb80540Seric 		if (*p == '\0')
337bfb80540Seric 			break;
338bfb80540Seric 		f = p;
339bfb80540Seric 		p = strchr(p, ',');
340bfb80540Seric 		if (p != NULL)
341bfb80540Seric 			*p++ = '\0';
342bfb80540Seric 		v = strchr(f, '=');
343bfb80540Seric 		if (v == NULL)
344bfb80540Seric 			continue;
345bfb80540Seric 		while (isascii(*++v) && isspace(*v))
346bfb80540Seric 			continue;
347bfb80540Seric 
348bfb80540Seric 		switch (*f)
349bfb80540Seric 		{
350850144caSeric 		  case 'F':		/* address family */
351850144caSeric 			if (isascii(*v) && isdigit(*v))
352850144caSeric 				DaemonAddr.sa.sa_family = atoi(v);
353850144caSeric #ifdef NETINET
354850144caSeric 			else if (strcasecmp(v, "inet") == 0)
355850144caSeric 				DaemonAddr.sa.sa_family = AF_INET;
356850144caSeric #endif
357850144caSeric #ifdef NETISO
358850144caSeric 			else if (strcasecmp(v, "iso") == 0)
359850144caSeric 				DaemonAddr.sa.sa_family = AF_ISO;
360850144caSeric #endif
361850144caSeric #ifdef NETNS
362850144caSeric 			else if (strcasecmp(v, "ns") == 0)
363850144caSeric 				DaemonAddr.sa.sa_family = AF_NS;
364850144caSeric #endif
365850144caSeric #ifdef NETX25
366850144caSeric 			else if (strcasecmp(v, "x.25") == 0)
367850144caSeric 				DaemonAddr.sa.sa_family = AF_CCITT;
368850144caSeric #endif
369850144caSeric 			else
370850144caSeric 				syserr("554 Unknown address family %s in Family=option", v);
371850144caSeric 			break;
372850144caSeric 
373850144caSeric 		  case 'A':		/* address */
374850144caSeric 			switch (DaemonAddr.sa.sa_family)
375850144caSeric 			{
376850144caSeric #ifdef NETINET
377850144caSeric 			  case AF_INET:
378850144caSeric 				if (isascii(*v) && isdigit(*v))
379850144caSeric 					DaemonAddr.sin.sin_addr.s_addr = inet_network(v);
380850144caSeric 				else
381850144caSeric 				{
382850144caSeric 					register struct netent *np;
383850144caSeric 
384850144caSeric 					np = getnetbyname(v);
385850144caSeric 					if (np == NULL)
386850144caSeric 						syserr("554 network \"%s\" unknown", v);
387850144caSeric 					else
388850144caSeric 						DaemonAddr.sin.sin_addr.s_addr = np->n_net;
389850144caSeric 				}
390850144caSeric 				break;
391850144caSeric #endif
392850144caSeric 
393850144caSeric 			  default:
394850144caSeric 				syserr("554 Address= option unsupported for family %d",
395850144caSeric 					DaemonAddr.sa.sa_family);
396850144caSeric 				break;
397850144caSeric 			}
398850144caSeric 			break;
399850144caSeric 
400bfb80540Seric 		  case 'P':		/* port */
401850144caSeric 			switch (DaemonAddr.sa.sa_family)
402850144caSeric 			{
403850144caSeric 				short port;
404850144caSeric 
405850144caSeric #ifdef NETINET
406850144caSeric 			  case AF_INET:
407bfb80540Seric 				if (isascii(*v) && isdigit(*v))
408bfb80540Seric 					DaemonAddr.sin.sin_port = atoi(v);
409bfb80540Seric 				else
410bfb80540Seric 				{
411bfb80540Seric 					register struct servent *sp;
412bfb80540Seric 
413bfb80540Seric 					sp = getservbyname(v, "tcp");
414bfb80540Seric 					if (sp == NULL)
415ad977999Seric 						syserr("554 service \"%s\" unknown", v);
416bfb80540Seric 					else
417bfb80540Seric 						DaemonAddr.sin.sin_port = sp->s_port;
418bfb80540Seric 				}
419bfb80540Seric 				break;
420850144caSeric #endif
421bfb80540Seric 
422850144caSeric #ifdef NETISO
423850144caSeric 			  case AF_ISO:
424850144caSeric 				/* assume two byte transport selector */
425bfb80540Seric 				if (isascii(*v) && isdigit(*v))
426850144caSeric 					port = atoi(v);
427bfb80540Seric 				else
428bfb80540Seric 				{
429850144caSeric 					register struct servent *sp;
430bfb80540Seric 
431850144caSeric 					sp = getservbyname(v, "tcp");
432850144caSeric 					if (sp == NULL)
433ad977999Seric 						syserr("554 service \"%s\" unknown", v);
434bfb80540Seric 					else
435850144caSeric 						port = sp->s_port;
436850144caSeric 				}
437850144caSeric 				bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2);
438850144caSeric 				break;
439850144caSeric #endif
440850144caSeric 
441850144caSeric 			  default:
442850144caSeric 				syserr("554 Port= option unsupported for family %d",
443850144caSeric 					DaemonAddr.sa.sa_family);
444850144caSeric 				break;
445bfb80540Seric 			}
446bfb80540Seric 			break;
447bfb80540Seric 		}
448bfb80540Seric 	}
449bfb80540Seric }
450bfb80540Seric /*
4517aa493c5Seric **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
4527aa493c5Seric **
4537aa493c5Seric **	Parameters:
4547aa493c5Seric **		host -- the name of the host.
45548ff0a9dSeric **		port -- the port number to connect to.
456655feedbSeric **		mci -- a pointer to the mail connection information
457655feedbSeric **			structure to be filled in.
458914346b1Seric **		usesecureport -- if set, use a low numbered (reserved)
459914346b1Seric **			port to provide some rudimentary authentication.
4607aa493c5Seric **
4617aa493c5Seric **	Returns:
4627aa493c5Seric **		An exit code telling whether the connection could be
4637aa493c5Seric **			made and if not why not.
4647aa493c5Seric **
4657aa493c5Seric **	Side Effects:
4667aa493c5Seric **		none.
4677aa493c5Seric */
4687aa493c5Seric 
469e2f2f828Seric SOCKADDR	CurHostAddr;		/* address of current host */
47071ff6caaSeric 
471b31e7f2bSeric int
472655feedbSeric makeconnection(host, port, mci, usesecureport)
4737aa493c5Seric 	char *host;
474210215eaSeric 	u_short port;
475b31e7f2bSeric 	register MCI *mci;
476914346b1Seric 	bool usesecureport;
4777aa493c5Seric {
47804344589Sbloom 	register int i, s;
47904344589Sbloom 	register struct hostent *hp = (struct hostent *)NULL;
480e2f2f828Seric 	SOCKADDR addr;
4816286bb75Sbloom 	int sav_errno;
482e2f2f828Seric 	int addrlen;
483134746fbSeric #ifdef NAMED_BIND
484134746fbSeric 	extern int h_errno;
485134746fbSeric #endif
4867aa493c5Seric 
4877aa493c5Seric 	/*
4887aa493c5Seric 	**  Set up the address for the mailer.
48971096d12Seric 	**	Accept "[a.b.c.d]" syntax for host name.
4907aa493c5Seric 	*/
4917aa493c5Seric 
492134746fbSeric #ifdef NAMED_BIND
493794bdbb9Smiriam 	h_errno = 0;
494134746fbSeric #endif
495794bdbb9Smiriam 	errno = 0;
496967778e2Seric 	bzero(&CurHostAddr, sizeof CurHostAddr);
497d945ebe8Seric 	CurHostName = host;
498794bdbb9Smiriam 
49971096d12Seric 	if (host[0] == '[')
50071096d12Seric 	{
501a44d5a5eSeric 		long hid;
5026c2c3107Seric 		register char *p = strchr(host, ']');
50371096d12Seric 
504a44d5a5eSeric 		if (p != NULL)
50571096d12Seric 		{
506a44d5a5eSeric 			*p = '\0';
507a44d5a5eSeric 			hid = inet_addr(&host[1]);
508a7e21fe6Seric 			if (hid == -1)
509a7e21fe6Seric 			{
510a7e21fe6Seric 				/* try it as a host name (avoid MX lookup) */
511a7e21fe6Seric 				hp = gethostbyname(&host[1]);
512a7e21fe6Seric 				*p = ']';
513a7e21fe6Seric 				goto gothostent;
514a7e21fe6Seric 			}
515a44d5a5eSeric 			*p = ']';
51671096d12Seric 		}
517a7e21fe6Seric 		if (p == NULL)
51871096d12Seric 		{
51908b25121Seric 			usrerr("553 Invalid numeric domain spec \"%s\"", host);
52071096d12Seric 			return (EX_NOHOST);
52171096d12Seric 		}
52283c1f4bcSeric 		addr.sin.sin_family = AF_INET;
52383c1f4bcSeric 		addr.sin.sin_addr.s_addr = hid;
52471096d12Seric 	}
5251c71e510Seric 	else
5261c71e510Seric 	{
52704344589Sbloom 		hp = gethostbyname(host);
528a7e21fe6Seric gothostent:
529794bdbb9Smiriam 		if (hp == NULL)
530794bdbb9Smiriam 		{
531134746fbSeric #ifdef NAMED_BIND
532794bdbb9Smiriam 			if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
53352308a50Seric 				return (EX_TEMPFAIL);
53482e5d8ddSeric 
535134746fbSeric 			/* if name server is specified, assume temp fail */
536134746fbSeric 			if (errno == ECONNREFUSED && UseNameServer)
537134746fbSeric 				return (EX_TEMPFAIL);
538134746fbSeric #endif
5397aa493c5Seric 			return (EX_NOHOST);
540794bdbb9Smiriam 		}
54183c1f4bcSeric 		addr.sa.sa_family = hp->h_addrtype;
54283c1f4bcSeric 		switch (hp->h_addrtype)
54383c1f4bcSeric 		{
54483c1f4bcSeric #ifdef NETINET
54583c1f4bcSeric 		  case AF_INET:
546e2f2f828Seric 			bcopy(hp->h_addr,
54783c1f4bcSeric 				&addr.sin.sin_addr,
548e2f2f828Seric 				hp->h_length);
54983c1f4bcSeric 			break;
55083c1f4bcSeric #endif
55183c1f4bcSeric 
55283c1f4bcSeric 		  default:
553e2f2f828Seric 			bcopy(hp->h_addr,
55483c1f4bcSeric 				addr.sa.sa_data,
555e2f2f828Seric 				hp->h_length);
55683c1f4bcSeric 			break;
55783c1f4bcSeric 		}
55804344589Sbloom 		i = 1;
5591c71e510Seric 	}
5601c71e510Seric 
5611c71e510Seric 	/*
5621c71e510Seric 	**  Determine the port number.
5631c71e510Seric 	*/
5641c71e510Seric 
565fd7c0790Seric 	if (port != 0)
566e2f2f828Seric 		port = htons(port);
567fd7c0790Seric 	else
5681c71e510Seric 	{
5691c71e510Seric 		register struct servent *sp = getservbyname("smtp", "tcp");
5701c71e510Seric 
5711c71e510Seric 		if (sp == NULL)
5721c71e510Seric 		{
573ad977999Seric 			syserr("554 makeconnection: service \"smtp\" unknown");
574845e533cSeric 			return (EX_OSERR);
5751c71e510Seric 		}
576e2f2f828Seric 		port = sp->s_port;
577e2f2f828Seric 	}
578e2f2f828Seric 
57983c1f4bcSeric 	switch (addr.sa.sa_family)
580e2f2f828Seric 	{
581e2f2f828Seric 	  case AF_INET:
58283c1f4bcSeric 		addr.sin.sin_port = port;
583e2f2f828Seric 		addrlen = sizeof (struct sockaddr_in);
584e2f2f828Seric 		break;
585e2f2f828Seric 
586e2f2f828Seric #ifdef NETISO
587e2f2f828Seric 	  case AF_ISO:
588e2f2f828Seric 		/* assume two byte transport selector */
589e2f2f828Seric 		bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2);
590e2f2f828Seric 		addrlen = sizeof (struct sockaddr_iso);
591e2f2f828Seric 		break;
592e2f2f828Seric #endif
593e2f2f828Seric 
594e2f2f828Seric 	  default:
59583c1f4bcSeric 		syserr("Can't connect to address family %d", addr.sa.sa_family);
596e2f2f828Seric 		return (EX_NOHOST);
5971c71e510Seric 	}
5987aa493c5Seric 
5997aa493c5Seric 	/*
6007aa493c5Seric 	**  Try to actually open the connection.
6017aa493c5Seric 	*/
6027aa493c5Seric 
603e17a3a5aSeric #ifdef XLA
604e17a3a5aSeric 	/* if too many connections, don't bother trying */
605e17a3a5aSeric 	if (!xla_noqueue_ok(host))
606e17a3a5aSeric 		return EX_TEMPFAIL;
607e17a3a5aSeric #endif
608e17a3a5aSeric 
609aea02ca1Seric 	for (;;)
610aea02ca1Seric 	{
61161e4310fSeric 		if (tTd(16, 1))
612e2f2f828Seric 			printf("makeconnection (%s [%s])\n",
613e2f2f828Seric 				host, anynet_ntoa(&addr));
6147aa493c5Seric 
615226e3022Seric 		/* save for logging */
616226e3022Seric 		CurHostAddr = addr;
617226e3022Seric 
618914346b1Seric 		if (usesecureport)
619914346b1Seric 		{
620914346b1Seric 			int rport = IPPORT_RESERVED - 1;
621914346b1Seric 
622914346b1Seric 			s = rresvport(&rport);
623914346b1Seric 		}
624914346b1Seric 		else
625914346b1Seric 		{
626af5e902cSeric 			s = socket(AF_INET, SOCK_STREAM, 0);
627914346b1Seric 		}
6287aa493c5Seric 		if (s < 0)
6297aa493c5Seric 		{
6306286bb75Sbloom 			sav_errno = errno;
631914346b1Seric 			syserr("makeconnection: no socket");
6327aa493c5Seric 			goto failure;
6337aa493c5Seric 		}
6347aa493c5Seric 
63561e4310fSeric 		if (tTd(16, 1))
636b31e7f2bSeric 			printf("makeconnection: fd=%d\n", s);
6371b6e4a15Seric 
6381b6e4a15Seric 		/* turn on network debugging? */
639a2ef5fa4Seric 		if (tTd(16, 101))
64052308a50Seric 		{
64152308a50Seric 			int on = 1;
642aea02ca1Seric 			(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG,
643aea02ca1Seric 					  (char *)&on, sizeof on);
64452308a50Seric 		}
64587d6e633Srick 		if (CurEnv->e_xfp != NULL)
646877a6142Seric 			(void) fflush(CurEnv->e_xfp);		/* for debugging */
6474bd6a662Seric 		errno = 0;					/* for debugging */
648e2f2f828Seric 		if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
649aea02ca1Seric 			break;
650aea02ca1Seric 
651aea02ca1Seric 		/* couldn't connect.... figure out why */
6526286bb75Sbloom 		sav_errno = errno;
6536286bb75Sbloom 		(void) close(s);
65404344589Sbloom 		if (hp && hp->h_addr_list[i])
65504344589Sbloom 		{
656e2f2f828Seric 			extern char *errstring();
657e2f2f828Seric 
658aea02ca1Seric 			if (tTd(16, 1))
659e2f2f828Seric 				printf("Connect failed (%s); trying new address....\n",
660e2f2f828Seric 					errstring(sav_errno));
66183c1f4bcSeric 			switch (addr.sa.sa_family)
66283c1f4bcSeric 			{
66383c1f4bcSeric #ifdef NETINET
66483c1f4bcSeric 			  case AF_INET:
665e2f2f828Seric 				bcopy(hp->h_addr_list[i++],
66683c1f4bcSeric 				      &addr.sin.sin_addr,
667e2f2f828Seric 				      hp->h_length);
66883c1f4bcSeric 				break;
66983c1f4bcSeric #endif
67083c1f4bcSeric 
67183c1f4bcSeric 			  default:
672e2f2f828Seric 				bcopy(hp->h_addr_list[i++],
67383c1f4bcSeric 					addr.sa.sa_data,
674914346b1Seric 					hp->h_length);
67583c1f4bcSeric 				break;
67683c1f4bcSeric 			}
677aea02ca1Seric 			continue;
67804344589Sbloom 		}
67904344589Sbloom 
6807aa493c5Seric 		/* failure, decide if temporary or not */
6817aa493c5Seric 	failure:
682244b09d1Seric #ifdef XLA
683244b09d1Seric 		xla_host_end(host);
684244b09d1Seric #endif
685e2de2524Seric 		if (transienterror(sav_errno))
686e2de2524Seric 			return EX_TEMPFAIL;
687e2de2524Seric 		else
68887d6e633Srick 		{
68987d6e633Srick 			extern char *errstring();
69087d6e633Srick 
69108b25121Seric 			message("%s", errstring(sav_errno));
6927aa493c5Seric 			return (EX_UNAVAILABLE);
6937aa493c5Seric 		}
6947aa493c5Seric 	}
6957aa493c5Seric 
6967aa493c5Seric 	/* connection ok, put it into canonical form */
697655feedbSeric 	mci->mci_out = fdopen(s, "w");
698655feedbSeric 	mci->mci_in = fdopen(dup(s), "r");
6997aa493c5Seric 
700dca8e1f7Seric 	return (EX_OK);
7017aa493c5Seric }
702444eaf03Seric /*
703444eaf03Seric **  MYHOSTNAME -- return the name of this host.
704444eaf03Seric **
705444eaf03Seric **	Parameters:
706444eaf03Seric **		hostbuf -- a place to return the name of this host.
707897f1869Seric **		size -- the size of hostbuf.
708444eaf03Seric **
709444eaf03Seric **	Returns:
710444eaf03Seric **		A list of aliases for this host.
711444eaf03Seric **
712444eaf03Seric **	Side Effects:
71338ad259dSeric **		Sets the MyIpAddrs buffer to a list of my IP addresses.
714444eaf03Seric */
715444eaf03Seric 
71638ad259dSeric struct in_addr	MyIpAddrs[MAXIPADDR + 1];
71738ad259dSeric 
718444eaf03Seric char **
719897f1869Seric myhostname(hostbuf, size)
720444eaf03Seric 	char hostbuf[];
721897f1869Seric 	int size;
722444eaf03Seric {
72338ad259dSeric 	register struct hostent *hp;
724444eaf03Seric 	extern struct hostent *gethostbyname();
725444eaf03Seric 
726af5e902cSeric 	if (gethostname(hostbuf, size) < 0)
727af5e902cSeric 	{
728af5e902cSeric 		(void) strcpy(hostbuf, "localhost");
729af5e902cSeric 	}
730a44d5a5eSeric 	hp = gethostbyname(hostbuf);
731a44d5a5eSeric 	if (hp != NULL)
7327364df9fSeric 	{
73338ad259dSeric 		(void) strncpy(hostbuf, hp->h_name, size - 1);
73438ad259dSeric 		hostbuf[size - 1] = '\0';
73538ad259dSeric 
73638ad259dSeric 		if (hp->h_addrtype == AF_INET && hp->h_length == 4)
73738ad259dSeric 		{
73838ad259dSeric 			register int i;
73938ad259dSeric 
74038ad259dSeric 			for (i = 0; i < MAXIPADDR; i++)
74138ad259dSeric 			{
74238ad259dSeric 				if (hp->h_addr_list[i] == NULL)
74338ad259dSeric 					break;
74438ad259dSeric 				MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i];
74538ad259dSeric 			}
74638ad259dSeric 			MyIpAddrs[i].s_addr = 0;
74738ad259dSeric 		}
74838ad259dSeric 
749a44d5a5eSeric 		return (hp->h_aliases);
7507364df9fSeric 	}
751444eaf03Seric 	else
752444eaf03Seric 		return (NULL);
753444eaf03Seric }
754cb452edcSeric /*
7559f8b0eadSeric **  GETAUTHINFO -- get the real host name asociated with a file descriptor
7569f8b0eadSeric **
7579f8b0eadSeric **	Uses RFC1413 protocol to try to get info from the other end.
758320e0d1cSeric **
759320e0d1cSeric **	Parameters:
760320e0d1cSeric **		fd -- the descriptor
761320e0d1cSeric **
762320e0d1cSeric **	Returns:
7639f8b0eadSeric **		The user@host information associated with this descriptor.
764320e0d1cSeric **
765320e0d1cSeric **	Side Effects:
7669f8b0eadSeric **		Sets RealHostName to the name of the host at the other end.
767320e0d1cSeric */
768320e0d1cSeric 
7699f8b0eadSeric #ifdef IDENTPROTO
7709f8b0eadSeric 
7719f8b0eadSeric static jmp_buf	CtxAuthTimeout;
7729f8b0eadSeric 
7739f8b0eadSeric static
7749f8b0eadSeric authtimeout()
7759f8b0eadSeric {
7769f8b0eadSeric 	longjmp(CtxAuthTimeout, 1);
7779f8b0eadSeric }
7789f8b0eadSeric 
7799f8b0eadSeric #endif
7809f8b0eadSeric 
781320e0d1cSeric char *
7829f8b0eadSeric getauthinfo(fd)
783320e0d1cSeric 	int fd;
784320e0d1cSeric {
7859f8b0eadSeric 	SOCKADDR fa;
7869f8b0eadSeric 	int falen;
787a5546e24Seric 	register char *p;
7889f8b0eadSeric #ifdef IDENTPROTO
7899f8b0eadSeric 	SOCKADDR la;
7909f8b0eadSeric 	int lalen;
7919f8b0eadSeric 	register struct servent *sp;
7929f8b0eadSeric 	int s;
7939f8b0eadSeric 	int i;
7949f8b0eadSeric 	EVENT *ev;
7959f8b0eadSeric #endif
7969f8b0eadSeric 	static char hbuf[MAXNAME * 2 + 2];
7979f8b0eadSeric 	extern char *hostnamebyanyaddr();
7989f8b0eadSeric 	extern char RealUserName[];			/* main.c */
799320e0d1cSeric 
8009f8b0eadSeric 	falen = sizeof fa;
8019f8b0eadSeric 	if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0)
8029f8b0eadSeric 	{
8039f8b0eadSeric 		RealHostName = "localhost";
8049f8b0eadSeric 		(void) sprintf(hbuf, "%s@localhost", RealUserName);
80553853673Seric 		if (tTd(9, 1))
8069f8b0eadSeric 			printf("getauthinfo: %s\n", hbuf);
807320e0d1cSeric 		return hbuf;
808320e0d1cSeric 	}
8099f8b0eadSeric 
8109f8b0eadSeric 	RealHostName = newstr(hostnamebyanyaddr(&fa));
8119f8b0eadSeric 	RealHostAddr = fa;
8129f8b0eadSeric 
8139f8b0eadSeric #ifdef IDENTPROTO
8149f8b0eadSeric 	lalen = sizeof la;
8159f8b0eadSeric 	if (fa.sa.sa_family != AF_INET ||
8169f8b0eadSeric 	    getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 ||
8179f8b0eadSeric 	    la.sa.sa_family != AF_INET)
8189f8b0eadSeric 	{
8199f8b0eadSeric 		/* no ident info */
8209f8b0eadSeric 		goto noident;
8219f8b0eadSeric 	}
8229f8b0eadSeric 
8239f8b0eadSeric 	/* create ident query */
8249f8b0eadSeric 	(void) sprintf(hbuf, "%d,%d\r\n", fa.sin.sin_port, la.sin.sin_port);
8259f8b0eadSeric 
8269f8b0eadSeric 	/* create local address */
8279f8b0eadSeric 	bzero(&la, sizeof la);
8289f8b0eadSeric 
8299f8b0eadSeric 	/* create foreign address */
8309f8b0eadSeric 	sp = getservbyname("auth", "tcp");
8319f8b0eadSeric 	if (sp != NULL)
8329f8b0eadSeric 		fa.sin.sin_port = sp->s_port;
8339f8b0eadSeric 	else
8341038598cSeric 		fa.sin.sin_port = htons(113);
8359f8b0eadSeric 
8369f8b0eadSeric 	s = -1;
8379f8b0eadSeric 	if (setjmp(CtxAuthTimeout) != 0)
8389f8b0eadSeric 	{
8399f8b0eadSeric 		if (s >= 0)
8409f8b0eadSeric 			(void) close(s);
8419f8b0eadSeric 		goto noident;
8429f8b0eadSeric 	}
8439f8b0eadSeric 
8449f8b0eadSeric 	/* put a timeout around the whole thing */
8459f8b0eadSeric 	ev = setevent((time_t) 30, authtimeout, 0);
8469f8b0eadSeric 
8479f8b0eadSeric 	/* connect to foreign IDENT server */
8489f8b0eadSeric 	s = socket(AF_INET, SOCK_STREAM, 0);
8499f8b0eadSeric 	if (s < 0)
8509f8b0eadSeric 	{
8519f8b0eadSeric 		clrevent(ev);
8529f8b0eadSeric 		goto noident;
8539f8b0eadSeric 	}
8549f8b0eadSeric 	if (connect(s, &fa.sa, sizeof fa.sin) < 0)
8559f8b0eadSeric 	{
8569f8b0eadSeric closeident:
8579f8b0eadSeric 		(void) close(s);
8589f8b0eadSeric 		clrevent(ev);
8599f8b0eadSeric 		goto noident;
8609f8b0eadSeric 	}
8619f8b0eadSeric 
86253853673Seric 	if (tTd(9, 10))
8639f8b0eadSeric 		printf("getauthinfo: sent %s", hbuf);
8649f8b0eadSeric 
8659f8b0eadSeric 	/* send query */
8669f8b0eadSeric 	if (write(s, hbuf, strlen(hbuf)) < 0)
8679f8b0eadSeric 		goto closeident;
8689f8b0eadSeric 
8699f8b0eadSeric 	/* get result */
8709f8b0eadSeric 	i = read(s, hbuf, sizeof hbuf);
8719f8b0eadSeric 	(void) close(s);
8729f8b0eadSeric 	clrevent(ev);
8739f8b0eadSeric 	if (i <= 0)
8749f8b0eadSeric 		goto noident;
8759f8b0eadSeric 	if (hbuf[--i] == '\n' && hbuf[--i] == '\r')
8769f8b0eadSeric 		i--;
8779f8b0eadSeric 	hbuf[++i] = '\0';
8789f8b0eadSeric 
87953853673Seric 	if (tTd(9, 3))
8809f8b0eadSeric 		printf("getauthinfo:  got %s\n", hbuf);
8819f8b0eadSeric 
8829f8b0eadSeric 	/* parse result */
8839f8b0eadSeric 	p = strchr(hbuf, ':');
8849f8b0eadSeric 	if (p == NULL)
8859f8b0eadSeric 	{
8869f8b0eadSeric 		/* malformed response */
8879f8b0eadSeric 		goto noident;
8889f8b0eadSeric 	}
8899f8b0eadSeric 	while (isascii(*++p) && isspace(*p))
8909f8b0eadSeric 		continue;
8919f8b0eadSeric 	if (strncasecmp(p, "userid", 6) != 0)
8929f8b0eadSeric 	{
8939f8b0eadSeric 		/* presumably an error string */
8949f8b0eadSeric 		goto noident;
8959f8b0eadSeric 	}
8969f8b0eadSeric 	p += 6;
8979f8b0eadSeric 	while (isascii(*p) && isspace(*p))
8989f8b0eadSeric 		p++;
8999f8b0eadSeric 	if (*p++ != ':')
9009f8b0eadSeric 	{
9019f8b0eadSeric 		/* either useridxx or malformed response */
9029f8b0eadSeric 		goto noident;
9039f8b0eadSeric 	}
9049f8b0eadSeric 
9059f8b0eadSeric 	/* p now points to the OSTYPE field */
9069f8b0eadSeric 	p = strchr(p, ':');
9079f8b0eadSeric 	if (p == NULL)
9089f8b0eadSeric 	{
9099f8b0eadSeric 		/* malformed response */
9109f8b0eadSeric 		goto noident;
9119f8b0eadSeric 	}
91253853673Seric 
91353853673Seric 	/* 1413 says don't do this -- but it's broken otherwise */
91453853673Seric 	while (isascii(*++p) && isspace(*p))
91553853673Seric 		continue;
9169f8b0eadSeric 
9179f8b0eadSeric 	/* p now points to the authenticated name */
9189f8b0eadSeric 	(void) sprintf(hbuf, "%s@%s", p, RealHostName);
91953853673Seric 	goto finish;
92053853673Seric 
92153853673Seric #endif /* IDENTPROTO */
92253853673Seric 
92353853673Seric noident:
92453853673Seric 	(void) strcpy(hbuf, RealHostName);
92553853673Seric 
92653853673Seric finish:
9279f8b0eadSeric 	if (RealHostName[0] != '[')
9289f8b0eadSeric 	{
9299f8b0eadSeric 		p = &hbuf[strlen(hbuf)];
9309f8b0eadSeric 		(void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr));
9319f8b0eadSeric 	}
93253853673Seric 	if (tTd(9, 1))
9339f8b0eadSeric 		printf("getauthinfo: %s\n", hbuf);
9349f8b0eadSeric 	return hbuf;
9359f8b0eadSeric }
936320e0d1cSeric /*
93715d084d5Seric **  MAPHOSTNAME -- turn a hostname into canonical form
93815d084d5Seric **
93915d084d5Seric **	Parameters:
94005b57da8Seric **		map -- a pointer to this map (unused).
94115d084d5Seric **		hbuf -- a buffer containing a hostname.
94215d084d5Seric **		hbsize -- the size of hbuf.
943d798a1deSeric **		avp -- unused -- for compatibility with other mapping
944d798a1deSeric **			functions.
9452d29d43aSeric **		statp -- an exit status (out parameter) -- set to
9462d29d43aSeric **			EX_TEMPFAIL if the name server is unavailable.
94715d084d5Seric **
94815d084d5Seric **	Returns:
94915d084d5Seric **		The mapping, if found.
95015d084d5Seric **		NULL if no mapping found.
95115d084d5Seric **
95215d084d5Seric **	Side Effects:
95315d084d5Seric **		Looks up the host specified in hbuf.  If it is not
95415d084d5Seric **		the canonical name for that host, return the canonical
95515d084d5Seric **		name.
956f36ede03Sbostic */
957cb452edcSeric 
95815d084d5Seric char *
9592d29d43aSeric maphostname(map, hbuf, hbsize, avp, statp)
96005b57da8Seric 	MAP *map;
96199f7cf32Seric 	char *hbuf;
96299f7cf32Seric 	int hbsize;
96315d084d5Seric 	char **avp;
9642d29d43aSeric 	int *statp;
96599f7cf32Seric {
96699f7cf32Seric 	register struct hostent *hp;
9675f78836eSmiriam 	u_long in_addr;
96805b57da8Seric 	char *cp;
96938ad259dSeric 	int i;
970*eea91d78Seric 	register STAB *s;
971*eea91d78Seric 	extern struct hostent *gethostbyaddr();
972*eea91d78Seric 	extern int h_errno;
9735f78836eSmiriam 
97499b358daSeric 	/* allow room for null */
97515d084d5Seric 	hbsize--;
97615d084d5Seric 
977f36ede03Sbostic 	/*
978*eea91d78Seric 	**  See if we have already looked up this name.  If so, just
979*eea91d78Seric 	**  return it.
980*eea91d78Seric 	*/
981*eea91d78Seric 
982*eea91d78Seric 	s = stab(hbuf, ST_NAMECANON, ST_ENTER);
983*eea91d78Seric 	if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
984*eea91d78Seric 	{
985*eea91d78Seric 		errno = s->s_namecanon.nc_errno;
986*eea91d78Seric 		h_errno = s->s_namecanon.nc_herrno;
987*eea91d78Seric 		*statp = s->s_namecanon.nc_stat;
988*eea91d78Seric 		return s->s_namecanon.nc_cname;
989*eea91d78Seric 	}
990*eea91d78Seric 
991*eea91d78Seric 	/*
992*eea91d78Seric 	**  If first character is a bracket, then it is an address
993*eea91d78Seric 	**  lookup.  Address is copied into a temporary buffer to
994*eea91d78Seric 	**  strip the brackets and to preserve hbuf if address is
995*eea91d78Seric 	**  unknown.
996f36ede03Sbostic 	*/
99715d084d5Seric 
998cb452edcSeric 	if (*hbuf != '[')
99915d084d5Seric 	{
1000d798a1deSeric 		extern bool getcanonname();
1001d798a1deSeric 
10028cb4653dSeric 		if (tTd(9, 1))
10039040ec4fSeric 			printf("maphostname(%s, %d) => ", hbuf, hbsize);
1004*eea91d78Seric 		s->s_namecanon.nc_flags |= NCF_VALID;		/* will be soon */
1005d5c60ac0Seric 		if (getcanonname(hbuf, hbsize))
10069040ec4fSeric 		{
10079040ec4fSeric 			if (tTd(9, 1))
10089040ec4fSeric 				printf("%s\n", hbuf);
1009*eea91d78Seric 			s->s_namecanon.nc_cname = newstr(hbuf);
101015d084d5Seric 			return hbuf;
10119040ec4fSeric 		}
101215d084d5Seric 		else
10139040ec4fSeric 		{
10142d29d43aSeric 			register struct hostent *hp;
10152d29d43aSeric 
10169040ec4fSeric 			if (tTd(9, 1))
10172d29d43aSeric 				printf("FAIL (%d)\n", h_errno);
1018*eea91d78Seric 			s->s_namecanon.nc_errno = errno;
1019*eea91d78Seric 			s->s_namecanon.nc_herrno = h_errno;
10202d29d43aSeric 			switch (h_errno)
10212d29d43aSeric 			{
10222d29d43aSeric 			  case TRY_AGAIN:
102389cb2793Seric 				if (UseNameServer)
102489cb2793Seric 					message("Recipient domain nameserver timed out");
10252d29d43aSeric 				*statp = EX_TEMPFAIL;
10262d29d43aSeric 				break;
10272d29d43aSeric 
10282d29d43aSeric 			  case HOST_NOT_FOUND:
10292d29d43aSeric 				*statp = EX_NOHOST;
10302d29d43aSeric 				break;
10312d29d43aSeric 
10322d29d43aSeric 			  case NO_RECOVERY:
10332d29d43aSeric 				*statp = EX_SOFTWARE;
10342d29d43aSeric 				break;
10352d29d43aSeric 
10362d29d43aSeric 			  default:
10372d29d43aSeric 				*statp = EX_UNAVAILABLE;
10382d29d43aSeric 				break;
10392d29d43aSeric 			}
1040*eea91d78Seric 			s->s_namecanon.nc_stat = *statp;
10412d29d43aSeric 			if (*statp != EX_TEMPFAIL || UseNameServer)
104215d084d5Seric 				return NULL;
10432d29d43aSeric 
10442d29d43aSeric 			/*
10452d29d43aSeric 			**  Try to look it up in /etc/hosts
10462d29d43aSeric 			*/
10472d29d43aSeric 
10482d29d43aSeric 			hp = gethostbyname(hbuf);
10492d29d43aSeric 			if (hp == NULL)
10502d29d43aSeric 			{
10512d29d43aSeric 				/* no dice there either */
1052*eea91d78Seric 				s->s_namecanon.nc_stat = *statp = EX_NOHOST;
10532d29d43aSeric 				return NULL;
10542d29d43aSeric 			}
10552d29d43aSeric 
1056*eea91d78Seric 			s->s_namecanon.nc_stat = *statp = EX_OK;
1057*eea91d78Seric 			s->s_namecanon.nc_cname = newstr(hp->h_name);
10582d29d43aSeric 			return hp->h_name;
105915d084d5Seric 		}
10609040ec4fSeric 	}
106105b57da8Seric 	if ((cp = strchr(hbuf, ']')) == NULL)
106215d084d5Seric 		return (NULL);
106334e39927Sbostic 	*cp = '\0';
106405b57da8Seric 	in_addr = inet_addr(&hbuf[1]);
106538ad259dSeric 
106638ad259dSeric 	/* check to see if this is one of our addresses */
106738ad259dSeric 	for (i = 0; MyIpAddrs[i].s_addr != 0; i++)
106838ad259dSeric 	{
106938ad259dSeric 		if (MyIpAddrs[i].s_addr == in_addr)
107038ad259dSeric 		{
107138ad259dSeric 			strncpy(hbuf, MyHostName, hbsize);
107238ad259dSeric 			hbuf[hbsize] = '\0';
107338ad259dSeric 			return hbuf;
107438ad259dSeric 		}
107538ad259dSeric 	}
107638ad259dSeric 
107738ad259dSeric 	/* nope -- ask the name server */
107831601fa7Seric 	hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
1079*eea91d78Seric 	s->s_namecanon.nc_errno = errno;
1080*eea91d78Seric 	s->s_namecanon.nc_herrno = h_errno;
1081*eea91d78Seric 	s->s_namecanon.nc_flags |= NCF_VALID;		/* will be soon */
10825f78836eSmiriam 	if (hp == NULL)
1083*eea91d78Seric 	{
1084*eea91d78Seric 		s->s_namecanon.nc_stat = *statp = EX_NOHOST;
108515d084d5Seric 		return (NULL);
1086*eea91d78Seric 	}
108715d084d5Seric 
108838ad259dSeric 	/* found a match -- copy out */
1089*eea91d78Seric 	s->s_namecanon.nc_cname = newstr(hp->h_name);
109005b57da8Seric 	if (strlen(hp->h_name) > hbsize)
109105b57da8Seric 		hp->h_name[hbsize] = '\0';
1092fefbbe29Seric 	(void) strcpy(hbuf, hp->h_name);
1093*eea91d78Seric 	s->s_namecanon.nc_stat = *statp = EX_OK;
109415d084d5Seric 	return hbuf;
109599f7cf32Seric }
1096e2f2f828Seric /*
1097e2f2f828Seric **  ANYNET_NTOA -- convert a network address to printable form.
1098e2f2f828Seric **
1099e2f2f828Seric **	Parameters:
1100e2f2f828Seric **		sap -- a pointer to a sockaddr structure.
1101e2f2f828Seric **
1102e2f2f828Seric **	Returns:
1103e2f2f828Seric **		A printable version of that sockaddr.
1104e2f2f828Seric */
1105e2f2f828Seric 
1106e2f2f828Seric char *
1107e2f2f828Seric anynet_ntoa(sap)
1108e2f2f828Seric 	register SOCKADDR *sap;
1109e2f2f828Seric {
1110e2f2f828Seric 	register char *bp;
1111e2f2f828Seric 	register char *ap;
1112e2f2f828Seric 	int l;
1113e2f2f828Seric 	static char buf[80];
1114e2f2f828Seric 
11158cb4653dSeric 	/* check for null/zero family */
11168cb4653dSeric 	if (sap == NULL)
11178cb4653dSeric 		return "NULLADDR";
11188cb4653dSeric 	if (sap->sa.sa_family == 0)
11198cb4653dSeric 		return "0";
11208cb4653dSeric 
112183c1f4bcSeric #ifdef NETINET
112283c1f4bcSeric 	if (sap->sa.sa_family == AF_INET)
1123e2f2f828Seric 	{
1124e2f2f828Seric 		extern char *inet_ntoa();
1125e2f2f828Seric 
1126e2f2f828Seric 		return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr);
1127e2f2f828Seric 	}
112883c1f4bcSeric #endif
1129e2f2f828Seric 
1130e2f2f828Seric 	/* unknown family -- just dump bytes */
113183c1f4bcSeric 	(void) sprintf(buf, "Family %d: ", sap->sa.sa_family);
1132e2f2f828Seric 	bp = &buf[strlen(buf)];
113383c1f4bcSeric 	ap = sap->sa.sa_data;
113483c1f4bcSeric 	for (l = sizeof sap->sa.sa_data; --l >= 0; )
1135e2f2f828Seric 	{
1136e2f2f828Seric 		(void) sprintf(bp, "%02x:", *ap++ & 0377);
1137e2f2f828Seric 		bp += 3;
1138e2f2f828Seric 	}
1139e2f2f828Seric 	*--bp = '\0';
1140e2f2f828Seric 	return buf;
1141e2f2f828Seric }
11429f8b0eadSeric /*
11439f8b0eadSeric **  HOSTNAMEBYANYADDR -- return name of host based on address
11449f8b0eadSeric **
11459f8b0eadSeric **	Parameters:
11469f8b0eadSeric **		sap -- SOCKADDR pointer
11479f8b0eadSeric **
11489f8b0eadSeric **	Returns:
11499f8b0eadSeric **		text representation of host name.
11509f8b0eadSeric **
11519f8b0eadSeric **	Side Effects:
11529f8b0eadSeric **		none.
11539f8b0eadSeric */
11549f8b0eadSeric 
11559f8b0eadSeric char *
11569f8b0eadSeric hostnamebyanyaddr(sap)
11579f8b0eadSeric 	register SOCKADDR *sap;
11589f8b0eadSeric {
11599f8b0eadSeric 	register struct hostent *hp;
11609f8b0eadSeric 
11613490b9dfSeric #ifdef NAMED_BIND
11623490b9dfSeric 	int saveretry;
11633490b9dfSeric 
11643490b9dfSeric 	/* shorten name server timeout to avoid higher level timeouts */
11653490b9dfSeric 	saveretry = _res.retry;
11663490b9dfSeric 	_res.retry = 3;
11673490b9dfSeric #endif /* NAMED_BIND */
11683490b9dfSeric 
11699f8b0eadSeric 	switch (sap->sa.sa_family)
11709f8b0eadSeric 	{
11719f8b0eadSeric #ifdef NETINET
11729f8b0eadSeric 	  case AF_INET:
11739f8b0eadSeric 		hp = gethostbyaddr((char *) &sap->sin.sin_addr,
11749f8b0eadSeric 			sizeof sap->sin.sin_addr,
11759f8b0eadSeric 			AF_INET);
11769f8b0eadSeric 		break;
11779f8b0eadSeric #endif
11789f8b0eadSeric 
11799f8b0eadSeric #ifdef NETISO
11809f8b0eadSeric 	  case AF_ISO:
11819f8b0eadSeric 		hp = gethostbyaddr((char *) &sap->siso.siso_addr,
11829f8b0eadSeric 			sizeof sap->siso.siso_addr,
11839f8b0eadSeric 			AF_ISO);
11849f8b0eadSeric 		break;
11859f8b0eadSeric #endif
11869f8b0eadSeric 
11879f8b0eadSeric 	  default:
11889f8b0eadSeric 		hp = gethostbyaddr(sap->sa.sa_data,
11899f8b0eadSeric 			   sizeof sap->sa.sa_data,
11909f8b0eadSeric 			   sap->sa.sa_family);
11919f8b0eadSeric 		break;
11929f8b0eadSeric 	}
11939f8b0eadSeric 
11943490b9dfSeric #ifdef NAMED_BIND
11953490b9dfSeric 	_res.retry = saveretry;
11963490b9dfSeric #endif /* NAMED_BIND */
11973490b9dfSeric 
11989f8b0eadSeric 	if (hp != NULL)
11999f8b0eadSeric 		return hp->h_name;
12009f8b0eadSeric 	else
12019f8b0eadSeric 	{
12029f8b0eadSeric 		/* produce a dotted quad */
12039f8b0eadSeric 		static char buf[512];
12049f8b0eadSeric 
12059f8b0eadSeric 		(void) sprintf(buf, "[%s]", anynet_ntoa(sap));
12069f8b0eadSeric 		return buf;
12079f8b0eadSeric 	}
12089f8b0eadSeric }
1209f36ede03Sbostic 
12106c2c3107Seric # else /* DAEMON */
121199f7cf32Seric /* code for systems without sophisticated networking */
1212444eaf03Seric 
1213444eaf03Seric /*
1214444eaf03Seric **  MYHOSTNAME -- stub version for case of no daemon code.
121521e9914dSeric **
121621e9914dSeric **	Can't convert to upper case here because might be a UUCP name.
1217897f1869Seric **
1218897f1869Seric **	Mark, you can change this to be anything you want......
1219444eaf03Seric */
1220444eaf03Seric 
1221444eaf03Seric char **
1222897f1869Seric myhostname(hostbuf, size)
1223444eaf03Seric 	char hostbuf[];
1224897f1869Seric 	int size;
1225444eaf03Seric {
1226444eaf03Seric 	register FILE *f;
1227444eaf03Seric 
1228444eaf03Seric 	hostbuf[0] = '\0';
1229444eaf03Seric 	f = fopen("/usr/include/whoami", "r");
1230444eaf03Seric 	if (f != NULL)
1231444eaf03Seric 	{
1232897f1869Seric 		(void) fgets(hostbuf, size, f);
1233444eaf03Seric 		fixcrlf(hostbuf, TRUE);
1234444eaf03Seric 		(void) fclose(f);
1235444eaf03Seric 	}
1236444eaf03Seric 	return (NULL);
1237444eaf03Seric }
123899f7cf32Seric /*
12399f8b0eadSeric **  GETAUTHINFO -- get the real host name asociated with a file descriptor
1240320e0d1cSeric **
1241320e0d1cSeric **	Parameters:
1242320e0d1cSeric **		fd -- the descriptor
1243320e0d1cSeric **
1244320e0d1cSeric **	Returns:
1245320e0d1cSeric **		The host name associated with this descriptor, if it can
1246320e0d1cSeric **			be determined.
1247320e0d1cSeric **		NULL otherwise.
1248320e0d1cSeric **
1249320e0d1cSeric **	Side Effects:
1250320e0d1cSeric **		none
1251320e0d1cSeric */
1252320e0d1cSeric 
1253320e0d1cSeric char *
12549f8b0eadSeric getauthinfo(fd)
1255320e0d1cSeric 	int fd;
1256320e0d1cSeric {
1257320e0d1cSeric 	return NULL;
1258320e0d1cSeric }
1259320e0d1cSeric /*
126099f7cf32Seric **  MAPHOSTNAME -- turn a hostname into canonical form
126199f7cf32Seric **
126299f7cf32Seric **	Parameters:
126305b57da8Seric **		map -- a pointer to the database map.
126499f7cf32Seric **		hbuf -- a buffer containing a hostname.
12652d29d43aSeric **		hbsize -- size of hbuf.
126615d084d5Seric **		avp -- a pointer to a (cf file defined) argument vector.
12672d29d43aSeric **		statp -- an exit status (out parameter).
126899f7cf32Seric **
126999f7cf32Seric **	Returns:
127015d084d5Seric **		mapped host name
1271cb452edcSeric **		FALSE otherwise.
127299f7cf32Seric **
127399f7cf32Seric **	Side Effects:
127499f7cf32Seric **		Looks up the host specified in hbuf.  If it is not
127599f7cf32Seric **		the canonical name for that host, replace it with
127699f7cf32Seric **		the canonical name.  If the name is unknown, or it
127799f7cf32Seric **		is already the canonical name, leave it unchanged.
127899f7cf32Seric */
127999f7cf32Seric 
128099f7cf32Seric /*ARGSUSED*/
128115d084d5Seric char *
12822d29d43aSeric maphostname(map, hbuf, hbsize, avp, statp)
128305b57da8Seric 	MAP *map;
128499f7cf32Seric 	char *hbuf;
128599f7cf32Seric 	int hbsize;
128615d084d5Seric 	char **avp;
12872d29d43aSeric 	char *statp;
128899f7cf32Seric {
12892d29d43aSeric 	register struct hostent *hp;
12902d29d43aSeric 
12912d29d43aSeric 	hp = gethostbyname(hbuf);
12922d29d43aSeric 	if (hp != NULL)
12932d29d43aSeric 		return hp->h_name;
12942d29d43aSeric 	*statp = EX_NOHOST;
129515d084d5Seric 	return NULL;
129699f7cf32Seric }
129799f7cf32Seric 
12986c2c3107Seric #endif /* DAEMON */
1299