Commit | Line | Data |
---|---|---|
51db6920 VM |
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 */ |