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