diff -ru irc2.11.1p1/common/send.c irc2.11.1p1+v6/common/send.c --- irc2.11.1p1/common/send.c 2005-02-22 17:34:02.000000000 +0100 +++ irc2.11.1p1+v6/common/send.c 2005-06-01 07:18:29.000000000 +0200 @@ -1298,6 +1298,8 @@ case EXITC_GUHMAX: anyptr="G u@h max"; break; case EXITC_LHMAX: anyptr="L IP max"; break; case EXITC_LUHMAX: anyptr="L u@h max"; break; +/* case EXITC_RHMAX: anyptr="R IP max"; break; + case EXITC_RUHMAX: anyptr="R u@h max"; break; */ case EXITC_AREF: case EXITC_AREFQ: anyptr=" Denied "; break; case EXITC_KLINE: anyptr=" K lined "; break; diff -ru irc2.11.1p1/common/struct_def.h irc2.11.1p1+v6/common/struct_def.h --- irc2.11.1p1/common/struct_def.h 2005-03-30 01:23:49.000000000 +0200 +++ irc2.11.1p1+v6/common/struct_def.h 2005-06-01 03:31:08.000000000 +0200 @@ -304,6 +304,7 @@ struct CPing *ping; time_t hold; /* Hold action until this time (calendar time) */ char *source_ip; + int chkmask; #ifndef VMSP aClass *class; /* Class of connection */ #endif diff -ru irc2.11.1p1/common/support.c irc2.11.1p1+v6/common/support.c --- irc2.11.1p1/common/support.c 2005-02-04 19:08:48.000000000 +0100 +++ irc2.11.1p1+v6/common/support.c 2005-06-01 10:34:50.000000000 +0200 @@ -742,7 +742,7 @@ char *make_version(void) { int ve, re, mi, dv, pl; - char ver[15]; + char ver[15+2]; /* +r */ sscanf(PATCHLEVEL, "%2d%2d%2d%2d%2d", &ve, &re, &mi, &dv, &pl); /* version & revision */ @@ -754,6 +754,7 @@ sprintf(ver + strlen(ver), "%c%d", DEVLEVEL, dv); if (pl) /* patchlevel */ sprintf(ver + strlen(ver), "p%d", pl); + strcat(ver, "+r"); return mystrdup(ver); } diff -ru irc2.11.1p1/ircd/list.c irc2.11.1p1+v6/ircd/list.c --- irc2.11.1p1/ircd/list.c 2005-01-30 14:42:03.000000000 +0100 +++ irc2.11.1p1+v6/ircd/list.c 2005-06-01 06:46:15.000000000 +0200 @@ -584,6 +584,11 @@ aconf->hold = time(NULL); aconf->source_ip = NULL; aconf->flags = 0L; +#ifdef INET6 + aconf->chkmask = 128; +#else + aconf->chkmask = 32; +#endif Class(aconf) = NULL; return (aconf); } diff -ru irc2.11.1p1/ircd/s_conf.c irc2.11.1p1+v6/ircd/s_conf.c --- irc2.11.1p1/ircd/s_conf.c 2005-04-14 01:14:38.000000000 +0200 +++ irc2.11.1p1+v6/ircd/s_conf.c 2005-06-01 08:46:27.000000000 +0200 @@ -354,6 +354,34 @@ } } +static int match_ip(struct IN_ADDR *addr1, struct IN_ADDR *addr2, int m) +{ + u_long lmask; +#ifdef INET6 + int j; + + j = m & 0x1F; /* number not mutliple of 32 bits */ + m >>= 5; /* number of 32 bits */ + + if (m && memcmp((void *)(addr1->s6_addr), + (void *)(addr2->s6_addr), m << 2)) + return 1; + + if (j) + { + lmask = htonl((u_long)0xffffffffL << (32 - j)); + if ((((u_int32_t *)(addr1->s6_addr))[m] ^ + ((u_int32_t *)(addr2->s6_addr))[m]) & lmask) + return 1; + } + + return 0; +#else + lmask = htonl((u_long)0xffffffffL << (32 - m)); + return ((addr1->s_addr ^ addr2->s_addr) & lmask) ? 1 : 0; +#endif +} + /* * Match address by #IP bitmask (10.11.12.128/27) * Now should work for IPv6 too. @@ -394,9 +422,7 @@ #ifndef INET6 if (m < 0 || m > 32) goto badmask; - lmask = htonl((u_long)0xffffffffL << (32 - m)); addr.s_addr = inetaddr(mask); - return ((addr.s_addr ^ cptr->ip.s_addr) & lmask) ? 1 : 0; #else if (m < 0 || m > 128) goto badmask; @@ -414,24 +440,10 @@ if (m <= 96) goto badmask; } +#endif - j = m & 0x1F; /* number not mutliple of 32 bits */ - m >>= 5; /* number of 32 bits */ - - if (m && memcmp((void *)(addr.s6_addr), - (void *)(cptr->ip.s6_addr), m << 2)) - return 1; - - if (j) - { - lmask = htonl((u_long)0xffffffffL << (32 - j)); - if ((((u_int32_t *)(addr.s6_addr))[m] ^ - ((u_int32_t *)(cptr->ip.s6_addr))[m]) & lmask) - return 1; - } + return match_ip(&addr, &cptr->ip, m); - return 0; -#endif badmask: if (maskwithusername) sendto_flag(SCH_ERROR, "Ignoring bad mask: %s", omask); @@ -720,12 +732,13 @@ { int hcnt = 0, ucnt = 0; int ghcnt = 0, gucnt = 0; + int i, m; anUser *user = NULL; /* check on local/global limits per host and per user@host */ /* ** local limits first to save CPU if any is hit. - ** host check is done on the IP address. + ** host check is done on the HOST, and NOT the IP address. ** user check is done on the IDENT reply. */ if (ConfMaxHLocal(aconf) > 0 || ConfMaxUHLocal(aconf) > 0 || @@ -734,7 +747,8 @@ for ((user = hash_find_hostname(cptr->sockhost, NULL)); user; user = user->hhnext) { - if (!mycmp(cptr->sockhost, user->host)) + if (!mycmp(cptr->user->sip, user->sip) && + !mycmp(cptr->sockhost, user->host)) { ghcnt++; if (MyConnect(user->bcptr)) @@ -779,6 +793,54 @@ } } } + + + m = aconf->chkmask; +#ifdef INET6 + if (IN6_IS_ADDR_V4MAPPED(&cptr->ip)) + { + if (m <= 32) + m += 96; + if (m <= 96) + m = 128; + } + + if(m < 128) +#else + if(m < 32) +#endif + { + for(i = 0; i < highest_fd; i++) + { + aClient *acptr; + if(!(acptr = local[i]) || !IsPerson(acptr)) + continue; + if(!match_ip(&acptr->ip, &cptr->ip, m)) + { + hcnt++; + ghcnt++; + if (!mycmp(acptr->user->username, + cptr->user->username + )) + { + ucnt++; + gucnt++; + } + + if (ConfMaxUHLocal(aconf) > 0 && + ucnt >= ConfMaxUHLocal(aconf)) + { + return -10; /* EXITC_RUHMAX */ + } + + if (ConfMaxHLocal(aconf) > 0 && + hcnt >= ConfMaxHLocal(aconf)) + { + return -9; /* EXITC_RHMAX */ + } + } + } + } } } @@ -1669,6 +1731,20 @@ pline_flags_parse(tmp3)); } + if(tmp4 && aconf->status == CONF_CLIENT) + { + aconf->chkmask = atoi(tmp4); +#ifndef INET6 + if (aconf->chkmask < 0 || aconf->chkmask > 32 || + (aconf->chkmask == 0 && !isdigit(*tmp4))) + aconf->chkmask = 32; +#else + if (aconf->chkmask < 1 || aconf->chkmask > 128 || + (aconf->chkmask == 0 && !isdigit(*tmp4))) + aconf->chkmask = 128; +#endif + } + /* trying to find exact conf line in already existing * conf, so we don't delete old one, just update it */ if ( @@ -1686,6 +1762,7 @@ * (from lowercase i:lines). In any case we * don't want old flags to remain. --B. */ bconf->flags = aconf->flags; + bconf->chkmask = aconf->chkmask; /* in case class was changed */ if (aconf->status == CONF_CLIENT && aconf->class != bconf->class) diff -ru irc2.11.1p1/ircd/s_user.c irc2.11.1p1+v6/ircd/s_user.c --- irc2.11.1p1/ircd/s_user.c 2005-04-14 01:10:37.000000000 +0200 +++ irc2.11.1p1+v6/ircd/s_user.c 2005-06-01 07:19:27.000000000 +0200 @@ -484,8 +484,10 @@ if ((i = check_client(sptr))) { struct msg_set { char shortm; char *longm; }; -#define EXIT_MSG_COUNT 8 +#define EXIT_MSG_COUNT 10 static struct msg_set exit_msg[EXIT_MSG_COUNT] = { + { EXITC_LUHMAX, "Too many user connections (range)" }, + { EXITC_LHMAX, "Too many host connections (range)" }, { EXITC_BADPASS, "Bad password" }, { EXITC_GUHMAX, "Too many user connections (global)" }, { EXITC_GHMAX, "Too many host connections (global)" },