daemon.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:72k
源码类别:

Email客户端

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #include <sendmail.h>
  14. #ifndef lint
  15. # ifdef DAEMON
  16. static char id[] = "@(#)$Id: daemon.c,v 8.387 1999/12/03 03:40:28 gshapiro Exp $ (with daemon mode)";
  17. # else /* DAEMON */
  18. static char id[] = "@(#)$Id: daemon.c,v 8.387 1999/12/03 03:40:28 gshapiro Exp $ (without daemon mode)";
  19. # endif /* DAEMON */
  20. #endif /* ! lint */
  21. #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__)
  22. # define USE_SOCK_STREAM 1
  23. #endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */
  24. #if DAEMON || defined(USE_SOCK_STREAM)
  25. # if NETINET || NETINET6
  26. #  include <arpa/inet.h>
  27. # endif /* NETINET || NETINET6 */
  28. # if NAMED_BIND
  29. #  ifndef NO_DATA
  30. #   define NO_DATA NO_ADDRESS
  31. #  endif /* ! NO_DATA */
  32. # endif /* NAMED_BIND */
  33. #endif /* DAEMON || defined(USE_SOCK_STREAM) */
  34. #if DAEMON
  35. # include <sys/time.h>
  36. # if IP_SRCROUTE && NETINET
  37. #  include <netinet/in_systm.h>
  38. #  include <netinet/ip.h>
  39. #  if HAS_IN_H
  40. #   include <netinet/in.h>
  41. #   ifndef IPOPTION
  42. #    define IPOPTION ip_opts
  43. #    define IP_LIST ip_opts
  44. #    define IP_DST ip_dst
  45. #   endif /* ! IPOPTION */
  46. #  else /* HAS_IN_H */
  47. #   include <netinet/ip_var.h>
  48. #   ifndef IPOPTION
  49. #    define IPOPTION ipoption
  50. #    define IP_LIST ipopt_list
  51. #    define IP_DST ipopt_dst
  52. #   endif /* ! IPOPTION */
  53. #  endif /* HAS_IN_H */
  54. # endif /* IP_SRCROUTE && NETINET */
  55. /* structure to describe a daemon */
  56. struct daemon
  57. {
  58. int d_socket; /* fd for socket */
  59. SOCKADDR d_addr; /* socket for incoming */
  60. u_short d_port; /* port number */
  61. int d_listenqueue; /* size of listen queue */
  62. int d_tcprcvbufsize; /* size of TCP receive buffer */
  63. int d_tcpsndbufsize; /* size of TCP send buffer */
  64. time_t d_refuse_connections_until;
  65. bool d_firsttime;
  66. int d_socksize;
  67. BITMAP256 d_flags; /* flags; see sendmail.h */
  68. char * d_mflags; /* flags for use in macro */
  69. char * d_name; /* user-supplied name */
  70. };
  71. typedef struct daemon DAEMON_T;
  72. static void connecttimeout __P((void));
  73. static int opendaemonsocket __P((struct daemon *, bool));
  74. static u_short setupdaemon __P((SOCKADDR *));
  75. /*
  76. **  DAEMON.C -- routines to use when running as a daemon.
  77. **
  78. ** This entire file is highly dependent on the 4.2 BSD
  79. ** interprocess communication primitives.  No attempt has
  80. ** been made to make this file portable to Version 7,
  81. ** Version 6, MPX files, etc.  If you should try such a
  82. ** thing yourself, I recommend chucking the entire file
  83. ** and starting from scratch.  Basic semantics are:
  84. **
  85. ** getrequests(e)
  86. ** Opens a port and initiates a connection.
  87. ** Returns in a child.  Must set InChannel and
  88. ** OutChannel appropriately.
  89. ** clrdaemon()
  90. ** Close any open files associated with getting
  91. ** the connection; this is used when running the queue,
  92. ** etc., to avoid having extra file descriptors during
  93. ** the queue run and to avoid confusing the network
  94. ** code (if it cares).
  95. ** makeconnection(host, port, outfile, infile, e)
  96. ** Make a connection to the named host on the given
  97. ** port.  Set *outfile and *infile to the files
  98. ** appropriate for communication.  Returns zero on
  99. ** success, else an exit status describing the
  100. ** error.
  101. ** host_map_lookup(map, hbuf, avp, pstat)
  102. ** Convert the entry in hbuf into a canonical form.
  103. */
  104. static DAEMON_T Daemons[MAXDAEMONS];
  105. static int ndaemons = 0; /* actual number of daemons */
  106. /* options for client */
  107. static int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
  108. static int TcpSndBufferSize = 0; /* size of TCP send buffer */
  109. /*
  110. **  GETREQUESTS -- open mail IPC port and get requests.
  111. **
  112. ** Parameters:
  113. ** e -- the current envelope.
  114. **
  115. ** Returns:
  116. ** pointer to flags.
  117. **
  118. ** Side Effects:
  119. ** Waits until some interesting activity occurs.  When
  120. ** it does, a child is created to process it, and the
  121. ** parent waits for completion.  Return from this
  122. ** routine is always in the child.  The file pointers
  123. ** "InChannel" and "OutChannel" should be set to point
  124. ** to the communication channel.
  125. */
  126. BITMAP256 *
  127. getrequests(e)
  128. ENVELOPE *e;
  129. {
  130. int t;
  131. time_t last_disk_space_check = 0;
  132. int idx, curdaemon = -1;
  133. # if XDEBUG
  134. bool j_has_dot;
  135. # endif /* XDEBUG */
  136. char status[MAXLINE];
  137. SOCKADDR sa;
  138. SOCKADDR_LEN_T len = sizeof sa;
  139. # if NETUNIX
  140. extern int ControlSocket;
  141. # endif /* NETUNIX */
  142. extern ENVELOPE BlankEnvelope;
  143. #define D(x,idx) x[idx]
  144. for (idx = 0; idx < ndaemons; idx++)
  145. {
  146. Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr));
  147. Daemons[idx].d_firsttime = TRUE;
  148. Daemons[idx].d_refuse_connections_until = (time_t) 0;
  149. }
  150. /*
  151. **  Try to actually open the connection.
  152. */
  153. if (tTd(15, 1))
  154. {
  155. for (idx = 0; idx < ndaemons; idx++)
  156. dprintf("getrequests: daemon %s: port %dn",
  157. Daemons[idx].d_name,
  158. ntohs(Daemons[idx].d_port));
  159. }
  160. /* get a socket for the SMTP connection */
  161. for (idx = 0; idx < ndaemons; idx++)
  162. Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE);
  163. if (opencontrolsocket() < 0)
  164. sm_syslog(LOG_WARNING, NOQID,
  165.   "daemon could not open control socket %s: %s",
  166.   ControlSocketName, errstring(errno));
  167. (void) setsignal(SIGCHLD, reapchild);
  168. /* write the pid to file */
  169. log_sendmail_pid(e);
  170. # if XDEBUG
  171. {
  172. char jbuf[MAXHOSTNAMELEN];
  173. expand("201j", jbuf, sizeof jbuf, e);
  174. j_has_dot = strchr(jbuf, '.') != NULL;
  175. }
  176. # endif /* XDEBUG */
  177. /* Add parent process as first item */
  178. proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON);
  179. if (tTd(15, 1))
  180. {
  181. for (idx = 0; idx < ndaemons; idx++)
  182. dprintf("getrequests: daemon %s: %dn",
  183. Daemons[idx].d_name,
  184. Daemons[idx].d_socket);
  185. }
  186. for (;;)
  187. {
  188. register pid_t pid;
  189. auto SOCKADDR_LEN_T lotherend;
  190. bool timedout = FALSE;
  191. bool control = FALSE;
  192. int save_errno;
  193. int pipefd[2];
  194. /* see if we are rejecting connections */
  195. (void) blocksignal(SIGALRM);
  196. for (idx = 0; idx < ndaemons; idx++)
  197. {
  198. if (curtime() < Daemons[idx].d_refuse_connections_until)
  199. continue;
  200. if (refuseconnections(Daemons[idx].d_name, e, idx))
  201. {
  202. if (Daemons[idx].d_socket >= 0)
  203. {
  204.        /* close socket so peer fails quickly */
  205.        (void) close(Daemons[idx].d_socket);
  206.        Daemons[idx].d_socket = -1;
  207. }
  208. /* refuse connections for next 15 seconds */
  209. Daemons[idx].d_refuse_connections_until = curtime() + 15;
  210. }
  211. else if (Daemons[idx].d_socket < 0 ||
  212.  Daemons[idx].d_firsttime)
  213. {
  214.       if (!Daemons[idx].d_firsttime && LogLevel >= 9)
  215. sm_syslog(LOG_INFO, NOQID,
  216.   "accepting connections again for daemon %s",
  217.   Daemons[idx].d_name);
  218.       /* arrange to (re)open the socket if needed */
  219.       (void) opendaemonsocket(&Daemons[idx], FALSE);
  220.       Daemons[idx].d_firsttime = FALSE;
  221. }
  222. }
  223. if (curtime() >= last_disk_space_check)
  224. {
  225. if (!enoughdiskspace(MinBlocksFree + 1, FALSE))
  226. {
  227. if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags))
  228. {
  229. /* log only if not logged before */
  230. if (LogLevel >= 9)
  231. sm_syslog(LOG_INFO, NOQID,
  232.   "rejecting new messages: min free: %d",
  233.   MinBlocksFree);
  234. sm_setproctitle(TRUE, e,
  235. "rejecting new messages: min free: %d",
  236.  MinBlocksFree);
  237. setbitn(D_ETRNONLY, Daemons[idx].d_flags);
  238. }
  239. }
  240. else if (bitnset(D_ETRNONLY, Daemons[idx].d_flags))
  241. {
  242. /* log only if not logged before */
  243. if (LogLevel >= 9)
  244. sm_syslog(LOG_INFO, NOQID,
  245.   "accepting new messages (again)");
  246. /* title will be set below */
  247. clrbitn(D_ETRNONLY, Daemons[idx].d_flags);
  248. }
  249. /* only check disk space once a minute */
  250. last_disk_space_check = curtime() + 60;
  251. }
  252. # if XDEBUG
  253. /* check for disaster */
  254. {
  255. char jbuf[MAXHOSTNAMELEN];
  256. expand("201j", jbuf, sizeof jbuf, e);
  257. if (!wordinclass(jbuf, 'w'))
  258. {
  259. dumpstate("daemon lost $j");
  260. sm_syslog(LOG_ALERT, NOQID,
  261.   "daemon process doesn't have $j in $=w; see syslog");
  262. abort();
  263. }
  264. else if (j_has_dot && strchr(jbuf, '.') == NULL)
  265. {
  266. dumpstate("daemon $j lost dot");
  267. sm_syslog(LOG_ALERT, NOQID,
  268.   "daemon process $j lost dot; see syslog");
  269. abort();
  270. }
  271. }
  272. # endif /* XDEBUG */
  273. # if 0
  274. /*
  275. **  Andrew Sun <asun@ieps-sun.ml.com> claims that this will
  276. **  fix the SVr4 problem.  But it seems to have gone away,
  277. **  so is it worth doing this?
  278. */
  279. if (DaemonSocket >= 0 &&
  280.     SetNonBlocking(DaemonSocket, FALSE) < 0)
  281. log an error here;
  282. # endif /* 0 */
  283. (void) releasesignal(SIGALRM);
  284. for (;;)
  285. {
  286. int highest = -1;
  287. fd_set readfds;
  288. struct timeval timeout;
  289. FD_ZERO(&readfds);
  290. for (idx = 0; idx < ndaemons; idx++)
  291. {
  292. /* wait for a connection */
  293. if (Daemons[idx].d_socket >= 0)
  294. {
  295. if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags))
  296. {
  297. sm_setproctitle(TRUE, e,
  298. "accepting connections");
  299. }
  300. if (Daemons[idx].d_socket > highest)
  301. highest = Daemons[idx].d_socket;
  302. FD_SET(Daemons[idx].d_socket, &readfds);
  303. }
  304. }
  305. # if NETUNIX
  306. if (ControlSocket >= 0)
  307. {
  308. if (ControlSocket > highest)
  309. highest = ControlSocket;
  310. FD_SET(ControlSocket, &readfds);
  311. }
  312. # endif /* NETUNIX */
  313. /*
  314. **  if one socket is closed, set the timeout
  315. **  to 5 seconds (so it might get reopened soon),
  316. **  otherwise (all sockets open) 60.
  317. */
  318. idx = 0;
  319. while (idx < ndaemons && Daemons[idx].d_socket >= 0)
  320. idx++;
  321. if (idx < ndaemons)
  322. timeout.tv_sec = 5;
  323. else
  324. timeout.tv_sec = 60;
  325. timeout.tv_usec = 0;
  326. t = select(highest + 1, FDSET_CAST &readfds,
  327.    NULL, NULL, &timeout);
  328. if (DoQueueRun)
  329. (void) runqueue(TRUE, FALSE);
  330. if (t <= 0)
  331. {
  332. timedout = TRUE;
  333. break;
  334. }
  335. control = FALSE;
  336. errno = 0;
  337. curdaemon = -1;
  338. for (idx = 0; idx < ndaemons; idx++)
  339. {
  340. if (Daemons[idx].d_socket >= 0 &&
  341.     FD_ISSET(Daemons[idx].d_socket, &readfds))
  342. {
  343. lotherend = Daemons[idx].d_socksize;
  344. t = accept(Daemons[idx].d_socket,
  345.    (struct sockaddr *)&RealHostAddr,
  346.    &lotherend);
  347. curdaemon = idx;
  348. }
  349. }
  350. # if NETUNIX
  351. if (curdaemon == -1 && ControlSocket >= 0 &&
  352.  FD_ISSET(ControlSocket, &readfds))
  353. {
  354. struct sockaddr_un sa_un;
  355. lotherend = sizeof sa_un;
  356. t = accept(ControlSocket,
  357.    (struct sockaddr *)&sa_un,
  358.    &lotherend);
  359. control = TRUE;
  360. }
  361. # endif /* NETUNIX */
  362. if (t >= 0 || errno != EINTR)
  363. break;
  364. }
  365. if (timedout)
  366. {
  367. timedout = FALSE;
  368. continue;
  369. }
  370. save_errno = errno;
  371. (void) blocksignal(SIGALRM);
  372. if (t < 0)
  373. {
  374. errno = save_errno;
  375. syserr("getrequests: accept");
  376. /* arrange to re-open the socket next time around */
  377. (void) close(Daemons[curdaemon].d_socket);
  378. Daemons[curdaemon].d_socket = -1;
  379. continue;
  380. }
  381. if (!control)
  382. {
  383. /* set some daemon related macros */
  384. switch (Daemons[curdaemon].d_addr.sa.sa_family)
  385. {
  386.   case AF_UNSPEC:
  387. define(macid("{daemon_family}", NULL),
  388.        "unspec", &BlankEnvelope);
  389. break;
  390. # if NETINET
  391.   case AF_INET:
  392. define(macid("{daemon_family}", NULL),
  393.        "inet", &BlankEnvelope);
  394. break;
  395. # endif /* NETINET */
  396. # if NETINET6
  397.   case AF_INET6:
  398. define(macid("{daemon_family}", NULL),
  399.        "inet6", &BlankEnvelope);
  400. break;
  401. # endif /* NETINET6 */
  402. # if NETISO
  403.   case AF_ISO:
  404. define(macid("{daemon_family}", NULL),
  405.        "iso", &BlankEnvelope);
  406. break;
  407. # endif /* NETISO */
  408. # if NETNS
  409.   case AF_NS:
  410. define(macid("{daemon_family}", NULL),
  411.        "ns", &BlankEnvelope);
  412. break;
  413. # endif /* NETNS */
  414. # if NETX25
  415.   case AF_CCITT:
  416. define(macid("{daemon_family}", NULL),
  417.        "x.25", &BlankEnvelope);
  418. break;
  419. # endif /* NETX25 */
  420. }
  421. define(macid("{daemon_name}", NULL),
  422.        Daemons[curdaemon].d_name, &BlankEnvelope);
  423. define(macid("{daemon_addr}", NULL),
  424.        newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)),
  425.        &BlankEnvelope);
  426. (void) snprintf(status, sizeof status, "%d",
  427. ntohs(Daemons[curdaemon].d_port));
  428. define(macid("{daemon_port}", NULL), newstr(status),
  429.        &BlankEnvelope);
  430. if (Daemons[curdaemon].d_mflags != NULL)
  431. define(macid("{daemon_flags}", NULL),
  432.        newstr(Daemons[curdaemon].d_mflags),
  433.        &BlankEnvelope);
  434. else
  435. define(macid("{daemon_flags}", NULL),
  436.        "", &BlankEnvelope);
  437. }
  438. /*
  439. **  Create a subprocess to process the mail.
  440. */
  441. if (tTd(15, 2))
  442. dprintf("getrequests: forking (fd = %d)n", t);
  443. /*
  444. **  Create a pipe to keep the child from writing to the
  445. **  socket until after the parent has closed it.  Otherwise
  446. **  the parent may hang if the child has closed it first.
  447. */
  448. if (pipe(pipefd) < 0)
  449. pipefd[0] = pipefd[1] = -1;
  450. (void) blocksignal(SIGCHLD);
  451. pid = fork();
  452. if (pid < 0)
  453. {
  454. syserr("daemon: cannot fork");
  455. if (pipefd[0] != -1)
  456. {
  457. (void) close(pipefd[0]);
  458. (void) close(pipefd[1]);
  459. }
  460. (void) releasesignal(SIGCHLD);
  461. (void) sleep(10);
  462. (void) close(t);
  463. continue;
  464. }
  465. if (pid == 0)
  466. {
  467. char *p;
  468. FILE *inchannel, *outchannel = NULL;
  469. /*
  470. **  CHILD -- return to caller.
  471. ** Collect verified idea of sending host.
  472. ** Verify calling user id if possible here.
  473. */
  474. (void) releasesignal(SIGALRM);
  475. (void) releasesignal(SIGCHLD);
  476. (void) setsignal(SIGCHLD, SIG_DFL);
  477. (void) setsignal(SIGHUP, intsig);
  478. for (idx = 0; idx < ndaemons; idx++)
  479. {
  480. if (Daemons[idx].d_socket >= 0)
  481. (void) close(Daemons[idx].d_socket);
  482. }
  483. clrcontrol();
  484. /* Avoid SMTP daemon actions if control command */
  485. if (control)
  486. {
  487. /* Add control socket process */
  488. proc_list_add(getpid(), "console socket child",
  489.       PROC_CONTROL_CHILD);
  490. }
  491. else
  492. {
  493. proc_list_clear();
  494. /* Add parent process as first child item */
  495. proc_list_add(getpid(), "daemon child",
  496.       PROC_DAEMON_CHILD);
  497. /* don't schedule queue runs if ETRN */
  498. QueueIntvl = 0;
  499. sm_setproctitle(TRUE, e, "startup with %s",
  500. anynet_ntoa(&RealHostAddr));
  501. }
  502. if (pipefd[0] != -1)
  503. {
  504. auto char c;
  505. /*
  506. **  Wait for the parent to close the write end
  507. **  of the pipe, which we will see as an EOF.
  508. **  This guarantees that we won't write to the
  509. **  socket until after the parent has closed
  510. **  the pipe.
  511. */
  512. /* close the write end of the pipe */
  513. (void) close(pipefd[1]);
  514. /* we shouldn't be interrupted, but ... */
  515. while (read(pipefd[0], &c, 1) < 0 &&
  516.        errno == EINTR)
  517. continue;
  518. (void) close(pipefd[0]);
  519. }
  520. /* control socket processing */
  521. if (control)
  522. {
  523. control_command(t, e);
  524. /* NOTREACHED */
  525. exit(EX_SOFTWARE);
  526. }
  527. /* determine host name */
  528. p = hostnamebyanyaddr(&RealHostAddr);
  529. if (strlen(p) > (SIZE_T) MAXNAME)
  530. p[MAXNAME] = '';
  531. RealHostName = newstr(p);
  532. if (RealHostName[0] == '[')
  533. {
  534. /* TEMP, FAIL: which one? */
  535. define(macid("{client_resolve}", NULL),
  536.        (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL",
  537.        &BlankEnvelope);
  538. }
  539. else
  540. define(macid("{client_resolve}", NULL), "OK",
  541.        &BlankEnvelope);
  542. sm_setproctitle(TRUE, e, "startup with %s", p);
  543. if ((inchannel = fdopen(t, "r")) == NULL ||
  544.     (t = dup(t)) < 0 ||
  545.     (outchannel = fdopen(t, "w")) == NULL)
  546. {
  547. syserr("cannot open SMTP server channel, fd=%d", t);
  548. finis(FALSE, EX_OK);
  549. }
  550. InChannel = inchannel;
  551. OutChannel = outchannel;
  552. DisConnected = FALSE;
  553. # ifdef XLA
  554. if (!xla_host_ok(RealHostName))
  555. {
  556. message("421 4.4.5 Too many SMTP sessions for this host");
  557. finis(FALSE, EX_OK);
  558. }
  559. # endif /* XLA */
  560. /* find out name for interface of connection */
  561. if (getsockname(fileno(InChannel), &sa.sa,
  562. &len) == 0)
  563. {
  564. p = hostnamebyanyaddr(&sa);
  565. if (tTd(15, 9))
  566. dprintf("getreq: got name %sn", p);
  567. define(macid("{if_name}", NULL),
  568.        newstr(p), &BlankEnvelope);
  569. /* do this only if it is not the loopback */
  570. /* interface: how to figure out? XXX */
  571. if (!isloopback(sa))
  572. {
  573. define(macid("{if_addr}", NULL),
  574.        newstr(anynet_ntoa(&sa)),
  575.        &BlankEnvelope);
  576. if (tTd(15, 7))
  577. dprintf("getreq: got addr %sn",
  578. macvalue(macid("{if_addr}", NULL),
  579.  &BlankEnvelope));
  580. p = xalloc(5);
  581. snprintf(p, 4, "%d", sa.sa.sa_family);
  582. define(macid("{if_family}", NULL), p,
  583.        &BlankEnvelope);
  584. }
  585. else
  586. {
  587. define(macid("{if_addr}", NULL), NULL,
  588.        &BlankEnvelope);
  589. define(macid("{if_family}", NULL), NULL,
  590.        &BlankEnvelope);
  591. }
  592. }
  593. else
  594. {
  595. if (tTd(15, 7))
  596. dprintf("getreq: getsockname failedn");
  597. define(macid("{if_name}", NULL), NULL,
  598.        &BlankEnvelope);
  599. define(macid("{if_addr}", NULL), NULL,
  600.        &BlankEnvelope);
  601. define(macid("{if_family}", NULL), NULL,
  602.        &BlankEnvelope);
  603. }
  604. break;
  605. }
  606. /* parent -- keep track of children */
  607. if (control)
  608. {
  609. snprintf(status, sizeof status,
  610.  "control socket server child");
  611. proc_list_add(pid, status, PROC_CONTROL);
  612. }
  613. else
  614. {
  615. snprintf(status, sizeof status,
  616.  "SMTP server child for %s",
  617.  anynet_ntoa(&RealHostAddr));
  618. proc_list_add(pid, status, PROC_DAEMON);
  619. }
  620. (void) releasesignal(SIGCHLD);
  621. /* close the read end of the synchronization pipe */
  622. if (pipefd[0] != -1)
  623. (void) close(pipefd[0]);
  624. /* close the port so that others will hang (for a while) */
  625. (void) close(t);
  626. /* release the child by closing the read end of the sync pipe */
  627. if (pipefd[1] != -1)
  628. (void) close(pipefd[1]);
  629. }
  630. if (tTd(15, 2))
  631. dprintf("getreq: returningn");
  632. return &Daemons[curdaemon].d_flags;
  633. }
  634. /*
  635. **  OPENDAEMONSOCKET -- open SMTP socket
  636. **
  637. ** Deals with setting all appropriate options.
  638. **
  639. ** Parameters:
  640. ** d -- the structure for the daemon to open.
  641. ** firsttime -- set if this is the initial open.
  642. **
  643. ** Returns:
  644. ** Size in bytes of the daemon socket addr.
  645. **
  646. ** Side Effects:
  647. ** Leaves DaemonSocket set to the open socket.
  648. ** Exits if the socket cannot be created.
  649. */
  650. # define MAXOPENTRIES 10 /* maximum number of tries to open connection */
  651. static int
  652. opendaemonsocket(d, firsttime)
  653. struct daemon *d;
  654. bool firsttime;
  655. {
  656. int on = 1;
  657. int fdflags;
  658. SOCKADDR_LEN_T socksize = 0;
  659. int ntries = 0;
  660. int save_errno;
  661. if (tTd(15, 2))
  662. dprintf("opendaemonsocket(%s)n", d->d_name);
  663. do
  664. {
  665. if (ntries > 0)
  666. (void) sleep(5);
  667. if (firsttime || d->d_socket < 0)
  668. {
  669. d->d_socket = socket(d->d_addr.sa.sa_family,
  670.      SOCK_STREAM, 0);
  671. if (d->d_socket < 0)
  672. {
  673. save_errno = errno;
  674. syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name);
  675.   severe:
  676. if (LogLevel > 0)
  677. sm_syslog(LOG_ALERT, NOQID,
  678.   "daemon %s: problem creating SMTP socket", d->d_name);
  679. d->d_socket = -1;
  680. continue;
  681. }
  682. /* turn on network debugging? */
  683. if (tTd(15, 101))
  684. (void) setsockopt(d->d_socket, SOL_SOCKET,
  685.   SO_DEBUG, (char *)&on,
  686.   sizeof on);
  687. (void) setsockopt(d->d_socket, SOL_SOCKET,
  688.   SO_REUSEADDR, (char *)&on, sizeof on);
  689. (void) setsockopt(d->d_socket, SOL_SOCKET,
  690.   SO_KEEPALIVE, (char *)&on, sizeof on);
  691. # ifdef SO_RCVBUF
  692. if (d->d_tcprcvbufsize > 0)
  693. {
  694. if (setsockopt(d->d_socket, SOL_SOCKET,
  695.        SO_RCVBUF,
  696.        (char *) &d->d_tcprcvbufsize,
  697.        sizeof(d->d_tcprcvbufsize)) < 0)
  698. syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name);
  699. }
  700. # endif /* SO_RCVBUF */
  701. # ifdef SO_SNDBUF
  702. if (d->d_tcpsndbufsize > 0)
  703. {
  704. if (setsockopt(d->d_socket, SOL_SOCKET,
  705.        SO_SNDBUF,
  706.        (char *) &d->d_tcpsndbufsize,
  707.        sizeof(d->d_tcpsndbufsize)) < 0)
  708. syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name);
  709. }
  710. # endif /* SO_SNDBUF */
  711. if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 ||
  712.     fcntl(d->d_socket, F_SETFD,
  713.   fdflags | FD_CLOEXEC) == -1)
  714. {
  715. save_errno = errno;
  716. syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s",
  717.        d->d_name,
  718.        fdflags == -1 ? "get" : "set",
  719.        strerror(save_errno));
  720. (void) close(d->d_socket);
  721. goto severe;
  722. }
  723. switch (d->d_addr.sa.sa_family)
  724. {
  725. # if NETINET
  726.   case AF_INET:
  727. socksize = sizeof d->d_addr.sin;
  728. break;
  729. # endif /* NETINET */
  730. # if NETINET6
  731.   case AF_INET6:
  732. socksize = sizeof d->d_addr.sin6;
  733. break;
  734. # endif /* NETINET6 */
  735. # if NETISO
  736.   case AF_ISO:
  737. socksize = sizeof d->d_addr.siso;
  738. break;
  739. # endif /* NETISO */
  740.   default:
  741. socksize = sizeof d->d_addr;
  742. break;
  743. }
  744. if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0)
  745. {
  746. /* probably another daemon already */
  747. save_errno = errno;
  748. syserr("opendaemonsocket: daemon %s: cannot bind",
  749.        d->d_name);
  750. (void) close(d->d_socket);
  751. goto severe;
  752. }
  753. }
  754. if (!firsttime &&
  755.     listen(d->d_socket, d->d_listenqueue) < 0)
  756. {
  757. save_errno = errno;
  758. syserr("opendaemonsocket: daemon %s: cannot listen",
  759.        d->d_name);
  760. (void) close(d->d_socket);
  761. goto severe;
  762. }
  763. return socksize;
  764. } while (ntries++ < MAXOPENTRIES && transienterror(save_errno));
  765. syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting",
  766.        d->d_name);
  767. /* NOTREACHED */
  768. return -1;  /* avoid compiler warning on IRIX */
  769. }
  770. /*
  771. **  SETUPDAEMON -- setup socket for daemon
  772. **
  773. ** Parameters:
  774. ** daemonaddr -- socket for daemon
  775. ** daemon -- number of daemon
  776. **
  777. ** Returns:
  778. ** port number on which daemon should run
  779. **
  780. */
  781. static u_short
  782. setupdaemon(daemonaddr)
  783. SOCKADDR *daemonaddr;
  784. {
  785. u_short port;
  786. /*
  787. **  Set up the address for the mailer.
  788. */
  789. if (daemonaddr->sa.sa_family == AF_UNSPEC)
  790. {
  791. memset(daemonaddr, '', sizeof *daemonaddr);
  792. daemonaddr->sa.sa_family = InetMode;
  793. }
  794. switch (daemonaddr->sa.sa_family)
  795. {
  796. # if NETINET
  797.   case AF_INET:
  798. if (daemonaddr->sin.sin_addr.s_addr == 0)
  799. daemonaddr->sin.sin_addr.s_addr = INADDR_ANY;
  800. port = daemonaddr->sin.sin_port;
  801. break;
  802. # endif /* NETINET */
  803. # if NETINET6
  804.   case AF_INET6:
  805. if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr))
  806. daemonaddr->sin6.sin6_addr = in6addr_any;
  807. port = daemonaddr->sin6.sin6_port;
  808. break;
  809. # endif /* NETINET6 */
  810.   default:
  811. /* unknown protocol */
  812. port = 0;
  813. break;
  814. }
  815. if (port == 0)
  816. {
  817. # ifdef NO_GETSERVBYNAME
  818. port = htons(25);
  819. # else /* NO_GETSERVBYNAME */
  820. {
  821. register struct servent *sp;
  822. sp = getservbyname("smtp", "tcp");
  823. if (sp == NULL)
  824. {
  825. syserr("554 5.3.5 service "smtp" unknown");
  826. port = htons(25);
  827. }
  828. else
  829. port = sp->s_port;
  830. }
  831. # endif /* NO_GETSERVBYNAME */
  832. }
  833. switch (daemonaddr->sa.sa_family)
  834. {
  835. # if NETINET
  836.   case AF_INET:
  837. daemonaddr->sin.sin_port = port;
  838. break;
  839. # endif /* NETINET */
  840. # if NETINET6
  841.   case AF_INET6:
  842. daemonaddr->sin6.sin6_port = port;
  843. break;
  844. # endif /* NETINET6 */
  845.   default:
  846. /* unknown protocol */
  847. break;
  848. }
  849. return(port);
  850. }
  851. /*
  852. **  CLRDAEMON -- reset the daemon connection
  853. **
  854. ** Parameters:
  855. ** none.
  856. **
  857. ** Returns:
  858. ** none.
  859. **
  860. ** Side Effects:
  861. ** releases any resources used by the passive daemon.
  862. */
  863. void
  864. clrdaemon()
  865. {
  866. int i;
  867. for (i = 0; i < ndaemons; i++)
  868. {
  869. if (Daemons[i].d_socket >= 0)
  870. (void) close(Daemons[i].d_socket);
  871. Daemons[i].d_socket = -1;
  872. }
  873. }
  874. /*
  875. **  SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client)
  876. **
  877. ** Parameters:
  878. ** p -- the options line.
  879. ** d -- the daemon structure to fill in.
  880. **
  881. ** Returns:
  882. ** none.
  883. */
  884. static void
  885. setsockaddroptions(p, d)
  886. register char *p;
  887. struct daemon *d;
  888. {
  889. # if NETISO
  890. short port;
  891. # endif /* NETISO */
  892. int l;
  893. char *h, *flags;
  894. if (d->d_addr.sa.sa_family == AF_UNSPEC)
  895. d->d_addr.sa.sa_family = InetMode;
  896. while (p != NULL)
  897. {
  898. register char *f;
  899. register char *v;
  900. while (isascii(*p) && isspace(*p))
  901. p++;
  902. if (*p == '')
  903. break;
  904. f = p;
  905. p = strchr(p, ',');
  906. if (p != NULL)
  907. *p++ = '';
  908. v = strchr(f, '=');
  909. if (v == NULL)
  910. continue;
  911. while (isascii(*++v) && isspace(*v))
  912. continue;
  913. if (isascii(*f) && islower(*f))
  914. *f = toupper(*f);
  915. switch (*f)
  916. {
  917.   case 'F': /* address family */
  918. if (isascii(*v) && isdigit(*v))
  919. d->d_addr.sa.sa_family = atoi(v);
  920. # if NETINET
  921. else if (strcasecmp(v, "inet") == 0)
  922. d->d_addr.sa.sa_family = AF_INET;
  923. # endif /* NETINET */
  924. # if NETINET6
  925. else if (strcasecmp(v, "inet6") == 0)
  926. d->d_addr.sa.sa_family = AF_INET6;
  927. # endif /* NETINET6 */
  928. # if NETISO
  929. else if (strcasecmp(v, "iso") == 0)
  930. d->d_addr.sa.sa_family = AF_ISO;
  931. # endif /* NETISO */
  932. # if NETNS
  933. else if (strcasecmp(v, "ns") == 0)
  934. d->d_addr.sa.sa_family = AF_NS;
  935. # endif /* NETNS */
  936. # if NETX25
  937. else if (strcasecmp(v, "x.25") == 0)
  938. d->d_addr.sa.sa_family = AF_CCITT;
  939. # endif /* NETX25 */
  940. else
  941. syserr("554 5.3.5 Unknown address family %s in Family=option",
  942.        v);
  943. break;
  944.   case 'A': /* address */
  945. switch (d->d_addr.sa.sa_family)
  946. {
  947. # if NETINET
  948.   case AF_INET:
  949. if (!isascii(*v) || !isdigit(*v) ||
  950.     ((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE))
  951. {
  952. register struct hostent *hp;
  953. hp = sm_gethostbyname(v, AF_INET);
  954. if (hp == NULL)
  955. syserr("554 5.3.0 host "%s" unknown",
  956.        v);
  957. else
  958. {
  959. while (*(hp->h_addr_list) &&
  960.        hp->h_addrtype != AF_INET)
  961. hp->h_addr_list++;
  962. if (*(hp->h_addr_list) == NULL)
  963. syserr("554 5.3.0 host "%s" unknown",
  964.        v);
  965. else
  966. memmove(&d->d_addr.sin.sin_addr,
  967. *(hp->h_addr_list),
  968. INADDRSZ);
  969. }
  970. }
  971. break;
  972. # endif /* NETINET */
  973. # if NETINET6
  974.   case AF_INET6:
  975. if (!isascii(*v) || !isxdigit(*v) ||
  976.     inet_pton(AF_INET6, v,
  977.       &d->d_addr.sin6.sin6_addr) != 1)
  978. {
  979. register struct hostent *hp;
  980. hp = sm_gethostbyname(v, AF_INET6);
  981. if (hp == NULL)
  982. syserr("554 5.3.0 host "%s" unknown",
  983.        v);
  984. else
  985. {
  986. while (*(hp->h_addr_list) &&
  987.        hp->h_addrtype != AF_INET6)
  988. hp->h_addr_list++;
  989. if (*(hp->h_addr_list) == NULL)
  990. syserr("554 5.3.0 host "%s" unknown",
  991.        v);
  992. else
  993. memmove(&d->d_addr.sin6.sin6_addr,
  994. *(hp->h_addr_list),
  995. IN6ADDRSZ);
  996. }
  997. }
  998. break;
  999. # endif /* NETINET6 */
  1000.   default:
  1001. syserr("554 5.3.5 address= option unsupported for family %d",
  1002.        d->d_addr.sa.sa_family);
  1003. break;
  1004. }
  1005. break;
  1006.   case 'P': /* port */
  1007. switch (d->d_addr.sa.sa_family)
  1008. {
  1009. # if NETINET
  1010.   case AF_INET:
  1011. if (isascii(*v) && isdigit(*v))
  1012. d->d_addr.sin.sin_port = htons(atoi(v));
  1013. else
  1014. {
  1015. #  ifdef NO_GETSERVBYNAME
  1016. syserr("554 5.3.5 invalid port number: %s",
  1017.        v);
  1018. #  else /* NO_GETSERVBYNAME */
  1019. register struct servent *sp;
  1020. sp = getservbyname(v, "tcp");
  1021. if (sp == NULL)
  1022. syserr("554 5.3.5 service "%s" unknown",
  1023.        v);
  1024. else
  1025. d->d_addr.sin.sin_port = sp->s_port;
  1026. #  endif /* NO_GETSERVBYNAME */
  1027. }
  1028. break;
  1029. # endif /* NETINET */
  1030. # if NETINET6
  1031.   case AF_INET6:
  1032. if (isascii(*v) && isdigit(*v))
  1033. d->d_addr.sin6.sin6_port = htons(atoi(v));
  1034. else
  1035. {
  1036. #  ifdef NO_GETSERVBYNAME
  1037. syserr("554 5.3.5 invalid port number: %s",
  1038.        v);
  1039. #  else /* NO_GETSERVBYNAME */
  1040. register struct servent *sp;
  1041. sp = getservbyname(v, "tcp");
  1042. if (sp == NULL)
  1043. syserr("554 5.3.5 service "%s" unknown",
  1044.        v);
  1045. else
  1046. d->d_addr.sin6.sin6_port = sp->s_port;
  1047. #  endif /* NO_GETSERVBYNAME */
  1048. }
  1049. break;
  1050. # endif /* NETINET6 */
  1051. # if NETISO
  1052.   case AF_ISO:
  1053. /* assume two byte transport selector */
  1054. if (isascii(*v) && isdigit(*v))
  1055. port = htons(atoi(v));
  1056. else
  1057. {
  1058. #  ifdef NO_GETSERVBYNAME
  1059. syserr("554 5.3.5 invalid port number: %s",
  1060.        v);
  1061. #  else /* NO_GETSERVBYNAME */
  1062. register struct servent *sp;
  1063. sp = getservbyname(v, "tcp");
  1064. if (sp == NULL)
  1065. syserr("554 5.3.5 service "%s" unknown",
  1066.        v);
  1067. else
  1068. port = sp->s_port;
  1069. #  endif /* NO_GETSERVBYNAME */
  1070. }
  1071. memmove(TSEL(&d->d_addr.siso),
  1072. (char *) &port, 2);
  1073. break;
  1074. # endif /* NETISO */
  1075.   default:
  1076. syserr("554 5.3.5 Port= option unsupported for family %d",
  1077.        d->d_addr.sa.sa_family);
  1078. break;
  1079. }
  1080. break;
  1081.   case 'L': /* listen queue size */
  1082. d->d_listenqueue = atoi(v);
  1083. break;
  1084.   case 'M': /* modifiers (flags) */
  1085. l = 3 * strlen(v) + 3;
  1086. h = v;
  1087. flags = xalloc(l);
  1088. d->d_mflags = flags;
  1089. for (; *h != ''; h++)
  1090. {
  1091. if (!(isascii(*h) && isspace(*h)))
  1092. {
  1093. if (flags != d->d_mflags)
  1094. *f++ = ' ';
  1095. *flags++ = *h;
  1096. if (isupper(*h))
  1097. *flags++ = *h;
  1098. }
  1099. }
  1100. *flags++ = '';
  1101. for (; *v != ''; v++)
  1102. if (!(isascii(*v) && isspace(*v)))
  1103. setbitn(*v, d->d_flags);
  1104. break;
  1105.   case 'S': /* send buffer size */
  1106. d->d_tcpsndbufsize = atoi(v);
  1107. break;
  1108.   case 'R': /* receive buffer size */
  1109. d->d_tcprcvbufsize = atoi(v);
  1110. break;
  1111.   case 'N': /* name */
  1112. d->d_name = v;
  1113. break;
  1114.   default:
  1115. syserr("554 5.3.5 PortOptions parameter "%s" unknown",
  1116.        f);
  1117. }
  1118. }
  1119. }
  1120. /*
  1121. **  SETDAEMONOPTIONS -- set options for running the MTA daemon
  1122. **
  1123. ** Parameters:
  1124. ** p -- the options line.
  1125. **
  1126. ** Returns:
  1127. ** TRUE if successful, FALSE otherwise.
  1128. */
  1129. bool
  1130. setdaemonoptions(p)
  1131. register char *p;
  1132. {
  1133. if (ndaemons >= MAXDAEMONS)
  1134. return FALSE;
  1135. Daemons[ndaemons].d_socket = -1;
  1136. Daemons[ndaemons].d_listenqueue = 10;
  1137. clrbitmap(Daemons[ndaemons].d_flags);
  1138. setsockaddroptions(p, &Daemons[ndaemons]);
  1139. if (Daemons[ndaemons].d_name != NULL)
  1140. Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name);
  1141. else
  1142. {
  1143. char num[30];
  1144. snprintf(num, sizeof num, "Daemon%d", ndaemons);
  1145. Daemons[ndaemons].d_name = newstr(num);
  1146. }
  1147. if (tTd(37, 1))
  1148. {
  1149. dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name);
  1150. if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags))
  1151. dprintf("ETRNONLY ");
  1152. if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags))
  1153. dprintf("NOETRN ");
  1154. dprintf("n");
  1155. }
  1156. ++ndaemons;
  1157. return TRUE;
  1158. }
  1159. /*
  1160. **  INITDAEMON -- initialize daemon if not yet done.
  1161. **
  1162. ** Parameters:
  1163. ** none
  1164. **
  1165. ** Returns:
  1166. ** none
  1167. **
  1168. ** Side Effects:
  1169. ** initializes structure for one daemon.
  1170. */
  1171. void
  1172. initdaemon()
  1173. {
  1174. if (ndaemons == 0)
  1175. {
  1176. Daemons[ndaemons].d_socket = -1;
  1177. Daemons[ndaemons].d_listenqueue = 10;
  1178. Daemons[ndaemons].d_name = "Daemon0";
  1179. ndaemons = 1;
  1180. }
  1181. }
  1182. /*
  1183. **  SETCLIENTOPTIONS -- set options for running the client
  1184. **
  1185. ** Parameters:
  1186. ** p -- the options line.
  1187. **
  1188. ** Returns:
  1189. ** none.
  1190. */
  1191. static SOCKADDR ClientAddr; /* address for client */
  1192. void
  1193. setclientoptions(p)
  1194. register char *p;
  1195. {
  1196. struct daemon d;
  1197. extern ENVELOPE BlankEnvelope;
  1198. memset(&d, '', sizeof d);
  1199. setsockaddroptions(p, &d);
  1200. /* grab what we need */
  1201. memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr);
  1202. TcpSndBufferSize = d.d_tcpsndbufsize;
  1203. TcpRcvBufferSize = d.d_tcprcvbufsize;
  1204. if (d.d_mflags != NULL)
  1205. define(macid("{client_flags}", NULL), d.d_mflags,
  1206.        &BlankEnvelope);
  1207. else
  1208. define(macid("{client_flags}", NULL), "", &BlankEnvelope);
  1209. }
  1210. /*
  1211. **  MAKECONNECTION -- make a connection to an SMTP socket on a machine.
  1212. **
  1213. ** Parameters:
  1214. ** host -- the name of the host.
  1215. ** port -- the port number to connect to.
  1216. ** mci -- a pointer to the mail connection information
  1217. ** structure to be filled in.
  1218. ** e -- the current envelope.
  1219. **
  1220. ** Returns:
  1221. ** An exit code telling whether the connection could be
  1222. ** made and if not why not.
  1223. **
  1224. ** Side Effects:
  1225. ** none.
  1226. */
  1227. static jmp_buf CtxConnectTimeout;
  1228. SOCKADDR CurHostAddr; /* address of current host */
  1229. int
  1230. makeconnection(host, port, mci, e)
  1231. char *host;
  1232. volatile u_int port;
  1233. register MCI *mci;
  1234. ENVELOPE *e;
  1235. {
  1236. register volatile int addrno = 0;
  1237. register volatile int s;
  1238. register struct hostent *volatile hp = (struct hostent *)NULL;
  1239. SOCKADDR addr;
  1240. SOCKADDR clt_addr;
  1241. int save_errno = 0;
  1242. volatile SOCKADDR_LEN_T addrlen;
  1243. volatile bool firstconnect;
  1244. EVENT *volatile ev = NULL;
  1245. # if NETINET6
  1246. volatile int family = AF_INET6;
  1247. bool v6found = FALSE;
  1248. # else /* NETINET6 */
  1249. int family = AF_INET;
  1250. # endif /* NETINET6 */
  1251. SOCKADDR_LEN_T len;
  1252. volatile SOCKADDR_LEN_T socksize = 0;
  1253. volatile bool clt_bind = FALSE;
  1254. BITMAP256 d_flags;
  1255. char *p;
  1256. extern ENVELOPE BlankEnvelope;
  1257. /* retranslate ${daemon_flags} into bitmap */
  1258. clrbitmap(d_flags);
  1259. if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL)
  1260. {
  1261. for (; *p != ''; p++)
  1262. if (!(isascii(*p) && isspace(*p)))
  1263. setbitn(*p, d_flags);
  1264. }
  1265. /* "add" ${client_flags} to bitmap */
  1266. if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL)
  1267. {
  1268. for (; *p != ''; p++)
  1269. {
  1270. /* look for just this one flag */
  1271. if (*p == D_IFNHELO)
  1272. {
  1273. setbitn(*p, d_flags);
  1274. break;
  1275. }
  1276. }
  1277. }
  1278. /* Set up the address for outgoing connection. */
  1279. if (bitnset(D_BINDIF, d_flags) &&
  1280.     (p = macvalue(macid("{if_addr}", NULL), e)) != NULL)
  1281. {
  1282. char *f;
  1283. memset(&clt_addr, '', sizeof clt_addr);
  1284. /* XXX set all necessary values... */
  1285. if ((f = macvalue(macid("{if_family}", NULL), e)) != NULL)
  1286. clt_addr.sa.sa_family = atoi(f);
  1287. else
  1288. clt_addr.sa.sa_family = AF_INET;
  1289. switch (clt_addr.sa.sa_family)
  1290. {
  1291. # if NETINET
  1292.   case AF_INET:
  1293. if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p))
  1294.     != INADDR_NONE)
  1295. {
  1296. clt_bind = TRUE;
  1297. socksize = sizeof (struct sockaddr_in);
  1298. }
  1299. else if (clt_addr.sin.sin_port != 0)
  1300. {
  1301. clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
  1302. clt_bind = TRUE;
  1303. socksize = sizeof (struct sockaddr_in);
  1304. }
  1305. break;
  1306. # endif /* NETINET */
  1307. # if NETINET6
  1308.   case AF_INET6:
  1309. f = strchr(p, ']');
  1310. if (f != NULL)
  1311. {
  1312. *f = '';
  1313. if (inet_pton(AF_INET6, p + 1,
  1314.       &clt_addr.sin6.sin6_addr) == 1)
  1315. {
  1316. *f = ']';
  1317. clt_bind = TRUE;
  1318. socksize = sizeof (struct sockaddr_in6);
  1319. }
  1320. }
  1321. if (!clt_bind && clt_addr.sin6.sin6_port != 0)
  1322. {
  1323. if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
  1324. clt_addr.sin6.sin6_addr = in6addr_any;
  1325. clt_bind = TRUE;
  1326. socksize = sizeof (struct sockaddr_in);
  1327. }
  1328. break;
  1329. # endif /* NETINET6 */
  1330. # if 0
  1331.   default:
  1332. syserr("554 5.3.5 Address= option unsupported for family %d",
  1333.        clt_addr.sa.sa_family);
  1334. break;
  1335. # endif /* 0 */
  1336. }
  1337. }
  1338. else
  1339. {
  1340. STRUCTCOPY(ClientAddr, clt_addr);
  1341. switch (clt_addr.sa.sa_family)
  1342. {
  1343.   case AF_UNSPEC:
  1344. # if NETINET
  1345. clt_addr.sa.sa_family = AF_INET;
  1346. /* FALLTHROUGH */
  1347.   case AF_INET:
  1348. if (clt_addr.sin.sin_addr.s_addr == 0)
  1349. clt_addr.sin.sin_addr.s_addr = INADDR_ANY;
  1350. else
  1351. clt_bind = TRUE;
  1352. if (clt_addr.sin.sin_port != 0)
  1353. clt_bind = TRUE;
  1354. socksize = sizeof (struct sockaddr_in);
  1355. break;
  1356. # endif /* NETINET */
  1357. # if NETINET6
  1358.   case AF_INET6:
  1359. if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr))
  1360. clt_addr.sin6.sin6_addr = in6addr_any;
  1361. else
  1362. clt_bind = TRUE;
  1363. socksize = sizeof (struct sockaddr_in6);
  1364. if (clt_addr.sin6.sin6_port != 0)
  1365. clt_bind = TRUE;
  1366. break;
  1367. # endif /* NETINET6 */
  1368. # if NETISO
  1369.   case AF_ISO:
  1370. socksize = sizeof clt_addr.siso;
  1371. clt_bind = TRUE;
  1372. break;
  1373. # endif /* NETISO */
  1374. }
  1375. }
  1376. /*
  1377. **  Set up the address for the mailer.
  1378. ** Accept "[a.b.c.d]" syntax for host name.
  1379. */
  1380. # if NETINET6
  1381.  v4retry:
  1382. # endif /* NETINET6 */
  1383. # if NAMED_BIND
  1384. h_errno = 0;
  1385. # endif /* NAMED_BIND */
  1386. errno = 0;
  1387. memset(&CurHostAddr, '', sizeof CurHostAddr);
  1388. memset(&addr, '', sizeof addr);
  1389. SmtpPhase = mci->mci_phase = "initial connection";
  1390. CurHostName = host;
  1391. if (host[0] == '[')
  1392. {
  1393. p = strchr(host, ']');
  1394. if (p != NULL)
  1395. {
  1396. # if NETINET
  1397. unsigned long hid = INADDR_NONE;
  1398. # endif /* NETINET */
  1399. # if NETINET6
  1400. struct sockaddr_in6 hid6;
  1401. # endif /* NETINET6 */
  1402. *p = '';
  1403. # if NETINET6
  1404. memset(&hid6, '', sizeof hid6);
  1405. # endif /* NETINET6 */
  1406. # if NETINET
  1407. if (family == AF_INET &&
  1408.     (hid = inet_addr(&host[1])) != INADDR_NONE)
  1409. {
  1410. addr.sin.sin_family = AF_INET;
  1411. addr.sin.sin_addr.s_addr = hid;
  1412. }
  1413. else
  1414. # endif /* NETINET */
  1415. # if NETINET6
  1416. if (family == AF_INET6 &&
  1417.     inet_pton(AF_INET6, &host[1],
  1418.       &hid6.sin6_addr) == 1)
  1419. {
  1420. addr.sin6.sin6_family = AF_INET6;
  1421. addr.sin6.sin6_addr = hid6.sin6_addr;
  1422. }
  1423. else
  1424. # endif /* NETINET6 */
  1425. {
  1426. /* try it as a host name (avoid MX lookup) */
  1427. hp = sm_gethostbyname(&host[1], family);
  1428. if (hp == NULL && p[-1] == '.')
  1429. {
  1430. # if NAMED_BIND
  1431. int oldopts = _res.options;
  1432. _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
  1433. # endif /* NAMED_BIND */
  1434. p[-1] = '';
  1435. hp = sm_gethostbyname(&host[1],
  1436.       family);
  1437. p[-1] = '.';
  1438. # if NAMED_BIND
  1439. _res.options = oldopts;
  1440. # endif /* NAMED_BIND */
  1441. }
  1442. *p = ']';
  1443. goto gothostent;
  1444. }
  1445. *p = ']';
  1446. }
  1447. if (p == NULL)
  1448. {
  1449. extern char MsgBuf[];
  1450. usrerrenh("5.1.2",
  1451.   "553 Invalid numeric domain spec "%s"",
  1452.   host);
  1453. mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
  1454. errno = EINVAL;
  1455. return EX_NOHOST;
  1456. }
  1457. }
  1458. else
  1459. {
  1460. /* contortion to get around SGI cc complaints */
  1461. {
  1462. p = &host[strlen(host) - 1];
  1463. hp = sm_gethostbyname(host, family);
  1464. if (hp == NULL && *p == '.')
  1465. {
  1466. # if NAMED_BIND
  1467. int oldopts = _res.options;
  1468. _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
  1469. # endif /* NAMED_BIND */
  1470. *p = '';
  1471. hp = sm_gethostbyname(host, family);
  1472. *p = '.';
  1473. # if NAMED_BIND
  1474. _res.options = oldopts;
  1475. # endif /* NAMED_BIND */
  1476. }
  1477. }
  1478. gothostent:
  1479. if (hp == NULL)
  1480. {
  1481. # if NAMED_BIND
  1482. /* check for name server timeouts */
  1483. if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
  1484.     (errno == ECONNREFUSED && UseNameServer))
  1485. {
  1486. save_errno = errno;
  1487. mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
  1488. errno = save_errno;
  1489. return EX_TEMPFAIL;
  1490. }
  1491. # endif /* NAMED_BIND */
  1492. # if NETINET6
  1493. /*
  1494. **  Try v6 first, then fall back to v4.
  1495. **  If we found a v6 address, but no v4
  1496. **  addresses, then TEMPFAIL.
  1497. */
  1498. if (family == AF_INET6)
  1499. {
  1500. family = AF_INET;
  1501. goto v4retry;
  1502. }
  1503. if (v6found)
  1504. goto v6tempfail;
  1505. # endif /* NETINET6 */
  1506. save_errno = errno;
  1507. mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
  1508. errno = save_errno;
  1509. return EX_NOHOST;
  1510. }
  1511. addr.sa.sa_family = hp->h_addrtype;
  1512. switch (hp->h_addrtype)
  1513. {
  1514. # if NETINET
  1515.   case AF_INET:
  1516. memmove(&addr.sin.sin_addr,
  1517. hp->h_addr,
  1518. INADDRSZ);
  1519. break;
  1520. # endif /* NETINET */
  1521. # if NETINET6
  1522.   case AF_INET6:
  1523. memmove(&addr.sin6.sin6_addr,
  1524. hp->h_addr,
  1525. IN6ADDRSZ);
  1526. break;
  1527. # endif /* NETINET6 */
  1528.   default:
  1529. if (hp->h_length > sizeof addr.sa.sa_data)
  1530. {
  1531. syserr("makeconnection: long sa_data: family %d len %d",
  1532. hp->h_addrtype, hp->h_length);
  1533. mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
  1534. errno = EINVAL;
  1535. return EX_NOHOST;
  1536. }
  1537. memmove(addr.sa.sa_data,
  1538. hp->h_addr,
  1539. hp->h_length);
  1540. break;
  1541. }
  1542. addrno = 1;
  1543. }
  1544. /*
  1545. **  Determine the port number.
  1546. */
  1547. if (port == 0)
  1548. {
  1549. # ifdef NO_GETSERVBYNAME
  1550. port = htons(25);
  1551. # else /* NO_GETSERVBYNAME */
  1552. register struct servent *sp = getservbyname("smtp", "tcp");
  1553. if (sp == NULL)
  1554. {
  1555. if (LogLevel > 2)
  1556. sm_syslog(LOG_ERR, NOQID,
  1557.   "makeconnection: service "smtp" unknown");
  1558. port = htons(25);
  1559. }
  1560. else
  1561. port = sp->s_port;
  1562. # endif /* NO_GETSERVBYNAME */
  1563. }
  1564. switch (addr.sa.sa_family)
  1565. {
  1566. # if NETINET
  1567.   case AF_INET:
  1568. addr.sin.sin_port = port;
  1569. addrlen = sizeof (struct sockaddr_in);
  1570. break;
  1571. # endif /* NETINET */
  1572. # if NETINET6
  1573.   case AF_INET6:
  1574. addr.sin6.sin6_port = port;
  1575. addrlen = sizeof (struct sockaddr_in6);
  1576. break;
  1577. # endif /* NETINET6 */
  1578. # if NETISO
  1579.   case AF_ISO:
  1580. /* assume two byte transport selector */
  1581. memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2);
  1582. addrlen = sizeof (struct sockaddr_iso);
  1583. break;
  1584. # endif /* NETISO */
  1585.   default:
  1586. syserr("Can't connect to address family %d", addr.sa.sa_family);
  1587. mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
  1588. errno = EINVAL;
  1589. return EX_NOHOST;
  1590. }
  1591. /*
  1592. **  Try to actually open the connection.
  1593. */
  1594. # ifdef XLA
  1595. /* if too many connections, don't bother trying */
  1596. if (!xla_noqueue_ok(host))
  1597. return EX_TEMPFAIL;
  1598. # endif /* XLA */
  1599. firstconnect = TRUE;
  1600. for (;;)
  1601. {
  1602. if (tTd(16, 1))
  1603. dprintf("makeconnection (%s [%s])n",
  1604. host, anynet_ntoa(&addr));
  1605. /* save for logging */
  1606. CurHostAddr = addr;
  1607. if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
  1608. {
  1609. int rport = IPPORT_RESERVED - 1;
  1610. s = rresvport(&rport);
  1611. }
  1612. else
  1613. {
  1614. s = socket(addr.sa.sa_family, SOCK_STREAM, 0);
  1615. }
  1616. if (s < 0)
  1617. {
  1618. save_errno = errno;
  1619. syserr("makeconnection: cannot create socket");
  1620. # ifdef XLA
  1621. xla_host_end(host);
  1622. # endif /* XLA */
  1623. mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  1624. errno = save_errno;
  1625. return EX_TEMPFAIL;
  1626. }
  1627. # ifdef SO_SNDBUF
  1628. if (TcpSndBufferSize > 0)
  1629. {
  1630. if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
  1631.        (char *) &TcpSndBufferSize,
  1632.        sizeof(TcpSndBufferSize)) < 0)
  1633. syserr("makeconnection: setsockopt(SO_SNDBUF)");
  1634. }
  1635. # endif /* SO_SNDBUF */
  1636. # ifdef SO_RCVBUF
  1637. if (TcpRcvBufferSize > 0)
  1638. {
  1639. if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
  1640.        (char *) &TcpRcvBufferSize,
  1641.        sizeof(TcpRcvBufferSize)) < 0)
  1642. syserr("makeconnection: setsockopt(SO_RCVBUF)");
  1643. }
  1644. # endif /* SO_RCVBUF */
  1645. if (tTd(16, 1))
  1646. dprintf("makeconnection: fd=%dn", s);
  1647. /* turn on network debugging? */
  1648. if (tTd(16, 101))
  1649. {
  1650. int on = 1;
  1651. (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
  1652.   (char *)&on, sizeof on);
  1653. }
  1654. if (e->e_xfp != NULL)
  1655. (void) fflush(e->e_xfp); /* for debugging */
  1656. errno = 0; /* for debugging */
  1657. if (clt_bind)
  1658. {
  1659. int on = 1;
  1660. switch (clt_addr.sa.sa_family)
  1661. {
  1662. # if NETINET
  1663.   case AF_INET:
  1664. if (clt_addr.sin.sin_port != 0)
  1665. (void) setsockopt(s, SOL_SOCKET,
  1666.   SO_REUSEADDR,
  1667.   (char *) &on,
  1668.   sizeof on);
  1669. break;
  1670. # endif /* NETINET */
  1671. # if NETINET6
  1672.   case AF_INET6:
  1673. if (clt_addr.sin6.sin6_port != 0)
  1674. (void) setsockopt(s, SOL_SOCKET,
  1675.   SO_REUSEADDR,
  1676.   (char *) &on,
  1677.   sizeof on);
  1678. break;
  1679. # endif /* NETINET6 */
  1680. }
  1681. if (bind(s, &clt_addr.sa, socksize) < 0)
  1682. {
  1683. save_errno = errno;
  1684. (void) close(s);
  1685. errno = save_errno;
  1686. syserr("makeconnection: cannot bind socket [%s]",
  1687.        anynet_ntoa(&clt_addr));
  1688. errno = save_errno;
  1689. return EX_TEMPFAIL;
  1690. }
  1691. }
  1692. /*
  1693. **  Linux seems to hang in connect for 90 minutes (!!!).
  1694. **  Time out the connect to avoid this problem.
  1695. */
  1696. if (setjmp(CtxConnectTimeout) == 0)
  1697. {
  1698. int i;
  1699. if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
  1700. ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
  1701. else if (TimeOuts.to_connect != 0)
  1702. ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
  1703. else
  1704. ev = NULL;
  1705. switch (ConnectOnlyTo.sa.sa_family)
  1706. {
  1707. # if NETINET
  1708.   case AF_INET:
  1709. addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr;
  1710. break;
  1711. # endif /* NETINET */
  1712. # if NETINET6
  1713.   case AF_INET6:
  1714. memmove(&addr.sin6.sin6_addr,
  1715. &ConnectOnlyTo.sin6.sin6_addr,
  1716. IN6ADDRSZ);
  1717. break;
  1718. # endif /* NETINET6 */
  1719. }
  1720. i = connect(s, (struct sockaddr *) &addr, addrlen);
  1721. save_errno = errno;
  1722. if (ev != NULL)
  1723. clrevent(ev);
  1724. if (i >= 0)
  1725. break;
  1726. }
  1727. else
  1728. save_errno = errno;
  1729. /* if running demand-dialed connection, try again */
  1730. if (DialDelay > 0 && firstconnect)
  1731. {
  1732. if (tTd(16, 1))
  1733. dprintf("Connect failed (%s); trying again...n",
  1734. errstring(save_errno));
  1735. firstconnect = FALSE;
  1736. (void) sleep(DialDelay);
  1737. continue;
  1738. }
  1739. /* couldn't connect.... figure out why */
  1740. (void) close(s);
  1741. if (LogLevel >= 14)
  1742. sm_syslog(LOG_INFO, e->e_id,
  1743.   "makeconnection (%s [%s]) failed: %s",
  1744.   host, anynet_ntoa(&addr),
  1745.   errstring(save_errno));
  1746. if (hp != NULL && hp->h_addr_list[addrno] != NULL)
  1747. {
  1748. if (tTd(16, 1))
  1749. dprintf("Connect failed (%s); trying new address....n",
  1750. errstring(save_errno));
  1751. switch (addr.sa.sa_family)
  1752. {
  1753. # if NETINET
  1754.   case AF_INET:
  1755. memmove(&addr.sin.sin_addr,
  1756. hp->h_addr_list[addrno++],
  1757. INADDRSZ);
  1758. break;
  1759. # endif /* NETINET */
  1760. # if NETINET6
  1761.   case AF_INET6:
  1762. memmove(&addr.sin6.sin6_addr,
  1763. hp->h_addr_list[addrno++],
  1764. IN6ADDRSZ);
  1765. break;
  1766. # endif /* NETINET6 */
  1767.   default:
  1768. memmove(addr.sa.sa_data,
  1769. hp->h_addr_list[addrno++],
  1770. hp->h_length);
  1771. break;
  1772. }
  1773. continue;
  1774. }
  1775. # if NETINET6
  1776. if (family == AF_INET6)
  1777. {
  1778. if (tTd(16, 1))
  1779. dprintf("Connect failed (%s); retrying with AF_INET....n",
  1780. errstring(save_errno));
  1781. v6found = TRUE;
  1782. family = AF_INET;
  1783. goto v4retry;
  1784. }
  1785. v6tempfail:
  1786. # endif /* NETINET6 */
  1787. /* couldn't open connection */
  1788. # if NETINET6
  1789. /* Don't clobber an already saved errno from v4retry */
  1790. if (errno > 0)
  1791. # endif /* NETINET6 */
  1792. save_errno = errno;
  1793. if (tTd(16, 1))
  1794. dprintf("Connect failed (%s)n", errstring(save_errno));
  1795. # ifdef XLA
  1796. xla_host_end(host);
  1797. # endif /* XLA */
  1798. mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
  1799. errno = save_errno;
  1800. return EX_TEMPFAIL;
  1801. }
  1802. /* connection ok, put it into canonical form */
  1803. mci->mci_out = NULL;
  1804. if ((mci->mci_out = fdopen(s, "w")) == NULL ||
  1805.     (s = dup(s)) < 0 ||
  1806.     (mci->mci_in = fdopen(s, "r")) == NULL)
  1807. {
  1808. save_errno = errno;
  1809. syserr("cannot open SMTP client channel, fd=%d", s);
  1810. mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  1811. if (mci->mci_out != NULL)
  1812. (void) fclose(mci->mci_out);
  1813. (void) close(s);
  1814. errno = save_errno;
  1815. return EX_TEMPFAIL;
  1816. }
  1817. /* find out name for Interface through which we connect */
  1818. len = sizeof addr;
  1819. if (getsockname(s, &addr.sa, &len) == 0)
  1820. {
  1821. char *name;
  1822. define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)),
  1823.        &BlankEnvelope);
  1824. name = hostnamebyanyaddr(&addr);
  1825. define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope);
  1826. if (LogLevel > 11)
  1827. {
  1828. /* log connection information */
  1829. sm_syslog(LOG_INFO, e->e_id,
  1830.   "SMTP outcoming connect on %.40s", name);
  1831. }
  1832. if (bitnset(D_IFNHELO, d_flags))
  1833. {
  1834. if (name[0] != '[' && strchr(name, '.') != NULL)
  1835. mci->mci_heloname = newstr(name);
  1836. }
  1837. }
  1838. else
  1839. {
  1840. define(macid("{if_name}", NULL), NULL, &BlankEnvelope);
  1841. define(macid("{if_addr}", NULL), NULL, &BlankEnvelope);
  1842. }
  1843. mci_setstat(mci, EX_OK, NULL, NULL);
  1844. return EX_OK;
  1845. }
  1846. static void
  1847. connecttimeout()
  1848. {
  1849. errno = ETIMEDOUT;
  1850. longjmp(CtxConnectTimeout, 1);
  1851. }
  1852. /*
  1853. **  MAKECONNECTION_DS -- make a connection to a domain socket.
  1854. **
  1855. ** Parameters:
  1856. ** mux_path -- the path of the socket to connect to.
  1857. ** mci -- a pointer to the mail connection information
  1858. ** structure to be filled in.
  1859. **
  1860. ** Returns:
  1861. ** An exit code telling whether the connection could be
  1862. ** made and if not why not.
  1863. **
  1864. ** Side Effects:
  1865. ** none.
  1866. */
  1867. # if NETUNIX
  1868. int makeconnection_ds(mux_path, mci)
  1869. char *mux_path;
  1870. register MCI *mci;
  1871. {
  1872. int sock;
  1873. int rval, save_errno;
  1874. long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK;
  1875. struct sockaddr_un unix_addr;
  1876. /* if not safe, don't connect */
  1877. rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName,
  1878. sff, S_IRUSR|S_IWUSR, NULL);
  1879. if (rval != 0)
  1880. {
  1881. syserr("makeconnection_ds: unsafe domain socket");
  1882. mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL);
  1883. errno = rval;
  1884. return EX_TEMPFAIL;
  1885. }
  1886. /* prepare address structure */
  1887. memset(&unix_addr, '', sizeof unix_addr);
  1888. unix_addr.sun_family = AF_UNIX;
  1889. if (strlen(mux_path) >= sizeof unix_addr.sun_path)
  1890. {
  1891. syserr("makeconnection_ds: domain socket name too long");
  1892. /* XXX why TEMPFAIL ? */
  1893. mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL);
  1894. errno = ENAMETOOLONG;
  1895. return EX_UNAVAILABLE;
  1896. }
  1897. (void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path);
  1898. /* initialize domain socket */
  1899. sock = socket(AF_UNIX, SOCK_STREAM, 0);
  1900. if (sock == -1)
  1901. {
  1902. save_errno = errno;
  1903. syserr("makeconnection_ds: could not create domain socket");
  1904. mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  1905. errno = save_errno;
  1906. return EX_TEMPFAIL;
  1907. }
  1908. /* connect to server */
  1909. if (connect(sock, (struct sockaddr *) &unix_addr,
  1910.     sizeof(unix_addr)) == -1)
  1911. {
  1912. save_errno = errno;
  1913. syserr("Could not connect to socket %s", mux_path);
  1914. mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
  1915. (void) close(sock);
  1916. errno = save_errno;
  1917. return EX_TEMPFAIL;
  1918. }
  1919. /* connection ok, put it into canonical form */
  1920. mci->mci_out = NULL;
  1921. if ((mci->mci_out = fdopen(sock, "w")) == NULL ||
  1922.     (sock = dup(sock)) < 0 ||
  1923.     (mci->mci_in = fdopen(sock, "r")) == NULL)
  1924. {
  1925. save_errno = errno;
  1926. syserr("cannot open SMTP client channel, fd=%d", sock);
  1927. mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
  1928. if (mci->mci_out != NULL)
  1929. (void) fclose(mci->mci_out);
  1930. (void) close(sock);
  1931. errno = save_errno;
  1932. return EX_TEMPFAIL;
  1933. }
  1934. mci_setstat(mci, EX_OK, NULL, NULL);
  1935. errno = 0;
  1936. return EX_OK;
  1937. }
  1938. # endif /* NETUNIX */
  1939. /*
  1940. **  MYHOSTNAME -- return the name of this host.
  1941. **
  1942. ** Parameters:
  1943. ** hostbuf -- a place to return the name of this host.
  1944. ** size -- the size of hostbuf.
  1945. **
  1946. ** Returns:
  1947. ** A list of aliases for this host.
  1948. **
  1949. ** Side Effects:
  1950. ** Adds numeric codes to $=w.
  1951. */
  1952. struct hostent *
  1953. myhostname(hostbuf, size)
  1954. char hostbuf[];
  1955. int size;
  1956. {
  1957. register struct hostent *hp;
  1958. if (gethostname(hostbuf, size) < 0)
  1959. {
  1960. (void) strlcpy(hostbuf, "localhost", size);
  1961. }
  1962. hp = sm_gethostbyname(hostbuf, InetMode);
  1963. if (hp == NULL)
  1964. return NULL;
  1965. if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
  1966. (void) cleanstrcpy(hostbuf, hp->h_name, size);
  1967. # if NETINFO
  1968. if (strchr(hostbuf, '.') == NULL)
  1969. {
  1970. char *domainname;
  1971. domainname = ni_propval("/locations", NULL, "resolver",
  1972. "domain", '');
  1973. if (domainname != NULL &&
  1974.     strlen(domainname) + strlen(hostbuf) + 1 < size)
  1975. {
  1976. (void) strlcat(hostbuf, ".", size);
  1977. (void) strlcat(hostbuf, domainname, size);
  1978. }
  1979. }
  1980. # endif /* NETINFO */
  1981. /*
  1982. **  If there is still no dot in the name, try looking for a
  1983. **  dotted alias.
  1984. */
  1985. if (strchr(hostbuf, '.') == NULL)
  1986. {
  1987. char **ha;
  1988. for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
  1989. {
  1990. if (strchr(*ha, '.') != NULL)
  1991. {
  1992. (void) cleanstrcpy(hostbuf, *ha, size - 1);
  1993. hostbuf[size - 1] = '';
  1994. break;
  1995. }
  1996. }
  1997. }
  1998. /*
  1999. **  If _still_ no dot, wait for a while and try again -- it is
  2000. **  possible that some service is starting up.  This can result
  2001. **  in excessive delays if the system is badly configured, but
  2002. **  there really isn't a way around that, particularly given that
  2003. **  the config file hasn't been read at this point.
  2004. **  All in all, a bit of a mess.
  2005. */
  2006. if (strchr(hostbuf, '.') == NULL &&
  2007.     !getcanonname(hostbuf, size, TRUE))
  2008. {
  2009. sm_syslog(LOG_CRIT, NOQID,
  2010.   "My unqualified host name (%s) unknown; sleeping for retry",
  2011.   hostbuf);
  2012. message("My unqualified host name (%s) unknown; sleeping for retry",
  2013. hostbuf);
  2014. (void) sleep(60);
  2015. if (!getcanonname(hostbuf, size, TRUE))
  2016. {
  2017. sm_syslog(LOG_ALERT, NOQID,
  2018.   "unable to qualify my own domain name (%s) -- using short name",
  2019.   hostbuf);
  2020. message("WARNING: unable to qualify my own domain name (%s) -- using short name",
  2021. hostbuf);
  2022. }
  2023. }
  2024. return hp;
  2025. }
  2026. /*
  2027. **  ADDRCMP -- compare two host addresses
  2028. **
  2029. ** Parameters:
  2030. ** hp -- hostent structure for the first address
  2031. ** ha -- actual first address
  2032. ** sa -- second address
  2033. **
  2034. ** Returns:
  2035. ** 0 -- if ha and sa match
  2036. ** else -- they don't match
  2037. */
  2038. static int
  2039. addrcmp(hp, ha, sa)
  2040. struct hostent *hp;
  2041. char *ha;
  2042. SOCKADDR *sa;
  2043. {
  2044. # if NETINET6
  2045. u_char *a;
  2046. # endif /* NETINET6 */
  2047. switch (sa->sa.sa_family)
  2048. {
  2049. # if NETINET
  2050.   case AF_INET:
  2051. if (hp->h_addrtype == AF_INET)
  2052. return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ);
  2053. break;
  2054. # endif /* NETINET */
  2055. # if NETINET6
  2056.   case AF_INET6:
  2057. a = (u_char *) &sa->sin6.sin6_addr;
  2058. /* Straight binary comparison */
  2059. if (hp->h_addrtype == AF_INET6)
  2060. return memcmp(ha, a, IN6ADDRSZ);
  2061. /* If IPv4-mapped IPv6 address, compare the IPv4 section */
  2062. if (hp->h_addrtype == AF_INET &&
  2063.     IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr))
  2064. return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ);
  2065. break;
  2066. # endif /* NETINET6 */
  2067. }
  2068. return -1;
  2069. }
  2070. /*
  2071. **  GETAUTHINFO -- get the real host name associated with a file descriptor
  2072. **
  2073. ** Uses RFC1413 protocol to try to get info from the other end.
  2074. **
  2075. ** Parameters:
  2076. ** fd -- the descriptor
  2077. ** may_be_forged -- an outage that is set to TRUE if the
  2078. ** forward lookup of RealHostName does not match
  2079. ** RealHostAddr; set to FALSE if they do match.
  2080. **
  2081. ** Returns:
  2082. ** The user@host information associated with this descriptor.
  2083. */
  2084. static jmp_buf CtxAuthTimeout;
  2085. static void
  2086. authtimeout()
  2087. {
  2088. longjmp(CtxAuthTimeout, 1);
  2089. }
  2090. char *
  2091. getauthinfo(fd, may_be_forged)
  2092. int fd;
  2093. bool *may_be_forged;
  2094. {
  2095. SOCKADDR_LEN_T falen;
  2096. register char *volatile p = NULL;
  2097. SOCKADDR la;
  2098. SOCKADDR_LEN_T lalen;
  2099. register struct servent *sp;
  2100. volatile int s;
  2101. int i = 0;
  2102. EVENT *ev;
  2103. int nleft;
  2104. struct hostent *hp;
  2105. char *ostype = NULL;
  2106. char **ha;
  2107. char ibuf[MAXNAME + 1];
  2108. static char hbuf[MAXNAME * 2 + 11];
  2109. *may_be_forged = FALSE;
  2110. falen = sizeof RealHostAddr;
  2111. if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 ||
  2112.     falen <= 0 || RealHostAddr.sa.sa_family == 0)
  2113. {
  2114. if (i < 0 && errno != ENOTSOCK)
  2115. return NULL;
  2116. (void) snprintf(hbuf, sizeof hbuf, "%s@localhost",
  2117. RealUserName);
  2118. if (tTd(9, 1))
  2119. dprintf("getauthinfo: %sn", hbuf);
  2120. return hbuf;
  2121. }
  2122. if (RealHostName == NULL)
  2123. {
  2124. /* translate that to a host name */
  2125. RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
  2126. if (strlen(RealHostName) > MAXNAME)
  2127. RealHostName[MAXNAME] = '';
  2128. }
  2129. /* cross check RealHostName with forward DNS lookup */
  2130. if (anynet_ntoa(&RealHostAddr)[0] == '[' ||
  2131.     RealHostName[0] == '[')
  2132. {
  2133. /*
  2134. **  address is not a socket or have an
  2135. **  IP address with no forward lookup
  2136. */
  2137. *may_be_forged = FALSE;
  2138. }
  2139. else
  2140. {
  2141. /* try to match the reverse against the forward lookup */
  2142. hp = sm_gethostbyname(RealHostName,
  2143.       RealHostAddr.sa.sa_family);
  2144. if (hp == NULL)
  2145. *may_be_forged = TRUE;
  2146. else
  2147. {
  2148. for (ha = hp->h_addr_list; *ha != NULL; ha++)
  2149. if (addrcmp(hp, *ha, &RealHostAddr) == 0)
  2150. break;
  2151. *may_be_forged = *ha == NULL;
  2152. }
  2153. }
  2154. if (TimeOuts.to_ident == 0)
  2155. goto noident;
  2156. lalen = sizeof la;
  2157. switch (RealHostAddr.sa.sa_family)
  2158. {
  2159. # if NETINET
  2160.   case AF_INET:
  2161. if (getsockname(fd, &la.sa, &lalen) < 0 ||
  2162.     lalen <= 0 ||
  2163.     la.sa.sa_family != AF_INET)
  2164. {
  2165. /* no ident info */
  2166. goto noident;
  2167. }
  2168. /* create ident query */
  2169. (void) snprintf(ibuf, sizeof ibuf, "%d,%drn",
  2170. ntohs(RealHostAddr.sin.sin_port),
  2171. ntohs(la.sin.sin_port));
  2172. /* create local address */
  2173. la.sin.sin_port = 0;
  2174. /* create foreign address */
  2175. #  ifdef NO_GETSERVBYNAME
  2176. RealHostAddr.sin.sin_port = htons(113);
  2177. #  else /* NO_GETSERVBYNAME */
  2178. sp = getservbyname("auth", "tcp");
  2179. if (sp != NULL)
  2180. RealHostAddr.sin.sin_port = sp->s_port;
  2181. else
  2182. RealHostAddr.sin.sin_port = htons(113);
  2183. break;
  2184. #  endif /* NO_GETSERVBYNAME */
  2185. # endif /* NETINET */
  2186. # if NETINET6
  2187.   case AF_INET6:
  2188. if (getsockname(fd, &la.sa, &lalen) < 0 ||
  2189.     lalen <= 0 ||
  2190.     la.sa.sa_family != AF_INET6)
  2191. {
  2192. /* no ident info */
  2193. goto noident;
  2194. }
  2195. /* create ident query */
  2196. (void) snprintf(ibuf, sizeof ibuf, "%d,%drn",
  2197. ntohs(RealHostAddr.sin6.sin6_port),
  2198. ntohs(la.sin6.sin6_port));
  2199. /* create local address */
  2200. la.sin6.sin6_port = 0;
  2201. /* create foreign address */
  2202. #  ifdef NO_GETSERVBYNAME
  2203. RealHostAddr.sin6.sin6_port = htons(113);
  2204. #  else /* NO_GETSERVBYNAME */
  2205. sp = getservbyname("auth", "tcp");
  2206. if (sp != NULL)
  2207. RealHostAddr.sin6.sin6_port = sp->s_port;
  2208. else
  2209. RealHostAddr.sin6.sin6_port = htons(113);
  2210. break;
  2211. #  endif /* NO_GETSERVBYNAME */
  2212. # endif /* NETINET6 */
  2213.   default:
  2214. /* no ident info */
  2215. goto noident;
  2216. }
  2217. s = -1;
  2218. if (setjmp(CtxAuthTimeout) != 0)
  2219. {
  2220. if (s >= 0)
  2221. (void) close(s);
  2222. goto noident;
  2223. }
  2224. /* put a timeout around the whole thing */
  2225. ev = setevent(TimeOuts.to_ident, authtimeout, 0);
  2226. /* connect to foreign IDENT server using same address as SMTP socket */
  2227. s = socket(la.sa.sa_family, SOCK_STREAM, 0);
  2228. if (s < 0)
  2229. {
  2230. clrevent(ev);
  2231. goto noident;
  2232. }
  2233. if (bind(s, &la.sa, lalen) < 0 ||
  2234.     connect(s, &RealHostAddr.sa, lalen) < 0)
  2235. {
  2236. goto closeident;
  2237. }
  2238. if (tTd(9, 10))
  2239. dprintf("getauthinfo: sent %s", ibuf);
  2240. /* send query */
  2241. if (write(s, ibuf, strlen(ibuf)) < 0)
  2242. goto closeident;
  2243. /* get result */
  2244. p = &ibuf[0];
  2245. nleft = sizeof ibuf - 1;
  2246. while ((i = read(s, p, nleft)) > 0)
  2247. {
  2248. p += i;
  2249. nleft -= i;
  2250. *p = '';
  2251. if (strchr(ibuf, 'n') != NULL)
  2252. break;
  2253. }
  2254. (void) close(s);
  2255. clrevent(ev);
  2256. if (i < 0 || p == &ibuf[0])
  2257. goto noident;
  2258. if (*--p == 'n' && *--p == 'r')
  2259. p--;
  2260. *++p = '';
  2261. if (tTd(9, 3))
  2262. dprintf("getauthinfo:  got %sn", ibuf);
  2263. /* parse result */
  2264. p = strchr(ibuf, ':');
  2265. if (p == NULL)
  2266. {
  2267. /* malformed response */
  2268. goto noident;
  2269. }
  2270. while (isascii(*++p) && isspace(*p))
  2271. continue;
  2272. if (strncasecmp(p, "userid", 6) != 0)
  2273. {
  2274. /* presumably an error string */
  2275. goto noident;
  2276. }
  2277. p += 6;
  2278. while (isascii(*p) && isspace(*p))
  2279. p++;
  2280. if (*p++ != ':')
  2281. {
  2282. /* either useridxx or malformed response */
  2283. goto noident;
  2284. }
  2285. /* p now points to the OSTYPE field */
  2286. while (isascii(*p) && isspace(*p))
  2287. p++;
  2288. ostype = p;
  2289. p = strchr(p, ':');
  2290. if (p == NULL)
  2291. {
  2292. /* malformed response */
  2293. goto noident;
  2294. }
  2295. else
  2296. {
  2297. char *charset;
  2298. *p = '';
  2299. charset = strchr(ostype, ',');
  2300. if (charset != NULL)
  2301. *charset = '';
  2302. }
  2303. /* 1413 says don't do this -- but it's broken otherwise */
  2304. while (isascii(*++p) && isspace(*p))
  2305. continue;
  2306. /* p now points to the authenticated name -- copy carefully */
  2307. if (strncasecmp(ostype, "other", 5) == 0 &&
  2308.     (ostype[5] == ' ' || ostype[5] == ''))
  2309. {
  2310. snprintf(hbuf, sizeof hbuf, "IDENT:");
  2311. cleanstrcpy(&hbuf[6], p, MAXNAME);
  2312. }
  2313. else
  2314. cleanstrcpy(hbuf, p, MAXNAME);
  2315. i = strlen(hbuf);
  2316. snprintf(&hbuf[i], sizeof hbuf - i, "@%s",
  2317.  RealHostName == NULL ? "localhost" : RealHostName);
  2318. goto postident;
  2319. closeident:
  2320. (void) close(s);
  2321. clrevent(ev);
  2322. noident:
  2323. if (RealHostName == NULL)
  2324. {
  2325. if (tTd(9, 1))
  2326. dprintf("getauthinfo: NULLn");
  2327. return NULL;
  2328. }
  2329. snprintf(hbuf, sizeof hbuf, "%s", RealHostName);
  2330. postident:
  2331. # if IP_SRCROUTE
  2332. #  ifndef GET_IPOPT_DST
  2333. #   define GET_IPOPT_DST(dst) (dst)
  2334. #  endif /* ! GET_IPOPT_DST */
  2335. /*
  2336. **  Extract IP source routing information.
  2337. **
  2338. ** Format of output for a connection from site a through b
  2339. ** through c to d:
  2340. ** loose:      @site-c@site-b:site-a
  2341. ** strict:    !@site-c@site-b:site-a
  2342. **
  2343. ** o - pointer within ipopt_list structure.
  2344. ** q - pointer within ls/ss rr route data
  2345. ** p - pointer to hbuf
  2346. */
  2347. if (RealHostAddr.sa.sa_family == AF_INET)
  2348. {
  2349. SOCKOPT_LEN_T ipoptlen;
  2350. int j;
  2351. u_char *q;
  2352. u_char *o;
  2353. int l;
  2354. struct IPOPTION ipopt;
  2355. ipoptlen = sizeof ipopt;
  2356. if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
  2357.        (char *) &ipopt, &ipoptlen) < 0)
  2358. goto noipsr;
  2359. if (ipoptlen == 0)
  2360. goto noipsr;
  2361. o = (u_char *) ipopt.IP_LIST;
  2362. while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
  2363. {
  2364. switch (*o)
  2365. {
  2366.   case IPOPT_EOL:
  2367. o = NULL;
  2368. break;
  2369.   case IPOPT_NOP:
  2370. o++;
  2371. break;
  2372.   case IPOPT_SSRR:
  2373.   case IPOPT_LSRR:
  2374. /*
  2375. **  Source routing.
  2376. ** o[0] is the option type (loose/strict).
  2377. ** o[1] is the length of this option,
  2378. ** including option type and
  2379. ** length.
  2380. ** o[2] is the pointer into the route
  2381. ** data.
  2382. ** o[3] begins the route data.
  2383. */
  2384. p = &hbuf[strlen(hbuf)];
  2385. l = sizeof hbuf - (hbuf - p) - 6;
  2386. snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s",
  2387.     *o == IPOPT_SSRR ? "!" : "",
  2388.     l > 240 ? 120 : l / 2,
  2389.     inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST)));
  2390. i = strlen(p);
  2391. p += i;
  2392. l -= strlen(p);
  2393. j = o[1] / sizeof(struct in_addr) - 1;
  2394. /* q skips length and router pointer to data */
  2395. q = &o[3];
  2396. for ( ; j >= 0; j--)
  2397. {
  2398. struct in_addr addr;
  2399. memcpy(&addr, q, sizeof(addr));
  2400. snprintf(p, SPACELEFT(hbuf, p),
  2401.  "%c%.*s",
  2402.  j != 0 ? '@' : ':',
  2403.  l > 240 ? 120 :
  2404.  j == 0 ? l : l / 2,
  2405.  inet_ntoa(addr));
  2406. i = strlen(p);
  2407. p += i;
  2408. l -= i + 1;
  2409. q += sizeof(struct in_addr);
  2410. }
  2411. o += o[1];
  2412. break;
  2413.   default:
  2414. /* Skip over option */
  2415. o += o[1];
  2416. break;
  2417. }
  2418. }
  2419. snprintf(p, SPACELEFT(hbuf, p), "]");
  2420. goto postipsr;
  2421. }
  2422. noipsr:
  2423. # endif /* IP_SRCROUTE */
  2424. if (RealHostName != NULL && RealHostName[0] != '[')
  2425. {
  2426. p = &hbuf[strlen(hbuf)];
  2427. (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]",
  2428. anynet_ntoa(&RealHostAddr));
  2429. }
  2430. if (*may_be_forged)
  2431. {
  2432. p = &hbuf[strlen(hbuf)];
  2433. (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)");
  2434. }
  2435. # if IP_SRCROUTE
  2436. postipsr:
  2437. # endif /* IP_SRCROUTE */
  2438. if (tTd(9, 1))
  2439. dprintf("getauthinfo: %sn", hbuf);
  2440. return hbuf;
  2441. }
  2442. /*
  2443. **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
  2444. **
  2445. ** Parameters:
  2446. ** map -- a pointer to this map.
  2447. ** name -- the (presumably unqualified) hostname.
  2448. ** av -- unused -- for compatibility with other mapping
  2449. ** functions.
  2450. ** statp -- an exit status (out parameter) -- set to
  2451. ** EX_TEMPFAIL if the name server is unavailable.
  2452. **
  2453. ** Returns:
  2454. ** The mapping, if found.
  2455. ** NULL if no mapping found.
  2456. **
  2457. ** Side Effects:
  2458. ** Looks up the host specified in hbuf.  If it is not
  2459. ** the canonical name for that host, return the canonical
  2460. ** name (unless MF_MATCHONLY is set, which will cause the
  2461. ** status only to be returned).
  2462. */
  2463. char *
  2464. host_map_lookup(map, name, av, statp)
  2465. MAP *map;
  2466. char *name;
  2467. char **av;
  2468. int *statp;
  2469. {
  2470. register struct hostent *hp;
  2471. # if NETINET
  2472. struct in_addr in_addr;
  2473. # endif /* NETINET */
  2474. # if NETINET6
  2475. struct in6_addr in6_addr;
  2476. # endif /* NETINET6 */
  2477. char *cp, *ans = NULL;
  2478. register STAB *s;
  2479. char hbuf[MAXNAME + 1];
  2480. /*
  2481. **  See if we have already looked up this name.  If so, just
  2482. **  return it.
  2483. */
  2484. s = stab(name, ST_NAMECANON, ST_ENTER);
  2485. if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
  2486. {
  2487. if (tTd(9, 1))
  2488. dprintf("host_map_lookup(%s) => CACHE %sn",
  2489. name,
  2490. s->s_namecanon.nc_cname == NULL
  2491. ? "NULL"
  2492. : s->s_namecanon.nc_cname);
  2493. errno = s->s_namecanon.nc_errno;
  2494. # if NAMED_BIND
  2495. h_errno = s->s_namecanon.nc_herrno;
  2496. # endif /* NAMED_BIND */
  2497. *statp = s->s_namecanon.nc_stat;
  2498. if (*statp == EX_TEMPFAIL)
  2499. {
  2500. CurEnv->e_status = "4.4.3";
  2501. message("851 %s: Name server timeout",
  2502. shortenstring(name, 33));
  2503. }
  2504. if (*statp != EX_OK)
  2505. return NULL;
  2506. if (s->s_namecanon.nc_cname == NULL)
  2507. {
  2508. syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d",
  2509.        name,
  2510.        s->s_namecanon.nc_errno,
  2511.        s->s_namecanon.nc_herrno);
  2512. return NULL;
  2513. }
  2514. if (bitset(MF_MATCHONLY, map->map_mflags))
  2515. cp = map_rewrite(map, name, strlen(name), NULL);
  2516. else
  2517. cp = map_rewrite(map,
  2518.  s->s_namecanon.nc_cname,
  2519.  strlen(s->s_namecanon.nc_cname),
  2520.  av);
  2521. return cp;
  2522. }
  2523. /*
  2524. **  If we are running without a regular network connection (usually
  2525. **  dial-on-demand) and we are just queueing, we want to avoid DNS
  2526. **  lookups because those could try to connect to a server.
  2527. */
  2528. if (CurEnv->e_sendmode == SM_DEFER &&
  2529.     bitset(MF_DEFER, map->map_mflags))
  2530. {
  2531. if (tTd(9, 1))
  2532. dprintf("host_map_lookup(%s) => DEFERREDn", name);
  2533. *statp = EX_TEMPFAIL;
  2534. return NULL;
  2535. }
  2536. /*
  2537. **  If first character is a bracket, then it is an address
  2538. **  lookup.  Address is copied into a temporary buffer to
  2539. **  strip the brackets and to preserve name if address is
  2540. **  unknown.
  2541. */
  2542. if (tTd(9, 1))
  2543. dprintf("host_map_lookup(%s) => ", name);
  2544. if (*name != '[')
  2545. {
  2546. snprintf(hbuf, sizeof hbuf, "%s", name);
  2547. if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
  2548. ans = hbuf;
  2549. }
  2550. else
  2551. {
  2552. if ((cp = strchr(name, ']')) == NULL)
  2553. return NULL;
  2554. *cp = '';
  2555. hp = NULL;
  2556. # if NETINET
  2557. if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE)
  2558. hp = sm_gethostbyaddr((char *)&in_addr,
  2559.       INADDRSZ, AF_INET);
  2560. # endif /* NETINET */
  2561. # if NETINET6
  2562. if (hp == NULL &&
  2563.     inet_pton(AF_INET6, &name[1], &in6_addr) == 1)
  2564. hp = sm_gethostbyaddr((char *)&in6_addr,
  2565.       IN6ADDRSZ, AF_INET6);
  2566. # endif /* NETINET6 */
  2567. *cp = ']';
  2568. if (hp != NULL)
  2569. {
  2570. /* found a match -- copy out */
  2571. ans = denlstring((char *) hp->h_name, TRUE, TRUE);
  2572. }
  2573. }
  2574. s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
  2575. /* Found an answer */
  2576. if (ans != NULL)
  2577. {
  2578. s->s_namecanon.nc_stat = *statp = EX_OK;
  2579. s->s_namecanon.nc_cname = newstr(ans);
  2580. if (bitset(MF_MATCHONLY, map->map_mflags))
  2581. cp = map_rewrite(map, name, strlen(name), NULL);
  2582. else
  2583. cp = map_rewrite(map, ans, strlen(ans), av);
  2584. return cp;
  2585. }
  2586. /* No match found */
  2587. s->s_namecanon.nc_errno = errno;
  2588. # if NAMED_BIND
  2589. s->s_namecanon.nc_herrno = h_errno;
  2590. if (tTd(9, 1))
  2591. dprintf("FAIL (%d)n", h_errno);
  2592. switch (h_errno)
  2593. {
  2594.   case TRY_AGAIN:
  2595. if (UseNameServer)
  2596. {
  2597. CurEnv->e_status = "4.4.3";
  2598. message("851 %s: Name server timeout",
  2599. shortenstring(name, 33));
  2600. }
  2601. *statp = EX_TEMPFAIL;
  2602. break;
  2603.   case HOST_NOT_FOUND:
  2604.   case NO_DATA:
  2605. *statp = EX_NOHOST;
  2606. break;
  2607.   case NO_RECOVERY:
  2608. *statp = EX_SOFTWARE;
  2609. break;
  2610.   default:
  2611. *statp = EX_UNAVAILABLE;
  2612. break;
  2613. }
  2614. # else /* NAMED_BIND */
  2615. if (tTd(9, 1))
  2616. dprintf("FAILn");
  2617. *statp = EX_NOHOST;
  2618. # endif /* NAMED_BIND */
  2619. s->s_namecanon.nc_stat = *statp;
  2620. return NULL;
  2621. }
  2622. #else /* DAEMON */
  2623. /* code for systems without sophisticated networking */
  2624. /*
  2625. **  MYHOSTNAME -- stub version for case of no daemon code.
  2626. **
  2627. ** Can't convert to upper case here because might be a UUCP name.
  2628. **
  2629. ** Mark, you can change this to be anything you want......
  2630. */
  2631. char **
  2632. myhostname(hostbuf, size)
  2633. char hostbuf[];
  2634. int size;
  2635. {
  2636. register FILE *f;
  2637. hostbuf[0] = '';
  2638. f = fopen("/usr/include/whoami", "r");
  2639. if (f != NULL)
  2640. {
  2641. (void) fgets(hostbuf, size, f);
  2642. fixcrlf(hostbuf, TRUE);
  2643. (void) fclose(f);
  2644. }
  2645. return NULL;
  2646. }
  2647. /*
  2648. **  GETAUTHINFO -- get the real host name associated with a file descriptor
  2649. **
  2650. ** Parameters:
  2651. ** fd -- the descriptor
  2652. ** may_be_forged -- an outage that is set to TRUE if the
  2653. ** forward lookup of RealHostName does not match
  2654. ** RealHostAddr; set to FALSE if they do match.
  2655. **
  2656. ** Returns:
  2657. ** The host name associated with this descriptor, if it can
  2658. ** be determined.
  2659. ** NULL otherwise.
  2660. **
  2661. ** Side Effects:
  2662. ** none
  2663. */
  2664. char *
  2665. getauthinfo(fd, may_be_forged)
  2666. int fd;
  2667. bool *may_be_forged;
  2668. {
  2669. *may_be_forged = FALSE;
  2670. return NULL;
  2671. }
  2672. /*
  2673. **  HOST_MAP_LOOKUP -- turn a hostname into canonical form
  2674. **
  2675. ** Parameters:
  2676. ** map -- a pointer to the database map.
  2677. ** name -- a buffer containing a hostname.
  2678. ** avp -- a pointer to a (cf file defined) argument vector.
  2679. ** statp -- an exit status (out parameter).
  2680. **
  2681. ** Returns:
  2682. ** mapped host name
  2683. ** FALSE otherwise.
  2684. **
  2685. ** Side Effects:
  2686. ** Looks up the host specified in name.  If it is not
  2687. ** the canonical name for that host, replace it with
  2688. ** the canonical name.  If the name is unknown, or it
  2689. ** is already the canonical name, leave it unchanged.
  2690. */
  2691. /*ARGSUSED*/
  2692. char *
  2693. host_map_lookup(map, name, avp, statp)
  2694. MAP *map;
  2695. char *name;
  2696. char **avp;
  2697. char *statp;
  2698. {
  2699. register struct hostent *hp = NULL;
  2700. char *cp;
  2701. # if NETINET6
  2702. hp = sm_gethostbyname(name, AF_INET6);
  2703. # endif /* NETINET6 */
  2704. if (hp == NULL)
  2705. hp = sm_gethostbyname(name, AF_INET);
  2706. if (hp == NULL)
  2707. {
  2708. # if NAMED_BIND
  2709. if (tTd(9, 1))
  2710. dprintf("FAIL (%d)n", h_errno);
  2711. switch (h_errno)
  2712. {
  2713.   case TRY_AGAIN:
  2714. if (UseNameServer)
  2715. {
  2716. CurEnv->e_status = "4.4.3";
  2717. message("851 %s: Name server timeout",
  2718. shortenstring(name, 33));
  2719. }
  2720. *statp = EX_TEMPFAIL;
  2721. break;
  2722.   case HOST_NOT_FOUND:
  2723.   case NO_DATA:
  2724. *statp = EX_NOHOST;
  2725. break;
  2726.   case NO_RECOVERY:
  2727. *statp = EX_SOFTWARE;
  2728. break;
  2729.   default:
  2730. *statp = EX_UNAVAILABLE;
  2731. break;
  2732. }
  2733. #else /* NAMED_BIND */
  2734. *statp = EX_NOHOST;
  2735. #endif /* NAMED_BIND */
  2736. return NULL;
  2737. }
  2738. if (bitset(MF_MATCHONLY, map->map_mflags))
  2739. cp = map_rewrite(map, name, strlen(name), NULL);
  2740. else
  2741. cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp);
  2742. return cp;
  2743. }
  2744. #endif /* DAEMON */
  2745. /*
  2746. **  HOST_MAP_INIT -- initialize host class structures
  2747. */
  2748. bool
  2749. host_map_init(map, args)
  2750. MAP *map;
  2751. char *args;
  2752. {
  2753. register char *p = args;
  2754. for (;;)
  2755. {
  2756. while (isascii(*p) && isspace(*p))
  2757. p++;
  2758. if (*p != '-')
  2759. break;
  2760. switch (*++p)
  2761. {
  2762.   case 'a':
  2763. map->map_app = ++p;
  2764. break;
  2765.   case 'T':
  2766. map->map_tapp = ++p;
  2767. break;
  2768.   case 'm':
  2769. map->map_mflags |= MF_MATCHONLY;
  2770. break;
  2771.   case 't':
  2772. map->map_mflags |= MF_NODEFER;
  2773. break;
  2774.   case 'S': /* only for consistency */
  2775. map->map_spacesub = *++p;
  2776. break;
  2777.   case 'D':
  2778. map->map_mflags |= MF_DEFER;
  2779. break;
  2780. }
  2781. while (*p != '' && !(isascii(*p) && isspace(*p)))
  2782. p++;
  2783. if (*p != '')
  2784. *p++ = '';
  2785. }
  2786. if (map->map_app != NULL)
  2787. map->map_app = newstr(map->map_app);
  2788. if (map->map_tapp != NULL)
  2789. map->map_tapp = newstr(map->map_tapp);
  2790. return TRUE;
  2791. }
  2792. #if NETINET6
  2793. /*
  2794. **  ANYNET_NTOP -- convert an IPv6 network address to printable form.
  2795. **
  2796. ** Parameters:
  2797. ** s6a -- a pointer to an in6_addr structure.
  2798. ** dst -- buffer to store result in
  2799. ** dst_len -- size of dst buffer
  2800. **
  2801. ** Returns:
  2802. ** A printable version of that structure.
  2803. */
  2804. char *
  2805. anynet_ntop(s6a, dst, dst_len)
  2806. struct in6_addr *s6a;
  2807. char *dst;
  2808. size_t dst_len;
  2809. {
  2810. register char *ap;
  2811. if (IN6_IS_ADDR_V4MAPPED(s6a))
  2812. ap = (char *) inet_ntop(AF_INET,
  2813. &s6a->s6_addr[IN6ADDRSZ - INADDRSZ],
  2814. dst, dst_len);
  2815. else
  2816. ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len);
  2817. return ap;
  2818. }
  2819. #endif /* NETINET6 */
  2820. /*
  2821. **  ANYNET_NTOA -- convert a network address to printable form.
  2822. **
  2823. ** Parameters:
  2824. ** sap -- a pointer to a sockaddr structure.
  2825. **
  2826. ** Returns:
  2827. ** A printable version of that sockaddr.
  2828. */
  2829. #ifdef USE_SOCK_STREAM
  2830. # if NETLINK
  2831. #  include <net/if_dl.h>
  2832. # endif /* NETLINK */
  2833. char *
  2834. anynet_ntoa(sap)
  2835. register SOCKADDR *sap;
  2836. {
  2837. register char *bp;
  2838. register char *ap;
  2839. int l;
  2840. static char buf[100];
  2841. /* check for null/zero family */
  2842. if (sap == NULL)
  2843. return "NULLADDR";
  2844. if (sap->sa.sa_family == 0)
  2845. return "0";
  2846. switch (sap->sa.sa_family)
  2847. {
  2848. # if NETUNIX
  2849.   case AF_UNIX:
  2850. if (sap->sunix.sun_path[0] != '')
  2851. snprintf(buf, sizeof buf, "[UNIX: %.64s]",
  2852. sap->sunix.sun_path);
  2853. else
  2854. snprintf(buf, sizeof buf, "[UNIX: localhost]");
  2855. return buf;
  2856. # endif /* NETUNIX */
  2857. # if NETINET
  2858.   case AF_INET:
  2859. return (char *) inet_ntoa(sap->sin.sin_addr);
  2860. # endif /* NETINET */
  2861. # if NETINET6
  2862.   case AF_INET6:
  2863. ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf);
  2864. if (ap != NULL)
  2865. return ap;
  2866. break;
  2867. # endif /* NETINET6 */
  2868. # if NETLINK
  2869.   case AF_LINK:
  2870. snprintf(buf, sizeof buf, "[LINK: %s]",
  2871. link_ntoa((struct sockaddr_dl *) &sap->sa));
  2872. return buf;
  2873. # endif /* NETLINK */
  2874.   default:
  2875. /* this case is needed when nothing is #defined */
  2876. /* in order to keep the switch syntactically correct */
  2877. break;
  2878. }
  2879. /* unknown family -- just dump bytes */
  2880. (void) snprintf(buf, sizeof buf, "Family %d: ", sap->sa.sa_family);
  2881. bp = &buf[strlen(buf)];
  2882. ap = sap->sa.sa_data;
  2883. for (l = sizeof sap->sa.sa_data; --l >= 0; )
  2884. {
  2885. (void) snprintf(bp, SPACELEFT(buf, bp), "%02x:", *ap++ & 0377);
  2886. bp += 3;
  2887. }
  2888. *--bp = '';
  2889. return buf;
  2890. }
  2891. /*
  2892. **  HOSTNAMEBYANYADDR -- return name of host based on address
  2893. **
  2894. ** Parameters:
  2895. ** sap -- SOCKADDR pointer
  2896. **
  2897. ** Returns:
  2898. ** text representation of host name.
  2899. **
  2900. ** Side Effects:
  2901. ** none.
  2902. */
  2903. char *
  2904. hostnamebyanyaddr(sap)
  2905. register SOCKADDR *sap;
  2906. {
  2907. register struct hostent *hp;
  2908. # if NAMED_BIND
  2909. int saveretry;
  2910. # endif /* NAMED_BIND */
  2911. # if NETINET6
  2912. struct in6_addr in6_addr;
  2913. # endif /* NETINET6 */
  2914. # if NAMED_BIND
  2915. /* shorten name server timeout to avoid higher level timeouts */
  2916. saveretry = _res.retry;
  2917. if (_res.retry * _res.retrans > 20)
  2918. _res.retry = 20 / _res.retrans;
  2919. # endif /* NAMED_BIND */
  2920. switch (sap->sa.sa_family)
  2921. {
  2922. # if NETINET
  2923.   case AF_INET:
  2924. hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
  2925. INADDRSZ,
  2926. AF_INET);
  2927. break;
  2928. # endif /* NETINET */
  2929. # if NETINET6
  2930.   case AF_INET6:
  2931. hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr,
  2932.       IN6ADDRSZ,
  2933.       AF_INET6);
  2934. break;
  2935. # endif /* NETINET6 */
  2936. # if NETISO
  2937.   case AF_ISO:
  2938. hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
  2939. sizeof sap->siso.siso_addr,
  2940. AF_ISO);
  2941. break;
  2942. # endif /* NETISO */
  2943. # if NETUNIX
  2944.   case AF_UNIX:
  2945. hp = NULL;
  2946. break;
  2947. # endif /* NETUNIX */
  2948.   default:
  2949. hp = sm_gethostbyaddr(sap->sa.sa_data,
  2950.    sizeof sap->sa.sa_data,
  2951.    sap->sa.sa_family);
  2952. break;
  2953. }
  2954. # if NAMED_BIND
  2955. _res.retry = saveretry;
  2956. # endif /* NAMED_BIND */
  2957. # if NETINET || NETINET6
  2958. if (hp != NULL && hp->h_name[0] != '['
  2959. #  if NETINET6
  2960.     && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1
  2961. #  endif /* NETINET6 */
  2962. #  if NETINET
  2963.     && inet_addr(hp->h_name) == INADDR_NONE
  2964. #  endif /* NETINET */
  2965.     )
  2966. return denlstring((char *) hp->h_name, TRUE, TRUE);
  2967. # endif /* NETINET || NETINET6 */
  2968. # if NETUNIX
  2969. if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '')
  2970. return "localhost";
  2971. # endif /* NETUNIX */
  2972. {
  2973. static char buf[203];
  2974. (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap));
  2975. return buf;
  2976. }
  2977. }
  2978. #endif /* USE_SOCK_STREAM */