"Fossies" - the Fresh Open Source Software Archive

Member "bahamut-2.1.5/src/s_bsd.c" (28 May 2020, 63791 Bytes) of package /linux/privat/bahamut-2.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "s_bsd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.4_vs_2.1.5.

    1 /************************************************************************
    2  *   IRC - Internet Relay Chat, src/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 #include "struct.h"
   22 #include "common.h"
   23 #include "sys.h"
   24 #include "res.h"
   25 #include "numeric.h"
   26 #include "patchlevel.h"
   27 #include "zlink.h"
   28 #include "throttle.h"
   29 #include "userban.h"
   30 #include <sys/types.h>
   31 #include <sys/socket.h>
   32 #include <sys/file.h>
   33 #include <sys/ioctl.h>
   34 #if defined(SOL20)
   35 #include <sys/filio.h>
   36 #include <sys/select.h>
   37 #include <unistd.h>
   38 #endif
   39 #include "inet.h"
   40 #include <stdio.h>
   41 #include <signal.h>
   42 #include <fcntl.h>
   43 #include <sys/resource.h>
   44 #include "hooks.h"
   45 
   46 #ifdef  AIX
   47 #include <time.h>
   48 #include <arpa/nameser.h>
   49 #else
   50 #include "nameser.h"
   51 #endif
   52 #include "resolv.h"
   53 #include "memcount.h"
   54 
   55 /* If FD_ZERO isn't define up to this point,
   56  * define it (BSD4.2 needs this) */
   57 
   58 #include "h.h"
   59 #include "fdlist.h"
   60 #include "fds.h"
   61 
   62 extern void      engine_init();
   63 extern fdlist default_fdlist;
   64 extern int forked;
   65 extern void free_port(aPort *);
   66 
   67 #ifndef IN_LOOPBACKNET
   68 #define IN_LOOPBACKNET  0x7f
   69 #endif
   70 
   71 #if defined(MAXBUFFERS)
   72 int rcvbufmax = 0, sndbufmax = 0;
   73 #endif
   74 
   75 #ifdef MAXBUFFERS
   76 void reset_sock_opts(int, int);
   77 #endif
   78 
   79 static void set_listener_sock_opts(int, aListener *, int);
   80 static void set_listener_non_blocking(int, aListener *);
   81 /* listener list, count */
   82 aListener *listen_list = NULL;
   83 int listen_count = 0;
   84 
   85 
   86 aClient *local[MAXCONNECTIONS];
   87 int highest_fd = 0, resfd = -1;
   88 time_t timeofday;
   89 static struct sockaddr_in mysk;
   90 
   91 static struct sockaddr *connect_inet(aConnect *, aClient *, int *);
   92 static int check_init(aClient *, char *);
   93 static void set_sock_opts(int, aClient *);
   94 
   95 #if defined(MAXBUFFERS)
   96 static char *readbuf;
   97 #else
   98 static char readbuf[8192];
   99 #endif
  100 
  101 /* Silly macro to ignore certain report error statements */
  102 #define silent_report_error(x,y) do { } while(0)
  103 
  104 
  105 /*
  106  * Try and find the correct name to use with getrlimit() for setting
  107  * the max. number of files allowed to be open by this process.
  108  */
  109 
  110 #ifdef RLIMIT_FDMAX
  111 #define RLIMIT_FD_MAX   RLIMIT_FDMAX
  112 #else
  113 #ifdef RLIMIT_NOFILE
  114 #define RLIMIT_FD_MAX RLIMIT_NOFILE
  115 #else
  116 #ifdef RLIMIT_OPEN_MAX
  117 #define RLIMIT_FD_MAX RLIMIT_OPEN_MAX
  118 #else
  119 #undef RLIMIT_FD_MAX
  120 #endif
  121 #endif
  122 #endif
  123 
  124 /*
  125  * add_local_domain() 
  126  * Add the domain to hostname, if it is missing
  127  * (as suggested by eps@TOASTER.SFSU.EDU)
  128  */
  129 
  130 void add_local_domain(char *hname, int size)
  131 {
  132 #ifdef RES_INIT
  133     /* try to fix up unqualified name */
  134     if (!strchr(hname, '.')) 
  135     {
  136         if (size < 3)
  137             return;
  138         if (!(_res.options & RES_INIT))
  139         {
  140             Debug((DEBUG_DNS, "res_init()"));
  141             res_init();
  142         }
  143         if (_res.defdname[0])
  144         {
  145             strncat(hname, ".", size - 1);
  146             strncat(hname, _res.defdname, size - 2);
  147         }
  148     }
  149 #endif
  150     return;
  151 }
  152 
  153 /*
  154  * Cannot use perror() within daemon. stderr is closed in 
  155  * ircd and cannot be used. And, worse yet, it might have 
  156  * been reassigned to a normal connection...
  157  */
  158 
  159 /*
  160  * report_error 
  161  * This a replacement for perror(). Record error to log and 
  162  * also send a copy to all *LOCAL* opers online. 
  163  * text    is a *format* string for outputting error. It must
  164  * contain only two '%s', the first will be replaced by the
  165  * sockhost from the cptr, and the latter will be taken from 
  166  * sys_errlist[errno].
  167  * 
  168  * cptr, if not NULL, is the *LOCAL* client associated with
  169  * the error.
  170  */
  171 
  172 void report_error(char *text, aClient * cptr)
  173 {
  174     int errtmp = errno;     /* debug may change 'errno' */
  175     char *host;
  176     int err;
  177     unsigned int len = sizeof(err);
  178     extern char *strerror();
  179 
  180     host = (cptr) ? get_client_name(cptr, (IsServer(cptr) ? HIDEME : FALSE)) 
  181                   : "";
  182 
  183     Debug((DEBUG_ERROR, text, host, strerror(errtmp)));
  184     /* 
  185      * Get the *real* error from the socket (well try to anyway..). This
  186      * may only work when SO_DEBUG is enabled but its worth the gamble
  187      * anyway.
  188      */
  189 
  190 #ifdef  SO_ERROR
  191     if (!IsMe(cptr) && cptr->fd >= 0)
  192         if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len))
  193             if (err)
  194                 errtmp = err;
  195 #endif
  196     sendto_realops_lev(DEBUG_LEV, text, host, strerror(errtmp));
  197 #ifdef USE_SYSLOG
  198     syslog(LOG_WARNING, text, host, strerror(errtmp));
  199     if (!forked)
  200     {
  201         fprintf(stderr, text, host, strerror(errtmp));
  202         fprintf(stderr, "\n");
  203     }
  204 #endif
  205     return;
  206 }
  207 
  208 void report_listener_error(char *text, aListener *lptr)
  209 {
  210     int errtmp = errno;          /* debug may change 'errno' */
  211     char *host;
  212     int err;
  213     unsigned int len = sizeof(err);
  214     extern char *strerror();
  215 
  216     host = get_listener_name(lptr);
  217 
  218     Debug((DEBUG_ERROR, text, host, strerror(errtmp)));
  219 
  220 #ifdef  SO_ERROR
  221     if (lptr->fd >= 0)
  222         if (!getsockopt(lptr->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len))
  223             if (err)
  224                 errtmp = err;
  225 #endif
  226     sendto_realops_lev(DEBUG_LEV, text, host, strerror(errtmp));
  227 #ifdef USE_SYSLOG
  228     syslog(LOG_WARNING, text, host, strerror(errtmp));
  229 #endif
  230     if (!forked) 
  231     {
  232         fprintf(stderr, text, host, strerror(errtmp));
  233         fprintf(stderr, "\n");
  234     }
  235     return;
  236 }
  237 
  238 /*
  239  * open_listeners()
  240  *
  241  * cycle through our entire ports list and open them if they
  242  * arent already open.
  243  * Added Feb/04 -epi
  244  */
  245 
  246 void
  247 open_listeners()
  248 {
  249     aPort *tmp;
  250     if(!ports)
  251         sendto_realops("Lost all port configurations!");
  252     for(tmp = ports; tmp; tmp = tmp->next)
  253     {
  254         if(tmp->lstn)
  255             continue;
  256         add_listener(tmp);
  257     }
  258     return;
  259 }
  260 
  261 /*
  262  * add_listener
  263  *
  264  * Create a new client which is essentially the stub like 'me' to be used
  265  * for a socket that is passive (listen'ing for connections to be
  266  * accepted).
  267  * Backported from defunct 1.6 and updated for aPort structure in Feb04.
  268  * I'm assuming lucas rewrote this originally. -epi
  269  */
  270 int add_listener(aPort *aport)
  271 {
  272     aListener *lptr;
  273     aListener lstn;
  274     union
  275     {
  276     struct sockaddr sa;
  277     struct sockaddr_in addr4;
  278     struct sockaddr_in6 addr6;
  279     } server;
  280     unsigned int len = sizeof(server);
  281 #ifdef USE_SSL
  282     extern int ssl_capable;
  283 #endif
  284 
  285     memset(&lstn, 0, sizeof(aListener));
  286     lstn.port = aport->port;
  287 
  288     memset(&server, 0, sizeof(server));
  289     if (!BadPtr(aport->address) && (*aport->address != '*'))
  290     {
  291         strncpyzt(lstn.vhost_string, aport->address, sizeof(lstn.vhost_string));
  292 
  293     if (inet_pton(AF_INET6, aport->address, &server.addr6.sin6_addr) == 1)
  294     {
  295         server.addr6.sin6_family = AF_INET6;
  296         server.addr6.sin6_port = htons(lstn.port);
  297         len = sizeof(server.addr6);
  298     }
  299     else
  300     {
  301         server.addr4.sin_family = AF_INET;
  302         server.addr4.sin_addr.s_addr = inet_addr(aport->address);
  303         server.addr4.sin_port = htons(lstn.port);
  304         len = sizeof(server.addr4);
  305     }
  306     }
  307     else
  308     {
  309     server.addr4.sin_family = AF_INET;
  310     server.addr4.sin_addr.s_addr = INADDR_ANY;
  311     server.addr4.sin_port = htons(lstn.port);
  312     len = sizeof(server.addr4);
  313     }
  314 
  315     if(!BadPtr(aport->allow))
  316     {
  317     int bits;
  318 
  319         strncpyzt(lstn.allow_string, aport->allow, sizeof(lstn.allow_string));
  320 
  321     bits = inet_parse_cidr(server.sa.sa_family,
  322                    lstn.allow_string, &lstn.allow_ip,
  323                    sizeof(lstn.allow_ip));
  324     if (bits > 0)
  325         lstn.allow_cidr_bits = bits;
  326     else
  327         lstn.allow_cidr_bits = -1;
  328     }
  329 
  330     if(lstn.port <= 0) /* stop stupidity cold */
  331         return -1;
  332 
  333     lstn.fd = socket(server.sa.sa_family, SOCK_STREAM, 0);
  334     if (lstn.fd < 0)
  335     {
  336         report_listener_error("opening stream socket %s:%s", &lstn);
  337         return -1;
  338     }
  339 
  340     set_listener_sock_opts(lstn.fd, &lstn, server.sa.sa_family);
  341 
  342     if (bind(lstn.fd, &server.sa, len))
  343     {
  344         report_listener_error("binding stream socket %s:%s", &lstn);
  345         close(lstn.fd);
  346         return -1;
  347     }
  348 
  349     if (getsockname(lstn.fd, &server.sa, &len))
  350     {
  351         report_listener_error("getsockname failed for %s:%s", &lstn);
  352         close(lstn.fd);
  353         return -1;
  354     }
  355 
  356     if (lstn.fd > highest_fd)
  357         highest_fd = lstn.fd;
  358 
  359 #ifdef SOMAXCONN
  360     if(listen(lstn.fd, SOMAXCONN))
  361 #else
  362     if(listen(lstn.fd, HYBRID_SOMAXCONN))
  363 #endif
  364     {
  365         report_listener_error("error listening on FD %s:%s", &lstn);
  366         close(lstn.fd);
  367         return -1;
  368     }
  369 
  370 
  371     lptr = (aListener *) MyMalloc(sizeof(aListener));
  372     memcpy(lptr, &lstn, sizeof(aListener));
  373 
  374     if(local[lptr->fd])
  375     {
  376         report_listener_error("!!!! listener fd is held by client"
  377                               " in local[] array %s:%s", &lstn);
  378         abort();
  379     }
  380 
  381     lptr->aport = aport;
  382     aport->lstn = lptr;
  383 
  384     lptr->flags = aport->flags;
  385 #ifdef USE_SSL
  386     if(lptr->flags & CONF_FLAGS_P_SSL && ssl_capable)
  387     {
  388         SetSSL(lptr);
  389         lptr->ssl = NULL;
  390         lptr->client_cert = NULL;
  391     }
  392 #endif
  393 
  394     set_listener_non_blocking(lptr->fd, lptr);
  395     add_fd(lptr->fd, FDT_LISTENER, lptr);
  396     set_fd_flags(lptr->fd, FDF_WANTREAD);
  397 
  398     listen_count++;
  399     lptr->next = listen_list;
  400     listen_list = lptr;
  401 
  402     lptr->lasttime = timeofday;
  403 
  404     return 0;
  405 }
  406 
  407 void close_listener(aListener *lptr)
  408 {
  409     aListener *alptr, *alptrprev = NULL;
  410     aPort *aport, *aportl, *aportn = NULL;
  411 
  412     del_fd(lptr->fd);
  413     close(lptr->fd);
  414 
  415     /* drop our conf link */
  416     aport = lptr->aport;
  417     aport->lstn = NULL;
  418 
  419     /* and now drop the conf itself */
  420 
  421     for(aportl = ports ; aportl ; aportl = aportl->next)
  422     {
  423         if(aportl == aport)
  424         {
  425             if(aportn)
  426                 aportn->next = aportl->next;
  427             else
  428                 ports = aportl->next;
  429             free_port(aportl);
  430             break;
  431         }
  432         aportn = aportl;
  433     }
  434 
  435     /* now drop the listener */
  436 
  437     for(alptr = listen_list; alptr; alptr = alptr->next)
  438     {
  439         if(alptr == lptr)
  440         {
  441             if(alptrprev)
  442                 alptrprev->next = alptr->next;
  443             else
  444                 listen_list = alptr->next;
  445             MyFree(lptr);
  446             listen_count--;
  447             break;
  448         }
  449         alptrprev = alptr;
  450     }
  451 }
  452 
  453 /*
  454  * close_listeners
  455  *
  456  * Close and free all clients which are marked as having their socket open
  457  * and in a state where they can accept connections.  Unix sockets have
  458  * the path to the socket unlinked for cleanliness.
  459  */
  460 void close_listeners()
  461 {
  462     aListener *lptr, *lptrnext;
  463 
  464     lptr = listen_list;
  465 
  466     while(lptr)
  467     {
  468         lptrnext = lptr->next;
  469         if(lptr->clients <= 0)
  470             close_listener(lptr);
  471         else                
  472             /* if we cant close it, mark it for closing
  473              * when we loose all of our connections */
  474             lptr->aport->legal = -1;
  475         lptr = lptrnext;
  476     }
  477 }
  478 
  479 /* init_sys */
  480 void init_sys()
  481 {
  482     int fd;
  483 
  484 #ifdef RLIMIT_FD_MAX
  485     struct rlimit limit;
  486 
  487     if (!getrlimit(RLIMIT_FD_MAX, &limit))
  488     {
  489         if (limit.rlim_max < MAXCONNECTIONS)
  490         {
  491             printf("FATAL: System is only allowing %ld open files.\n",
  492                    (long)limit.rlim_max);
  493             printf("ircd requires at least %ld.\n", (long)MAXCONNECTIONS);
  494             printf("Fix the system account limits or recompile ircd.\n");
  495             printf("Aborting...\n");
  496             exit(-1);
  497         }
  498         /* set limit to exactly what we can handle */
  499         limit.rlim_cur = MAXCONNECTIONS;
  500         if (setrlimit(RLIMIT_FD_MAX, &limit) == -1)
  501         {
  502             printf("FATAL: Unable to set open file limit to %ld:\n%s\n",
  503                    (long)limit.rlim_cur, strerror(errno));
  504             printf("Aborting...\n");
  505             exit(-1);
  506         }
  507     }
  508 #endif
  509 
  510     printf("\nIrcd is now becoming a daemon.\n");
  511 
  512 #if !defined(SOL20)
  513     setlinebuf(stderr);
  514 #endif
  515 
  516     for (fd = 3; fd < MAXCONNECTIONS; fd++)
  517     {
  518         close(fd);
  519         local[fd] = NULL;
  520     }
  521     local[1] = NULL;
  522 
  523     if (bootopt & BOOT_TTY)
  524     {
  525         engine_init();
  526 
  527         /* debugging is going to a tty */
  528         resfd = init_resolver(0x1f);
  529         add_fd(resfd, FDT_RESOLVER, NULL);
  530         set_fd_flags(resfd, FDF_WANTREAD);
  531         return;
  532     }
  533 
  534     close(1);
  535 
  536     if (!(bootopt & BOOT_DEBUG) && !(bootopt & BOOT_STDERR))
  537         close(2);
  538 
  539 
  540     if ((isatty(0)) && !(bootopt & BOOT_OPER) && !(bootopt & BOOT_STDERR))
  541     {
  542         int pid;
  543 
  544         if ((pid = fork()) < 0)
  545         {
  546             if ((fd = open("/dev/tty", O_RDWR)) >= 0)
  547             write(fd, "Couldn't fork!\n", 15);  /* crude, but effective */
  548             exit(0);
  549         } 
  550         else if (pid > 0)
  551             exit(0);
  552 
  553         setsid();
  554 
  555         close(0);       /* fd 0 opened by inetd */
  556         local[0] = NULL;
  557     }
  558 
  559     engine_init();
  560     resfd = init_resolver(0x1f);
  561     add_fd(resfd, FDT_RESOLVER, NULL);
  562     set_fd_flags(resfd, FDF_WANTREAD);
  563     return;
  564 }
  565 
  566 void write_pidfile()
  567 {
  568 #ifdef IRCD_PIDFILE
  569     int fd;
  570     char buff[20];
  571 
  572     if ((fd = open(IRCD_PIDFILE, O_CREAT | O_WRONLY, 0600)) >= 0)
  573     {
  574         ircsprintf(buff, "%5d\n", (int) getpid());
  575         if (write(fd, buff, strlen(buff)) == -1)
  576             Debug((DEBUG_NOTICE, "Error writing to pid file %s", IRCD_PIDFILE));
  577         close(fd);
  578         return;
  579     }
  580 #ifdef  DEBUGMODE
  581     else
  582         Debug((DEBUG_NOTICE, "Error opening pid file %s", IRCD_PIDFILE));
  583 #endif
  584 #endif
  585 }
  586 
  587 /*
  588  * Initialize the various name strings used to store hostnames. This is
  589  * set from either the server's sockhost (if client fd is a tty or
  590  * localhost) or from the ip# converted into a string. 0 = success, -1
  591  * = fail.
  592  */
  593 static int check_init(aClient * cptr, char *sockn)
  594 {
  595     union
  596     {
  597     struct sockaddr sa;
  598     struct sockaddr_in addr4;
  599     struct sockaddr_in6 addr6;
  600     } sk;
  601     unsigned int len = sizeof(sk);
  602 
  603     /* If descriptor is a tty, special checking... * IT can't EVER be a tty */
  604 
  605     if (getpeername(cptr->fd, &sk.sa, &len) == -1)
  606         return -1;
  607 
  608     if (sk.sa.sa_family == AF_INET)
  609     {
  610     strcpy(sockn, (char *) inetntoa((char *) &sk.addr4.sin_addr));
  611     if (inet_netof(sk.addr4.sin_addr) == IN_LOOPBACKNET)
  612     {
  613         cptr->hostp = NULL;
  614         strncpyzt(sockn, me.sockhost, HOSTLEN + 1);
  615     }
  616     memcpy((char *) &cptr->ip.ip4, (char *) &sk.addr4.sin_addr,
  617            sizeof(struct in_addr));
  618 
  619     cptr->port = (int) (ntohs(sk.addr4.sin_port));
  620     }
  621     else if (sk.sa.sa_family == AF_INET6)
  622     {
  623     strcpy(sockn, (char *) inet6ntoa((char *) &sk.addr6.sin6_addr));
  624     memcpy((char *) &cptr->ip.ip6, (char *) &sk.addr6.sin6_addr,
  625            sizeof(struct in6_addr));
  626     cptr->port = (int) (ntohs(sk.addr6.sin6_port));
  627     }
  628 
  629     return 0;
  630 }
  631 
  632 /*
  633  * Ordinary client access check. Look for conf lines which have the
  634  * same status as the flags passed. 0 = Success -1 = Access denied -2 =
  635  * Bad socket.
  636  */
  637 int check_client(aClient *cptr)
  638 {
  639     char *sockname;
  640     struct hostent *hp = NULL;
  641     int i;
  642 
  643     Debug((DEBUG_DNS, "ch_cl: check access for %s[%s]",
  644            cptr->name, cipntoa(cptr)));
  645 
  646     if (cptr->ip_family == AF_INET &&
  647     inet_netof(cptr->ip.ip4) == IN_LOOPBACKNET)
  648     {
  649     cptr->hostp = NULL;
  650     sockname = me.sockhost;
  651     }
  652     else
  653     sockname = cptr->sockhost;
  654 
  655     hp = cptr->hostp;
  656     /* 
  657      * Verify that the host to ip mapping is correct both ways and that
  658      * the ip#(s) for the socket is listed for the host.
  659      */
  660     if (hp)
  661     {
  662         for (i = 0; hp->h_addr_list[i]; i++)
  663             if ((unsigned) hp->h_addrtype == cptr->ip_family &&
  664         !memcmp(hp->h_addr_list[i], (char *) &cptr->ip,
  665             hp->h_length))
  666                 break;
  667 
  668         if (!hp->h_addr_list[i])
  669         {
  670             sendto_one(cptr, "NOTICE AUTH :*** Your forward and reverse"
  671                              " DNS do not match, ignoring hostname.");
  672             hp = NULL;
  673         }
  674     }
  675 
  676     /*
  677      * Use the client's IP address instead of truncating a long hostname.
  678      */
  679     if (hp && strlen(hp->h_name) > HOSTLEN)
  680     hp = NULL;
  681 
  682     if ((i = attach_Iline(cptr, hp, sockname)))
  683     {
  684         Debug((DEBUG_DNS, "ch_cl: access denied: %s[%s]",
  685                 cptr->name, sockname));
  686         return i;
  687     }
  688 
  689     Debug((DEBUG_DNS, "ch_cl: access ok: %s[%s]", cptr->name, sockname));
  690 
  691     if (cptr->ip_family == AF_INET &&
  692     (inet_netof(cptr->ip.ip4) == IN_LOOPBACKNET ||
  693      inet_netof(cptr->ip.ip4) == inet_netof(mysk.sin_addr)))
  694     {
  695         ircstp->is_loc++;
  696         cptr->flags |= FLAGS_LOCAL;
  697     }
  698     return 0;
  699 }
  700 
  701 #define CFLAG   CONF_CONNECT_SERVER
  702 #define NFLAG   CONF_NOCONNECT_SERVER
  703 
  704 /*
  705  * check_server_init(), check_server() check access for a server given
  706  * its name (passed in cptr struct). Must check for all C/N lines which
  707  * have a name which matches the name given and a host which matches. A
  708  * host alias which is the same as the server name is also acceptable
  709  * in the host field of a C/N line. 0 = Success -1 = Access denied -2 =
  710  * Bad socket.
  711  *
  712  * This was terrible code.  Terrible!  Almost fucking scary! Rewritten into
  713  * a single function, much prettier.  Feb04 -epi
  714  */
  715 int check_server_init(aClient * cptr)
  716 {
  717     aConnect *aconn = NULL;
  718     struct hostent *hp = NULL;
  719     char sockname[HOSTLEN + 1], fullname[HOSTLEN + 1];
  720     char abuff[HOSTLEN + USERLEN + 2];
  721     int i = 0, ok = 0;
  722 
  723     if (check_init(cptr, sockname))
  724         return -2;
  725 
  726     if (!(aconn = find_aConnect(cptr->name)))
  727     {
  728         Debug((DEBUG_DNS, "No Connect block for %s", cptr->name));
  729         return -1;
  730     }
  731 
  732     /* 
  733      * * If the servername is a hostname, either an alias (CNAME) or
  734      * real name, then check with it as the host. Use gethostbyname()
  735      * to check for servername as hostname.
  736      */
  737     if (!cptr->hostp)
  738     {
  739         char *s;
  740         Link lin;
  741 
  742         /* 
  743          * * Do a lookup for the CONF line *only* and not the server
  744          * connection else we get stuck in a nasty state since it
  745          * takes a SERVER message to get us here and we cant
  746          * interrupt that very well.
  747          */
  748         lin.value.aconn = aconn;
  749         lin.flags = ASYNC_CONF;
  750         nextdnscheck = 1;
  751         if ((s = strchr(aconn->host, '@')))
  752             s++;
  753         else
  754             s = aconn->host;
  755         Debug((DEBUG_DNS, "sv_ci:cache lookup (%s)", s));
  756         if((hp = gethost_byname(s, &lin, cptr->ip_family)))
  757         {
  758             for (i = 0; hp->h_addr_list[i]; i++)
  759                 if ((unsigned) hp->h_addrtype == cptr->ip_family &&
  760             !memcmp(hp->h_addr_list[i], (char *) &cptr->ip,
  761                 hp->h_length))
  762                     break;
  763             if (!hp->h_addr_list[i])
  764             {
  765         const char *h_addr_str;
  766 
  767         if (hp->h_addrtype == AF_INET)
  768             h_addr_str = inetntoa((char *)hp->h_addr);
  769         else if (hp->h_addrtype == AF_INET6)
  770             h_addr_str = inet6ntoa((char *)hp->h_addr);
  771         else
  772             h_addr_str = "invalid.address.family.invalid";
  773 
  774                 sendto_realops_lev(ADMIN_LEV,
  775                     "Server IP# Mismatch: %s != %s[%s]",
  776                     cipntoa(cptr), hp->h_name, h_addr_str);
  777                 hp = NULL;
  778             }
  779         }
  780     }
  781     else
  782     {
  783         hp = cptr->hostp;
  784         for (i = 0; hp->h_addr_list[i]; i++)
  785         if ((unsigned) hp->h_addrtype == cptr->ip_family &&
  786         !memcmp(hp->h_addr_list[i], (char *) &cptr->ip,
  787             hp->h_length))
  788                 break;
  789     }
  790 
  791     if(hp)
  792     {
  793         strncpyzt(fullname, cptr->name, sizeof(fullname));
  794         add_local_domain(fullname, HOSTLEN - strlen(fullname));
  795         Debug((DEBUG_DNS, "sv_cl: gethostbyaddr: %s->%s",
  796                 sockname, fullname));
  797         ircsprintf(abuff, "%s@%s", cptr->username, fullname);
  798         get_sockhost(cptr, fullname);
  799         for (i = 0; hp->h_addr_list[i]; i++)
  800         {
  801             if(aconn->ipnum_family == hp->h_addrtype &&
  802            !memcmp((char *) &aconn->ipnum, (char *) hp->h_addr_list[i],
  803                hp->h_length))
  804                 ok = 1;
  805             else
  806                 ok = 0;
  807         }
  808     }
  809     else
  810     {
  811         /* having no luck finding a host.. check against IP */
  812     if((unsigned) aconn->ipnum_family == cptr->ip_family &&
  813        !memcmp((char *) &aconn->ipnum, (char *) &cptr->ip,
  814            sizeof(aconn->ipnum)))
  815         ok = 1;
  816         else
  817             ok = 0;
  818     }
  819 
  820     /* if they dont match up, then away with them */
  821     if (!ok)
  822     {
  823         get_sockhost(cptr, sockname);
  824         return -1;
  825     }
  826     /* check for Ulined access and link it if nessecary */
  827     if(find_aUserver(cptr->name))
  828         cptr->flags |= FLAGS_ULINE;
  829     make_server(cptr);
  830     cptr->serv->aconn = aconn;
  831     aconn->acpt = cptr;
  832     set_effective_class(cptr);
  833 
  834     if (aconn->ipnum_family == 0)
  835     {
  836     aconn->ipnum_family = cptr->ip_family;
  837     memcpy((char *) &aconn->ipnum, (char *) &cptr->ip,
  838            sizeof(aconn->ipnum));
  839     }
  840 
  841     get_sockhost(cptr, aconn->host);
  842     
  843     Debug((DEBUG_DNS, "sv_cl: access ok: %s[%s]", cptr->name, cptr->sockhost));
  844     return 0;
  845 }
  846 
  847 /*
  848  * completed_connection 
  849  * Complete non-blocking
  850  * connect()-sequence. Check access and terminate connection,
  851  * if trouble detected. 
  852  *
  853  * Return TRUE if successfully completed - FALSE if failed and ClientExit
  854  */
  855 int completed_connection(aClient * cptr)
  856 {
  857     aConnect *aconn;
  858 
  859     if(!(cptr->flags & FLAGS_BLOCKED))
  860         unset_fd_flags(cptr->fd, FDF_WANTWRITE);
  861     unset_fd_flags(cptr->fd, FDF_WANTREAD);
  862 
  863     SetHandshake(cptr);
  864 
  865     if (!(aconn = find_aConnect(cptr->name)))
  866     {
  867         sendto_realops("Lost Config for %s", get_client_name(cptr, HIDEME));
  868         return -1;
  869     }
  870     if (!BadPtr(aconn->cpasswd))
  871         sendto_one(cptr, "PASS %s :TS", aconn->cpasswd);
  872 
  873     /* pass on our capabilities to the server we /connect'd */
  874 #ifdef HAVE_ENCRYPTION_ON
  875     if(!(aconn->flags & CONN_DKEY))
  876         sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT ZIP"
  877                          " NICKIP NICKIPSTR TSMODE");
  878     else
  879     {
  880         sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT DKEY"
  881                          " ZIP NICKIP NICKIPSTR TSMODE");
  882         SetWantDKEY(cptr);
  883     }
  884 #else
  885     sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT ZIP NICKIP NICKIPSTR TSMODE");
  886 #endif
  887 
  888     if(aconn->flags & CONN_ZIP)
  889         cptr->capabilities |= CAPAB_DOZIP;
  890 
  891     sendto_one(cptr, "SERVER %s 1 :%s", my_name_for_link(me.name, aconn), 
  892                                         me.info);
  893 #ifdef DO_IDENTD
  894     /* Is this the right place to do this?  dunno... -Taner */
  895     if (!IsDead(cptr))
  896         start_auth(cptr);
  897 #endif
  898 
  899     check_client_fd(cptr);
  900     return (IsDead(cptr)) ? -1 : 0;
  901 }
  902 
  903 /*
  904  * close_connection 
  905  * Close the physical connection. This function must make 
  906  * MyConnect(cptr) == FALSE, and set cptr->from == NULL.
  907  */
  908 void close_connection(aClient *cptr)
  909 {
  910     aConnect *aconn;
  911 
  912     if (IsServer(cptr))
  913     {
  914         ircstp->is_sv++;
  915         ircstp->is_sbs += cptr->sendB;
  916         ircstp->is_sbr += cptr->receiveB;
  917         ircstp->is_sks += cptr->sendK;
  918         ircstp->is_skr += cptr->receiveK;
  919         ircstp->is_sti += timeofday - cptr->firsttime;
  920         if (ircstp->is_sbs > 2047)
  921         {
  922             ircstp->is_sks += (ircstp->is_sbs >> 10);
  923             ircstp->is_sbs &= 0x3ff;
  924         }
  925         if (ircstp->is_sbr > 2047)
  926         {
  927             ircstp->is_skr += (ircstp->is_sbr >> 10);
  928             ircstp->is_sbr &= 0x3ff;
  929         }
  930         /* schedule a quick reconnect if we've been connected a long time */
  931         if((aconn = find_aConnect_match(cptr->name, cptr->username,
  932                                     cptr->sockhost)))
  933         {
  934             aconn->hold = time(NULL);
  935             aconn->hold += (aconn->hold - cptr->since > HANGONGOODLINK) ?
  936                 HANGONRETRYDELAY : aconn->class->connfreq;
  937             if (nextconnect > aconn->hold)
  938                 nextconnect = aconn->hold;
  939         }
  940     } 
  941     else if (IsClient(cptr))
  942     {
  943         ircstp->is_cl++;
  944         ircstp->is_cbs += cptr->sendB;
  945         ircstp->is_cbr += cptr->receiveB;
  946         ircstp->is_cks += cptr->sendK;
  947         ircstp->is_ckr += cptr->receiveK;
  948         ircstp->is_cti += timeofday - cptr->firsttime;
  949         if (ircstp->is_cbs > 2047)
  950         {
  951             ircstp->is_cks += (ircstp->is_cbs >> 10);
  952             ircstp->is_cbs &= 0x3ff;
  953         }
  954         if (ircstp->is_cbr > 2047)
  955         {
  956             ircstp->is_ckr += (ircstp->is_cbr >> 10);
  957             ircstp->is_cbr &= 0x3ff;
  958         }
  959     } 
  960     else
  961         ircstp->is_ni++;
  962 
  963     /* remove outstanding DNS queries. */
  964     del_queries((char *) cptr);
  965 
  966     if (cptr->authfd >= 0)
  967     {
  968         del_fd(cptr->authfd);
  969         close(cptr->authfd);
  970         cptr->authfd = -1;
  971     }
  972 
  973     if (cptr->fd >= 0)
  974     {
  975 #ifdef USE_SSL
  976         if(!IsDead(cptr))
  977 #endif
  978         dump_connections(cptr->fd);
  979         local[cptr->fd] = NULL;
  980 #ifdef USE_SSL
  981         if(IsSSL(cptr) && cptr->ssl)
  982         {
  983             SSL_set_shutdown(cptr->ssl, SSL_RECEIVED_SHUTDOWN);
  984             ssl_smart_shutdown(cptr->ssl);
  985             SSL_free(cptr->ssl);
  986             cptr->ssl = NULL;
  987         }
  988 #endif
  989         del_fd(cptr->fd);
  990         close(cptr->fd);
  991         cptr->fd = -2;
  992         SBufClear(&cptr->sendQ);
  993         SBufClear(&cptr->recvQ);
  994         memset(cptr->passwd, '\0', sizeof(cptr->passwd));
  995         if(cptr->lstn)
  996             cptr->lstn->clients--;
  997     }
  998     for (; highest_fd > 0; highest_fd--)
  999     if (local[highest_fd])
 1000         break;
 1001 
 1002     clear_conflinks(cptr);
 1003 
 1004     if (cptr->webirc_username)
 1005     MyFree(cptr->webirc_username);
 1006     if (cptr->webirc_ip)
 1007     MyFree(cptr->webirc_ip);
 1008 
 1009     cptr->from = NULL;      /* ...this should catch them! >:) --msa */
 1010 
 1011     /* if we're the last socket open on this listener,
 1012      * check to make sure the listener is even supposed to be
 1013      * open, and close it if its not -epi
 1014      */
 1015      if (cptr->lstn && (cptr->lstn->clients <= 0) && 
 1016                 (cptr->lstn->aport->legal == -1))
 1017         close_listener(cptr->lstn);
 1018 
 1019     return;
 1020 }
 1021 
 1022 #ifdef MAXBUFFERS
 1023 /* reset_sock_opts type =  0 = client, 1 = server */
 1024 void reset_sock_opts(int fd, int type)
 1025 {
 1026 #define CLIENT_BUFFER_SIZE  4096
 1027 #define SEND_BUF_SIZE       2920
 1028     int opt;
 1029 
 1030     opt = type ? rcvbufmax : CLIENT_BUFFER_SIZE;
 1031     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, sizeof(opt)) < 0) 
 1032         sendto_realops("REsetsockopt(SO_RCVBUF) for fd %d (%s) failed",
 1033                         fd, type ? "server" : "client");
 1034     opt = type ? sndbufmax : SEND_BUF_SIZE;
 1035     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, sizeof(opt)) < 0) 
 1036         sendto_realops("REsetsockopt(SO_SNDBUF) for fd %d (%s) failed",
 1037                         fd, type ? "server" : "client");
 1038 }
 1039 #endif              /* MAXBUFFERS */
 1040 
 1041 /* set_sock_opts */
 1042 static void set_sock_opts(int fd, aClient * cptr)
 1043 {
 1044     unsigned int opt;
 1045     
 1046 #ifdef SO_REUSEADDR
 1047     opt = 1;
 1048     if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt,
 1049             sizeof(opt)) < 0)
 1050         silent_report_error("setsockopt(SO_REUSEADDR) %s:%s", cptr);
 1051 #endif
 1052 #if  defined(SO_DEBUG) && defined(DEBUGMODE) && 0
 1053     /* Solaris with SO_DEBUG writes to syslog by default */
 1054 #if !defined(SOL20) || defined(USE_SYSLOG)
 1055     opt = 1;
 1056     if (setsockopt(fd, SOL_SOCKET, SO_DEBUG, (char *) &opt, sizeof(opt)) < 0)
 1057         silent_report_error("setsockopt(SO_DEBUG) %s:%s", cptr);
 1058 #endif              /* SOL20 */
 1059 #endif
 1060 #ifdef  SO_USELOOPBACK
 1061     opt = 1;
 1062     if (setsockopt(fd, SOL_SOCKET, SO_USELOOPBACK, (char *) &opt,
 1063            sizeof(opt)) < 0)
 1064         silent_report_error("setsockopt(SO_USELOOPBACK) %s:%s", cptr);
 1065 #endif
 1066 #ifdef  SO_RCVBUF
 1067 #if defined(MAXBUFFERS)
 1068     if (rcvbufmax == 0)
 1069     {
 1070         unsigned int optlen;
 1071 
 1072         optlen = sizeof(rcvbufmax);
 1073         getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbufmax, &optlen);
 1074         while ((rcvbufmax < 16385) && (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, 
 1075                (char *) (char *) &rcvbufmax,optlen) >= 0))
 1076             rcvbufmax += 1024;
 1077         getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbufmax, &optlen);
 1078         readbuf = (char *) MyMalloc(rcvbufmax * sizeof(char));
 1079     }
 1080     if (IsServer(cptr))
 1081         opt = rcvbufmax;
 1082     else
 1083         opt = 4096;
 1084 #else
 1085     opt = 8192;
 1086 #endif
 1087     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, sizeof(opt)) < 0)
 1088         silent_report_error("setsockopt(SO_RCVBUF) %s:%s", cptr);
 1089 #endif
 1090 #ifdef  SO_SNDBUF
 1091 #if defined(MAXBUFFERS)
 1092     if (sndbufmax == 0)
 1093     {
 1094         unsigned int optlen;
 1095     
 1096         optlen = sizeof(sndbufmax);
 1097         getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &sndbufmax, &optlen);
 1098         while ((sndbufmax < 16385) && (setsockopt (fd, SOL_SOCKET, SO_SNDBUF,
 1099                            (char *) &sndbufmax, optlen) >= 0))
 1100             sndbufmax += 1024;
 1101         getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &sndbufmax, &optlen);
 1102     }
 1103     if (IsServer(cptr))
 1104         opt = sndbufmax;
 1105     else
 1106         opt = 4096;
 1107 #else
 1108     opt = 8192;
 1109 #endif
 1110     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, sizeof(opt)) < 0)
 1111         silent_report_error("setsockopt(SO_SNDBUF) %s:%s", cptr);
 1112 #endif
 1113 #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
 1114     {
 1115 #if defined(MAXBUFFERS)
 1116         char *s = readbuf, *t = readbuf + (rcvbufmax * sizeof(char)) / 2;
 1117         opt = (rcvbufmax * sizeof(char)) / 8;
 1118 #else
 1119         char *s = readbuf, *t = readbuf + sizeof(readbuf) / 2;
 1120     
 1121         opt = sizeof(readbuf) / 8;
 1122 #endif
 1123         if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, t, &opt) < 0)
 1124             silent_report_error("getsockopt(IP_OPTIONS) %s:%s", cptr);
 1125         else if (opt > 0)
 1126         {
 1127             for (*readbuf = '\0'; opt > 0; opt--, s += 3)
 1128                 ircsprintf(s, "%2.2x:", *t++);
 1129             *s = '\0';
 1130             sendto_realops("Connection %s using IP opts: (%s)",
 1131                             get_client_name(cptr, HIDEME), readbuf);
 1132         }
 1133         if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, (char *) NULL, 0) < 0)
 1134             silent_report_error("setsockopt(IP_OPTIONS) %s:%s", cptr);
 1135     }
 1136 #endif
 1137 }
 1138 
 1139 static void set_listener_sock_opts(int fd, aListener *lptr, int family)
 1140 {
 1141     int opt;
 1142 
 1143 #ifdef IPV6_V6ONLY
 1144     if (family == AF_INET6)
 1145     {
 1146     opt = 1;
 1147     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
 1148                sizeof(opt)) < 0)
 1149         report_listener_error("setsockopt(IPV6_V6ONLY) %s:%s", lptr);
 1150     }
 1151 #endif
 1152 #ifdef SO_REUSEADDR
 1153     opt = 1;
 1154     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, 
 1155                    sizeof(opt)) < 0)
 1156         report_listener_error("setsockopt(SO_REUSEADDR) %s:%s", lptr);
 1157 #endif
 1158 #if  defined(SO_DEBUG) && defined(DEBUGMODE) && 0
 1159    /*
 1160     * Solaris with SO_DEBUG writes to syslog by default
 1161     */
 1162 #if !defined(SOL20) || defined(USE_SYSLOG)
 1163     opt = 1;
 1164     if (setsockopt(fd, SOL_SOCKET, SO_DEBUG, (char *) &opt, sizeof(opt)) < 0) 
 1165         report_listener_error("setsockopt(SO_DEBUG) %s:%s", lptr);
 1166 #endif                         /* SOL20 */
 1167 #endif
 1168 #ifdef  SO_USELOOPBACK
 1169     opt = 1;
 1170     if (setsockopt (fd, SOL_SOCKET, SO_USELOOPBACK, (char *) &opt, 
 1171                     sizeof(opt)) < 0)
 1172         report_listener_error("setsockopt(SO_USELOOPBACK) %s:%s", lptr);
 1173 #endif
 1174 #ifdef  SO_RCVBUF
 1175 # if defined(MAXBUFFERS)
 1176     if (rcvbufmax == 0) 
 1177     {
 1178         unsigned int optlen;
 1179 
 1180         optlen = sizeof(rcvbufmax);
 1181         getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbufmax, &optlen);
 1182         while ((rcvbufmax < 16385) && (setsockopt (fd, SOL_SOCKET, SO_RCVBUF, 
 1183                (char *) (char *) &rcvbufmax, optlen) >= 0)) 
 1184             rcvbufmax += 1024;
 1185         getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &rcvbufmax, &optlen);
 1186         readbuf = (char *) MyMalloc(rcvbufmax * sizeof(char));
 1187     }
 1188     opt = 4096;
 1189 # else
 1190     opt = 8192;
 1191 # endif
 1192     if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, sizeof(opt)) < 0) 
 1193         report_listener_error("setsockopt(SO_RCVBUF) %s:%s", lptr);
 1194 #endif
 1195 #ifdef  SO_SNDBUF
 1196 #if defined(MAXBUFFERS)
 1197     if (sndbufmax == 0) 
 1198     {
 1199         unsigned int optlen;
 1200 
 1201         optlen = sizeof(sndbufmax);
 1202         getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &sndbufmax, &optlen);
 1203         while ((sndbufmax < 16385) && (setsockopt (fd, SOL_SOCKET, SO_SNDBUF, 
 1204                 (char *) &sndbufmax, optlen) >= 0)) 
 1205             sndbufmax += 1024;
 1206         getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &sndbufmax, &optlen);
 1207     }
 1208     opt = 4096;
 1209 #else
 1210     opt = 8192;
 1211 #endif
 1212     if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, sizeof(opt)) < 0)
 1213         report_listener_error("setsockopt(SO_SNDBUF) %s:%s", lptr);
 1214 #endif
 1215 }
 1216 
 1217 
 1218 int get_sockerr(aClient * cptr)
 1219 {
 1220     int errtmp = errno, err = 0;
 1221     unsigned int len = sizeof(err);
 1222     
 1223 #ifdef  SO_ERROR
 1224     if (cptr->fd >= 0)
 1225     if (!getsockopt(cptr->fd, SOL_SOCKET, SO_ERROR, (char *) &err, &len))
 1226         if (err)
 1227             errtmp = err;
 1228 #endif
 1229     return errtmp;
 1230 }
 1231 
 1232 char *irc_get_sockerr(aClient *cptr)
 1233 {
 1234     if(cptr->sockerr == 0)
 1235         return "No error";
 1236     
 1237     if(cptr->sockerr > 0)
 1238         return strerror(cptr->sockerr);
 1239     
 1240     switch(cptr->sockerr)
 1241     { 
 1242         case -1: /* this is the default */
 1243             return "Unset error message [this is a bug!]";
 1244         case IRCERR_BUFALLOC:
 1245             return "dbuf allocation error";
 1246         case IRCERR_ZIP:
 1247             return "compression general failure";
 1248         case IRCERR_SSL:
 1249             return "SSL error";
 1250         default:
 1251             return "Unknown error!";
 1252     }
 1253     
 1254     /* unreachable code, but the compiler is complaining.. */
 1255     return NULL;
 1256 }
 1257 
 1258 /*
 1259  * * set_non_blocking 
 1260  *       Set the client connection into non-blocking mode. 
 1261  */
 1262 void set_non_blocking(int fd, aClient * cptr)
 1263 {
 1264     int res, nonb = 0;
 1265 
 1266     nonb |= O_NONBLOCK;
 1267     if ((res = fcntl(fd, F_GETFL, 0)) == -1)
 1268         silent_report_error("fcntl(fd, F_GETFL) failed for %s:%s", cptr);
 1269     else if (fcntl(fd, F_SETFL, res | nonb) == -1)
 1270         silent_report_error("fcntl(fd, F_SETL, nonb) failed for %s:%s", cptr);
 1271     return;
 1272 }
 1273 
 1274 void set_listener_non_blocking(int fd, aListener *lptr)
 1275 {
 1276     int res, nonb = 0;
 1277 
 1278     nonb |= O_NONBLOCK;
 1279     if ((res = fcntl(fd, F_GETFL, 0)) == -1)
 1280         report_listener_error("fcntl(fd, F_GETFL) failed for %s:%s", lptr);
 1281     else if (fcntl(fd, F_SETFL, res | nonb) == -1)
 1282         report_listener_error("fcntl(fd, F_SETL, nonb) failed for %s:%s", lptr);
 1283     return;
 1284 }
 1285 
 1286 
 1287 /*
 1288  * Creates a client which has just connected to us on the given fd. The
 1289  * sockhost field is initialized with the ip# of the host. The client
 1290  * is added to the linked list of clients but isnt added to any hash
 1291  * tables yuet since it doesnt have a name.
 1292  */
 1293 aClient *add_connection(aListener *lptr, int fd)
 1294 {
 1295     Link lin;
 1296     aClient *acptr = NULL;
 1297     union
 1298     {
 1299     struct sockaddr sa;
 1300     struct sockaddr_in addr4;
 1301     struct sockaddr_in6 addr6;
 1302     } addr;
 1303     unsigned int len = sizeof(addr);
 1304     struct userBan *ban;
 1305 
 1306     if (getpeername(fd, &addr.sa, &len) == -1)
 1307     {
 1308         ircstp->is_ref++;
 1309         close(fd);
 1310         return NULL;
 1311     }
 1312 
 1313     acptr = make_client(NULL, &me);
 1314     acptr->ip_family = addr.sa.sa_family;
 1315 
 1316     /*
 1317      * Copy ascii address to 'sockhost' just in case. Then we have
 1318      * something valid to put into error messages...
 1319      */
 1320     if (acptr->ip_family == AF_INET)
 1321     {
 1322     get_sockhost(acptr, (char *) inetntoa((char *) &addr.addr4.sin_addr));
 1323     memcpy((char *) &acptr->ip.ip4, (char *) &addr.addr4.sin_addr,
 1324         sizeof(struct in_addr));
 1325     acptr->port = ntohs(addr.addr4.sin_port);
 1326     }
 1327     else if (acptr->ip_family == AF_INET6)
 1328     {
 1329     get_sockhost(acptr, (char *) inet6ntoa((char *) &addr.addr6.sin6_addr));
 1330     memcpy((char *) &acptr->ip.ip6, (char *) &addr.addr6.sin6_addr,
 1331         sizeof(struct in6_addr));
 1332     acptr->port = ntohs(addr.addr6.sin6_port);
 1333     }
 1334 
 1335     /*
 1336      * Check that this socket (client) is allowed to accept
 1337      * connections from this IP#.
 1338      */
 1339     if (lptr->allow_cidr_bits > 0 &&
 1340     bitncmp(&acptr->ip, &lptr->allow_ip, lptr->allow_cidr_bits) != 0)
 1341     {
 1342     ircstp->is_ref++;
 1343     acptr->fd = -2;
 1344     free_client(acptr);
 1345     close(fd);
 1346     return NULL;
 1347     }
 1348 
 1349     lptr->ccount++;
 1350     lptr->clients++;
 1351     Count.unknown++;
 1352     add_fd(fd, FDT_CLIENT, acptr);
 1353     local[fd] = acptr;
 1354 
 1355     acptr->fd = fd;
 1356     if (fd > highest_fd)
 1357         highest_fd = fd;
 1358 
 1359     /* sockets inherit the options of their parents.. do we need these? */
 1360     set_non_blocking(acptr->fd, acptr);
 1361     set_sock_opts(acptr->fd, acptr);
 1362 
 1363     acptr->lstn = lptr;
 1364     add_client_to_list(acptr);
 1365 
 1366     ban = check_userbanned(acptr, UBAN_IP|UBAN_CIDR4|UBAN_WILDUSER, 0);
 1367     if(ban)
 1368     {
 1369         int loc = (ban->flags & UBAN_LOCAL) ? 1 : 0;
 1370         
 1371         ircstp->is_ref++;
 1372         ircstp->is_ref_1++;
 1373         exit_banned_client(acptr, loc, loc ? 'K' : 'A', ban->reason, 0);
 1374 
 1375         return NULL;
 1376     }
 1377 
 1378     if(call_hooks(CHOOK_PREACCESS, acptr) == FLUSH_BUFFER)
 1379         return NULL;
 1380 
 1381     /* do the dns check, if we're thusly configured */
 1382     if(!(lptr->flags & CONF_FLAGS_P_NODNS))
 1383     {
 1384 #ifdef SHOW_HEADERS
 1385         sendto_one(acptr, "%s", REPORT_DO_DNS);
 1386 #endif
 1387         lin.flags = ASYNC_CLIENT;
 1388         lin.value.cptr = acptr;
 1389     if (acptr->ip_family == AF_INET)
 1390     {
 1391         Debug((DEBUG_DNS, "lookup %s",
 1392            inetntoa((char *) &addr.addr4.sin_addr)));
 1393         acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip4, &lin,
 1394                       AF_INET);
 1395     }
 1396     else if (acptr->ip_family == AF_INET6)
 1397     {
 1398         Debug((DEBUG_DNS, "lookup %s",
 1399            inet6ntoa((char *) &addr.addr6.s6_addr)));
 1400         acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip6, &lin,
 1401                       AF_INET6);
 1402     }
 1403     if (!acptr->hostp)
 1404             SetDNS(acptr);
 1405 #ifdef SHOW_HEADERS
 1406         else
 1407             sendto_one(acptr, "%s", REPORT_FIN_DNSC);
 1408 #endif
 1409         nextdnscheck = 1;
 1410     }
 1411     
 1412 #ifdef DO_IDENTD
 1413     if(!(lptr->flags & CONF_FLAGS_P_NOIDENT))
 1414         start_auth(acptr);
 1415 #endif
 1416     check_client_fd(acptr);
 1417 
 1418 #ifdef USE_SSL
 1419     if(IsSSL(lptr))
 1420     {
 1421         extern SSL_CTX *ircdssl_ctx;
 1422 
 1423         acptr->ssl = NULL;
 1424         if((acptr->ssl = SSL_new(ircdssl_ctx)) == NULL)
 1425         {
 1426               sendto_realops_lev(DEBUG_LEV, "SSL creation of "
 1427                         "new SSL object failed [client %s]",
 1428                         acptr->sockhost);
 1429               ircstp->is_ref++;
 1430               acptr->fd = -2;
 1431               free_client(acptr);
 1432               return NULL;
 1433         }
 1434         SetSSL(acptr);
 1435         set_non_blocking(fd, acptr);
 1436         set_sock_opts(fd, acptr);
 1437         SSL_set_fd(acptr->ssl, fd);
 1438         if(!safe_ssl_accept(acptr, fd))
 1439         {
 1440             SSL_set_shutdown(acptr->ssl, SSL_RECEIVED_SHUTDOWN);
 1441             ssl_smart_shutdown(acptr->ssl);
 1442             SSL_free(acptr->ssl);
 1443             ircstp->is_ref++;
 1444             acptr->fd = -2;
 1445             free_client(acptr);
 1446             close(fd);
 1447             return NULL;
 1448         }
 1449     }
 1450 #endif
 1451 
 1452     return acptr;
 1453 }
 1454 
 1455 /* handle taking care of the client's recvq here */
 1456 int do_client_queue(aClient *cptr)
 1457 {
 1458     int dolen = 0, done;
 1459     
 1460     while (SBufLength(&cptr->recvQ) && !NoNewLine(cptr) &&
 1461        ((cptr->status < STAT_UNKNOWN) || (cptr->since - timeofday < 10) ||
 1462         IsNegoServer(cptr))) 
 1463     {
 1464         /* If it's become registered as a server, just parse the whole block */
 1465         if (IsServer(cptr) || IsNegoServer(cptr)) 
 1466         {
 1467 #if defined(MAXBUFFERS)
 1468             dolen = sbuf_get(&cptr->recvQ, readbuf, rcvbufmax * sizeof(char));
 1469 #else
 1470             dolen = sbuf_get(&cptr->recvQ, readbuf, sizeof(readbuf));
 1471 #endif
 1472             if (dolen <= 0)
 1473                 break;
 1474             if ((done = dopacket(cptr, readbuf, dolen)))
 1475                 return done;
 1476             break;
 1477         }
 1478 #if defined(MAXBUFFERS)
 1479         dolen = sbuf_getmsg(&cptr->recvQ, readbuf, rcvbufmax * sizeof(char));
 1480 #else
 1481         dolen = sbuf_getmsg(&cptr->recvQ, readbuf, sizeof(readbuf));
 1482 #endif
 1483     
 1484         if (dolen <= 0) 
 1485         {
 1486             if (dolen < 0)
 1487                 return exit_client(cptr, cptr, cptr, "sbuf_getmsg fail");
 1488         
 1489             if (SBufLength(&cptr->recvQ) < 510) 
 1490             {
 1491                 cptr->flags |= FLAGS_NONL;
 1492                 break;
 1493             }
 1494             /* The buffer is full (more than 512 bytes) and it has no \n
 1495              * Some user is trying to trick us. Kill their recvq. */
 1496             SBufClear(&cptr->recvQ);
 1497             break;
 1498         }
 1499         else if(client_dopacket(cptr, readbuf, dolen) == FLUSH_BUFFER)
 1500             return FLUSH_BUFFER;
 1501     }
 1502 
 1503     if(!(cptr->flags & FLAGS_HAVERECVQ) && SBufLength(&cptr->recvQ) && 
 1504         !NoNewLine(cptr))
 1505     {
 1506        add_to_list(&recvq_clients, cptr);
 1507        cptr->flags |= FLAGS_HAVERECVQ;
 1508     }
 1509 
 1510     return 1;
 1511 }
 1512 
 1513 /*
 1514  * read_packet
 1515  *
 1516  * Read a 'packet' of data from a connection and process it.  Read in 8k 
 1517  * chunks to give a better performance rating (for server connections). 
 1518  * Do some tricky stuff for client connections to make sure they don't
 1519  * do any flooding >:-) -avalon
 1520  */
 1521 
 1522 #define MAX_CLIENT_RECVQ 8192
 1523 
 1524 int read_packet(aClient * cptr)
 1525 {
 1526     int length = 0, done;
 1527 
 1528     /* If data is ready, and the user is either not a person or
 1529      * is a person and has a recvq of less than MAX_CLIENT_RECVQ,
 1530      * read from this client
 1531      */ 
 1532     if (!(IsPerson(cptr) && SBufLength(&cptr->recvQ) > MAX_CLIENT_RECVQ)) 
 1533     {
 1534         errno = 0;
 1535     
 1536 #if defined(MAXBUFFERS)
 1537         if (IsPerson(cptr))
 1538         {
 1539 #ifdef USE_SSL
 1540             if(IsSSL(cptr) && cptr->ssl)
 1541                 length = safe_ssl_read(cptr, readbuf, 8192 * sizeof(char));
 1542             else
 1543 #endif
 1544             length = recv(cptr->fd, readbuf, 8192 * sizeof(char), 0);
 1545         }
 1546 #ifdef USE_SSL
 1547         else if(IsSSL(cptr) && cptr->ssl)
 1548             length = safe_ssl_read(cptr, readbuf, rcvbufmax * sizeof(char));
 1549 #endif
 1550         else
 1551             length = recv(cptr->fd, readbuf, rcvbufmax * sizeof(char), 0);
 1552 #else
 1553 #ifdef USE_SSL
 1554         if(IsSSL(cptr) && cptr->ssl)
 1555             length = safe_ssl_read(cptr, readbuf, sizeof(readbuf));
 1556         else
 1557 #endif
 1558         length = recv(cptr->fd, readbuf, sizeof(readbuf), 0);
 1559 #endif
 1560 
 1561         cptr->lasttime = timeofday;
 1562         if (cptr->lasttime > cptr->since)
 1563             cptr->since = cptr->lasttime;
 1564         cptr->flags &= ~(FLAGS_PINGSENT | FLAGS_NONL);
 1565         /* If not ready, fake it so it isnt closed */
 1566         if (length == -1 && ((errno == EWOULDBLOCK) || (errno == EAGAIN)))
 1567             return 1;
 1568         if (length <= 0)
 1569         {
 1570             cptr->sockerr = length ? errno : 0;
 1571             return length;
 1572         }
 1573     }
 1574 
 1575     /* 
 1576      * For server connections, we process as many as we can without
 1577      * worrying about the time of day or anything :)
 1578      */
 1579     if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr) ||
 1580         IsNegoServer(cptr)) 
 1581     {
 1582         if (length > 0)
 1583             if ((done = dopacket(cptr, readbuf, length)))
 1584                 return done;
 1585     } 
 1586     else 
 1587     {
 1588         /* 
 1589          * Before we even think of parsing what we just read, stick 
 1590          * it on the end of the receive queue and do it when its turn
 1591          * comes around. */
 1592         if (sbuf_put(&cptr->recvQ, readbuf, length) < 0)
 1593             return exit_client(cptr, cptr, cptr, "sbuf_put fail");
 1594     
 1595         if (IsPerson(cptr) &&
 1596 #ifdef NO_OPER_FLOOD
 1597         !IsAnOper(cptr) &&
 1598 #endif
 1599         SBufLength(&cptr->recvQ) > ((cptr->class && cptr->class->maxrecvq) ? cptr->class->maxrecvq : CLIENT_FLOOD))
 1600         {
 1601             if(call_hooks(CHOOK_FLOODWARN, cptr, NULL, 2, NULL, NULL) != FLUSH_BUFFER)
 1602                 sendto_realops_lev(FLOOD_LEV, "Flood -- %s!%s@%s (%d) Exceeds %d"
 1603                                    " RecvQ", cptr->name[0] ? cptr->name : "*",
 1604                                    cptr->user ? cptr->user->username : "*",
 1605                                    cptr->user ? cptr->user->host : "*",
 1606                                    SBufLength(&cptr->recvQ), (cptr->class && cptr->class->maxrecvq) ? cptr->class->maxrecvq : CLIENT_FLOOD);
 1607             return exit_client(cptr, cptr, cptr, "Excess Flood");
 1608         }
 1609         return do_client_queue(cptr);
 1610     }
 1611     return 1;
 1612 }
 1613 
 1614 void read_error_exit(aClient *cptr, int length, int err)
 1615 {
 1616     char fbuf[512];
 1617     char errmsg[512];
 1618     
 1619     if (IsServer(cptr) || IsHandshake(cptr) || IsConnecting(cptr)) 
 1620     {
 1621         if (length == 0) 
 1622         {
 1623             char *errtxt = "Server %s closed the connection";
 1624         
 1625             ircsprintf(fbuf, "from %s: %s", me.name, errtxt);
 1626             sendto_gnotice(fbuf, get_client_name(cptr, HIDEME));
 1627             ircsprintf(fbuf, ":%s GNOTICE :%s", me.name, errtxt);
 1628             sendto_serv_butone(cptr, fbuf, get_client_name(cptr, HIDEME));
 1629         }
 1630         else 
 1631         {
 1632             char *errtxt = (IsConnecting(cptr) || IsHandshake(cptr)) ? 
 1633                             "Connect error to %s (%s)" : 
 1634                             "Read error from %s, closing link (%s)";
 1635 
 1636             ircsprintf(fbuf, "from %s: %s", me.name, errtxt);
 1637             sendto_gnotice(fbuf, get_client_name(cptr, HIDEME), strerror(err));
 1638             ircsprintf(fbuf, ":%s GNOTICE :%s", me.name, errtxt);
 1639             sendto_serv_butone(cptr, fbuf, get_client_name(cptr, HIDEME), 
 1640                                strerror(err));
 1641         }
 1642     }
 1643     
 1644     if (err && !(err==IRCERR_SSL && length==-1 && errno==0))
 1645         ircsprintf(errmsg, "Read error: %s", strerror(err));
 1646     else
 1647         ircsprintf(errmsg, "Client closed connection");
 1648     
 1649     exit_client(cptr, cptr, &me, errmsg);
 1650 }
 1651 
 1652 void accept_connection(aListener *lptr)
 1653 {
 1654     union
 1655     {
 1656     struct sockaddr sa;
 1657     struct sockaddr_in addr4;
 1658     struct sockaddr_in6 addr6;
 1659     } addr;
 1660     unsigned int addrlen = sizeof(addr);
 1661     char host[HOSTLEN + 2];
 1662     int newfd;
 1663     int i;
 1664 
 1665     lptr->lasttime = timeofday;
 1666 
 1667     for (i = 0; i < 100; i++) /* accept up to 100 times per call
 1668                                * to deal with high connect rates */
 1669     {
 1670         if((newfd = accept(lptr->fd, &addr.sa, &addrlen)) < 0)
 1671         {
 1672             switch(errno)
 1673             {
 1674 #ifdef EMFILE
 1675                 case EMFILE:
 1676                     report_listener_error("Cannot accept connections %s:%s", 
 1677                                            lptr);
 1678                     break;
 1679 #endif
 1680 #ifdef ENFILE
 1681                 case ENFILE:
 1682                     report_listener_error("Cannot accept connections %s:%s", 
 1683                                            lptr);
 1684                     break;
 1685 #endif
 1686             }
 1687         return;
 1688         }
 1689 
 1690     if (addr.sa.sa_family == AF_INET)
 1691     {
 1692         strncpyzt(host, (char *) inetntoa((char *) &addr.addr4.sin_addr),
 1693               sizeof(host));
 1694     }
 1695     else if (addr.sa.sa_family == AF_INET6)
 1696     {
 1697         strncpyzt(host, (char *) inet6ntoa((char *) &addr.addr6.sin6_addr),
 1698               sizeof(host));
 1699     }
 1700     else
 1701     {
 1702         /* unknown address family. */
 1703         close(newfd);
 1704         return;
 1705     }
 1706 
 1707         /* if they are throttled, drop them silently. */
 1708         if (throttle_check(host, newfd, NOW) == 0)
 1709         {
 1710             ircstp->is_ref++;
 1711             ircstp->is_throt++;
 1712             close(newfd);
 1713             return;
 1714         }
 1715 
 1716         if (newfd >= MAX_ACTIVECONN)
 1717         {
 1718             ircstp->is_ref++;
 1719             sendto_realops_lev(CCONN_LEV,"All connections in use. fd: %d (%s)",
 1720                 newfd,get_listener_name(lptr));
 1721             send(newfd, "ERROR :All connections in use\r\n", 32, 0);
 1722             close(newfd);
 1723             return;
 1724         }
 1725         if(lptr->aport->legal == -1)
 1726         {
 1727             ircstp->is_ref++;
 1728             send(newfd, "ERROR :This port is closed\r\n", 29, 0);
 1729             close(newfd);
 1730             return;
 1731         }
 1732         ircstp->is_ac++;
 1733 
 1734         add_connection(lptr, newfd);
 1735 #ifdef PINGNAZI
 1736         nextping = timeofday;
 1737 #endif
 1738     }
 1739 }
 1740 
 1741 int readwrite_client(aClient *cptr, int isread, int iswrite)
 1742 {
 1743     /*
 1744      * NOTE
 1745      * We now do this in a more logical way.
 1746      * We request a write poll on a socket for two reasons
 1747      * - the socket is waiting for a connect() call
 1748      * - the socket is blocked
 1749      */
 1750 
 1751 #ifdef USE_SSL
 1752     if(cptr->ssl && IsSSL(cptr) && !SSL_is_init_finished(cptr->ssl))
 1753     {
 1754         if(IsDead(cptr) || !safe_ssl_accept(cptr, cptr->fd))
 1755         {
 1756             if(IsClient(cptr))
 1757                 return exit_client(cptr, cptr, &me, iswrite?"Write Error: SSL Bug #7845":"Read Error: SSL Bug #7845");
 1758             close_connection(cptr);
 1759         }
 1760         return 1;
 1761     }
 1762 #endif
 1763 
 1764     if(iswrite)
 1765     {
 1766         if (IsConnecting(cptr) && completed_connection(cptr))
 1767         {
 1768             char errmsg[512];
 1769 
 1770             ircsprintf(errmsg, "Connect Error: %s", irc_get_sockerr(cptr));
 1771             return exit_client(cptr, cptr, &me, errmsg);
 1772         }
 1773 
 1774         if(cptr->flags & FLAGS_BLOCKED)
 1775         {
 1776             cptr->flags &= ~FLAGS_BLOCKED;
 1777             unset_fd_flags(cptr->fd, FDF_WANTWRITE);
 1778         }
 1779         else 
 1780         {
 1781             /* this may be our problem with occational 100% cpu looping
 1782              * we've experienced.  jason suggested this, here we will try
 1783              * this and see if it happens at all -epi */
 1784             sendto_realops_lev(DEBUG_LEV, "Removing socket %d: reported ready"
 1785                                " for write, but not blocking", cptr->fd);
 1786             /* This unset_fd_flags() does not appear to make any difference
 1787              * to the write set.  The socket appears stuck, and there has
 1788              * to be a reason for it.  Since we're experiencing a very low
 1789              * number of these, simply drop the client entirely, and treat
 1790              * this as a socket handling error.  This is essentially a kludge
 1791              * however tracking down this bug will take a serious amount of
 1792              * time and testing - since its not easily reproducable.  This 
 1793              * will in the meantime prevent maxing the CPU.  -epi 
 1794              *
 1795              * unset_fd_flags(cptr->fd, FDF_WANTWRITE);
 1796              */
 1797             exit_client(cptr, cptr, &me, "Socket error (write)");
 1798             return FLUSH_BUFFER;
 1799         }
 1800 
 1801     }
 1802 
 1803     if (isread)
 1804     {
 1805         int length = read_packet(cptr);
 1806 
 1807         if(length == FLUSH_BUFFER)
 1808             return length;
 1809 
 1810         if(length <= 0)
 1811         {
 1812             read_error_exit(cptr, length, cptr->sockerr);
 1813             return FLUSH_BUFFER;
 1814         }
 1815     }
 1816 
 1817     if (IsDead(cptr))
 1818     {
 1819         char errmsg[512];
 1820 
 1821         ircsprintf(errmsg, "Write Error: %s", (cptr->flags & FLAGS_SENDQEX) ?
 1822                    "SendQ Exceeded" : irc_get_sockerr(cptr));
 1823         return exit_client(cptr, cptr, &me, errmsg);
 1824     }
 1825 
 1826     return 1;
 1827 }
 1828 
 1829 /* connect_server */
 1830 int connect_server(aConnect *aconn, aClient * by, struct hostent *hp)
 1831 {
 1832     struct sockaddr *svp;
 1833     aClient *cptr, *c2ptr;
 1834     char *s;
 1835     int errtmp, len;
 1836 
 1837     if (aconn->ipnum_family == AF_INET)
 1838     {
 1839     Debug((DEBUG_NOTICE, "Connect to %s[%s] @%s", aconn->name, aconn->host,
 1840            inetntoa((char *)aconn->ipnum.ip4)));
 1841     }
 1842     else if (aconn->ipnum_family == AF_INET6)
 1843     {
 1844     Debug((DEBUG_NOTICE, "Connect to %s[%s] @%s", aconn->name, aconn->host,
 1845            inet6ntoa((char *)aconn->ipnum.ip6)));
 1846     }
 1847     else
 1848     {
 1849     Debug((DEBUG_NOTICE, "Connect to %s[%s]", aconn->name, aconn->host));
 1850     }
 1851 
 1852     if ((c2ptr = find_server(aconn->name, NULL)))
 1853     {
 1854         sendto_ops("Server %s already present from %s",
 1855                     aconn->name, get_client_name(c2ptr, HIDEME));
 1856         if (by && IsPerson(by) && !MyClient(by))
 1857             sendto_one(by, ":%s NOTICE %s :Server %s already present from %s",
 1858                        me.name, by->name, aconn->name,
 1859                        get_client_name(c2ptr, HIDEME));
 1860         return -1;
 1861     }
 1862 
 1863     /*
 1864      * If we dont know the IP# for this host and itis a hostname and not
 1865      * a ip# string, then try and find the appropriate host record.
 1866      */
 1867     if (aconn->ipnum_family == 0)
 1868     {
 1869         Link lin;
 1870 
 1871         lin.flags = ASYNC_CONNECT;
 1872         lin.value.aconn = aconn;
 1873         nextdnscheck = 1;
 1874         s = (char *) strchr(aconn->host, '@');
 1875         s++;            /* should NEVER be NULL */
 1876 
 1877     if (inet_pton(AF_INET, s, &aconn->ipnum.ip4) == 1)
 1878         aconn->ipnum_family = AF_INET;
 1879     else if (inet_pton(AF_INET6, s, &aconn->ipnum.ip6) == 1)
 1880         aconn->ipnum_family = AF_INET6;
 1881     else
 1882         {
 1883         union
 1884         {
 1885         struct sockaddr_in ip4;
 1886         struct sockaddr_in6 ip6;
 1887         } tmp_addr;
 1888         int family;
 1889 
 1890         /* Try to use the same address family as what we bind to. */
 1891         if (aconn->source &&
 1892         inet_pton(AF_INET, aconn->source, &tmp_addr.ip4) == 1)
 1893         family = AF_INET;
 1894         else if (aconn->source &&
 1895              inet_pton(AF_INET6, aconn->source, &tmp_addr.ip6) == 1)
 1896         family = AF_INET6;
 1897         else
 1898         family = AF_INET;
 1899 
 1900             hp = gethost_byname(s, &lin, family);
 1901             Debug((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s",
 1902                                  hp, aconn, aconn->name, s));
 1903             if (!hp)
 1904                 return 0;
 1905 
 1906         aconn->ipnum_family = hp->h_addrtype;
 1907             memcpy((char *) &aconn->ipnum, hp->h_addr, hp->h_length);
 1908         }
 1909     }
 1910     cptr = make_client(NULL, &me);
 1911     cptr->hostp = hp;
 1912     /* Copy these in so we have something for error detection. */
 1913     strncpyzt(cptr->name, aconn->name, sizeof(cptr->name));
 1914     strncpyzt(cptr->sockhost, aconn->host, HOSTLEN + 1);
 1915     svp = connect_inet(aconn, cptr, &len);
 1916 
 1917     if (!svp)
 1918     {
 1919         if (cptr->fd >= 0)
 1920             close(cptr->fd);
 1921         cptr->fd = -2;
 1922         free_client(cptr);
 1923         return -1;
 1924     }
 1925     
 1926     set_non_blocking(cptr->fd, cptr);
 1927     set_sock_opts(cptr->fd, cptr);
 1928     signal(SIGALRM, dummy);
 1929     if (connect(cptr->fd, svp, len) < 0 && errno != EINPROGRESS) 
 1930     {
 1931         errtmp = errno;     /* other system calls may eat errno */
 1932         report_error("Connect to host %s failed: %s", cptr);
 1933         if (by && IsPerson(by) && !MyClient(by))
 1934             sendto_one(by, ":%s NOTICE %s :Connect to server %s failed.",
 1935                        me.name, by->name, cptr->name);
 1936         close(cptr->fd);
 1937         cptr->fd = -2;
 1938         free_client(cptr);
 1939         errno = errtmp;
 1940         if (errno == EINTR)
 1941             errno = ETIMEDOUT;
 1942         return -1;
 1943     }
 1944     
 1945     make_server(cptr);
 1946     cptr->serv->aconn = aconn;
 1947     
 1948     /* The socket has been connected or connect is in progress. */
 1949     if (by && IsPerson(by))
 1950     {
 1951         strcpy(cptr->serv->bynick, by->name);
 1952         strcpy(cptr->serv->byuser, by->user->username);
 1953         strcpy(cptr->serv->byhost, by->user->host);
 1954     }
 1955     else
 1956     {
 1957         strcpy(cptr->serv->bynick, "AutoConn.");
 1958         *cptr->serv->byuser = '\0';
 1959         *cptr->serv->byhost = '\0';
 1960     }
 1961     cptr->serv->up = me.name;
 1962     if (cptr->fd > highest_fd)
 1963         highest_fd = cptr->fd;
 1964     local[cptr->fd] = cptr;
 1965     SetConnecting(cptr);
 1966 
 1967     get_sockhost(cptr, aconn->host);
 1968     add_client_to_list(cptr);
 1969 #ifdef PINGNAZI
 1970     nextping = timeofday;
 1971 #endif
 1972 
 1973     add_fd(cptr->fd, FDT_CLIENT, cptr);
 1974     cptr->flags |= FLAGS_BLOCKED;
 1975     set_fd_flags(cptr->fd, FDF_WANTREAD|FDF_WANTWRITE);
 1976 
 1977     return 0;
 1978 }
 1979 
 1980 static struct sockaddr *
 1981 connect_inet(aConnect *aconn, aClient *cptr, int *lenp)
 1982 {
 1983     static union
 1984     {
 1985     struct sockaddr sa;
 1986     struct sockaddr_in addr4;
 1987     struct sockaddr_in6 addr6;
 1988     } server;
 1989     struct hostent *hp;
 1990     union
 1991     {
 1992     struct sockaddr sa;
 1993     struct sockaddr_in addr4;
 1994     struct sockaddr_in6 addr6;
 1995     } sin;
 1996     unsigned int len;
 1997 
 1998     /*
 1999      * Might as well get sockhost from here, the connection is attempted
 2000      * with it so if it fails its useless.
 2001      */
 2002     memset((char *) &server, '\0', sizeof(server));
 2003     memset((char *) &sin, '\0', sizeof(sin));
 2004     get_sockhost(cptr, aconn->host);
 2005 
 2006     /*
 2007      * By this point we should know the IP# of the host listed in the
 2008      * conf line, whether as a result of the hostname lookup or the ip#
 2009      * being present instead. If we dont know it, then the connect
 2010      * fails.
 2011      */
 2012     if (aconn->ipnum_family == 0)
 2013     {
 2014         hp = cptr->hostp;
 2015         if (!hp)
 2016         {
 2017             Debug((DEBUG_FATAL, "%s: unknown host", aconn->host));
 2018             return NULL;
 2019         }
 2020     aconn->ipnum_family = hp->h_addrtype;
 2021         memcpy((char *) &aconn->ipnum, hp->h_addr, hp->h_length);
 2022     }
 2023 
 2024     if (aconn->ipnum_family == AF_INET)
 2025     {
 2026     server.addr4.sin_family = AF_INET;
 2027     memcpy((char *) &server.addr4.sin_addr, (char *) &aconn->ipnum.ip4,
 2028            sizeof(struct in_addr));
 2029     server.addr4.sin_port = htons((aconn->port > 0) ? aconn->port : PORTNUM);
 2030     len = sizeof(server.addr4);
 2031 
 2032     cptr->ip_family = AF_INET;
 2033     memcpy((char *) &cptr->ip.ip4, (char *) &aconn->ipnum.ip4,
 2034            sizeof(struct in_addr));
 2035     }
 2036     else if (aconn->ipnum_family == AF_INET6)
 2037     {
 2038     server.addr6.sin6_family = AF_INET6;
 2039     memcpy((char *) &server.addr6.sin6_addr, (char *) &aconn->ipnum.ip6,
 2040            sizeof(struct in6_addr));
 2041     server.addr6.sin6_port = htons((aconn->port > 0) ? aconn->port : PORTNUM);
 2042     len = sizeof(server.addr6);
 2043 
 2044     cptr->ip_family = AF_INET6;
 2045     memcpy((char *) &cptr->ip.ip6, (char *) &aconn->ipnum.ip6,
 2046            sizeof(struct in6_addr));
 2047     }
 2048     else
 2049     {
 2050     report_error("unknown address family connecting to server %s:%s", cptr);
 2051     return NULL;
 2052     }
 2053 
 2054     cptr->fd = socket(server.sa.sa_family, SOCK_STREAM, 0);
 2055     if (cptr->fd >= MAX_ACTIVECONN)
 2056     {
 2057         sendto_realops("No more connections allowed (%s)", cptr->name);
 2058         return NULL;
 2059     }
 2060     if (cptr->fd < 0)
 2061     {
 2062         report_error("opening stream socket to server %s:%s", cptr);
 2063         cptr->fd = -2;
 2064         return NULL;
 2065     }
 2066 
 2067     /*
 2068      * Bind to a local IP# (with unknown port - let unix decide) so *
 2069      * we have some chance of knowing the IP# that gets used for a host *
 2070      * with more than one IP#.
 2071      *
 2072      * No we don't bind it, not all OS's can handle connecting with an
 2073      * already bound socket, different ip# might occur anyway leading to
 2074      * a freezing select() on this side for some time.
 2075      */
 2076     if (aconn->source)
 2077     {
 2078         /*
 2079          * * No, we do bind it if we have virtual host support. If we
 2080          * don't explicitly bind it, it will default to IN_ADDR_ANY and
 2081          * we lose due to the other server not allowing our base IP
 2082          * --smg
 2083          */
 2084     if (inet_pton(AF_INET, aconn->source, &sin.addr4.sin_addr) == 1)
 2085     {
 2086         sin.addr4.sin_family = AF_INET;
 2087         len = sizeof(sin.addr4);
 2088     }
 2089     else if (inet_pton(AF_INET6, aconn->source, &sin.addr6.sin6_addr) == 1)
 2090     {
 2091         sin.addr6.sin6_family = AF_INET6;
 2092         len = sizeof(sin.addr6);
 2093     }
 2094     else
 2095         sin.sa.sa_family = 0;
 2096 
 2097     if (server.sa.sa_family != sin.sa.sa_family)
 2098     {
 2099         report_error("address family for bind and connect do not match "
 2100              "for %s:%s", cptr);
 2101         close(cptr->fd);
 2102         return NULL;
 2103     }
 2104 
 2105         if (bind(cptr->fd, (struct sockaddr *) &sin, len) == -1)
 2106         {
 2107             report_error("error binding to local port for %s:%s", cptr);
 2108             close(cptr->fd);
 2109             return NULL;
 2110         }
 2111     }
 2112 
 2113     *lenp = len;
 2114     return (struct sockaddr *) &server;
 2115 }
 2116 
 2117 /*
 2118  * find the real hostname for the host running the server (or one
 2119  * which matches the server's name) and its primary IP#.  Hostname is
 2120  * stored in the client structure passed as a pointer.
 2121  */
 2122 void get_my_name(aClient * cptr, char *name, int len)
 2123 {
 2124     static char tmp[HOSTLEN + 1];
 2125     struct hostent *hp;
 2126 
 2127     /* 
 2128      * The following conflicts with both AIX and linux prototypes oh
 2129      * well, we can put up with the errors from other systems -Dianora
 2130      */
 2131 
 2132     char *cname = cptr->name;
 2133     
 2134     /* Setup local socket structure to use for binding to. */
 2135     memset((char *) &mysk, '\0', sizeof(mysk));
 2136     mysk.sin_family = AF_INET;
 2137 
 2138     if (gethostname(name, len) == -1)
 2139         return;
 2140     name[len] = '\0';
 2141     
 2142     /* assume that a name containing '.' is a FQDN */
 2143     if (!strchr(name, '.'))
 2144         add_local_domain(name, len - strlen(name));
 2145     /* 
 2146      * If hostname gives another name than cname, then check if there
 2147      * is a CNAME record for cname pointing to hostname. If so accept
 2148      * cname as our name.   meLazy
 2149      */
 2150     if (BadPtr(cname))
 2151         return;
 2152     if ((hp = gethostbyname(cname)) || (hp = gethostbyname(name)))
 2153     {
 2154         char *hname;
 2155         int i = 0;
 2156     
 2157         for (hname = hp->h_name; hname; hname = hp->h_aliases[i++])
 2158         {
 2159             strncpyzt(tmp, hname, sizeof(tmp));
 2160             add_local_domain(tmp, sizeof(tmp) - strlen(tmp));
 2161             /* 
 2162              * Copy the matching name over and store the 'primary' IP#
 2163              * as 'myip' which is used later for making the right one is
 2164              * used for connecting to other hosts.
 2165              */
 2166             if (!mycmp(me.name, tmp))
 2167                 break;
 2168         }
 2169         if (mycmp(me.name, tmp))
 2170             strncpyzt(name, hp->h_name, len);
 2171         else
 2172             strncpyzt(name, tmp, len);
 2173         memcpy((char *) &mysk.sin_addr, hp->h_addr, sizeof(struct in_addr));
 2174 
 2175         Debug((DEBUG_DEBUG, "local name is %s", get_client_name(&me, TRUE)));
 2176     }
 2177     return;
 2178 }
 2179 
 2180 /*
 2181  * do_dns_async
 2182  *
 2183  * Called when the fd returned from init_resolver() has been selected for
 2184  * reading.
 2185  */
 2186 void do_dns_async()
 2187 {
 2188     static Link ln;
 2189     aClient *cptr;
 2190     aConnect *aconn;
 2191     struct hostent *hp;
 2192     int bytes, packets = 0;
 2193 
 2194     do
 2195     {
 2196         ln.flags = -1;
 2197         hp = get_res((char *) &ln);
 2198         Debug((DEBUG_DNS, "%#x = get_res(%d,%#x)", hp, ln.flags, 
 2199                ln.value.cptr));
 2200 
 2201         switch (ln.flags)
 2202         {
 2203             case ASYNC_NONE:
 2204             /* 
 2205              * no reply was processed that was outstanding or had
 2206              * a client still waiting.
 2207              */
 2208                 break;
 2209             case ASYNC_CLIENT:
 2210                 if ((cptr = ln.value.cptr))
 2211                 {
 2212                     del_queries((char *) cptr);
 2213 #ifdef SHOW_HEADERS
 2214                     sendto_one(cptr, "%s", REPORT_FIN_DNS);
 2215 #endif
 2216                     ClearDNS(cptr);
 2217                     cptr->hostp = hp;
 2218                     check_client_fd(cptr);
 2219                 }
 2220                 break;
 2221             case ASYNC_CONNECT:
 2222                 aconn = ln.value.aconn;
 2223                 if (hp && aconn)
 2224                 {
 2225             aconn->ipnum_family = hp->h_addrtype;
 2226                     memcpy((char *) &aconn->ipnum, hp->h_addr, hp->h_length);
 2227 
 2228                     connect_server(aconn, NULL, hp);
 2229                 }
 2230                 else
 2231                     sendto_ops("Connect to %s failed: host lookup",
 2232                                 (aconn) ? aconn->host : "unknown");
 2233                 break;
 2234             case ASYNC_CONF:
 2235                 aconn = ln.value.aconn;
 2236                 if (hp && aconn)
 2237         {
 2238             aconn->ipnum_family = hp->h_addrtype;
 2239                     memcpy((char *) &aconn->ipnum, hp->h_addr,
 2240                hp->h_length);
 2241         }
 2242                 break;
 2243             default:
 2244                 break;
 2245         }
 2246         if (ioctl(resfd, FIONREAD, &bytes) == -1)
 2247             bytes = 0;
 2248         packets++;
 2249     } while ((bytes > 0) && (packets < 512));
 2250 }
 2251 
 2252 u_long
 2253 memcount_s_bsd(MCs_bsd *mc)
 2254 {
 2255     aListener   *lptr;
 2256 
 2257     mc->file = __FILE__;
 2258 
 2259     for (lptr = listen_list; lptr; lptr = lptr->next)
 2260     {
 2261         mc->listeners.c++;
 2262         mc->listeners.m += sizeof(*lptr);
 2263     }
 2264     mc->total.c += mc->listeners.c;
 2265     mc->total.m += mc->listeners.m;
 2266 
 2267     mc->s_local.c = sizeof(local)/sizeof(local[0]);
 2268     mc->s_local.m = sizeof(local);
 2269 
 2270     mc->s_readbuf.c = 1;
 2271 #ifndef MAXBUFFERS
 2272     mc->s_readbuf.m = sizeof(readbuf);
 2273 #else
 2274     mc->s_readbuf.m = rcvbufmax;
 2275     mc->total.c += mc->s_readbuf.c;
 2276     mc->total.m += mc->s_readbuf.m;
 2277 #endif
 2278 
 2279     return mc->total.m;
 2280 }
 2281