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