[PATCH 1/4] Change the resolver to use a larger maximum hostname length.

Since addresses in the ip6.arpa domain are longer than HOSTLEN characters, use a larger maximum length in the resolver code. --- src/res.c | 26 ++++++++++++++------------ 1 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/res.c b/src/res.c index dfda0ee..b4cad3b 100644 --- a/src/res.c +++ b/src/res.c @@ -56,6 +56,8 @@ #define TTL_SIZE 4 #define DLEN_SIZE 2 +#define RES_HOSTLEN 127 /* big enough to handle addresses in in6.arpa */ + extern int dn_expand(char *, char *, char *, char *, int); extern int dn_skipname(char *, char *); extern int @@ -68,7 +70,7 @@ extern int errno, h_errno; extern int highest_fd; extern aClient *local[]; -static char hostbuf[HOSTLEN + 1]; +static char hostbuf[RES_HOSTLEN + 1]; static int incache = 0; static CacheTable hashtable[ARES_CACSIZE]; static ResHash idcphashtable[ARES_IDCACSIZE]; @@ -501,10 +503,10 @@ struct hostent *gethost_byaddr(char *addr, Link *lp) static int do_query_name(Link *lp, char *name, ResRQ * rptr) { - char hname[HOSTLEN + 1]; + char hname[RES_HOSTLEN + 1]; int len; - strncpyzt(hname, name, HOSTLEN); + strncpyzt(hname, name, RES_HOSTLEN); len = strlen(hname); if (rptr && !strchr(hname, '.') && _res.options & RES_DEFNAMES) @@ -628,7 +630,7 @@ static void resend_query(ResRQ * rptr) int arpa_to_ip(char *arpastring, unsigned int *saddr) { int idx = 0, onum = 0; - char ipbuf[HOSTLEN + 1]; + char ipbuf[RES_HOSTLEN + 1]; char *fragptr[4]; u_char *ipptr; @@ -671,7 +673,7 @@ int arpa_to_ip(char *arpastring, unsigned int *saddr) #define MAX_ACCEPTABLE_ANS 10 -static char acceptable_answers[MAX_ACCEPTABLE_ANS][HOSTLEN + 1]; +static char acceptable_answers[MAX_ACCEPTABLE_ANS][RES_HOSTLEN + 1]; static int num_acc_answers = 0; #define add_acceptable_answer(x) do { \ @@ -691,7 +693,7 @@ static inline char *is_acceptable_answer(char *h) } #ifdef DNS_ANS_DEBUG_MAX -static char dhostbuf[HOSTLEN + 1]; +static char dhostbuf[RES_HOSTLEN + 1]; #endif /* process name server reply. */ @@ -736,9 +738,9 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) else { int strangeness = 0; - char tmphost[HOSTLEN]; + char tmphost[RES_HOSTLEN]; - hostbuf[HOSTLEN] = '\0'; + hostbuf[RES_HOSTLEN] = '\0'; cp += n; type = (int) _getshort(cp); cp += TYPE_SIZE; @@ -798,7 +800,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) while (hptr->ancount-- > 0 && cp && cp < eob) { n = dn_expand(buf, eob, cp, hostbuf, sizeof(hostbuf)-1); - hostbuf[HOSTLEN] = '\0'; + hostbuf[RES_HOSTLEN] = '\0'; if (n <= 0) break; @@ -826,7 +828,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) { strncpy(hostbuf, _res.defdname, sizeof(hostbuf) - 1 - len); - hostbuf[HOSTLEN] = '\0'; + hostbuf[RES_HOSTLEN] = '\0'; len = MIN(len + strlen(_res.defdname), sizeof(hostbuf)) - 1; } @@ -954,7 +956,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) * dn_expand also guarantee buffer is terminated with * null byte? Lets not take chances. -Dianora */ - hostbuf[HOSTLEN] = '\0'; + hostbuf[RES_HOSTLEN] = '\0'; cp += n; len = strlen(hostbuf); @@ -1070,7 +1072,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) break; } - hostbuf[HOSTLEN] = '\0'; + hostbuf[RES_HOSTLEN] = '\0'; cp += n; add_acceptable_answer(hostbuf); -- 1.7.2.3

