
This patch adds an address family field to each client structure, which is now checked in various places that expect to only be working with IPv4 addresses, such as CIDR masking for /who and /rwho. The IP address 0.0.0.1 is reserved to indicate that a non-IPv4 address was passed through a server that does not have the NICKIPSTR capability. --- include/struct.h | 6 +++++- src/clones.c | 12 ++++++++---- src/klines.c | 9 +++++++-- src/m_nick.c | 4 ++-- src/m_rwho.c | 26 ++++++++++++++++++-------- src/m_server.c | 3 ++- src/m_who.c | 3 ++- src/s_bsd.c | 7 +++++-- src/s_user.c | 44 +++++++++++++++++++++++++++++++++++--------- src/struct.c | 5 ++++- src/userban.c | 11 ++++++----- 11 files changed, 94 insertions(+), 36 deletions(-) diff --git a/include/struct.h b/include/struct.h index 523b61d..9dce1cd 100644 --- a/include/struct.h +++ b/include/struct.h @@ -887,7 +887,11 @@ struct Client Link *fludees; #endif - struct in_addr ip; /* keep real ip# too */ + int ip_family; + union + { + struct in_addr ip4; + } ip; /* keep real ip# too */ char hostip[HOSTIPLEN + 1]; /* Keep real ip as string * too - Dianora */ diff --git a/src/clones.c b/src/clones.c index f4d6fc2..e929f70 100644 --- a/src/clones.c +++ b/src/clones.c @@ -274,8 +274,10 @@ clones_add(aClient *cptr) CloneEnt *ceip; CloneEnt *ce24; - if (cptr->ip.s_addr == 0) - return; + if (cptr->ip_family != AF_INET) + return; + if (cptr->ip.ip4.s_addr == 0) + return; get_clones(cptr, &ceip, &ce24, 1); @@ -304,8 +306,10 @@ clones_remove(aClient *cptr) CloneEnt *ceip; CloneEnt *ce24; - if (cptr->ip.s_addr == 0) - return; + if (cptr->ip_family != AF_INET) + return; + if (cptr->ip.ip4.s_addr == 0) + return; get_clones(cptr, &ceip, &ce24, 0); diff --git a/src/klines.c b/src/klines.c index f35fe9b..fb8ac6f 100644 --- a/src/klines.c +++ b/src/klines.c @@ -148,8 +148,13 @@ m_kline(aClient *cptr, aClient *sptr, int parc, char *parv[]) return 0; user = acptr->user->username; - ircsprintf(hostbuf, "%s/24", acptr->hostip); - host = hostbuf; + if (acptr->ip_family == AF_INET) + { + ircsprintf(hostbuf, "%s/24", acptr->hostip); + host = hostbuf; + } + else + host = acptr->hostip; } if (!match(user, "akjhfkahfasfjd") && diff --git a/src/m_nick.c b/src/m_nick.c index 2e2ad07..2a7f75b 100644 --- a/src/m_nick.c +++ b/src/m_nick.c @@ -36,7 +36,7 @@ extern int do_user(char *, aClient *, aClient *, char *, char *, char *, unsigned long, char *, char *); -extern int register_user(aClient *, aClient *, char *, char *); +extern int register_user(aClient *, aClient *, char *, char *, char *); extern int del_dccallow(aClient *, aClient *, int); @@ -632,7 +632,7 @@ int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[]) { /* USER already received, now we have NICK */ - if (register_user(cptr, sptr, nick, sptr->user->username) + if (register_user(cptr, sptr, nick, sptr->user->username, NULL) == FLUSH_BUFFER) return FLUSH_BUFFER; } diff --git a/src/m_rwho.c b/src/m_rwho.c index 6b98fbe..242dc04 100644 --- a/src/m_rwho.c +++ b/src/m_rwho.c @@ -930,26 +930,36 @@ static int rwho_match(aClient *cptr, int *failcode, aClient **failclient) if (rwho_opts.check[0] & RWM_IP) { - if (rwho_opts.ip_str[0]) + if (rwho_opts.ip_str[0]) { if (match(rwho_opts.ip_str[0], cptr->hostip)) return 0; } - else if ((cptr->ip.s_addr & rwho_opts.ip_mask[0]) - != rwho_opts.ip_addr[0]) - return 0; + else if (cptr->ip_family == AF_INET) + { + if ((cptr->ip.ip4.s_addr & rwho_opts.ip_mask[0]) + != rwho_opts.ip_addr[0]) + return 0; + } + else + return 0; } if (rwho_opts.check[1] & RWM_IP) { - if (rwho_opts.ip_str[1]) + if (rwho_opts.ip_str[1]) { if (!match(rwho_opts.ip_str[1], cptr->hostip)) return 0; } - else if ((cptr->ip.s_addr & rwho_opts.ip_mask[1]) - == rwho_opts.ip_addr[1]) - return 0; + else if (cptr->ip_family == AF_INET) + { + if ((cptr->ip.ip4.s_addr & rwho_opts.ip_mask[1]) + == rwho_opts.ip_addr[1]) + return 0; + } + else + return 0; } if ((rwho_opts.check[0] & RWM_HOST) && diff --git a/src/m_server.c b/src/m_server.c index f4ce52e..b21f674 100644 --- a/src/m_server.c +++ b/src/m_server.c @@ -62,7 +62,8 @@ static void sendnick_TS(aClient *cptr, aClient *acptr) acptr->name, acptr->hopcount + 1, acptr->tsinfo, ubuf, acptr->user->username, acptr->user->host, acptr->user->server, acptr->user->servicestamp, - htonl(acptr->ip.s_addr), acptr->info); + (acptr->ip_family == AF_INET) ? + htonl(acptr->ip.ip4.s_addr) : 1, acptr->info); } } } diff --git a/src/m_who.c b/src/m_who.c index 49e9fb5..d64b7f5 100644 --- a/src/m_who.c +++ b/src/m_who.c @@ -567,7 +567,8 @@ int chk_who(aClient *ac, int showall) return 0; if(wsopts.cidr4_plus) - if((ac->ip.s_addr & wsopts.cidr4_mask) != wsopts.cidr4_ip) + if(ac->ip_family != AF_INET || + (ac->ip.ip4.s_addr & wsopts.cidr4_mask) != wsopts.cidr4_ip) return 0; if(wsopts.ip_plus) diff --git a/src/s_bsd.c b/src/s_bsd.c index 10243ef..f920906 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -642,8 +642,9 @@ int check_client(aClient *cptr) Debug((DEBUG_DNS, "ch_cl: access ok: %s[%s]", cptr->name, sockname)); - if (inet_netof(cptr->ip) == IN_LOOPBACKNET || - inet_netof(cptr->ip) == inet_netof(mysk.sin_addr)) + if (cptr->ip_family == AF_INET && + (inet_netof(cptr->ip.ip4) == IN_LOOPBACKNET || + inet_netof(cptr->ip.ip4) == inet_netof(mysk.sin_addr))) { ircstp->is_loc++; cptr->flags |= FLAGS_LOCAL; @@ -1235,6 +1236,7 @@ aClient *add_connection(aListener *lptr, int fd) * something valid to put into error messages... */ get_sockhost(acptr, (char *) inetntoa((char *) &addr.sin_addr)); + acptr->ip_family = AF_INET; memcpy((char *) &acptr->ip, (char *) &addr.sin_addr, sizeof(struct in_addr)); @@ -1895,6 +1897,7 @@ connect_inet(aConnect *aconn, aClient *cptr, int *lenp) memcpy((char *) &server.sin_addr, (char *) &aconn->ipnum, sizeof(struct in_addr)); + cptr->ip_family = AF_INET; memcpy((char *) &cptr->ip, (char *) &aconn->ipnum, sizeof(struct in_addr)); diff --git a/src/s_user.c b/src/s_user.c index 84cb6c4..2a75ee9 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -443,7 +443,8 @@ reject_proxy(aClient *cptr, char *cmd, char *args) */ int -register_user(aClient *cptr, aClient *sptr, char *nick, char *username) +register_user(aClient *cptr, aClient *sptr, char *nick, char *username, + char *hostip) { aAllow *pwaconf = NULL; char *parv[3]; @@ -465,7 +466,7 @@ register_user(aClient *cptr, aClient *sptr, char *nick, char *username) parv[0] = sptr->name; parv[1] = parv[2] = NULL; - p = cipntoa(sptr); + p = hostip ? hostip : cipntoa(sptr); strncpyzt(sptr->hostip, p, HOSTIPLEN + 1); if (MyConnect(sptr)) { @@ -936,7 +937,8 @@ register_user(aClient *cptr, aClient *sptr, char *nick, char *username) strncpyzt(sptr->user->username, onick, USERLEN + 1); strncpyzt(sptr->username, onick, USERLEN + 1); sptr->flags |= FLAGS_GOTID; /* fake ident */ - sptr->ip.s_addr = 0; + sptr->ip_family = AF_INET; + memset(&sptr->ip, 0, sizeof(sptr->ip)); strcpy(sptr->hostip, "0.0.0.0"); strncpy(sptr->sockhost, Staff_Address, HOSTLEN + 1); } @@ -1081,7 +1083,8 @@ register_user(aClient *cptr, aClient *sptr, char *nick, char *username) nick, sptr->hopcount + 1, sptr->tsinfo, ubuf, user->username, user->host, user->server, sptr->user->servicestamp, - htonl(sptr->ip.s_addr), sptr->info); + (sptr->ip_family == AF_INET) ? + htonl(sptr->ip.ip4.s_addr) : 1, sptr->info); } if(MyClient(sptr)) @@ -2147,21 +2150,44 @@ do_user(char *nick, aClient *cptr, aClient *sptr, char *username, char *host, sptr->user->servicestamp = serviceid; if (!MyConnect(sptr)) { - if (inet_pton(AF_INET, ip, &sptr->ip) == 0) - sptr->ip.s_addr = ntohl(strtoul(ip, NULL, 10)); + if (inet_pton(AF_INET, ip, &sptr->ip.ip4) == 1) + { + if (sptr->ip.ip4.s_addr != htonl(1)) + sptr->ip_family = AF_INET; + else + sptr->ip_family = 0; + } + else + { + char *end; + unsigned long l; + + l = ntohl(strtoul(ip, &end, 10)); + if (*ip != '\0' && *end == '\0' && l != 1) + { + sptr->ip_family = AF_INET; + sptr->ip.ip4.s_addr = l; + } + else + sptr->ip_family = 0; + } /* add non-local clients to the throttle checker. obviously, we only * do this for REMOTE clients!@$$@! throttle_check() is called * elsewhere for the locals! -wd */ #ifdef THROTTLE_ENABLE - if (sptr->ip.s_addr != 0) - throttle_check(cipntoa(sptr), -1, sptr->tsinfo); + if (sptr->ip_family == 0) + ; + else if (sptr->ip_family == AF_INET && sptr->ip.ip4.s_addr == 0) + ; + else + throttle_check(ip, -1, sptr->tsinfo); #endif } if(MyConnect(sptr)) sptr->oflag=0; if (sptr->name[0]) /* NICK already received, now I have USER... */ - return register_user(cptr, sptr, sptr->name, username); + return register_user(cptr, sptr, sptr->name, username, ip); else strncpyzt(sptr->user->username, username, USERLEN + 1); return 0; diff --git a/src/struct.c b/src/struct.c index 2651efa..a3d705e 100644 --- a/src/struct.c +++ b/src/struct.c @@ -125,7 +125,10 @@ Link *ac_fludees(aClient *cptr) struct in_addr ac_ip(aClient *cptr) { - return cptr->ip; + if (cptr->ip_family == AF_INET) + return cptr->ip.ip4; + else + return (struct in_addr){1}; } char *ac_hostip(aClient *cptr) diff --git a/src/userban.c b/src/userban.c index 02430f1..e651d62 100644 --- a/src/userban.c +++ b/src/userban.c @@ -205,7 +205,8 @@ int user_match_ban(aClient *cptr, struct userBan *ban) if(ban->flags & (UBAN_CIDR4|UBAN_CIDR4BIG)) { - if((cptr->ip.s_addr & ban->cidr4mask) == ban->cidr4ip) + if(cptr->ip_family == AF_INET && + (cptr->ip.ip4.s_addr & ban->cidr4mask) == ban->cidr4ip) return 1; return 0; } @@ -257,9 +258,9 @@ struct userBan *check_userbanned(aClient *cptr, unsigned int yflags, unsigned in } } - if(yflags & UBAN_CIDR4) + if(yflags & UBAN_CIDR4 && cptr->ip_family == AF_INET) { - unsigned char *s = (unsigned char *) &cptr->ip.s_addr; + unsigned char *s = (unsigned char *) &cptr->ip.ip4.s_addr; int a, b; a = (int) *s++; @@ -277,7 +278,7 @@ struct userBan *check_userbanned(aClient *cptr, unsigned int yflags, unsigned in if((!(bl->ban->flags & UBAN_WILDUSER)) && match(bl->ban->u, cptr->user->username)) continue; - if((cptr->ip.s_addr & bl->ban->cidr4mask) == bl->ban->cidr4ip) + if((cptr->ip.ip4.s_addr & bl->ban->cidr4mask) == bl->ban->cidr4ip) return bl->ban; } @@ -293,7 +294,7 @@ struct userBan *check_userbanned(aClient *cptr, unsigned int yflags, unsigned in if((!(bl->ban->flags & UBAN_WILDUSER)) && match(bl->ban->u, cptr->user->username)) continue; - if((cptr->ip.s_addr & bl->ban->cidr4mask) == bl->ban->cidr4ip) + if((cptr->ip.ip4.s_addr & bl->ban->cidr4mask) == bl->ban->cidr4ip) return bl->ban; } } -- 1.7.2.3