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