home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / in4wjcxu / other / irc / ircd / s_bsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-14  |  56.9 KB  |  2,353 lines

  1. /************************************************************************
  2.  *   IRC - Internet Relay Chat, ircd/s_bsd.c
  3.  *   Copyright (C) 1990 Jarkko Oikarinen and
  4.  *                      University of Oulu, Computing Center
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation; either version 1, or (at your option)
  9.  *   any later version.
  10.  *
  11.  *   This program is distributed in the hope that it will be useful,
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *   GNU General Public License for more details.
  15.  *
  16.  *   You should have received a copy of the GNU General Public License
  17.  *   along with this program; if not, write to the Free Software
  18.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* -- Jto -- 07 Jul 1990
  22.  * Added jlp@hamblin.byu.edu's debugtty fix
  23.  */
  24.  
  25. /* -- Armin -- Jun 18 1990
  26.  * Added setdtablesize() for more socket connections
  27.  * (sequent OS Dynix only) -- maybe select()-call must be changed ...
  28.  */
  29.  
  30. /* -- Jto -- 13 May 1990
  31.  * Added several fixes from msa:
  32.  *   Better error messages
  33.  *   Changes in check_access
  34.  * Added SO_REUSEADDR fix from zessel@informatik.uni-kl.de
  35.  */
  36.  
  37. #ifndef lint
  38. static  char sccsid[] = "@(#)s_bsd.c    2.78 2/7/94 (C) 1988 University of Oulu, \
  39. Computing Center and Jarkko Oikarinen";
  40. #endif
  41.  
  42. #include "struct.h"
  43. #include "common.h"
  44. #include "sys.h"
  45. #include "res.h"
  46. #include "numeric.h"
  47. #include "patchlevel.h"
  48. #include <sys/socket.h>
  49. #include <sys/file.h>
  50. #include <sys/ioctl.h>
  51. #if defined(SOL20)
  52. #include <sys/filio.h>
  53. #endif
  54. #if defined(UNIXPORT) && (!defined(SVR3) || defined(sgi) || \
  55.     defined(_SEQUENT_))
  56. # include <sys/un.h>
  57. #endif
  58. #include "inet.h"
  59. #include <stdio.h>
  60. #include <signal.h>
  61. #include <fcntl.h>
  62. #include <utmp.h>
  63. #include <sys/resource.h>
  64. #ifdef    AIX
  65. # include <time.h>
  66. # include <arpa/nameser.h>
  67. #else
  68. # include "nameser.h"
  69. #endif
  70. #include "resolv.h"
  71. #include "sock.h"    /* If FD_ZERO isn't define up to this point,  */
  72.             /* define it (BSD4.2 needs this) */
  73. #include "h.h"
  74.  
  75. #ifndef IN_LOOPBACKNET
  76. #define IN_LOOPBACKNET    0x7f
  77. #endif
  78.  
  79. aClient    *local[MAXCONNECTIONS];
  80. int    highest_fd = 0, readcalls = 0, udpfd = -1, resfd = -1;
  81. static    struct    sockaddr_in    mysk;
  82. static    void    polludp();
  83.  
  84. static    struct    sockaddr *connect_inet PROTO((aConfItem *, aClient *, int *));
  85. static    int    completed_connection PROTO((aClient *));
  86. static    int    check_init PROTO((aClient *, char *));
  87. static    void    do_dns_async PROTO(()), set_sock_opts PROTO((int, aClient *));
  88. #ifdef    UNIXPORT
  89. static    struct    sockaddr *connect_unix PROTO((aConfItem *, aClient *, int *));
  90. static    void    add_unixconnection PROTO((aClient *, int));
  91. static    char    unixpath[256];
  92. #endif
  93. static    char    readbuf[8192];
  94.  
  95. /*
  96.  * Try and find the correct name to use with getrlimit() for setting the max.
  97.  * number of files allowed to be open by this process.
  98.  */
  99. #ifdef RLIMIT_FDMAX
  100. # define RLIMIT_FD_MAX   RLIMIT_FDMAX
  101. #else
  102. # ifdef RLIMIT_NOFILE
  103. #  define RLIMIT_FD_MAX RLIMIT_NOFILE
  104. # else
  105. #  ifdef RLIMIT_OPEN_MAX
  106. #   define RLIMIT_FD_MAX RLIMIT_OPEN_MAX
  107. #  else
  108. #   undef RLIMIT_FD_MAX
  109. #  endif
  110. # endif
  111. #endif
  112.  
  113. /*
  114. ** add_local_domain()
  115. ** Add the domain to hostname, if it is missing
  116. ** (as suggested by eps@TOASTER.SFSU.EDU)
  117. */
  118.  
  119. void    add_local_domain(hname, size)
  120. char    *hname;
  121. int    size;
  122. {
  123. #ifdef RES_INIT
  124.     /* try to fix up unqualified names */
  125.     if (!index(hname, '.'))
  126.         {
  127.         if (!(_res.options & RES_INIT))
  128.             {
  129.             Debug((DEBUG_DNS,"res_init()"));
  130.             res_init();
  131.             }
  132.         if (_res.defdname[0])
  133.             {
  134.             (void)strncat(hname, ".", size-1);
  135.             (void)strncat(hname, _res.defdname, size-2);
  136.             }
  137.         }
  138. #endif
  139.     return;
  140. }
  141.  
  142. /*
  143. ** Cannot use perror() within daemon. stderr is closed in
  144. ** ircd and cannot be used. And, worse yet, it might have
  145. ** been reassigned to a normal connection...
  146. */
  147.  
  148. /*
  149. ** report_error
  150. **    This a replacement for perror(). Record error to log and
  151. **    also send a copy to all *LOCAL* opers online.
  152. **
  153. **    text    is a *format* string for outputting error. It must
  154. **        contain only two '%s', the first will be replaced
  155. **        by the sockhost from the cptr, and the latter will
  156. **        be taken from sys_errlist[errno].
  157. **
  158. **    cptr    if not NULL, is the *LOCAL* client associated with
  159. **        the error.
  160. */
  161. void    report_error(text, cptr)
  162. char    *text;
  163. aClient *cptr;
  164. {
  165.     Reg1    int    errtmp = errno; /* debug may change 'errno' */
  166.     Reg2    char    *host;
  167.     int    err, len = sizeof(err);
  168.     extern    char    *strerror();
  169.  
  170.     host = (cptr) ? get_client_name(cptr, FALSE) : "";
  171.  
  172.     Debug((DEBUG_ERROR, text, host, strerror(errtmp)));
  173.  
  174.     /*
  175.      * Get the *real* error from the socket (well try to anyway..).
  176.      * This may only work when SO_DEBUG is enabled but its worth the
  177.      * gamble anyway.
  178.      */
  179. #ifdef    SO_ERROR
  180.     if (!IsMe(cptr) && cptr->fd >= 0)
  181.         if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, &err, &len))
  182.             if (err)
  183.                 errtmp = err;
  184. #endif
  185.     sendto_ops(text, host, strerror(errtmp));
  186. #ifdef USE_SYSLOG
  187.     syslog(LOG_WARNING, text, host, strerror(errtmp));
  188. #endif
  189.     return;
  190. }
  191.  
  192. /*
  193.  * inetport
  194.  *
  195.  * Create a socket in the AF_INET domain, bind it to the port given in
  196.  * 'port' and listen to it.  Connections are accepted to this socket
  197.  * depending on the IP# mask given by 'name'.  Returns the fd of the
  198.  * socket created or -1 on error.
  199.  */
  200. int    inetport(cptr, name, port)
  201. aClient    *cptr;
  202. char    *name;
  203. int    port;
  204. {
  205.     static    struct sockaddr_in server;
  206.     int    ad[4], len = sizeof(server);
  207.     char    ipname[20];
  208.  
  209.     ad[0] = ad[1] = ad[2] = ad[3] = 0;
  210.  
  211.     /*
  212.      * do it this way because building ip# from separate values for each
  213.      * byte requires endian knowledge or some nasty messing. Also means
  214.      * easy conversion of "*" 0.0.0.0 or 134.* to 134.0.0.0 :-)
  215.      */
  216.     (void)sscanf(name, "%d.%d.%d.%d", &ad[0], &ad[1], &ad[2], &ad[3]);
  217.     (void)sprintf(ipname, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]);
  218.  
  219.     if (cptr != &me)
  220.         {
  221.         (void)sprintf(cptr->sockhost, "%-.42s.%.u",
  222.             name, (unsigned int)port);
  223.         (void)strcpy(cptr->name, me.name);
  224.         }
  225.     /*
  226.      * At first, open a new socket
  227.      */
  228.     if (cptr->fd == -1)
  229.         cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
  230.     if (cptr->fd < 0)
  231.         {
  232.         report_error("opening stream socket %s:%s", cptr);
  233.         return -1;
  234.         }
  235.     else if (cptr->fd >= MAXCLIENTS)
  236.         {
  237.         sendto_ops("No more connections allowed (%s)", cptr->name);
  238.         (void)close(cptr->fd);
  239.         return -1;
  240.         }
  241.     set_sock_opts(cptr->fd, cptr);
  242.     /*
  243.      * Bind a port to listen for new connections if port is non-null,
  244.      * else assume it is already open and try get something from it.
  245.      */
  246.     if (port)
  247.         {
  248.         server.sin_family = AF_INET;
  249.         server.sin_addr.s_addr = INADDR_ANY;
  250.         server.sin_port = htons(port);
  251.         /*
  252.          * Try 10 times to bind the socket with an interval of 20
  253.          * seconds. Do this so we dont have to keepp trying manually
  254.          * to bind. Why ? Because a port that has closed often lingers
  255.          * around for a short time.
  256.          * This used to be the case.  Now it no longer is.
  257.          * Could cause the server to hang for too long - avalon
  258.          */
  259.         if (bind(cptr->fd, &server, sizeof(server)) == -1)
  260.             {
  261.             report_error("binding stream socket %s:%s", cptr);
  262.             (void)close(cptr->fd);
  263.             return -1;
  264.             }
  265.         }
  266.     if (getsockname(cptr->fd, (struct sockaddr *)&server, &len))
  267.         {
  268.         report_error("getsockname failed for %s:%s",cptr);
  269.         (void)close(cptr->fd);
  270.         return -1;
  271.         }
  272.  
  273.     if (cptr == &me) /* KLUDGE to get it work... */
  274.         {
  275.         char    buf[1024];
  276.  
  277.         (void)sprintf(buf, rpl_str(RPL_MYPORTIS), me.name, "*",
  278.             ntohs(server.sin_port));
  279.         (void)write(0, buf, strlen(buf));
  280.         }
  281.     if (cptr->fd > highest_fd)
  282.         highest_fd = cptr->fd;
  283.     cptr->ip.s_addr = inet_addr(ipname);
  284.     cptr->port = (int)ntohs(server.sin_port);
  285.     (void)listen(cptr->fd, 5);
  286.     local[cptr->fd] = cptr;
  287.  
  288.     return 0;
  289. }
  290.  
  291. /*
  292.  * add_listener
  293.  *
  294.  * Create a new client which is essentially the stub like 'me' to be used
  295.  * for a socket that is passive (listen'ing for connections to be accepted).
  296.  */
  297. int    add_listener(aconf)
  298. aConfItem *aconf;
  299. {
  300.     aClient    *cptr;
  301.  
  302.     cptr = make_client(NULL);
  303.     cptr->flags = FLAGS_LISTEN;
  304.     cptr->acpt = cptr;
  305.     cptr->from = cptr;
  306.     SetMe(cptr);
  307.     strncpyzt(cptr->name, aconf->host, sizeof(cptr->name));
  308. #ifdef    UNIXPORT
  309.     if (*aconf->host == '/')
  310.         {
  311.         if (unixport(cptr, aconf->host, aconf->port))
  312.             cptr->fd = -2;
  313.         }
  314.     else
  315. #endif
  316.         if (inetport(cptr, aconf->host, aconf->port))
  317.             cptr->fd = -2;
  318.  
  319.     if (cptr->fd >= 0)
  320.         {
  321.         cptr->confs = make_link();
  322.         cptr->confs->next = NULL;
  323.         cptr->confs->value.aconf = aconf;
  324.         set_non_blocking(cptr->fd, cptr);
  325.         }
  326.     else
  327.         free_client(cptr);
  328.     return 0;
  329. }
  330.  
  331. #ifdef    UNIXPORT
  332. /*
  333.  * unixport
  334.  *
  335.  * Create a socket and bind it to a filename which is comprised of the path
  336.  * (directory where file is placed) and port (actual filename created).
  337.  * Set directory permissions as rwxr-xr-x so other users can connect to the
  338.  * file which is 'forced' to rwxrwxrwx (different OS's have different need of
  339.  * modes so users can connect to the socket).
  340.  */
  341. int    unixport(cptr, path, port)
  342. aClient    *cptr;
  343. char    *path;
  344. int    port;
  345. {
  346.     struct sockaddr_un un;
  347.  
  348.     if ((cptr->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  349.         {
  350.         report_error("error opening unix domain socket %s:%s", cptr);
  351.         return -1;
  352.         }
  353.     else if (cptr->fd >= MAXCLIENTS)
  354.         {
  355.         sendto_ops("No more connections allowed (%s)", cptr->name);
  356.         (void)close(cptr->fd);
  357.         return -1;
  358.         }
  359.  
  360.     un.sun_family = AF_UNIX;
  361.     (void)mkdir(path, 0755);
  362.     (void)sprintf(unixpath, "%s/%d", path, port);
  363.     (void)unlink(unixpath);
  364.     strncpyzt(un.sun_path, unixpath, sizeof(un.sun_path));
  365.     (void)strcpy(cptr->name, me.name);
  366.     errno = 0;
  367.     get_sockhost(cptr, unixpath);
  368.  
  369.     if (bind(cptr->fd, (struct sockaddr *)&un, strlen(unixpath)+2) == -1)
  370.         {
  371.         report_error("error binding unix socket %s:%s", cptr);
  372.         (void)close(cptr->fd);
  373.         return -1;
  374.         }
  375.     if (cptr->fd > highest_fd)
  376.         highest_fd = cptr->fd;
  377.     (void)listen(cptr->fd, 5);
  378.     (void)chmod(path, 0755);
  379.     (void)chmod(unixpath, 0777);
  380.     cptr->flags |= FLAGS_UNIX;
  381.     cptr->port = 0;
  382.     local[cptr->fd] = cptr;
  383.  
  384.     return 0;
  385. }
  386. #endif
  387.  
  388. /*
  389.  * close_listeners
  390.  *
  391.  * Close and free all clients which are marked as having their socket open
  392.  * and in a state where they can accept connections.  Unix sockets have
  393.  * the path to the socket unlinked for cleanliness.
  394.  */
  395. void    close_listeners()
  396. {
  397.     Reg1    aClient    *cptr;
  398.     Reg2    int    i;
  399.     Reg3    aConfItem *aconf;
  400.  
  401.     /*
  402.      * close all 'extra' listening ports we have and unlink the file
  403.      * name if it was a unix socket.
  404.      */
  405.     for (i = highest_fd; i >= 0; i--)
  406.         {
  407.         if (!(cptr = local[i]))
  408.             continue;
  409.         if (!IsMe(cptr) || cptr == &me || !IsListening(cptr))
  410.             continue;
  411.         aconf = cptr->confs->value.aconf;
  412.  
  413.         if (IsIllegal(aconf) && aconf->clients == 0)
  414.             {
  415. #ifdef    UNIXPORT
  416.             if (IsUnixSocket(cptr))
  417.                 {
  418.                 (void)sprintf(unixpath, "%s/%d", aconf->host,
  419.                     aconf->port);
  420.                 (void)unlink(unixpath);
  421.                 }
  422. #endif
  423.             close_connection(cptr);
  424.             }
  425.         }
  426. }
  427.  
  428. /*
  429.  * init_sys
  430.  */
  431. void    init_sys()
  432. {
  433.     Reg1    int    fd;
  434. #ifdef RLIMIT_FD_MAX
  435.     struct rlimit limit;
  436.  
  437.     if (!getrlimit(RLIMIT_FD_MAX, &limit))
  438.         {
  439. # ifdef    pyr
  440.         if (limit.rlim_cur < MAXCONNECTIONS)
  441. #else
  442.         if (limit.rlim_max < MAXCONNECTIONS)
  443. # endif
  444.             {
  445.             (void)fprintf(stderr,"ircd fd table too big\n");
  446.             (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
  447.                 limit.rlim_max, MAXCONNECTIONS);
  448.             (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
  449.             exit(-1);
  450.             }
  451. # ifndef    pyr
  452.         limit.rlim_cur = limit.rlim_max; /* make soft limit the max */
  453.         if (setrlimit(RLIMIT_FD_MAX, &limit) == -1)
  454.             {
  455.             (void)fprintf(stderr,"error setting max fd's to %d\n",
  456.                     limit.rlim_cur);
  457.             exit(-1);
  458.             }
  459. # endif
  460.         }
  461. #endif
  462. #ifdef sequent
  463. # ifndef    DYNIXPTX
  464.     int    fd_limit;
  465.  
  466.     fd_limit = setdtablesize(MAXCONNECTIONS + 1);
  467.     if (fd_limit < MAXCONNECTIONS)
  468.         {
  469.         (void)fprintf(stderr,"ircd fd table too big\n");
  470.         (void)fprintf(stderr,"Hard Limit: %d IRC max: %d\n",
  471.             fd_limit, MAXCONNECTIONS);
  472.         (void)fprintf(stderr,"Fix MAXCONNECTIONS\n");
  473.         exit(-1);
  474.         }
  475. # endif
  476. #endif
  477. #if defined(PCS) || defined(DYNIXPTX) || defined(SVR3)
  478.     char    logbuf[BUFSIZ];
  479.  
  480.     (void)setvbuf(stderr,logbuf,_IOLBF,sizeof(logbuf));
  481. #else
  482. # if defined(HPUX)
  483.     (void)setvbuf(stderr, NULL, _IOLBF, 0);
  484. # else
  485. #  if !defined(SOL20)
  486.     (void)setlinebuf(stderr);
  487. #  endif
  488. # endif
  489. #endif
  490.  
  491.     for (fd = 3; fd < MAXCONNECTIONS; fd++)
  492.         {
  493.         (void)close(fd);
  494.         local[fd] = NULL;
  495.         }
  496.     local[1] = NULL;
  497.     (void)close(1);
  498.  
  499.     if (bootopt & BOOT_TTY)    /* debugging is going to a tty */
  500.         goto init_dgram;
  501.     if (!(bootopt & BOOT_DEBUG))
  502.         (void)close(2);
  503.  
  504.     if (((bootopt & BOOT_CONSOLE) || isatty(0)) &&
  505.         !(bootopt & (BOOT_INETD|BOOT_OPER)))
  506.         {
  507.         if (fork())
  508.             exit(0);
  509. #ifdef TIOCNOTTY
  510.         if ((fd = open("/dev/tty", O_RDWR)) >= 0)
  511.             {
  512.             (void)ioctl(fd, TIOCNOTTY, (char *)NULL);
  513.             (void)close(fd);
  514.             }
  515. #endif
  516. #if defined(HPUX) || defined(SOL20) || defined(DYNIXPTX) || \
  517.     defined(_POSIX_SOURCE) || defined(SVR4)
  518.         (void)setsid();
  519. #else
  520.         (void)setpgrp(0, (int)getpid());
  521. #endif
  522.         (void)close(0);    /* fd 0 opened by inetd */
  523.         local[0] = NULL;
  524.         }
  525. init_dgram:
  526.     resfd = init_resolver(0x1f);
  527.  
  528.     return;
  529. }
  530.  
  531. void    write_pidfile()
  532. {
  533. #ifdef IRCD_PIDFILE
  534.     int fd;
  535.     char buff[20];
  536.     if ((fd = open(IRCD_PIDFILE, O_CREAT|O_WRONLY, 0600))>=0)
  537.         {
  538.         bzero(buff, sizeof(buff));
  539.         (void)sprintf(buff,"%5d\n", (int)getpid());
  540.         if (write(fd, buff, strlen(buff)) == -1)
  541.             Debug((DEBUG_NOTICE,"Error writing to pid file %s",
  542.                   IRCD_PIDFILE));
  543.         (void)close(fd);
  544.         return;
  545.         }
  546. #ifdef    DEBUGMODE
  547.     else
  548.         Debug((DEBUG_NOTICE,"Error opening pid file %s",
  549.             IRCD_PIDFILE));
  550. #endif
  551. #endif
  552. }
  553.         
  554. /*
  555.  * Initialize the various name strings used to store hostnames. This is set
  556.  * from either the server's sockhost (if client fd is a tty or localhost)
  557.  * or from the ip# converted into a string. 0 = success, -1 = fail.
  558.  */
  559. static    int    check_init(cptr, sockn)
  560. Reg1    aClient    *cptr;
  561. Reg2    char    *sockn;
  562. {
  563.     struct    sockaddr_in sk;
  564.     int    len = sizeof(struct sockaddr_in);
  565.  
  566. #ifdef    UNIXPORT
  567.     if (IsUnixSocket(cptr))
  568.         {
  569.         strncpyzt(sockn, cptr->acpt->sockhost, HOSTLEN+1);
  570.         get_sockhost(cptr, sockn);
  571.         return 0;
  572.         }
  573. #endif
  574.  
  575.     /* If descriptor is a tty, special checking... */
  576.     if (isatty(cptr->fd))
  577.         {
  578.         strncpyzt(sockn, me.sockhost, HOSTLEN);
  579.         bzero((char *)&sk, sizeof(struct sockaddr_in));
  580.         }
  581.     else if (getpeername(cptr->fd, &sk, &len) == -1)
  582.         {
  583.         report_error("connect failure: %s %s", cptr);
  584.         return -1;
  585.         }
  586.     (void)strcpy(sockn, (char *)inetntoa((char *)&sk.sin_addr));
  587.     if (inet_netof(sk.sin_addr) == IN_LOOPBACKNET)
  588.         {
  589.         cptr->hostp = NULL;
  590.         strncpyzt(sockn, me.sockhost, HOSTLEN);
  591.         }
  592.     bcopy((char *)&sk.sin_addr, (char *)&cptr->ip,
  593.         sizeof(struct in_addr));
  594.     cptr->port = (int)(ntohs(sk.sin_port));
  595.  
  596.     return 0;
  597. }
  598.  
  599. /*
  600.  * Ordinary client access check. Look for conf lines which have the same
  601.  * status as the flags passed.
  602.  *  0 = Success
  603.  * -1 = Access denied
  604.  * -2 = Bad socket.
  605.  */
  606. int    check_client(cptr)
  607. Reg1    aClient    *cptr;
  608. {
  609.     static    char    sockname[HOSTLEN+1];
  610.     Reg2    struct    hostent *hp = NULL;
  611.     Reg3    int    i;
  612.  
  613.     ClearAccess(cptr);
  614.     Debug((DEBUG_DNS, "ch_cl: check access for %s[%s]",
  615.         cptr->name, inetntoa((char *)&cptr->ip)));
  616.  
  617.     if (check_init(cptr, sockname))
  618.         return -2;
  619.  
  620.     if (!IsUnixSocket(cptr))
  621.         hp = cptr->hostp;
  622.     /*
  623.      * Verify that the host to ip mapping is correct both ways and that
  624.      * the ip#(s) for the socket is listed for the host.
  625.      */
  626.     if (hp)
  627.         {
  628.         for (i = 0; hp->h_addr_list[i]; i++)
  629.             if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
  630.                   sizeof(struct in_addr)))
  631.                 break;
  632.         if (!hp->h_addr_list[i])
  633.             {
  634.             sendto_ops("IP# Mismatch: %s != %s[%08x]",
  635.                    inetntoa((char *)&cptr->ip), hp->h_name,
  636.                    *((unsigned long *)hp->h_addr));
  637.             hp = NULL;
  638.             }
  639.         }
  640.  
  641.     if ((i = attach_Iline(cptr, hp, sockname)))
  642.         {
  643.         Debug((DEBUG_DNS,"ch_cl: access denied: %s[%s]",
  644.             cptr->name, sockname));
  645.         return i;
  646.         }
  647.  
  648.     Debug((DEBUG_DNS, "ch_cl: access ok: %s[%s]",
  649.         cptr->name, sockname));
  650.  
  651.     if (inet_netof(cptr->ip) == IN_LOOPBACKNET || IsUnixSocket(cptr) ||
  652.         inet_netof(cptr->ip) == inet_netof(mysk.sin_addr))
  653.         {
  654.         ircstp->is_loc++;
  655.         cptr->flags |= FLAGS_LOCAL;
  656.         }
  657.     return 0;
  658. }
  659.  
  660. #define    CFLAG    CONF_CONNECT_SERVER
  661. #define    NFLAG    CONF_NOCONNECT_SERVER
  662. /*
  663.  * check_server_init(), check_server()
  664.  *    check access for a server given its name (passed in cptr struct).
  665.  *    Must check for all C/N lines which have a name which matches the
  666.  *    name given and a host which matches. A host alias which is the
  667.  *    same as the server name is also acceptable in the host field of a
  668.  *    C/N line.
  669.  *  0 = Success
  670.  * -1 = Access denied
  671.  * -2 = Bad socket.
  672.  */
  673. int    check_server_init(cptr)
  674. aClient    *cptr;
  675. {
  676.     Reg1    char    *name;
  677.     Reg2    aConfItem *c_conf = NULL, *n_conf = NULL;
  678.     struct    hostent    *hp = NULL;
  679.     Link    *lp;
  680.  
  681.     name = cptr->name;
  682.     Debug((DEBUG_DNS, "sv_cl: check access for %s[%s]",
  683.         name, cptr->sockhost));
  684.  
  685.     if (IsUnknown(cptr) && !attach_confs(cptr, name, CFLAG|NFLAG))
  686.         {
  687.         Debug((DEBUG_DNS,"No C/N lines for %s", name));
  688.         return -1;
  689.         }
  690.     lp = cptr->confs;
  691.     /*
  692.      * We initiated this connection so the client should have a C and N
  693.      * line already attached after passing through the connec_server()
  694.      * function earlier.
  695.      */
  696.     if (IsConnecting(cptr) || IsHandshake(cptr))
  697.         {
  698.         c_conf = find_conf(lp, name, CFLAG);
  699.         n_conf = find_conf(lp, name, NFLAG);
  700.         if (!c_conf || !n_conf)
  701.             {
  702.             sendto_ops("Connecting Error: %s[%s]", name,
  703.                    cptr->sockhost);
  704.             det_confs_butmask(cptr, 0);
  705.             return -1;
  706.             }
  707.         }
  708. #ifdef    UNIXPORT
  709.     if (IsUnixSocket(cptr))
  710.         {
  711.         if (!c_conf)
  712.             c_conf = find_conf(lp, name, CFLAG);
  713.         if (!n_conf)
  714.             n_conf = find_conf(lp, name, NFLAG);
  715.         }
  716. #endif
  717.  
  718.     /*
  719.     ** If the servername is a hostname, either an alias (CNAME) or
  720.     ** real name, then check with it as the host. Use gethostbyname()
  721.     ** to check for servername as hostname.
  722.     */
  723.     if (!IsUnixSocket(cptr) && !cptr->hostp)
  724.         {
  725.         Reg1    aConfItem *aconf;
  726.  
  727.         aconf = count_cnlines(lp);
  728.         if (aconf)
  729.             {
  730.             Reg1    char    *s;
  731.             Link    lin;
  732.  
  733.             /*
  734.             ** Do a lookup for the CONF line *only* and not
  735.             ** the server connection else we get stuck in a
  736.             ** nasty state since it takes a SERVER message to
  737.             ** get us here and we cant interrupt that very
  738.             ** well.
  739.             */
  740.             ClearAccess(cptr);
  741.             lin.value.aconf = aconf;
  742.             lin.flags = ASYNC_CONF;
  743.             nextdnscheck = 1;
  744.             if ((s = index(aconf->host, '@')))
  745.                 s++;
  746.             else
  747.                 s = aconf->host;
  748.             Debug((DEBUG_DNS,"sv_ci:cache lookup (%s)",s));
  749.             hp = gethost_byname(s, &lin);
  750.             }
  751.         }
  752.     return check_server(cptr, hp, c_conf, n_conf, 0);
  753. }
  754.  
  755. int    check_server(cptr, hp, c_conf, n_conf, estab)
  756. aClient    *cptr;
  757. Reg1    aConfItem    *n_conf, *c_conf;
  758. Reg2    struct    hostent    *hp;
  759. int    estab;
  760. {
  761.     Reg3    char    *name;
  762.     char    abuff[HOSTLEN+USERLEN+2];
  763.     char    sockname[HOSTLEN+1], fullname[HOSTLEN+1];
  764.     Link    *lp = cptr->confs;
  765.     int    i;
  766.  
  767.     ClearAccess(cptr);
  768.     if (check_init(cptr, sockname))
  769.         return -2;
  770.  
  771. check_serverback:
  772.     if (hp)
  773.         {
  774.         for (i = 0; hp->h_addr_list[i]; i++)
  775.             if (!bcmp(hp->h_addr_list[i], (char *)&cptr->ip,
  776.                   sizeof(struct in_addr)))
  777.                 break;
  778.         if (!hp->h_addr_list[i])
  779.             {
  780.             sendto_ops("IP# Mismatch: %s != %s[%08x]",
  781.                    inetntoa((char *)&cptr->ip), hp->h_name,
  782.                    *((unsigned long *)hp->h_addr));
  783.             hp = NULL;
  784.             }
  785.         }
  786.     else if (cptr->hostp)
  787.         {
  788.         hp = cptr->hostp;
  789.         goto check_serverback;
  790.         }
  791.  
  792.     if (hp)
  793.         /*
  794.          * if we are missing a C or N line from above, search for
  795.          * it under all known hostnames we have for this ip#.
  796.          */
  797.         for (i=0,name = hp->h_name; name ; name = hp->h_aliases[i++])
  798.             {
  799.             strncpyzt(fullname, name, sizeof(fullname));
  800.             add_local_domain(fullname, HOSTLEN-strlen(fullname));
  801.             Debug((DEBUG_DNS, "sv_cl: gethostbyaddr: %s->%s",
  802.                 sockname, fullname));
  803.             (void)sprintf(abuff, "%s@%s",
  804.                 cptr->username, fullname);
  805.             if (!c_conf)
  806.                 c_conf = find_conf_host(lp, abuff, CFLAG);
  807.             if (!n_conf)
  808.                 n_conf = find_conf_host(lp, abuff, NFLAG);
  809.             if (c_conf && n_conf)
  810.                 {
  811.                 get_sockhost(cptr, fullname);
  812.                 break;
  813.                 }
  814.             }
  815.     name = cptr->name;
  816.  
  817.     /*
  818.      * Check for C and N lines with the hostname portion the ip number
  819.      * of the host the server runs on. This also checks the case where
  820.      * there is a server connecting from 'localhost'.
  821.      */
  822.     if (IsUnknown(cptr) && (!c_conf || !n_conf))
  823.         {
  824.         (void)sprintf(abuff, "%s@%s", cptr->username, sockname);
  825.         if (!c_conf)
  826.             c_conf = find_conf_host(lp, abuff, CFLAG);
  827.         if (!n_conf)
  828.             n_conf = find_conf_host(lp, abuff, NFLAG);
  829.         }
  830.     /*
  831.      * Attach by IP# only if all other checks have failed.
  832.      * It is quite possible to get here with the strange things that can
  833.      * happen when using DNS in the way the irc server does. -avalon
  834.      */
  835.     if (!hp)
  836.         {
  837.         if (!c_conf)
  838.             c_conf = find_conf_ip(lp, (char *)&cptr->ip,
  839.                           cptr->username, CFLAG);
  840.         if (!n_conf)
  841.             n_conf = find_conf_ip(lp, (char *)&cptr->ip,
  842.                           cptr->username, NFLAG);
  843.         }
  844.     else
  845.         for (i = 0; hp->h_addr_list[i]; i++)
  846.             {
  847.             if (!c_conf)
  848.                 c_conf = find_conf_ip(lp, hp->h_addr_list[i],
  849.                               cptr->username, CFLAG);
  850.             if (!n_conf)
  851.                 n_conf = find_conf_ip(lp, hp->h_addr_list[i],
  852.                               cptr->username, NFLAG);
  853.             }
  854.     /*
  855.      * detach all conf lines that got attached by attach_confs()
  856.      */
  857.     det_confs_butmask(cptr, 0);
  858.     /*
  859.      * if no C or no N lines, then deny access
  860.      */
  861.     if (!c_conf || !n_conf)
  862.         {
  863.         get_sockhost(cptr, sockname);
  864.         Debug((DEBUG_DNS, "sv_cl: access denied: %s[%s@%s] c %x n %x",
  865.             name, cptr->username, cptr->sockhost,
  866.             c_conf, n_conf));
  867.         return -1;
  868.         }
  869.     /*
  870.      * attach the C and N lines to the client structure for later use.
  871.      */
  872.     (void)attach_conf(cptr, n_conf);
  873.     (void)attach_conf(cptr, c_conf);
  874.     (void)attach_confs(cptr, name, CONF_HUB|CONF_LEAF);
  875.  
  876.     if ((c_conf->ipnum.s_addr == -1) && !IsUnixSocket(cptr))
  877.         bcopy((char *)&cptr->ip, (char *)&c_conf->ipnum,
  878.             sizeof(struct in_addr));
  879.     if (!IsUnixSocket(cptr))
  880.         get_sockhost(cptr, c_conf->host);
  881.  
  882.     Debug((DEBUG_DNS,"sv_cl: access ok: %s[%s]",
  883.         name, cptr->sockhost));
  884.     if (estab)
  885.         return m_server_estab(cptr);
  886.     return 0;
  887. }
  888. #undef    CFLAG
  889. #undef    NFLAG
  890.  
  891. /*
  892. ** completed_connection
  893. **    Complete non-blocking connect()-sequence. Check access and
  894. **    terminate connection, if trouble detected.
  895. **
  896. **    Return    TRUE, if successfully completed
  897. **        FALSE, if failed and ClientExit
  898. */
  899. static    int completed_connection(cptr)
  900. aClient    *cptr;
  901. {
  902.     aConfItem *aconf;
  903.  
  904.     SetHandshake(cptr);
  905.     
  906.     aconf = find_conf(cptr->confs, cptr->name, CONF_CONNECT_SERVER);
  907.     if (!aconf)
  908.         {
  909.         sendto_ops("Lost C-Line for %s", get_client_name(cptr,FALSE));
  910.         return -1;
  911.         }
  912.     if (!BadPtr(aconf->passwd))
  913.         sendto_one(cptr, "PASS :%s", aconf->passwd);
  914.  
  915.     aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER);
  916.     if (!aconf)
  917.         {
  918.         sendto_ops("Lost N-Line for %s", get_client_name(cptr,FALSE));
  919.         return -1;
  920.         }
  921.     sendto_one(cptr, "SERVER %s 1 :%s",
  922.            my_name_for_link(me.name, aconf), me.info);
  923.     if (!IsDead(cptr))
  924.         start_auth(cptr);
  925.  
  926.     return (IsDead(cptr)) ? -1 : 0;
  927. }
  928.  
  929. /*
  930. ** close_connection
  931. **    Close the physical connection. This function must make
  932. **    MyConnect(cptr) == FALSE, and set cptr->from == NULL.
  933. */
  934. void    close_connection(cptr)
  935. aClient *cptr;
  936. {
  937.         Reg1    aConfItem *aconf;
  938.     Reg2    int    i,j;
  939.     int    empty = cptr->fd;
  940.  
  941.     if (IsServer(cptr))
  942.         {
  943.         ircstp->is_sv++;
  944.         ircstp->is_sbs += cptr->sendB;
  945.         ircstp->is_sbr += cptr->receiveB;
  946.         ircstp->is_sks += cptr->sendK;
  947.         ircstp->is_skr += cptr->receiveK;
  948.         ircstp->is_sti += time(NULL) - cptr->firsttime;
  949.         if (ircstp->is_sbs > 1023)
  950.             {
  951.             ircstp->is_sks += (ircstp->is_sbs >> 10);
  952.             ircstp->is_sbs &= 0x3ff;
  953.             }
  954.         if (ircstp->is_sbr > 1023)
  955.             {
  956.             ircstp->is_skr += (ircstp->is_sbr >> 10);
  957.             ircstp->is_sbr &= 0x3ff;
  958.             }
  959.         }
  960.     else if (IsClient(cptr))
  961.         {
  962.         ircstp->is_cl++;
  963.         ircstp->is_cbs += cptr->sendB;
  964.         ircstp->is_cbr += cptr->receiveB;
  965.         ircstp->is_cks += cptr->sendK;
  966.         ircstp->is_ckr += cptr->receiveK;
  967.         ircstp->is_cti += time(NULL) - cptr->firsttime;
  968.         if (ircstp->is_cbs > 1023)
  969.             {
  970.             ircstp->is_cks += (ircstp->is_cbs >> 10);
  971.             ircstp->is_cbs &= 0x3ff;
  972.             }
  973.         if (ircstp->is_cbr > 1023)
  974.             {
  975.             ircstp->is_ckr += (ircstp->is_cbr >> 10);
  976.             ircstp->is_cbr &= 0x3ff;
  977.             }
  978.         }
  979.     else
  980.         ircstp->is_ni++;
  981.  
  982.     /*
  983.      * remove outstanding DNS queries.
  984.      */
  985.     del_queries((char *)cptr);
  986.     /*
  987.      * If the connection has been up for a long amount of time, schedule
  988.      * a 'quick' reconnect, else reset the next-connect cycle.
  989.      */
  990.     if ((aconf = find_conf_exact(cptr->name, cptr->username,
  991.                     cptr->sockhost, CONF_CONNECT_SERVER)))
  992.         {
  993.         /*
  994.          * Reschedule a faster reconnect, if this was a automaticly
  995.          * connected configuration entry. (Note that if we have had
  996.          * a rehash in between, the status has been changed to
  997.          * CONF_ILLEGAL). But only do this if it was a "good" link.
  998.          */
  999.         aconf->hold = time(NULL);
  1000.         aconf->hold += (aconf->hold - cptr->since > HANGONGOODLINK) ?
  1001.                 HANGONRETRYDELAY : ConfConFreq(aconf);
  1002.         if (nextconnect > aconf->hold)
  1003.             nextconnect = aconf->hold;
  1004.         }
  1005.  
  1006.     if (cptr->authfd >= 0)
  1007.         (void)close(cptr->authfd);
  1008.  
  1009.     if (cptr->fd >= 0)
  1010.         {
  1011.         flush_connections(cptr->fd);
  1012.         local[cptr->fd] = NULL;
  1013.         (void)close(cptr->fd);
  1014.         cptr->fd = -2;
  1015.         DBufClear(&cptr->sendQ);
  1016.         DBufClear(&cptr->recvQ);
  1017.         bzero(cptr->passwd, sizeof(cptr->passwd));
  1018.         /*
  1019.          * clean up extra sockets from P-lines which have been
  1020.          * discarded.
  1021.          */
  1022.         if (cptr->acpt != &me && cptr->acpt != cptr)
  1023.             {
  1024.             aconf = cptr->acpt->confs->value.aconf;
  1025.             if (aconf->clients > 0)
  1026.                 aconf->clients--;
  1027.             if (!aconf->clients && IsIllegal(aconf))
  1028.                 close_connection(cptr->acpt);
  1029.             }
  1030.         }
  1031.     for (; highest_fd > 0; highest_fd--)
  1032.         if (local[highest_fd])
  1033.             break;
  1034.  
  1035.     det_confs_butmask(cptr, 0);
  1036.     cptr->from = NULL; /* ...this should catch them! >:) --msa */
  1037.  
  1038.     /*
  1039.      * fd remap to keep local[i] filled at the bottom.
  1040.      */
  1041.     if (empty > 0)
  1042.         if ((j = highest_fd) > (i = empty) &&
  1043.             (local[j]->status != STAT_LOG))
  1044.             {
  1045.             if (dup2(j,i) == -1)
  1046.                 return;
  1047.             local[i] = local[j];
  1048.             local[i]->fd = i;
  1049.             local[j] = NULL;
  1050.             (void)close(j);
  1051.             while (!local[highest_fd])
  1052.                 highest_fd--;
  1053.             }
  1054.     return;
  1055. }
  1056.  
  1057. /*
  1058. ** set_sock_opts
  1059. */
  1060. static    void    set_sock_opts(fd, cptr)
  1061. int    fd;
  1062. aClient    *cptr;
  1063. {
  1064.     int    opt;
  1065. #ifdef SO_REUSEADDR
  1066.     opt = 1;
  1067.     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
  1068.         report_error("setsockopt(SO_REUSEADDR) %s:%s", cptr);
  1069. #endif
  1070. #if  defined(SO_DEBUG) && defined(DEBUGMODE) && 0
  1071. /* Solaris with SO_DEBUG writes to syslog by default */
  1072. #if !defined(SOL20) || defined(USE_SYSLOG)
  1073.     opt = 1;
  1074.     if (setsockopt(fd, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) < 0)
  1075.         report_error("setsockopt(SO_DEBUG) %s:%s", cptr);
  1076. #endif /* SOL20 */
  1077. #endif
  1078. #ifdef    SO_USELOOPBACK
  1079.     opt = 1;
  1080.     if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, &opt, sizeof(opt)) < 0)
  1081.         report_error("setsockopt(SO_USELOOPBACK) %s:%s", cptr);
  1082. #endif
  1083. #ifdef    SO_RCVBUF
  1084.     opt = 8192;
  1085.     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0)
  1086.         report_error("setsockopt(SO_RCVBUF) %s:%s", cptr);
  1087. #endif
  1088. #ifdef    SO_SNDBUF
  1089. # ifdef    _SEQUENT_
  1090. /* seems that Sequent freezes up if the receving buffer is a different size
  1091.  * to the sending buffer (maybe a tcp window problem too).
  1092.  */
  1093.     opt = 8192;
  1094. # else
  1095.     opt = 8192;
  1096. # endif
  1097.     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0)
  1098.         report_error("setsockopt(SO_SNDBUF) %s:%s", cptr);
  1099. #endif
  1100. #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
  1101.     {
  1102.     char    *s = readbuf, *t = readbuf + sizeof(readbuf) / 2;
  1103.  
  1104.     opt = sizeof(readbuf) / 8;
  1105.     if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, t, &opt) < 0)
  1106.         report_error("getsockopt(IP_OPTIONS) %s:%s", cptr);
  1107.     else if (opt > 0)
  1108.         {
  1109.         for (*readbuf = '\0'; opt > 0; opt--, s+= 3)
  1110.             (void)sprintf(s, "%02.2x:", *t++);
  1111.         *s = '\0';
  1112.         sendto_ops("Connection %s using IP opts: (%s)",
  1113.                get_client_name(cptr, TRUE), readbuf);
  1114.         }
  1115.     if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, (char *)NULL, 0) < 0)
  1116.         report_error("setsockopt(IP_OPTIONS) %s:%s", cptr);
  1117.     }
  1118. #endif
  1119. }
  1120.  
  1121.  
  1122. int    get_sockerr(cptr)
  1123. aClient    *cptr;
  1124. {
  1125.     int errtmp = errno, err = 0, len = sizeof(err);
  1126. #ifdef    SO_ERROR
  1127.     if (cptr->fd >= 0)
  1128.         if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, &err, &len))
  1129.             if (err)
  1130.                 errtmp = err;
  1131. #endif
  1132.     return errtmp;
  1133. }
  1134.  
  1135. /*
  1136. ** set_non_blocking
  1137. **    Set the client connection into non-blocking mode. If your
  1138. **    system doesn't support this, you can make this a dummy
  1139. **    function (and get all the old problems that plagued the
  1140. **    blocking version of IRC--not a problem if you are a
  1141. **    lightly loaded node...)
  1142. */
  1143. void    set_non_blocking(fd, cptr)
  1144. int    fd;
  1145. aClient *cptr;
  1146. {
  1147.     int    res, nonb = 0;
  1148.  
  1149.     /*
  1150.     ** NOTE: consult ALL your relevant manual pages *BEFORE* changing
  1151.     **     these ioctl's.  There are quite a few variations on them,
  1152.     **     as can be seen by the PCS one.  They are *NOT* all the same.
  1153.     **     Heed this well. - Avalon.
  1154.     */
  1155. #ifdef    NBLOCK_POSIX
  1156.     nonb |= O_NONBLOCK;
  1157. #endif
  1158. #ifdef    NBLOCK_BSD
  1159.     nonb |= O_NDELAY;
  1160. #endif
  1161. #ifdef    NBLOCK_SYSV
  1162.     /* This portion of code might also apply to NeXT.  -LynX */
  1163.     res = 1;
  1164.  
  1165.     if (ioctl (fd, FIONBIO, &res) < 0)
  1166.         report_error("ioctl(fd,FIONBIO) failed for %s:%s", cptr);
  1167. #else
  1168.     if ((res = fcntl(fd, F_GETFL, 0)) == -1)
  1169.         report_error("fcntl(fd, F_GETFL) failed for %s:%s",cptr);
  1170.     else if (fcntl(fd, F_SETFL, res | nonb) == -1)
  1171.         report_error("fcntl(fd, F_SETL, nonb) failed for %s:%s",cptr);
  1172. #endif
  1173.     return;
  1174. }
  1175.  
  1176. /*
  1177.  * Creates a client which has just connected to us on the given fd.
  1178.  * The sockhost field is initialized with the ip# of the host.
  1179.  * The client is added to the linked list of clients but isnt added to any
  1180.  * hash tables yuet since it doesnt have a name.
  1181.  */
  1182. aClient    *add_connection(cptr, fd)
  1183. aClient    *cptr;
  1184. int    fd;
  1185. {
  1186.     Link    lin;
  1187.     aClient *acptr;
  1188.     aConfItem *aconf = NULL;
  1189.     acptr = make_client(NULL);
  1190.  
  1191.     if (cptr != &me)
  1192.         aconf = cptr->confs->value.aconf;
  1193.     /* Removed preliminary access check. Full check is performed in
  1194.      * m_server and m_user instead. Also connection time out help to
  1195.      * get rid of unwanted connections.
  1196.      */
  1197.     if (isatty(fd)) /* If descriptor is a tty, special checking... */
  1198.         get_sockhost(acptr, cptr->sockhost);
  1199.     else
  1200.         {
  1201.         Reg1    char    *s, *t;
  1202.         struct    sockaddr_in addr;
  1203.         int    len = sizeof(struct sockaddr_in);
  1204.  
  1205.         if (getpeername(fd, (struct sockaddr *) &addr, &len) == -1)
  1206.             {
  1207.             report_error("Failed in connecting to %s :%s", cptr);
  1208. add_con_refuse:
  1209.             ircstp->is_ref++;
  1210.             acptr->fd = -2;
  1211.             free_client(acptr);
  1212.             (void)close(fd);
  1213.             return NULL;
  1214.             }
  1215.         /* don't want to add "Failed in connecting to" here.. */
  1216.         if (aconf && IsIllegal(aconf))
  1217.             goto add_con_refuse;
  1218.         /* Copy ascii address to 'sockhost' just in case. Then we
  1219.          * have something valid to put into error messages...
  1220.          */
  1221.         get_sockhost(acptr, (char *)inetntoa((char *)&addr.sin_addr));
  1222.         bcopy ((char *)&addr.sin_addr, (char *)&acptr->ip,
  1223.             sizeof(struct in_addr));
  1224.         acptr->port = ntohs(addr.sin_port);
  1225.  
  1226.         /*
  1227.          * Check that this socket (client) is allowed to accept
  1228.          * connections from this IP#.
  1229.          */
  1230.         for (s = (char *)&cptr->ip, t = (char *)&acptr->ip, len = 4;
  1231.              len > 0; len--, s++, t++)
  1232.             {
  1233.             if (!*s)
  1234.                 continue;
  1235.             if (*s != *t)
  1236.                 break;
  1237.             }
  1238.  
  1239.         if (len)
  1240.             goto add_con_refuse;
  1241.  
  1242.         lin.flags = ASYNC_CLIENT;
  1243.         lin.value.cptr = acptr;
  1244.         Debug((DEBUG_DNS, "lookup %s",
  1245.             inetntoa((char *)&addr.sin_addr)));
  1246.         acptr->hostp = gethost_byaddr((char *)&acptr->ip, &lin);
  1247.         if (!acptr->hostp)
  1248.             SetDNS(acptr);
  1249.         nextdnscheck = 1;
  1250.         }
  1251.  
  1252.     if (aconf)
  1253.         aconf->clients++;
  1254.     acptr->fd = fd;
  1255.     if (fd > highest_fd)
  1256.         highest_fd = fd;
  1257.     local[fd] = acptr;
  1258.     acptr->acpt = cptr;
  1259.     add_client_to_list(acptr);
  1260.     set_non_blocking(acptr->fd, acptr);
  1261.     set_sock_opts(acptr->fd, acptr);
  1262.     start_auth(acptr);
  1263.     return acptr;
  1264. }
  1265.  
  1266. #ifdef    UNIXPORT
  1267. static    void    add_unixconnection(cptr, fd)
  1268. aClient    *cptr;
  1269. int    fd;
  1270. {
  1271.     aClient *acptr;
  1272.     aConfItem *aconf = NULL;
  1273.  
  1274.     acptr = make_client(NULL);
  1275.  
  1276.     /* Copy ascii address to 'sockhost' just in case. Then we
  1277.      * have something valid to put into error messages...
  1278.      */
  1279.     get_sockhost(acptr, me.sockhost);
  1280.     if (cptr != &me)
  1281.         aconf = cptr->confs->value.aconf;
  1282.     if (aconf)
  1283.         {
  1284.         if (IsIllegal(aconf))
  1285.             {
  1286.             ircstp->is_ref++;
  1287.             acptr->fd = -2;
  1288.             free_client(acptr);
  1289.             (void)close(fd);
  1290.             return;
  1291.             }
  1292.         else
  1293.             aconf->clients++;
  1294.         }
  1295.     acptr->fd = fd;
  1296.     if (fd > highest_fd)
  1297.         highest_fd = fd;
  1298.     local[fd] = acptr;
  1299.     acptr->acpt = cptr;
  1300.     SetUnixSock(acptr);
  1301.     bcopy((char *)&me.ip, (char *)&acptr->ip, sizeof(struct in_addr));
  1302.  
  1303.     add_client_to_list(acptr);
  1304.     set_non_blocking(acptr->fd, acptr);
  1305.     set_sock_opts(acptr->fd, acptr);
  1306.     SetAccess(acptr);
  1307.     return;
  1308. }
  1309. #endif
  1310.  
  1311. /*
  1312. ** read_packet
  1313. **
  1314. ** Read a 'packet' of data from a connection and process it.  Read in 8k
  1315. ** chunks to give a better performance rating (for server connections).
  1316. ** Do some tricky stuff for client connections to make sure they don't do
  1317. ** any flooding >:-) -avalon
  1318. */
  1319. static    int    read_packet(cptr, rfd)
  1320. Reg1    aClient *cptr;
  1321. fd_set    *rfd;
  1322. {
  1323.     Reg1    int    dolen = 0, length = 0, done;
  1324.     time_t    now = time(NULL);
  1325.  
  1326.     if (FD_ISSET(cptr->fd, rfd) &&
  1327.         !(IsPerson(cptr) && DBufLength(&cptr->recvQ) > 6090))
  1328.         {
  1329.         errno = 0;
  1330.         length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
  1331.  
  1332.         cptr->lasttime = now;
  1333.         if (cptr->lasttime > cptr->since)
  1334.             cptr->since = cptr->lasttime;
  1335.         cptr->flags &= ~(FLAGS_PINGSENT|FLAGS_NONL);
  1336.         /*
  1337.          * If not ready, fake it so it isnt closed
  1338.          */
  1339.         if (length == -1 &&
  1340.             ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
  1341.             return 1;
  1342.         if (length <= 0)
  1343.             return length;
  1344.         }
  1345.  
  1346.     /*
  1347.     ** For server connections, we process as many as we can without
  1348.     ** worrying about the time of day or anything :)
  1349.     */
  1350.     if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr) ||
  1351.         IsService(cptr))
  1352.         {
  1353.         if (length > 0)
  1354.             if ((done = dopacket(cptr, readbuf, length)))
  1355.                 return done;
  1356.         }
  1357.     else
  1358.         {
  1359.         Debug((DEBUG_DEBUG, "JK: read %d bytes: <%s>", length, readbuf ));
  1360.         /*
  1361.         ** Before we even think of parsing what we just read, stick
  1362.         ** it on the end of the receive queue and do it when its
  1363.         ** turn comes around.
  1364.         */
  1365.         if (dbuf_put(&cptr->recvQ, readbuf, length) < 0)
  1366.             return exit_client(cptr, cptr, cptr, "dbuf_put fail");
  1367.  
  1368.         if (IsPerson(cptr) &&
  1369.             DBufLength(&cptr->recvQ) > CLIENT_FLOOD)
  1370.             return exit_client(cptr, cptr, cptr, "Excess Flood");
  1371.  
  1372.         while (DBufLength(&cptr->recvQ) && !NoNewLine(cptr) &&
  1373.                ((cptr->status < STAT_UNKNOWN) ||
  1374.             (cptr->since - now < 10)))
  1375.             {
  1376.             /*
  1377.             ** If it has become registered as a Service or Server
  1378.             ** then skip the per-message parsing below.
  1379.             */
  1380.             if (IsService(cptr) || IsServer(cptr))
  1381.                 {
  1382.                 dolen = dbuf_get(&cptr->recvQ, readbuf,
  1383.                          sizeof(readbuf));
  1384.                 if (dolen <= 0)
  1385.                     break;
  1386.                 if ((done = dopacket(cptr, readbuf, dolen)))
  1387.                     return done;
  1388.                 break;
  1389.                 }
  1390.  
  1391.             dolen = dbuf_getmsg(&cptr->recvQ, readbuf,
  1392.                         sizeof(readbuf));
  1393.  
  1394.             /*
  1395.             ** Devious looking...whats it do ? well..if a client
  1396.             ** sends a *long* message without any CR or LF, then
  1397.             ** dbuf_getmsg fails and we pull it out using this
  1398.             ** loop which just gets the next 512 bytes and then
  1399.             ** deletes the rest of the buffer contents.
  1400.             ** -avalon
  1401.             */
  1402.  
  1403.             while (dolen <= 0)
  1404.                 {
  1405.                 if (dolen < 0)
  1406.                     return exit_client(cptr, cptr, cptr,
  1407.                                "dbuf_getmsg fail");
  1408.                 if (DBufLength(&cptr->recvQ) < IRC_SUCKS_LINE_LENGTH)
  1409.                     {
  1410.                     cptr->flags |= FLAGS_NONL;
  1411.                     break;
  1412.                     }
  1413.                 dolen = dbuf_get(&cptr->recvQ, readbuf, IRC_SUCKS_LINE_LENGTH+1);
  1414.                 if (dolen > 0 && DBufLength(&cptr->recvQ))
  1415.                     DBufClear(&cptr->recvQ);
  1416.                 }
  1417.  
  1418.             if (dolen > 0 &&
  1419.                 (dopacket(cptr, readbuf, dolen) == FLUSH_BUFFER))
  1420.                 return FLUSH_BUFFER;
  1421.             }
  1422.         }
  1423.     return 1;
  1424. }
  1425.  
  1426.  
  1427. /*
  1428.  * Check all connections for new connections and input data that is to be
  1429.  * processed. Also check for connections with data queued and whether we can
  1430.  * write it out.
  1431.  */
  1432. int    read_message(delay)
  1433. time_t    delay; /* Don't ever use ZERO here, unless you mean to poll and then
  1434.         * you have to have sleep/wait somewhere else in the code.--msa
  1435.         */
  1436. {
  1437.     Reg1    aClient    *cptr;
  1438.     Reg2    int    nfds;
  1439.     struct    timeval    wait;
  1440. #ifdef    pyr
  1441.     struct    timeval    nowt;
  1442.     u_long    us;
  1443. #endif
  1444.     fd_set    read_set, write_set;
  1445.     time_t    delay2 = delay, now;
  1446.     u_long    usec = 0;
  1447.     int    res, length, fd, i;
  1448.     int    auth = 0;
  1449.  
  1450. #ifdef NPATH
  1451.     check_command(&delay, NULL);
  1452. #endif
  1453. #ifdef    pyr
  1454.     (void) gettimeofday(&nowt, NULL);
  1455.     now = nowt.tv_sec;
  1456. #else
  1457.     now = time(NULL);
  1458. #endif
  1459.  
  1460.     for (res = 0;;)
  1461.         {
  1462.         FD_ZERO(&read_set);
  1463.         FD_ZERO(&write_set);
  1464.  
  1465.         for (i = highest_fd; i >= 0; i--)
  1466.             {
  1467.             if (!(cptr = local[i]))
  1468.                 continue;
  1469.             if (IsLog(cptr))
  1470.                 continue;
  1471.             if (DoingAuth(cptr))
  1472.                 {
  1473.                 auth++;
  1474.                 Debug((DEBUG_NOTICE,"auth on %x %d", cptr, i));
  1475.                 FD_SET(cptr->authfd, &read_set);
  1476.                 if (cptr->flags & FLAGS_WRAUTH)
  1477.                     FD_SET(cptr->authfd, &write_set);
  1478.                 }
  1479.             if (DoingDNS(cptr) || DoingAuth(cptr))
  1480.                 continue;
  1481.             if (IsMe(cptr) && IsListening(cptr))
  1482.                 {
  1483.                 if ((now > cptr->lasttime + 2))
  1484.                     FD_SET(i, &read_set);
  1485.                 else if (delay2 > 2)
  1486.                     delay2 = 2;
  1487.                 }
  1488.             else if (!IsMe(cptr))
  1489.                 {
  1490.                 if (DBufLength(&cptr->recvQ) && delay2 > 2)
  1491.                     delay2 = 1;
  1492.                 if (DBufLength(&cptr->recvQ) < 4088)
  1493.                     FD_SET(i, &read_set);
  1494.                 }
  1495.  
  1496.             if (DBufLength(&cptr->sendQ) || IsConnecting(cptr))
  1497. #ifndef    pyr
  1498.                 FD_SET(i, &write_set);
  1499. #else
  1500.                 {
  1501.                 if (!(cptr->flags & FLAGS_BLOCKED))
  1502.                     FD_SET(i, &write_set);
  1503.                 else
  1504.                     delay2 = 0, usec = 500000;
  1505.                 }
  1506.             if (now - cptr->lw.tv_sec &&
  1507.                 nowt.tv_usec - cptr->lw.tv_usec < 0)
  1508.                 us = 1000000;
  1509.             else
  1510.                 us = 0;
  1511.             us += nowt.tv_usec;
  1512.             if (us - cptr->lw.tv_usec > 500000)
  1513.                 cptr->flags &= ~FLAGS_BLOCKED;
  1514. #endif
  1515.             }
  1516.  
  1517.         if (udpfd >= 0)
  1518.             FD_SET(udpfd, &read_set);
  1519.         if (resfd >= 0)
  1520.             FD_SET(resfd, &read_set);
  1521.  
  1522.         wait.tv_sec = MIN(delay2, delay);
  1523.         wait.tv_usec = usec;
  1524. #ifdef    HPUX
  1525.         nfds = select(FD_SETSIZE, (int *)&read_set, (int *)&write_set,
  1526.                 0, &wait);
  1527. #else
  1528.         nfds = select(FD_SETSIZE, &read_set, &write_set, 0, &wait);
  1529. #endif
  1530.         if (nfds == -1 && errno == EINTR)
  1531.             return -1;
  1532.         else if (nfds >= 0)
  1533.             break;
  1534.         report_error("select %s:%s", &me);
  1535.         res++;
  1536.         if (res > 5)
  1537.             restart("too many select errors");
  1538.         sleep(10);
  1539.         }
  1540.   
  1541.     if (udpfd >= 0 && FD_ISSET(udpfd, &read_set))
  1542.         {
  1543.             polludp();
  1544.             nfds--;
  1545.             FD_CLR(udpfd, &read_set);
  1546.         }
  1547.     if (resfd >= 0 && FD_ISSET(resfd, &read_set))
  1548.         {
  1549.             do_dns_async();
  1550.             nfds--;
  1551.             FD_CLR(resfd, &read_set);
  1552.         }
  1553.  
  1554.     /*
  1555.      * Check fd sets for the auth fd's (if set and valid!) first
  1556.      * because these can not be processed using the normal loops below.
  1557.      * -avalon
  1558.      */
  1559.     for (i = highest_fd; (auth > 0) && (i >= 0); i--)
  1560.         {
  1561.         if (!(cptr = local[i]))
  1562.             continue;
  1563.         if (cptr->authfd < 0)
  1564.             continue;
  1565.         auth--;
  1566.         if ((nfds > 0) && FD_ISSET(cptr->authfd, &write_set))
  1567.             {
  1568.             nfds--;
  1569.             send_authports(cptr);
  1570.             }
  1571.         else if ((nfds > 0) && FD_ISSET(cptr->authfd, &read_set))
  1572.             {
  1573.             nfds--;
  1574.             read_authports(cptr);
  1575.             }
  1576.         }
  1577.     for (i = highest_fd; i >= 0; i--)
  1578.         if ((cptr = local[i]) && FD_ISSET(i, &read_set) &&
  1579.             IsListening(cptr))
  1580.             {
  1581.             FD_CLR(i, &read_set);
  1582.             nfds--;
  1583.             cptr->lasttime = time(NULL);
  1584.             /*
  1585.             ** There may be many reasons for error return, but
  1586.             ** in otherwise correctly working environment the
  1587.             ** probable cause is running out of file descriptors
  1588.             ** (EMFILE, ENFILE or others?). The man pages for
  1589.             ** accept don't seem to list these as possible,
  1590.             ** although it's obvious that it may happen here.
  1591.             ** Thus no specific errors are tested at this
  1592.             ** point, just assume that connections cannot
  1593.             ** be accepted until some old is closed first.
  1594.             */
  1595.             if ((fd = accept(i, NULL, NULL)) < 0)
  1596.                 {
  1597.                 report_error("Cannot accept connections %s:%s",
  1598.                         cptr);
  1599.                 break;
  1600.                 }
  1601.             ircstp->is_ac++;
  1602.             if (fd >= MAXCLIENTS)
  1603.                 {
  1604.                 ircstp->is_ref++;
  1605.                 sendto_ops("All connections in use. (%s)",
  1606.                        get_client_name(cptr, TRUE));
  1607.                 (void)send(fd,
  1608.                     "ERROR :All connections in use\r\n",
  1609.                     32, 0);
  1610.                 (void)close(fd);
  1611.                 break;
  1612.                 }
  1613.             /*
  1614.              * Use of add_connection (which never fails :) meLazy
  1615.              */
  1616. #ifdef    UNIXPORT
  1617.             if (IsUnixSocket(cptr))
  1618.                 add_unixconnection(cptr, fd);
  1619.             else
  1620. #endif
  1621.                 (void)add_connection(cptr, fd);
  1622.             nextping = time(NULL);
  1623.             if (!cptr->acpt)
  1624.                 cptr->acpt = &me;
  1625.             }
  1626.  
  1627.     for (i = highest_fd; i >= 0; i--)
  1628.         {
  1629.         if (!(cptr = local[i]) || IsMe(cptr))
  1630.             continue;
  1631.         if (FD_ISSET(i, &write_set))
  1632.             {
  1633.             int    write_err = 0;
  1634.             nfds--;
  1635.             /*
  1636.             ** ...room for writing, empty some queue then...
  1637.             */
  1638.             if (IsConnecting(cptr))
  1639.                   write_err = completed_connection(cptr);
  1640.             if (!write_err)
  1641.                   (void)send_queued(cptr);
  1642.             if (IsDead(cptr) || write_err)
  1643.                 {
  1644. deadsocket:
  1645.                 if (FD_ISSET(i, &read_set))
  1646.                     {
  1647.                     nfds--;
  1648.                     FD_CLR(i, &read_set);
  1649.                     }
  1650.                 (void)exit_client(cptr, cptr, &me,
  1651.                          strerror(get_sockerr(cptr)));
  1652.                 continue;
  1653.                 }
  1654.             }
  1655.         length = 1;    /* for fall through case */
  1656.         if (!NoNewLine(cptr) || FD_ISSET(i, &read_set))
  1657.             length = read_packet(cptr, &read_set);
  1658.         if (length > 0)
  1659.             flush_connections(i);
  1660.         if ((length != FLUSH_BUFFER) && IsDead(cptr))
  1661.             goto deadsocket;
  1662.         if (!FD_ISSET(i, &read_set) && length > 0)
  1663.             continue;
  1664.         nfds--;
  1665.         readcalls++;
  1666.         if (length > 0)
  1667.             continue;
  1668.  
  1669.         /*
  1670.         ** ...hmm, with non-blocking sockets we might get
  1671.         ** here from quite valid reasons, although.. why
  1672.         ** would select report "data available" when there
  1673.         ** wasn't... so, this must be an error anyway...  --msa
  1674.         ** actually, EOF occurs when read() returns 0 and
  1675.         ** in due course, select() returns that fd as ready
  1676.         ** for reading even though it ends up being an EOF. -avalon
  1677.         */
  1678.         Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d",
  1679.             i, errno, length));
  1680.  
  1681.         /*
  1682.         ** NOTE: if length == -2 then cptr has already been freed!
  1683.         */
  1684.         if (length != -2 && (IsServer(cptr) || IsHandshake(cptr)))
  1685.             {
  1686.             if (length == 0)
  1687.                  sendto_ops("Server %s closed the connection",
  1688.                         get_client_name(cptr,FALSE));
  1689.             else
  1690.                  report_error("Lost connection to %s:%s",
  1691.                           cptr);
  1692.             }
  1693.         if (length != FLUSH_BUFFER)
  1694.             (void)exit_client(cptr, cptr, &me, length >= 0 ?
  1695.                       "EOF From client" :
  1696.                       strerror(get_sockerr(cptr)));
  1697.         }
  1698.     return 0;
  1699. }
  1700.  
  1701. /*
  1702.  * connect_server
  1703.  */
  1704. int    connect_server(aconf, by, hp)
  1705. aConfItem *aconf;
  1706. aClient    *by;
  1707. struct    hostent    *hp;
  1708. {
  1709.     Reg1    struct    sockaddr *svp;
  1710.     Reg2    aClient *cptr, *c2ptr;
  1711.     Reg3    char    *s;
  1712.     int    errtmp, len;
  1713.  
  1714.     Debug((DEBUG_NOTICE,"Connect to %s[%s] @%s",
  1715.         aconf->name, aconf->host, inetntoa((char *)&aconf->ipnum)));
  1716.  
  1717.     if ((c2ptr = find_server(aconf->name, NULL)))
  1718.         {
  1719.         sendto_ops("Server %s already present from %s",
  1720.                aconf->name, get_client_name(c2ptr, TRUE));
  1721.         if (by && IsPerson(by) && !MyClient(by))
  1722.           sendto_one(by,
  1723.                              ":%s NOTICE %s :Server %s already present from %s",
  1724.                              me.name, by->name, aconf->name,
  1725.                  get_client_name(c2ptr, TRUE));
  1726.         return -1;
  1727.         }
  1728.  
  1729.     /*
  1730.      * If we dont know the IP# for this host and itis a hostname and
  1731.      * not a ip# string, then try and find the appropriate host record.
  1732.      */
  1733.     if ( ( !aconf->ipnum.s_addr )
  1734. #ifdef UNIXPORT
  1735.         && ( ( aconf->host[2] ) != '/' )  /* needed for Unix domain -- dl*/
  1736. #endif
  1737.             )
  1738.         {
  1739.             Link    lin;
  1740.  
  1741.         lin.flags = ASYNC_CONNECT;
  1742.         lin.value.aconf = aconf;
  1743.         nextdnscheck = 1;
  1744.         s = (char *)index(aconf->host, '@');
  1745.         s++; /* should NEVER be NULL */
  1746.         if ((aconf->ipnum.s_addr = inet_addr(s)) == -1)
  1747.             {
  1748.             aconf->ipnum.s_addr = 0;
  1749.             hp = gethost_byname(s, &lin);
  1750.             Debug((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s",
  1751.                 hp, aconf, aconf->name, s));
  1752.             if (!hp)
  1753.                 return 0;
  1754.             bcopy(hp->h_addr, (char *)&aconf->ipnum,
  1755.                 sizeof(struct in_addr));
  1756.             }
  1757.         }
  1758.     cptr = make_client(NULL);
  1759.     cptr->hostp = hp;
  1760.     /*
  1761.      * Copy these in so we have something for error detection.
  1762.      */
  1763.     strncpyzt(cptr->name, aconf->name, sizeof(cptr->name));
  1764.     strncpyzt(cptr->sockhost, aconf->host, HOSTLEN+1);
  1765.  
  1766. #ifdef    UNIXPORT
  1767.     if (aconf->host[2] == '/') /* (/ starts a 2), Unix domain -- dl*/
  1768.         svp = connect_unix(aconf, cptr, &len);
  1769.     else
  1770.         svp = connect_inet(aconf, cptr, &len);
  1771. #else
  1772.     svp = connect_inet(aconf, cptr, &len);
  1773. #endif
  1774.  
  1775.     if (!svp)
  1776.         {
  1777.         if (cptr->fd != -1)
  1778.             (void)close(cptr->fd);
  1779.         cptr->fd = -2;
  1780.         free_client(cptr);
  1781.         return -1;
  1782.         }
  1783.  
  1784.     set_non_blocking(cptr->fd, cptr);
  1785.     set_sock_opts(cptr->fd, cptr);
  1786.     (void)signal(SIGALRM, dummy);
  1787.     (void)alarm(4);
  1788.     if (connect(cptr->fd, svp, len) < 0 && errno != EINPROGRESS)
  1789.         {
  1790.         errtmp = errno; /* other system calls may eat errno */
  1791.         (void)alarm(0);
  1792.         report_error("Connect to host %s failed: %s",cptr);
  1793.                 if (by && IsPerson(by) && !MyClient(by))
  1794.                   sendto_one(by,
  1795.                              ":%s NOTICE %s :Connect to host %s failed.",
  1796.                  me.name, by->name, cptr);
  1797.         (void)close(cptr->fd);
  1798.         cptr->fd = -2;
  1799.         free_client(cptr);
  1800.         errno = errtmp;
  1801.         if (errno == EINTR)
  1802.             errno = ETIMEDOUT;
  1803.         return -1;
  1804.         }
  1805.     (void)alarm(0);
  1806.  
  1807.         /* Attach config entries to client here rather than in
  1808.          * completed_connection. This to avoid null pointer references
  1809.          * when name returned by gethostbyaddr matches no C lines
  1810.          * (could happen in 2.6.1a when host and servername differ).
  1811.          * No need to check access and do gethostbyaddr calls.
  1812.          * There must at least be one as we got here C line...  meLazy
  1813.          */
  1814.         (void)attach_confs_host(cptr, aconf->host,
  1815.                CONF_NOCONNECT_SERVER | CONF_CONNECT_SERVER);
  1816.  
  1817.     if (!find_conf_host(cptr->confs, aconf->host, CONF_NOCONNECT_SERVER) ||
  1818.         !find_conf_host(cptr->confs, aconf->host, CONF_CONNECT_SERVER))
  1819.         {
  1820.               sendto_ops("Host %s is not enabled for connecting:no C/N-line",
  1821.                aconf->host);
  1822.                 if (by && IsPerson(by) && !MyClient(by))
  1823.                   sendto_one(by,
  1824.                              ":%s NOTICE %s :Connect to host %s failed.",
  1825.                  me.name, by->name, cptr);
  1826.         det_confs_butmask(cptr, 0);
  1827.         (void)close(cptr->fd);
  1828.         cptr->fd = -2;
  1829.         free_client(cptr);
  1830.                 return(-1);
  1831.         }
  1832.     /*
  1833.     ** The socket has been connected or connect is in progress.
  1834.     */
  1835.     (void)make_server(cptr);
  1836.     if (by && IsPerson(by))
  1837.         {
  1838.         (void)strcpy(cptr->serv->by, by->name);
  1839.         cptr->serv->user = by->user;
  1840.         by->user->refcnt++;
  1841.         } else
  1842.         (void)strcpy(cptr->serv->by, "AutoConn.");
  1843.     (void)strcpy(cptr->serv->up, me.name);
  1844.     if (cptr->fd > highest_fd)
  1845.         highest_fd = cptr->fd;
  1846.     local[cptr->fd] = cptr;
  1847.     cptr->acpt = &me;
  1848.     SetConnecting(cptr);
  1849.  
  1850.     get_sockhost(cptr, aconf->host);
  1851.     add_client_to_list(cptr);
  1852.     nextping = time(NULL);
  1853.  
  1854.     return 0;
  1855. }
  1856.  
  1857. static    struct    sockaddr *connect_inet(aconf, cptr, lenp)
  1858. Reg1    aConfItem    *aconf;
  1859. Reg2    aClient    *cptr;
  1860. int    *lenp;
  1861. {
  1862.     static    struct    sockaddr_in    server;
  1863.     Reg3    struct    hostent    *hp;
  1864.  
  1865.     /*
  1866.      * Might as well get sockhost from here, the connection is attempted
  1867.      * with it so if it fails its useless.
  1868.      */
  1869.     cptr->fd = socket(AF_INET, SOCK_STREAM, 0);
  1870.     if (cptr->fd >= MAXCLIENTS)
  1871.         {
  1872.         sendto_ops("No more connections allowed (%s)", cptr->name);
  1873.         return NULL;
  1874.         }
  1875.     mysk.sin_port = 0;
  1876.     bzero((char *)&server, sizeof(server));
  1877.     server.sin_family = AF_INET;
  1878.     get_sockhost(cptr, aconf->host);
  1879.  
  1880.     if (cptr->fd == -1)
  1881.         {
  1882.         report_error("opening stream socket to server %s:%s", cptr);
  1883.         return NULL;
  1884.         }
  1885.     /*
  1886.     ** Bind to a local IP# (with unknown port - let unix decide) so
  1887.     ** we have some chance of knowing the IP# that gets used for a host
  1888.     ** with more than one IP#.
  1889.     */
  1890.     if (bind(cptr->fd, (struct sockaddr *)&mysk, sizeof(mysk)) == -1)
  1891.         {
  1892.         report_error("error binding to local port for %s:%s", cptr);
  1893.         return NULL;
  1894.         }
  1895.     /*
  1896.      * By this point we should know the IP# of the host listed in the
  1897.      * conf line, whether as a result of the hostname lookup or the ip#
  1898.      * being present instead. If we dont know it, then the connect fails.
  1899.      */
  1900.     if (isdigit(*aconf->host) && (aconf->ipnum.s_addr == -1))
  1901.         aconf->ipnum.s_addr = inet_addr(aconf->host);
  1902.     if (aconf->ipnum.s_addr == -1)
  1903.         {
  1904.         hp = cptr->hostp;
  1905.         if (!hp)
  1906.             {
  1907.             Debug((DEBUG_FATAL, "%s: unknown host", aconf->host));
  1908.             return NULL;
  1909.             }
  1910.         bcopy(hp->h_addr, (char *)&aconf->ipnum,
  1911.               sizeof(struct in_addr));
  1912.          }
  1913.     bcopy((char *)&aconf->ipnum, (char *)&server.sin_addr,
  1914.         sizeof(struct in_addr));
  1915.     bcopy((char *)&aconf->ipnum, (char *)&cptr->ip,
  1916.         sizeof(struct in_addr));
  1917.     server.sin_port = htons((aconf->port > 0) ? aconf->port : portnum);
  1918.     *lenp = sizeof(server);
  1919.     return    (struct sockaddr *)&server;
  1920. }
  1921.  
  1922. #ifdef    UNIXPORT
  1923. /* connect_unix
  1924.  *
  1925.  * Build a socket structure for cptr so that it can connet to the unix
  1926.  * socket defined by the conf structure aconf.
  1927.  */
  1928. static    struct    sockaddr *connect_unix(aconf, cptr, lenp)
  1929. aConfItem    *aconf;
  1930. aClient    *cptr;
  1931. int    *lenp;
  1932. {
  1933.     static    struct    sockaddr_un    sock;
  1934.  
  1935.     if ((cptr->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  1936.         {
  1937.         report_error("Unix domain connect to host %s failed: %s", cptr);
  1938.         return NULL;
  1939.         }
  1940.     else if (cptr->fd >= MAXCLIENTS)
  1941.         {
  1942.         sendto_ops("No more connections allowed (%s)", cptr->name);
  1943.         return NULL;
  1944.         }
  1945.  
  1946.     get_sockhost(cptr, aconf->host);
  1947.     /* +2 needed for working Unix domain -- dl*/
  1948.     strncpyzt(sock.sun_path, aconf->host+2, sizeof(sock.sun_path));
  1949.     sock.sun_family = AF_UNIX;
  1950.     *lenp = strlen(sock.sun_path) + 2;
  1951.  
  1952.     SetUnixSock(cptr);
  1953.     return (struct sockaddr *)&sock;
  1954. }
  1955. #endif
  1956.  
  1957. /*
  1958.  * The following section of code performs summoning of users to irc.
  1959.  */
  1960. #if defined(ENABLE_SUMMON) || defined(ENABLE_USERS)
  1961. int    utmp_open()
  1962. {
  1963. #ifdef O_NOCTTY
  1964.     return (open(UTMP, O_RDONLY|O_NOCTTY));
  1965. #else
  1966.     return (open(UTMP, O_RDONLY));
  1967. #endif
  1968. }
  1969.  
  1970. int    utmp_read(fd, name, line, host, hlen)
  1971. int    fd, hlen;
  1972. char    *name, *line, *host;
  1973. {
  1974.     struct    utmp    ut;
  1975.     while (read(fd, (char *)&ut, sizeof (struct utmp))
  1976.                == sizeof (struct utmp))
  1977.         {
  1978.         strncpyzt(name, ut.ut_name, 9);
  1979.         strncpyzt(line, ut.ut_line, 10);
  1980. #ifdef USER_PROCESS
  1981. #  if defined(HPUX) || defined(AIX)
  1982.         strncpyzt(host,(ut.ut_host[0]) ? (ut.ut_host) : me.name, 16);
  1983. #  else
  1984.         strncpyzt(host, me.name, 9);
  1985. #  endif
  1986.         if (ut.ut_type == USER_PROCESS)
  1987.             return 0;
  1988. #else
  1989.         strncpyzt(host, (ut.ut_host[0]) ? (ut.ut_host) : me.name,
  1990.             hlen);
  1991.         if (ut.ut_name[0])
  1992.             return 0;
  1993. #endif
  1994.         }
  1995.     return -1;
  1996. }
  1997.  
  1998. int    utmp_close(fd)
  1999. int    fd;
  2000. {
  2001.     return(close(fd));
  2002. }
  2003.  
  2004. #ifdef ENABLE_SUMMON
  2005. void    summon(who, namebuf, linebuf, chname)
  2006. aClient *who;
  2007. char    *namebuf, *linebuf, *chname;
  2008. {
  2009.     static    char    wrerr[] = "NOTICE %s :Write error. Couldn't summon.";
  2010.     int    fd;
  2011.     char    line[120];
  2012.     time_t    now;
  2013.     struct    tm    *tp;
  2014.  
  2015.     now = time(NULL);
  2016.     tp = localtime(&now);
  2017.     if (strlen(linebuf) > (size_t) 9)
  2018.         {
  2019.         sendto_one(who,"NOTICE %s :Serious fault in SUMMON.",
  2020.                who->name);
  2021.         sendto_one(who,
  2022.                "NOTICE %s :linebuf too long. Inform Administrator",
  2023.                who->name);
  2024.         return;
  2025.         }
  2026.     /*
  2027.      * Following line added to prevent cracking to e.g. /dev/kmem if
  2028.      * UTMP is for some silly reason writable to everyone...
  2029.      */
  2030.     if ((linebuf[0] != 't' || linebuf[1] != 't' || linebuf[2] != 'y')
  2031.         && (linebuf[0] != 'c' || linebuf[1] != 'o' || linebuf[2] != 'n')
  2032. #ifdef HPUX
  2033.         && (linebuf[0] != 'p' || linebuf[1] != 't' || linebuf[2] != 'y' ||
  2034.         linebuf[3] != '/')
  2035. #endif
  2036.         )
  2037.         {
  2038.         sendto_one(who,
  2039.               "NOTICE %s :Looks like mere mortal souls are trying to",
  2040.                who->name);
  2041.         sendto_one(who,"NOTICE %s :enter the twilight zone... ",
  2042.                who->name);
  2043.         Debug((0, "%s (%s@%s, nick %s, %s)",
  2044.               "FATAL: major security hack. Notify Administrator !",
  2045.               who->username, who->user->host,
  2046.               who->name, who->info));
  2047.         return;
  2048.         }
  2049.  
  2050.     (void)sprintf(line,"/dev/%s", linebuf);
  2051.     (void)alarm(5);
  2052. #ifdef    O_NOCTTY
  2053.     if ((fd = open(line, O_WRONLY | O_NDELAY | O_NOCTTY)) == -1)
  2054. #else
  2055.     if ((fd = open(line, O_WRONLY | O_NDELAY)) == -1)
  2056. #endif
  2057.         {
  2058.         (void)alarm(0);
  2059.         sendto_one(who,
  2060.                "NOTICE %s :%s seems to have disabled summoning...",
  2061.                who->name, namebuf);
  2062.         return;
  2063.         }
  2064. #if !defined(O_NOCTTY) && defined(TIOCNOTTY)
  2065.     (void) ioctl(fd, TIOCNOTTY, NULL);
  2066. #endif
  2067.     (void)alarm(0);
  2068.     (void)sprintf(line,"\n\r\007Message from IRC_Daemon@%s at %d:%02d\n\r",
  2069.             me.name, tp->tm_hour, tp->tm_min);
  2070.     if (write(fd, line, strlen(line)) != strlen(line))
  2071.         {
  2072.         (void)alarm(0);
  2073.         (void)close(fd);
  2074.         sendto_one(who, wrerr, who->name);
  2075.         return;
  2076.         }
  2077.     (void)alarm(0);
  2078.     (void)strcpy(line, "ircd: You are being summoned to Internet Relay \
  2079. Chat on\n\r");
  2080.     (void)alarm(5);
  2081.     if (write(fd, line, strlen(line)) != strlen(line))
  2082.         {
  2083.         (void)alarm(0);
  2084.         (void)close(fd);
  2085.         sendto_one(who, wrerr, who->name);
  2086.         return;
  2087.         }
  2088.     (void)alarm(0);
  2089.     (void)sprintf(line, "ircd: Channel %s, by %s@%s (%s) %s\n\r",
  2090.         chname, who->user->username, who->user->host, who->name, who->info);
  2091.     (void)alarm(5);
  2092.     if (write(fd, line, strlen(line)) != strlen(line))
  2093.         {
  2094.         (void)alarm(0);
  2095.         (void)close(fd);
  2096.         sendto_one(who, wrerr, who->name);
  2097.         return;
  2098.         }
  2099.     (void)alarm(0);
  2100.     (void)strcpy(line,"ircd: Respond with irc\n\r");
  2101.     (void)alarm(5);
  2102.     if (write(fd, line, strlen(line)) != strlen(line))
  2103.         {
  2104.         (void)alarm(0);
  2105.         (void)close(fd);
  2106.         sendto_one(who, wrerr, who->name);
  2107.         return;
  2108.         }
  2109.     (void)close(fd);
  2110.     (void)alarm(0);
  2111.     sendto_one(who, rpl_str(RPL_SUMMONING), me.name, who->name, namebuf);
  2112.     return;
  2113. }
  2114. #  endif
  2115. #endif /* ENABLE_SUMMON */
  2116.  
  2117. /*
  2118. ** find the real hostname for the host running the server (or one which
  2119. ** matches the server's name) and its primary IP#.  Hostname is stored
  2120. ** in the client structure passed as a pointer.
  2121. */
  2122. void    get_my_name(cptr, name, len)
  2123. aClient    *cptr;
  2124. char    *name;
  2125. int    len;
  2126. {
  2127.     static    char tmp[HOSTLEN+1];
  2128.     struct    hostent    *hp;
  2129.     char    *cname = cptr->name;
  2130.  
  2131.     /*
  2132.     ** Setup local socket structure to use for binding to.
  2133.     */
  2134.     bzero((char *)&mysk, sizeof(mysk));
  2135.     mysk.sin_family = AF_INET;
  2136.  
  2137.     if (gethostname(name,len) == -1)
  2138.         return;
  2139.     name[len] = '\0';
  2140.  
  2141.     /* assume that a name containing '.' is a FQDN */
  2142.     if (!index(name,'.'))
  2143.         add_local_domain(name, len - strlen(name));
  2144.  
  2145.     /*
  2146.     ** If hostname gives another name than cname, then check if there is
  2147.     ** a CNAME record for cname pointing to hostname. If so accept
  2148.     ** cname as our name.   meLazy
  2149.     */
  2150.     if (BadPtr(cname))
  2151.         return;
  2152.     if ((hp = gethostbyname(cname)) || (hp = gethostbyname(name)))
  2153.         {
  2154.         char    *hname;
  2155.         int    i = 0;
  2156.  
  2157.         for (hname = hp->h_name; hname; hname = hp->h_aliases[i++])
  2158.               {
  2159.             strncpyzt(tmp, hname, sizeof(tmp));
  2160.             add_local_domain(tmp, sizeof(tmp) - strlen(tmp));
  2161.  
  2162.             /*
  2163.             ** Copy the matching name over and store the
  2164.             ** 'primary' IP# as 'myip' which is used
  2165.             ** later for making the right one is used
  2166.             ** for connecting to other hosts.
  2167.             */
  2168.             if (!mycmp(me.name, tmp))
  2169.                 break;
  2170.              }
  2171.         if (mycmp(me.name, tmp))
  2172.             strncpyzt(name, hp->h_name, len);
  2173.         else
  2174.             strncpyzt(name, tmp, len);
  2175.         bcopy(hp->h_addr, (char *)&mysk.sin_addr,
  2176.             sizeof(struct in_addr));
  2177.         Debug((DEBUG_DEBUG,"local name is %s",
  2178.                 get_client_name(&me,TRUE)));
  2179.         }
  2180.     return;
  2181. }
  2182.  
  2183. /*
  2184. ** setup a UDP socket and listen for incoming packets
  2185. */
  2186. int    setup_ping()
  2187. {
  2188.     struct    sockaddr_in    from;
  2189.     int    on = 1;
  2190.  
  2191.     bzero((char *)&from, sizeof(from));
  2192.     from.sin_addr.s_addr = htonl(INADDR_ANY);
  2193.     from.sin_port = htons(me.port);
  2194.     from.sin_family = AF_INET;
  2195.  
  2196.     if ((udpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  2197.         {
  2198.         Debug((DEBUG_ERROR, "socket udp : %s", strerror(errno)));
  2199.         return -1;
  2200.         }
  2201.     if (setsockopt(udpfd, SOL_SOCKET, SO_REUSEADDR,
  2202.             (char *)&on, sizeof(on)) == -1)
  2203.         {
  2204. #ifdef    USE_SYSLOG
  2205.         syslog(LOG_ERR, "setsockopt udp fd %d : %m", udpfd);
  2206. #endif
  2207.         Debug((DEBUG_ERROR, "setsockopt so_reuseaddr : %s",
  2208.             strerror(errno)));
  2209.         (void)close(udpfd);
  2210.         udpfd = -1;
  2211.         return -1;
  2212.         }
  2213.     on = 0;
  2214.     (void) setsockopt(udpfd, SOL_SOCKET, SO_BROADCAST,
  2215.               (char *)&on, sizeof(on));
  2216.     if (bind(udpfd, (struct sockaddr *)&from, sizeof(from))==-1)
  2217.         {
  2218. #ifdef    USE_SYSLOG
  2219.         syslog(LOG_ERR, "bind udp.%d fd %d : %m",
  2220.             from.sin_port, udpfd);
  2221. #endif
  2222.         Debug((DEBUG_ERROR, "bind : %s", strerror(errno)));
  2223.         (void)close(udpfd);
  2224.         udpfd = -1;
  2225.         return -1;
  2226.         }
  2227.     if (fcntl(udpfd, F_SETFL, FNDELAY)==-1)
  2228.         {
  2229.         Debug((DEBUG_ERROR, "fcntl fndelay : %s", strerror(errno)));
  2230.         (void)close(udpfd);
  2231.         udpfd = -1;
  2232.         return -1;
  2233.         }
  2234.     return udpfd;
  2235. }
  2236.  
  2237. /*
  2238.  * max # of pings set to 15/sec.
  2239.  */
  2240. static    void    polludp()
  2241. {
  2242.     Reg1    char    *s;
  2243.     struct    sockaddr_in    from;
  2244.     int    n, fromlen = sizeof(from);
  2245.     static    time_t    last = 0, now;
  2246.     static    int    cnt = 0, mlen = 0;
  2247.  
  2248.     /*
  2249.      * find max length of data area of packet.
  2250.      */
  2251.     if (!mlen)
  2252.         {
  2253.         mlen = sizeof(readbuf) - strlen(me.name) - strlen(PATCHLEVEL);
  2254.         mlen -= 6;
  2255.         if (mlen < 0)
  2256.             mlen = 0;
  2257.         }
  2258.     Debug((DEBUG_DEBUG,"udp poll"));
  2259.  
  2260.     n = recvfrom(udpfd, readbuf, mlen, 0, &from, &fromlen);
  2261.     now = time(NULL);
  2262.     if (now == last)
  2263.         if (++cnt > 14)
  2264.             return;
  2265.     cnt = 0;
  2266.     last = now;
  2267.  
  2268.     if (n == -1)
  2269.         {
  2270.         if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
  2271.             return;
  2272.         else
  2273.             {
  2274.             report_error("udp port recvfrom (%s): %s", &me);
  2275.             return;
  2276.             }
  2277.         }
  2278.     ircstp->is_udp++;
  2279.     if (n  < 8)
  2280.         return;
  2281.  
  2282.     s = readbuf + n;
  2283.     /*
  2284.      * attach my name and version for the reply
  2285.      */
  2286.     *readbuf |= 1;
  2287.     (void)strcpy(s, me.name);
  2288.     s += strlen(s)+1;
  2289.     (void)strcpy(s, PATCHLEVEL);
  2290.     s += strlen(s);
  2291.     (void)sendto(udpfd, readbuf, s-readbuf, 0, &from ,sizeof(from));
  2292.     return;
  2293. }
  2294.  
  2295. /*
  2296.  * do_dns_async
  2297.  *
  2298.  * Called when the fd returned from init_resolver() has been selected for
  2299.  * reading.
  2300.  */
  2301. static    void    do_dns_async()
  2302. {
  2303.     static    Link    ln;
  2304.     aClient    *cptr;
  2305.     aConfItem    *aconf;
  2306.     struct    hostent    *hp;
  2307.  
  2308.     ln.flags = -1;
  2309.     hp = get_res((char *)&ln);
  2310.  
  2311.     Debug((DEBUG_DNS,"%#x = get_res(%d,%#x)",hp,ln.flags,ln.value.cptr));
  2312.  
  2313.     switch (ln.flags)
  2314.     {
  2315.     case ASYNC_NONE :
  2316.         /*
  2317.          * no reply was processed that was outstanding or had a client
  2318.          * still waiting.
  2319.          */
  2320.         break;
  2321.     case ASYNC_CLIENT :
  2322.         if ((cptr = ln.value.cptr))
  2323.             {
  2324.             del_queries((char *)cptr);
  2325.             ClearDNS(cptr);
  2326.             if (!DoingAuth(cptr))
  2327.                 SetAccess(cptr);
  2328.             cptr->hostp = hp;
  2329.             }
  2330.         break;
  2331.     case ASYNC_CONNECT :
  2332.         aconf = ln.value.aconf;
  2333.         if (hp && aconf)
  2334.             {
  2335.             bcopy(hp->h_addr, (char *)&aconf->ipnum,
  2336.                   sizeof(struct in_addr));
  2337.             (void)connect_server(aconf, NULL, hp);
  2338.             }
  2339.         else
  2340.             sendto_ops("Connect to %s failed: host lookup",
  2341.                    (aconf) ? aconf->host : "unknown");
  2342.         break;
  2343.     case ASYNC_CONF :
  2344.         aconf = ln.value.aconf;
  2345.         if (hp && aconf)
  2346.             bcopy(hp->h_addr, (char *)&aconf->ipnum,
  2347.                   sizeof(struct in_addr));
  2348.         break;
  2349.     default :
  2350.         break;
  2351.     }
  2352. }
  2353.