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