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)
+/* Helper: format a cached hostent address for display */
+static const char *cache_addr_str(const struct hostent *hp, const char *addr)
{
- struct irc_addr a = irc_addr_from_v4 (in);
- return inetntoa (&a);
+ struct irc_addr a;
+ if (hp->h_addrtype == AF_INET6)
+ a = irc_addr_from_v6 ((struct in6_addr *) addr);
+ else
+ a = irc_addr_from_v4 ((struct in_addr *) addr);
+ return irc_addr_str (&a);
}
static char hostbuf[HOSTLEN + 1];
static void rem_cache (aCache *);
static int do_query_name (Link *, char *, ResRQ *);
-static int do_query_number (Link *, struct in_addr *, ResRQ *);
+static int do_query_number (Link *, struct irc_addr *, ResRQ *);
static void resend_query (ResRQ *);
static int proc_answer (ResRQ *, HEADER *, char *, char *);
static int query_name (char *, int, int, ResRQ *);
static aCache *make_cache (ResRQ *);
static aCache *find_cache_name (char *);
-static aCache *find_cache_number (ResRQ *, char *);
+static aCache *find_cache_number (ResRQ *, char *, int);
static int send_res_msg (char *, int, int);
static ResRQ *find_id (int);
static int hash_number (unsigned char *);
return NULL;
}
-struct hostent *gethost_byaddr (char *addr, Link *lp)
+struct hostent *gethost_byaddr (struct irc_addr *addr, Link *lp)
{
aCache *cp;
+ const void *raw;
+ int alen;
reinfo.re_nu_look++;
- if ((cp = find_cache_number (NULL, addr)))
+ alen = irc_addr_raw (addr, &raw);
+ if ((cp = find_cache_number (NULL, (char *) raw, alen)))
return (struct hostent *) &(cp->he);
if (!lp)
return NULL;
- (void) do_query_number (lp, (struct in_addr *) addr, NULL);
+ (void) do_query_number (lp, addr, NULL);
return NULL;
}
/*
* Use this to do reverse IP# lookups.
*/
-static int do_query_number (Link *lp, struct in_addr *numb, ResRQ *rptr)
+static int do_query_number (Link *lp, struct irc_addr *numb, ResRQ *rptr)
{
- char ipbuf[32];
- u_char *cp;
-
- cp = (u_char *) & numb->s_addr;
- (void) sprintf (ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
- (u_int) (cp[3]), (u_int) (cp[2]),
- (u_int) (cp[1]), (u_int) (cp[0]));
+ char ipbuf[128];
+
+ if (numb->family == AF_INET6) {
+ /* Build nibble-format ip6.arpa reverse name */
+ const u_char *b = (const u_char *) &numb->addr.v6;
+ char *p = ipbuf;
+ int i;
+ for (i = 15; i >= 0; i--) {
+ *p++ = "0123456789abcdef"[b[i] & 0x0f];
+ *p++ = '.';
+ *p++ = "0123456789abcdef"[(b[i] >> 4) & 0x0f];
+ *p++ = '.';
+ }
+ strcpy (p, "ip6.arpa.");
+ }
+ else {
+ u_char *cp = (u_char *) &numb->addr.v4.s_addr;
+ (void) sprintf (ipbuf, "%u.%u.%u.%u.in-addr.arpa.",
+ (u_int) (cp[3]), (u_int) (cp[2]),
+ (u_int) (cp[1]), (u_int) (cp[0]));
+ }
if (!rptr) {
rptr = make_request (lp);
rptr->type = T_PTR;
- rptr->addr.s_addr = numb->s_addr;
- memcpy ((char *) &rptr->he.h_addr, (char *) &numb->s_addr, sizeof (struct in_addr));
- rptr->he.h_length = sizeof (struct in_addr);
+ IRC_ADDR_COPY (&rptr->addr, numb);
+ IRC_ADDR_COPY (&rptr->he.h_addr, numb);
+ rptr->he.h_addrtype = numb->family;
+ rptr->he.h_length = (numb->family == AF_INET6) ? 16 : 4;
}
return (query_name (ipbuf, C_IN, T_PTR, rptr));
}
char *cp, **alias;
struct hent *hp;
int class, type, dlen, len, ans = 0, n;
- struct in_addr dr, *adr;
+ struct irc_addr *adr;
cp = buf + sizeof (HEADER);
hp = (struct hent *) &(rptr->he);
adr = &hp->h_addr;
- while (adr->s_addr)
+ while (!irc_addr_is_zero (adr))
adr++;
alias = hp->h_aliases;
while (*alias)
hp->h_length = dlen;
if (ans == 1)
hp->h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
- memcpy ((char *) &dr, cp, dlen);
- adr->s_addr = dr.s_addr;
+ adr->family = AF_INET;
+ memcpy (&adr->addr.v4, cp, dlen);
Debug ((DEBUG_INFO, "got ip # %s for %s",
- inetntoa_v4 (adr), hostbuf));
+ irc_addr_str (adr), hostbuf));
+ if (!hp->h_name) {
+ hp->h_name = (char *) MyMalloc (len + 1);
+ (void) strcpy (hp->h_name, hostbuf);
+ }
+ ans++;
+ adr++;
+ cp += dlen;
+ break;
+ case T_AAAA:
+ hp->h_length = dlen;
+ if (ans == 1)
+ hp->h_addrtype = (class == C_IN) ? AF_INET6 : AF_UNSPEC;
+ adr->family = AF_INET6;
+ memcpy (&adr->addr.v6, cp, dlen);
+ Debug ((DEBUG_INFO, "got ipv6 # %s for %s",
+ irc_addr_str (adr), hostbuf));
if (!hp->h_name) {
hp->h_name = (char *) MyMalloc (len + 1);
(void) strcpy (hp->h_name, hostbuf);
struct hostent *hp2 = NULL;
Debug ((DEBUG_DNS, "relookup %s <-> %s",
- rptr->he.h_name, inetntoa_v4 (&rptr->he.h_addr)));
+ rptr->he.h_name, irc_addr_str (&rptr->he.h_addr)));
if (!rptr->he.h_name) {
char badip[128];
sprintf (badip, "%s (a = %d)",
- inetntoa_v4 (&rptr->he.h_addr), a);
+ irc_addr_str (&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.",
{
aCache **cpp, *cp = cachep;
char *s, *t, **base;
- int i, j;
+ int i, j, n;
int addrcount;
/*
/*
* Do the same again for IP#'s.
*/
- for (s = (char *) &rptr->he.h_addr.s_addr;
- ((struct in_addr *) s)->s_addr; s += sizeof (struct in_addr)) {
- for (i = 0; (t = cp->he.h_addr_list[i]); i++)
- if (!memcmp (s, t, sizeof (struct in_addr)))
+ {
+ int addr_sz = cp->he.h_length;
+ int k;
+ for (k = 0; !irc_addr_is_zero (&rptr->he.h_addr_list[k]); k++) {
+ const void *raw;
+ int alen = irc_addr_raw (&rptr->he.h_addr_list[k], &raw);
+ if (alen != addr_sz)
+ continue; /* skip mismatched address families */
+ for (i = 0; (t = cp->he.h_addr_list[i]); i++)
+ if (!memcmp (raw, t, addr_sz))
+ break;
+ if (i >= MAXADDRS || addrcount >= MAXADDRS)
break;
- if (i >= MAXADDRS || addrcount >= MAXADDRS)
- break;
- /*
- * Oh man this is bad...I *HATE* it. -avalon
- *
- * Whats it do ? Reallocate two arrays, one of pointers
- * to "char *" and the other of IP addresses. Contents of
- * the IP array *MUST* be preserved and the pointers into
- * it recalculated.
- */
- if (!t) {
- base = cp->he.h_addr_list;
- addrcount++;
- t = (char *) MyRealloc (*base,
- addrcount * sizeof (struct in_addr));
- base =
- (char **) MyRealloc ((char *) base,
- (addrcount + 1) * sizeof (char *));
- cp->he.h_addr_list = base;
+ /*
+ * Oh man this is bad...I *HATE* it. -avalon
+ *
+ * Whats it do ? Reallocate two arrays, one of pointers
+ * to "char *" and the other of IP addresses. Contents of
+ * the IP array *MUST* be preserved and the pointers into
+ * it recalculated.
+ */
+ if (!t) {
+ base = cp->he.h_addr_list;
+ addrcount++;
+ t = (char *) MyRealloc (*base,
+ addrcount * addr_sz);
+ base =
+ (char **) MyRealloc ((char *) base,
+ (addrcount + 1) * sizeof (char *));
+ cp->he.h_addr_list = base;
#ifdef DEBUG
- Debug ((DEBUG_DNS, "u_l:add IP %x hal %x ac %d",
- ntohl (((struct in_addr *) s)->s_addr),
- cp->he.h_addr_list, addrcount));
+ Debug ((DEBUG_DNS, "u_l:add IP hal %x ac %d",
+ cp->he.h_addr_list, addrcount));
#endif
- for (; addrcount; addrcount--) {
- *base++ = t;
- t += sizeof (struct in_addr);
+ for (n = addrcount; n; n--) {
+ *base++ = t;
+ t += addr_sz;
+ }
+ *base = NULL;
+ memcpy (*--base, raw, addr_sz);
}
- *base = NULL;
- memcpy (*--base, s, sizeof (struct in_addr));
}
}
return;
/*
* find a cache entry by ip# and update its expire time
*/
-static aCache *find_cache_number (ResRQ *rptr, char *numb)
+static aCache *find_cache_number (ResRQ *rptr, char *numb, int addrlen)
{
aCache *cp;
int hashv, i;
-#ifdef DEBUG
- struct in_addr *ip = (struct in_addr *) numb;
-#endif
hashv = hash_number ((u_char *) numb);
cp = hashtable[hashv].num_list;
#ifdef DEBUG
- Debug ((DEBUG_DNS, "find_cache_number:find %s[%08x]: hashv = %d",
- inetntoa_v4 ((struct in_addr *) numb), ntohl (ip->s_addr), hashv));
+ Debug ((DEBUG_DNS, "find_cache_number:find hashv = %d addrlen = %d",
+ hashv, addrlen));
#endif
for (; cp; cp = cp->hnum_next)
- for (i = 0; cp->he.h_addr_list[i]; i++)
- if (!memcmp (cp->he.h_addr_list[i], numb, sizeof (struct in_addr))) {
- cainfo.ca_nu_hits++;
- update_list (rptr, cp);
- return cp;
- }
+ if (cp->he.h_length == addrlen)
+ for (i = 0; cp->he.h_addr_list[i]; i++)
+ if (!memcmp (cp->he.h_addr_list[i], numb, addrlen)) {
+ cainfo.ca_nu_hits++;
+ update_list (rptr, cp);
+ return cp;
+ }
for (cp = cachetop; cp; cp = cp->list_next) {
+ if (cp->he.h_length != addrlen)
+ continue;
/*
* single address entry...would have been done by hashed
* search above...
if (hashv == hash_number ((u_char *) cp->he.h_addr_list[0]))
continue;
for (i = 1; cp->he.h_addr_list[i]; i++)
- if (!memcmp (cp->he.h_addr_list[i], numb, sizeof (struct in_addr))) {
+ if (!memcmp (cp->he.h_addr_list[i], numb, addrlen)) {
cainfo.ca_nu_hits++;
update_list (rptr, cp);
return cp;
/*
** shouldn't happen but it just might...
*/
- if (!rptr->he.h_name || !rptr->he.h_addr.s_addr)
+ if (!rptr->he.h_name || irc_addr_is_zero (&rptr->he.h_addr))
return NULL;
/*
** Make cache entry. First check to see if the cache already exists
** and if so, return a pointer to it.
*/
- if ((cp = find_cache_number (rptr, (char *) &rptr->he.h_addr.s_addr)))
- return cp;
- for (i = 1; rptr->he.h_addr_list[i].s_addr; i++)
- if ((cp = find_cache_number (rptr,
- (char *) &(rptr->he.h_addr_list[i].
- s_addr))))
+ {
+ const void *raw;
+ int alen = irc_addr_raw (&rptr->he.h_addr, &raw);
+ if ((cp = find_cache_number (rptr, (char *) raw, alen)))
return cp;
+ for (i = 1; !irc_addr_is_zero (&rptr->he.h_addr_list[i]); i++) {
+ alen = irc_addr_raw (&rptr->he.h_addr_list[i], &raw);
+ if ((cp = find_cache_number (rptr, (char *) raw, alen)))
+ return cp;
+ }
+ }
/*
** a matching entry wasnt found in the cache so go and make one up.
hp = &cp->he;
for (i = 0; i < MAXADDRS; i++)
- if (!rptr->he.h_addr_list[i].s_addr)
+ if (irc_addr_is_zero (&rptr->he.h_addr_list[i]))
break;
/*
** build two arrays, one for IP#'s, another of pointers to them.
*/
- t = hp->h_addr_list = (char **) MyMalloc (sizeof (char *) * (i + 1));
- memset ((char *) t, 0, sizeof (char *) * (i + 1));
-
- s = (char *) MyMalloc (sizeof (struct in_addr) * i);
- memset (s, 0, sizeof (struct in_addr) * i);
-
- for (n = 0; n < i; n++, s += sizeof (struct in_addr)) {
- *t++ = s;
- memcpy (s, (char *) &(rptr->he.h_addr_list[n].s_addr), sizeof (struct in_addr));
+ {
+ int addr_sz = rptr->he.h_length;
+ t = hp->h_addr_list = (char **) MyMalloc (sizeof (char *) * (i + 1));
+ memset ((char *) t, 0, sizeof (char *) * (i + 1));
+
+ s = (char *) MyMalloc (addr_sz * i);
+ memset (s, 0, addr_sz * i);
+
+ for (n = 0; n < i; n++, s += addr_sz) {
+ const void *raw;
+ irc_addr_raw (&rptr->he.h_addr_list[n], &raw);
+ *t++ = s;
+ memcpy (s, raw, addr_sz);
+ }
+ *t = (char *) NULL;
}
- *t = (char *) NULL;
/*
** an array of pointers to CNAMEs.
*/
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_v4 ((struct in_addr *) hp->h_addr), hashv, ocp->hnum_next,
- hashtable[hashv].num_list));
+ Debug ((DEBUG_DEBUG, "rem_cache: h_addr hashv %d next %#x first %#x",
+ hashv, ocp->hnum_next, hashtable[hashv].num_list));
#endif
for (cp = &hashtable[hashv].num_list; *cp; cp = &((*cp)->hnum_next))
if (*cp == ocp) {
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_v4 ((struct in_addr *) cp->he.h_addr));
+ cp->he.h_name, cache_addr_str (&cp->he, 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_v4 ((struct in_addr *) cp->he.h_addr_list[i]));
+ cache_addr_str (&cp->he, cp->he.h_addr_list[i]));
}
return 0;
}
h = &c->he;
for (i = 0; h->h_addr_list[i]; i++) {
im += sizeof (char *);
- im += sizeof (struct in_addr);
+ im += h->h_length;
}
im += sizeof (char *);
for (i = 0; h->h_aliases[i]; i++) {