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