IPv6 Phase 1: Replace struct in_addr with dual-stack irc_addr abstraction
authorRemco Rijnders <remmy@serenity-irc.net>
Sat, 7 Mar 2026 17:17:36 +0000 (12:17 -0500)
committerRemco Rijnders <remmy@serenity-irc.net>
Sat, 7 Mar 2026 17:17:36 +0000 (12:17 -0500)
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 <noreply@anthropic.com>
12 files changed:
include/h.h
include/irc_addr.h [new file with mode: 0644]
include/struct.h
src/list.c
src/res.c
src/s_bsd.c
src/s_conf.c
src/s_misc.c
src/s_ping.c
src/s_user.c
src/support.c
src/whowas.c

index 04915a01ee5d62756c3ae00875df81dd1913ec3f..10b5e2de321f2a833e1fae3270838ddefe593c44 100644 (file)
@@ -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 (file)
index 0000000..539d878
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#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__ */
+
index e2d49487e8479e14106b96f66ceb64acf20b1aa3..d38ed2e7d7656b72f282b2380ea5cddc911e6faf 100644 (file)
@@ -28,6 +28,7 @@
 #include <netinet/in.h>
 #include <netdb.h>
 #include <stddef.h>
+#include "irc_addr.h"
 
 #ifdef USE_SYSLOG
 # include <syslog.h>
@@ -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 */
index 0a101de741b9838143b5ae1380819f996d69cfd6..eb1d5b2d592a2e600f7acadcb31ea0cb6b9d50e1 100644 (file)
@@ -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;
index 7a337de49e1f9b5d39dcca34497a1bc7aa648c45..e79c2389a086df1d7f0bed97a4af97bc99a525a1 100644 (file)
--- a/src/res.c
+++ b/src/res.c
 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;
     }
index 1bfa782055e1f1f8de3f78bc19f700b8c04725f4..ad2c48664e24e735f2b75ae35a26b76f0289c5b3 100644 (file)
@@ -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;
            }
index 08eb005e05311a7d553cadb9c94587e6ad9e4404..b4b913a83d4c711898e970a5231a02778fa0bfd6 100644 (file)
@@ -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;
     }
index f68b9729872ea49feeb54dbfaff9b8f5376dc590..5f458258322b3d2594c8e7956e7686513ec2804f 100644 (file)
@@ -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))
index 644e0fd92b401edbf019a11f7165c9d9891dfc61..107aaf6cb31ad1868b16b266f2b3cdc42aeea6d6 100644 (file)
@@ -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);
index ec57021574c32457a7211f45f946e6ce5755eeec..b5bdeb66f8c4c208301156cb67333075c09f3f11 100644 (file)
@@ -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)",
index 1013f56d016e50c0c5537a5771e3b9c68b08e624..804dffbc47f9476662dbb03bf37d0634595c1d62 100644 (file)
@@ -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;
 }
 
index ed7703570ca9eacbec261af65b69741bd4027c7f..fbfb32f53fa24849716865abe2f973ff31a759a9 100644 (file)
@@ -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, "<n/a>", 6);
        ip = ipaddress;