From: Remco Rijnders Date: Sat, 7 Mar 2026 17:17:36 +0000 (-0500) Subject: IPv6 Phase 1: Replace struct in_addr with dual-stack irc_addr abstraction X-Git-Url: http://git.serene-ircd.net/?a=commitdiff_plain;h=f488f6e5426dcdd8769468df8ef00909acfce852;p=serene-ircd.git IPv6 Phase 1: Replace struct in_addr with dual-stack irc_addr abstraction Introduce struct irc_addr (include/irc_addr.h) that holds either an IPv4 or IPv6 address. Convert Client.ip, ConfItem.ipnum, and aThrottle.ip from struct in_addr to struct irc_addr throughout the codebase. Rewrite inetntoa() to use inet_ntop() via irc_addr. Update all call sites in s_bsd.c, s_conf.c, s_ping.c, s_user.c, s_misc.c, whowas.c, and list.c. The DNS resolver (res.c) stays IPv4-only internally with an inetntoa_v4() bridge function for the transition. Co-Authored-By: Claude Opus 4.6 --- diff --git a/include/h.h b/include/h.h index 04915a0..10b5e2d 100644 --- a/include/h.h +++ b/include/h.h @@ -88,7 +88,7 @@ extern char *find_restartpass(); extern aConfItem *find_conf (Link *, char*, int); extern aConfItem *find_conf_exact (char *, char *, char *, int); extern aConfItem *find_conf_host (Link *, char *, int); -extern aConfItem *find_conf_ip (Link *, char *, char *, int); +extern aConfItem *find_conf_ip (Link *, struct irc_addr *, char *, int); extern aConfItem *find_conf_name (char *, int); extern aConfItem *find_temp_conf_entry (aConfItem *, u_int); extern aConfItem *find_conf_servern (char *); @@ -127,7 +127,7 @@ extern void get_sockhost (aClient *, char *); extern char *rpl_str (int), *err_str (int); extern char *strerror (int); extern int dgets (int, char *, int); -extern char *inetntoa (char *); +extern char *inetntoa (const struct irc_addr *); extern int dbufalloc, dbufblocks, debuglevel, errno, h_errno; extern int highest_fd, debuglevel, portnum, debugtty, maxusersperchannel; diff --git a/include/irc_addr.h b/include/irc_addr.h new file mode 100644 index 0000000..539d878 --- /dev/null +++ b/include/irc_addr.h @@ -0,0 +1,135 @@ +/************************************************************************ + * IRC - Internet Relay Chat, include/irc_addr.h + * + * Dual-stack (IPv4/IPv6) address abstraction. + * Replaces raw struct in_addr usage throughout the ircd. + */ + +#ifndef __irc_addr_include__ +#define __irc_addr_include__ + +#include +#include +#include +#include +#include + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +/* Large enough for any formatted address */ +#define IRC_ADDRSTRLEN INET6_ADDRSTRLEN + +/* + * irc_addr - holds either an IPv4 or IPv6 address. + * Used in Client, ConfItem, throttle records, and the resolver. + */ +struct irc_addr { + int family; /* AF_INET or AF_INET6 */ + union { + struct in_addr v4; + struct in6_addr v6; + } addr; +}; + +/* Zero out an irc_addr */ +#define IRC_ADDR_ZERO(a) memset((a), 0, sizeof(struct irc_addr)) + +/* Check if an irc_addr is all zeros (unset) */ +static inline int irc_addr_is_zero(const struct irc_addr *a) +{ + static const struct irc_addr zero; + return memcmp(a, &zero, sizeof(struct irc_addr)) == 0; +} + +/* Compare two irc_addrs for equality */ +static inline int irc_addr_equal(const struct irc_addr *a, const struct irc_addr *b) +{ + if (a->family != b->family) + return 0; + if (a->family == AF_INET6) + return memcmp(&a->addr.v6, &b->addr.v6, sizeof(struct in6_addr)) == 0; + return a->addr.v4.s_addr == b->addr.v4.s_addr; +} + +/* Copy an irc_addr */ +#define IRC_ADDR_COPY(dst, src) memcpy((dst), (src), sizeof(struct irc_addr)) + +/* Format an irc_addr to a static buffer (not thread-safe, matches old inetntoa pattern) */ +static inline const char *irc_addr_str(const struct irc_addr *a) +{ + static char buf[IRC_ADDRSTRLEN]; + if (a->family == AF_INET6) + inet_ntop(AF_INET6, &a->addr.v6, buf, sizeof(buf)); + else + inet_ntop(AF_INET, &a->addr.v4, buf, sizeof(buf)); + return buf; +} + +/* Parse a string into an irc_addr. Returns 1 on success, 0 on failure. */ +static inline int irc_addr_from_str(struct irc_addr *a, const char *s) +{ + IRC_ADDR_ZERO(a); + if (strchr(s, ':')) { + a->family = AF_INET6; + return inet_pton(AF_INET6, s, &a->addr.v6) == 1; + } + a->family = AF_INET; + return inet_pton(AF_INET, s, &a->addr.v4) == 1; +} + +/* Set an irc_addr from a sockaddr (v4 or v6) */ +static inline void irc_addr_from_sockaddr(struct irc_addr *a, const struct sockaddr *sa) +{ + IRC_ADDR_ZERO(a); + if (sa->sa_family == AF_INET6) { + a->family = AF_INET6; + memcpy(&a->addr.v6, &((struct sockaddr_in6 *)sa)->sin6_addr, + sizeof(struct in6_addr)); + } else { + a->family = AF_INET; + memcpy(&a->addr.v4, &((struct sockaddr_in *)sa)->sin_addr, + sizeof(struct in_addr)); + } +} + +/* Check if address is loopback */ +static inline int irc_addr_is_loopback(const struct irc_addr *a) +{ + if (a->family == AF_INET6) + return IN6_IS_ADDR_LOOPBACK(&a->addr.v6); + return (ntohl(a->addr.v4.s_addr) >> 24) == 127; +} + +/* Compute a hash byte from an irc_addr (for throttle table etc.) */ +static inline unsigned char irc_addr_hash(const struct irc_addr *a) +{ + const unsigned char *p; + unsigned char h = 0; + int len, i; + + if (a->family == AF_INET6) { + p = (const unsigned char *)&a->addr.v6; + len = 16; + } else { + p = (const unsigned char *)&a->addr.v4; + len = 4; + } + for (i = 0; i < len; i++) + h ^= p[i]; + return h; +} + +/* Create an irc_addr from a raw struct in_addr (convenience for IPv4 code) */ +static inline struct irc_addr irc_addr_from_v4(const struct in_addr *v4) +{ + struct irc_addr a; + IRC_ADDR_ZERO(&a); + a.family = AF_INET; + memcpy(&a.addr.v4, v4, sizeof(struct in_addr)); + return a; +} + +#endif /* __irc_addr_include__ */ + diff --git a/include/struct.h b/include/struct.h index e2d4948..d38ed2e 100644 --- a/include/struct.h +++ b/include/struct.h @@ -28,6 +28,7 @@ #include #include #include +#include "irc_addr.h" #ifdef USE_SYSLOG # include @@ -433,7 +434,7 @@ struct SqlineItem { struct ConfItem { unsigned int status; /* If CONF_ILLEGAL, delete when no clients */ int clients; /* Number of *LOCAL* clients using this */ - struct in_addr ipnum; /* ip number of host field */ + struct irc_addr ipnum; /* ip number of host field */ char *host; char *passwd; char *name; @@ -646,7 +647,7 @@ struct Client { #ifdef ZIP_LINKS aZdata *zip; #endif - struct in_addr ip; /* keep real ip# too */ + struct irc_addr ip; /* keep real ip# too */ u_short port; /* and the remote port# too :-) */ struct hostent *hostp; u_short notifies; /* Keep track of count of notifies */ diff --git a/src/list.c b/src/list.c index 0a101de..eb1d5b2 100644 --- a/src/list.c +++ b/src/list.c @@ -465,7 +465,7 @@ aConfItem *make_conf () #ifdef DEBUGMODE aconfs.inuse++; #endif - memset ((char *) &aconf->ipnum, 0, sizeof (struct in_addr)); + IRC_ADDR_ZERO (&aconf->ipnum); aconf->next = NULL; aconf->host = aconf->passwd = aconf->name = NULL; aconf->status = CONF_ILLEGAL; diff --git a/src/res.c b/src/res.c index 7a337de..e79c238 100644 --- a/src/res.c +++ b/src/res.c @@ -26,6 +26,13 @@ extern int highest_fd; extern aClient *local[]; +/* Helper: format a raw in_addr for debug/log output (resolver is still IPv4-only) */ +static char *inetntoa_v4(const struct in_addr *in) +{ + struct irc_addr a = irc_addr_from_v4 (in); + return inetntoa (&a); +} + static char hostbuf[HOSTLEN + 1]; static char dot[] = "."; static int incache = 0; @@ -499,7 +506,7 @@ static int proc_answer (ResRQ *rptr, HEADER *hptr, char *buf, char *eob) memcpy ((char *) &dr, cp, dlen); adr->s_addr = dr.s_addr; Debug ((DEBUG_INFO, "got ip # %s for %s", - inetntoa ((char *) adr), hostbuf)); + inetntoa_v4 (adr), hostbuf)); if (!hp->h_name) { hp->h_name = (char *) MyMalloc (len + 1); (void) strcpy (hp->h_name, hostbuf); @@ -647,12 +654,12 @@ struct hostent *get_res (char *lp) struct hostent *hp2 = NULL; Debug ((DEBUG_DNS, "relookup %s <-> %s", - rptr->he.h_name, inetntoa ((char *) &rptr->he.h_addr))); + rptr->he.h_name, inetntoa_v4 (&rptr->he.h_addr))); if (!rptr->he.h_name) { char badip[128]; sprintf (badip, "%s (a = %d)", - inetntoa ((char *) &rptr->he.h_addr), a); + inetntoa_v4 (&rptr->he.h_addr), a); sendto_realops ("WARNING: Error in lookup of %s.", badip); sendto_serv_butone (&me, ":%s GLOBOPS :Error in lookup of %s.", @@ -963,7 +970,7 @@ static aCache *find_cache_number (ResRQ *rptr, char *numb) cp = hashtable[hashv].num_list; #ifdef DEBUG Debug ((DEBUG_DNS, "find_cache_number:find %s[%08x]: hashv = %d", - inetntoa (numb), ntohl (ip->s_addr), hashv)); + inetntoa_v4 ((struct in_addr *) numb), ntohl (ip->s_addr), hashv)); #endif for (; cp; cp = cp->hnum_next) @@ -1128,7 +1135,7 @@ static void rem_cache (aCache *ocp) hashv = hash_number ((u_char *) hp->h_addr); #ifdef DEBUG Debug ((DEBUG_DEBUG, "rem_cache: h_addr %s hashv %d next %#x first %#x", - inetntoa (hp->h_addr), hashv, ocp->hnum_next, + inetntoa_v4 ((struct in_addr *) hp->h_addr), hashv, ocp->hnum_next, hashtable[hashv].num_list)); #endif for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next)) @@ -1205,14 +1212,14 @@ int m_dns (aClient *cptr, aClient *sptr, int parc, char *parv[]) for (cp = cachetop; cp; cp = cp->list_next) { sendto_one (sptr, "NOTICE %s :Ex %d ttl %d host %s(%s)", parv[0], cp->expireat - time (NULL), cp->ttl, - cp->he.h_name, inetntoa (cp->he.h_addr)); + cp->he.h_name, inetntoa_v4 ((struct in_addr *) cp->he.h_addr)); for (i = 0; cp->he.h_aliases[i]; i++) sendto_one (sptr, "NOTICE %s : %s = %s (CN)", parv[0], cp->he.h_name, cp->he.h_aliases[i]); for (i = 1; cp->he.h_addr_list[i]; i++) sendto_one (sptr, "NOTICE %s : %s = %s (IP)", parv[0], cp->he.h_name, - inetntoa (cp->he.h_addr_list[i])); + inetntoa_v4 ((struct in_addr *) cp->he.h_addr_list[i])); } return 0; } diff --git a/src/s_bsd.c b/src/s_bsd.c index 1bfa782..ad2c486 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -199,7 +199,7 @@ int inetport (aClient *cptr, char *name, int port) if (port) { server.sin_family = AF_INET; /* per-port bindings, fixes /stats l */ - server.sin_addr.s_addr = inet_addr (ipname); + inet_pton (AF_INET, ipname, &server.sin_addr); server.sin_port = htons (port); /* */ @@ -225,7 +225,10 @@ int inetport (aClient *cptr, char *name, int port) if (cptr->fd > highest_fd) highest_fd = cptr->fd; - cptr->ip.s_addr = name ? inet_addr (ipname) : me.ip.s_addr; + if (name) + irc_addr_from_str (&cptr->ip, ipname); + else + IRC_ADDR_COPY (&cptr->ip, &me.ip); cptr->port = (int) ntohs (server.sin_port); (void) listen (cptr->fd, cfg_listen_size); local[cptr->fd] = cptr; @@ -399,12 +402,12 @@ static int check_init (aClient *cptr, char *sockn) report_error ("connect failure: %s %s", cptr); return -1; } - (void) strcpy (sockn, (char *) inetntoa ((char *) &sk.sin_addr)); - if (inet_netof (sk.sin_addr) == IN_LOOPBACKNET) { + irc_addr_from_sockaddr (&cptr->ip, (struct sockaddr *) &sk); + (void) strcpy (sockn, (char *) inetntoa (&cptr->ip)); + if (irc_addr_is_loopback (&cptr->ip)) { cptr->hostp = NULL; strncpyzt (sockn, me.sockhost, HOSTLEN); } - memcpy ((char *) &cptr->ip, (char *) &sk.sin_addr, sizeof (struct in_addr)); cptr->port = (int) ntohs (sk.sin_port); return 0; @@ -425,7 +428,7 @@ int check_client (aClient *cptr) ClearAccess (cptr); Debug ((DEBUG_DNS, "ch_cl: check access for %s[%s]", - cptr->name, inetntoa ((char *) &cptr->ip))); + cptr->name, inetntoa (&cptr->ip))); if (check_init (cptr, sockname)) return -2; @@ -438,12 +441,11 @@ int check_client (aClient *cptr) */ if (hp) { for (i = 0; hp->h_addr_list[i]; i++) - if (!memcmp (hp->h_addr_list[i], (char *) &cptr->ip, sizeof (struct in_addr))) + if (!memcmp (hp->h_addr_list[i], (char *) &cptr->ip.addr.v4, sizeof (struct in_addr))) break; if (!hp->h_addr_list[i]) { - sendto_ops ("IP# Mismatch: %s != %s[%08x]", - inetntoa ((char *) &cptr->ip), hp->h_name, - *((unsigned long *) hp->h_addr)); + sendto_ops ("IP# Mismatch: %s != %s", + inetntoa (&cptr->ip), hp->h_name); hp = NULL; } } @@ -454,8 +456,7 @@ int check_client (aClient *cptr) } Debug ((DEBUG_DNS, "ch_cl: access ok: %s[%s]", cptr->name, sockname)); - if (inet_netof (cptr->ip) == IN_LOOPBACKNET || IsUnixSocket (cptr) || - inet_netof (cptr->ip) == inet_netof (mysk.sin_addr)) { + if (irc_addr_is_loopback (&cptr->ip) || IsUnixSocket (cptr)) { ircstp->is_loc++; cptr->flags |= FLAGS_LOCAL; } @@ -559,12 +560,11 @@ int check_server (aClient *cptr, struct hostent *hp, aConfItem *c_conf, aConfIte */ if (hp) { for (i = 0; hp->h_addr_list[i]; i++) - if (!memcmp (hp->h_addr_list[i], (char *) &cptr->ip, sizeof (struct in_addr))) + if (!memcmp (hp->h_addr_list[i], (char *) &cptr->ip.addr.v4, sizeof (struct in_addr))) break; if (!hp->h_addr_list[i]) { - sendto_ops ("IP# Mismatch: %s != %s[%08x]", - inetntoa ((char *) &cptr->ip), hp->h_name, - *((unsigned long *) hp->h_addr)); + sendto_ops ("IP# Mismatch: %s != %s", + inetntoa (&cptr->ip), hp->h_name); hp = NULL; } } @@ -614,20 +614,21 @@ int check_server (aClient *cptr, struct hostent *hp, aConfItem *c_conf, aConfIte if (!hp) { if (!c_conf) c_conf = - find_conf_ip (lp, (char *) &cptr->ip, cptr->username, CFLAG); + find_conf_ip (lp, &cptr->ip, cptr->username, CFLAG); if (!n_conf) n_conf = - find_conf_ip (lp, (char *) &cptr->ip, cptr->username, NFLAG); + find_conf_ip (lp, &cptr->ip, cptr->username, NFLAG); } else for (i = 0; hp->h_addr_list[i]; i++) { + struct irc_addr tmp_ip = irc_addr_from_v4 ((struct in_addr *) hp->h_addr_list[i]); if (!c_conf) c_conf = - find_conf_ip (lp, hp->h_addr_list[i], cptr->username, + find_conf_ip (lp, &tmp_ip, cptr->username, CFLAG); if (!n_conf) n_conf = - find_conf_ip (lp, hp->h_addr_list[i], cptr->username, + find_conf_ip (lp, &tmp_ip, cptr->username, NFLAG); } /* @@ -650,8 +651,8 @@ int check_server (aClient *cptr, struct hostent *hp, aConfItem *c_conf, aConfIte (void) attach_conf (cptr, c_conf); (void) attach_confs (cptr, name, CONF_HUB | CONF_UWORLD); - if ((c_conf->ipnum.s_addr == -1) && !IsUnixSocket (cptr)) - memcpy ((char *) &c_conf->ipnum, (char *) &cptr->ip, sizeof (struct in_addr)); + if (irc_addr_is_zero (&c_conf->ipnum) && !IsUnixSocket (cptr)) + IRC_ADDR_COPY (&c_conf->ipnum, &cptr->ip); if (!IsUnixSocket (cptr)) get_sockhost (cptr, c_conf->host); @@ -962,8 +963,8 @@ aClient * add_connection (aClient *cptr, int fd) /* Copy ascii address to 'sockhost' just in case. Then we * have something valid to put into error messages... */ - get_sockhost (acptr, (char *) inetntoa ((char *) &addr.sin_addr)); - memcpy ((char *) &acptr->ip, (char *) &addr.sin_addr, sizeof (struct in_addr)); + irc_addr_from_sockaddr (&acptr->ip, (struct sockaddr *) &addr); + get_sockhost (acptr, (char *) inetntoa (&acptr->ip)); /* Check for zaps -- Barubary */ if (find_zap (acptr, 0)) { set_non_blocking (fd, acptr); @@ -980,17 +981,17 @@ aClient * add_connection (aClient *cptr, int fd) for (aconf2 = conf; aconf2; aconf2 = aconf2->next) if (aconf2->status == CONF_CONNECT_SERVER && - (match (inetntoa ((char *) &addr.sin_addr), aconf2->host) == 0 - || match (inetntoa ((char *) &addr.sin_addr), + (match (inetntoa (&acptr->ip), aconf2->host) == 0 + || match (inetntoa (&acptr->ip), strchr (aconf2->host, '@') + 1) == 0)) break; if (!aconf2) { for (aconf2 = conf; aconf2; aconf2 = aconf2->next) if (aconf2->status == CONF_NOCONNECT_SERVER && - (match (inetntoa ((char *) &addr.sin_addr), aconf2->host) + (match (inetntoa (&acptr->ip), aconf2->host) == 0 - || match (inetntoa ((char *) &addr.sin_addr), + || match (inetntoa (&acptr->ip), strchr (aconf2->host, '@') + 1) == 0)) break; } @@ -1003,7 +1004,7 @@ aClient * add_connection (aClient *cptr, int fd) lin.flags = ASYNC_CLIENT; lin.value.cptr = acptr; - Debug ((DEBUG_DNS, "lookup %s", inetntoa ((char *) &addr.sin_addr))); + Debug ((DEBUG_DNS, "lookup %s", inetntoa (&acptr->ip))); acptr->hostp = gethost_byaddr ((char *) &acptr->ip, &lin); if (!acptr->hostp) SetDNS (acptr); @@ -1382,7 +1383,7 @@ int connect_server (aConfItem *aconf, aClient *by, struct hostent *hp) int errtmp, len; Debug ((DEBUG_NOTICE, "Connect to %s[%s] @%s", - aconf->name, aconf->host, inetntoa ((char *) &aconf->ipnum))); + aconf->name, aconf->host, inetntoa (&aconf->ipnum))); if ((c2ptr = find_server (aconf->name, NULL))) { sendto_ops ("Server %s already present from %s", @@ -1398,7 +1399,7 @@ int connect_server (aConfItem *aconf, aClient *by, struct hostent *hp) * If we dont know the IP# for this host and itis a hostname and * not a ip# string, then try and find the appropriate host record. */ - if ((!aconf->ipnum.s_addr)) { + if (irc_addr_is_zero (&aconf->ipnum)) { Link lin; lin.flags = ASYNC_CONNECT; @@ -1406,14 +1407,14 @@ int connect_server (aConfItem *aconf, aClient *by, struct hostent *hp) nextdnscheck = 1; s = (char *) strchr (aconf->host, '@'); s++; /* should NEVER be NULL */ - if ((aconf->ipnum.s_addr = inet_addr (s)) == -1) { - aconf->ipnum.s_addr = 0; + if (!irc_addr_from_str (&aconf->ipnum, s)) { + IRC_ADDR_ZERO (&aconf->ipnum); hp = gethost_byname (s, &lin); Debug ((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s", hp, aconf, aconf->name, s)); if (!hp) return 0; - memcpy ((char *) &aconf->ipnum, hp->h_addr, sizeof (struct in_addr)); + aconf->ipnum = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); } } cptr = make_client (NULL, NULL); @@ -1531,7 +1532,7 @@ static struct sockaddr * connect_inet (aConfItem *aconf, aClient *cptr, int *len } get_sockhost (cptr, aconf->host); server.sin_port = 0; - server.sin_addr = me.ip; + server.sin_addr = me.ip.addr.v4; server.sin_family = AF_INET; /* ** Bind to a local IP# (with unknown port - let unix decide) so @@ -1544,7 +1545,7 @@ static struct sockaddr * connect_inet (aConfItem *aconf, aClient *cptr, int *len ** I had this on my Linux 1.1.88 --Run */ /* We do now. Virtual interface stuff --ns */ - if (me.ip.s_addr != INADDR_ANY) + if (!irc_addr_is_zero (&me.ip)) if (bind (cptr->fd, (struct sockaddr *) &server, sizeof (server)) == -1) { report_error ("error binding to local port for %s:%s", cptr); @@ -1557,18 +1558,18 @@ static struct sockaddr * connect_inet (aConfItem *aconf, aClient *cptr, int *len * conf line, whether as a result of the hostname lookup or the ip# * being present instead. If we dont know it, then the connect fails. */ - if (isdigit (*aconf->host) && (aconf->ipnum.s_addr == -1)) - aconf->ipnum.s_addr = inet_addr (aconf->host); - if (aconf->ipnum.s_addr == -1) { + if (isdigit (*aconf->host) && irc_addr_is_zero (&aconf->ipnum)) + irc_addr_from_str (&aconf->ipnum, aconf->host); + if (irc_addr_is_zero (&aconf->ipnum)) { hp = cptr->hostp; if (!hp) { Debug ((DEBUG_FATAL, "%s: unknown host", aconf->host)); return NULL; } - memcpy ((char *) &aconf->ipnum, hp->h_addr, sizeof (struct in_addr)); + aconf->ipnum = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); } - memcpy ((char *) &server.sin_addr, (char *) &aconf->ipnum, sizeof (struct in_addr)); - memcpy ((char *) &cptr->ip, (char *) &aconf->ipnum, sizeof (struct in_addr)); + memcpy ((char *) &server.sin_addr, (char *) &aconf->ipnum.addr.v4, sizeof (struct in_addr)); + IRC_ADDR_COPY (&cptr->ip, &aconf->ipnum); server.sin_port = htons (((aconf->port > 0) ? aconf->port : portnum)); *lenp = sizeof (server); return (struct sockaddr *) &server; @@ -1609,7 +1610,7 @@ int setup_ping () int on = 1; memset ((char *) &from, 0, sizeof (from)); - from.sin_addr = me.ip; + from.sin_addr = me.ip.addr.v4; from.sin_port = htons (7007); from.sin_family = AF_INET; @@ -1745,7 +1746,7 @@ static void do_dns_async () case ASYNC_CONNECT: aconf = ln.value.aconf; if (hp && aconf) { - memcpy ((char *) &aconf->ipnum, hp->h_addr, sizeof (struct in_addr)); + aconf->ipnum = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); (void) connect_server (aconf, NULL, hp); } else @@ -1755,7 +1756,7 @@ static void do_dns_async () case ASYNC_CONF: aconf = ln.value.aconf; if (hp && aconf) - memcpy ((char *) &aconf->ipnum, hp->h_addr, sizeof (struct in_addr)); + aconf->ipnum = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); break; case ASYNC_SERVER: cptr = ln.value.cptr; @@ -1768,7 +1769,7 @@ static void do_dns_async () cptr = ln.value.cptr; del_queries ((char *) cptr); if (hp) { - memcpy (&cptr->ip, hp->h_addr, sizeof (struct in_addr)); + cptr->ip = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); if (ping_server (cptr, hp) != -1) break; } diff --git a/src/s_conf.c b/src/s_conf.c index 08eb005..b4b913a 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -519,7 +519,7 @@ aConfItem * find_conf_host (Link *lp, char *host, int statmask) * Find a conf line using the IP# stored in it to search upon. * Added 1/8/92 by Avalon. */ -aConfItem * find_conf_ip (Link *lp, char *ip, char *user, int statmask) +aConfItem * find_conf_ip (Link *lp, struct irc_addr *ip, char *user, int statmask) { aConfItem *tmp; char *s; @@ -535,7 +535,7 @@ aConfItem * find_conf_ip (Link *lp, char *ip, char *user, int statmask) continue; } *s = '@'; - if (!memcmp ((char *) &tmp->ipnum, ip, sizeof (struct in_addr))) + if (irc_addr_equal (&tmp->ipnum, ip)) return tmp; } return NULL; @@ -987,9 +987,9 @@ static void conf_add_item (aConfItem *aconf, int opt) if (me.name[0] == '\0' && aconf->host[0]) strncpyzt (me.name, aconf->host, sizeof (me.name)); if (aconf->passwd[0] && (aconf->passwd[0] != '*')) - me.ip.s_addr = inet_addr (aconf->passwd); + irc_addr_from_str (&me.ip, aconf->passwd); else - me.ip.s_addr = INADDR_ANY; + IRC_ADDR_ZERO (&me.ip); if (portnum < 0 && aconf->port >= 0) portnum = aconf->port; } @@ -1451,17 +1451,18 @@ static int lookup_confhost (aConfItem *aconf) ln.value.aconf = aconf; ln.flags = ASYNC_CONF; - if (isdigit (*s)) - aconf->ipnum.s_addr = inet_addr (s); + if (isdigit (*s)) { + if (!irc_addr_from_str (&aconf->ipnum, s)) + goto badlookup; + } else if ((hp = gethost_byname (s, &ln))) - memcpy ((char *) &(aconf->ipnum), hp->h_addr, sizeof (struct in_addr)); + aconf->ipnum = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); - if (aconf->ipnum.s_addr == -1) + if (irc_addr_is_zero (&aconf->ipnum) && isdigit (*s)) goto badlookup; return 0; badlookup: - if (aconf->ipnum.s_addr == -1) - memset ((char *) &aconf->ipnum, 0, sizeof (struct in_addr)); + IRC_ADDR_ZERO (&aconf->ipnum); Debug ((DEBUG_ERROR, "Host/server name error: (%s) (%s)", aconf->host, aconf->name)); return -1; @@ -1478,7 +1479,7 @@ int find_kill (aClient *cptr) host = cptr->sockhost; name = cptr->user->username; - strncpy (ipaddy, inetntoa ((char *) &(cptr->ip)), HOSTLEN); + strncpy (ipaddy, inetntoa (&cptr->ip), HOSTLEN); if (strlen (host) > (size_t) HOSTLEN || (name ? strlen (name) : 0) > (size_t) HOSTLEN) @@ -1547,7 +1548,7 @@ char *find_zap (aClient * cptr, int dokillmsg) char *retval = NULL; char ipaddy[HOSTLEN + 1]; - strncpy (ipaddy, inetntoa ((char *) &cptr->ip), HOSTLEN); + strncpy (ipaddy, inetntoa (&cptr->ip), HOSTLEN); for (tmp = conf; tmp; tmp = tmp->next) if ((tmp->status == CONF_ZAP) && tmp->host @@ -1562,7 +1563,7 @@ char *find_zap (aClient * cptr, int dokillmsg) if (!dokillmsg && retval) { sprintf (zlinebuf, "ERROR :Closing Link: [%s] (You are not welcome on " - "this server: %s.\r\n", inetntoa ((char *) &cptr->ip), + "this server: %s.\r\n", inetntoa (&cptr->ip), retval); retval = zlinebuf; } @@ -2156,7 +2157,7 @@ int m_zline (aClient *cptr, aClient *sptr, int parc, char *parv[]) me.name, sptr->name); return -1; } - strcpy (userhost, inetntoa ((char *) &acptr->ip)); + strcpy (userhost, inetntoa (&acptr->ip)); person = &acptr->name[0]; acptr = NULL; } diff --git a/src/s_misc.c b/src/s_misc.c index f68b972..5f45825 100644 --- a/src/s_misc.c +++ b/src/s_misc.c @@ -242,7 +242,7 @@ char * get_client_name (aClient *sptr, int showip) (void) sprintf (nbuf, "%s[%s@%s.%u]", sptr->name, sptr->username, - inetntoa ((char *) &sptr->ip), + inetntoa (&sptr->ip), (unsigned int) sptr->port); else { if (mycmp (sptr->name, sptr->sockhost)) diff --git a/src/s_ping.c b/src/s_ping.c index 644e0fd..107aaf6 100644 --- a/src/s_ping.c +++ b/src/s_ping.c @@ -56,7 +56,7 @@ void sendto_one_notice (aClient *to, char *pattern, ...) return; } -extern u_long inet_addr (); +/* inet_addr() provided by arpa/inet.h via struct.h */ void end_ping (); void cancel_ping (); @@ -104,7 +104,7 @@ int start_ping (aClient *cptr) if (!(cptr->acpt)) return -1; - memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip, sizeof (struct in_addr)); + memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip.addr.v4, sizeof (struct in_addr)); remote_addr.sin_port = htons (cptr->port); remote_addr.sin_family = AF_INET; @@ -112,7 +112,7 @@ int start_ping (aClient *cptr) "Sending %d ping%s to %s[%s] port %d", cptr->hopcount, (cptr->hopcount == 1) ? "" : "s", cptr->name, - inetntoa ((char *) &remote_addr.sin_addr), + inetntoa (&cptr->ip), ntohs (remote_addr.sin_port)); cptr->firsttime = time (NULL) + UPINGTIMEOUT; @@ -131,7 +131,7 @@ void send_ping (aClient *cptr) struct sockaddr_in remote_addr; struct timeval tv; - memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip, sizeof (struct in_addr)); + memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip.addr.v4, sizeof (struct in_addr)); remote_addr.sin_port = htons (cptr->port); remote_addr.sin_family = AF_INET; @@ -141,7 +141,7 @@ void send_ping (aClient *cptr) Debug ((DEBUG_SEND, "send_ping: sending [%s %s] to %s.%d on %d", (char *) cptr->confs, (char *) cptr->confs + 12, - inetntoa ((char *) &remote_addr.sin_addr), + inetntoa (&cptr->ip), ntohs (remote_addr.sin_port), cptr->fd)); if (sendto (cptr->fd, (char *) cptr->confs, 1024, 0, @@ -173,7 +173,7 @@ void read_ping (aClient *cptr) unsigned long int pingtime; char *s; - memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip, sizeof (struct in_addr)); + memcpy ((char *) &remote_addr.sin_addr, (char *) &cptr->ip.addr.v4, sizeof (struct in_addr)); remote_addr.sin_port = htons (cptr->port); remote_addr.sin_family = AF_INET; @@ -225,7 +225,7 @@ void read_ping (aClient *cptr) int ping_server (aClient *cptr, struct hostent *hp) { - if ((!cptr->ip.s_addr)) { + if (irc_addr_is_zero (&cptr->ip)) { struct hostent *hp; char *s; Link lin; @@ -238,13 +238,13 @@ int ping_server (aClient *cptr, struct hostent *hp) nextdnscheck = 1; s = (char *) strchr (cptr->sockhost, '@'); s++; /* should never be NULL; cptr->sockhost is actually a conf->host */ - if ((cptr->ip.s_addr = inet_addr (s)) == -1) { - cptr->ip.s_addr = 0; + if (!irc_addr_from_str (&cptr->ip, s)) { + IRC_ADDR_ZERO (&cptr->ip); hp = gethost_byname (s, &lin); Debug ((DEBUG_NOTICE, "ping_sv: hp %x ac %x ho %s", hp, cptr, s)); if (!hp) return 0; - memcpy ((char *) &cptr->ip, hp->h_addr, sizeof (struct in_addr)); + cptr->ip = irc_addr_from_v4 ((struct in_addr *) hp->h_addr); } } return start_ping (cptr); @@ -395,7 +395,7 @@ int m_uping (aClient *cptr, aClient *sptr, int parc, char *parv[]) strcpy (cptr->sockhost, aconf->host); cptr->acpt = sptr; SetAskedPing (sptr); - memcpy ((void *) &cptr->ip, (void *) &aconf->ipnum, sizeof (struct in_addr)); + IRC_ADDR_COPY (&cptr->ip, &aconf->ipnum); strcpy (cptr->name, aconf->name); cptr->firsttime = 0; SetPing (cptr); diff --git a/src/s_user.c b/src/s_user.c index ec57021..b5bdeb6 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -262,7 +262,7 @@ int check_for_target_limit (aClient * sptr, void *target, const char *name) struct aThrottle { /* this is a throttle record */ - struct in_addr ip; + struct irc_addr ip; time_t last; struct aThrottle *next; char *connected; @@ -277,14 +277,13 @@ static struct aThrottle *throttles[256]; static void remove_clone_check (aClient * cptr) { - unsigned char *p = (unsigned char *) &cptr->ip.s_addr; struct aThrottle *ptr = - throttles[(p[0] + p[1] + p[2] + p[3]) & 0xff]; + throttles[irc_addr_hash (&cptr->ip)]; - if (cptr->ip.s_addr == 0) + if (irc_addr_is_zero (&cptr->ip)) return; - while (ptr && (cptr->ip.s_addr != ptr->ip.s_addr)) + while (ptr && !irc_addr_equal (&cptr->ip, &ptr->ip)) ptr = ptr->next; if (ptr && (ptr->count > 1)) @@ -294,14 +293,13 @@ static void remove_clone_check (aClient * cptr) int check_clones (aClient * cptr, const char *remote) { struct aThrottle **tscn, *tptr; - unsigned char *p = (unsigned char *) &cptr->ip.s_addr; - unsigned char hval = (unsigned char) (p[0] ^ p[1] ^ p[2] ^ p[3]) & 0xFF; + unsigned char hval = irc_addr_hash (&cptr->ip); tscn = &throttles[hval]; - if (cptr->ip.s_addr == 0) + if (irc_addr_is_zero (&cptr->ip)) return 0; - while (*tscn && (cptr->ip.s_addr != (*tscn)->ip.s_addr)) { + while (*tscn && !irc_addr_equal (&cptr->ip, &(*tscn)->ip)) { if ((*tscn)->last + cfg_clone_period < now) { tptr = *tscn; *tscn = tptr->next; @@ -490,7 +488,7 @@ static int register_user (aClient *cptr, aClient *sptr, char *nick, char *userna int ret = exit_client (cptr, sptr, sptr, "Your host/ip has been throttled"); static char hostip[128]; - strcpy (hostip, inetntoa ((char *) &sptr->ip)); + strcpy (hostip, inetntoa (&sptr->ip)); if (!ZLineExists (hostip)) { add_temp_conf (CONF_ZAP, hostip, "Too_many_connection_attempts_from_your_IP_address", @@ -526,7 +524,7 @@ static int register_user (aClient *cptr, aClient *sptr, char *nick, char *userna for (tmpstr = sptr->sockhost; *tmpstr > ' ' && *tmpstr < 127; tmpstr++); if (*tmpstr || !*user->host || isdigit (*(tmpstr - 1))) - strncpyzt (sptr->sockhost, (char *) inetntoa ((char *) &sptr->ip), sizeof (sptr->sockhost)); /* Fix the sockhost for debug jic */ + strncpyzt (sptr->sockhost, (char *) inetntoa (&sptr->ip), sizeof (sptr->sockhost)); /* Fix the sockhost for debug jic */ strncpyzt (user->host, sptr->sockhost, sizeof (sptr->sockhost)); } else /* Failsafe point, don't let the user define their @@ -691,7 +689,7 @@ static int register_user (aClient *cptr, aClient *sptr, char *nick, char *userna nextping = time (NULL); sendto_umode (UMODE_OPER | UMODE_CLIENT, "*** Notice -- Client connecting on port %d: %s (%s@%s) [%s] [%s/%s]", - sptr->acpt->port, nick, user->username, user->host, inetntoa ((char *) &sptr->ip), sptr->sup_host, sptr->sup_server); + sptr->acpt->port, nick, user->username, user->host, inetntoa (&sptr->ip), sptr->sup_host, sptr->sup_server); } else if (IsServer (cptr)) { aClient *acptr; @@ -2737,7 +2735,7 @@ int m_oper (aClient *cptr, aClient *sptr, int parc, char *parv[]) if (!(aconf = find_conf_exact (name, sptr->user->username, sptr->sockhost, CONF_OPS)) && !(aconf = find_conf_exact (name, sptr->user->username, - inetntoa ((char *) &cptr->ip), + inetntoa (&cptr->ip), CONF_OPS))) { sendto_one (sptr, err_str (ERR_NOOPERHOST), me.name, parv[0]); sendto_realops ("Failed OPER attempt by %s (%s@%s)", diff --git a/src/support.c b/src/support.c index 1013f56..804dffb 100644 --- a/src/support.c +++ b/src/support.c @@ -64,23 +64,17 @@ char * strtoken (char **save, char *str, char *fs) #endif /* HAVE_STRTOKEN */ /* - ** inetntoa -- changed name to remove collision possibility and - ** so behaviour is guaranteed to take a pointer arg. - ** -avalon 23/11/92 + ** inetntoa -- format an irc_addr to a static string buffer. + ** Supports both IPv4 and IPv6 addresses. */ -char * inetntoa (char *in) +char * inetntoa (const struct irc_addr *addr) { - static char buf[16]; - u_char *s = (u_char *) in; - int a, b, c, d; - - a = (int) *s++; - b = (int) *s++; - c = (int) *s++; - d = (int) *s++; - (void) sprintf (buf, "%d.%d.%d.%d", a, b, c, d); - + static char buf[IRC_ADDRSTRLEN]; + if (addr->family == AF_INET6) + inet_ntop (AF_INET6, &addr->addr.v6, buf, sizeof (buf)); + else + inet_ntop (AF_INET, &addr->addr.v4, buf, sizeof (buf)); return buf; } diff --git a/src/whowas.c b/src/whowas.c index ed77035..fbfb32f 100644 --- a/src/whowas.c +++ b/src/whowas.c @@ -41,7 +41,7 @@ void add_history (aClient *cptr) ip = ipaddress; if (MyClient (cptr)) - ip = inetntoa ((char *) &cptr->ip); + ip = inetntoa (&cptr->ip); else { strncpyzt (ip, "", 6); ip = ipaddress;