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