These are Bob Jenkins' hash algorithms. The integer hash will allow us to hash IPv6 addresses in the future. --- include/res.h | 4 ++-- src/res.c | 52 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/include/res.h b/include/res.h index 95e3663..54fa8b2 100644 --- a/include/res.h +++ b/include/res.h @@ -74,8 +74,8 @@ typedef struct reshash ResRQ *cp_list; } ResHash; -#define ARES_CACSIZE 307 -#define ARES_IDCACSIZE 2099 +#define ARES_CACSIZE 8192 +#define ARES_IDCACSIZE 8192 #define IRC_MAXCACHED 281 diff --git a/src/res.c b/src/res.c index b4cad3b..5a67e02 100644 --- a/src/res.c +++ b/src/res.c @@ -91,7 +91,7 @@ static int add_request(ResRQ *); static ResRQ *make_request(Link *); static int send_res_msg(char *, int, int); static ResRQ *find_id(int); -static int hash_number(unsigned char *); +static int hash_number(unsigned char *, int); static unsigned int hash_id(unsigned int); static unsigned int hash_cp(char *); static void update_list(ResRQ *, aCache *); @@ -1412,15 +1412,26 @@ static struct hostent *getres_err(ResRQ * rptr, char *lp) return (struct hostent *) NULL; } -static int hash_number(unsigned char *ip) +static int hash_number(unsigned char *ip, int len) { + u_int *p, *end; u_int hashv = 0; - /* could use loop but slower */ - hashv += (int) *ip++; - hashv += hashv + (int) *ip++; - hashv += hashv + (int) *ip++; - hashv += hashv + (int) *ip++; + for (p = (u_int *)ip, end = (u_int *)(ip + len); p < end; p++) + { + u_int h; + + /* Bob Jenkins 4-byte integer hash, full avalanche */ + h = hashv + *p; + h = (h+0x7ed55d16) + (h<<12); + h = (h^0xc761c23c) ^ (h>>19); + h = (h+0x165667b1) + (h<<5); + h = (h+0xd3a2646c) ^ (h<<9); + h = (h+0xfd7046c5) + (h<<3); + h = (h^0xb55a4f09) ^ (h>>16); + hashv = h; + } + hashv %= ARES_CACSIZE; return (hashv); } @@ -1429,9 +1440,18 @@ static int hash_number(unsigned char *ip) static int hash_name(char *name) { u_int hashv = 0; - + + /* Bob Jenkins one-at-a-time hash */ for (; *name && *name != '.'; name++) + { hashv += *name; + hashv += (hashv << 10); + hashv ^= (hash >> 6); + } + hashv += (hashv << 3); + hashv ^= (hashv >> 11); + hashv += (hashv << 15); + hashv %= ARES_CACSIZE; return (hashv); } @@ -1439,6 +1459,13 @@ static int hash_name(char *name) static unsigned int hash_id(unsigned int id) { + /* Bob Jenkins 4-byte integer hash, full avalanche */ + id = (id+0x7ed55d16) + (id<<12); + id = (id^0xc761c23c) ^ (id>>19); + id = (id+0x165667b1) + (id<<5); + id = (id+0xd3a2646c) ^ (id<<9); + id = (id+0xfd7046c5) + (id<<3); + id = (id^0xb55a4f09) ^ (id>>16); return id % ARES_IDCACSIZE; } @@ -1476,7 +1503,7 @@ static aCache *add_to_cache(aCache * ocp) hashtable[hashv].name_list = ocp; #endif - hashv = hash_number((u_char *) ocp->he.h_addr); + hashv = hash_number((u_char *) ocp->he.h_addr, ocp->he.h_length); ocp->hnum_next = hashtable[hashv].num_list; hashtable[hashv].num_list = ocp; @@ -1677,7 +1704,7 @@ find_cache_number(ResRQ * rptr, char *numb) if ((u_char *) numb == (u_char *) NULL) return ((aCache *) NULL); - hashv = hash_number((u_char *) numb); + hashv = hash_number((u_char *) numb, sizeof(struct in_addr)); cp = hashtable[hashv].num_list; #ifdef DEBUG Debug((DEBUG_DNS, "find_cache_number:find %s[%08x]: hashv = %d", @@ -1715,7 +1742,8 @@ find_cache_number(ResRQ * rptr, char *numb) * if the first IP# has the same hashnumber as the IP# we are * looking for, its been done already. */ - if (hashv == hash_number((u_char *) cp->he.h_addr_list[0])) + if (hashv == hash_number((u_char *) cp->he.h_addr_list[0], + cp->he.h_length)) continue; for (i = 1; cp->he.h_addr_list[i]; i++) if (!memcmp(cp->he.h_addr_list[i], numb, @@ -1853,7 +1881,7 @@ static void rem_cache(aCache * ocp) } #endif /* remove cache entry from hashed number list */ - hashv = hash_number((u_char *) hp->h_addr); + hashv = hash_number((u_char *) hp->h_addr, hp->h_length); if (hashv < 0) return; #ifdef DEBUG -- 1.7.2.3

