From 06ea484c36fed98f69f86dcc573c2e6523b8f482 Mon Sep 17 00:00:00 2001 From: Perry Lorier Date: Sat, 15 Jul 2000 23:55:33 +0000 Subject: [PATCH] Author: Isomer Log message: IP gline's / k:lines are now done with bit tests. This should be much much faster. As a side effect you can now gline/kline 10.0.0.0/8 for instance. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@271 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 9 ++- include/gline.h | 3 + include/s_conf.h | 1 + include/support.h | 8 +- ircd/gline.c | 97 ++++++++++++++++------- ircd/list.c | 1 + ircd/s_conf.c | 191 +++++++++++++++++++--------------------------- ircd/support.c | 2 +- 8 files changed, 168 insertions(+), 144 deletions(-) diff --git a/ChangeLog b/ChangeLog index f78ed10..68dcd21 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2000-07-15 Perry Lorier + * various: IP only k:'s and G:'s now do bit tests instead of two(!) + match()'s. Major Major cpu savings. Also speed up the + other case slightly. As a side effect you can now + k/Gline *@10.0.0.0/8. I'll do bans tomorrow, it's nearing + 3am. + 2000-07-15 Perry Lorier * various: Fixed warnings after compiling on an alpha. 2000-07-09 Perry Lorier @@ -1279,7 +1286,7 @@ # # ChangeLog for ircu2.10.11 # -# $Id: ChangeLog,v 1.157 2000-07-15 12:29:15 isomer Exp $ +# $Id: ChangeLog,v 1.158 2000-07-15 23:55:32 isomer Exp $ # # Insert new changes at beginning of the change list. # diff --git a/include/gline.h b/include/gline.h index d623e85..4a90466 100644 --- a/include/gline.h +++ b/include/gline.h @@ -30,6 +30,7 @@ #define INCLUDED_sys_types_h #endif +#include struct Client; @@ -43,6 +44,8 @@ struct Gline { char *gl_reason; time_t gl_expire; time_t gl_lastmod; + struct in_addr ipnum; /* We store the IP in binary for ip glines */ + char bits; unsigned int gl_flags; }; diff --git a/include/s_conf.h b/include/s_conf.h index 6d3f7f1..62a7f39 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -66,6 +66,7 @@ struct ConfItem { unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ unsigned int clients; /* Number of *LOCAL* clients using this */ struct in_addr ipnum; /* ip number of host field */ + char bits; /* Number of bits for ipkills */ char* host; char* passwd; char* name; diff --git a/include/support.h b/include/support.h index 3d07a30..09ce20d 100644 --- a/include/support.h +++ b/include/support.h @@ -17,9 +17,15 @@ #endif /* 0 */ /* - * Prototypes + * Given a number of bits, make a netmask out of it. */ +#define NETMASK(bits) htonl((0xffffffff>>(32-(bits)))<<(32-(bits))) + +/* + * Prototypes + */ + extern int check_if_ipmask(const char *mask); extern void write_log(const char *filename, const char *pattern, ...); diff --git a/ircd/gline.c b/ircd/gline.c index 53bd096..bc18f39 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -28,6 +28,7 @@ #include "match.h" #include "numeric.h" #include "s_bsd.h" +#include "s_debug.h" #include "s_misc.h" #include "send.h" #include "struct.h" @@ -39,6 +40,8 @@ #include #include +#include +#include /* for inet_ntoa */ struct Gline* GlobalGlineList = 0; struct Gline* BadChanGlineList = 0; @@ -109,8 +112,25 @@ make_gline(char *userhost, char *reason, time_t expire, time_t lastmod, DupString(gline->gl_user, user); /* remember them... */ DupString(gline->gl_host, host); - if (check_if_ipmask(host)) /* mark if it's an IP mask */ + if (check_if_ipmask(host)) { /* mark if it's an IP mask */ + int class; + char ipname[16]; + int ad[4] = { 0 }; + int bits2 = 0; + + class = sscanf(host,"%d.%d.%d.%d/%d", + &ad[0],&ad[1],&ad[2],&ad[3], &bits2); + if (class!=5) { + gline->bits=class*8; + } + else { + gline->bits=bits2; + } + sprintf_irc(ipname,"%d.%d.%d.%d",ad[0],ad[1],ad[2],ad[3]); + gline->ipnum.s_addr = inet_addr(ipname); + Debug((DEBUG_DEBUG,"IP gline: %08x/%i",gline->ipnum.s_addr,gline->bits)); gline->gl_flags |= GLINE_IPMASK; + } if (after) { gline->gl_next = after->gl_next; @@ -146,27 +166,35 @@ do_gline(struct Client *cptr, struct Client *sptr, struct Gline *gline) if ((acptr = LocalClientArray[fd])) { if (!acptr->user) continue; - - if ((GlineIsIpMask(gline) ? match(gline->gl_host, acptr->sock_ip) : - match(gline->gl_host, acptr->sockhost)) == 0 && - (!acptr->user->username || - match(gline->gl_user, acptr->user->username) == 0)) { - /* ok, here's one that got G-lined */ - send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s", - gline->gl_reason); - - /* let the ops know about it */ - sendto_opmask_butone(0, SNO_GLINE, "G-line active for %s", - get_client_name(acptr, FALSE)); - - /* and get rid of him */ - if ((tval = exit_client_msg(cptr, acptr, &me, "G-lined (%s)", - gline->gl_reason))) - retval = tval; /* retain killed status */ + + if (acptr->user->username && + match(gline->gl_user, acptr->user->username) == 0) + continue; + + if (GlineIsIpMask(gline)) { + Debug((DEBUG_DEBUG,"IP gline: %08x %08x/%i",cptr->ip.s_addr,gline->ipnum.s_addr,gline->bits)); + if ((cptr->ip.s_addr & NETMASK(gline->bits)) != gline->ipnum.s_addr) + continue; + } + else { + if (match(gline->gl_host, acptr->sock_ip) != 0) + continue; } + + /* ok, here's one that got G-lined */ + send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s", + gline->gl_reason); + + /* let the ops know about it */ + sendto_opmask_butone(0, SNO_GLINE, "G-line active for %s", + get_client_name(acptr, FALSE)); + + /* and get rid of him */ + if ((tval = exit_client_msg(cptr, acptr, &me, "G-lined (%s)", + gline->gl_reason))) + retval = tval; /* retain killed status */ } } - return retval; } @@ -268,7 +296,6 @@ gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline, unsigned int saveflags = 0; assert(0 != gline); - assert(!GlineIsLocal(gline)); saveflags = gline->gl_flags; @@ -436,18 +463,32 @@ gline_lookup(struct Client *cptr, unsigned int flags) for (gline = GlobalGlineList; gline; gline = sgline) { sgline = gline->gl_next; - if (gline->gl_expire <= CurrentTime) + if (gline->gl_expire <= CurrentTime) { gline_free(gline); - else if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || + continue; + } + + if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || (flags & GLINE_LASTMOD && !gline->gl_lastmod)) continue; - else if ((GlineIsIpMask(gline) ? - match(gline->gl_host, ircd_ntoa((const char *)&cptr->ip)) : - match(gline->gl_host, cptr->user->host)) == 0 && - match(gline->gl_user, cptr->user->username) == 0) - return gline; + + if (match(gline->gl_user, cptr->user->username) != 0) + continue; + + if (GlineIsIpMask(gline)) { + Debug((DEBUG_DEBUG,"IP gline: %08x %08x/%i",cptr->ip.s_addr,gline->ipnum.s_addr,gline->bits)); + if ((cptr->ip.s_addr & NETMASK(gline->bits)) != gline->ipnum.s_addr) + continue; + } + else { + if (match(gline->gl_host, cptr->user->host) != 0) + continue; + } + return gline; } - + /* + * No Glines matched + */ return 0; } diff --git a/ircd/list.c b/ircd/list.c index fb86192..af65dde 100644 --- a/ircd/list.c +++ b/ircd/list.c @@ -23,6 +23,7 @@ #include "class.h" #include "client.h" +#include "IPcheck.h" #include "ircd.h" #include "ircd_alloc.h" #include "ircd_reply.h" diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 83b0b0f..a6b7d13 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -75,79 +75,6 @@ struct TRecord* tdata = NULL; struct tm motd_tm; -/* - * is the K line field an interval or a comment? - Mmmm - */ -static int is_comment(const char *comment) -{ - unsigned int i; - unsigned int len = strlen(comment); - for (i = 0; i < len; ++i) { - if (!IsKTimeChar(comment[i])) - return 1; - } - return 0; -} - -/* - * check against a set of time intervals - */ -static int check_time_interval(char *interval, char *reply, size_t reply_size) -{ - struct tm* tptr; - char* p; - int perm_min_hours; - int perm_min_minutes; - int perm_max_hours; - int perm_max_minutes; - int nowm; - int perm_min; - int perm_max; - - tptr = localtime(&CurrentTime); - nowm = tptr->tm_hour * 60 + tptr->tm_min; - - while (interval) { - p = strchr(interval, ','); - if (p) - *p = '\0'; - if (sscanf(interval, "%2d%2d-%2d%2d", &perm_min_hours, &perm_min_minutes, - &perm_max_hours, &perm_max_minutes) != 4) - { - if (p) - *p = ','; - return 0; - } - if (p) - *(p++) = ','; - perm_min = 60 * perm_min_hours + perm_min_minutes; - perm_max = 60 * perm_max_hours + perm_max_minutes; - /* - * The following check allows intervals over midnight ... - */ - if ((perm_min < perm_max) - ? (perm_min <= nowm && nowm <= perm_max) - : (perm_min <= nowm || nowm <= perm_max)) - { - ircd_snprintf(0, reply, reply_size, ":You are not allowed to connect " - "from %d:%02d to %d:%02d.", perm_min_hours, - perm_min_minutes, perm_max_hours, perm_max_minutes); - return (ERR_YOUREBANNEDCREEP); - } - if ((perm_min < perm_max) - ? (perm_min <= nowm + 5 && nowm + 5 <= perm_max) - : (perm_min <= nowm + 5 || nowm + 5 <= perm_max)) - { - ircd_snprintf(0, reply, reply_size, ":%d minute%s and you will be " - "denied for further access", perm_min - nowm, - (perm_min - nowm) > 1 ? "s" : ""); - return (ERR_YOUWILLBEBANNED); - } - interval = p; - } - return 0; -} - /* * output the reason for being k lined from a file - Mmmm * sptr is server @@ -1066,6 +993,7 @@ int conf_init(void) /* Could we test if it's conf line at all? -Vesa */ if (line[1] != ':') { Debug((DEBUG_ERROR, "Bad config line: %s", line)); + sendto_op_mask(SNO_OLDSNO,"Bad Config line"); continue; } if (aconf) @@ -1144,6 +1072,7 @@ int conf_init(void) break; default: Debug((DEBUG_ERROR, "Error in config file: %s", line)); + sendto_op_mask(SNO_OLDSNO,"Unknown prefix in config file: %c",*tmp); break; } if (IsIllegal(aconf)) @@ -1167,9 +1096,9 @@ int conf_init(void) if (aconf->status & CONF_ME) { if (!tmp) { Debug((DEBUG_FATAL, "Your M: line must have the Numeric, " - "assigned to you by routing-com, behind the port number!\n")); + "assigned to you by routing-com!\n")); ircd_log(L_WARNING, "Your M: line must have the Numeric, " - "assigned to you by routing-com, behind the port number!\n"); + "assigned to you by routing-com!\n"); exit(-1); } SetYXXServerName(&me, atoi(tmp)); /* Our Numeric Nick */ @@ -1278,6 +1207,31 @@ int conf_init(void) if (aconf->status == CONF_ME) { ircd_strncpy(me.info, aconf->name, REALLEN); } + + if (aconf->status == CONF_IPKILL) { + /* + * Here we use the same kludge as in listener.c to parse + * a.b.c.d, or a.b.c.*, or a.b.c.d/e. + */ + int class; + char ipname[16]; + int ad[4] = { 0 }; + int bits2=0; + class=sscanf(aconf->host,"%d.%d.%d.%d/%d", + &ad[0], &ad[1], &ad[2], &ad[3], &bits2); + if (class!=5) { + aconf->bits=class*8; + } + else { + aconf->bits=bits2; + } + sprintf_irc(ipname,"%d.%d.%d.%d",ad[0], ad[1], ad[2], ad[3]); + + /* This ensures endian correctness */ + aconf->ipnum.s_addr = inet_addr(ipname); + Debug((DEBUG_DEBUG,"IPkill: %s = %08x/%i (%08x)",ipname, + aconf->ipnum.s_addr,aconf->bits,NETMASK(aconf->bits))); + } /* * Juped nicks are listed in the 'password' field of U:lines, @@ -1357,9 +1311,19 @@ void read_tlines() } } +/* + * find_kill + * input: + * client pointer + * returns: + * 0: Client may continue to try and connect + * -1: Client was K/k:'d - sideeffect: reason was sent. + * -2: Client was G/g:'d - sideeffect: reason was sent. + * sideeffects: + * Client may have been sent a reason why they are denied, as above. + */ int find_kill(struct Client *cptr) { - char reply[256]; const char* host; const char* name; struct ConfItem* tmp; @@ -1373,47 +1337,43 @@ int find_kill(struct Client *cptr) host = cptr->sockhost; name = cptr->user->username; -#if 0 - /* - * whee :) - * XXX - if this ever happens, we're already screwed + assert(strlen(host) <= HOSTLEN); + assert((name ? strlen(name) : 0) <= HOSTLEN); + + /* 2000-07-14: Rewrote this loop for massive speed increases. + * -- Isomer */ - if (strlen(host) > HOSTLEN || - (name ? strlen(name) : 0) > HOSTLEN) - return (0); -#endif - - reply[0] = '\0'; - for (tmp = GlobalConfList; tmp; tmp = tmp->next) { - /* Added a check against the user's IP address as well. - * If the line is either CONF_KILL or CONF_IPKILL, check it; if and only - * if it's CONF_IPKILL, check the IP address as well (the && below will - * short circuit and the match won't even get run) -Kev + + if ((tmp->status & CONF_KLINE) == 0) + continue; + + /* + * What is this for? You can K: by port?! + * -- Isomer */ - if ((tmp->status & CONF_KLINE) && tmp->host && tmp->name && - (match(tmp->host, host) == 0 || - ((tmp->status == CONF_IPKILL) && - match(tmp->host, ircd_ntoa((const char*) &cptr->ip)) == 0)) && - (!name || match(tmp->name, name) == 0) && - (!tmp->port || (tmp->port == cptr->listener->port))) - { - /* - * Can short-circuit evaluation - not taking chances - * because check_time_interval destroys tmp->passwd - * - Mmmm - */ - if (EmptyString(tmp->passwd)) - break; - else if (is_comment(tmp->passwd)) - break; - else if (check_time_interval(tmp->passwd, reply, sizeof(reply))) - break; + if (tmp->port && tmp->port != cptr->listener->port) + continue; + + if (!tmp->name || match(tmp->name, name) != 0) + continue; + + if (!tmp->host) + break; + + if (tmp->status != CONF_IPKILL) { + if (match(tmp->host, host) == 0) + break; + } + else { /* k: by IP */ + Debug((DEBUG_DEBUG, "ip: %08x network: %08x/%i mask: %08x", + cptr->ip.s_addr, tmp->ipnum.s_addr, tmp->bits, + NETMASK(tmp->bits))); + if ((cptr->ip.s_addr & NETMASK(tmp->bits)) == tmp->ipnum.s_addr) + break; } } - if (reply[0]) - send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, reply); - else if (tmp) { + if (tmp) { if (EmptyString(tmp->passwd)) send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":Connection from your host is refused on this server."); @@ -1442,7 +1402,12 @@ int find_kill(struct Client *cptr) else agline = NULL; /* if a gline was found, it was inactive */ - return (tmp ? -1 : (agline ? -2 : 0)); + if (tmp) + return -1; + if (agline) + return -2; + + return 0; } struct MotdItem* read_motd(const char* motdfile) diff --git a/ircd/support.c b/ircd/support.c index ac1f7d4..93a94e3 100644 --- a/ircd/support.c +++ b/ircd/support.c @@ -42,7 +42,7 @@ int check_if_ipmask(const char *mask) const char *p; for (p = mask; *p; ++p) - if (*p != '*' && *p != '?' && *p != '.') + if (*p != '*' && *p != '?' && *p != '.' && *p != '/') { if (!IsDigit(*p)) return 0; -- 2.20.1