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