--- include/h.h | 4 +- include/res.h | 12 +++- src/res.c | 220 +++++++++++++++++++++++++++++++++++---------------------- src/s_bsd.c | 7 +- src/s_conf.c | 2 +- 5 files changed, 153 insertions(+), 92 deletions(-) diff --git a/include/h.h b/include/h.h index 8fc4181..36c8bd9 100644 --- a/include/h.h +++ b/include/h.h @@ -296,8 +296,8 @@ extern void set_effective_class(aClient *); extern void initclass(); extern struct hostent *get_res(char *); -extern struct hostent *gethost_byaddr(char *, Link *); -extern struct hostent *gethost_byname(char *, Link *); +extern struct hostent *gethost_byaddr(char *, Link *, int); +extern struct hostent *gethost_byname(char *, Link *, int); extern void flush_cache(void); extern int init_resolver(int); extern time_t timeout_query_list(time_t); diff --git a/include/res.h b/include/res.h index 54fa8b2..8d46e85 100644 --- a/include/res.h +++ b/include/res.h @@ -17,6 +17,11 @@ #define AR_TTL 600 /* TTL in seconds for dns cache entries */ +struct res_in_addr +{ + char buf[16]; +}; + struct hent { char *h_name; /* official name of host */ @@ -25,7 +30,7 @@ struct hent int h_length; /* length of address */ /* list of addresses from name server */ - struct in_addr h_addr_list[IRC_MAXADDRS]; + struct res_in_addr h_addr_list[IRC_MAXADDRS]; #define h_addr h_addr_list[0] /* address, for backward compatiblity */ }; @@ -42,7 +47,10 @@ typedef struct reslist char resend; /* send flag. 0 == dont resend */ time_t sentat; time_t timeout; - struct in_addr addr; + union + { + struct in_addr addr4; + } addr; char *name; Link cinfo; struct hent he; diff --git a/src/res.c b/src/res.c index 5a67e02..358b108 100644 --- a/src/res.c +++ b/src/res.c @@ -79,16 +79,16 @@ static ResRQ *last, *first; static void rem_cache(aCache *); static void rem_request(ResRQ *); -static int do_query_name(Link *, char *, ResRQ *); +static int do_query_name(Link *, char *, ResRQ *, int); static int do_query_number(Link *, struct in_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 add_request(ResRQ *); -static ResRQ *make_request(Link *); +static ResRQ *make_request(Link *, int); static int send_res_msg(char *, int, int); static ResRQ *find_id(int); static int hash_number(unsigned char *, int); @@ -125,6 +125,16 @@ static struct resinfo int re_unkrep; } reinfo; +static struct res_in_addr res_zeroaddr; + +static const char *resntoa(char *ip, int family) +{ + if (family == AF_INET) + return inetntoa(ip); + else + return "<unknown addrtype>"; +} + int init_resolver(int op) { int ret = 0; @@ -321,7 +331,7 @@ static void rem_request(ResRQ * old) } /* Create a DNS request record for the server. */ -static ResRQ *make_request(Link *lp) +static ResRQ *make_request(Link *lp, int family) { ResRQ *nreq; @@ -342,7 +352,7 @@ static ResRQ *make_request(Link *lp) memset((char *) &nreq->cinfo, '\0', sizeof(Link)); nreq->timeout = 4; /* start at 4 and exponential inc. */ - nreq->he.h_addrtype = AF_INET; + nreq->he.h_addrtype = family; nreq->he.h_name = NULL; nreq->he.h_aliases[0] = NULL; (void) add_request(nreq); @@ -469,7 +479,7 @@ static ResRQ *find_id(int id) return ret; } -struct hostent *gethost_byname(char *name, Link *lp) +struct hostent *gethost_byname(char *name, Link *lp, int family) { aCache *cp; @@ -481,11 +491,11 @@ struct hostent *gethost_byname(char *name, Link *lp) return (struct hostent *) &(cp->he); if (!lp) return NULL; - (void) do_query_name(lp, name, NULL); + (void) do_query_name(lp, name, NULL, family); return ((struct hostent *) NULL); } -struct hostent *gethost_byaddr(char *addr, Link *lp) +struct hostent *gethost_byaddr(char *addr, Link *lp, int family) { aCache *cp; @@ -493,15 +503,16 @@ struct hostent *gethost_byaddr(char *addr, Link *lp) return ((struct hostent *) NULL); reinfo.re_nu_look++; - if ((cp = find_cache_number(NULL, addr))) + if ((cp = find_cache_number(NULL, addr, family))) return (struct hostent *) &(cp->he); if (!lp) return NULL; - (void) do_query_number(lp, (struct in_addr *) addr, NULL); + if (family == AF_INET) + (void) do_query_number(lp, (struct in_addr *) addr, NULL); return ((struct hostent *) NULL); } -static int do_query_name(Link *lp, char *name, ResRQ * rptr) +static int do_query_name(Link *lp, char *name, ResRQ * rptr, int family) { char hname[RES_HOSTLEN + 1]; int len; @@ -525,7 +536,7 @@ static int do_query_name(Link *lp, char *name, ResRQ * rptr) */ if (!rptr) { - rptr = make_request(lp); + rptr = make_request(lp, AF_INET); rptr->type = T_A; rptr->name = (char *) MyMalloc(strlen(name) + 1); (void) strcpy(rptr->name, name); @@ -546,9 +557,9 @@ static int do_query_number(Link *lp, struct in_addr *numb, ResRQ * rptr) if (!rptr) { - rptr = make_request(lp); + rptr = make_request(lp, AF_INET); rptr->type = T_PTR; - rptr->addr.s_addr = numb->s_addr; + rptr->addr.addr4.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); @@ -615,10 +626,11 @@ static void resend_query(ResRQ * rptr) switch (rptr->type) { case T_PTR: - (void) do_query_number(NULL, &rptr->addr, rptr); + if (rptr->he.h_addrtype == AF_INET) + (void) do_query_number(NULL, &rptr->addr.addr4, rptr); break; case T_A: - (void) do_query_name(NULL, rptr->name, rptr); + (void) do_query_name(NULL, rptr->name, rptr, AF_INET); break; default: break; @@ -703,14 +715,14 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) struct hent *hp; int class, type, dlen, len, ans = 0, n, origtype = rptr->type; int adr = 0; - struct in_addr ptrrep, dr; num_acc_answers = 0; cp = buf + sizeof(HEADER); hp = (struct hent *) &(rptr->he); - while ((hp->h_addr_list[adr].s_addr) && (adr < IRC_MAXADDRS)) + while (memcmp(&hp->h_addr_list[adr], &res_zeroaddr, hp->h_length) != 0 && + adr < IRC_MAXADDRS) adr++; alias = hp->h_aliases; @@ -769,11 +781,16 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) else if(rptr->type == T_PTR) { u_char *ipp; - - ipp = (u_char *) &rptr->addr.s_addr; - ircsprintf(tmphost, "%u.%u.%u.%u.in-addr.arpa", - (u_int) (ipp[3]), (u_int) (ipp[2]), - (u_int) (ipp[1]), (u_int) (ipp[0])); + + if (rptr->he.h_addrtype == AF_INET) + { + ipp = (u_char *) &rptr->addr.addr4.s_addr; + ircsprintf(tmphost, "%u.%u.%u.%u.in-addr.arpa", + (u_int) (ipp[3]), (u_int) (ipp[2]), + (u_int) (ipp[1]), (u_int) (ipp[0])); + } + else + *tmphost = '\0'; } else { @@ -869,7 +886,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) if (ans == 1) hp->h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; /* from Christophe Kalt <kalt@stealth.net> */ - if (dlen != sizeof(dr)) + if (dlen != sizeof(struct in_addr)) { sendto_realops("Bad IP length (%d) returned for %s", dlen, hostbuf); @@ -881,14 +898,15 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) if(adr < IRC_MAXADDRS) { /* ensure we never go over the bounds of our adr array */ - memcpy((char *)&dr, cp, sizeof(dr)); - hp->h_addr_list[adr].s_addr = dr.s_addr; + memcpy((char *)&hp->h_addr_list[adr], cp, sizeof(struct in_addr)); Debug((DEBUG_INFO, "got ip # %s for %s", - inetntoa((char *) &hp->h_addr_list[adr]), hostbuf)); + resntoa((char *) &hp->h_addr_list[adr], + hp->h_addrtype), hostbuf)); #ifdef DNS_ANS_DEBUG_MAX sendto_realops_lev(DEBUG_LEV, "%s A %s", dhostbuf, - inetntoa((char *) &hp->h_addr_list[adr])); + resntoa((char *) &hp->h_addr_list[adr], + hp->h_addrtype)); #endif adr++; } @@ -907,18 +925,22 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) acc = NULL; if(!num_acc_answers || !(acc = is_acceptable_answer(hostbuf))) { + struct in_addr ptrrep; + if(!(arpa_to_ip(hostbuf, &ptrrep.s_addr))) { #ifdef DNS_ANS_DEBUG sendto_realops_lev(DEBUG_LEV, "Received strangely formed PTR answer " "for %s (asked for %s) -- ignoring", - hostbuf, inetntoa((char *)&rptr->addr)); + hostbuf, resntoa((char *)&rptr->addr, + rptr->he.h_addrtype)); #endif return PROCANSWER_STRANGE; } - if(ptrrep.s_addr != rptr->addr.s_addr) + if(rptr->he.h_addrtype != AF_INET || + ptrrep.s_addr != rptr->addr.addr4.s_addr) { #ifdef DNS_ANS_DEBUG char ipbuf[16]; @@ -927,7 +949,8 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) sendto_realops_lev(DEBUG_LEV, "Received DNS_PTR answer for %s, " "but asked question for %s", - ipbuf, inetntoa((char*)&rptr->addr)); + ipbuf, resntoa((char*)&rptr->addr, + rptr->he.h_addrtype)); #endif return PROCANSWER_STRANGE; } @@ -1001,6 +1024,8 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) { if(!num_acc_answers || !(acc = is_acceptable_answer(hostbuf))) { + struct in_addr ptrrep; + if(!(arpa_to_ip(hostbuf, &ptrrep.s_addr))) { #ifdef DNS_ANS_DEBUG @@ -1009,12 +1034,14 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) "CNAME(PTR) answer for %s (asked " "for %s) -- ignoring", hostbuf, - inetntoa((char *)&rptr->addr)); + resntoa((char *)&rptr->addr, + rptr->he.h_addrtype)); #endif return PROCANSWER_STRANGE; } - if(ptrrep.s_addr != rptr->addr.s_addr) + if(rptr->he.h_addrtype != AF_INET && + ptrrep.s_addr != rptr->addr.addr4.s_addr) { #ifdef DNS_ANS_DEBUG char ipbuf[16]; @@ -1024,7 +1051,8 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) "DNS_CNAME(PTR) answer for %s, " "but asked question for %s", ipbuf, - inetntoa((char*)&rptr->addr)); + resntoa((char *)&rptr->addr, + rptr->he.h_addrtype)); #endif return PROCANSWER_STRANGE; } @@ -1222,13 +1250,15 @@ 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, resntoa((char *) &rptr->he.h_addr, + rptr->he.h_addrtype))); /* * Lookup the 'authoritive' name that we were given for the ip#. * By using this call rather than regenerating the type we * automatically gain the use of the cache with no extra kludges. */ - if ((hp2 = gethost_byname(rptr->he.h_name, &rptr->cinfo))) + if ((hp2 = gethost_byname(rptr->he.h_name, &rptr->cinfo, + rptr->he.h_addrtype))) if (lp) memcpy(lp, (char *) &rptr->cinfo, sizeof(Link)); @@ -1249,7 +1279,7 @@ struct hostent *get_res(char *lp) { sendto_realops_lev(ADMIN_LEV, "Blindly accepting dns result for %s", rptr->he.h_name ? rptr->he.h_name : - inetntoa((char *)&rptr->addr)); + resntoa((char *)&rptr->addr, rptr->he.h_addrtype)); } else { @@ -1258,13 +1288,15 @@ struct hostent *get_res(char *lp) int found_match_ip = 0; int nidx, tidx; int numaddr, numnewaddr; - struct in_addr new_addr_list[IRC_MAXADDRS]; + struct res_in_addr new_addr_list[IRC_MAXADDRS]; if(!(rptr->he.h_name && rptr->he_rev.h_name)) invalid_parms_name++; - if(!(rptr->he.h_addr_list[0].s_addr && - rptr->he_rev.h_addr_list[0].s_addr)) + if (memcmp(&rptr->he.h_addr_list[0], &res_zeroaddr, + rptr->he.h_length) == 0 && + memcmp(&rptr->he_rev.h_addr_list[0], &res_zeroaddr, + rptr->he_rev.h_length) != 0) invalid_parms_ip++; if(invalid_parms_name || invalid_parms_ip) @@ -1274,7 +1306,8 @@ struct hostent *get_res(char *lp) invalid_parms_name ? "MISSING" : rptr->he.h_name, invalid_parms_ip ? "MISSING" : - inetntoa((char *)&rptr->he.h_addr_list[0])); + resntoa((char *)&rptr->he.h_addr_list[0], + rptr->he.h_addrtype)); if (lp) memcpy(lp, (char *) &rptr->cinfo, sizeof(Link)); rem_request(rptr); @@ -1291,18 +1324,22 @@ struct hostent *get_res(char *lp) { int does_match; - if(rptr->he.h_addr_list[nidx].s_addr == 0) + if (memcmp(&rptr->he.h_addr_list[nidx], &res_zeroaddr, + rptr->he.h_length) == 0) break; numaddr++; for(tidx = does_match = 0; tidx < IRC_MAXADDRS; tidx++) { - if(rptr->he_rev.h_addr_list[tidx].s_addr == 0) + if (memcmp(&rptr->he_rev.h_addr_list[tidx], &res_zeroaddr, + rptr->he_rev.h_length) == 0) break; - if(rptr->he_rev.h_addr_list[tidx].s_addr == - rptr->he.h_addr_list[nidx].s_addr) /* MATCH */ + if(rptr->he_rev.h_length == rptr->he.h_length && + memcmp(&rptr->he_rev.h_addr_list[tidx], + &rptr->he.h_addr_list[nidx], + rptr->he.h_length) == 0) /* MATCH */ { found_match_ip++; does_match = 1; @@ -1312,9 +1349,13 @@ struct hostent *get_res(char *lp) if(does_match) { - new_addr_list[numnewaddr++].s_addr = - rptr->he.h_addr_list[nidx].s_addr; - new_addr_list[numnewaddr].s_addr = 0; + /* RUNE */ + memcpy(&new_addr_list[numnewaddr++], + &rptr->he.h_addr_list[nidx], + rptr->he.h_length); + memset(&new_addr_list[numnewaddr], + 0, + sizeof(new_addr_list[numnewaddr])); } } @@ -1323,9 +1364,10 @@ struct hostent *get_res(char *lp) char ntoatmp_r[64]; char ntoatmp_f[64]; - strcpy(ntoatmp_f, inetntoa((char *)&rptr->he.h_addr_list[0])); - strcpy(ntoatmp_r, - inetntoa((char *)&rptr->he_rev.h_addr_list[0])); + strcpy(ntoatmp_f, resntoa((char *)&rptr->he.h_addr_list[0], + rptr->he.h_addrtype)); + strcpy(ntoatmp_r, resntoa((char *)&rptr->he_rev.h_addr_list[0], + rptr->he_rev.h_addrtype)); #ifdef DNS_ANS_DEBUG sendto_realops_lev(DEBUG_LEV, "Forward and Reverse queries do " "not have matching IP! %s<>%s %s<>%s", @@ -1350,8 +1392,9 @@ struct hostent *get_res(char *lp) if(numnewaddr != numaddr) { + /* RUNE */ memcpy(rptr->he.h_addr_list, new_addr_list, - sizeof(struct in_addr) * IRC_MAXADDRS); + sizeof(struct res_in_addr) * IRC_MAXADDRS); #ifdef DNS_ANS_DEBUG sendto_realops_lev(DEBUG_LEV, "numaddr = %d, numnewaddr = %d", numaddr, numnewaddr); @@ -1598,10 +1641,11 @@ static void update_list(ResRQ * rptr, aCache * cachep) for (i = 0; cp->he.h_addr_list[i]; i++); addrcount = i; /* 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 (s = (char *) &rptr->he.h_addr; + memcmp(s, &res_zeroaddr, rptr->he.h_length) != 0; + s += sizeof(struct res_in_addr)) { for (i = 0; (t = cp->he.h_addr_list[i]); i++) - if (!memcmp(s, t, sizeof(struct in_addr))) + if (!memcmp(s, t, rptr->he.h_length)) break; if (i >= IRC_MAXADDRS || addrcount >= IRC_MAXADDRS) @@ -1618,7 +1662,7 @@ static void update_list(ResRQ * rptr, aCache * cachep) base = cp->he.h_addr_list; addrcount++; t = (char *) MyRealloc(*base, - addrcount * sizeof(struct in_addr)); + addrcount * sizeof(struct res_in_addr)); base = (char **) MyRealloc(base, (addrcount + 1) * sizeof(char *)); @@ -1633,10 +1677,10 @@ static void update_list(ResRQ * rptr, aCache * cachep) for (; addrcount; addrcount--) { *base++ = t; - t += sizeof(struct in_addr); + t += sizeof(struct res_in_addr); } *base = NULL; - memcpy(*--base, s, sizeof(struct in_addr)); + memcpy(*--base, s, sizeof(struct res_in_addr)); } } return; @@ -1696,31 +1740,32 @@ static aCache *find_cache_name(char *name) /* find a cache entry by ip# and update its expire time */ static aCache * -find_cache_number(ResRQ * rptr, char *numb) +find_cache_number(ResRQ * rptr, char *numb, int family) { aCache *cp; - int hashv, i; - struct in_addr *ip = (struct in_addr *) numb; + int hashv, i, h_length; if ((u_char *) numb == (u_char *) NULL) return ((aCache *) NULL); - hashv = hash_number((u_char *) numb, sizeof(struct in_addr)); + if (family == AF_INET) + h_length = sizeof(struct in_addr); + else + h_length = 0; + hashv = hash_number((u_char *) numb, h_length); 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)); + { + Debug((DEBUG_DNS, "find_cache_number:find %s: hashv = %d", + resntoa(numb, family), hashv)); + } #endif for (; cp; cp = cp->hnum_next) { for (i = 0; cp->he.h_addr_list[i]; i++) { - /* - * A 32 bit integer compare should be faster than this... - * if (!memcmp(cp->he.h_addr_list[i], numb, - * sizeof(struct in_addr))) - */ - if(((struct in_addr *)cp->he.h_addr_list[i])->s_addr == ip->s_addr) + if (cp->he.h_length == h_length && + memcmp(cp->he.h_addr_list[i], numb, h_length) == 0) { cainfo.ca_nu_hits++; update_list(NULL, cp); @@ -1746,8 +1791,8 @@ find_cache_number(ResRQ * rptr, char *numb) cp->he.h_length)) 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 (cp->he.h_length == h_length && + !memcmp(cp->he.h_addr_list[i], numb, h_length)) { cainfo.ca_nu_hits++; update_list(NULL, cp); @@ -1766,38 +1811,43 @@ static aCache *make_cache(ResRQ * rptr) char *s, **t; /* shouldn't happen but it just might... */ - if (!rptr->he.h_name || !rptr->he.h_addr.s_addr) + if (!rptr->he.h_name || + memcmp(&rptr->he.h_addr, &res_zeroaddr, rptr->he.h_length) == 0) 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))) + if ((cp = find_cache_number(rptr, (char *) &rptr->he.h_addr, + rptr->he.h_addrtype))) return cp; - for (i = 1; rptr->he.h_addr_list[i].s_addr && i < IRC_MAXADDRS; i++) + for (i = 1; memcmp(&rptr->he.h_addr_list[i], &res_zeroaddr, + rptr->he.h_length) != 0 && i < IRC_MAXADDRS; i++) if ((cp = find_cache_number(rptr, - (char *) &(rptr->he.h_addr_list[i].s_addr)))) + (char *) &(rptr->he.h_addr_list[i]), + rptr->he.h_addrtype))) return cp; /* a matching entry wasnt found in the cache so go and make one up. */ cp = (aCache *) MyMalloc(sizeof(aCache)); memset((char *) cp, '\0', sizeof(aCache)); hp = &cp->he; for (i = 0; i < IRC_MAXADDRS; i++) - if (!rptr->he.h_addr_list[i].s_addr) + if (memcmp(&rptr->he.h_addr_list[i], &res_zeroaddr, + rptr->he.h_length) == 0) 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); + s = (char *) MyMalloc(sizeof(struct res_in_addr) * i); + memset(s, '\0', sizeof(struct res_in_addr) * i); - for (n = 0; n < i; n++, s += sizeof(struct in_addr)) + for (n = 0; n < i; n++, s += sizeof(struct res_in_addr)) { *t++ = s; - memcpy(s, (char *) &(rptr->he.h_addr_list[n].s_addr), - sizeof(struct in_addr)); + memcpy(s, (char *) &(rptr->he.h_addr_list[n]), + sizeof(struct res_in_addr)); } *t = (char *) NULL; /* an array of pointers to CNAMEs. */ @@ -1885,6 +1935,7 @@ static void rem_cache(aCache * ocp) if (hashv < 0) return; #ifdef DEBUG + /* RUNE */ Debug((DEBUG_DEBUG, "rem_cache: h_addr %s hashv %d next %#x first %#x", inetntoa(hp->h_addr), hashv, ocp->hnum_next, hashtable[hashv].num_list)); @@ -1978,7 +2029,8 @@ int m_dns(aClient *cptr, aClient *sptr, int parc, char *parv[]) { sendto_one(sptr, "NOTICE %s :Ex %ld ttl %ld host %s(%s)", parv[0], (long)(cp->expireat - timeofday), (long)cp->ttl, - cp->he.h_name, inetntoa(cp->he.h_addr)); + cp->he.h_name, resntoa(cp->he.h_addr, + cp->he.h_addrtype)); for (i = 0; cp->he.h_aliases[i]; i++) sendto_one(sptr, "NOTICE %s : %s = %s (CN)", parv[0], cp->he.h_name, @@ -1986,7 +2038,7 @@ int m_dns(aClient *cptr, aClient *sptr, int parc, char *parv[]) 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])); + resntoa(cp->he.h_addr_list[i], cp->he.h_addrtype)); } return 0; } diff --git a/src/s_bsd.c b/src/s_bsd.c index dc3a231..6baccff 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -737,7 +737,7 @@ int check_server_init(aClient * cptr) else s = aconn->host; Debug((DEBUG_DNS, "sv_ci:cache lookup (%s)", s)); - if((hp = gethost_byname(s, &lin))) + if((hp = gethost_byname(s, &lin, AF_INET))) { for (i = 0; hp->h_addr_list[i]; i++) if (!memcmp(hp->h_addr_list[i], (char *) &cptr->ip, @@ -1362,7 +1362,8 @@ aClient *add_connection(aListener *lptr, int fd) { Debug((DEBUG_DNS, "lookup %s", inetntoa((char *) &addr.addr4.sin_addr))); - acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip4, &lin); + acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip4, &lin, + AF_INET); } if (acptr->ip_family == AF_INET && !acptr->hostp) SetDNS(acptr); @@ -1822,7 +1823,7 @@ int connect_server(aConnect *aconn, aClient * by, struct hostent *hp) if ((aconn->ipnum.s_addr = inet_addr(s)) == -1) { aconn->ipnum.s_addr = 0; - hp = gethost_byname(s, &lin); + hp = gethost_byname(s, &lin, AF_INET); Debug((DEBUG_NOTICE, "co_sv: hp %x ac %x na %s ho %s", hp, aconn, aconn->name, s)); if (!hp) diff --git a/src/s_conf.c b/src/s_conf.c index 70d2eaf..6165c23 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -2342,7 +2342,7 @@ static int lookup_confhost(aConnect *aconn) if (IsDigit(*s)) aconn->ipnum.s_addr = inet_addr(s); - else if ((hp = gethost_byname(s, &ln))) + else if ((hp = gethost_byname(s, &ln, AF_INET))) memcpy((char *) &(aconn->ipnum), hp->h_addr, sizeof(struct in_addr)); -- 1.7.2.3

