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