diff --git a/Changes b/Changes index da8112e73..998dc10cb 100644 --- a/Changes +++ b/Changes @@ -3272,3 +3272,7 @@ This is the 3.2 fixes branch. - Win32: Readded /J compiler flag (was accidentally lost in December). This could cause some weird issues. Reported by Troco (#0001877). - Fixed compile problem with debugmode + ipv6 +- Added CIDR support (#0001296) suggested by many people. + - Imported the latest CIDR functions from Hybrid 7.0.1 (and fixed numerous bugs) + - Implemented CIDR support for ban ip, ban user, allow, except ban/tkl/throttle, and TKL + - Note: This needs testing diff --git a/doc/unreal32docs.html b/doc/unreal32docs.html index 40811eb48..0686433f4 100644 --- a/doc/unreal32docs.html +++ b/doc/unreal32docs.html @@ -64,7 +64,8 @@ English | German

-- 3.12. Anti-flood features
-- 3.13. Ban types
-- 3.14. Spamfilter
- -- 3.15. Other features
+ -- 3.15. CIDR
+ -- 3.16. Other features
4. Configuring your unrealircd.conf file
---4.1. Configuration file explained
@@ -509,7 +510,17 @@ into spaces at runtime. And double underscore ('__') gets an underscore ('_'). A set::spamfilter::virus-help-channel-deny allows you to block any normal joins to virus-help-channel (default: no)

-

3.15 - Other features

+

3.15 - CIDR

+

UnrealIRCd now has support for CIDR (Classless Interdomain Routing). CIDR allows you to ban +IP ranges. IPs are allocated to ISPs using CIDR, therefore, being able to set a CIDR based ban +allows you to easily ban an ISP. Unreal supports CIDR for both IPv4 and IPv6. CIDR masks may be +used in the allow::ip, ban user::mask, ban ip::mask, except ban::mask, except throttle::mask, +and except tkl::mask (for gzline, gline, and shun). Additionally, CIDR can be used in /kline, +/gline, /zline, /gzline, and /shun. Unreal uses the standard syntax of IP/bits, e.g., +127.0.0.0/8 (matches 127.0.0.0 - 127.255.255.255), and fe80:0:0:123::/64 (matches +fe80:0:0:123:0:0:0:0 - fe80:0:0:123:ffff:ffff:ffff:ffff).

+ +

3.16 - Other features

UnrealIRCd has a lot of features so not everything is covered here... You'll find that out by yourself.

diff --git a/include/h.h b/include/h.h index 51dd22b17..770281ff7 100644 --- a/include/h.h +++ b/include/h.h @@ -122,21 +122,19 @@ ConfigItem_deny_dcc *Find_deny_dcc(char *name); ConfigItem_oper *Find_oper(char *name); ConfigItem_listen *Find_listen(char *ipmask, int port); ConfigItem_ulines *Find_uline(char *host); -ConfigItem_except *Find_except(char *host, short type); +ConfigItem_except *Find_except(aClient *, char *host, short type); ConfigItem_tld *Find_tld(aClient *cptr, char *host); ConfigItem_link *Find_link(char *username, char *hostname, char *ip, char *servername); -ConfigItem_ban *Find_ban(char *host, short type); -ConfigItem_ban *Find_banEx(char *host, short type, short type2); +ConfigItem_ban *Find_ban(aClient *, char *host, short type); +ConfigItem_ban *Find_banEx(aClient *,char *host, short type, short type2); ConfigItem_vhost *Find_vhost(char *name); ConfigItem_deny_channel *Find_channel_allowed(char *name); ConfigItem_alias *Find_alias(char *name); ConfigItem_help *Find_Help(char *command); int AllowClient(aClient *cptr, struct hostent *hp, char *sockhost, char *username); -int parse_netmask(const char *text, struct IN_ADDR *addr, int *b); -int match_ipv4(struct IN_ADDR *addr, struct IN_ADDR *mask, int b); -#ifdef INET6 -int match_ipv6(struct IN_ADDR *addr, struct IN_ADDR *mask, int b); -#endif +int parse_netmask(const char *text, struct irc_netmask *netmask); +int match_ip(struct IN_ADDR addr, char *uhost, char *mask, struct irc_netmask *netmask); +ConfigItem_ban *Find_ban_ip(aClient *sptr); extern MODVAR struct tm motd_tm, smotd_tm; extern MODVAR Link *Servers; void add_ListItem(ListStruct *, ListStruct **); diff --git a/include/struct.h b/include/struct.h index e5dc6e83b..e9ff03da9 100644 --- a/include/struct.h +++ b/include/struct.h @@ -658,6 +658,13 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */ #define DCC_LINK_ME 1 /* My dcc allow */ #define DCC_LINK_REMOTE 2 /* I need to remove dccallows from these clients when I die */ +struct irc_netmask +{ + short int type; + struct IN_ADDR mask; + short int bits; +}; + struct FloodOpt { unsigned short nmsg; TS firstmsg; @@ -790,7 +797,10 @@ struct t_kline { aTKline *prev, *next; int type; unsigned short subtype; /* subtype (currently spamfilter only), see SPAMF_* */ - Spamfilter *spamf; + union { + Spamfilter *spamf; + struct irc_netmask *netmask; + } ptr; char usermask[USERLEN + 3]; char *hostmask, *reason, *setby; TS expire_at, set_at; @@ -1061,6 +1071,7 @@ struct _configitem_allow { unsigned short maxperip; int port; ConfigItem_class *class; + struct irc_netmask *netmask; ConfigFlag_allow flags; }; @@ -1147,15 +1158,14 @@ struct _configitem_except { ConfigFlag_except flag; int type; char *mask; + struct irc_netmask *netmask; }; struct _configitem_ban { ConfigItem *prev, *next; ConfigFlag_ban flag; char *mask, *reason; - struct IN_ADDR netmask; - int bits; - short masktype; + struct irc_netmask *netmask; unsigned short action; }; @@ -1697,7 +1707,7 @@ int hash_throttling(struct IN_ADDR *in); struct ThrottlingBucket *find_throttling_bucket(struct IN_ADDR *in); void add_throttling_bucket(struct IN_ADDR *in); void del_throttling_bucket(struct ThrottlingBucket *bucket); -int throttle_can_connect(struct IN_ADDR *in); +int throttle_can_connect(aClient *, struct IN_ADDR *in); #endif diff --git a/src/cidr.c b/src/cidr.c index c0372f30b..840cfd3c7 100644 --- a/src/cidr.c +++ b/src/cidr.c @@ -23,338 +23,382 @@ #include "struct.h" #include "h.h" #include "inet.h" -/* The following functions have been taken from Hybrid7-beta8 simply because +/* The following functions have been taken from Hybrid-7.0.1 simply because * I didn't feel like writing my own when they had ones that work just fine :) + * However, several bugs were found and some stuff was moved around to work + * better. */ #ifdef INET6 -static int parse_v6_netmask(const char *, struct IN_ADDR *, int *); +static int parse_v6_netmask(const char *, struct IN_ADDR *addr, short int *b); #endif -static int parse_v4_netmask(const char *, struct IN_ADDR *, int *); +static int parse_v4_netmask(const char *, struct IN_ADDR *addr, short int *b); -#define DigitParse(ch) if (ch >= '0' && ch <= '9') \ +#define DigitParse(ch) do { \ + if (ch >= '0' && ch <= '9') \ ch = ch - '0'; \ else if (ch >= 'A' && ch <= 'F') \ - ch = ch - 'A' + '0'; \ + ch = ch - 'A' + 10; \ else if (ch >= 'a' && ch <= 'f') \ - ch = ch - 'a' + '0'; + ch = ch - 'a' + 10; \ + } while(0); /* The mask parser/type determination code... */ -/* int parse_v6_netmask(const char *, struct IN_ADDR*, int *); +/* int parse_v6_netmask(const char *, struct IN_ADDR*, short int *); * Input: An possible IPV6 address as a string. * Output: An integer describing whether it is an IPV6 or hostmask, * an address(if it is IPV6), a bitlength(if it is IPV6). * Side effects: None * Comments: Called from parse_netmask */ +/* Fixed so ::/0 (any IPv6 address) is valid + Also a bug in DigitParse above. + -Gozem 2002-07-19 gozem@linux.nu + */ #ifdef INET6 -static int -parse_v6_netmask(const char *text, struct IN_ADDR *addr, int *b) +static int parse_v6_netmask(const char *text, struct IN_ADDR *addr, short int *b) { - const char *p; - char c; - int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }, dp = 0, nyble = 4, finsert = - -1, bits = 0, deficit = 0; - short dc[8]; + const char *p; + char c; + int d[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + int dp = 0; + int nyble = 4; + int finsert = -1; + short int bits = 128; + int deficit = 0; + unsigned short dc[8]; - for (p = text; (c = *p); p++) - if (isxdigit(c)) - { - if (nyble == 0) - return HM_HOST; - DigitParse(c); - d[dp] |= c << (4 * --nyble); - } - else if (c == ':') - { - if (p > text && *(p - 1) == ':') - { - if (finsert >= 0) - return HM_HOST; - finsert = dp; - } - else - { - /* If there were less than 4 hex digits, e.g. :ABC: shift right - * so we don't interpret it as ABC0 -A1kmm */ - d[dp] = d[dp] >> 4 * nyble; - nyble = 4; - if (++dp >= 8) - return HM_HOST; - } - } - else if (c == '*') - { - /* * must be last, and * is ambiguous if there is a ::... -A1kmm */ - if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':') - return HM_HOST; - bits = dp * 16; - } - else if (c == '/') - { - char *after; + for (p = text; (c = *p); p++) + /* Parse a digit */ + if (isxdigit(c)) + { + if (nyble == 0) + return HM_HOST; + DigitParse(c); + d[dp] |= c << (4 * --nyble); + } + else if (c == ':') + { + /* It's a :: */ + if (p > text && *(p - 1) == ':') + { + if (finsert >= 0) /* Error: already has a :: */ + return HM_HOST; + finsert = dp; + } + /* Just a regular : */ + else + { + /* If there were less than 4 hex digits, e.g. :ABC: shift right + * so we don't interpret it as ABC0 -A1kmm */ + d[dp] = d[dp] >> 4 * nyble; + nyble = 4; + if (++dp >= 8) /* Error: more than 8 segments */ + return HM_HOST; + } + } + /* Wildcard */ + else if (c == '*') + { + /* Error: there was a ::, or it is not the last segment */ + if (finsert >= 0 || *(p + 1) || dp == 0 || *(p - 1) != ':') + return HM_HOST; + bits = dp * 16; + } + /* Bit section */ + else if (c == '/') + { + char *after; - d[dp] = d[dp] >> 4 * nyble; - dp++; - if (p > text && *(p - 1) == ':') - return HM_HOST; - bits = strtoul(p + 1, &after, 10); - if (bits == 0 || *after) - return HM_HOST; - if (bits > dp * 4 && !(finsert >= 0 && bits <= 128)) - return HM_HOST; - break; - } - else - return HM_HOST; + d[dp] = d[dp] >> 4 * nyble; + dp++; + bits = strtoul(p + 1, &after, 10); + if (bits < 0 || *after) /* Error: bits is invalid or not the end */ + return HM_HOST; + /* Error: Bits is greater than the number of bits given + * and there is no :: */ + if (bits > dp * 16 && !(finsert >= 0 && bits <= 128)) + return HM_HOST; + break; + } + else /* Error: Illegal character */ + return HM_HOST; - d[dp] = d[dp] >> 4 * nyble; - if (c == 0) - dp++; - if (finsert < 0 && bits == 0) - bits = dp * 16; - else if (bits == 0) - bits = 128; - /* How many words are missing? -A1kmm */ - deficit = bits / 16 + ((bits % 16) ? 1 : 0) - dp; - /* Now fill in the gaps(from ::) in the copied table... -A1kmm */ - for (dp = 0, nyble = 0; dp < 8; dp++) - { - if (nyble == finsert && deficit) - { - dc[dp] = 0; - deficit--; - } - else - dc[dp] = d[nyble++]; - } - /* Set unused bits to 0... -A1kmm */ - if (bits < 128 && (bits % 16 != 0)) - dc[bits / 16] &= ~((1 << (15 - bits % 16)) - 1); - for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++) - dc[dp] = 0; - /* And assign... -A1kmm */ - if (addr) - for (dp = 0; dp < 8; dp++) - /* The cast is a kludge to make netbsd work. */ - ((unsigned short *)&addr->s6_addr)[dp] = htons(dc[dp]); - if (b) - *b = bits; - return HM_IPV6; + /* This is handled above if it was a / */ + if (c != '/') + d[dp] = d[dp] >> 4 * nyble; + if (c == 0) + dp++; + + /* If there was no bit section, set the number of bits */ + if (finsert < 0 && bits == 0) + bits = dp * 16; + /* How many words are missing? -A1kmm */ + /* The original check was wrong -- codemastr */ + deficit = 8 - dp; + + /* Now fill in the gaps(from ::) in the copied table... -A1kmm */ + for (dp = 0, nyble = 0; dp < 8; dp++) + { + if (nyble == finsert && deficit) + { + dc[dp] = 0; + deficit--; + } + else + dc[dp] = d[nyble++]; + } + /* Set unused bits to 0... -A1kmm */ + /* This check was wrong as well -- codemastr */ + if (bits < 128 && (bits % 16 != 0)) + dc[bits / 16] &= ~((1 << (16 - bits % 16)) - 1); + for (dp = bits / 16 + (bits % 16 ? 1 : 0); dp < 8; dp++) + dc[dp] = 0; + /* And assign... -A1kmm */ + if (addr) + for (dp = 0; dp < 8; dp++) + /* The cast is a kludge to make netbsd work. */ + ((unsigned short *)&addr->s6_addr)[dp] = htons(dc[dp]); + if (b != NULL) + *b = bits; + return HM_IPV6; } #endif -/* int parse_v4_netmask(const char *, struct IN_ADDR *, int *); - * Input: An possible IPV4 address as a string. +/* int parse_v4_netmask(const char *, struct IN_ADDR *, short int *); + * Input: A possible IPV4 address as a string. * Output: An integer describing whether it is an IPV4 or hostmask, * an address(if it is IPV4), a bitlength(if it is IPV4). * Side effects: None * Comments: Called from parse_netmask */ -static int -parse_v4_netmask(const char *text, struct IN_ADDR *addr, int *b) +static int parse_v4_netmask(const char *text, struct IN_ADDR *addr, short int *b) { + const char *p; + const char *digits[4]; + unsigned char addb[4]; + int n = 0, bits = 0; + char c; + + digits[n++] = text; + + for (p = text; (c = *p); p++) + if (c >= '0' && c <= '9') /* empty */ + ; + else if (c == '.') + { + if (n >= 4) /* Error: More than four sections */ + return HM_HOST; + digits[n++] = p + 1; + } + else if (c == '*') + { + if (*(p + 1) || n == 0 || *(p - 1) != '.') /* Error: * is not at the end + * or not its own section */ + return HM_HOST; + bits = (n - 1) * 8; + break; + } + else if (c == '/') + { + char *after; + bits = strtoul(p + 1, &after, 10); + if (!bits || *after) /* Error: Invalid number or not end */ + return HM_HOST; + if (bits > n * 8) /* Error: More than the bits given */ + return HM_HOST; + break; + } + else /* Error: Illegal character */ + return HM_HOST; + + if (n < 4 && bits == 0) + bits = n * 8; + if (bits) + while (n < 4) + digits[n++] = "0"; + for (n = 0; n < 4; n++) + addb[n] = strtoul(digits[n], NULL, 10); + if (bits == 0) + bits = 32; + /* Set unused bits to 0... -A1kmm */ + if (bits < 32 && bits % 8) + addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1); + for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 4; n++) + addb[n] = 0; + if (addr) + { #ifndef INET6 - const char *p; - const char *digits[4]; - unsigned char addb[8]; /* will only use 4, but space for overflow [?]. -- Syzop*/ - int n = 0, bits = 0; - char c; - - digits[n++] = text; - - for (p = text; (c = *p); p++) - if (c >= '0' && c <= '9') /* empty */ - ; - else if (c == '.') - { - if (n >= 4) - return HM_HOST; - digits[n++] = p + 1; - } - else if (c == '*') - { - if (*(p + 1) || n == 0 || *(p - 1) != '.') - return HM_HOST; - bits = (n - 1) * 8; - break; - } - else if (c == '/') - { - char *after; - bits = strtoul(p + 1, &after, 10); - if (!bits || *after) - return HM_HOST; - if (bits > n * 8) - return HM_HOST; - break; - } - else - return HM_HOST; - - if (n < 4 && bits == 0) - bits = n * 8; - if (bits) - while (n < 4) - digits[n++] = "0"; - for (n = 0; n < 4; n++) - addb[n] = strtoul(digits[n], NULL, 10); - if (bits == 0) - bits = 32; - /* Set unused bits to 0... -A1kmm */ - if (bits < 32 && bits % 8) - addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1); - for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 8; n++) - addb[n] = 0; - if (addr) - addr->S_ADDR = - htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]); - if (b) - *b = bits; - return HM_IPV4; + addr->s_addr = htonl(addb[0] << 24 | addb[1] << 16 | addb[2] << 8 | addb[3]); #else - u_char *cp; - const char *p; - const char *digits[4]; - unsigned char addb[4]; - int n = 0, bits = 0; - char c; - - digits[n++] = text; - - for (p = text; (c = *p); p++) - if (c >= '0' && c <= '9') /* empty */ - ; - else if (c == '.') - { - if (n >= 4) - return HM_HOST; - digits[n++] = p + 1; - } - else if (c == '*') - { - if (*(p + 1) || n == 0 || *(p - 1) != '.') - return HM_HOST; - bits = (n - 1) * 8; - break; - } - else if (c == '/') - { - char *after; - bits = strtoul(p + 1, &after, 10); - if (!bits || *after) - return HM_HOST; - if (bits > n * 8) - return HM_HOST; - break; - } - else - return HM_HOST; - - if (n < 4 && bits == 0) - bits = n * 8; - if (bits) - while (n < 4) - digits[n++] = "0"; - for (n = 0; n < 4; n++) - addb[n] = strtoul(digits[n], NULL, 10); - if (bits == 0) - bits = 32; - /* Set unused bits to 0... -A1kmm */ - if (bits < 32 && bits % 8) - addb[bits / 8] &= ~((1 << (8 - bits % 8)) - 1); - for (n = bits / 8 + (bits % 8 ? 1 : 0); n < 8; n++) - addb[n] = 0; - if (addr) - { - cp = (u_char *)addr->s6_addr; - for (n = 0; n <= 9; n++) - cp[n] = 0; - cp[10] = 0xff; - cp[11] = 0xff; - cp[12] = addb[0]; - cp[13] = addb[1]; - cp[14] = addb[2]; - cp[15] = addb[3]; - } - if (b) - *b = bits; - return HM_IPV4; - + for (n = 0; n <= 9; n++) + addr->s6_addr[n] = 0; + addr->s6_addr[10] = 0xff; + addr->s6_addr[11] = 0xff; + addr->s6_addr[12] = addb[0]; + addr->s6_addr[13] = addb[1]; + addr->s6_addr[14] = addb[2]; + addr->s6_addr[15] = addb[3]; #endif + } + if (b) + *b = bits; + return HM_IPV4; } -/* int parse_netmask(const char *, struct IN_ADDR *, int *); +/* int parse_netmask(const char *, struct irc_netmask *); * Input: A hostmask, or an IPV4/6 address. * Output: An integer describing whether it is an IPV4, IPV6 address or a * hostmask, an address(if it is an IP mask), * a bitlength(if it is IP mask). * Side effects: None */ -int -parse_netmask(const char *text, struct IN_ADDR *addr, int *b) +int parse_netmask(const char *text, struct irc_netmask *netmask) { + char *c; + const char *host; + + /* So a user@ip can be specified -- codemastr */ + if ((c = strchr(text, '@')) && *(c+1)) + host = c+1; + else + host = text; #ifdef INET6 - if (strchr(text, ':')) - return parse_v6_netmask(text, addr, b); + if (strchr(host, ':')) + return parse_v6_netmask(host, &netmask->mask, &netmask->bits); #endif - if (strchr(text, '.')) - return parse_v4_netmask(text, addr, b); - return HM_HOST; + else if (strchr(host, '.')) + return parse_v4_netmask(host, &netmask->mask, &netmask->bits); + else + { + /* Well, lets just try and see? + * This is here because ffff/10, for example, + * is valid for our purposes */ + if (parse_v4_netmask(host, &netmask->mask, &netmask->bits) == HM_IPV4) + return HM_IPV4; +#ifdef INET6 + return parse_v6_netmask(host, &netmask->mask, &netmask->bits); +#endif + } + return HM_HOST; } /* The address matching stuff... */ /* int match_ipv6(struct IN_ADDR *, struct IN_ADDR *, int) * Input: An IP address, an IP mask, the number of bits in the mask. - * Output: if match, 0 else 1 + * Output: if match, 1 else 0 * Side effects: None */ #ifdef INET6 -int -match_ipv6(struct IN_ADDR *addr, struct IN_ADDR *mask, int bits) +int match_ipv6(struct IN_ADDR *addr, struct IN_ADDR *mask, int bits) { - int i, m, n = bits / 8; + int i, m, n = bits / 8; - for (i = 0; i < n; i++) - if (addr->S_ADDR[i] != mask->S_ADDR[i]) - return 1; - if ((m = bits % 8) == 0) - return 0; - if ((addr->S_ADDR[n] & ~((1 << (8 - m)) - 1)) == - mask->S_ADDR[n]) - return 0; - return 1; + for (i = 0; i < n; i++) + if (addr->s6_addr[i] != mask->s6_addr[i]) + return 0; + if ((m = bits % 8) == 0) + return 1; + if ((addr->s6_addr[n] & ~((1 << (8 - m)) - 1)) == mask->s6_addr[n]) + return 1; + return 0; } #endif /* int match_ipv4(struct IN_ADDR *, struct IN_ADDR *, int) * Input: An IP address, an IP mask, the number of bits in the mask. - * Output: if match, 0 else 1 + * Output: if match, 1 else 0 * Side Effects: None */ -int -match_ipv4(struct IN_ADDR *addr, struct IN_ADDR *mask, int bits) +int match_ipv4(struct IN_ADDR *addr, struct IN_ADDR *mask, int bits) { #ifndef INET6 - if ((ntohl(addr->S_ADDR) & ~((1 << (32 - bits)) - 1)) != - ntohl(mask->S_ADDR)) - - return 1; - return 0; + if ((ntohl(addr->s_addr) & ~((1 << (32 - bits)) - 1)) == ntohl(mask->s_addr)) + return 0; + return 1; #else - struct in_addr ipv4addr, ipv4mask; - - ipv4addr.s_addr = inet_addr((char *)Inet_ia2p(addr)); - ipv4mask.s_addr = inet_addr((char *)Inet_ia2p(mask)); - if ((ntohl(ipv4addr.s_addr) & ~((1 << (32 - bits)) - 1)) != - ntohl(ipv4mask.s_addr)) + struct in_addr ipv4addr, ipv4mask; + u_char *cp; + cp = (u_char *)((struct IN_ADDR *)addr)->s6_addr; - return 1; - return 0; - + /* Make sure the address is IPv4 */ + if (cp[0] == 0 && cp[1] == 0 && cp[2] == 0 && cp[3] == 0 && cp[4] == 0 + && cp[5] == 0 && cp[6] == 0 && cp[7] == 0 && cp[8] == 0 + && cp[9] == 0 && cp[10] == 0xff && cp[11] == 0xff) + { + /* Convert the v6 representation to v4 */ + bcopy(&addr->s6_addr[12], &ipv4addr, sizeof(struct in_addr)); + bcopy(&mask->s6_addr[12], &ipv4mask, sizeof(struct in_addr)); + if ((ntohl(ipv4addr.s_addr) & ~((1 << (32 - bits)) - 1)) == + ntohl(ipv4mask.s_addr)) + return 1; + } + return 0; #endif } +/* int match_ip(aClient *sptr, int type, char *mask, struct irc_netmask netmask) + * Input: a Client, a netmask type, a string mask, and a netmask struct + * Output: if match, 1 else 0 + * Side Effects: None + */ +#if 0 +int match_ip(struct IN_ADDR addr, char *uhost, char *mask, struct irc_netmask *netmask) +{ + if (!netmask) + return (!match(mask, uhost)); + + switch (netmask->type) + { + case HM_HOST: + return (!match(mask, uhost)); + case HM_IPV4: + return match_ipv4(&addr, &netmask->mask, netmask->bits); +#ifdef INET6 + case HM_IPV6: + return match_ipv6(&addr, &netmask->mask, netmask->bits); +#endif + default: + return 0; + } +} +#endif +int match_ip(struct IN_ADDR addr, char *uhost, char *mask, struct irc_netmask *netmask) +{ + char *end; + + if (!netmask) + return (!match(mask, uhost)); + + /* If it is an IP mask, we need to extract the user portion of both + * and run a match. + */ + if (mask && (end = strchr(mask, '@'))) + { + char username[USERLEN+1], usermask[USERLEN+1]; + strlcpy(usermask, mask, end-mask+1 > USERLEN+1 ? USERLEN+1 : end-mask+1); + if ((end = strchr(uhost, '@'))) + { + strlcpy(username, uhost, end-uhost+1 > USERLEN+1 ? USERLEN+1 : end-uhost+1); + if (match(usermask, username)) + return 0; + } + } + + switch (netmask->type) + { + case HM_HOST: + return (!match(mask, uhost)); + case HM_IPV4: + return match_ipv4(&addr, &netmask->mask, netmask->bits); +#ifdef INET6 + case HM_IPV6: + return match_ipv6(&addr, &netmask->mask, netmask->bits); +#endif + default: + return 0; + } +} diff --git a/src/hash.c b/src/hash.c index 8ff5daf5d..a828e7adb 100644 --- a/src/hash.c +++ b/src/hash.c @@ -846,7 +846,7 @@ void del_throttling_bucket(struct ThrottlingBucket *bucket) * @retval 2 Allowed, not in list or is an exception. * @see add_connection() */ -int throttle_can_connect(struct IN_ADDR *in) +int throttle_can_connect(aClient *sptr, struct IN_ADDR *in) { struct ThrottlingBucket *b; @@ -857,7 +857,7 @@ int throttle_can_connect(struct IN_ADDR *in) return 1; else { - if (Find_except(Inet_ia2p(in), CONF_EXCEPT_THROTTLE)) + if (Find_except(sptr, Inet_ia2p(in), CONF_EXCEPT_THROTTLE)) return 2; b->count++; if (b->count > (THROTTLING_COUNT ? THROTTLING_COUNT : 3)) diff --git a/src/ircd.c b/src/ircd.c index 58510fff4..17ff8f086 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -545,7 +545,7 @@ extern TS check_pings(TS currenttime) * If it's a user, we check for CONF_BAN_USER */ bconf = - Find_ban(make_user_host(cptr-> + Find_ban(cptr, make_user_host(cptr-> user ? cptr->user->username : cptr-> username, cptr->user ? cptr->user->realhost : cptr-> @@ -555,7 +555,7 @@ extern TS check_pings(TS currenttime) if (!killflag && !IsAnOper(cptr) && (bconf = - Find_ban(cptr->info, CONF_BAN_REALNAME))) { + Find_ban(NULL, cptr->info, CONF_BAN_REALNAME))) { killflag++; } @@ -565,7 +565,7 @@ extern TS check_pings(TS currenttime) */ if (!killflag) if ((bconf = - Find_ban(Inet_ia2p(&cptr->ip), + Find_ban(cptr, Inet_ia2p(&cptr->ip), CONF_BAN_IP))) killflag++; if (killflag) { @@ -1128,13 +1128,6 @@ int InitwIRCD(int argc, char *argv[]) } #endif exit(0); - case 'W':{ - struct IN_ADDR bah; - int bit; - parse_netmask("255.255.255.255/8", &bah, &bit); - printf("%s - %d\n", Inet_ia2p(&bah), bit); - exit(0); - } case 'C': config_verbose = atoi(p); break; diff --git a/src/modules/m_chgname.c b/src/modules/m_chgname.c index 1e76f6a8b..34d3ca1d6 100644 --- a/src/modules/m_chgname.c +++ b/src/modules/m_chgname.c @@ -163,7 +163,7 @@ DLLFUNC int m_chgname(aClient *cptr, aClient *sptr, int parc, char *parv[]) /* set the realname first to make n:line checking work */ ircsprintf(acptr->info, "%s", parv[2]); /* only check for n:lines if the person who's name is being changed is not an oper */ - if (!IsAnOper(acptr) && Find_ban(acptr->info, CONF_BAN_REALNAME)) { + if (!IsAnOper(acptr) && Find_ban(NULL, acptr->info, CONF_BAN_REALNAME)) { int xx; xx = exit_client(cptr, sptr, &me, diff --git a/src/modules/m_server.c b/src/modules/m_server.c index 1f0b248ea..0d02fffa1 100644 --- a/src/modules/m_server.c +++ b/src/modules/m_server.c @@ -268,7 +268,7 @@ nohostcheck: return exit_client(acptr, acptr, acptr, "Server Exists"); } - if ((bconf = Find_ban(servername, CONF_BAN_SERVER))) + if ((bconf = Find_ban(NULL, servername, CONF_BAN_SERVER))) { sendto_realops ("Cancelling link %s, banned server", @@ -471,7 +471,7 @@ CMD_FUNC(m_server_remote) return 0; } } - if ((bconf = Find_ban(servername, CONF_BAN_SERVER))) + if ((bconf = Find_ban(NULL, servername, CONF_BAN_SERVER))) { sendto_realops ("Cancelling link %s, banned server %s", diff --git a/src/modules/m_setname.c b/src/modules/m_setname.c index d9283bb8e..0c9d05af2 100644 --- a/src/modules/m_setname.c +++ b/src/modules/m_setname.c @@ -116,7 +116,7 @@ DLLFUNC int m_setname(aClient *cptr, aClient *sptr, int parc, char *parv[]) { else ircsprintf(sptr->info, "%s", parv[1]); /* Check for n:lines here too */ - if (!IsAnOper(sptr) && Find_ban(sptr->info, CONF_BAN_REALNAME)) + if (!IsAnOper(sptr) && Find_ban(NULL, sptr->info, CONF_BAN_REALNAME)) { int xx; xx = diff --git a/src/modules/m_svsnline.c b/src/modules/m_svsnline.c index 8a367b5a4..9e3ca5033 100644 --- a/src/modules/m_svsnline.c +++ b/src/modules/m_svsnline.c @@ -137,7 +137,7 @@ DLLFUNC int m_svsnline(aClient *cptr, aClient *sptr, int parc, char *parv[]) if (parc < 4) return 0; - if (!Find_banEx(parv[3], CONF_BAN_REALNAME, CONF_BAN_TYPE_AKILL)) + if (!Find_banEx(NULL, parv[3], CONF_BAN_REALNAME, CONF_BAN_TYPE_AKILL)) { bconf = (ConfigItem_ban *) MyMallocEx(sizeof(ConfigItem_ban)); bconf->flag.type = CONF_BAN_REALNAME; diff --git a/src/s_bsd.c b/src/s_bsd.c index df15d34d9..a5ccfa417 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -1252,7 +1252,7 @@ add_con_refuse: } } - if ((bconf = Find_ban(acptr->sockhost, CONF_BAN_IP))) { + if ((bconf = Find_ban(acptr, Inet_ia2p(&acptr->ip), CONF_BAN_IP))) { if (bconf) { ircsprintf(zlinebuf, @@ -1278,7 +1278,7 @@ add_con_refuse: else { int val; - if (!(val = throttle_can_connect(&acptr->ip))) + if (!(val = throttle_can_connect(acptr, &acptr->ip))) { ircsprintf(zlinebuf, "ERROR :Closing Link: [%s] (Throttled: Reconnecting too fast) -" diff --git a/src/s_conf.c b/src/s_conf.c index 1c1dc444d..b56c74afa 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -1479,11 +1479,11 @@ char *encoded; { if (tk->type != TKL_SPAMF) continue; /* global entry or something else.. */ - if (!strcmp(tk->spamf->tkl_reason, "")) + if (!strcmp(tk->ptr.spamf->tkl_reason, "")) { - MyFree(tk->spamf->tkl_reason); - tk->spamf->tkl_reason = strdup(encoded); - tk->spamf->tkl_duration = SPAMFILTER_BAN_TIME; + MyFree(tk->ptr.spamf->tkl_reason); + tk->ptr.spamf->tkl_reason = strdup(encoded); + tk->ptr.spamf->tkl_duration = SPAMFILTER_BAN_TIME; } /* This one is even more ugly, but our config crap is VERY confusing :[ */ if (!tk->setby) @@ -1726,6 +1726,8 @@ void config_rehash() next = (ListStruct *)allow_ptr->next; ircfree(allow_ptr->ip); ircfree(allow_ptr->hostname); + if (allow_ptr->netmask) + MyFree(allow_ptr->netmask); Auth_DeleteAuthStruct(allow_ptr->auth); DelListItem(allow_ptr, conf_allow); MyFree(allow_ptr); @@ -1734,6 +1736,8 @@ void config_rehash() { next = (ListStruct *)except_ptr->next; ircfree(except_ptr->mask); + if (except_ptr->netmask) + MyFree(except_ptr->netmask); DelListItem(except_ptr, conf_except); MyFree(except_ptr); } @@ -1744,6 +1748,8 @@ void config_rehash() { ircfree(ban_ptr->mask); ircfree(ban_ptr->reason); + if (ban_ptr->netmask) + MyFree(ban_ptr->netmask); DelListItem(ban_ptr, conf_ban); MyFree(ban_ptr); } @@ -2319,7 +2325,7 @@ ConfigItem_ulines *Find_uline(char *host) { } -ConfigItem_except *Find_except(char *host, short type) { +ConfigItem_except *Find_except(aClient *sptr, char *host, short type) { ConfigItem_except *excepts; if (!host) @@ -2327,8 +2333,10 @@ ConfigItem_except *Find_except(char *host, short type) { for(excepts = conf_except; excepts; excepts =(ConfigItem_except *) excepts->next) { if (excepts->flag.type == type) - if (!match(excepts->mask, host)) + { + if (match_ip(sptr->ip, host, excepts->mask, excepts->netmask)) return excepts; + } } return NULL; } @@ -2375,7 +2383,7 @@ ConfigItem_link *Find_link(char *username, } -ConfigItem_ban *Find_ban(char *host, short type) +ConfigItem_ban *Find_ban(aClient *sptr, char *host, short type) { ConfigItem_ban *ban; @@ -2386,17 +2394,18 @@ ConfigItem_ban *Find_ban(char *host, short type) for (ban = conf_ban; ban; ban = (ConfigItem_ban *) ban->next) if (ban->flag.type == type) - if (!match(ban->mask, host)) { + if (match_ip(sptr->ip, host, ban->mask, ban->netmask)) + { /* Person got a exception */ if ((type == CONF_BAN_USER || type == CONF_BAN_IP) - && Find_except(host, CONF_EXCEPT_BAN)) + && Find_except(sptr, host, CONF_EXCEPT_BAN)) return NULL; return ban; } return NULL; } -ConfigItem_ban *Find_banEx(char *host, short type, short type2) +ConfigItem_ban *Find_banEx(aClient *sptr, char *host, short type, short type2) { ConfigItem_ban *ban; @@ -2407,9 +2416,9 @@ ConfigItem_ban *Find_banEx(char *host, short type, short type2) for (ban = conf_ban; ban; ban = (ConfigItem_ban *) ban->next) if ((ban->flag.type == type) && (ban->flag.type2 == type2)) - if (!match(ban->mask, host)) { + if (match_ip(sptr->ip, host, ban->mask, ban->netmask)) { /* Person got a exception */ - if (Find_except(host, type)) + if (Find_except(sptr, host, type)) return NULL; return ban; } @@ -2479,7 +2488,8 @@ int AllowClient(aClient *cptr, struct hostent *hp, char *sockhost, char *usernam else *uhost = '\0'; (void)strncat(uhost, sockhost, sizeof(uhost) - strlen(uhost)); - if (!match(aconf->ip, uhost)) + /* Check the IP */ + if (match_ip(cptr->ip, uhost, aconf->ip, aconf->netmask)) goto attach; /* Hmm, localhost is a special case, hp == NULL and sockhost contains @@ -3827,7 +3837,7 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce) ConfigEntry *cep, *cepp; ConfigItem_allow *allow; Hook *h; - + struct irc_netmask tmp; if (ce->ce_vardata) { if (!strcmp(ce->ce_vardata, "channel")) @@ -3846,10 +3856,17 @@ int _conf_allow(ConfigFile *conf, ConfigEntry *ce) return 0; } } - allow = MyMallocEx(sizeof(ConfigItem_allow)); cep = config_find_entry(ce->ce_entries, "ip"); allow->ip = strdup(cep->ce_vardata); + /* CIDR */ + tmp.type = parse_netmask(allow->ip, &tmp); + if (tmp.type != HM_HOST) + { + allow->netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, allow->netmask, sizeof(struct irc_netmask)); + } + cep = config_find_entry(ce->ce_entries, "hostname"); allow->hostname = strdup(cep->ce_vardata); if ((cep = config_find_entry(ce->ce_entries, "password"))) @@ -4218,6 +4235,7 @@ int _conf_except(ConfigFile *conf, ConfigEntry *ce) ConfigEntry *cep, *cep2, *cep3; ConfigItem_except *ca; Hook *h; + struct irc_netmask tmp; if (!strcmp(ce->ce_vardata, "ban")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) @@ -4225,6 +4243,12 @@ int _conf_except(ConfigFile *conf, ConfigEntry *ce) if (!strcmp(cep->ce_varname, "mask")) { ca = MyMallocEx(sizeof(ConfigItem_except)); ca->mask = strdup(cep->ce_vardata); + tmp.type = parse_netmask(ca->mask, &tmp); + if (tmp.type != HM_HOST) + { + ca->netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, ca->netmask, sizeof(struct irc_netmask)); + } ca->flag.type = CONF_EXCEPT_BAN; AddListItem(ca, conf_except); } @@ -4239,6 +4263,12 @@ int _conf_except(ConfigFile *conf, ConfigEntry *ce) if (!strcmp(cep->ce_varname, "mask")) { ca = MyMallocEx(sizeof(ConfigItem_except)); ca->mask = strdup(cep->ce_vardata); + tmp.type = parse_netmask(ca->mask, &tmp); + if (tmp.type != HM_HOST) + { + ca->netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, ca->netmask, sizeof(struct irc_netmask)); + } ca->flag.type = CONF_EXCEPT_THROTTLE; AddListItem(ca, conf_except); } @@ -4266,6 +4296,15 @@ int _conf_except(ConfigFile *conf, ConfigEntry *ce) else {} + if (ca->type & TKL_KILL || ca->type & TKL_ZAP || ca->type & TKL_SHUN) + { + tmp.type = parse_netmask(ca->mask, &tmp); + if (tmp.type != HM_HOST) + { + ca->netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, ca->netmask, sizeof(struct irc_netmask)); + } + } ca->flag.type = CONF_EXCEPT_TKL; AddListItem(ca, conf_except); } @@ -4930,18 +4969,18 @@ int _conf_spamfilter(ConfigFile *conf, ConfigEntry *ce) nl->hostmask = strdup(cep->ce_vardata); nl->setby = BadPtr(me.name) ? NULL : strdup(me.name); /* Hmm! */ - nl->spamf = unreal_buildspamfilter(word); - nl->spamf->action = action; + nl->ptr.spamf = unreal_buildspamfilter(word); + nl->ptr.spamf->action = action; if ((cep = config_find_entry(ce->ce_entries, "reason"))) - nl->spamf->tkl_reason = strdup(unreal_encodespace(cep->ce_vardata)); + nl->ptr.spamf->tkl_reason = strdup(unreal_encodespace(cep->ce_vardata)); else - nl->spamf->tkl_reason = strdup(""); + nl->ptr.spamf->tkl_reason = strdup(""); if ((cep = config_find_entry(ce->ce_entries, "ban-time"))) - nl->spamf->tkl_duration = config_checkval(cep->ce_vardata, CFG_TIME); + nl->ptr.spamf->tkl_duration = config_checkval(cep->ce_vardata, CFG_TIME); else - nl->spamf->tkl_duration = (SPAMFILTER_BAN_TIME ? SPAMFILTER_BAN_TIME : 86400); + nl->ptr.spamf->tkl_duration = (SPAMFILTER_BAN_TIME ? SPAMFILTER_BAN_TIME : 86400); AddListItem(nl, tklines[tkl_hash('f')]); return 1; @@ -5500,8 +5539,17 @@ int _conf_ban(ConfigFile *conf, ConfigEntry *ce) } cep = config_find_entry(ce->ce_entries, "mask"); ca->mask = strdup(cep->ce_vardata); - if (ca->flag.type == CONF_BAN_IP) - ca->masktype = parse_netmask(ca->mask, &ca->netmask, &ca->bits); + if (ca->flag.type == CONF_BAN_IP || ca->flag.type == CONF_BAN_USER) + { + struct irc_netmask tmp; + tmp.type = parse_netmask(ca->mask, &tmp); + if (tmp.type != HM_HOST) + { + ca->netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, ca->netmask, sizeof(struct irc_netmask)); + } + } + cep = config_find_entry(ce->ce_entries, "reason"); ca->reason = strdup(cep->ce_vardata); cep = config_find_entry(ce->ce_entries, "action"); diff --git a/src/s_kline.c b/src/s_kline.c index 7affb1e9e..b88b3f1cb 100644 --- a/src/s_kline.c +++ b/src/s_kline.c @@ -142,17 +142,26 @@ int tkl_add_line(int type, char *usermask, char *hostmask, char *reason, char * { /* Need to set some additional flags like 'targets' and 'action'.. */ nl->subtype = spamfilter_gettargets(usermask, NULL); - nl->spamf = unreal_buildspamfilter(reason); - nl->spamf->action = banact_chartoval(*hostmask); + nl->ptr.spamf = unreal_buildspamfilter(reason); + nl->ptr.spamf->action = banact_chartoval(*hostmask); nl->expire_at = 0; /* temporary spamfilters are NOT supported! (makes no sense) */ if (!spamf_tkl_reason) { /* no exttkl support, use default values... */ - nl->spamf->tkl_duration = SPAMFILTER_BAN_TIME; - nl->spamf->tkl_reason = strdup(unreal_encodespace(SPAMFILTER_BAN_REASON)); + nl->ptr.spamf->tkl_duration = SPAMFILTER_BAN_TIME; + nl->ptr.spamf->tkl_reason = strdup(unreal_encodespace(SPAMFILTER_BAN_REASON)); } else { - nl->spamf->tkl_duration = spamf_tkl_duration; - nl->spamf->tkl_reason = strdup(spamf_tkl_reason); /* already encoded */ + nl->ptr.spamf->tkl_duration = spamf_tkl_duration; + nl->ptr.spamf->tkl_reason = strdup(spamf_tkl_reason); /* already encoded */ + } + } + else if (type & TKL_KILL || type & TKL_ZAP || type & TKL_SHUN) + { + struct irc_netmask tmp; + if ((tmp.type = parse_netmask(nl->hostmask, &tmp)) != HM_HOST) + { + nl->ptr.netmask = MyMallocEx(sizeof(struct irc_netmask)); + bcopy(&tmp, nl->ptr.netmask, sizeof(struct irc_netmask)); } } index = tkl_hash(tkl_typetochar(type)); @@ -173,13 +182,16 @@ aTKline *tkl_del_line(aTKline *tkl) MyFree(p->hostmask); MyFree(p->reason); MyFree(p->setby); - if (p->spamf) + if (p->type & TKL_SPAMF && p->ptr.spamf) { - regfree(&p->spamf->expr); - if (p->spamf->tkl_reason) - MyFree(p->spamf->tkl_reason); - MyFree(p->spamf); + regfree(&p->ptr.spamf->expr); + if (p->ptr.spamf->tkl_reason) + MyFree(p->ptr.spamf->tkl_reason); + MyFree(p->ptr.spamf); } + if ((p->type & TKL_KILL || p->type & TKL_ZAP || p->type & TKL_SHUN) + && p->ptr.netmask) + MyFree(p->ptr.netmask); DelListItem(p, tklines[index]); MyFree(p); return q; @@ -364,12 +376,28 @@ int find_tkline_match(aClient *cptr, int xx) { if ((lp->type & TKL_SHUN) || (lp->type & TKL_SPAMF) || (lp->type & TKL_NICK)) continue; + + /* If it's tangy and brown, you're in CIDR town! */ + if (lp->ptr.netmask) + { + if (match_ip(cptr->ip, NULL, NULL, lp->ptr.netmask) && + !match(lp->usermask, cname)) + { + points = 1; + break; + } + continue; + } if (!match(lp->usermask, cname) && !match(lp->hostmask, chost)) + { points = 1; - if (!match(lp->usermask, cname) && !match(lp->hostmask, cip)) - points = 1; - if (points) break; + } + if (!match(lp->usermask, cname) && !match(lp->hostmask, cip)) + { + points = 1; + break; + } } if (points) break; @@ -387,7 +415,11 @@ int find_tkline_match(aClient *cptr, int xx) if (excepts->flag.type != match_type || (match_type == CONF_EXCEPT_TKL && excepts->type != lp->type)) continue; - if (!match(excepts->mask, host) || !match(excepts->mask, host2)) + + if (excepts->netmask) + if (match_ip(cptr->ip, NULL, NULL, excepts->netmask)) + return 1; + else if (!match(excepts->mask, host) || !match(excepts->mask, host2)) return 1; } @@ -468,12 +500,28 @@ int find_shun(aClient *cptr) if (!(lp->type & TKL_SHUN)) continue; + /* CIDR */ + if (lp->ptr.netmask) + { + if (match_ip(cptr->ip, NULL, NULL, lp->ptr.netmask) && + !match(lp->usermask, cname)) + { + points = 1; + break; + } + continue; + } + if (!match(lp->usermask, cname) && !match(lp->hostmask, chost)) + { points = 1; - if (!match(lp->usermask, cname) && !match(lp->hostmask, cip)) - points = 1; - if (points == 1) break; + } + if (!match(lp->usermask, cname) && !match(lp->hostmask, cip)) + { + points = 1; + break; + } else points = 0; } @@ -483,11 +531,15 @@ int find_shun(aClient *cptr) strcpy(host, make_user_host(cname, chost)); strcpy(host2, make_user_host(cname, cip)); match_type = CONF_EXCEPT_TKL; + for (excepts = conf_except; excepts; excepts = (ConfigItem_except *)excepts->next) { if (excepts->flag.type != match_type || (match_type == CONF_EXCEPT_TKL && excepts->type != lp->type)) continue; - if (!match(excepts->mask, host) || !match(excepts->mask, host2)) + if (excepts->netmask) + if (match_ip(cptr->ip, NULL, NULL, excepts->netmask)) + return 1; + else if (!match(excepts->mask, host) || !match(excepts->mask, host2)) return 1; } @@ -538,7 +590,10 @@ aTKline *find_qline(aClient *cptr, char *nick, int *ishold) for (excepts = conf_except; excepts; excepts = (ConfigItem_except *)excepts->next) { if (excepts->flag.type != CONF_EXCEPT_TKL || excepts->type != TKL_NICK) continue; - if (!match(excepts->mask, host) || !match(excepts->mask, host2)) + if (excepts->netmask) + if (match_ip(cptr->ip, NULL, NULL, excepts->netmask)) + return 1; + else if (!match(excepts->mask, host) || !match(excepts->mask, host2)) return NULL; } return lp; @@ -564,12 +619,17 @@ int find_tkline_match_zap(aClient *cptr) { if (lp->type & TKL_ZAP) { - if (!match(lp->hostmask, cip)) + if ((lp->ptr.netmask && match_ip(cptr->ip, NULL, NULL, lp->ptr.netmask)) + || !match(lp->hostmask, cip)) { + for (excepts = conf_except; excepts; excepts = (ConfigItem_except *)excepts->next) { if (excepts->flag.type != CONF_EXCEPT_TKL || excepts->type != lp->type) continue; - if (!match(excepts->mask, cip)) + if (excepts->netmask) + if (match_ip(cptr->ip, NULL, NULL, excepts->netmask)) + return -1; + else if (!match(excepts->mask, cip)) return -1; } for (tmphook = Hooks[HOOKTYPE_TKL_EXCEPT]; tmphook; tmphook = tmphook->next) @@ -763,10 +823,10 @@ void tkl_stats(aClient *cptr, int type, char *para) cptr->name, (tk->type & TKL_GLOBAL) ? 'F' : 'f', spamfilter_target_inttostring(tk->subtype), - banact_valtostring(tk->spamf->action), + banact_valtostring(tk->ptr.spamf->action), (tk->expire_at != 0) ? (tk->expire_at - curtime) : 0, curtime - tk->set_at, - tk->spamf->tkl_duration, tk->spamf->tkl_reason, + tk->ptr.spamf->tkl_duration, tk->ptr.spamf->tkl_reason, tk->setby, tk->reason); } @@ -808,7 +868,7 @@ void tkl_synch(aClient *sptr) typ, tk->usermask, tk->hostmask, tk->setby, tk->expire_at, tk->set_at, - tk->spamf->tkl_duration, tk->spamf->tkl_reason, + tk->ptr.spamf->tkl_duration, tk->ptr.spamf->tkl_reason, tk->reason); } else sendto_one(sptr, @@ -984,8 +1044,8 @@ int m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[]) MSG_TKL, TOK_TKL, "%s %s %s %s %s %ld %ld %ld %s :%s", parv[1], parv[2], parv[3], parv[4], - tk->setby, tk->expire_at, tk->set_at, tk->spamf->tkl_duration, - tk->spamf->tkl_reason, tk->reason); + tk->setby, tk->expire_at, tk->set_at, tk->ptr.spamf->tkl_duration, + tk->ptr.spamf->tkl_reason, tk->reason); } else sendto_serv_butone(cptr, ":%s TKL %s %s %s %s %s %ld %ld :%s", sptr->name, @@ -1372,7 +1432,7 @@ char *str = (char *)StripControlCodes(str_in); { if (!(tk->subtype & type)) continue; - if (!regexec(&tk->spamf->expr, str, 0, NULL, 0)) + if (!regexec(&tk->ptr.spamf->expr, str, 0, NULL, 0)) { /* matched! */ char buf[1024]; @@ -1391,48 +1451,48 @@ char *str = (char *)StripControlCodes(str_in); sptr->name, sptr->user->username, sptr->user->realhost, tk->reason, spamfilter_inttostring_long(type), targetbuf, str, - unreal_decodespace(tk->spamf->tkl_reason)); + unreal_decodespace(tk->ptr.spamf->tkl_reason)); sendto_snomask(SNO_SPAMF, "%s", buf); sendto_serv_butone_token(NULL, me.name, MSG_SENDSNO, TOK_SENDSNO, "S :%s", buf); - if (tk->spamf->action == BAN_ACT_BLOCK) + if (tk->ptr.spamf->action == BAN_ACT_BLOCK) { switch(type) { case SPAMF_USERMSG: case SPAMF_USERNOTICE: sendnotice(sptr, "Message to %s blocked: %s", - target, unreal_decodespace(tk->spamf->tkl_reason)); + target, unreal_decodespace(tk->ptr.spamf->tkl_reason)); break; case SPAMF_CHANMSG: case SPAMF_CHANNOTICE: sendto_one(sptr, ":%s 404 %s %s :Message blocked: %s", me.name, sptr->name, target, - unreal_decodespace(tk->spamf->tkl_reason)); + unreal_decodespace(tk->ptr.spamf->tkl_reason)); break; case SPAMF_DCC: sendnotice(sptr, "DCC to %s blocked: %s", - target, unreal_decodespace(tk->spamf->tkl_reason)); + target, unreal_decodespace(tk->ptr.spamf->tkl_reason)); break; default: break; } return -1; } else - if (tk->spamf->action == BAN_ACT_DCCBLOCK) + if (tk->ptr.spamf->action == BAN_ACT_DCCBLOCK) { if (type == SPAMF_DCC) { sendnotice(sptr, "DCC to %s blocked: %s", - target, unreal_decodespace(tk->spamf->tkl_reason)); + target, unreal_decodespace(tk->ptr.spamf->tkl_reason)); sendnotice(sptr, "*** You have been blocked from sending files, " "reconnect to regain permission to send files"); sptr->flags |= FLAGS_DCCBLOCK; } return -1; } else - if (tk->spamf->action == BAN_ACT_VIRUSCHAN) + if (tk->ptr.spamf->action == BAN_ACT_VIRUSCHAN) { char *xparv[3], chbuf[CHANNELLEN + 16]; aChannel *chptr; @@ -1451,7 +1511,7 @@ char *str = (char *)StripControlCodes(str_in); if (ret == FLUSH_BUFFER) return FLUSH_BUFFER; /* don't ask me how we could have died... */ sendnotice(sptr, "You are now restricted to talking in %s: %s", - SPAMFILTER_VIRUSCHAN, unreal_decodespace(tk->spamf->tkl_reason)); + SPAMFILTER_VIRUSCHAN, unreal_decodespace(tk->ptr.spamf->tkl_reason)); /* todo: send notice to channel? */ chptr = find_channel(SPAMFILTER_VIRUSCHAN, NULL); if (chptr) @@ -1459,15 +1519,15 @@ char *str = (char *)StripControlCodes(str_in); ircsprintf(chbuf, "@%s", chptr->chname); ircsprintf(buf, "[Spamfilter] %s matched filter '%s' [%s%s] [%s]", sptr->name, tk->reason, spamfilter_inttostring_long(type), targetbuf, - unreal_decodespace(tk->spamf->tkl_reason)); + unreal_decodespace(tk->ptr.spamf->tkl_reason)); sendto_channelprefix_butone_tok(NULL, &me, chptr, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER, MSG_NOTICE, TOK_NOTICE, chbuf, buf, 0); } SetVirus(sptr); return -1; } else - return place_host_ban(sptr, tk->spamf->action, - unreal_decodespace(tk->spamf->tkl_reason), tk->spamf->tkl_duration); + return place_host_ban(sptr, tk->ptr.spamf->action, + unreal_decodespace(tk->ptr.spamf->tkl_reason), tk->ptr.spamf->tkl_duration); } } return 0; diff --git a/src/s_user.c b/src/s_user.c index 6da912607..72f1a49a3 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -933,7 +933,7 @@ int register_user(aClient *cptr, aClient *sptr, char *nick, char *username, char * following block for the benefit of time-dependent K:-lines */ if ((bconf = - Find_ban(make_user_host(user->username, user->realhost), + Find_ban(sptr, make_user_host(user->username, user->realhost), CONF_BAN_USER))) { ircstp->is_ref++; @@ -945,7 +945,7 @@ int register_user(aClient *cptr, aClient *sptr, char *nick, char *username, char KLINE_ADDRESS); return exit_client(cptr, cptr, cptr, "You are banned"); } - if ((bconf = Find_ban(sptr->info, CONF_BAN_REALNAME))) + if ((bconf = Find_ban(NULL, sptr->info, CONF_BAN_REALNAME))) { ircstp->is_ref++; sendto_one(cptr, diff --git a/src/webtv.c b/src/webtv.c index 8f91a99cc..bc792a036 100644 --- a/src/webtv.c +++ b/src/webtv.c @@ -417,7 +417,7 @@ int ban_version(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; if (parv[1][len-1] == '\1') parv[1][len-1] = '\0'; - if ((ban = Find_ban(parv[1], CONF_BAN_VERSION))) + if ((ban = Find_ban(NULL, parv[1], CONF_BAN_VERSION))) return place_host_ban(sptr, ban->action, ban->reason, BAN_VERSION_TKL_TIME); return 0; }