--- include/nameser.h | 1 + include/res.h | 1 + src/res.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++----- src/s_bsd.c | 20 ++++-- 4 files changed, 219 insertions(+), 28 deletions(-) diff --git a/include/nameser.h b/include/nameser.h index ef21c6a..bb22d24 100644 --- a/include/nameser.h +++ b/include/nameser.h @@ -84,6 +84,7 @@ #define T_MINFO 14 /* mailbox information */ #define T_MX 15 /* mail routing information */ #define T_TXT 16 /* text strings */ +#define T_AAAA 28 /* IP6 Address */ /* non standard */ diff --git a/include/res.h b/include/res.h index 8d46e85..9084a6e 100644 --- a/include/res.h +++ b/include/res.h @@ -50,6 +50,7 @@ typedef struct reslist union { struct in_addr addr4; + struct in6_addr addr6; } addr; char *name; Link cinfo; diff --git a/src/res.c b/src/res.c index 358b108..54c94a8 100644 --- a/src/res.c +++ b/src/res.c @@ -81,6 +81,7 @@ static void rem_cache(aCache *); static void rem_request(ResRQ *); static int do_query_name(Link *, char *, ResRQ *, int); static int do_query_number(Link *, struct in_addr *, ResRQ *); +static int do_query_number6(Link *, struct in6_addr *, ResRQ *); static void resend_query(ResRQ *); static int proc_answer(ResRQ *, HEADER *, char *, char *); static int query_name(char *, int, int, ResRQ *); @@ -509,6 +510,8 @@ struct hostent *gethost_byaddr(char *addr, Link *lp, int family) return NULL; if (family == AF_INET) (void) do_query_number(lp, (struct in_addr *) addr, NULL); + else if (family == AF_INET6) + (void) do_query_number6(lp, (struct in6_addr *) addr, NULL); return ((struct hostent *) NULL); } @@ -536,12 +539,13 @@ static int do_query_name(Link *lp, char *name, ResRQ * rptr, int family) */ if (!rptr) { - rptr = make_request(lp, AF_INET); - rptr->type = T_A; + rptr = make_request(lp, family); + rptr->type = (family == AF_INET6) ? T_AAAA : T_A; rptr->name = (char *) MyMalloc(strlen(name) + 1); (void) strcpy(rptr->name, name); } - return (query_name(hname, C_IN, T_A, rptr)); + return (query_name(hname, C_IN, (family == AF_INET6) ? T_AAAA : T_A, + rptr)); } /* Use this to do reverse IP# lookups. */ @@ -567,6 +571,45 @@ static int do_query_number(Link *lp, struct in_addr *numb, ResRQ * rptr) return (query_name(ipbuf, C_IN, T_PTR, rptr)); } +/* Use this to do reverse IP# lookups for IPv6 addresses. */ +static int do_query_number6(Link *lp, struct in6_addr *numb, ResRQ * rptr) +{ + char ipbuf[RES_HOSTLEN + 1]; + u_char *cp; + + cp = (u_char *) &numb->s6_addr; + (void)ircsprintf(ipbuf, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa.", + (u_int) (cp[15] & 0xf), (u_int) (cp[15] >> 4), + (u_int) (cp[14] & 0xf), (u_int) (cp[14] >> 4), + (u_int) (cp[13] & 0xf), (u_int) (cp[13] >> 4), + (u_int) (cp[12] & 0xf), (u_int) (cp[12] >> 4), + (u_int) (cp[11] & 0xf), (u_int) (cp[11] >> 4), + (u_int) (cp[10] & 0xf), (u_int) (cp[10] >> 4), + (u_int) (cp[ 9] & 0xf), (u_int) (cp[ 9] >> 4), + (u_int) (cp[ 8] & 0xf), (u_int) (cp[ 8] >> 4), + (u_int) (cp[ 7] & 0xf), (u_int) (cp[ 7] >> 4), + (u_int) (cp[ 6] & 0xf), (u_int) (cp[ 6] >> 4), + (u_int) (cp[ 5] & 0xf), (u_int) (cp[ 5] >> 4), + (u_int) (cp[ 4] & 0xf), (u_int) (cp[ 4] >> 4), + (u_int) (cp[ 3] & 0xf), (u_int) (cp[ 3] >> 4), + (u_int) (cp[ 2] & 0xf), (u_int) (cp[ 2] >> 4), + (u_int) (cp[ 1] & 0xf), (u_int) (cp[ 1] >> 4), + (u_int) (cp[ 0] & 0xf), (u_int) (cp[ 0] >> 4)); + + if (!rptr) + { + rptr = make_request(lp, AF_INET6); + rptr->type = T_PTR; + memcpy((char *) &rptr->addr.addr6, + (char *) &numb->s6_addr, sizeof(struct in6_addr)); + memcpy((char *) &rptr->he.h_addr, + (char *) &numb->s6_addr, sizeof(struct in6_addr)); + rptr->he.h_length = sizeof(struct in6_addr); + } + return (query_name(ipbuf, C_IN, T_PTR, rptr)); +} + /* generate a query based on class, type and name. */ static int query_name(char *name, int class, int type, ResRQ * rptr) { @@ -628,10 +671,15 @@ static void resend_query(ResRQ * rptr) case T_PTR: if (rptr->he.h_addrtype == AF_INET) (void) do_query_number(NULL, &rptr->addr.addr4, rptr); + else if (rptr->he.h_addrtype == AF_INET6) + (void) do_query_number6(NULL, &rptr->addr.addr6, rptr); break; case T_A: (void) do_query_name(NULL, rptr->name, rptr, AF_INET); break; + case T_AAAA: + (void) do_query_name(NULL, rptr->name, rptr, AF_INET6); + break; default: break; } @@ -680,6 +728,82 @@ int arpa_to_ip(char *arpastring, unsigned int *saddr) return 1; } +/* returns 0 on failure, nonzero on success */ +int arpa6_to_ip(char *arpastring, unsigned char *addr6) +{ + int idx = 0, n = 16; + unsigned char buf[16]; + + while(arpastring[idx]) + { + u_char c, x; + + c = arpastring[idx]; + if (c >= '0' && c <= '9') + { + x = c - '0'; + idx++; + } + else if (c >= 'a' && c <= 'f') + { + x = (c - 'a') + 10; + idx++; + } + else if (c >= 'A' && c <= 'F') + { + x = (c - 'A') + 10; + idx++; + } + else + return 0; + + c = arpastring[idx]; + if (c == '.') + idx++; + else + return 0; + + c = arpastring[idx]; + if (c >= '0' && c <= '9') + { + x |= (c - '0') << 4; + idx++; + } + else if (c >= 'a' && c <= 'f') + { + x |= ((c - 'a') + 10) << 4; + idx++; + } + else if (c >= 'A' && c <= 'F') + { + x |= ((c - 'A') + 10) << 4; + idx++; + } + else + return 0; + + buf[--n] = x; + + c = arpastring[idx]; + if (c == '.') + idx++; + else + return 0; + + if (n == 0) + break; + } + + if(n != 0) + return 0; + + if(mycmp(arpastring + idx, "ip6.arpa")) + return 0; + + memcpy(addr6, buf, sizeof(struct in6_addr)); + return 1; +} + #undef DNS_ANS_DEBUG_MAX #undef DNS_ANS_DEBUG @@ -778,6 +902,10 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) { strcpy(tmphost, rptr->name); } + else if(rptr->type == T_AAAA && rptr->name) + { + strcpy(tmphost, rptr->name); + } else if(rptr->type == T_PTR) { u_char *ipp; @@ -789,6 +917,28 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) (u_int) (ipp[3]), (u_int) (ipp[2]), (u_int) (ipp[1]), (u_int) (ipp[0])); } + else if (hp->h_addrtype == AF_INET6) + { + ipp = (u_char *) &rptr->addr.addr6.s6_addr; + (void)ircsprintf(tmphost, + "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", + (u_int) (ipp[15] & 0xf), (u_int) (ipp[15] >> 4), + (u_int) (ipp[14] & 0xf), (u_int) (ipp[14] >> 4), + (u_int) (ipp[13] & 0xf), (u_int) (ipp[13] >> 4), + (u_int) (ipp[12] & 0xf), (u_int) (ipp[12] >> 4), + (u_int) (ipp[11] & 0xf), (u_int) (ipp[11] >> 4), + (u_int) (ipp[10] & 0xf), (u_int) (ipp[10] >> 4), + (u_int) (ipp[ 9] & 0xf), (u_int) (ipp[ 9] >> 4), + (u_int) (ipp[ 8] & 0xf), (u_int) (ipp[ 8] >> 4), + (u_int) (ipp[ 7] & 0xf), (u_int) (ipp[ 7] >> 4), + (u_int) (ipp[ 6] & 0xf), (u_int) (ipp[ 6] >> 4), + (u_int) (ipp[ 5] & 0xf), (u_int) (ipp[ 5] >> 4), + (u_int) (ipp[ 4] & 0xf), (u_int) (ipp[ 4] >> 4), + (u_int) (ipp[ 3] & 0xf), (u_int) (ipp[ 3] >> 4), + (u_int) (ipp[ 2] & 0xf), (u_int) (ipp[ 2] >> 4), + (u_int) (ipp[ 1] & 0xf), (u_int) (ipp[ 1] >> 4), + (u_int) (ipp[ 0] & 0xf), (u_int) (ipp[ 0] >> 4)); + } else *tmphost = '\0'; } @@ -858,6 +1008,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) switch (type) { case T_A: + case T_AAAA: if(rptr->name == NULL) { sendto_realops_lev(DEBUG_LEV,"Received DNS_A answer, but null " @@ -883,10 +1034,13 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) #endif } hp->h_length = dlen; - if (ans == 1) + if (ans == 1 && type == T_A) hp->h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; + else if (ans == 1 && type == T_AAAA) + hp->h_addrtype = (class == C_IN) ? AF_INET6 : AF_UNSPEC; /* from Christophe Kalt <kalt@stealth.net> */ - if (dlen != sizeof(struct in_addr)) + if ((type == T_A && dlen != sizeof(struct in_addr)) || + (type == T_AAAA && dlen != sizeof(struct in6_addr))) { sendto_realops("Bad IP length (%d) returned for %s", dlen, hostbuf); @@ -898,7 +1052,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) if(adr < IRC_MAXADDRS) { /* ensure we never go over the bounds of our adr array */ - memcpy((char *)&hp->h_addr_list[adr], cp, sizeof(struct in_addr)); + memcpy((char *)&hp->h_addr_list[adr], cp, dlen); Debug((DEBUG_INFO, "got ip # %s for %s", resntoa((char *) &hp->h_addr_list[adr], hp->h_addrtype), hostbuf)); @@ -925,9 +1079,32 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) acc = NULL; if(!num_acc_answers || !(acc = is_acceptable_answer(hostbuf))) { - struct in_addr ptrrep; + union + { + struct in_addr addr4; + struct in6_addr addr6; + } ptrrep; - if(!(arpa_to_ip(hostbuf, &ptrrep.s_addr))) + if(arpa6_to_ip(hostbuf, ptrrep.addr6.s6_addr)) + { + if(rptr->he.h_addrtype != AF_INET6 || + memcmp(&ptrrep.addr6.s6_addr, rptr->addr.addr6.s6_addr, + sizeof(struct in6_addr)) != 0) + { +#ifdef DNS_ANS_DEBUG + char ipbuf[RES_HOSTLEN + 1]; + + strcpy(ipbuf, inet6ntoa((char *)&ptrrep.addr6)); + sendto_realops_lev(DEBUG_LEV, + "Received DNS_PTR answer for %s, " + "but asked question for %s", + ipbuf, resntoa((char*)&rptr->addr, + rptr->he.h_addrtype)); +#endif + return PROCANSWER_STRANGE; + } + } + else if(!(arpa_to_ip(hostbuf, &ptrrep.addr4.s_addr))) { #ifdef DNS_ANS_DEBUG sendto_realops_lev(DEBUG_LEV, @@ -938,21 +1115,23 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) #endif return PROCANSWER_STRANGE; } - - if(rptr->he.h_addrtype != AF_INET || - ptrrep.s_addr != rptr->addr.addr4.s_addr) + else { + if(rptr->he.h_addrtype != AF_INET || + ptrrep.addr4.s_addr != rptr->addr.addr4.s_addr) + { #ifdef DNS_ANS_DEBUG - char ipbuf[16]; - - strcpy(ipbuf, inetntoa((char *)&ptrrep)); - sendto_realops_lev(DEBUG_LEV, - "Received DNS_PTR answer for %s, " - "but asked question for %s", - ipbuf, resntoa((char*)&rptr->addr, - rptr->he.h_addrtype)); + char ipbuf[16]; + + strcpy(ipbuf, inetntoa((char *)&ptrrep.addr4)); + sendto_realops_lev(DEBUG_LEV, + "Received DNS_PTR answer for %s, " + "but asked question for %s", + ipbuf, resntoa((char*)&rptr->addr, + rptr->he.h_addrtype)); #endif - return PROCANSWER_STRANGE; + return PROCANSWER_STRANGE; + } } } @@ -1063,7 +1242,7 @@ static int proc_answer(ResRQ * rptr, HEADER *hptr, char *buf, char *eob) "from an acceptable (%s)", acc); #endif } - else if(origtype == T_A) + else if(origtype == T_A || origtype == T_AAAA) { if(mycmp(rptr->name, hostbuf) != 0) { @@ -1273,7 +1452,7 @@ struct hostent *get_res(char *lp) return hp2; } - if(a > 0 && rptr->type == T_A) + if(a > 0 && (rptr->type == T_A || rptr->type == T_AAAA)) { if(rptr->has_rev == 0) { @@ -1749,6 +1928,8 @@ find_cache_number(ResRQ * rptr, char *numb, int family) return ((aCache *) NULL); if (family == AF_INET) h_length = sizeof(struct in_addr); + else if (family == AF_INET6) + h_length = sizeof(struct in6_addr); else h_length = 0; hashv = hash_number((u_char *) numb, h_length); diff --git a/src/s_bsd.c b/src/s_bsd.c index 6baccff..65585e6 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -651,8 +651,9 @@ 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 (hp->h_addrtype == cptr->ip_family && + !memcmp(hp->h_addr_list[i], (char *) &cptr->ip, + hp->h_length)) break; if (!hp->h_addr_list[i]) @@ -1365,7 +1366,14 @@ aClient *add_connection(aListener *lptr, int fd) acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip4, &lin, AF_INET); } - if (acptr->ip_family == AF_INET && !acptr->hostp) + else if (acptr->ip_family == AF_INET6) + { + Debug((DEBUG_DNS, "lookup %s", + inet6ntoa((char *) &addr.addr6.s6_addr))); + acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip6, &lin, + AF_INET6); + } + if (!acptr->hostp) SetDNS(acptr); #ifdef SHOW_HEADERS else @@ -1828,7 +1836,7 @@ int connect_server(aConnect *aconn, aClient * by, struct hostent *hp) hp, aconn, aconn->name, s)); if (!hp) return 0; - memcpy((char *) &aconn->ipnum, hp->h_addr, sizeof(struct in_addr)); + memcpy((char *) &aconn->ipnum, hp->h_addr, hp->h_length); } } cptr = make_client(NULL, &me); @@ -2095,7 +2103,7 @@ void do_dns_async() if (hp && aconn) { memcpy((char *) &aconn->ipnum, hp->h_addr, - sizeof(struct in_addr)); + hp->h_length); connect_server(aconn, NULL, hp); } @@ -2107,7 +2115,7 @@ void do_dns_async() aconn = ln.value.aconn; if (hp && aconn) memcpy((char *) &aconn->ipnum, hp->h_addr, - sizeof(struct in_addr)); + hp->h_length); break; default: -- 1.7.2.3
participants (1)
-
Ned T. Crigler