| 1 | Revert this upstream commit: |
| 2 | |
| 3 | commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7 |
| 4 | Author: Andreas Schwab <schwab@suse.de> |
| 5 | Date: Thu Feb 19 15:52:08 2015 +0100 |
| 6 | |
| 7 | Simplify handling of nameserver configuration in resolver |
| 8 | |
| 9 | Remove use of ext.nsmap member of struct __res_state and always use |
| 10 | an identity mapping betwen the nsaddr_list array and the ext.nsaddrs |
| 11 | array. The fact that a nameserver has an IPv6 address is signalled by |
| 12 | setting nsaddr_list[].sin_family to zero. |
| 13 | |
| 14 | reverted: |
| 15 | Index: b/resolv/res_init.c |
| 16 | =================================================================== |
| 17 | --- a/resolv/res_init.c |
| 18 | +++ b/resolv/res_init.c |
| 19 | @@ -153,8 +153,10 @@ __res_vinit(res_state statp, int preinit |
| 20 | char *cp, **pp; |
| 21 | int n; |
| 22 | char buf[BUFSIZ]; |
| 23 | - int nserv = 0; /* number of nameservers read from file */ |
| 24 | - int have_serv6 = 0; |
| 25 | + int nserv = 0; /* number of IPv4 nameservers read from file */ |
| 26 | +#ifdef _LIBC |
| 27 | + int nservall = 0; /* number of (IPv4 + IPV6) nameservers read from file */ |
| 28 | +#endif |
| 29 | int haveenv = 0; |
| 30 | int havesearch = 0; |
| 31 | #ifdef RESOLVSORT |
| 32 | @@ -183,9 +185,15 @@ __res_vinit(res_state statp, int preinit |
| 33 | statp->_flags = 0; |
| 34 | statp->qhook = NULL; |
| 35 | statp->rhook = NULL; |
| 36 | + statp->_u._ext.nsinit = 0; |
| 37 | statp->_u._ext.nscount = 0; |
| 38 | - for (n = 0; n < MAXNS; n++) |
| 39 | - statp->_u._ext.nsaddrs[n] = NULL; |
| 40 | +#ifdef _LIBC |
| 41 | + statp->_u._ext.nscount6 = 0; |
| 42 | + for (n = 0; n < MAXNS; n++) { |
| 43 | + statp->_u._ext.nsaddrs[n] = NULL; |
| 44 | + statp->_u._ext.nsmap[n] = MAXNS; |
| 45 | + } |
| 46 | +#endif |
| 47 | |
| 48 | /* Allow user to override the local domain definition */ |
| 49 | if ((cp = getenv("LOCALDOMAIN")) != NULL) { |
| 50 | @@ -289,7 +297,11 @@ __res_vinit(res_state statp, int preinit |
| 51 | continue; |
| 52 | } |
| 53 | /* read nameservers to query */ |
| 54 | +#ifdef _LIBC |
| 55 | + if (MATCH(buf, "nameserver") && nservall < MAXNS) { |
| 56 | +#else |
| 57 | if (MATCH(buf, "nameserver") && nserv < MAXNS) { |
| 58 | +#endif |
| 59 | struct in_addr a; |
| 60 | |
| 61 | cp = buf + sizeof("nameserver") - 1; |
| 62 | @@ -297,12 +309,13 @@ __res_vinit(res_state statp, int preinit |
| 63 | cp++; |
| 64 | if ((*cp != '\0') && (*cp != '\n') |
| 65 | && __inet_aton(cp, &a)) { |
| 66 | - statp->nsaddr_list[nserv].sin_addr = a; |
| 67 | - statp->nsaddr_list[nserv].sin_family = AF_INET; |
| 68 | - statp->nsaddr_list[nserv].sin_port = |
| 69 | + statp->nsaddr_list[nservall].sin_addr = a; |
| 70 | + statp->nsaddr_list[nservall].sin_family = AF_INET; |
| 71 | + statp->nsaddr_list[nservall].sin_port = |
| 72 | htons(NAMESERVER_PORT); |
| 73 | nserv++; |
| 74 | #ifdef _LIBC |
| 75 | + nservall++; |
| 76 | } else { |
| 77 | struct in6_addr a6; |
| 78 | char *el; |
| 79 | @@ -344,11 +357,10 @@ __res_vinit(res_state statp, int preinit |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | - statp->nsaddr_list[nserv].sin_family = 0; |
| 84 | - statp->_u._ext.nsaddrs[nserv] = sa6; |
| 85 | - statp->_u._ext.nssocks[nserv] = -1; |
| 86 | - have_serv6 = 1; |
| 87 | - nserv++; |
| 88 | + statp->_u._ext.nsaddrs[nservall] = sa6; |
| 89 | + statp->_u._ext.nssocks[nservall] = -1; |
| 90 | + statp->_u._ext.nsmap[nservall] = MAXNS + 1; |
| 91 | + nservall++; |
| 92 | } |
| 93 | } |
| 94 | #endif |
| 95 | @@ -403,9 +415,10 @@ __res_vinit(res_state statp, int preinit |
| 96 | continue; |
| 97 | } |
| 98 | } |
| 99 | - statp->nscount = nserv; |
| 100 | + statp->nscount = nservall; |
| 101 | #ifdef _LIBC |
| 102 | - if (have_serv6) { |
| 103 | + if (nservall - nserv > 0) { |
| 104 | + statp->_u._ext.nscount6 = nservall - nserv; |
| 105 | /* We try IPv6 servers again. */ |
| 106 | statp->ipv6_unavail = false; |
| 107 | } |
| 108 | @@ -594,7 +607,11 @@ __res_iclose(res_state statp, bool free_ |
| 109 | statp->_vcsock = -1; |
| 110 | statp->_flags &= ~(RES_F_VC | RES_F_CONN); |
| 111 | } |
| 112 | +#ifdef _LIBC |
| 113 | + for (ns = 0; ns < MAXNS; ns++) |
| 114 | +#else |
| 115 | for (ns = 0; ns < statp->_u._ext.nscount; ns++) |
| 116 | +#endif |
| 117 | if (statp->_u._ext.nsaddrs[ns]) { |
| 118 | if (statp->_u._ext.nssocks[ns] != -1) { |
| 119 | close_not_cancel_no_status(statp->_u._ext.nssocks[ns]); |
| 120 | @@ -605,6 +622,8 @@ __res_iclose(res_state statp, bool free_ |
| 121 | statp->_u._ext.nsaddrs[ns] = NULL; |
| 122 | } |
| 123 | } |
| 124 | + if (free_addr) |
| 125 | + statp->_u._ext.nsinit = 0; |
| 126 | } |
| 127 | libc_hidden_def (__res_iclose) |
| 128 | |
| 129 | Index: b/resolv/res_send.c |
| 130 | =================================================================== |
| 131 | --- a/resolv/res_send.c |
| 132 | +++ b/resolv/res_send.c |
| 133 | @@ -176,7 +176,6 @@ evNowTime(struct timespec *res) { |
| 134 | |
| 135 | /* Forward. */ |
| 136 | |
| 137 | -static struct sockaddr *get_nsaddr (res_state, int); |
| 138 | static int send_vc(res_state, const u_char *, int, |
| 139 | const u_char *, int, |
| 140 | u_char **, int *, int *, int, u_char **, |
| 141 | @@ -214,21 +213,20 @@ res_ourserver_p(const res_state statp, c |
| 142 | in_port_t port = in4p->sin_port; |
| 143 | in_addr_t addr = in4p->sin_addr.s_addr; |
| 144 | |
| 145 | - for (ns = 0; ns < statp->nscount; ns++) { |
| 146 | + for (ns = 0; ns < MAXNS; ns++) { |
| 147 | const struct sockaddr_in *srv = |
| 148 | - (struct sockaddr_in *) get_nsaddr (statp, ns); |
| 149 | + (struct sockaddr_in *)EXT(statp).nsaddrs[ns]; |
| 150 | |
| 151 | - if ((srv->sin_family == AF_INET) && |
| 152 | + if ((srv != NULL) && (srv->sin_family == AF_INET) && |
| 153 | (srv->sin_port == port) && |
| 154 | (srv->sin_addr.s_addr == INADDR_ANY || |
| 155 | srv->sin_addr.s_addr == addr)) |
| 156 | return (1); |
| 157 | } |
| 158 | } else if (inp->sin6_family == AF_INET6) { |
| 159 | - for (ns = 0; ns < statp->nscount; ns++) { |
| 160 | - const struct sockaddr_in6 *srv |
| 161 | - = (struct sockaddr_in6 *) get_nsaddr (statp, ns); |
| 162 | - if ((srv->sin6_family == AF_INET6) && |
| 163 | + for (ns = 0; ns < MAXNS; ns++) { |
| 164 | + const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns]; |
| 165 | + if ((srv != NULL) && (srv->sin6_family == AF_INET6) && |
| 166 | (srv->sin6_port == inp->sin6_port) && |
| 167 | !(memcmp(&srv->sin6_addr, &in6addr_any, |
| 168 | sizeof (struct in6_addr)) && |
| 169 | @@ -378,48 +376,80 @@ __libc_res_nsend(res_state statp, const |
| 170 | * If the ns_addr_list in the resolver context has changed, then |
| 171 | * invalidate our cached copy and the associated timing data. |
| 172 | */ |
| 173 | - if (EXT(statp).nscount != 0) { |
| 174 | + if (EXT(statp).nsinit) { |
| 175 | int needclose = 0; |
| 176 | |
| 177 | if (EXT(statp).nscount != statp->nscount) |
| 178 | needclose++; |
| 179 | else |
| 180 | - for (ns = 0; ns < statp->nscount; ns++) { |
| 181 | - if (statp->nsaddr_list[ns].sin_family != 0 |
| 182 | + for (ns = 0; ns < MAXNS; ns++) { |
| 183 | + unsigned int map = EXT(statp).nsmap[ns]; |
| 184 | + if (map < MAXNS |
| 185 | && !sock_eq((struct sockaddr_in6 *) |
| 186 | - &statp->nsaddr_list[ns], |
| 187 | + &statp->nsaddr_list[map], |
| 188 | EXT(statp).nsaddrs[ns])) |
| 189 | { |
| 190 | needclose++; |
| 191 | break; |
| 192 | } |
| 193 | } |
| 194 | - if (needclose) { |
| 195 | + if (needclose) |
| 196 | __res_iclose(statp, false); |
| 197 | - EXT(statp).nscount = 0; |
| 198 | - } |
| 199 | } |
| 200 | |
| 201 | /* |
| 202 | * Maybe initialize our private copy of the ns_addr_list. |
| 203 | */ |
| 204 | - if (EXT(statp).nscount == 0) { |
| 205 | - for (ns = 0; ns < statp->nscount; ns++) { |
| 206 | - EXT(statp).nssocks[ns] = -1; |
| 207 | - if (statp->nsaddr_list[ns].sin_family == 0) |
| 208 | - continue; |
| 209 | - if (EXT(statp).nsaddrs[ns] == NULL) |
| 210 | - EXT(statp).nsaddrs[ns] = |
| 211 | + if (EXT(statp).nsinit == 0) { |
| 212 | + unsigned char map[MAXNS]; |
| 213 | + |
| 214 | + memset (map, MAXNS, sizeof (map)); |
| 215 | + for (n = 0; n < MAXNS; n++) { |
| 216 | + ns = EXT(statp).nsmap[n]; |
| 217 | + if (ns < statp->nscount) |
| 218 | + map[ns] = n; |
| 219 | + else if (ns < MAXNS) { |
| 220 | + free(EXT(statp).nsaddrs[n]); |
| 221 | + EXT(statp).nsaddrs[n] = NULL; |
| 222 | + EXT(statp).nsmap[n] = MAXNS; |
| 223 | + } |
| 224 | + } |
| 225 | + n = statp->nscount; |
| 226 | + if (statp->nscount > EXT(statp).nscount) |
| 227 | + for (n = EXT(statp).nscount, ns = 0; |
| 228 | + n < statp->nscount; n++) { |
| 229 | + while (ns < MAXNS |
| 230 | + && EXT(statp).nsmap[ns] != MAXNS) |
| 231 | + ns++; |
| 232 | + if (ns == MAXNS) |
| 233 | + break; |
| 234 | + /* NS never exceeds MAXNS, but gcc 4.9 somehow |
| 235 | + does not see this. */ |
| 236 | + DIAG_PUSH_NEEDS_COMMENT; |
| 237 | + DIAG_IGNORE_NEEDS_COMMENT (4.9, |
| 238 | + "-Warray-bounds"); |
| 239 | + EXT(statp).nsmap[ns] = n; |
| 240 | + DIAG_POP_NEEDS_COMMENT; |
| 241 | + map[n] = ns++; |
| 242 | + } |
| 243 | + EXT(statp).nscount = n; |
| 244 | + for (ns = 0; ns < EXT(statp).nscount; ns++) { |
| 245 | + n = map[ns]; |
| 246 | + if (EXT(statp).nsaddrs[n] == NULL) |
| 247 | + EXT(statp).nsaddrs[n] = |
| 248 | malloc(sizeof (struct sockaddr_in6)); |
| 249 | - if (EXT(statp).nsaddrs[ns] != NULL) |
| 250 | - memset (mempcpy(EXT(statp).nsaddrs[ns], |
| 251 | + if (EXT(statp).nsaddrs[n] != NULL) { |
| 252 | + memset (mempcpy(EXT(statp).nsaddrs[n], |
| 253 | &statp->nsaddr_list[ns], |
| 254 | sizeof (struct sockaddr_in)), |
| 255 | '\0', |
| 256 | sizeof (struct sockaddr_in6) |
| 257 | - sizeof (struct sockaddr_in)); |
| 258 | + EXT(statp).nssocks[n] = -1; |
| 259 | + n++; |
| 260 | + } |
| 261 | } |
| 262 | - EXT(statp).nscount = statp->nscount; |
| 263 | + EXT(statp).nsinit = 1; |
| 264 | } |
| 265 | |
| 266 | /* |
| 267 | @@ -428,37 +458,44 @@ __libc_res_nsend(res_state statp, const |
| 268 | */ |
| 269 | if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) && |
| 270 | (statp->options & RES_BLAST) == 0) { |
| 271 | - struct sockaddr_in ina; |
| 272 | - struct sockaddr_in6 *inp; |
| 273 | - int lastns = statp->nscount - 1; |
| 274 | - int fd; |
| 275 | - |
| 276 | - inp = EXT(statp).nsaddrs[0]; |
| 277 | - ina = statp->nsaddr_list[0]; |
| 278 | - fd = EXT(statp).nssocks[0]; |
| 279 | - for (ns = 0; ns < lastns; ns++) { |
| 280 | - EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1]; |
| 281 | - statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; |
| 282 | - EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; |
| 283 | - } |
| 284 | - EXT(statp).nsaddrs[lastns] = inp; |
| 285 | - statp->nsaddr_list[lastns] = ina; |
| 286 | - EXT(statp).nssocks[lastns] = fd; |
| 287 | + struct sockaddr_in6 *ina; |
| 288 | + unsigned int map; |
| 289 | + |
| 290 | + n = 0; |
| 291 | + while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS) |
| 292 | + n++; |
| 293 | + if (n < MAXNS) { |
| 294 | + ina = EXT(statp).nsaddrs[n]; |
| 295 | + map = EXT(statp).nsmap[n]; |
| 296 | + for (;;) { |
| 297 | + ns = n + 1; |
| 298 | + while (ns < MAXNS |
| 299 | + && EXT(statp).nsmap[ns] == MAXNS) |
| 300 | + ns++; |
| 301 | + if (ns == MAXNS) |
| 302 | + break; |
| 303 | + EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns]; |
| 304 | + EXT(statp).nsmap[n] = EXT(statp).nsmap[ns]; |
| 305 | + n = ns; |
| 306 | + } |
| 307 | + EXT(statp).nsaddrs[n] = ina; |
| 308 | + EXT(statp).nsmap[n] = map; |
| 309 | + } |
| 310 | } |
| 311 | |
| 312 | /* |
| 313 | * Send request, RETRY times, or until successful. |
| 314 | */ |
| 315 | for (try = 0; try < statp->retry; try++) { |
| 316 | - for (ns = 0; ns < statp->nscount; ns++) |
| 317 | + for (ns = 0; ns < MAXNS; ns++) |
| 318 | { |
| 319 | #ifdef DEBUG |
| 320 | char tmpbuf[40]; |
| 321 | #endif |
| 322 | -#if defined USE_HOOKS || defined DEBUG |
| 323 | - struct sockaddr *nsap = get_nsaddr (statp, ns); |
| 324 | -#endif |
| 325 | + struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; |
| 326 | |
| 327 | + if (nsap == NULL) |
| 328 | + goto next_ns; |
| 329 | same_ns: |
| 330 | #ifdef USE_HOOKS |
| 331 | if (__glibc_unlikely (statp->qhook != NULL)) { |
| 332 | @@ -615,21 +652,6 @@ libresolv_hidden_def (res_nsend) |
| 333 | |
| 334 | /* Private */ |
| 335 | |
| 336 | -static struct sockaddr * |
| 337 | -get_nsaddr (res_state statp, int n) |
| 338 | -{ |
| 339 | - |
| 340 | - if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL) |
| 341 | - /* EXT(statp).nsaddrs[n] holds an address that is larger than |
| 342 | - struct sockaddr, and user code did not update |
| 343 | - statp->nsaddr_list[n]. */ |
| 344 | - return (struct sockaddr *) EXT(statp).nsaddrs[n]; |
| 345 | - else |
| 346 | - /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n] |
| 347 | - has the same content as EXT(statp).nsaddrs[n]. */ |
| 348 | - return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; |
| 349 | -} |
| 350 | - |
| 351 | static int |
| 352 | send_vc(res_state statp, |
| 353 | const u_char *buf, int buflen, const u_char *buf2, int buflen2, |
| 354 | @@ -644,7 +666,7 @@ send_vc(res_state statp, |
| 355 | // XXX REMOVE |
| 356 | // int anssiz = *anssizp; |
| 357 | HEADER *anhp = (HEADER *) ans; |
| 358 | - struct sockaddr *nsap = get_nsaddr (statp, ns); |
| 359 | + struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; |
| 360 | int truncating, connreset, n; |
| 361 | /* On some architectures compiler might emit a warning indicating |
| 362 | 'resplen' may be used uninitialized. However if buf2 == NULL |
| 363 | @@ -677,8 +699,8 @@ send_vc(res_state statp, |
| 364 | |
| 365 | if (getpeername(statp->_vcsock, |
| 366 | (struct sockaddr *)&peer, &size) < 0 || |
| 367 | - !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) { |
| 368 | - __res_iclose(statp, false); |
| 369 | + !sock_eq(&peer, nsap)) { |
| 370 | + __res_iclose(statp, false); |
| 371 | statp->_flags &= ~RES_F_VC; |
| 372 | } |
| 373 | } |
| 374 | @@ -687,19 +709,20 @@ send_vc(res_state statp, |
| 375 | if (statp->_vcsock >= 0) |
| 376 | __res_iclose(statp, false); |
| 377 | |
| 378 | - statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); |
| 379 | + statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0); |
| 380 | if (statp->_vcsock < 0) { |
| 381 | *terrno = errno; |
| 382 | Perror(statp, stderr, "socket(vc)", errno); |
| 383 | return (-1); |
| 384 | } |
| 385 | __set_errno (0); |
| 386 | - if (connect(statp->_vcsock, nsap, |
| 387 | - nsap->sa_family == AF_INET |
| 388 | + if (connect(statp->_vcsock, (struct sockaddr *)nsap, |
| 389 | + nsap->sin6_family == AF_INET |
| 390 | ? sizeof (struct sockaddr_in) |
| 391 | : sizeof (struct sockaddr_in6)) < 0) { |
| 392 | *terrno = errno; |
| 393 | - Aerror(statp, stderr, "connect/vc", errno, nsap); |
| 394 | + Aerror(statp, stderr, "connect/vc", errno, |
| 395 | + (struct sockaddr *) nsap); |
| 396 | __res_iclose(statp, false); |
| 397 | return (0); |
| 398 | } |
| 399 | @@ -906,7 +929,8 @@ static int |
| 400 | reopen (res_state statp, int *terrno, int ns) |
| 401 | { |
| 402 | if (EXT(statp).nssocks[ns] == -1) { |
| 403 | - struct sockaddr *nsap = get_nsaddr (statp, ns); |
| 404 | + struct sockaddr *nsap |
| 405 | + = (struct sockaddr *) EXT(statp).nsaddrs[ns]; |
| 406 | socklen_t slen; |
| 407 | |
| 408 | /* only try IPv6 if IPv6 NS and if not failed before */ |