]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 1997-2019 Free Software Foundation, Inc. |
e61abf83 | 2 | This file is part of the GNU C Library. |
1e275b9e | 3 | Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997. |
e61abf83 UD |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
e61abf83 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
e61abf83 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
e61abf83 | 18 | |
1eb946b9 | 19 | #include <assert.h> |
636e689e | 20 | #include <atomic.h> |
a334319f | 21 | #include <ctype.h> |
636e689e UD |
22 | #include <errno.h> |
23 | #include <netdb.h> | |
24 | #include <nss.h> | |
e61abf83 | 25 | #include <string.h> |
a334319f | 26 | #include <arpa/inet.h> |
636e689e | 27 | #include <netinet/in.h> |
a334319f | 28 | #include <rpcsvc/nis.h> |
ec999b8e | 29 | #include <libc-lock.h> |
e61abf83 UD |
30 | |
31 | #include "nss-nisplus.h" | |
32 | ||
33 | __libc_lock_define_initialized (static, lock) | |
34 | ||
fc9f33e3 UD |
35 | static nis_result *result; |
36 | static nis_name tablename_val; | |
37 | static u_long tablename_len; | |
e61abf83 | 38 | |
840094b5 | 39 | #define NISENTRYVAL(idx, col, res) \ |
a682a1bf | 40 | (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val) |
e61abf83 | 41 | |
840094b5 | 42 | #define NISENTRYLEN(idx, col, res) \ |
a682a1bf | 43 | (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len) |
e61abf83 UD |
44 | |
45 | /* Get implementation for some internal functions. */ | |
b76e0659 | 46 | #include <resolv/resolv-internal.h> |
d71b808a | 47 | #include <resolv/mapv4v6addr.h> |
e61abf83 | 48 | |
840094b5 | 49 | |
e61abf83 | 50 | static int |
900bec85 | 51 | _nss_nisplus_parse_hostent (nis_result *result, int af, struct hostent *host, |
1e275b9e UD |
52 | char *buffer, size_t buflen, int *errnop, |
53 | int flags) | |
e61abf83 | 54 | { |
7799b7b3 | 55 | unsigned int i; |
900bec85 UD |
56 | char *first_unused = buffer; |
57 | size_t room_left = buflen; | |
e61abf83 UD |
58 | |
59 | if (result == NULL) | |
26dee9c4 | 60 | return 0; |
e61abf83 | 61 | |
1eb946b9 UD |
62 | if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) |
63 | || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ | |
64 | || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "hosts_tbl") != 0 | |
65 | || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4) | |
26dee9c4 | 66 | return 0; |
e61abf83 | 67 | |
840094b5 UD |
68 | char *data = first_unused; |
69 | ||
1eb946b9 | 70 | if (room_left < (af != AF_INET || (flags & AI_V4MAPPED) != 0 |
840094b5 | 71 | ? IN6ADDRSZ : INADDRSZ)) |
e61abf83 | 72 | { |
60c96635 | 73 | no_more_room: |
d71b808a | 74 | *errnop = ERANGE; |
60c96635 | 75 | return -1; |
e61abf83 | 76 | } |
900bec85 | 77 | |
1e275b9e | 78 | /* Parse address. */ |
1eb946b9 UD |
79 | if (af != AF_INET6 |
80 | && inet_pton (AF_INET, NISENTRYVAL (0, 2, result), data) > 0) | |
900bec85 | 81 | { |
1eb946b9 | 82 | assert ((flags & AI_V4MAPPED) == 0 || af != AF_UNSPEC); |
1e275b9e | 83 | if (flags & AI_V4MAPPED) |
900bec85 UD |
84 | { |
85 | map_v4v6_address (data, data); | |
86 | host->h_addrtype = AF_INET6; | |
87 | host->h_length = IN6ADDRSZ; | |
88 | } | |
89 | else | |
90 | { | |
91 | host->h_addrtype = AF_INET; | |
92 | host->h_length = INADDRSZ; | |
93 | } | |
94 | } | |
1eb946b9 | 95 | else if (af != AF_INET |
1e275b9e UD |
96 | && inet_pton (AF_INET6, NISENTRYVAL (0, 2, result), data) > 0) |
97 | { | |
98 | host->h_addrtype = AF_INET6; | |
99 | host->h_length = IN6ADDRSZ; | |
100 | } | |
101 | else | |
102 | /* Illegal address: ignore line. */ | |
103 | return 0; | |
104 | ||
840094b5 UD |
105 | first_unused += host->h_length; |
106 | room_left -= host->h_length; | |
e61abf83 UD |
107 | |
108 | if (NISENTRYLEN (0, 0, result) + 1 > room_left) | |
60c96635 | 109 | goto no_more_room; |
8f2ece69 | 110 | |
900bec85 | 111 | host->h_name = first_unused; |
840094b5 UD |
112 | first_unused = __stpncpy (first_unused, NISENTRYVAL (0, 0, result), |
113 | NISENTRYLEN (0, 0, result)); | |
114 | *first_unused++ = '\0'; | |
840094b5 | 115 | |
1eb946b9 | 116 | room_left -= NISENTRYLEN (0, 0, result) + 1; |
840094b5 | 117 | char *line = first_unused; |
1eb946b9 UD |
118 | |
119 | /* When this is a call to gethostbyname4_r we do not need the aliases. */ | |
120 | if (af != AF_UNSPEC) | |
e61abf83 | 121 | { |
1eb946b9 UD |
122 | /* XXX Rewrite at some point to allocate the array first and then |
123 | copy the strings. It is wasteful to first concatenate the strings | |
124 | to just split them again later. */ | |
125 | for (i = 0; i < NIS_RES_NUMOBJ (result); ++i) | |
900bec85 | 126 | { |
1eb946b9 UD |
127 | if (strcmp (NISENTRYVAL (i, 1, result), host->h_name) != 0) |
128 | { | |
129 | if (NISENTRYLEN (i, 1, result) + 2 > room_left) | |
130 | goto no_more_room; | |
131 | ||
132 | *first_unused++ = ' '; | |
133 | first_unused = __stpncpy (first_unused, | |
134 | NISENTRYVAL (i, 1, result), | |
135 | NISENTRYLEN (i, 1, result)); | |
136 | *first_unused = '\0'; | |
137 | room_left -= NISENTRYLEN (i, 1, result) + 1; | |
138 | } | |
900bec85 | 139 | } |
1eb946b9 | 140 | *first_unused++ = '\0'; |
900bec85 | 141 | } |
880f421f | 142 | |
900bec85 UD |
143 | /* Adjust the pointer so it is aligned for |
144 | storing pointers. */ | |
840094b5 UD |
145 | size_t adjust = ((__alignof__ (char *) |
146 | - (first_unused - (char *) 0) % __alignof__ (char *)) | |
147 | % __alignof__ (char *)); | |
148 | if (room_left < adjust + 3 * sizeof (char *)) | |
a334319f | 149 | goto no_more_room; |
840094b5 UD |
150 | first_unused += adjust; |
151 | room_left -= adjust; | |
152 | host->h_addr_list = (char **) first_unused; | |
8f2ece69 | 153 | |
840094b5 | 154 | room_left -= 3 * sizeof (char *); |
900bec85 UD |
155 | host->h_addr_list[0] = data; |
156 | host->h_addr_list[1] = NULL; | |
157 | host->h_aliases = &host->h_addr_list[2]; | |
900bec85 | 158 | |
1eb946b9 UD |
159 | /* When this is a call to gethostbyname4_r we do not need the aliases. */ |
160 | if (af != AF_UNSPEC) | |
900bec85 | 161 | { |
1eb946b9 UD |
162 | i = 0; |
163 | while (*line != '\0') | |
164 | { | |
165 | /* Skip leading blanks. */ | |
166 | while (isspace (*line)) | |
167 | ++line; | |
900bec85 | 168 | |
1eb946b9 UD |
169 | if (*line == '\0') |
170 | break; | |
900bec85 | 171 | |
1eb946b9 UD |
172 | if (room_left < sizeof (char *)) |
173 | goto no_more_room; | |
900bec85 | 174 | |
1eb946b9 UD |
175 | room_left -= sizeof (char *); |
176 | host->h_aliases[i++] = line; | |
900bec85 | 177 | |
1eb946b9 UD |
178 | while (*line != '\0' && *line != ' ') |
179 | ++line; | |
900bec85 | 180 | |
1eb946b9 UD |
181 | if (*line == ' ') |
182 | *line++ = '\0'; | |
183 | } | |
840094b5 | 184 | |
1eb946b9 UD |
185 | host->h_aliases[i] = NULL; |
186 | } | |
840094b5 | 187 | |
900bec85 | 188 | return 1; |
e61abf83 UD |
189 | } |
190 | ||
840094b5 | 191 | |
2d7da676 | 192 | static enum nss_status |
d71b808a | 193 | _nss_create_tablename (int *errnop) |
2d7da676 UD |
194 | { |
195 | if (tablename_val == NULL) | |
196 | { | |
636e689e UD |
197 | const char *local_dir = nis_local_directory (); |
198 | size_t local_dir_len = strlen (local_dir); | |
199 | static const char prefix[] = "hosts.org_dir."; | |
2d7da676 | 200 | |
636e689e | 201 | char *p = malloc (sizeof (prefix) + local_dir_len); |
c8e82b4a | 202 | if (p == NULL) |
d71b808a UD |
203 | { |
204 | *errnop = errno; | |
205 | return NSS_STATUS_TRYAGAIN; | |
206 | } | |
636e689e UD |
207 | |
208 | memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1); | |
209 | ||
210 | tablename_len = sizeof (prefix) - 1 + local_dir_len; | |
211 | ||
212 | atomic_write_barrier (); | |
213 | ||
214 | tablename_val = p; | |
2d7da676 | 215 | } |
636e689e | 216 | |
2d7da676 UD |
217 | return NSS_STATUS_SUCCESS; |
218 | } | |
219 | ||
1eb946b9 | 220 | |
e61abf83 | 221 | enum nss_status |
51eecc4a | 222 | _nss_nisplus_sethostent (int stayopen) |
e61abf83 | 223 | { |
2d7da676 | 224 | enum nss_status status = NSS_STATUS_SUCCESS; |
d71b808a | 225 | int err; |
2d7da676 | 226 | |
e61abf83 UD |
227 | __libc_lock_lock (lock); |
228 | ||
636e689e UD |
229 | if (result != NULL) |
230 | { | |
231 | nis_freeresult (result); | |
232 | result = NULL; | |
233 | } | |
2d7da676 UD |
234 | |
235 | if (tablename_val == NULL) | |
d71b808a | 236 | status = _nss_create_tablename (&err); |
e61abf83 UD |
237 | |
238 | __libc_lock_unlock (lock); | |
239 | ||
2d7da676 | 240 | return status; |
e61abf83 UD |
241 | } |
242 | ||
1eb946b9 | 243 | |
e61abf83 UD |
244 | enum nss_status |
245 | _nss_nisplus_endhostent (void) | |
246 | { | |
247 | __libc_lock_lock (lock); | |
248 | ||
636e689e UD |
249 | if (result != NULL) |
250 | { | |
251 | nis_freeresult (result); | |
252 | result = NULL; | |
253 | } | |
e61abf83 UD |
254 | |
255 | __libc_lock_unlock (lock); | |
256 | ||
257 | return NSS_STATUS_SUCCESS; | |
258 | } | |
259 | ||
1eb946b9 | 260 | |
e61abf83 UD |
261 | static enum nss_status |
262 | internal_nisplus_gethostent_r (struct hostent *host, char *buffer, | |
d71b808a | 263 | size_t buflen, int *errnop, int *herrnop) |
e61abf83 UD |
264 | { |
265 | int parse_res; | |
266 | ||
267 | /* Get the next entry until we found a correct one. */ | |
268 | do | |
269 | { | |
60c96635 UD |
270 | nis_result *saved_res; |
271 | ||
e61abf83 UD |
272 | if (result == NULL) |
273 | { | |
60c96635 | 274 | saved_res = NULL; |
2d7da676 | 275 | if (tablename_val == NULL) |
d71b808a UD |
276 | { |
277 | enum nss_status status = _nss_create_tablename (errnop); | |
e61abf83 | 278 | |
d71b808a UD |
279 | if (status != NSS_STATUS_SUCCESS) |
280 | return status; | |
281 | } | |
282 | ||
283 | result = nis_first_entry (tablename_val); | |
487609e3 UD |
284 | if (result == NULL) |
285 | { | |
286 | *errnop = errno; | |
287 | return NSS_STATUS_TRYAGAIN; | |
288 | } | |
e61abf83 | 289 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
a682a1bf UD |
290 | { |
291 | enum nss_status retval = niserr2nss (result->status); | |
292 | if (retval == NSS_STATUS_TRYAGAIN) | |
293 | { | |
294 | *herrnop = NETDB_INTERNAL; | |
295 | *errnop = errno; | |
296 | } | |
297 | return retval; | |
298 | } | |
8f2ece69 | 299 | |
e61abf83 UD |
300 | } |
301 | else | |
302 | { | |
60c96635 | 303 | saved_res = result; |
487609e3 UD |
304 | result = nis_next_entry (tablename_val, &result->cookie); |
305 | if (result == NULL) | |
306 | { | |
307 | *errnop = errno; | |
308 | return NSS_STATUS_TRYAGAIN; | |
309 | } | |
e61abf83 | 310 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
a682a1bf UD |
311 | { |
312 | enum nss_status retval= niserr2nss (result->status); | |
e61abf83 | 313 | |
60c96635 UD |
314 | nis_freeresult (result); |
315 | result = saved_res; | |
a682a1bf UD |
316 | if (retval == NSS_STATUS_TRYAGAIN) |
317 | { | |
318 | *herrnop = NETDB_INTERNAL; | |
d71b808a | 319 | *errnop = errno; |
a682a1bf UD |
320 | } |
321 | return retval; | |
322 | } | |
e61abf83 | 323 | } |
8f2ece69 | 324 | |
b76e0659 | 325 | if (res_use_inet6 ()) |
1e275b9e UD |
326 | parse_res = _nss_nisplus_parse_hostent (result, AF_INET6, host, buffer, |
327 | buflen, errnop, AI_V4MAPPED); | |
328 | else | |
329 | parse_res = _nss_nisplus_parse_hostent (result, AF_INET, host, buffer, | |
330 | buflen, errnop, 0); | |
331 | ||
ac9f45cf | 332 | if (parse_res == -1) |
a682a1bf | 333 | { |
60c96635 UD |
334 | nis_freeresult (result); |
335 | result = saved_res; | |
a682a1bf | 336 | *herrnop = NETDB_INTERNAL; |
d71b808a | 337 | *errnop = ERANGE; |
a682a1bf UD |
338 | return NSS_STATUS_TRYAGAIN; |
339 | } | |
60c96635 UD |
340 | if (saved_res != NULL) |
341 | nis_freeresult (saved_res); | |
8f2ece69 | 342 | |
e61abf83 | 343 | } while (!parse_res); |
8f2ece69 | 344 | |
e61abf83 UD |
345 | return NSS_STATUS_SUCCESS; |
346 | } | |
347 | ||
1eb946b9 | 348 | |
e61abf83 UD |
349 | enum nss_status |
350 | _nss_nisplus_gethostent_r (struct hostent *result, char *buffer, | |
d71b808a | 351 | size_t buflen, int *errnop, int *herrnop) |
e61abf83 UD |
352 | { |
353 | int status; | |
354 | ||
355 | __libc_lock_lock (lock); | |
356 | ||
d71b808a UD |
357 | status = internal_nisplus_gethostent_r (result, buffer, buflen, errnop, |
358 | herrnop); | |
e61abf83 UD |
359 | |
360 | __libc_lock_unlock (lock); | |
361 | ||
362 | return status; | |
363 | } | |
364 | ||
1eb946b9 UD |
365 | |
366 | static enum nss_status | |
367 | get_tablename (int *herrnop) | |
368 | { | |
369 | __libc_lock_lock (lock); | |
370 | ||
371 | enum nss_status status = _nss_create_tablename (herrnop); | |
372 | ||
373 | __libc_lock_unlock (lock); | |
374 | ||
375 | if (status != NSS_STATUS_SUCCESS) | |
376 | *herrnop = NETDB_INTERNAL; | |
377 | ||
378 | return status; | |
379 | } | |
380 | ||
381 | ||
1e275b9e UD |
382 | static enum nss_status |
383 | internal_gethostbyname2_r (const char *name, int af, struct hostent *host, | |
384 | char *buffer, size_t buflen, int *errnop, | |
385 | int *herrnop, int flags) | |
e61abf83 | 386 | { |
2d7da676 | 387 | if (tablename_val == NULL) |
d71b808a | 388 | { |
1eb946b9 | 389 | enum nss_status status = get_tablename (herrnop); |
d71b808a | 390 | if (status != NSS_STATUS_SUCCESS) |
1eb946b9 | 391 | return status; |
d71b808a | 392 | } |
2d7da676 | 393 | |
e61abf83 UD |
394 | if (name == NULL) |
395 | { | |
d71b808a | 396 | *errnop = EINVAL; |
e61abf83 UD |
397 | *herrnop = NETDB_INTERNAL; |
398 | return NSS_STATUS_NOTFOUND; | |
399 | } | |
e61abf83 | 400 | |
636e689e UD |
401 | char buf[strlen (name) + 10 + tablename_len]; |
402 | int olderr = errno; | |
8f2ece69 | 403 | |
636e689e UD |
404 | /* Search at first in the alias list, and use the correct name |
405 | for the next search. */ | |
406 | snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val); | |
1eb946b9 | 407 | nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
a334319f | 408 | |
636e689e UD |
409 | if (result != NULL) |
410 | { | |
636e689e UD |
411 | /* If we did not find it, try it as original name. But if the |
412 | database is correct, we should find it in the first case, too. */ | |
1eb946b9 UD |
413 | char *bufptr = buf; |
414 | size_t buflen = sizeof (buf); | |
415 | ||
416 | if ((result->status == NIS_SUCCESS || result->status == NIS_S_SUCCESS) | |
417 | && __type_of (result->objects.objects_val) == NIS_ENTRY_OBJ | |
418 | && strcmp (result->objects.objects_val->EN_data.en_type, | |
419 | "hosts_tbl") == 0 | |
420 | && result->objects.objects_val->EN_data.en_cols.en_cols_len >= 3) | |
901956a5 | 421 | { |
636e689e | 422 | /* We need to allocate a new buffer since there is no |
1eb946b9 UD |
423 | guarantee the returned alias name has a length limit. */ |
424 | name = NISENTRYVAL(0, 0, result); | |
425 | size_t buflen = strlen (name) + 10 + tablename_len; | |
636e689e | 426 | bufptr = alloca (buflen); |
901956a5 | 427 | } |
e61abf83 | 428 | |
1eb946b9 UD |
429 | snprintf (bufptr, buflen, "[cname=%s],%s", name, tablename_val); |
430 | ||
e61abf83 | 431 | nis_freeresult (result); |
636e689e UD |
432 | result = nis_list (bufptr, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
433 | } | |
8f2ece69 | 434 | |
636e689e UD |
435 | if (result == NULL) |
436 | { | |
437 | *errnop = ENOMEM; | |
a682a1bf | 438 | *herrnop = NETDB_INTERNAL; |
636e689e UD |
439 | return NSS_STATUS_TRYAGAIN; |
440 | } | |
e61abf83 | 441 | |
1eb946b9 | 442 | int retval = niserr2nss (result->status); |
a1ffb40e | 443 | if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS)) |
636e689e UD |
444 | { |
445 | if (retval == NSS_STATUS_TRYAGAIN) | |
d71b808a | 446 | { |
636e689e | 447 | *errnop = errno; |
a682a1bf | 448 | *herrnop = TRY_AGAIN; |
d71b808a | 449 | } |
e61abf83 | 450 | else |
a682a1bf UD |
451 | { |
452 | __set_errno (olderr); | |
453 | *herrnop = NETDB_INTERNAL; | |
454 | } | |
636e689e UD |
455 | nis_freeresult (result); |
456 | return retval; | |
e61abf83 | 457 | } |
636e689e | 458 | |
1eb946b9 UD |
459 | int parse_res = _nss_nisplus_parse_hostent (result, af, host, buffer, |
460 | buflen, errnop, flags); | |
636e689e UD |
461 | |
462 | nis_freeresult (result); | |
463 | ||
464 | if (parse_res > 0) | |
465 | return NSS_STATUS_SUCCESS; | |
466 | ||
467 | *herrnop = NETDB_INTERNAL; | |
468 | if (parse_res == -1) | |
469 | { | |
470 | *errnop = ERANGE; | |
471 | return NSS_STATUS_TRYAGAIN; | |
472 | } | |
473 | ||
474 | __set_errno (olderr); | |
475 | return NSS_STATUS_NOTFOUND; | |
e61abf83 UD |
476 | } |
477 | ||
1eb946b9 | 478 | |
1e275b9e UD |
479 | enum nss_status |
480 | _nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host, | |
481 | char *buffer, size_t buflen, int *errnop, | |
482 | int *herrnop) | |
483 | { | |
1eb946b9 UD |
484 | if (af != AF_INET && af != AF_INET6) |
485 | { | |
486 | *herrnop = HOST_NOT_FOUND; | |
487 | return NSS_STATUS_NOTFOUND; | |
488 | } | |
489 | ||
1e275b9e UD |
490 | return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop, |
491 | herrnop, | |
b76e0659 | 492 | (res_use_inet6 () ? AI_V4MAPPED : 0)); |
1e275b9e UD |
493 | } |
494 | ||
1eb946b9 | 495 | |
e61abf83 UD |
496 | enum nss_status |
497 | _nss_nisplus_gethostbyname_r (const char *name, struct hostent *host, | |
d71b808a UD |
498 | char *buffer, size_t buflen, int *errnop, |
499 | int *h_errnop) | |
e61abf83 | 500 | { |
b76e0659 | 501 | if (res_use_inet6 ()) |
e61abf83 UD |
502 | { |
503 | enum nss_status status; | |
504 | ||
1e275b9e UD |
505 | status = internal_gethostbyname2_r (name, AF_INET6, host, buffer, |
506 | buflen, errnop, h_errnop, | |
507 | AI_V4MAPPED); | |
e61abf83 | 508 | if (status == NSS_STATUS_SUCCESS) |
a682a1bf | 509 | return status; |
e61abf83 UD |
510 | } |
511 | ||
1e275b9e UD |
512 | return internal_gethostbyname2_r (name, AF_INET, host, buffer, |
513 | buflen, errnop, h_errnop, 0); | |
e61abf83 UD |
514 | } |
515 | ||
1eb946b9 | 516 | |
e61abf83 | 517 | enum nss_status |
9d4d69b8 | 518 | _nss_nisplus_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af, |
900bec85 | 519 | struct hostent *host, char *buffer, |
d71b808a | 520 | size_t buflen, int *errnop, int *herrnop) |
e61abf83 | 521 | { |
2d7da676 | 522 | if (tablename_val == NULL) |
d71b808a | 523 | { |
1eb946b9 | 524 | enum nss_status status = get_tablename (herrnop); |
d71b808a UD |
525 | if (status != NSS_STATUS_SUCCESS) |
526 | return status; | |
527 | } | |
2d7da676 | 528 | |
e61abf83 UD |
529 | if (addr == NULL) |
530 | return NSS_STATUS_NOTFOUND; | |
8f2ece69 | 531 | |
636e689e UD |
532 | char buf[24 + tablename_len]; |
533 | int retval, parse_res; | |
534 | int olderr = errno; | |
0ecb606c | 535 | |
636e689e UD |
536 | snprintf (buf, sizeof (buf), "[addr=%s],%s", |
537 | inet_ntoa (*(const struct in_addr *) addr), tablename_val); | |
538 | nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); | |
0ecb606c | 539 | |
636e689e UD |
540 | if (result == NULL) |
541 | { | |
542 | __set_errno (ENOMEM); | |
543 | return NSS_STATUS_TRYAGAIN; | |
544 | } | |
0ecb606c | 545 | |
636e689e | 546 | retval = niserr2nss (result->status); |
a1ffb40e | 547 | if (__glibc_unlikely (retval != NSS_STATUS_SUCCESS)) |
636e689e UD |
548 | { |
549 | if (retval == NSS_STATUS_TRYAGAIN) | |
a334319f | 550 | { |
636e689e UD |
551 | *errnop = errno; |
552 | *herrnop = NETDB_INTERNAL; | |
a334319f UD |
553 | } |
554 | else | |
636e689e UD |
555 | __set_errno (olderr); |
556 | nis_freeresult (result); | |
557 | return retval; | |
558 | } | |
559 | ||
560 | parse_res = _nss_nisplus_parse_hostent (result, af, host, | |
561 | buffer, buflen, errnop, | |
b76e0659 | 562 | (res_use_inet6 () |
636e689e UD |
563 | ? AI_V4MAPPED : 0)); |
564 | nis_freeresult (result); | |
565 | ||
566 | if (parse_res > 0) | |
567 | return NSS_STATUS_SUCCESS; | |
568 | ||
569 | *herrnop = NETDB_INTERNAL; | |
570 | if (parse_res == -1) | |
571 | { | |
572 | *errnop = ERANGE; | |
573 | return NSS_STATUS_TRYAGAIN; | |
0ecb606c | 574 | } |
636e689e UD |
575 | |
576 | __set_errno (olderr); | |
577 | return NSS_STATUS_NOTFOUND; | |
e61abf83 | 578 | } |
1eb946b9 UD |
579 | |
580 | ||
581 | enum nss_status | |
582 | _nss_nisplus_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, | |
583 | char *buffer, size_t buflen, int *errnop, | |
584 | int *herrnop, int32_t *ttlp) | |
585 | { | |
586 | struct hostent host; | |
587 | ||
588 | enum nss_status status = internal_gethostbyname2_r (name, AF_UNSPEC, &host, | |
589 | buffer, buflen, | |
590 | errnop, herrnop, 0); | |
a1ffb40e | 591 | if (__glibc_likely (status == NSS_STATUS_SUCCESS)) |
1eb946b9 UD |
592 | { |
593 | if (*pat == NULL) | |
594 | { | |
595 | uintptr_t pad = (-(uintptr_t) buffer | |
596 | % __alignof__ (struct gaih_addrtuple)); | |
597 | buffer += pad; | |
598 | buflen = buflen > pad ? buflen - pad : 0; | |
599 | ||
a1ffb40e | 600 | if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple))) |
1eb946b9 UD |
601 | { |
602 | free (result); | |
603 | *errnop = ERANGE; | |
604 | *herrnop = NETDB_INTERNAL; | |
605 | return NSS_STATUS_TRYAGAIN; | |
606 | } | |
607 | } | |
608 | ||
609 | (*pat)->next = NULL; | |
610 | (*pat)->name = host.h_name; | |
611 | (*pat)->family = host.h_addrtype; | |
612 | ||
613 | memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length); | |
614 | (*pat)->scopeid = 0; | |
615 | assert (host.h_addr_list[1] == NULL); | |
616 | } | |
617 | ||
618 | return status; | |
619 | } |