From b64e1566263764ddc1173cfa3f94d0ef92ae2883 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 31 May 2002 07:54:02 +0000 Subject: Update. 2002-05-21 Jakub Jelinek * resolv/resolv.h (struct __res_state): Remove unused nstimes. Add nsmap. * resolv/res_init.c (__res_vinit): Initialize nsmap array. Remove nstimes setting. (res_nclose): Check all MAXNS nameservers with non-NULL nsaddrs. * resolv/res_send.c (res_nsend): Don't close unconditionally if there is mix of IPv6 and IPv4 nameservers. Use nsmap array to find free slots and preserve nameserver ordering. Fix RES_ROTATE. --- ChangeLog | 12 +++++++ resolv/res_init.c | 16 ++++----- resolv/res_send.c | 101 +++++++++++++++++++++++++++++++++--------------------- resolv/resolv.h | 2 +- 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 56b6c1700c..f6efc19bfd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2002-05-21 Jakub Jelinek + + * resolv/resolv.h (struct __res_state): Remove unused nstimes. + Add nsmap. + * resolv/res_init.c (__res_vinit): Initialize nsmap array. + Remove nstimes setting. + (res_nclose): Check all MAXNS nameservers with non-NULL nsaddrs. + * resolv/res_send.c (res_nsend): Don't close unconditionally if + there is mix of IPv6 and IPv4 nameservers. + Use nsmap array to find free slots and preserve nameserver ordering. + Fix RES_ROTATE. + 2002-05-30 Ulrich Drepper * sysdeps/unix/sysv/linux/sys/sendfile.h: It is now possible to diff --git a/resolv/res_init.c b/resolv/res_init.c index bb66b02b6c..f5613825bf 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -182,8 +182,10 @@ __res_vinit(res_state statp, int preinit) { statp->_u._ext.nscount = 0; #ifdef _LIBC statp->_u._ext.nscount6 = 0; - for (n = 0; n < MAXNS; n++) - statp->_u._ext.nsaddrs[n] = NULL; + for (n = 0; n < MAXNS; n++) { + statp->_u._ext.nsaddrs[n] = NULL; + statp->_u._ext.nsmap[n] = MAXNS; + } #endif /* Allow user to override the local domain definition */ @@ -323,8 +325,8 @@ __res_vinit(res_state statp, int preinit) { sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(NAMESERVER_PORT); statp->_u._ext.nsaddrs[nservall] = sa6; - statp->_u._ext.nstimes[nservall] = RES_MAXTIME; statp->_u._ext.nssocks[nservall] = -1; + statp->_u._ext.nsmap[nservall] = MAXNS + 1; nservall++; } } @@ -537,16 +539,14 @@ res_nclose(res_state statp) { statp->_flags &= ~(RES_F_VC | RES_F_CONN); } #ifdef _LIBC - for (ns = 0; ns < statp->_u._ext.nscount + statp->_u._ext.nscount6; - ns++) + for (ns = 0; ns < MAXNS; ns++) #else for (ns = 0; ns < statp->_u._ext.nscount; ns++) #endif - { - if (statp->_u._ext.nssocks[ns] != -1) { + if (statp->_u._ext.nsaddrs[ns] + && statp->_u._ext.nssocks[ns] != -1) { (void) __close(statp->_u._ext.nssocks[ns]); statp->_u._ext.nssocks[ns] = -1; } - } statp->_u._ext.nsinit = 0; } diff --git a/resolv/res_send.c b/resolv/res_send.c index 751a5506a1..a163d06a0a 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -400,12 +400,15 @@ res_nsend(res_state statp, if (EXT(statp).nscount != statp->nscount) needclose++; else - for (ns = 0; ns < statp->nscount; ns++) #ifdef _LIBC - if (!sock_eq((struct sockaddr_in6 *) - &statp->nsaddr_list[ns], - EXT(statp).nsaddrs[ns])) + for (ns = 0; ns < MAXNS; ns++) { + unsigned int map = EXT(statp).nsmap[ns]; + if (map < MAXNS + && !sock_eq((struct sockaddr_in6 *) + &statp->nsaddr_list[map], + EXT(statp).nsaddrs[ns])) #else + for (ns = 0; ns < statp->nscount; ns++) { if (!sock_eq(&statp->nsaddr_list[ns], &EXT(statp).nsaddrs[ns])) #endif @@ -413,6 +416,7 @@ res_nsend(res_state statp, needclose++; break; } + } if (needclose) res_nclose(statp); } @@ -422,20 +426,34 @@ res_nsend(res_state statp, */ if (EXT(statp).nsinit == 0) { #ifdef _LIBC - n = 0; -#endif - for (ns = 0; ns < statp->nscount; ns++) { -#ifdef _LIBC - /* find a hole */ - while ((n < MAXNS) && - (EXT(statp).nsaddrs[n] != NULL) && - (EXT(statp).nsaddrs[n]->sin6_family == AF_INET6) && - !IN6_IS_ADDR_V4MAPPED( - &EXT(statp).nsaddrs[n]->sin6_addr)) - n++; - if (n == MAXNS) - break; - + unsigned char map[MAXNS]; + + memset (map, MAXNS, sizeof (map)); + for (n = 0; n < MAXNS; n++) { + ns = EXT(statp).nsmap[n]; + if (ns < statp->nscount) + map[ns] = n; + else if (ns < MAXNS) { + free(EXT(statp).nsaddrs[n]); + EXT(statp).nsaddrs[n] = NULL; + EXT(statp).nsmap[n] = MAXNS; + } + } + n = statp->nscount; + if (statp->nscount > EXT(statp).nscount) + for (n = EXT(statp).nscount, ns = 0; + n < statp->nscount; n++) { + while (ns < MAXNS + && EXT(statp).nsmap[ns] != MAXNS) + ns++; + if (ns == MAXNS) + break; + EXT(statp).nsmap[ns] = n; + map[n] = ns++; + } + EXT(statp).nscount = n; + for (ns = 0; ns < EXT(statp).nscount; ns++) { + n = map[ns]; if (EXT(statp).nsaddrs[n] == NULL) EXT(statp).nsaddrs[n] = malloc(sizeof (struct sockaddr_in6)); @@ -443,31 +461,18 @@ res_nsend(res_state statp, memcpy(EXT(statp).nsaddrs[n], &statp->nsaddr_list[ns], sizeof (struct sockaddr_in)); - EXT(statp).nstimes[n] = RES_MAXTIME; EXT(statp).nssocks[n] = -1; n++; } + } #else + for (ns = 0; ns < statp->nscount; ns++) { EXT(statp).nsaddrs[ns] = statp->nsaddr_list[ns]; - EXT(statp).nstimes[ns] = RES_MAXTIME; EXT(statp).nssocks[ns] = -1; -#endif - } - EXT(statp).nscount = statp->nscount; - EXT(statp).nsinit = 1; -#ifdef _LIBC - /* If holes left, free memory and set to NULL */ - while (n < MAXNS) { - if ((EXT(statp).nsaddrs[n] != NULL) && - ((EXT(statp).nsaddrs[n]->sin6_family != AF_INET6) - || IN6_IS_ADDR_V4MAPPED( - &EXT(statp).nsaddrs[n]->sin6_addr))) { - free(EXT(statp).nsaddrs[n]); - EXT(statp).nsaddrs[n] = NULL; - } - n++; } + EXT(statp).nscount = ns; #endif + EXT(statp).nsinit = 1; } /* @@ -478,12 +483,28 @@ res_nsend(res_state statp, (statp->options & RES_BLAST) == 0) { #ifdef _LIBC struct sockaddr_in6 *ina; - int lastns = statp->nscount + EXT(statp).nscount6 - 1; + unsigned int map; - ina = EXT(statp).nsaddrs[0]; - for (ns = 0; ns < lastns; ns++) - EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1]; - EXT(statp).nsaddrs[lastns] = ina; + n = 0; + while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS) + n++; + if (n < MAXNS) { + ina = EXT(statp).nsaddrs[n]; + map = EXT(statp).nsmap[n]; + for (;;) { + ns = n + 1; + while (ns < MAXNS + && EXT(statp).nsmap[ns] == MAXNS) + ns++; + if (ns == MAXNS) + break; + EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns]; + EXT(statp).nsmap[n] = EXT(statp).nsmap[ns]; + n = ns; + } + EXT(statp).nsaddrs[n] = ina; + EXT(statp).nsmap[n] = map; + } #else struct sockaddr_in ina; int lastns = statp->nscount - 1; diff --git a/resolv/resolv.h b/resolv/resolv.h index 238ea59d65..09bddb8965 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -130,7 +130,7 @@ struct __res_state { char pad[52]; /* On an i386 this means 512b total. */ struct { u_int16_t nscount; - u_int16_t nstimes[MAXNS]; /* ms. */ + u_int16_t nsmap[MAXNS]; int nssocks[MAXNS]; u_int16_t nscount6; u_int16_t nsinit; -- cgit v1.2.3