[IRC-Dev CVS] [CVS] Module ircd-ircdev: Change committed
Brought to you by:
zolty
From: Toni G. <zo...@us...> - 2004-11-24 16:03:58
|
CVSROOT : /cvsroot/irc-dev Module : ircd-ircdev Commit time: 2004-11-24 16:03:38 UTC Modified files: ircd/s_auth.c ircd/s_bsd.c ircd/s_conf.c ircd/s_debug.c ircd/s_err.c ircd/s_misc.c ircd/s_numeric.c ircd/s_serv.c ircd/s_stats.c ircd/s_user.c Log message: Author: zoltan <zo...@ir...> Log message: 2004-11-24 Toni García <zo...@ir...> 1.0.alpha13 * Comentarios para Doxygen * Excepciones de Silences * Soporte total de IPv6 * Sincronizacion Undernet ---------------------- diff included ---------------------- Index: ircd-ircdev/ircd/s_auth.c diff -u ircd-ircdev/ircd/s_auth.c:1.4 ircd-ircdev/ircd/s_auth.c:1.5 --- ircd-ircdev/ircd/s_auth.c:1.4 Sun Feb 22 08:11:42 2004 +++ ircd-ircdev/ircd/s_auth.c Wed Nov 24 08:03:18 2004 @@ -19,8 +19,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: s_auth.c,v 1.4 2004/02/22 16:11:42 zolty Exp $ - * + */ +/** @file + * @brief Implementation of DNS and ident lookups. + * @version $Id: s_auth.c,v 1.5 2004/11/24 16:03:18 zolty Exp $ */ #include "config.h" @@ -59,27 +61,27 @@ #include <sys/file.h> #include <sys/ioctl.h> -/* - * a bit different approach - * this replaces the original sendheader macros - */ +/** Array of message text (with length) pairs for AUTH status + * messages. Indexed using #ReportType. */ static struct { const char* message; unsigned int length; } HeaderMessages [] = { - /* 123456789012345678901234567890123456789012345678901234567890 */ - { "NOTICE AUTH :*** Looking up your hostname\r\n", 43 }, - { "NOTICE AUTH :*** Found your hostname\r\n", 38 }, - { "NOTICE AUTH :*** Found your hostname, cached\r\n", 46 }, - { "NOTICE AUTH :*** Couldn't look up your hostname\r\n", 49 }, - { "NOTICE AUTH :*** Checking Ident\r\n", 33 }, - { "NOTICE AUTH :*** Got ident response\r\n", 37 }, - { "NOTICE AUTH :*** No ident response\r\n", 36 }, - { "NOTICE AUTH :*** Your forward and reverse DNS do not match, " \ - "ignoring hostname.\r\n", 80 }, - { "NOTICE AUTH :*** Invalid hostname\r\n", 35 } +#define MSG(STR) { STR, sizeof(STR) - 1 } + MSG("NOTICE AUTH :*** Looking up your hostname\r\n"), + MSG("NOTICE AUTH :*** Found your hostname\r\n"), + MSG("NOTICE AUTH :*** Found your hostname, cached\r\n"), + MSG("NOTICE AUTH :*** Couldn't look up your hostname\r\n"), + MSG("NOTICE AUTH :*** Checking Ident\r\n"), + MSG("NOTICE AUTH :*** Got ident response\r\n"), + MSG("NOTICE AUTH :*** No ident response\r\n"), + MSG("NOTICE AUTH :*** Your forward and reverse DNS do not match, " + "ignoring hostname.\r\n"), + MSG("NOTICE AUTH :*** Invalid hostname\r\n") +#undef MSG }; +/** Enum used to index messages in the HeaderMessages[] array. */ typedef enum { REPORT_DO_DNS, REPORT_FIN_DNS, @@ -92,22 +94,21 @@ REPORT_INVAL_DNS } ReportType; +/** Sends response \a r (from #ReportType) to client \a c. */ #define sendheader(c, r) \ send(cli_fd(c), HeaderMessages[(r)].message, HeaderMessages[(r)].length, 0) -struct AuthRequest* AuthPollList = 0; /* GLOBAL - auth queries pending io */ -static struct AuthRequest* AuthIncompleteList = 0; - static void release_auth_client(struct Client* client); -static void unlink_auth_request(struct AuthRequest* request, - struct AuthRequest** list); void free_auth_request(struct AuthRequest* auth); -/* auth_verify_hostname - verify that a hostname is valid, i.e., only - * contains characters valid for a hostname and that a hostname is not - * too long. +/** Verify that a hostname is valid, i.e., only contains characters + * valid for a hostname and that a hostname is not too long. + * @param host Hostname to check. + * @param maxlen Maximum length of hostname, not including NUL terminator. + * @return Non-zero if the hostname is valid. */ -static int auth_verify_hostname(char *host, int maxlen) +static int +auth_verify_hostname(char *host, int maxlen) { int i; @@ -120,8 +121,9 @@ return 1; /* it's a valid hostname */ } -/* - * auth_timeout - timeout a given auth request +/** Timeout a given auth request. + * @param ev A timer event whose associated data is the expired struct + * AuthRequest. */ static void auth_timeout_callback(struct Event* ev) { @@ -130,7 +132,7 @@ assert(0 != ev_timer(ev)); assert(0 != t_data(ev_timer(ev))); - auth = (struct AuthRequest *)t_data(ev_timer(ev)); + auth = (struct AuthRequest*) t_data(ev_timer(ev)); if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ auth->flags &= ~AM_TIMEOUT; @@ -147,8 +149,9 @@ } } -/* - * auth_sock_callback - called when an event occurs on the socket +/** Handle socket I/O activity. + * @param ev A socket event whos associated data is the active struct + * AuthRequest. */ static void auth_sock_callback(struct Event* ev) { @@ -157,7 +160,7 @@ assert(0 != ev_socket(ev)); assert(0 != s_data(ev_socket(ev))); - auth = (struct AuthRequest *)s_data(ev_socket(ev)); + auth = (struct AuthRequest*) s_data(ev_socket(ev)); switch (ev_type(ev)) { case ET_DESTROY: /* being destroyed */ @@ -185,22 +188,19 @@ break; default: -#ifndef NDEBUG - abort(); /* unrecognized event */ -#endif + assert(0 && "Unrecognized event in auth_socket_callback()."); break; } } -/* - * destroy_auth_request - stop an auth request completely +/** Stop an auth request completely. + * @param auth The struct AuthRequest to cancel. + * @param send_reports If non-zero, report the failure to the user and + * resolver log. */ void destroy_auth_request(struct AuthRequest* auth, int send_reports) { - struct AuthRequest** authList; - if (IsDoingAuth(auth)) { - authList = &AuthPollList; if (-1 < auth->fd) { close(auth->fd); auth->fd = -1; @@ -209,8 +209,7 @@ if (send_reports && IsUserPort(auth->client)) sendheader(auth->client, REPORT_FAIL_ID); - } else - authList = &AuthIncompleteList; + } if (IsDNSPending(auth)) { delete_resolver_queries(auth); @@ -224,12 +223,12 @@ release_auth_client(auth->client); } - unlink_auth_request(auth, authList); free_auth_request(auth); } -/* - * make_auth_request - allocate a new auth request +/** Allocate a new auth request. + * @param client The client being looked up. + * @return The newly allocated auth request. */ static struct AuthRequest* make_auth_request(struct Client* client) { @@ -246,8 +245,8 @@ return auth; } -/* - * free_auth_request - cleanup auth request allocations +/** Clean up auth request allocations (event loop objects, etc). + * @param auth The request to clean up. */ void free_auth_request(struct AuthRequest* auth) { @@ -260,37 +259,10 @@ timer_del(&auth->timeout); } -/* - * unlink_auth_request - remove auth request from a list - */ -static void unlink_auth_request(struct AuthRequest* request, - struct AuthRequest** list) -{ - if (request->next) - request->next->prev = request->prev; - if (request->prev) - request->prev->next = request->next; - else - *list = request->next; -} - -/* - * link_auth_request - add auth request to a list - */ -static void link_auth_request(struct AuthRequest* request, - struct AuthRequest** list) -{ - request->prev = 0; - request->next = *list; - if (*list) - (*list)->prev = request; - *list = request; -} - -/* - * release_auth_client - release auth client from auth system - * this adds the client into the local client lists so it can be read by - * the main io processing loop +/** Release auth client from auth system. This adds the client into + * the local client lists so it can be read by the main io processing + * loop. + * @param client The client to release. */ static void release_auth_client(struct Client* client) { @@ -306,13 +278,14 @@ Debug((DEBUG_INFO, "Auth: release_auth_client %s@%s[%s]", cli_username(client), cli_sockhost(client), cli_sock_ip(client))); } - + +/** Terminate a client's connection due to auth failure. + * @param auth The client to terminate. + */ static void auth_kill_client(struct AuthRequest* auth) { assert(0 != auth); - unlink_auth_request(auth, (IsDoingAuth(auth)) ? &AuthPollList : &AuthIncompleteList); - if (IsDNSPending(auth)) delete_resolver_queries(auth); IPcheck_disconnect(auth->client); @@ -322,18 +295,16 @@ free_auth_request(auth); } -/* - * auth_dns_callback - called when resolver query finishes - * if the query resulted in a successful search, hp will contain - * a non-null pointer, otherwise hp will be null. - * set the client on it's way to a connection completion, regardless - * of success of failure +/** Handle a complete DNS lookup. Send the client on it's way to a + * connection completion, regardless of success or failure -- unless + * there was a mismatch and KILL_IPMISMATCH is set. + * @param vptr The pending struct AuthRequest. + * @param hp Pointer to the DNS reply (or NULL, if lookup failed). */ -static void auth_dns_callback(void* vptr, struct hostent* hp) +static void auth_dns_callback(void* vptr, struct DNSReply* hp) { struct AuthRequest* auth = (struct AuthRequest*) vptr; - - assert(0 != auth); + assert(auth); /* * need to do this here so auth_kill_client doesn't * try have the resolver delete the query it's about @@ -342,30 +313,28 @@ ClearDNSPending(auth); if (hp) { - int i; /* * Verify that the host to ip mapping is correct both ways and that * the ip#(s) for the socket is listed for the host. */ - for (i = 0; hp->h_addr_list[i]; ++i) { - if (0 == memcmp(hp->h_addr_list[i], &(cli_ip(auth->client)), - sizeof(struct in_addr))) - break; - } - if (!hp->h_addr_list[i]) { + if (irc_in_addr_cmp(&hp->addr, &cli_ip(auth->client))) { if (IsUserPort(auth->client)) sendheader(auth->client, REPORT_IP_MISMATCH); sendto_opmask_butone(0, SNO_IPMISMATCH, "IP# Mismatch: %s != %s[%s]", - cli_sock_ip(auth->client), hp->h_name, - ircd_ntoa(hp->h_addr_list[0])); + cli_sock_ip(auth->client), hp->h_name, + ircd_ntoa(&hp->addr)); if (feature_bool(FEAT_KILL_IPMISMATCH)) { auth_kill_client(auth); return; } - } else if (!auth_verify_hostname(hp->h_name, HOSTLEN)) { + } + else if (!auth_verify_hostname(hp->h_name, HOSTLEN)) + { if (IsUserPort(auth->client)) sendheader(auth->client, REPORT_INVAL_DNS); - } else { + } + else + { cli_dns_reply(auth->client) = hp; ircd_strncpy(cli_sockhost(auth->client), hp->h_name, HOSTLEN); if (IsUserPort(auth->client)) @@ -383,13 +352,13 @@ } if (!IsDoingAuth(auth)) { release_auth_client(auth->client); - unlink_auth_request(auth, &AuthIncompleteList); free_auth_request(auth); } } -/* - * authsenderr - handle auth send errors +/** Handle auth send errors. + * @param auth The request that saw the failure. + * @param kill If non-zero, a critical error; close the client's connection. */ static void auth_error(struct AuthRequest* auth, int kill) { @@ -415,66 +384,47 @@ } ClearAuth(auth); - unlink_auth_request(auth, &AuthPollList); - if (IsDNSPending(auth)) - link_auth_request(auth, &AuthIncompleteList); - else { + if (!IsDNSPending(auth)) { release_auth_client(auth->client); free_auth_request(auth); } } -/* - * start_auth_query - Flag the client to show that an attempt to - * contact the ident server on the client's host. The connect and - * subsequently the socket are all put into 'non-blocking' mode. - * Should the connect or any later phase of the identifing process fail, - * it is aborted and the user is given a username of "unknown". +/** Flag the client to show an attempt to contact the ident server on + * the client's host. Should the connect or any later phase of the + * identifing process fail, it is aborted and the user is given a + * username of "unknown". + * @param auth The request for which to start the ident lookup. + * @return Non-zero on success; zero if unable to start the lookup. */ static int start_auth_query(struct AuthRequest* auth) { - struct sockaddr_in remote_addr; - struct sockaddr_in local_addr; + struct irc_sockaddr remote_addr; + struct irc_sockaddr local_addr; int fd; IOResult result; assert(0 != auth); assert(0 != auth->client); - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - ++ServerStats->is_abad; - return 0; - } - if ((MAXCONNECTIONS - 10) < fd) { - close(fd); - return 0; - } - if (!os_set_nonblocking(fd)) { - close(fd); - return 0; - } - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_DO_ID); - /* + /* * get the local address of the client and bind to that to * make the auth request. This used to be done only for * ifdef VIRTTUAL_HOST, but needs to be done for all clients * since the ident request must originate from that same address-- * and machines with multiple IP addresses are common now */ - memset(&local_addr, 0, sizeof(struct sockaddr_in)); + memset(&local_addr, 0, sizeof(local_addr)); os_get_sockname(cli_fd(auth->client), &local_addr); - local_addr.sin_port = htons(0); - - if (bind(fd, (struct sockaddr*) &local_addr, sizeof(struct sockaddr_in))) { - close(fd); + local_addr.port = 0; + fd = os_socket(&local_addr, SOCK_STREAM, "auth query"); + if (fd < 0) return 0; - } - - remote_addr.sin_addr.s_addr = (cli_ip(auth->client)).s_addr; - remote_addr.sin_port = htons(113); - remote_addr.sin_family = AF_INET; + if (IsUserPort(auth->client)) + sendheader(auth->client, REPORT_DO_ID); + memcpy(&remote_addr.addr, &cli_ip(auth->client), sizeof(remote_addr.addr)); + remote_addr.port = 113; if ((result = os_connect_nonb(fd, &remote_addr)) == IO_FAILURE || !socket_add(&auth->socket, auth_sock_callback, (void*) auth, @@ -500,7 +450,7 @@ return 1; } - +/** Enum used to index ident reply fields in a human-readable way. */ enum IdentReplyFields { IDENT_PORT_NUMBERS, IDENT_REPLY_TYPE, @@ -509,6 +459,10 @@ USERID_TOKEN_COUNT }; +/** Parse an ident reply line and extract the userid from it. + * @param reply The ident reply line. + * @return The userid, or NULL on parse failure. + */ static char* check_ident_reply(char* reply) { char* token; @@ -577,11 +531,9 @@ return token; } -/* - * start_auth - starts auth (identd) and dns queries for a client +/** Starts auth (identd) and dns queries for a client. + * @param client The client for which to start queries. */ -enum { LOOPBACK = 127 }; - void start_auth(struct Client* client) { struct AuthRequest* auth = 0; @@ -594,7 +546,7 @@ Debug((DEBUG_INFO, "Beginning auth request on client %p", client)); if (!feature_bool(FEAT_NODNS)) { - if (LOOPBACK == inet_netof(cli_ip(client))) + if (irc_in_addr_is_loopback(&cli_ip(client))) strcpy(cli_sockhost(client), cli_name(&me)); else { struct DNSQuery query; @@ -605,7 +557,7 @@ if (IsUserPort(auth->client)) sendheader(client, REPORT_DO_DNS); - gethost_byaddr((const char*) &(cli_ip(client)), &query); + gethost_byaddr(&cli_ip(client), &query); SetDNSPending(auth); } } @@ -613,11 +565,9 @@ if (start_auth_query(auth)) { Debug((DEBUG_LIST, "identd query for %p initiated successfully", auth->client)); - link_auth_request(auth, &AuthPollList); } else if (IsDNSPending(auth)) { Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " "waiting on DNS", auth->client)); - link_auth_request(auth, &AuthIncompleteList); } else { Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " "no DNS pending; releasing immediately", auth->client)); @@ -626,17 +576,17 @@ } } -/* - * send_auth_query - send the ident server a query giving "theirport , ourport" - * The write is only attempted *once* so it is deemed to be a fail if the +/** Send the ident server a query giving "theirport , ourport". The + * write is only attempted *once* so it is deemed to be a fail if the * entire write doesn't write all the data given. This shouldnt be a - * problem since the socket should have a write buffer far greater than - * this message to store it in should problems arise. -avalon + * problem since the socket should have a write buffer far greater + * than this message to store it in should problems arise. -avalon + * @param auth The request to send. */ void send_auth_query(struct AuthRequest* auth) { - struct sockaddr_in us; - struct sockaddr_in them; + struct irc_sockaddr us; + struct irc_sockaddr them; char authbuf[32]; unsigned int count; @@ -649,8 +599,8 @@ return; } ircd_snprintf(0, authbuf, sizeof(authbuf), "%u , %u\r\n", - (unsigned int) ntohs(them.sin_port), - (unsigned int) ntohs(us.sin_port)); + (unsigned int) them.port, + (unsigned int) us.port); if (IO_SUCCESS == os_send_nonb(auth->fd, authbuf, strlen(authbuf), &count)) { ClearAuthConnect(auth); @@ -661,11 +611,10 @@ } -/* - * read_auth_reply - read the reply (if any) from the ident server - * we connected to. - * We only give it one shot, if the reply isn't good the first time - * fail the authentication entirely. --Bleep +/** Read the reply (if any) from the ident server we connected to. We + * only give it one shot, if the reply isn't good the first time fail + * the authentication entirely. --Bleep + * @param auth The request to read. */ void read_auth_reply(struct AuthRequest* auth) { @@ -692,7 +641,7 @@ Debug((DEBUG_LIST, "Deleting auth [%p] socket %p", auth, &auth->socket)); socket_del(&auth->socket); ClearAuth(auth); - + if (!EmptyString(username)) { ircd_strncpy(cli_username(auth->client), username, USERLEN); /* @@ -707,11 +656,8 @@ else { ++ServerStats->is_abad; } - unlink_auth_request(auth, &AuthPollList); - if (IsDNSPending(auth)) - link_auth_request(auth, &AuthIncompleteList); - else { + if (!IsDNSPending(auth)) { release_auth_client(auth->client); free_auth_request(auth); } Index: ircd-ircdev/ircd/s_bsd.c diff -u ircd-ircdev/ircd/s_bsd.c:1.5 ircd-ircdev/ircd/s_bsd.c:1.6 --- ircd-ircdev/ircd/s_bsd.c:1.5 Wed Nov 17 03:45:50 2004 +++ ircd-ircdev/ircd/s_bsd.c Wed Nov 24 08:03:28 2004 @@ -18,8 +18,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: s_bsd.c,v 1.5 2004/11/17 11:45:50 zolty Exp $ - * + */ +/** @file + * @brief Functions that now (or in the past) relied on BSD APIs. + * @version $Id: s_bsd.c,v 1.6 2004/11/24 16:03:28 zolty Exp $ */ #include "config.h" @@ -54,18 +56,15 @@ #include "s_user.h" #include "send.h" #include "struct.h" -#include "support.h" #include "sys.h" #include "uping.h" #include "version.h" #include <arpa/inet.h> -#include <arpa/nameser.h> #include <assert.h> #include <errno.h> #include <fcntl.h> #include <netdb.h> -#include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -79,13 +78,13 @@ #include <sys/poll.h> #endif /* USE_POLL */ -#ifndef INADDR_NONE -#define INADDR_NONE 0xffffffff -#endif - +/** Array of my own clients, indexed by file descriptor. */ struct Client* LocalClientArray[MAXCONNECTIONS]; +/** Maximum file descriptor in current use. */ int HighestFd = -1; -struct sockaddr_in VirtualHost; +/** Default local address for outbound connections. */ +struct irc_sockaddr VirtualHost; +/** Temporary buffer for reading data from a peer. */ static char readbuf[SERVER_TCP_WINDOW]; /* @@ -135,19 +134,14 @@ * been reassigned to a normal connection... */ -/* - * report_error - * - * This a replacement for perror(). Record error to log and - * also send a copy to all *LOCAL* opers online. - * - * text is a *format* string for outputting error. It must - * contain only two '%s', the first will be replaced - * by the sockhost from the cptr, and the latter will - * be taken from sys_errlist[errno]. - * - * cptr if not NULL, is the *LOCAL* client associated with - * the error. +/** Replacement for perror(). Record error to log. Send a copy to all + * *LOCAL* opers, but only if no errors were sent to them in the last + * 20 seconds. + * @param text A *format* string for outputting error. It must contain + * only two '%s', the first will be replaced by the sockhost from the + * cptr, and the latter will be taken from sys_errlist[errno]. + * @param who The client associated with the error. + * @param err The errno value to display. */ void report_error(const char* text, const char* who, int err) { @@ -173,19 +167,19 @@ } -/* - * connect_dns_callback - called when resolver query finishes - * if the query resulted in a successful search, reply will contain - * a non-null pointer, otherwise reply will be null. - * if successful start the connection, otherwise notify opers +/** Called when resolver query finishes. If the DNS lookup was + * successful, start the connection; otherwise notify opers of the + * failure. + * @param vptr The struct ConfItem representing the Connect block. + * @param hp A pointer to the DNS lookup results (NULL on failure). */ -static void connect_dns_callback(void* vptr, struct hostent* hp) +static void connect_dns_callback(void* vptr, struct DNSReply* hp) { struct ConfItem* aconf = (struct ConfItem*) vptr; assert(aconf); aconf->dns_pending = 0; if (hp) { - memcpy(&aconf->ipnum, hp->h_addr, sizeof(struct in_addr)); + memcpy(&aconf->address, &hp->addr, sizeof(aconf->address)); MyFree(hp); connect_server(aconf, 0); } @@ -194,9 +188,8 @@ aconf->name); } -/* - * close_connections - closes all connections - * close stderr if specified +/** Closes all file descriptors. + * @param close_stderr If non-zero, also close stderr. */ void close_connections(int close_stderr) { @@ -209,9 +202,7 @@ close(i); } -/* - * init_connection_limits - initialize process fd limit to - * MAXCONNECTIONS +/** Initialize process fd limit to MAXCONNECTIONS. */ int init_connection_limits(void) { @@ -229,12 +220,14 @@ return 0; } -/* - * connect_inet - set up address and port and make a connection +/** Set up address and port and make a connection. + * @param aconf Provides the connection information. + * @param cptr Client structure for the peer. + * @return Non-zero on success; zero on failure. */ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) { - static struct sockaddr_in sin, *locaddr = 0; + const struct irc_sockaddr *local; IOResult result; assert(0 != aconf); assert(0 != cptr); @@ -242,61 +235,19 @@ * Might as well get sockhost from here, the connection is attempted * with it so if it fails its useless. */ - cli_fd(cptr) = socket(AF_INET, SOCK_STREAM, 0); - if (-1 == cli_fd(cptr)) { - cli_error(cptr) = errno; - report_error(SOCKET_ERROR_MSG, cli_name(cptr), errno); - return 0; - } - if (cli_fd(cptr) >= MAXCLIENTS) { - report_error(CONNLIMIT_ERROR_MSG, cli_name(cptr), 0); - close(cli_fd(cptr)); - cli_fd(cptr) = -1; - return 0; - } - /* - * Bind to a local IP# (with unknown port - let unix decide) so - * we have some chance of knowing the IP# that gets used for a host - * with more than one IP#. - * - * No we don't bind it, not all OS's can handle connecting with - * an already bound socket, different ip# might occur anyway - * leading to a freezing select() on this side for some time. - * I had this on my Linux 1.1.88 --Run - */ - - /* - * No, we do bind it if we have virtual host support. If we don't - * explicitly bind it, it will default to IN_ADDR_ANY and we lose - * due to the other server not allowing our base IP --smg - */ - if (aconf->origin.s_addr != INADDR_NONE) { - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = aconf->origin.s_addr; - locaddr = &sin; - } else if (feature_bool(FEAT_VIRTUAL_HOST)) - locaddr = &VirtualHost; - - if (locaddr && - bind(cli_fd(cptr), (struct sockaddr*) locaddr, - sizeof(struct sockaddr_in))) { - report_error(BIND_ERROR_MSG, cli_name(cptr), errno); - close(cli_fd(cptr)); - cli_fd(cptr) = -1; + if (irc_in_addr_valid(&aconf->origin.addr)) + local = &aconf->origin; + else + local = &VirtualHost; + cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr)); + if (cli_fd(cptr) < 0) return 0; - } - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = aconf->ipnum.s_addr; - sin.sin_port = htons(aconf->port); /* * save connection info in client */ - (cli_ip(cptr)).s_addr = aconf->ipnum.s_addr; - cli_port(cptr) = aconf->port; - ircd_ntoa_r(cli_sock_ip(cptr), (const char*) &(cli_ip(cptr))); + memcpy(&cli_ip(cptr), &aconf->address.addr, sizeof(cli_ip(cptr))); + ircd_ntoa_r(cli_sock_ip(cptr), &cli_ip(cptr)); /* * we want a big buffer for server connections */ @@ -307,17 +258,7 @@ cli_fd(cptr) = -1; return 0; } - /* - * ALWAYS set sockets non-blocking - */ - if (!os_set_nonblocking(cli_fd(cptr))) { - cli_error(cptr) = errno; - report_error(NONB_ERROR_MSG, cli_name(cptr), errno); - close(cli_fd(cptr)); - cli_fd(cptr) = -1; - return 0; - } - if ((result = os_connect_nonb(cli_fd(cptr), &sin)) == IO_FAILURE) { + if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) { cli_error(cptr) = errno; report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno); close(cli_fd(cptr)); @@ -338,28 +279,13 @@ return 1; } -/* - * deliver_it - * Attempt to send a sequence of bytes to the connection. - * Returns - * - * < 0 Some fatal error occurred, (but not EWOULDBLOCK). - * This return is a request to close the socket and - * clean up the link. - * - * >= 0 No real error occurred, returns the number of - * bytes actually transferred. EWOULDBLOCK and other - * possibly similar conditions should be mapped to - * zero return. Upper level routine will have to - * decide what to do with those unwritten bytes... - * - * *NOTE* alarm calls have been preserved, so this should - * work equally well whether blocking or non-blocking - * mode is used... - * - * We don't use blocking anymore, that is impossible with the - * net.loads today anyway. Commented out the alarms to save cpu. - * --Run +/** Attempt to send a sequence of bytes to the connection. + * As a side effect, updates \a cptr's FLAG_BLOCKED setting + * and sendB/sendK fields. + * @param cptr Client that should receive data. + * @param buf Message buffer to send to client. + * @return Negative on connection-fatal error; otherwise + * number of bytes sent. */ unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf) { @@ -373,18 +299,7 @@ cli_sendB(cptr) += bytes_written; cli_sendB(&me) += bytes_written; - if (cli_sendB(cptr) > 1023) { - cli_sendK(cptr) += (cli_sendB(cptr) >> 10); - cli_sendB(cptr) &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */ - } - if (cli_sendB(&me) > 1023) { - cli_sendK(&me) += (cli_sendB(&me) >> 10); - cli_sendB(&me) &= 0x03ff; - } - /* - * XXX - hrmm.. set blocked here? the socket didn't - * say it was blocked - */ + /* A partial write implies that future writes will block. */ if (bytes_written < bytes_count) SetFlag(cptr, FLAG_BLOCKED); break; @@ -399,26 +314,25 @@ return bytes_written; } - +/** Free the client's DNS reply, if any. + * @param cptr Client to operate on. + */ void release_dns_reply(struct Client* cptr) { assert(0 != cptr); assert(MyConnect(cptr)); if (cli_dns_reply(cptr)) { + MyFree(cli_dns_reply(cptr)->h_name); MyFree(cli_dns_reply(cptr)); cli_dns_reply(cptr) = 0; } } -/* - * completed_connection - * - * Complete non-blocking connect()-sequence. Check access and +/** Complete non-blocking connect()-sequence. Check access and * terminate connection, if trouble detected. - * - * Return TRUE, if successfully completed - * FALSE, if failed and ClientExit + * @param cptr Client to which we have connected, with all Confitem structs attached. + * @return Zero on failure (caller should exit_client()), non-zero on success. */ static int completed_connection(struct Client* cptr) { @@ -480,11 +394,9 @@ return (IsDead(cptr)) ? 0 : 1; } -/* - * close_connection - * - * Close the physical connection. This function must make - * MyConnect(cptr) == FALSE, and set cptr->from == NULL. +/** Close the physical connection. Side effects: MyConnect(cptr) + * becomes false and cptr->from becomes NULL. + * @param cptr Client to disconnect. */ void close_connection(struct Client *cptr) { @@ -494,22 +406,12 @@ ServerStats->is_sv++; ServerStats->is_sbs += cli_sendB(cptr); ServerStats->is_sbr += cli_receiveB(cptr); - ServerStats->is_sks += cli_sendK(cptr); - ServerStats->is_skr += cli_receiveK(cptr); ServerStats->is_sti += CurrentTime - cli_firsttime(cptr); - if (ServerStats->is_sbs > 1023) { - ServerStats->is_sks += (ServerStats->is_sbs >> 10); - ServerStats->is_sbs &= 0x3ff; - } - if (ServerStats->is_sbr > 1023) { - ServerStats->is_skr += (ServerStats->is_sbr >> 10); - ServerStats->is_sbr &= 0x3ff; - } /* * If the connection has been up for a long amount of time, schedule * a 'quick' reconnect, else reset the next-connect cycle. */ - if ((aconf = find_conf_exact(cli_name(cptr), 0, cli_sockhost(cptr), CONF_SERVER))) { + if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) { /* * Reschedule a faster reconnect, if this was a automaticly * connected configuration entry. (Note that if we have had @@ -528,17 +430,7 @@ ServerStats->is_cl++; ServerStats->is_cbs += cli_sendB(cptr); ServerStats->is_cbr += cli_receiveB(cptr); - ServerStats->is_cks += cli_sendK(cptr); - ServerStats->is_ckr += cli_receiveK(cptr); ServerStats->is_cti += CurrentTime - cli_firsttime(cptr); - if (ServerStats->is_cbs > 1023) { - ServerStats->is_cks += (ServerStats->is_cbs >> 10); - ServerStats->is_cbs &= 0x3ff; - } - if (ServerStats->is_cbr > 1023) { - ServerStats->is_ckr += (ServerStats->is_cbr >> 10); - ServerStats->is_cbr &= 0x3ff; - } } else ServerStats->is_ni++; @@ -571,6 +463,10 @@ } } +/** Close all unregistered connections. + * @param source Oper who requested the close. + * @return Number of closed connections. + */ int net_close_unregistered_connections(struct Client* source) { int i; @@ -588,16 +484,15 @@ return count; } -/*---------------------------------------------------------------------------- - * add_connection - * - * Creates a client which has just connected to us on the given fd. +/** Creates a client which has just connected to us on the given fd. * The sockhost field is initialized with the ip# of the host. * The client is not added to the linked list of clients, it is * passed off to the auth handler for dns and ident queries. - *--------------------------------------------------------------------------*/ + * @param listener Listening socket that received the connection. + * @param fd File descriptor of new connection. + */ void add_connection(struct Listener* listener, int fd) { - struct sockaddr_in addr; + struct irc_sockaddr addr; struct Client *new_client; time_t next_target = 0; @@ -606,14 +501,13 @@ /* 12345678901234567890123456789012345679012345678901234567890123456 */ const char* const register_message = "ERROR :Unable to complete your registration\r\n"; - + assert(0 != listener); - /* * Removed preliminary access check. Full check is performed in m_server and * m_user instead. Also connection time out help to get rid of unwanted - * connections. + * connections. */ if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) { ++ServerStats->is_ref; @@ -636,25 +530,25 @@ * * If they're throttled, murder them, but tell them why first. */ - if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server) { + if (!IPcheck_local_connect(&addr.addr, &next_target) && !listener->server) + { ++ServerStats->is_ref; - write(fd, throttle_message, strlen(throttle_message)); - close(fd); - return; + write(fd, throttle_message, strlen(throttle_message)); + close(fd); + return; } - new_client = make_client(0, ((listener->server) ? + new_client = make_client(0, ((listener->server) ? STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER)); /* * Copy ascii address to 'sockhost' just in case. Then we have something - * valid to put into error messages... + * valid to put into error messages... */ SetIPChecked(new_client); - ircd_ntoa_r(cli_sock_ip(new_client), (const char*) &addr.sin_addr); + ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr); strcpy(cli_sockhost(new_client), cli_sock_ip(new_client)); - (cli_ip(new_client)).s_addr = addr.sin_addr.s_addr; - cli_port(new_client) = ntohs(addr.sin_port); + memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client))); if (next_target) cli_nexttarget(new_client) = next_target; @@ -677,11 +571,9 @@ start_auth(new_client); } -/* - * update_write - * - * Determines whether to tell the events engine we're interested in - * writable events +/** Determines whether to tell the events engine we're interested in + * writable events. + * @param cptr Client for which to decide this. */ void update_write(struct Client* cptr) { @@ -695,16 +587,16 @@ SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE); } -/* - * read_packet - * - * Read a 'packet' of data from a connection and process it. Read in 8k - * chunks to give a better performance rating (for server connections). - * Do some tricky stuff for client connections to make sure they don't do - * any flooding >:-) -avalon +/** Read a 'packet' of data from a connection and process it. Read in + * 8k chunks to give a better performance rating (for server + * connections). Do some tricky stuff for client connections to make + * sure they don't do any flooding >:-) -avalon + * @param cptr Client from which to read data. + * @param socket_ready If non-zero, more data can be read from the client's socket. + * @return Positive number on success, zero on connection-fatal failure, negative + * if user is killed. */ -static int -read_packet(struct Client *cptr, int socket_ready) +static int read_packet(struct Client *cptr, int socket_ready) { unsigned int dolen = 0; unsigned int length = 0; @@ -714,7 +606,8 @@ DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))) { switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) { case IO_SUCCESS: - if (length) { + if (length) + { if (!IsServer(cptr)) cli_lasttime(cptr) = CurrentTime; if (cli_lasttime(cptr) > cli_since(cptr)) @@ -814,18 +707,10 @@ return 1; } -/* - * connect_server - start or complete a connection to another server - * returns true (1) if successful, false (0) otherwise - * - * aconf must point to a valid C:line - * m_connect calls this with a valid by client and a null reply - * try_connections calls this with a null by client, and a null reply - * connect_dns_callback call this with a null by client, and a valid reply - * - * XXX - if this comes from an m_connect message and a dns query needs to - * be done, we loose the information about who started the connection and - * it's considered an auto connect. +/** Start a connection to another server. + * @param aconf Connect block data for target server. + * @param by Client who requested the connection (if any). + * @return Non-zero on success; zero on failure. */ int connect_server(struct ConfItem* aconf, struct Client* by) { @@ -838,7 +723,7 @@ return 0; } Debug((DEBUG_NOTICE, "Connect to %s[@%s]", aconf->name, - ircd_ntoa((const char*) &aconf->ipnum))); + ircd_ntoa(&aconf->address.addr))); if ((cptr = FindClient(aconf->name))) { if (IsServer(cptr) || IsMe(cptr)) { @@ -859,22 +744,21 @@ } } /* - * If we dont know the IP# for this host and itis a hostname and + * If we dont know the IP# for this host and it is a hostname and * not a ip# string, then try and find the appropriate host record. */ - if (INADDR_NONE == aconf->ipnum.s_addr) { - if (INADDR_NONE == (aconf->ipnum.s_addr = inet_addr(aconf->host))) { - char buf[HOSTLEN + 1]; - struct DNSQuery query; - - query.vptr = aconf; - query.callback = connect_dns_callback; - host_from_uh(buf, aconf->host, HOSTLEN); - buf[HOSTLEN] = '\0'; + if (!irc_in_addr_valid(&aconf->address.addr) + && !ircd_aton(&aconf->address.addr, aconf->host)) { + char buf[HOSTLEN + 1]; + struct DNSQuery query; + + query.vptr = aconf; + query.callback = connect_dns_callback; + host_from_uh(buf, aconf->host, HOSTLEN); + buf[HOSTLEN] = '\0'; - gethost_byname(buf, &query); - aconf->dns_pending = 1; - } + gethost_byname(buf, &query); + aconf->dns_pending = 1; return 0; } cptr = make_client(NULL, STAT_UNKNOWN_SERVER); @@ -939,7 +823,6 @@ if (cli_fd(cptr) > HighestFd) HighestFd = cli_fd(cptr); - LocalClientArray[cli_fd(cptr)] = cptr; Count_newunknown(UserStats); @@ -955,18 +838,7 @@ completed_connection(cptr) : 1; } -/* - * Setup local socket structure to use for binding to. - */ -void set_virtual_host(struct in_addr addr) -{ - memset(&VirtualHost, 0, sizeof(VirtualHost)); - VirtualHost.sin_family = AF_INET; - VirtualHost.sin_addr.s_addr = addr.s_addr; -} - -/* - * Find the real hostname for the host running the server (or one which +/** Find the real hostname for the host running the server (or one which * matches the server's name) and its primary IP#. Hostname is stored * in the client structure passed as a pointer. */ @@ -979,8 +851,9 @@ SetYXXServerName(&me, conf->numeric); } -/* - * Process events on a client socket +/** Process events on a client socket. + * @param ev Socket event structure that has a struct Connection as + * its associated data. */ static void client_sock_callback(struct Event* ev) { @@ -992,7 +865,7 @@ assert(0 != ev_socket(ev)); assert(0 != s_data(ev_socket(ev))); - con = (struct Connection *)s_data(ev_socket(ev)); + con = (struct Connection*) s_data(ev_socket(ev)); assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY); @@ -1038,7 +911,7 @@ case ET_WRITE: /* socket is writable */ ClrFlag(cptr, FLAG_BLOCKED); if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048) - list_next_channels(cptr, 64); + list_next_channels(cptr); Debug((DEBUG_SEND, "Sending queued data to %C", cptr)); send_queued(cptr); break; @@ -1052,9 +925,7 @@ break; default: -#ifndef NDEBUG - abort(); /* unrecognized event */ -#endif + assert(0 && "Unrecognized socket event in client_sock_callback()"); break; } @@ -1068,8 +939,9 @@ } } -/* - * Process a timer on client socket +/** Process a timer on client socket. + * @param ev Timer event that has a struct Connection as its + * associated data. */ static void client_timer_callback(struct Event* ev) { @@ -1080,7 +952,7 @@ assert(0 != t_data(ev_timer(ev))); assert(ET_DESTROY == ev_type(ev) || ET_EXPIRE == ev_type(ev)); - con = (struct Connection *)t_data(ev_timer(ev)); + con = (struct Connection*) t_data(ev_timer(ev)); assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY); Index: ircd-ircdev/ircd/s_conf.c diff -u ircd-ircdev/ircd/s_conf.c:1.6 ircd-ircdev/ircd/s_conf.c:1.7 --- ircd-ircdev/ircd/s_conf.c:1.6 Wed Nov 17 03:45:50 2004 +++ ircd-ircdev/ircd/s_conf.c Wed Nov 24 08:03:28 2004 @@ -18,8 +18,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: s_conf.c,v 1.6 2004/11/17 11:45:50 zolty Exp $ - * + */ +/** @file + * @brief ircd configuration file driver + * @version $Id: s_conf.c,v 1.7 2004/11/24 16:03:28 zolty Exp $ */ #include "config.h" @@ -34,6 +36,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_auth.h" #include "ircd_chattr.h" #include "ircd_log.h" #include "ircd_reply.h" @@ -53,7 +56,6 @@ #include "s_misc.h" #include "send.h" #include "struct.h" -#include "support.h" #include "sys.h" #include <assert.h> @@ -67,27 +69,28 @@ #include <sys/stat.h> #include <unistd.h> -#ifndef INADDR_NONE -#define INADDR_NONE 0xffffffff -#endif - -struct ConfItem* GlobalConfList = 0; -int GlobalConfCount = 0; -struct s_map *GlobalServiceMapList = 0; -struct qline *GlobalQuarantineList = 0; +/** Global list of all ConfItem structures. */ +struct ConfItem *GlobalConfList; +/** Count of items in #GlobalConfList. */ +int GlobalConfCount; +/** Global list of service mappings. */ +struct s_map *GlobalServiceMapList; +/** Global list of channel quarantines. */ +struct qline *GlobalQuarantineList; -void yyparse(void); -int conf_fd, lineno; +/** Current line number in scanner input. */ +int lineno; +/** Configuration information for #me. */ struct LocalConf localConf; +/** Global list of connection rules. */ struct CRuleConf* cruleConfList; -/* struct ServerConf* serverConfList; */ +/** Global list of K-lines. */ struct DenyConf* denyConfList; -/* - * output the reason for being k lined from a file - Mmmm - * sptr is client being dumped - * filename is the file that is to be output to the K lined client +/** Tell a user that they are banned, dumping the message from a file. + * @param sptr Client being rejected + * @param filename Send this file's contents to \a sptr */ static void killcomment(struct Client* sptr, const char* filename) { @@ -120,7 +123,10 @@ fbclose(file); } -struct ConfItem* make_conf(void) +/** Allocate a new struct ConfItem and link it to #GlobalConfList. + * @return Newly allocated structure. + */ +struct ConfItem* make_conf(int type) { struct ConfItem* aconf; @@ -130,31 +136,21 @@ ++GlobalConfCount; #endif memset(aconf, 0, sizeof(struct ConfItem)); - aconf->status = CONF_ILLEGAL; - aconf->ipnum.s_addr = INADDR_NONE; + aconf->status = type; + aconf->next = GlobalConfList; + GlobalConfList = aconf; return aconf; } -void delist_conf(struct ConfItem *aconf) -{ - if (aconf == GlobalConfList) - GlobalConfList = GlobalConfList->next; - else { - struct ConfItem *bconf; - - for (bconf = GlobalConfList; aconf != bconf->next; bconf = bconf->next) - ; - bconf->next = aconf->next; - } - aconf->next = 0; -} - +/** Free a struct ConfItem and any resources it owns. + * @param aconf Item to free. + */ void free_conf(struct ConfItem *aconf) { Debug((DEBUG_DEBUG, "free_conf: %s %s %d", aconf->host ? aconf->host : "*", aconf->name ? aconf->name : "*", - aconf->port)); + aconf->address.port)); if (aconf->dns_pending) delete_resolver_queries(aconf); MyFree(aconf->host); @@ -168,8 +164,9 @@ #endif } -/* - * detach_conf - Disassociate configuration from the client. +/** Disassociate configuration from the client. + * @param cptr Client to operate on. + * @param aconf ConfItem to detach. */ static void detach_conf(struct Client* cptr, struct ConfItem* aconf) { @@ -199,28 +196,57 @@ } } -/* - * conf_dns_callback - called when resolver query finishes - * if the query resulted in a successful search, hp will contain - * a non-null pointer, otherwise hp will be null. - * if successful save hp in the conf item it was called with +/** Parse a user\@host mask into username and host or IP parts. + * If \a host contains no username part, set \a aconf->username to + * NULL. If the host part of \a host looks like an IP mask, set \a + * aconf->addrbits and \a aconf->address to match. Otherwise, set + * \a aconf->host, and set \a aconf->addrbits to -1. + * @param[in,out] aconf Configuration item to set. + * @param[in] host user\@host mask to parse. */ -static void conf_dns_callback(void* vptr, struct hostent* hp) +void conf_parse_userhost(struct ConfItem *aconf, char *host) +{ + char *host_part; + unsigned char addrbits; + + MyFree(aconf->username); + MyFree(aconf->host); + host_part = strchr(host, '@'); + if (host_part) { + *host_part = '\0'; + DupString(aconf->username, host); + host_part++; + } else { + aconf->username = NULL; + host_part = host; + } + DupString(aconf->host, host_part); + if (ipmask_parse(aconf->host, &aconf->address.addr, &addrbits)) + aconf->addrbits = addrbits; + else + aconf->addrbits = -1; + MyFree(host); +} + +/** Copies a completed DNS query into its ConfItem. + * @param vptr Pointer to struct ConfItem for the block. + * @param hp DNS reply, or NULL if the lookup failed. + */ +static void conf_dns_callback(void* vptr, struct DNSReply* hp) { struct ConfItem* aconf = (struct ConfItem*) vptr; assert(aconf); aconf->dns_pending = 0; if (hp) { - memcpy(&aconf->ipnum, hp->h_addr, sizeof(struct in_addr)); + memcpy(&aconf->address.addr, &hp->addr, sizeof(aconf->address.addr)); MyFree(hp); } } -/* - * conf_dns_lookup - do a nameserver lookup of the conf host - * if the conf entry is currently doing a ns lookup do nothing, otherwise - * if the lookup returns a null pointer, set the conf dns_pending flag +/** Start a nameserver lookup of the conf host. If the conf entry is + * currently doing a lookup, do nothing. + * @param aconf ConfItem for which to start a request. */ static void conf_dns_lookup(struct ConfItem* aconf) { @@ -238,56 +264,41 @@ } -/* - * lookup_confhost - * - * Do (start) DNS lookups of all hostnames in the conf line and convert - * an IP addresses in a.b.c.d number for to IP#s. +/** Start lookups of all addresses in the conf line. The origin must + * be a numeric IP address. If the remote host field is not an IP + * address, start a DNS lookup for it. + * @param aconf Connection to do lookups for. */ -void lookup_confhost(struct ConfItem *aconf) +void +lookup_confhost(struct ConfItem *aconf) { - char *tmp, *tmp2; - if (EmptyString(aconf->host) || EmptyString(aconf->name)) { Debug((DEBUG_ERROR, "Host/server name error: (%s) (%s)", aconf->host, aconf->name)); return; } + if (aconf->origin_name + && !ircd_aton(&aconf->origin.addr, aconf->origin_name)) { + Debug((DEBUG_ERROR, "Origin name error: (%s) (%s)", + aconf->origin_name, aconf->name)); + } /* * Do name lookup now on hostnames given and store the * ip numbers in conf structure. */ - if ((tmp = strchr(aconf->host, '/'))) { - *(tmp++) = '\0'; - aconf->origin.s_addr = inet_addr(aconf->host); - tmp2 = aconf->host; - DupString(aconf->host, tmp); - free(tmp2); - } else - aconf->origin.s_addr = INADDR_NONE; - - if (IsDigit(*aconf->host)) { - /* - * rfc 1035 sez host names may not start with a digit - * XXX - this has changed code needs to be updated - */ - aconf->ipnum.s_addr = inet_addr(aconf->host); - if (INADDR_NONE == aconf->ipnum.s_addr) { + if (IsIP6Char(*aconf->host)) { + if (!ircd_aton(&aconf->address.addr, aconf->host)) { Debug((DEBUG_ERROR, "Host/server name error: (%s) (%s)", - aconf->host, aconf->name)); + aconf->host, aconf->name)); } } else conf_dns_lookup(aconf); } -/* - * conf_find_server - find a server by name or hostname - * returns a server conf item pointer if found, 0 otherwise - * - * NOTE: at some point when we don't have to scan the entire - * list it may be cheaper to look for server names and host - * names in separate loops (original code did it that way) +/** Find a server by name or hostname. + * @param name Server name to find. + * @return Pointer to the corresponding ConfItem, or NULL if none exists. */ struct ConfItem* conf_find_server(const char* name) { @@ -308,14 +319,10 @@ return 0; } -/* - * conf_eval_crule - evaluate connection rules - * returns the name of the rule triggered if found, 0 otherwise - * - * Evaluate connection rules... If no rules found, allow the - * connect. Otherwise stop with the first true rule (ie: rules - * are ored together. Oper connects are effected only by D - * lines (CRULE_ALL) not d lines (CRULE_AUTO). +/** Evaluate connection rules. + * @param name Name of server to check + * @param mask Filter for CRule types (only consider if type & \a mask != 0). + * @return Name of rule that forbids the connection; NULL if no prohibitions. */ const char* conf_eval_crule(const char* name, int mask) { @@ -331,9 +338,10 @@ return 0; } -/* - * Remove all conf entries from the client except those which match +/** Remove all conf entries from the client except those which match * the status field mask. + * @param cptr Client to operate on. + * @param mask ConfItem types to keep. */ void det_confs_butmask(struct Client* cptr, int mask) { @@ -348,96 +356,62 @@ } } -/* - * check_limit_and_attach - check client limits and attach I:line - * - * Made it accept 1 charactor, and 2 charactor limits (0->99 now), - * and dislallow more than 255 people here as well as in ipcheck. - * removed the old "ONE" scheme too. - * -- Isomer 2000-06-22 +/** Check client limits and attach Client block. + * If there are more connections from the IP than \a aconf->maximum + * allows, return ACR_TOO_MANY_FROM_IP. Otherwise, attach \a aconf to + * \a cptr. + * @param cptr Client getting \a aconf. + * @param aconf Configuration item to attach. + * @return Authorization check result. */ static enum AuthorizationCheckResult check_limit_and_attach(struct Client* cptr, struct ConfItem* aconf) { - int number = 255; - - if (aconf->passwd) { - if (IsDigit(*aconf->passwd) && !aconf->passwd[1]) - number = *aconf->passwd-'0'; - else if (IsDigit(*aconf->passwd) && IsDigit(aconf->passwd[1]) && - !aconf->passwd[2]) - number = (*aconf->passwd-'0')*10+(aconf->passwd[1]-'0'); - } - if (IPcheck_nr(cptr) > number) + if (IPcheck_nr(cptr) > aconf->maximum) return ACR_TOO_MANY_FROM_IP; return attach_conf(cptr, aconf); } -/* - * Find the first (best) I line to attach. +/** Find the first (best) Client block to attach. + * @param cptr Client for whom to check rules. + * @return Authorization check result. */ -enum AuthorizationCheckResult attach_iline(struct Client* cptr) +enum AuthorizationCheckResult attach_iline(struct Client* cptr) { struct ConfItem* aconf; - const char* hname; - int i; - static char uhost[HOSTLEN + USERLEN + 3]; - static char fullname[HOSTLEN + 1]; - struct hostent* hp = 0; + struct DNSReply* hp; assert(0 != cptr); - if (cli_dns_reply(cptr)) - hp = cli_dns_reply(cptr); - + hp = cli_dns_reply(cptr); for (aconf = GlobalConfList; aconf; aconf = aconf->next) { - if (aconf->status != CONF_CLIENT) - continue; - if (aconf->port && aconf->port != cli_listener(cptr)->port) + if (aconf->status != CONF_CLIENT || !aconf->host) continue; - if (!aconf->host || !aconf->name) + if (aconf->address.port && aconf->address.port != cli_listener(cptr)->addr.port) continue; - if (hp) { - for (i = 0, hname = hp->h_name; hname; hname = hp->h_aliases[i++]) { - ircd_strncpy(fullname, hname, HOSTLEN); - fullname[HOSTLEN] = '\0'; - - Debug((DEBUG_DNS, "a_il: %s->%s", cli_sockhost(cptr), fullname)); - - if (strchr(aconf->name, '@')) { - strcpy(uhost, cli_username(cptr)); - strcat(uhost, "@"); - } - else - *uhost = '\0'; - strncat(uhost, fullname, sizeof(uhost) - 1 - strlen(uhost)); - uhost[sizeof(uhost) - 1] = 0; - if (0 == match(aconf->name, uhost)) { - if (strchr(uhost, '@')) - SetFlag(cptr, FLAG_DOID); - return check_limit_and_attach(cptr, aconf); - } - } - } - if (strchr(aconf->host, '@')) { - ircd_strncpy(uhost, cli_username(cptr), sizeof(uhost) - 2); - uhost[sizeof(uhost) - 2] = 0; - strcat(uhost, "@"); - } - else - *uhost = '\0'; - strncat(uhost, cli_sock_ip(cptr), sizeof(uhost) - 1 - strlen(uhost)); - uhost[sizeof(uhost) - 1] = 0; - if (match(aconf->host, uhost)) - continue; - if (strchr(uhost, '@')) + if (aconf->username) { SetFlag(cptr, FLAG_DOID); - - return check_limit_and_attach(cptr, aconf); + if (match(aconf->username, cli_username(cptr))) + continue; + } + if (hp) { + Debug((DEBUG_DNS, "a_il: %s->%s", cli_sockhost(cptr), hp->h_name)); + if (!match(aconf->host, hp->h_name)) + return check_limit_and_attach(cptr, aconf); + } + if ((aconf->addrbits >= 0) + && ipmask_check(&cli_ip(cptr), &aconf->address.addr, aconf->addrbits)) + return check_limit_and_attach(cptr, aconf); } return ACR_NO_AUTHORIZATION; } +/** Check whether a particular ConfItem is already attached to a + * Client. + * @param aconf ConfItem to search for + * @param cptr Client to check + * @return Non-zero if \a aconf is attached to \a cptr, zero if not. + */ static int is_attached(struct ConfItem *aconf, struct Client *cptr) { struct SLink *lp; @@ -449,13 +423,12 @@ return 0; } -/* - * attach_conf - * - * Associate a specific configuration entry to a *local* - * client (this is the one which used in accepting the - * connection). Note, that this automaticly changes the - * attachment if there was an old one... +/** Associate a specific configuration entry to a *local* client (this + * is the one which used in accepting the connection). Note, that this + * automaticly changes the attachment if there was an old one... + * @param cptr Client to attach \a aconf to + * @param aconf ConfItem to attach + * @return Authorization check result. */ enum AuthorizationCheckResult attach_conf(struct Client *cptr, struct ConfItem *aconf) { @@ -478,17 +451,20 @@ return ACR_OK; } +/** Return our LocalConf configuration structure. + * @return A pointer to #localConf. + */ const struct LocalConf* conf_get_local(void) { return &localConf; } -/* - * attach_confs_byname - * - * Attach a CONF line to a client if the name passed matches that for - * the conf file (for non-C/N lines) or is an exact match (C/N lines - * only). The difference in behaviour is to stop C:*::* and N:*::*. +/** Attach ConfItems to a client if the name passed matches that for + * the ConfItems or is an exact match for them. + * @param cptr Client getting the ConfItem attachments. + * @param name Filter to match ConfItem::name. + * @param statmask Filter to limit ConfItem::status. + * @return First ConfItem attached to \a cptr. */ struct ConfItem* attach_confs_byname(struct Client* cptr, const char* name, int statmask) @@ -513,8 +489,12 @@ return first; } -/* - * Added for new access check meLazy +/** Attach ConfItems to a client if the host passed matches that for + * the ConfItems or is an exact match for them. + * @param cptr Client getting the ConfItem attachments. + * @param host Filter to match ConfItem::host. + * @param statmask Filter to limit ConfItem::status. + * @return First ConfItem attached to \a cptr. */ struct ConfItem* attach_confs_byhost(struct Client* cptr, const char* host, int statmask) @@ -538,43 +518,47 @@ return first; } -/* - * find a conf entry which matches the hostname and has the same name. +/** Find a ConfItem that has the same name and user+host fields as + * specified. Requires an exact match for \a name. + * @param name Name to match + * @param cptr Client to match against + * @param statmask Filter for ConfItem::status + * @return First found matching ConfItem. */ -struct ConfItem* find_conf_exact(const char* name, const char* user, - const char* host, int statmask) +struct ConfItem* find_conf_exact(const char* name, struct Client *cptr, int statmask) { struct ConfItem *tmp; - char userhost[USERLEN + HOSTLEN + 3]; - - if (user) - ircd_snprintf(0, userhost, sizeof(userhost), "%s@%s", user, host); - else - ircd_strncpy(userhost, host, sizeof(userhost) - 1); for (tmp = GlobalConfList; tmp; tmp = tmp->next) { if (!(tmp->status & statmask) || !tmp->name || !tmp->host || 0 != ircd_strcmp(tmp->name, name)) continue; - /* - * Accept if the *real* hostname (usually sockecthost) - * socket host) matches *either* host or name field - * of the configuration. - */ - if (match(tmp->host, userhost)) + if (tmp->username + && (EmptyString(cli_username(cptr)) + || match(tmp->username, cli_username(cptr)))) continue; - if (tmp->status & CONF_OPERATOR) { - if (tmp->clients < MaxLinks(tmp->conn_class)) - return tmp; - else + if (tmp->addrbits < 0) + { + if (match(tmp->host, cli_sockhost(cptr))) continue; } - else - return tmp; + else if (!ipmask_check(&cli_ip(cptr), &tmp->address.addr, tmp->addrbits)) + continue; + if ((tmp->status & CONF_OPERATOR) + && (tmp->clients >= MaxLinks(tmp->conn_class))) + continue; + return tmp; } return 0; } +/** Find a ConfItem from a list that has a name that matches \a name. + * @param lp List to search in. + * @param name Filter for ConfItem::name field; matches either exactly + * or as a glob. + * @param statmask Filter for ConfItem::status. + * @return First matching ConfItem from \a lp. + */ struct ConfItem* find_conf_byname(struct SLink* lp, const char* name, int statmask) { @@ -595,8 +579,11 @@ return 0; } -/* - * Added for new access check meLazy +/** Find a ConfItem from a list that has a host that matches \a host. + * @param lp List to search in. + * @param host Filter for ConfItem::host field; matches as a glob. + * @param statmask Filter for ConfItem::status. + * @return First matching ConfItem from \a lp. */ struct ConfItem* find_conf_byhost(struct SLink* lp, const char* host, int statmask) @@ -618,27 +605,27 @@ return 0; } -/* - * find_conf_ip - * - * Find a conf line using the IP# stored in it to search upon. - * Added 1/8/92 by Avalon. +/** Find a ConfItem from a list that has an address equal to \a ip. + * @param lp List to search in. + * @param ip Filter for ConfItem::address field; matches exactly. + * @param statmask Filter for ConfItem::status. + * @return First matching ConfItem from \a lp. */ -struct ConfItem* find_conf_byip(struct SLink* lp, const char* ip, +struct ConfItem* find_conf_byip(struct SLink* lp, const struct irc_in_addr* ip, int statmask) { struct ConfItem* tmp; for (; lp; lp = lp->next) { tmp = lp->value.aconf; - if (0 != (tmp->status & statmask)) { - if (0 == memcmp(&tmp->ipnum, ip, sizeof(struct in_addr))) - return tmp; - } + if (0 != (tmp->status & statmask) + && !irc_in_addr_cmp(&tmp->address.addr, ip)) + return tmp; } return 0; } +/** Free all CRules from #cruleConfList. */ void conf_erase_crule_list(void) { struct CRuleConf* next; @@ -654,11 +641,15 @@ cruleConfList = 0; } +/** Return #cruleConfList. + * @return #cruleConfList + */ const struct CRuleConf* conf_get_crule_list(void) { return cruleConfList; } +/** Fr... [truncated message content] |