Deleted Added
sdiff udiff text old ( 42575 ) new ( 43730 )
full compact
1/*
2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13#include <errno.h>
14#include "sendmail.h"
15
16#ifndef lint
17#ifdef DAEMON
18static char sccsid[] = "@(#)daemon.c 8.236 (Berkeley) 1/25/1999 (with daemon mode)";
19#else
20static char sccsid[] = "@(#)daemon.c 8.236 (Berkeley) 1/25/1999 (without daemon mode)";
21#endif
22#endif /* not lint */
23
24#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
25# define USE_SOCK_STREAM 1
26#endif
27
28#if DAEMON || defined(USE_SOCK_STREAM)
29# include <arpa/inet.h>
30# if NAMED_BIND
31# include <resolv.h>
32# ifndef NO_DATA
33# define NO_DATA NO_ADDRESS
34# endif
35# endif
36#endif
37
38#if DAEMON
39
40# include <sys/time.h>
41
42# if IP_SRCROUTE
43# include <netinet/in_systm.h>
44# include <netinet/ip.h>
45# include <netinet/ip_var.h>
46# endif
47
48/*
49** DAEMON.C -- routines to use when running as a daemon.
50**
51** This entire file is highly dependent on the 4.2 BSD
52** interprocess communication primitives. No attempt has
53** been made to make this file portable to Version 7,
54** Version 6, MPX files, etc. If you should try such a
55** thing yourself, I recommend chucking the entire file
56** and starting from scratch. Basic semantics are:
57**
58** getrequests(e)
59** Opens a port and initiates a connection.
60** Returns in a child. Must set InChannel and
61** OutChannel appropriately.
62** clrdaemon()
63** Close any open files associated with getting
64** the connection; this is used when running the queue,
65** etc., to avoid having extra file descriptors during
66** the queue run and to avoid confusing the network
67** code (if it cares).
68** makeconnection(host, port, outfile, infile, e)
69** Make a connection to the named host on the given
70** port. Set *outfile and *infile to the files
71** appropriate for communication. Returns zero on
72** success, else an exit status describing the
73** error.
74** host_map_lookup(map, hbuf, avp, pstat)
75** Convert the entry in hbuf into a canonical form.
76*/
77 /*
78** GETREQUESTS -- open mail IPC port and get requests.
79**
80** Parameters:
81** e -- the current envelope.
82**
83** Returns:
84** none.
85**
86** Side Effects:
87** Waits until some interesting activity occurs. When
88** it does, a child is created to process it, and the
89** parent waits for completion. Return from this
90** routine is always in the child. The file pointers
91** "InChannel" and "OutChannel" should be set to point
92** to the communication channel.
93*/
94
95int DaemonSocket = -1; /* fd describing socket */
96SOCKADDR DaemonAddr; /* socket for incoming */
97int ListenQueueSize = 10; /* size of listen queue */
98int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
99int TcpSndBufferSize = 0; /* size of TCP send buffer */
100
101void
102getrequests(e)
103 ENVELOPE *e;
104{
105 int t;
106 time_t refuse_connections_until = 0;
107 bool firsttime = TRUE;
108 FILE *pidf;
109 int sff;
110 int socksize;
111 u_short port;
112#if XDEBUG
113 bool j_has_dot;
114#endif
115 char status[MAXLINE];
116 extern void reapchild __P((int));
117#ifdef NETUNIX
118 extern int ControlSocket;
119#endif
120 extern int opendaemonsocket __P((bool));
121 extern int opencontrolsocket __P((void));
122
123 /*
124 ** Set up the address for the mailer.
125 */
126
127 switch (DaemonAddr.sa.sa_family)
128 {
129 case AF_UNSPEC:
130 DaemonAddr.sa.sa_family = AF_INET;
131 /* fall through ... */
132
133 case AF_INET:
134 if (DaemonAddr.sin.sin_addr.s_addr == 0)
135 DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY;
136 port = DaemonAddr.sin.sin_port;
137 break;
138
139 default:
140 /* unknown protocol */
141 port = 0;
142 break;
143 }
144 if (port == 0)
145 {
146 register struct servent *sp;
147
148 sp = getservbyname("smtp", "tcp");
149 if (sp == NULL)
150 {
151 syserr("554 service \"smtp\" unknown");
152 port = htons(25);
153 }
154 else
155 port = sp->s_port;
156 }
157
158 switch (DaemonAddr.sa.sa_family)
159 {
160 case AF_INET:
161 DaemonAddr.sin.sin_port = port;
162 break;
163
164 default:
165 /* unknown protocol */
166 break;
167 }
168
169 /*
170 ** Try to actually open the connection.
171 */
172
173 if (tTd(15, 1))
174 printf("getrequests: port 0x%x\n", port);
175
176 /* get a socket for the SMTP connection */
177 socksize = opendaemonsocket(TRUE);
178
179 if (opencontrolsocket() < 0)
180 sm_syslog(LOG_WARNING, NOQID,
181 "daemon could not open control socket %s: %s",
182 ControlSocketName, errstring(errno));
183
184 (void) setsignal(SIGCHLD, reapchild);
185
186 /* write the pid to the log file for posterity */
187 sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT;
188 if (TrustedUid != 0 && RealUid == TrustedUid)
189 sff |= SFF_OPENASROOT;
190 pidf = safefopen(PidFile, O_WRONLY|O_TRUNC, 0644, sff);
191 if (pidf == NULL)
192 {
193 sm_syslog(LOG_ERR, NOQID, "unable to write %s", PidFile);
194 }
195 else
196 {
197 extern char *CommandLineArgs;
198
199 /* write the process id on line 1 */
200 fprintf(pidf, "%ld\n", (long) getpid());
201
202 /* line 2 contains all command line flags */
203 fprintf(pidf, "%s\n", CommandLineArgs);
204
205 /* flush and close */
206 fclose(pidf);
207 }
208
209#if XDEBUG
210 {
211 char jbuf[MAXHOSTNAMELEN];
212
213 expand("\201j", jbuf, sizeof jbuf, e);
214 j_has_dot = strchr(jbuf, '.') != NULL;
215 }
216#endif
217
218 /* Add parent process as first item */
219 proc_list_add(getpid(), "Sendmail daemon");
220
221 if (tTd(15, 1))
222 printf("getrequests: %d\n", DaemonSocket);
223
224 for (;;)
225 {
226 register pid_t pid;
227 auto SOCKADDR_LEN_T lotherend;
228 bool timedout = FALSE;
229 bool control = FALSE;
230 int savederrno;
231 int pipefd[2];
232 extern bool refuseconnections __P((int));
233
234 /* see if we are rejecting connections */
235 (void) blocksignal(SIGALRM);
236 if (curtime() >= refuse_connections_until)
237 {
238 if (refuseconnections(ntohs(port)))
239 {
240 if (DaemonSocket >= 0)
241 {
242 /* close socket so peer fails quickly */
243 (void) close(DaemonSocket);
244 DaemonSocket = -1;
245 }
246
247 /* refuse connections for next 15 seconds */
248 refuse_connections_until = curtime() + 15;
249 }
250 else if (DaemonSocket < 0 || firsttime)
251 {
252 /* arrange to (re)open the socket if needed */
253 (void) opendaemonsocket(FALSE);
254 firsttime = FALSE;
255 }
256 }
257
258#if XDEBUG
259 /* check for disaster */
260 {
261 char jbuf[MAXHOSTNAMELEN];
262 extern void dumpstate __P((char *));
263
264 expand("\201j", jbuf, sizeof jbuf, e);
265 if (!wordinclass(jbuf, 'w'))
266 {
267 dumpstate("daemon lost $j");
268 sm_syslog(LOG_ALERT, NOQID,
269 "daemon process doesn't have $j in $=w; see syslog");
270 abort();
271 }
272 else if (j_has_dot && strchr(jbuf, '.') == NULL)
273 {
274 dumpstate("daemon $j lost dot");
275 sm_syslog(LOG_ALERT, NOQID,
276 "daemon process $j lost dot; see syslog");
277 abort();
278 }
279 }
280#endif
281
282#if 0
283 /*
284 ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will
285 ** fix the SVr4 problem. But it seems to have gone away,
286 ** so is it worth doing this?
287 */
288
289 if (DaemonSocket >= 0 &&
290 SetNonBlocking(DaemonSocket, FALSE) < 0)
291 log an error here;
292#endif
293 (void) releasesignal(SIGALRM);
294 for (;;)
295 {
296 int highest = -1;
297 fd_set readfds;
298 struct timeval timeout;
299
300 FD_ZERO(&readfds);
301
302 /* wait for a connection */
303 if (DaemonSocket >= 0)
304 {
305 sm_setproctitle(TRUE,
306 "accepting connections on port %d",
307 ntohs(port));
308 if (DaemonSocket > highest)
309 highest = DaemonSocket;
310 FD_SET(DaemonSocket, &readfds);
311 }
312#ifdef NETUNIX
313 if (ControlSocket >= 0)
314 {
315 if (ControlSocket > highest)
316 highest = ControlSocket;
317 FD_SET(ControlSocket, &readfds);
318 }
319#endif
320 if (DaemonSocket >= 0)
321 timeout.tv_sec = 60;
322 else
323 timeout.tv_sec = 5;
324 timeout.tv_usec = 0;
325
326 t = select(highest + 1, FDSET_CAST &readfds,
327 NULL, NULL, &timeout);
328
329 if (DoQueueRun)
330 (void) runqueue(TRUE, FALSE);
331 if (t <= 0)
332 {
333 timedout = TRUE;
334 break;
335 }
336
337 control = FALSE;
338 errno = 0;
339 if (DaemonSocket >= 0 &&
340 FD_ISSET(DaemonSocket, &readfds))
341 {
342 lotherend = socksize;
343 t = accept(DaemonSocket,
344 (struct sockaddr *)&RealHostAddr,
345 &lotherend);
346 }
347#ifdef NETUNIX
348 else if (ControlSocket >= 0 &&
349 FD_ISSET(ControlSocket, &readfds))
350 {
351 struct sockaddr_un sa_un;
352
353 lotherend = sizeof sa_un;
354 t = accept(ControlSocket,
355 (struct sockaddr *)&sa_un,
356 &lotherend);
357 control = TRUE;
358 }
359#endif
360 if (t >= 0 || errno != EINTR)
361 break;
362 }
363 if (timedout)
364 {
365 timedout = FALSE;
366 continue;
367 }
368 if (control)
369 {
370 if (t >= 0)
371 {
372 extern void control_command __P((int, ENVELOPE *));
373
374 control_command(t, e);
375 }
376 else
377 syserr("getrequests: control accept");
378 continue;
379 }
380 savederrno = errno;
381 (void) blocksignal(SIGALRM);
382 if (t < 0)
383 {
384 errno = savederrno;
385 syserr("getrequests: accept");
386
387 /* arrange to re-open the socket next time around */
388 (void) close(DaemonSocket);
389 DaemonSocket = -1;
390 continue;
391 }
392
393 /*
394 ** Create a subprocess to process the mail.
395 */
396
397 if (tTd(15, 2))
398 printf("getrequests: forking (fd = %d)\n", t);
399
400 /*
401 ** Create a pipe to keep the child from writing to the
402 ** socket until after the parent has closed it. Otherwise
403 ** the parent may hang if the child has closed it first.
404 */
405
406 if (pipe(pipefd) < 0)
407 pipefd[0] = pipefd[1] = -1;
408
409 blocksignal(SIGCHLD);
410 pid = fork();
411 if (pid < 0)
412 {
413 syserr("daemon: cannot fork");
414 if (pipefd[0] != -1)
415 {
416 (void) close(pipefd[0]);
417 (void) close(pipefd[1]);
418 }
419 (void) releasesignal(SIGCHLD);
420 sleep(10);
421 (void) close(t);
422 continue;
423 }
424
425 if (pid == 0)
426 {
427 char *p;
428 extern SIGFUNC_DECL intsig __P((int));
429 FILE *inchannel, *outchannel;
430
431 /*
432 ** CHILD -- return to caller.
433 ** Collect verified idea of sending host.
434 ** Verify calling user id if possible here.
435 */
436
437 (void) releasesignal(SIGALRM);
438 (void) releasesignal(SIGCHLD);
439 (void) setsignal(SIGCHLD, SIG_DFL);
440 (void) setsignal(SIGHUP, intsig);
441 (void) close(DaemonSocket);
442 clrcontrol();
443 proc_list_clear();
444
445 /* Add parent process as first child item */
446 proc_list_add(getpid(), "daemon child");
447
448 /* don't schedule queue runs if we are told to ETRN */
449 QueueIntvl = 0;
450
451 sm_setproctitle(TRUE, "startup with %s",
452 anynet_ntoa(&RealHostAddr));
453
454 if (pipefd[0] != -1)
455 {
456 auto char c;
457
458 /*
459 ** Wait for the parent to close the write end
460 ** of the pipe, which we will see as an EOF.
461 ** This guarantees that we won't write to the
462 ** socket until after the parent has closed
463 ** the pipe.
464 */
465
466 /* close the write end of the pipe */
467 (void) close(pipefd[1]);
468
469 /* we shouldn't be interrupted, but ... */
470 while (read(pipefd[0], &c, 1) < 0 &&
471 errno == EINTR)
472 continue;
473 (void) close(pipefd[0]);
474 }
475
476 /* determine host name */
477 p = hostnamebyanyaddr(&RealHostAddr);
478 if (strlen(p) > (SIZE_T) MAXNAME)
479 p[MAXNAME] = '\0';
480 RealHostName = newstr(p);
481 sm_setproctitle(TRUE, "startup with %s", p);
482
483 if ((inchannel = fdopen(t, "r")) == NULL ||
484 (t = dup(t)) < 0 ||
485 (outchannel = fdopen(t, "w")) == NULL)
486 {
487 syserr("cannot open SMTP server channel, fd=%d", t);
488 finis(FALSE, EX_OK);
489 }
490
491 InChannel = inchannel;
492 OutChannel = outchannel;
493 DisConnected = FALSE;
494
495#ifdef XLA
496 if (!xla_host_ok(RealHostName))
497 {
498 message("421 Too many SMTP sessions for this host");
499 finis(FALSE, EX_OK);
500 }
501#endif
502 break;
503 }
504
505 /* parent -- keep track of children */
506 snprintf(status, sizeof status, "SMTP server child for %s",
507 anynet_ntoa(&RealHostAddr));
508 proc_list_add(pid, status);
509 (void) releasesignal(SIGCHLD);
510
511 /* close the read end of the synchronization pipe */
512 if (pipefd[0] != -1)
513 (void) close(pipefd[0]);
514
515 /* close the port so that others will hang (for a while) */
516 (void) close(t);
517
518 /* release the child by closing the read end of the sync pipe */
519 if (pipefd[1] != -1)
520 (void) close(pipefd[1]);
521 }
522 if (tTd(15, 2))
523 printf("getreq: returning\n");
524 return;
525}
526 /*
527** OPENDAEMONSOCKET -- open the SMTP socket
528**
529** Deals with setting all appropriate options. DaemonAddr must
530** be set up in advance.
531**
532** Parameters:
533** firsttime -- set if this is the initial open.
534**
535** Returns:
536** Size in bytes of the daemon socket addr.
537**
538** Side Effects:
539** Leaves DaemonSocket set to the open socket.
540** Exits if the socket cannot be created.
541*/
542
543#define MAXOPENTRIES 10 /* maximum number of tries to open connection */
544
545int
546opendaemonsocket(firsttime)
547 bool firsttime;
548{
549 int on = 1;
550 int socksize = 0;
551 int ntries = 0;
552 int saveerrno;
553
554 if (tTd(15, 2))
555 printf("opendaemonsocket()\n");
556
557 do
558 {
559 if (ntries > 0)
560 sleep(5);
561 if (firsttime || DaemonSocket < 0)
562 {
563 DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0);
564 if (DaemonSocket < 0)
565 {
566 saveerrno = errno;
567 syserr("opendaemonsocket: can't create server SMTP socket");
568 severe:
569 if (LogLevel > 0)
570 sm_syslog(LOG_ALERT, NOQID,
571 "problem creating SMTP socket");
572 DaemonSocket = -1;
573 continue;
574 }
575
576 /* turn on network debugging? */
577 if (tTd(15, 101))
578 (void) setsockopt(DaemonSocket, SOL_SOCKET,
579 SO_DEBUG, (char *)&on,
580 sizeof on);
581
582 (void) setsockopt(DaemonSocket, SOL_SOCKET,
583 SO_REUSEADDR, (char *)&on, sizeof on);
584 (void) setsockopt(DaemonSocket, SOL_SOCKET,
585 SO_KEEPALIVE, (char *)&on, sizeof on);
586
587#ifdef SO_RCVBUF
588 if (TcpRcvBufferSize > 0)
589 {
590 if (setsockopt(DaemonSocket, SOL_SOCKET,
591 SO_RCVBUF,
592 (char *) &TcpRcvBufferSize,
593 sizeof(TcpRcvBufferSize)) < 0)
594 syserr("opendaemonsocket: setsockopt(SO_RCVBUF)");
595 }
596#endif
597
598 switch (DaemonAddr.sa.sa_family)
599 {
600# if NETINET
601 case AF_INET:
602 socksize = sizeof DaemonAddr.sin;
603 break;
604# endif
605
606# if NETISO
607 case AF_ISO:
608 socksize = sizeof DaemonAddr.siso;
609 break;
610# endif
611
612 default:
613 socksize = sizeof DaemonAddr;
614 break;
615 }
616
617 if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0)
618 {
619 /* probably another daemon already */
620 saveerrno = errno;
621 syserr("opendaemonsocket: cannot bind");
622 (void) close(DaemonSocket);
623 goto severe;
624 }
625 }
626 if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0)
627 {
628 saveerrno = errno;
629 syserr("opendaemonsocket: cannot listen");
630 (void) close(DaemonSocket);
631 goto severe;
632 }
633 return socksize;
634 } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno));
635 syserr("!opendaemonsocket: server SMTP socket wedged: exiting");
636 /*NOTREACHED*/
637 return -1; /* avoid compiler warning on IRIX */
638}
639 /*
640** CLRDAEMON -- reset the daemon connection
641**
642** Parameters:
643** none.
644**
645** Returns:
646** none.
647**
648** Side Effects:
649** releases any resources used by the passive daemon.
650*/
651
652void
653clrdaemon()
654{
655 if (DaemonSocket >= 0)
656 (void) close(DaemonSocket);
657 DaemonSocket = -1;
658}
659 /*
660** SETDAEMONOPTIONS -- set options for running the daemon
661**
662** Parameters:
663** p -- the options line.
664**
665** Returns:
666** none.
667*/
668
669void
670setdaemonoptions(p)
671 register char *p;
672{
673 if (DaemonAddr.sa.sa_family == AF_UNSPEC)
674 DaemonAddr.sa.sa_family = AF_INET;
675
676 while (p != NULL)
677 {
678 register char *f;
679 register char *v;
680
681 while (isascii(*p) && isspace(*p))
682 p++;
683 if (*p == '\0')
684 break;
685 f = p;
686 p = strchr(p, ',');
687 if (p != NULL)
688 *p++ = '\0';
689 v = strchr(f, '=');
690 if (v == NULL)
691 continue;
692 while (isascii(*++v) && isspace(*v))
693 continue;
694 if (isascii(*f) && islower(*f))
695 *f = toupper(*f);
696
697 switch (*f)
698 {
699 case 'F': /* address family */
700 if (isascii(*v) && isdigit(*v))
701 DaemonAddr.sa.sa_family = atoi(v);
702#if NETINET
703 else if (strcasecmp(v, "inet") == 0)
704 DaemonAddr.sa.sa_family = AF_INET;
705#endif
706#if NETISO
707 else if (strcasecmp(v, "iso") == 0)
708 DaemonAddr.sa.sa_family = AF_ISO;
709#endif
710#if NETNS
711 else if (strcasecmp(v, "ns") == 0)
712 DaemonAddr.sa.sa_family = AF_NS;
713#endif
714#if NETX25
715 else if (strcasecmp(v, "x.25") == 0)
716 DaemonAddr.sa.sa_family = AF_CCITT;
717#endif
718 else
719 syserr("554 Unknown address family %s in Family=option", v);
720 break;
721
722 case 'A': /* address */
723 switch (DaemonAddr.sa.sa_family)
724 {
725#if NETINET
726 case AF_INET:
727 if (isascii(*v) && isdigit(*v))
728 DaemonAddr.sin.sin_addr.s_addr = inet_addr(v);
729 else
730 {
731 register struct hostent *hp;
732
733 hp = sm_gethostbyname(v);
734 if (hp == NULL)
735 syserr("554 host \"%s\" unknown", v);
736 else
737 bcopy(hp->h_addr, &DaemonAddr.sin.sin_addr, INADDRSZ);
738 }
739 break;
740#endif
741
742 default:
743 syserr("554 Address= option unsupported for family %d",
744 DaemonAddr.sa.sa_family);
745 break;
746 }
747 break;
748
749 case 'P': /* port */
750 switch (DaemonAddr.sa.sa_family)
751 {
752#if NETISO
753 short port;
754#endif
755
756#if NETINET
757 case AF_INET:
758 if (isascii(*v) && isdigit(*v))
759 DaemonAddr.sin.sin_port = htons(atoi(v));
760 else
761 {
762 register struct servent *sp;
763
764 sp = getservbyname(v, "tcp");
765 if (sp == NULL)
766 syserr("554 service \"%s\" unknown", v);
767 else
768 DaemonAddr.sin.sin_port = sp->s_port;
769 }
770 break;
771#endif
772
773#if NETISO
774 case AF_ISO:
775 /* assume two byte transport selector */
776 if (isascii(*v) && isdigit(*v))
777 port = htons(atoi(v));
778 else
779 {
780 register struct servent *sp;
781
782 sp = getservbyname(v, "tcp");
783 if (sp == NULL)
784 syserr("554 service \"%s\" unknown", v);
785 else
786 port = sp->s_port;
787 }
788 bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2);
789 break;
790#endif
791
792 default:
793 syserr("554 Port= option unsupported for family %d",
794 DaemonAddr.sa.sa_family);
795 break;
796 }
797 break;
798
799 case 'L': /* listen queue size */
800 ListenQueueSize = atoi(v);
801 break;
802
803 case 'S': /* send buffer size */
804 TcpSndBufferSize = atoi(v);
805 break;
806
807 case 'R': /* receive buffer size */
808 TcpRcvBufferSize = atoi(v);
809 break;
810
811 default:
812 syserr("554 DaemonPortOptions parameter \"%s\" unknown", f);
813 }
814 }
815}
816 /*
817** MAKECONNECTION -- make a connection to an SMTP socket on another machine.
818**
819** Parameters:
820** host -- the name of the host.
821** port -- the port number to connect to.
822** mci -- a pointer to the mail connection information
823** structure to be filled in.
824** e -- the current envelope.
825**
826** Returns:
827** An exit code telling whether the connection could be
828** made and if not why not.
829**
830** Side Effects:
831** none.
832*/
833
834static jmp_buf CtxConnectTimeout;
835
836static void
837connecttimeout()
838{
839 errno = ETIMEDOUT;
840 longjmp(CtxConnectTimeout, 1);
841}
842
843SOCKADDR CurHostAddr; /* address of current host */
844
845int
846makeconnection(host, port, mci, e)
847 char *host;
848 u_short port;
849 register MCI *mci;
850 ENVELOPE *e;
851{
852 register volatile int addrno = 0;
853 register volatile int s;
854 register struct hostent *volatile hp = (struct hostent *)NULL;
855 SOCKADDR addr;
856 int sav_errno;
857 volatile int addrlen;
858 volatile bool firstconnect;
859 EVENT *volatile ev = NULL;
860
861 /*
862 ** Set up the address for the mailer.
863 ** Accept "[a.b.c.d]" syntax for host name.
864 */
865
866#if NAMED_BIND
867 h_errno = 0;
868#endif
869 errno = 0;
870 bzero(&CurHostAddr, sizeof CurHostAddr);
871 SmtpPhase = mci->mci_phase = "initial connection";
872 CurHostName = host;
873
874 if (host[0] == '[')
875 {
876#if NETINET
877 unsigned long hid = INADDR_NONE;
878#endif
879 register char *p = strchr(host, ']');
880
881 if (p != NULL)
882 {
883 *p = '\0';
884#if NETINET
885 hid = inet_addr(&host[1]);
886 if (hid == INADDR_NONE)
887#endif
888 {
889 /* try it as a host name (avoid MX lookup) */
890 hp = sm_gethostbyname(&host[1]);
891 if (hp == NULL && p[-1] == '.')
892 {
893#if NAMED_BIND
894 int oldopts = _res.options;
895
896 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
897#endif
898 p[-1] = '\0';
899 hp = sm_gethostbyname(&host[1]);
900 p[-1] = '.';
901#if NAMED_BIND
902 _res.options = oldopts;
903#endif
904 }
905 *p = ']';
906 goto gothostent;
907 }
908 *p = ']';
909 }
910 if (p == NULL)
911 {
912 extern char MsgBuf[];
913
914 usrerr("553 Invalid numeric domain spec \"%s\"", host);
915 mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
916 return EX_NOHOST;
917 }
918#if NETINET
919 addr.sin.sin_family = AF_INET; /*XXX*/
920 addr.sin.sin_addr.s_addr = hid;
921#endif
922 }
923 else
924 {
925 /* contortion to get around SGI cc complaints */
926 {
927 register char *p = &host[strlen(host) - 1];
928
929 hp = sm_gethostbyname(host);
930 if (hp == NULL && *p == '.')
931 {
932#if NAMED_BIND
933 int oldopts = _res.options;
934
935 _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
936#endif
937 *p = '\0';
938 hp = sm_gethostbyname(host);
939 *p = '.';
940#if NAMED_BIND
941 _res.options = oldopts;
942#endif
943 }
944 }
945gothostent:
946 if (hp == NULL)
947 {
948#if NAMED_BIND
949 /* check for name server timeouts */
950 if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
951 (errno == ECONNREFUSED && UseNameServer))
952 {
953 mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
954 return EX_TEMPFAIL;
955 }
956#endif
957 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
958 return (EX_NOHOST);
959 }
960 addr.sa.sa_family = hp->h_addrtype;
961 switch (hp->h_addrtype)
962 {
963#if NETINET
964 case AF_INET:
965 bcopy(hp->h_addr,
966 &addr.sin.sin_addr,
967 INADDRSZ);
968 break;
969#endif
970
971 default:
972 if (hp->h_length > sizeof addr.sa.sa_data)
973 {
974 syserr("makeconnection: long sa_data: family %d len %d",
975 hp->h_addrtype, hp->h_length);
976 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
977 return EX_NOHOST;
978 }
979 bcopy(hp->h_addr,
980 addr.sa.sa_data,
981 hp->h_length);
982 break;
983 }
984 addrno = 1;
985 }
986
987 /*
988 ** Determine the port number.
989 */
990
991 if (port == 0)
992 {
993 register struct servent *sp = getservbyname("smtp", "tcp");
994
995 if (sp == NULL)
996 {
997 if (LogLevel > 2)
998 sm_syslog(LOG_ERR, NOQID,
999 "makeconnection: service \"smtp\" unknown");
1000 port = htons(25);
1001 }
1002 else
1003 port = sp->s_port;
1004 }
1005
1006 switch (addr.sa.sa_family)
1007 {
1008#if NETINET
1009 case AF_INET:
1010 addr.sin.sin_port = port;
1011 addrlen = sizeof (struct sockaddr_in);
1012 break;
1013#endif
1014
1015#if NETISO
1016 case AF_ISO:
1017 /* assume two byte transport selector */
1018 bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2);
1019 addrlen = sizeof (struct sockaddr_iso);
1020 break;
1021#endif
1022
1023 default:
1024 syserr("Can't connect to address family %d", addr.sa.sa_family);
1025 mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
1026 return (EX_NOHOST);
1027 }
1028
1029 /*
1030 ** Try to actually open the connection.
1031 */
1032
1033#ifdef XLA
1034 /* if too many connections, don't bother trying */
1035 if (!xla_noqueue_ok(host))
1036 return EX_TEMPFAIL;
1037#endif
1038
1039 firstconnect = TRUE;
1040 for (;;)
1041 {
1042 if (tTd(16, 1))
1043 printf("makeconnection (%s [%s])\n",
1044 host, anynet_ntoa(&addr));
1045
1046 /* save for logging */
1047 CurHostAddr = addr;
1048
1049 if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
1050 {
1051 int rport = IPPORT_RESERVED - 1;
1052
1053 s = rresvport(&rport);
1054 }
1055 else
1056 {
1057 s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
1058 }
1059 if (s < 0)
1060 {
1061 sav_errno = errno;
1062 syserr("makeconnection: cannot create socket");
1063#ifdef XLA
1064 xla_host_end(host);
1065#endif
1066 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
1067 return EX_TEMPFAIL;
1068 }
1069
1070#ifdef SO_SNDBUF
1071 if (TcpSndBufferSize > 0)
1072 {
1073 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1074 (char *) &TcpSndBufferSize,
1075 sizeof(TcpSndBufferSize)) < 0)
1076 syserr("makeconnection: setsockopt(SO_SNDBUF)");
1077 }
1078#endif
1079
1080 if (tTd(16, 1))
1081 printf("makeconnection: fd=%d\n", s);
1082
1083 /* turn on network debugging? */
1084 if (tTd(16, 101))
1085 {
1086 int on = 1;
1087 (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
1088 (char *)&on, sizeof on);
1089 }
1090 if (e->e_xfp != NULL)
1091 (void) fflush(e->e_xfp); /* for debugging */
1092 errno = 0; /* for debugging */
1093
1094 /*
1095 ** Linux seems to hang in connect for 90 minutes (!!!).
1096 ** Time out the connect to avoid this problem.
1097 */
1098
1099 if (setjmp(CtxConnectTimeout) == 0)
1100 {
1101 int i;
1102
1103 if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
1104 ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
1105 else if (TimeOuts.to_connect != 0)
1106 ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
1107 else
1108 ev = NULL;
1109
1110#if _FFR_CONNECTONLYTO_OPTION
1111 /* for testing */
1112 if (ConnectOnlyTo != 0)
1113 addr.sin.sin_addr.s_addr = ConnectOnlyTo;
1114#endif
1115 i = connect(s, (struct sockaddr *) &addr, addrlen);
1116 sav_errno = errno;
1117 if (ev != NULL)
1118 clrevent(ev);
1119 if (i >= 0)
1120 break;
1121 }
1122 else
1123 sav_errno = errno;
1124
1125 /* if running demand-dialed connection, try again */
1126 if (DialDelay > 0 && firstconnect)
1127 {
1128 if (tTd(16, 1))
1129 printf("Connect failed (%s); trying again...\n",
1130 errstring(sav_errno));
1131 firstconnect = FALSE;
1132 sleep(DialDelay);
1133 continue;
1134 }
1135
1136 /* couldn't connect.... figure out why */
1137 (void) close(s);
1138
1139 if (LogLevel >= 14)
1140 sm_syslog(LOG_INFO, e->e_id,
1141 "makeconnection (%s [%s]) failed: %s",
1142 host, anynet_ntoa(&addr),
1143 errstring(sav_errno));
1144
1145 if (hp != NULL && hp->h_addr_list[addrno] != NULL)
1146 {
1147 if (tTd(16, 1))
1148 printf("Connect failed (%s); trying new address....\n",
1149 errstring(sav_errno));
1150 switch (addr.sa.sa_family)
1151 {
1152#if NETINET
1153 case AF_INET:
1154 bcopy(hp->h_addr_list[addrno++],
1155 &addr.sin.sin_addr,
1156 INADDRSZ);
1157 break;
1158#endif
1159
1160 default:
1161 bcopy(hp->h_addr_list[addrno++],
1162 addr.sa.sa_data,
1163 hp->h_length);
1164 break;
1165 }
1166 continue;
1167 }
1168
1169 /* couldn't open connection */
1170#ifdef XLA
1171 xla_host_end(host);
1172#endif
1173 mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
1174 return EX_TEMPFAIL;
1175 }
1176
1177 /* connection ok, put it into canonical form */
1178 if ((mci->mci_out = fdopen(s, "w")) == NULL ||
1179 (s = dup(s)) < 0 ||
1180 (mci->mci_in = fdopen(s, "r")) == NULL)
1181 {
1182 syserr("cannot open SMTP client channel, fd=%d", s);
1183 mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
1184 return EX_TEMPFAIL;
1185 }
1186
1187 mci_setstat(mci, EX_OK, NULL, NULL);
1188 return (EX_OK);
1189}
1190 /*
1191** MYHOSTNAME -- return the name of this host.
1192**
1193** Parameters:
1194** hostbuf -- a place to return the name of this host.
1195** size -- the size of hostbuf.
1196**
1197** Returns:
1198** A list of aliases for this host.
1199**
1200** Side Effects:
1201** Adds numeric codes to $=w.
1202*/
1203
1204struct hostent *
1205myhostname(hostbuf, size)
1206 char hostbuf[];
1207 int size;
1208{
1209 register struct hostent *hp;
1210
1211 if (gethostname(hostbuf, size) < 0)
1212 {
1213 (void) strcpy(hostbuf, "localhost");
1214 }
1215 hp = sm_gethostbyname(hostbuf);
1216 if (hp == NULL)
1217 return NULL;
1218 if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
1219 {
1220 (void) strncpy(hostbuf, hp->h_name, size - 1);
1221 hostbuf[size - 1] = '\0';
1222 }
1223
1224 /*
1225 ** If there is still no dot in the name, try looking for a
1226 ** dotted alias.
1227 */
1228
1229 if (strchr(hostbuf, '.') == NULL)
1230 {
1231 char **ha;
1232
1233 for (ha = hp->h_aliases; *ha != NULL; ha++)
1234 {
1235 if (strchr(*ha, '.') != NULL)
1236 {
1237 (void) strncpy(hostbuf, *ha, size - 1);
1238 hostbuf[size - 1] = '\0';
1239 break;
1240 }
1241 }
1242 }
1243
1244 /*
1245 ** If _still_ no dot, wait for a while and try again -- it is
1246 ** possible that some service is starting up. This can result
1247 ** in excessive delays if the system is badly configured, but
1248 ** there really isn't a way around that, particularly given that
1249 ** the config file hasn't been read at this point.
1250 ** All in all, a bit of a mess.
1251 */
1252
1253 if (strchr(hostbuf, '.') == NULL &&
1254 !getcanonname(hostbuf, size, TRUE))
1255 {
1256 sm_syslog(LOG_CRIT, NOQID,
1257 "My unqualified host name (%s) unknown; sleeping for retry",
1258 hostbuf);
1259 message("My unqualified host name (%s) unknown; sleeping for retry",
1260 hostbuf);
1261 sleep(60);
1262 if (!getcanonname(hostbuf, size, TRUE))
1263 {
1264 sm_syslog(LOG_ALERT, NOQID,
1265 "unable to qualify my own domain name (%s) -- using short name",
1266 hostbuf);
1267 message("WARNING: unable to qualify my own domain name (%s) -- using short name",
1268 hostbuf);
1269 }
1270 }
1271 return (hp);
1272}
1273 /*
1274** ADDRCMP -- compare two host addresses
1275**
1276** Parameters:
1277** hp -- hostent structure for the first address
1278** ha -- actual first address
1279** sa -- second address
1280**
1281** Returns:
1282** 0 -- if ha and sa match
1283** else -- they don't match
1284*/
1285
1286int
1287addrcmp(hp, ha, sa)
1288 struct hostent *hp;
1289 char *ha;
1290 SOCKADDR *sa;
1291{
1292 switch (sa->sa.sa_family)
1293 {
1294 case AF_INET:
1295 if (hp->h_addrtype == AF_INET)
1296 return bcmp(ha, (char *) &sa->sin.sin_addr, hp->h_length);
1297 break;
1298
1299 }
1300 return -1;
1301}
1302 /*
1303** GETAUTHINFO -- get the real host name asociated with a file descriptor
1304**
1305** Uses RFC1413 protocol to try to get info from the other end.
1306**
1307** Parameters:
1308** fd -- the descriptor
1309** may_be_forged -- an outage that is set to TRUE if the
1310** forward lookup of RealHostName does not match
1311** RealHostAddr; set to FALSE if they do match.
1312**
1313** Returns:
1314** The user@host information associated with this descriptor.
1315*/
1316
1317static jmp_buf CtxAuthTimeout;
1318
1319static void
1320authtimeout()
1321{
1322 longjmp(CtxAuthTimeout, 1);
1323}
1324
1325char *
1326getauthinfo(fd, may_be_forged)
1327 int fd;
1328 bool *may_be_forged;
1329{
1330 SOCKADDR_LEN_T falen;
1331 register char *volatile p = NULL;
1332 SOCKADDR la;
1333 SOCKADDR_LEN_T lalen;
1334 register struct servent *sp;
1335 volatile int s;
1336 int i = 0;
1337 EVENT *ev;
1338 int nleft;
1339 struct hostent *hp;
1340 char *ostype = NULL;
1341 char **ha;
1342 char ibuf[MAXNAME + 1];
1343 static char hbuf[MAXNAME * 2 + 11];
1344
1345 *may_be_forged = FALSE;
1346 falen = sizeof RealHostAddr;
1347 if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
1348 falen <= 0 || RealHostAddr.sa.sa_family == 0)
1349 {
1350 if (i < 0 && errno != ENOTSOCK)
1351 return NULL;
1352 (void) snprintf(hbuf, sizeof hbuf, "%s@localhost",
1353 RealUserName);
1354 if (tTd(9, 1))
1355 printf("getauthinfo: %s\n", hbuf);
1356 return hbuf;
1357 }
1358
1359 if (RealHostName == NULL)
1360 {
1361 /* translate that to a host name */
1362 RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
1363 if (strlen(RealHostName) > MAXNAME)
1364 RealHostName[MAXNAME] = '\0';
1365 }
1366
1367 /* cross check RealHostName with forward DNS lookup */
1368 if (anynet_ntoa(&RealHostAddr)[0] == '[' ||
1369 RealHostName[0] == '[')
1370 {
1371 /*
1372 ** address is not a socket or have an
1373 ** IP address with no forward lookup
1374 */
1375 *may_be_forged = FALSE;
1376 }
1377 else
1378 {
1379 /* try to match the reverse against the forward lookup */
1380 hp = sm_gethostbyname(RealHostName);
1381
1382 if (hp == NULL)
1383 *may_be_forged = TRUE;
1384 else
1385 {
1386 for (ha = hp->h_addr_list; *ha != NULL; ha++)
1387 if (addrcmp(hp, *ha, &RealHostAddr) == 0)
1388 break;
1389 *may_be_forged = *ha == NULL;
1390 }
1391 }
1392
1393 if (TimeOuts.to_ident == 0)
1394 goto noident;
1395
1396 lalen = sizeof la;
1397 if (RealHostAddr.sa.sa_family != AF_INET ||
1398 getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 ||
1399 la.sa.sa_family != AF_INET)
1400 {
1401 /* no ident info */
1402 goto noident;
1403 }
1404
1405 /* create ident query */
1406 (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n",
1407 ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port));
1408
1409 /* create local address */
1410 la.sin.sin_port = 0;
1411
1412 /* create foreign address */
1413 sp = getservbyname("auth", "tcp");
1414 if (sp != NULL)
1415 RealHostAddr.sin.sin_port = sp->s_port;
1416 else
1417 RealHostAddr.sin.sin_port = htons(113);
1418
1419 s = -1;
1420 if (setjmp(CtxAuthTimeout) != 0)
1421 {
1422 if (s >= 0)
1423 (void) close(s);
1424 goto noident;
1425 }
1426
1427 /* put a timeout around the whole thing */
1428 ev = setevent(TimeOuts.to_ident, authtimeout, 0);
1429
1430 /* connect to foreign IDENT server using same address as SMTP socket */
1431 s = socket(AF_INET, SOCK_STREAM, 0);
1432 if (s < 0)
1433 {
1434 clrevent(ev);
1435 goto noident;
1436 }
1437 if (bind(s, &la.sa, sizeof la.sin) < 0 ||
1438 connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0)
1439 {
1440 goto closeident;
1441 }
1442
1443 if (tTd(9, 10))
1444 printf("getauthinfo: sent %s", ibuf);
1445
1446 /* send query */
1447 if (write(s, ibuf, strlen(ibuf)) < 0)
1448 goto closeident;
1449
1450 /* get result */
1451 p = &ibuf[0];
1452 nleft = sizeof ibuf - 1;
1453 while ((i = read(s, p, nleft)) > 0)
1454 {
1455 p += i;
1456 nleft -= i;
1457 *p = '\0';
1458 if (strchr(ibuf, '\n') != NULL)
1459 break;
1460 }
1461 (void) close(s);
1462 clrevent(ev);
1463 if (i < 0 || p == &ibuf[0])
1464 goto noident;
1465
1466 if (*--p == '\n' && *--p == '\r')
1467 p--;
1468 *++p = '\0';
1469
1470 if (tTd(9, 3))
1471 printf("getauthinfo: got %s\n", ibuf);
1472
1473 /* parse result */
1474 p = strchr(ibuf, ':');
1475 if (p == NULL)
1476 {
1477 /* malformed response */
1478 goto noident;
1479 }
1480 while (isascii(*++p) && isspace(*p))
1481 continue;
1482 if (strncasecmp(p, "userid", 6) != 0)
1483 {
1484 /* presumably an error string */
1485 goto noident;
1486 }
1487 p += 6;
1488 while (isascii(*p) && isspace(*p))
1489 p++;
1490 if (*p++ != ':')
1491 {
1492 /* either useridxx or malformed response */
1493 goto noident;
1494 }
1495
1496 /* p now points to the OSTYPE field */
1497 while (isascii(*p) && isspace(*p))
1498 p++;
1499 ostype = p;
1500 p = strchr(p, ':');
1501 if (p == NULL)
1502 {
1503 /* malformed response */
1504 goto noident;
1505 }
1506 else
1507 {
1508 char *charset;
1509
1510 *p = '\0';
1511 charset = strchr(ostype, ',');
1512 if (charset != NULL)
1513 *charset = '\0';
1514 }
1515
1516 /* 1413 says don't do this -- but it's broken otherwise */
1517 while (isascii(*++p) && isspace(*p))
1518 continue;
1519
1520 /* p now points to the authenticated name -- copy carefully */
1521 if (strncasecmp(ostype, "other", 5) == 0 &&
1522 (ostype[5] == ' ' || ostype[5] == '\0'))
1523 {
1524 snprintf(hbuf, sizeof hbuf, "IDENT:");
1525 cleanstrcpy(&hbuf[6], p, MAXNAME);
1526 }
1527 else
1528 cleanstrcpy(hbuf, p, MAXNAME);
1529 i = strlen(hbuf);
1530 snprintf(&hbuf[i], sizeof hbuf - i, "@%s",
1531 RealHostName == NULL ? "localhost" : RealHostName);
1532 goto postident;
1533
1534closeident:
1535 (void) close(s);
1536 clrevent(ev);
1537
1538noident:
1539 if (RealHostName == NULL)
1540 {
1541 if (tTd(9, 1))
1542 printf("getauthinfo: NULL\n");
1543 return NULL;
1544 }
1545 snprintf(hbuf, sizeof hbuf, "%s", RealHostName);
1546
1547postident:
1548#if IP_SRCROUTE
1549# ifndef GET_IPOPT_DST
1550# define GET_IPOPT_DST(dst) (dst)
1551# endif
1552 /*
1553 ** Extract IP source routing information.
1554 **
1555 ** Format of output for a connection from site a through b
1556 ** through c to d:
1557 ** loose: @site-c@site-b:site-a
1558 ** strict: !@site-c@site-b:site-a
1559 **
1560 ** o - pointer within ipopt_list structure.
1561 ** q - pointer within ls/ss rr route data
1562 ** p - pointer to hbuf
1563 */
1564
1565 if (RealHostAddr.sa.sa_family == AF_INET)
1566 {
1567 SOCKOPT_LEN_T ipoptlen;
1568 int j;
1569 u_char *q;
1570 u_char *o;
1571 int l;
1572 struct in_addr addr;
1573 struct ipoption ipopt;
1574
1575 ipoptlen = sizeof ipopt;
1576 if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
1577 (char *) &ipopt, &ipoptlen) < 0)
1578 goto noipsr;
1579 if (ipoptlen == 0)
1580 goto noipsr;
1581 o = (u_char *) ipopt.ipopt_list;
1582 while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
1583 {
1584 switch (*o)
1585 {
1586 case IPOPT_EOL:
1587 o = NULL;
1588 break;
1589
1590 case IPOPT_NOP:
1591 o++;
1592 break;
1593
1594 case IPOPT_SSRR:
1595 case IPOPT_LSRR:
1596 /*
1597 ** Source routing.
1598 ** o[0] is the option type (loose/strict).
1599 ** o[1] is the length of this option,
1600 ** including option type and
1601 ** length.
1602 ** o[2] is the pointer into the route
1603 ** data.
1604 ** o[3] begins the route data.
1605 */
1606
1607 p = &hbuf[strlen(hbuf)];
1608 l = sizeof hbuf - (hbuf - p) - 6;
1609 snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
1610 *o == IPOPT_SSRR ? "!" : "",
1611 l > 240 ? 120 : l / 2,
1612 inet_ntoa(GET_IPOPT_DST(ipopt.ipopt_dst)));
1613 i = strlen(p);
1614 p += i;
1615 l -= strlen(p);
1616
1617 j = o[1] / sizeof(struct in_addr) - 1;
1618
1619 /* q skips length and router pointer to data */
1620 q = &o[3];
1621 for ( ; j >= 0; j--)
1622 {
1623 memcpy(&addr, q, sizeof(addr));
1624 snprintf(p, SPACELEFT(hbuf, p),
1625 "%c%.*s",
1626 j != 0 ? '@' : ':',
1627 l > 240 ? 120 :
1628 j == 0 ? l : l / 2,
1629 inet_ntoa(addr));
1630 i = strlen(p);
1631 p += i;
1632 l -= i + 1;
1633 q += sizeof(struct in_addr);
1634 }
1635 o += o[1];
1636 break;
1637
1638 default:
1639 /* Skip over option */
1640 o += o[1];
1641 break;
1642 }
1643 }
1644 snprintf(p, SPACELEFT(hbuf, p), "]");
1645 goto postipsr;
1646 }
1647
1648noipsr:
1649#endif
1650 if (RealHostName != NULL && RealHostName[0] != '[')
1651 {
1652 p = &hbuf[strlen(hbuf)];
1653 (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
1654 anynet_ntoa(&RealHostAddr));
1655 }
1656 if (*may_be_forged)
1657 {
1658 p = &hbuf[strlen(hbuf)];
1659 (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
1660 }
1661
1662#if IP_SRCROUTE
1663postipsr:
1664#endif
1665 if (tTd(9, 1))
1666 printf("getauthinfo: %s\n", hbuf);
1667 return hbuf;
1668}
1669 /*
1670** HOST_MAP_LOOKUP -- turn a hostname into canonical form
1671**
1672** Parameters:
1673** map -- a pointer to this map.
1674** name -- the (presumably unqualified) hostname.
1675** av -- unused -- for compatibility with other mapping
1676** functions.
1677** statp -- an exit status (out parameter) -- set to
1678** EX_TEMPFAIL if the name server is unavailable.
1679**
1680** Returns:
1681** The mapping, if found.
1682** NULL if no mapping found.
1683**
1684** Side Effects:
1685** Looks up the host specified in hbuf. If it is not
1686** the canonical name for that host, return the canonical
1687** name (unless MF_MATCHONLY is set, which will cause the
1688** status only to be returned).
1689*/
1690
1691char *
1692host_map_lookup(map, name, av, statp)
1693 MAP *map;
1694 char *name;
1695 char **av;
1696 int *statp;
1697{
1698 register struct hostent *hp;
1699 struct in_addr in_addr;
1700 char *cp;
1701 register STAB *s;
1702 char hbuf[MAXNAME + 1];
1703
1704 /*
1705 ** See if we have already looked up this name. If so, just
1706 ** return it.
1707 */
1708
1709 s = stab(name, ST_NAMECANON, ST_ENTER);
1710 if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
1711 {
1712 if (tTd(9, 1))
1713 printf("host_map_lookup(%s) => CACHE %s\n",
1714 name,
1715 s->s_namecanon.nc_cname == NULL
1716 ? "NULL"
1717 : s->s_namecanon.nc_cname);
1718 errno = s->s_namecanon.nc_errno;
1719#if NAMED_BIND
1720 h_errno = s->s_namecanon.nc_herrno;
1721#endif
1722 *statp = s->s_namecanon.nc_stat;
1723 if (*statp == EX_TEMPFAIL)
1724 {
1725 CurEnv->e_status = "4.4.3";
1726 message("851 %s: Name server timeout",
1727 shortenstring(name, 33));
1728 }
1729 if (*statp != EX_OK)
1730 return NULL;
1731 if (s->s_namecanon.nc_cname == NULL)
1732 {
1733 syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d",
1734 name,
1735 s->s_namecanon.nc_errno,
1736 s->s_namecanon.nc_herrno);
1737 return NULL;
1738 }
1739 if (bitset(MF_MATCHONLY, map->map_mflags))
1740 cp = map_rewrite(map, name, strlen(name), NULL);
1741 else
1742 cp = map_rewrite(map,
1743 s->s_namecanon.nc_cname,
1744 strlen(s->s_namecanon.nc_cname),
1745 av);
1746 return cp;
1747 }
1748
1749 /*
1750 ** If we are running without a regular network connection (usually
1751 ** dial-on-demand) and we are just queueing, we want to avoid DNS
1752 ** lookups because those could try to connect to a server.
1753 */
1754
1755 if (CurEnv->e_sendmode == SM_DEFER)
1756 {
1757 if (tTd(9, 1))
1758 printf("host_map_lookup(%s) => DEFERRED\n", name);
1759 *statp = EX_TEMPFAIL;
1760 return NULL;
1761 }
1762
1763 /*
1764 ** If first character is a bracket, then it is an address
1765 ** lookup. Address is copied into a temporary buffer to
1766 ** strip the brackets and to preserve name if address is
1767 ** unknown.
1768 */
1769
1770 if (*name != '[')
1771 {
1772 if (tTd(9, 1))
1773 printf("host_map_lookup(%s) => ", name);
1774 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
1775 snprintf(hbuf, sizeof hbuf, "%s", name);
1776 if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
1777 {
1778 if (tTd(9, 1))
1779 printf("%s\n", hbuf);
1780 s->s_namecanon.nc_stat = EX_OK;
1781 s->s_namecanon.nc_cname = newstr(hbuf);
1782 if (bitset(MF_MATCHONLY, map->map_mflags))
1783 cp = map_rewrite(map, name, strlen(name), NULL);
1784 else
1785 cp = map_rewrite(map, hbuf, strlen(hbuf), av);
1786 return cp;
1787 }
1788 else
1789 {
1790 s->s_namecanon.nc_errno = errno;
1791#if NAMED_BIND
1792 s->s_namecanon.nc_herrno = h_errno;
1793 if (tTd(9, 1))
1794 printf("FAIL (%d)\n", h_errno);
1795 switch (h_errno)
1796 {
1797 case TRY_AGAIN:
1798 if (UseNameServer)
1799 {
1800 CurEnv->e_status = "4.4.3";
1801 message("851 %s: Name server timeout",
1802 shortenstring(name, 33));
1803 }
1804 *statp = EX_TEMPFAIL;
1805 break;
1806
1807 case HOST_NOT_FOUND:
1808 case NO_DATA:
1809 *statp = EX_NOHOST;
1810 break;
1811
1812 case NO_RECOVERY:
1813 *statp = EX_SOFTWARE;
1814 break;
1815
1816 default:
1817 *statp = EX_UNAVAILABLE;
1818 break;
1819 }
1820#else
1821 if (tTd(9, 1))
1822 printf("FAIL\n");
1823 *statp = EX_NOHOST;
1824#endif
1825 s->s_namecanon.nc_stat = *statp;
1826 return NULL;
1827 }
1828 }
1829 if ((cp = strchr(name, ']')) == NULL)
1830 return (NULL);
1831 *cp = '\0';
1832 in_addr.s_addr = inet_addr(&name[1]);
1833 *cp = ']';
1834
1835 /* nope -- ask the name server */
1836 hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET);
1837 s->s_namecanon.nc_errno = errno;
1838#if NAMED_BIND
1839 s->s_namecanon.nc_herrno = h_errno;
1840#endif
1841 s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
1842 if (hp == NULL)
1843 {
1844 s->s_namecanon.nc_stat = *statp = EX_NOHOST;
1845 return (NULL);
1846 }
1847
1848 /* found a match -- copy out */
1849 hp->h_name = denlstring((char *) hp->h_name, TRUE, TRUE);
1850 s->s_namecanon.nc_stat = *statp = EX_OK;
1851 s->s_namecanon.nc_cname = newstr(hp->h_name);
1852 if (bitset(MF_MATCHONLY, map->map_mflags))
1853 cp = map_rewrite(map, name, strlen(name), NULL);
1854 else
1855 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
1856 return cp;
1857}
1858
1859# else /* DAEMON */
1860/* code for systems without sophisticated networking */
1861
1862/*
1863** MYHOSTNAME -- stub version for case of no daemon code.
1864**
1865** Can't convert to upper case here because might be a UUCP name.
1866**
1867** Mark, you can change this to be anything you want......
1868*/
1869
1870char **
1871myhostname(hostbuf, size)
1872 char hostbuf[];
1873 int size;
1874{
1875 register FILE *f;
1876
1877 hostbuf[0] = '\0';
1878 f = fopen("/usr/include/whoami", "r");
1879 if (f != NULL)
1880 {
1881 (void) fgets(hostbuf, size, f);
1882 fixcrlf(hostbuf, TRUE);
1883 (void) fclose(f);
1884 }
1885 return (NULL);
1886}
1887 /*
1888** GETAUTHINFO -- get the real host name asociated with a file descriptor
1889**
1890** Parameters:
1891** fd -- the descriptor
1892** may_be_forged -- an outage that is set to TRUE if the
1893** forward lookup of RealHostName does not match
1894** RealHostAddr; set to FALSE if they do match.
1895**
1896** Returns:
1897** The host name associated with this descriptor, if it can
1898** be determined.
1899** NULL otherwise.
1900**
1901** Side Effects:
1902** none
1903*/
1904
1905char *
1906getauthinfo(fd, may_be_forged)
1907 int fd;
1908 bool *may_be_forged;
1909{
1910 *may_be_forged = FALSE;
1911 return NULL;
1912}
1913 /*
1914** MAPHOSTNAME -- turn a hostname into canonical form
1915**
1916** Parameters:
1917** map -- a pointer to the database map.
1918** name -- a buffer containing a hostname.
1919** avp -- a pointer to a (cf file defined) argument vector.
1920** statp -- an exit status (out parameter).
1921**
1922** Returns:
1923** mapped host name
1924** FALSE otherwise.
1925**
1926** Side Effects:
1927** Looks up the host specified in name. If it is not
1928** the canonical name for that host, replace it with
1929** the canonical name. If the name is unknown, or it
1930** is already the canonical name, leave it unchanged.
1931*/
1932
1933/*ARGSUSED*/
1934char *
1935host_map_lookup(map, name, avp, statp)
1936 MAP *map;
1937 char *name;
1938 char **avp;
1939 char *statp;
1940{
1941 register struct hostent *hp;
1942 char *cp;
1943
1944 hp = sm_gethostbyname(name);
1945 if (hp == NULL)
1946 {
1947 *statp = EX_NOHOST;
1948 return NULL;
1949 }
1950 if (bitset(MF_MATCHONLY, map->map_mflags))
1951 cp = map_rewrite(map, name, strlen(name), NULL);
1952 else
1953 cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp);
1954 return cp;
1955}
1956
1957#endif /* DAEMON */
1958 /*
1959** HOST_MAP_INIT -- initialize host class structures
1960*/
1961
1962bool
1963host_map_init(map, args)
1964 MAP *map;
1965 char *args;
1966{
1967 register char *p = args;
1968
1969 for (;;)
1970 {
1971 while (isascii(*p) && isspace(*p))
1972 p++;
1973 if (*p != '-')
1974 break;
1975 switch (*++p)
1976 {
1977 case 'a':
1978 map->map_app = ++p;
1979 break;
1980
1981 case 'T':
1982 map->map_tapp = ++p;
1983 break;
1984
1985 case 'm':
1986 map->map_mflags |= MF_MATCHONLY;
1987 break;
1988
1989 case 't':
1990 map->map_mflags |= MF_NODEFER;
1991 break;
1992 }
1993 while (*p != '\0' && !(isascii(*p) && isspace(*p)))
1994 p++;
1995 if (*p != '\0')
1996 *p++ = '\0';
1997 }
1998 if (map->map_app != NULL)
1999 map->map_app = newstr(map->map_app);
2000 if (map->map_tapp != NULL)
2001 map->map_tapp = newstr(map->map_tapp);
2002 return TRUE;
2003}
2004 /*
2005** ANYNET_NTOA -- convert a network address to printable form.
2006**
2007** Parameters:
2008** sap -- a pointer to a sockaddr structure.
2009**
2010** Returns:
2011** A printable version of that sockaddr.
2012*/
2013
2014#ifdef USE_SOCK_STREAM
2015
2016#if NETLINK
2017# include <net/if_dl.h>
2018#endif
2019
2020char *
2021anynet_ntoa(sap)
2022 register SOCKADDR *sap;
2023{
2024 register char *bp;
2025 register char *ap;
2026 int l;
2027 static char buf[100];
2028
2029 /* check for null/zero family */
2030 if (sap == NULL)
2031 return "NULLADDR";
2032 if (sap->sa.sa_family == 0)
2033 return "0";
2034
2035 switch (sap->sa.sa_family)
2036 {
2037#if NETUNIX
2038 case AF_UNIX:
2039 if (sap->sunix.sun_path[0] != '\0')
2040 snprintf(buf, sizeof buf, "[UNIX: %.64s]",
2041 sap->sunix.sun_path);
2042 else
2043 snprintf(buf, sizeof buf, "[UNIX: localhost]");
2044 return buf;
2045#endif
2046
2047#if NETINET
2048 case AF_INET:
2049 return inet_ntoa(sap->sin.sin_addr);
2050#endif
2051
2052#if NETLINK
2053 case AF_LINK:
2054 snprintf(buf, sizeof buf, "[LINK: %s]",
2055 link_ntoa((struct sockaddr_dl *) &sap->sa));
2056 return buf;
2057#endif
2058 default:
2059 /* this case is needed when nothing is #defined */
2060 /* in order to keep the switch syntactically correct */
2061 break;
2062 }
2063
2064 /* unknown family -- just dump bytes */
2065 (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family);
2066 bp = &buf[strlen(buf)];
2067 ap = sap->sa.sa_data;
2068 for (l = sizeof sap->sa.sa_data; --l >= 0; )
2069 {
2070 (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377);
2071 bp += 3;
2072 }
2073 *--bp = '\0';
2074 return buf;
2075}
2076 /*
2077** HOSTNAMEBYANYADDR -- return name of host based on address
2078**
2079** Parameters:
2080** sap -- SOCKADDR pointer
2081**
2082** Returns:
2083** text representation of host name.
2084**
2085** Side Effects:
2086** none.
2087*/
2088
2089char *
2090hostnamebyanyaddr(sap)
2091 register SOCKADDR *sap;
2092{
2093 register struct hostent *hp;
2094 int saveretry;
2095
2096#if NAMED_BIND
2097 /* shorten name server timeout to avoid higher level timeouts */
2098 saveretry = _res.retry;
2099 _res.retry = 3;
2100#endif /* NAMED_BIND */
2101
2102 switch (sap->sa.sa_family)
2103 {
2104#if NETINET
2105 case AF_INET:
2106 hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
2107 INADDRSZ,
2108 AF_INET);
2109 break;
2110#endif
2111
2112#if NETISO
2113 case AF_ISO:
2114 hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
2115 sizeof sap->siso.siso_addr,
2116 AF_ISO);
2117 break;
2118#endif
2119
2120#if NETUNIX
2121 case AF_UNIX:
2122 hp = NULL;
2123 break;
2124#endif
2125
2126 default:
2127 hp = sm_gethostbyaddr(sap->sa.sa_data,
2128 sizeof sap->sa.sa_data,
2129 sap->sa.sa_family);
2130 break;
2131 }
2132
2133#if NAMED_BIND
2134 _res.retry = saveretry;
2135#endif /* NAMED_BIND */
2136
2137 if (hp != NULL && hp->h_name[0] != '[' &&
2138 inet_addr(hp->h_name) == INADDR_NONE)
2139 return denlstring((char *) hp->h_name, TRUE, TRUE);
2140#if NETUNIX
2141 else if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0')
2142 return "localhost";
2143#endif
2144 else
2145 {
2146 /* produce a dotted quad */
2147 static char buf[203];
2148
2149 (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap));
2150 return buf;
2151 }
2152}
2153
2154#endif /* SOCK_STREAM */