]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nis/nis-hosts.c
nss_nis, nss_nisplus: Remove RES_USE_INET6 handling
[thirdparty/glibc.git] / nis / nss_nis / nis-hosts.c
CommitLineData
04277e02 1/* Copyright (C) 1996-2019 Free Software Foundation, Inc.
6259ec0d 2 This file is part of the GNU C Library.
1e275b9e 3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6259ec0d
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.
6259ec0d
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.
6259ec0d 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/>. */
6259ec0d 18
1eb946b9 19#include <assert.h>
6259ec0d
UD
20#include <nss.h>
21#include <ctype.h>
6675b191
UD
22/* The following is an ugly trick to avoid a prototype declaration for
23 _nss_nis_endgrent. */
24#define _nss_nis_endhostent _nss_nis_endhostent_XXX
6259ec0d 25#include <netdb.h>
6675b191 26#undef _nss_nis_endhostent
6259ec0d
UD
27#include <string.h>
28#include <netinet/in.h>
29#include <arpa/inet.h>
ec999b8e 30#include <libc-lock.h>
6259ec0d
UD
31#include <rpcsvc/yp.h>
32#include <rpcsvc/ypclnt.h>
33
34#include "nss-nis.h"
35
6259ec0d
UD
36#define ENTNAME hostent
37#define DATABASE "hosts"
38#define NEED_H_ERRNO
39
ec255a97
FW
40#define EXTRA_ARGS , af
41#define EXTRA_ARGS_DECL , int af
1e275b9e 42
6259ec0d
UD
43#define ENTDATA hostent_data
44struct hostent_data
45 {
46 unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
47 char *h_addr_ptrs[2]; /* Points to that and null terminator. */
48 };
49
50#define TRAILING_LIST_MEMBER h_aliases
51#define TRAILING_LIST_SEPARATOR_P isspace
cf29ffbe 52#include <nss/nss_files/files-parse.c>
6259ec0d
UD
53LINE_PARSER
54("#",
55 {
56 char *addr;
57
58 STRING_FIELD (addr, isspace, 1);
59
1eb946b9
UD
60 assert (af == AF_INET || af == AF_INET6 || af == AF_UNSPEC);
61
6259ec0d 62 /* Parse address. */
1eb946b9 63 if (af != AF_INET6 && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
1e275b9e 64 {
ec255a97
FW
65 result->h_addrtype = AF_INET;
66 result->h_length = INADDRSZ;
1e275b9e 67 }
1eb946b9 68 else if (af != AF_INET
a682a1bf 69 && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
6259ec0d
UD
70 {
71 result->h_addrtype = AF_INET6;
72 result->h_length = IN6ADDRSZ;
73 }
74 else
1e275b9e
UD
75 /* Illegal address: ignore line. */
76 return 0;
6259ec0d
UD
77
78 /* Store a pointer to the address in the expected form. */
701666b7 79 entdata->h_addr_ptrs[0] = (char *) entdata->host_addr;
6259ec0d
UD
80 entdata->h_addr_ptrs[1] = NULL;
81 result->h_addr_list = entdata->h_addr_ptrs;
82
6259ec0d 83 STRING_FIELD (result->h_name, isspace, 1);
1e275b9e
UD
84 })
85
6259ec0d
UD
86
87__libc_lock_define_initialized (static, lock)
88
89static bool_t new_start = 1;
90static char *oldkey = NULL;
91static int oldkeylen = 0;
92
1eb946b9 93
6259ec0d 94enum nss_status
51eecc4a 95_nss_nis_sethostent (int stayopen)
6259ec0d
UD
96{
97 __libc_lock_lock (lock);
98
99 new_start = 1;
100 if (oldkey != NULL)
101 {
102 free (oldkey);
103 oldkey = NULL;
104 oldkeylen = 0;
105 }
106
107 __libc_lock_unlock (lock);
108
109 return NSS_STATUS_SUCCESS;
110}
6675b191
UD
111/* Make _nss_nis_endhostent an alias of _nss_nis_sethostent. We do this
112 even though the prototypes don't match. The argument of sethostent
113 is used so this makes no difference. */
114strong_alias (_nss_nis_sethostent, _nss_nis_endhostent)
6259ec0d 115
1eb946b9 116
1e275b9e 117/* The calling function always need to get a lock first. */
6259ec0d
UD
118static enum nss_status
119internal_nis_gethostent_r (struct hostent *host, char *buffer,
1e275b9e 120 size_t buflen, int *errnop, int *h_errnop,
ec255a97 121 int af)
6259ec0d
UD
122{
123 char *domain;
a1ffb40e 124 if (__glibc_unlikely (yp_get_default_domain (&domain)))
a334319f 125 return NSS_STATUS_UNAVAIL;
0ecb606c 126
2f1687b9
UD
127 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
128 buffer += pad;
129
ab9a9ff8 130 struct parser_data *data = (void *) buffer;
a1ffb40e 131 if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
6259ec0d 132 {
d71b808a 133 *errnop = ERANGE;
6259ec0d
UD
134 *h_errnop = NETDB_INTERNAL;
135 return NSS_STATUS_TRYAGAIN;
136 }
2f1687b9 137 buflen -= pad;
6259ec0d
UD
138
139 /* Get the next entry until we found a correct one. */
ab9a9ff8
UD
140 const size_t linebuflen = buffer + buflen - data->linebuffer;
141 int parse_res;
6259ec0d
UD
142 do
143 {
ab9a9ff8
UD
144 char *result;
145 int len;
146 char *outkey;
147 int keylen;
148 int yperr;
6259ec0d 149 if (new_start)
a682a1bf 150 yperr = yp_first (domain, "hosts.byname", &outkey, &keylen, &result,
ab9a9ff8 151 &len);
6259ec0d 152 else
a682a1bf 153 yperr = yp_next (domain, "hosts.byname", oldkey, oldkeylen, &outkey,
ab9a9ff8 154 &keylen, &result, &len);
6259ec0d 155
a1ffb40e 156 if (__glibc_unlikely (yperr != YPERR_SUCCESS))
a682a1bf 157 {
ab9a9ff8
UD
158 enum nss_status retval = yperr2nss (yperr);
159
6259ec0d
UD
160 switch (retval)
161 {
162 case NSS_STATUS_TRYAGAIN:
d71b808a 163 *errnop = errno;
6259ec0d
UD
164 *h_errnop = TRY_AGAIN;
165 break;
166 case NSS_STATUS_NOTFOUND:
167 *h_errnop = HOST_NOT_FOUND;
168 break;
169 default:
170 *h_errnop = NO_RECOVERY;
171 break;
172 }
173 return retval;
174 }
175
a1ffb40e 176 if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
a682a1bf
UD
177 {
178 free (result);
6259ec0d 179 *h_errnop = NETDB_INTERNAL;
a682a1bf
UD
180 *errnop = ERANGE;
181 return NSS_STATUS_TRYAGAIN;
182 }
6259ec0d 183
ab9a9ff8 184 char *p = strncpy (data->linebuffer, result, len);
6259ec0d
UD
185 data->linebuffer[len] = '\0';
186 while (isspace (*p))
187 ++p;
188 free (result);
189
ec255a97 190 parse_res = parse_line (p, host, data, buflen, errnop, af);
a1ffb40e 191 if (__glibc_unlikely (parse_res == -1))
6259ec0d 192 {
60c96635 193 free (outkey);
d71b808a
UD
194 *h_errnop = NETDB_INTERNAL;
195 *errnop = ERANGE;
6259ec0d
UD
196 return NSS_STATUS_TRYAGAIN;
197 }
198 free (oldkey);
199 oldkey = outkey;
200 oldkeylen = keylen;
201 new_start = 0;
202 }
203 while (!parse_res);
204
205 *h_errnop = NETDB_SUCCESS;
206 return NSS_STATUS_SUCCESS;
207}
208
1eb946b9 209
1e275b9e 210enum nss_status
6259ec0d 211_nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
d71b808a 212 int *errnop, int *h_errnop)
6259ec0d 213{
1e275b9e 214 enum nss_status status;
6259ec0d
UD
215
216 __libc_lock_lock (lock);
217
1e275b9e 218 status = internal_nis_gethostent_r (host, buffer, buflen, errnop, h_errnop,
ec255a97 219 AF_INET);
6259ec0d
UD
220
221 __libc_lock_unlock (lock);
222
223 return status;
224}
225
1eb946b9 226
1e275b9e
UD
227static enum nss_status
228internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
d71b808a 229 char *buffer, size_t buflen, int *errnop,
ec255a97 230 int *h_errnop)
6259ec0d 231{
2f1687b9
UD
232 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
233 buffer += pad;
234
6259ec0d 235 struct parser_data *data = (void *) buffer;
6259ec0d
UD
236
237 if (name == NULL)
238 {
ac9f45cf 239 *errnop = EINVAL;
6259ec0d
UD
240 return NSS_STATUS_UNAVAIL;
241 }
242
ab9a9ff8 243 char *domain;
6259ec0d
UD
244 if (yp_get_default_domain (&domain))
245 return NSS_STATUS_UNAVAIL;
246
2f1687b9 247 if (buflen < sizeof *data + 1 + pad)
6259ec0d
UD
248 {
249 *h_errnop = NETDB_INTERNAL;
d71b808a 250 *errnop = ERANGE;
6259ec0d
UD
251 return NSS_STATUS_TRYAGAIN;
252 }
2f1687b9 253 buflen -= pad;
cd897fe7 254
ab9a9ff8
UD
255 /* Convert name to lowercase. */
256 size_t namlen = strlen (name);
315eb1d8
AS
257 /* Limit name length to the maximum size of an RPC packet. */
258 if (namlen > UDPMSGSIZE)
259 {
260 *errnop = ERANGE;
261 return NSS_STATUS_UNAVAIL;
262 }
263
ab9a9ff8
UD
264 char name2[namlen + 1];
265 size_t i;
cd897fe7 266
ab9a9ff8
UD
267 for (i = 0; i < namlen; ++i)
268 name2[i] = tolower (name[i]);
269 name2[i] = '\0';
cd897fe7 270
ab9a9ff8
UD
271 char *result;
272 int len;
273 int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
6259ec0d 274
a1ffb40e 275 if (__glibc_unlikely (yperr != YPERR_SUCCESS))
6259ec0d 276 {
ab9a9ff8
UD
277 enum nss_status retval = yperr2nss (yperr);
278
6259ec0d
UD
279 if (retval == NSS_STATUS_TRYAGAIN)
280 {
281 *h_errnop = TRY_AGAIN;
d71b808a 282 *errnop = errno;
6259ec0d
UD
283 }
284 if (retval == NSS_STATUS_NOTFOUND)
285 *h_errnop = HOST_NOT_FOUND;
286 return retval;
287 }
288
ab9a9ff8 289 const size_t linebuflen = buffer + buflen - data->linebuffer;
a1ffb40e 290 if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
6259ec0d
UD
291 {
292 free (result);
293 *h_errnop = NETDB_INTERNAL;
d71b808a 294 *errnop = ERANGE;
6259ec0d
UD
295 return NSS_STATUS_TRYAGAIN;
296 }
297
ab9a9ff8 298 char *p = strncpy (data->linebuffer, result, len);
6259ec0d
UD
299 data->linebuffer[len] = '\0';
300 while (isspace (*p))
301 ++p;
302 free (result);
303
ec255a97 304 int parse_res = parse_line (p, host, data, buflen, errnop, af);
6259ec0d 305
a1ffb40e 306 if (__glibc_unlikely (parse_res < 1 || host->h_addrtype != af))
6259ec0d 307 {
60c96635 308 if (parse_res == -1)
6259ec0d
UD
309 {
310 *h_errnop = NETDB_INTERNAL;
311 return NSS_STATUS_TRYAGAIN;
312 }
313 else
314 {
315 *h_errnop = HOST_NOT_FOUND;
316 return NSS_STATUS_NOTFOUND;
317 }
318 }
319
320 *h_errnop = NETDB_SUCCESS;
321 return NSS_STATUS_SUCCESS;
322}
323
1eb946b9 324
1e275b9e
UD
325enum nss_status
326_nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
327 char *buffer, size_t buflen, int *errnop,
328 int *h_errnop)
329{
1eb946b9
UD
330 if (af != AF_INET && af != AF_INET6)
331 {
332 *h_errnop = HOST_NOT_FOUND;
333 return NSS_STATUS_NOTFOUND;
334 }
335
1e275b9e 336 return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
ec255a97 337 h_errnop);
1e275b9e
UD
338}
339
1eb946b9 340
0d8733c4 341enum nss_status
d71b808a
UD
342_nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer,
343 size_t buflen, int *errnop, int *h_errnop)
0d8733c4 344{
1e275b9e 345 return internal_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
ec255a97 346 errnop, h_errnop);
0d8733c4
UD
347}
348
1eb946b9 349
6259ec0d 350enum nss_status
9d4d69b8 351_nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
6259ec0d 352 struct hostent *host, char *buffer, size_t buflen,
d71b808a 353 int *errnop, int *h_errnop)
6259ec0d 354{
ab9a9ff8 355 char *domain;
a1ffb40e 356 if (__glibc_unlikely (yp_get_default_domain (&domain)))
a334319f 357 return NSS_STATUS_UNAVAIL;
0ecb606c 358
2f1687b9
UD
359 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
360 buffer += pad;
361
ab9a9ff8 362 struct parser_data *data = (void *) buffer;
a1ffb40e 363 if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
6259ec0d 364 {
d71b808a 365 *errnop = ERANGE;
6259ec0d
UD
366 *h_errnop = NETDB_INTERNAL;
367 return NSS_STATUS_TRYAGAIN;
368 }
2f1687b9 369 buflen -= pad;
6259ec0d 370
ab9a9ff8 371 char *buf = inet_ntoa (*(const struct in_addr *) addr);
6259ec0d 372
ab9a9ff8
UD
373 char *result;
374 int len;
375 int yperr = yp_match (domain, "hosts.byaddr", buf, strlen (buf), &result,
376 &len);
6259ec0d 377
a1ffb40e 378 if (__glibc_unlikely (yperr != YPERR_SUCCESS))
6259ec0d 379 {
ab9a9ff8
UD
380 enum nss_status retval = yperr2nss (yperr);
381
6259ec0d
UD
382 if (retval == NSS_STATUS_TRYAGAIN)
383 {
384 *h_errnop = TRY_AGAIN;
d71b808a 385 *errnop = errno;
6259ec0d 386 }
ab9a9ff8 387 else if (retval == NSS_STATUS_NOTFOUND)
34816665
UD
388 *h_errnop = HOST_NOT_FOUND;
389
6259ec0d
UD
390 return retval;
391 }
392
ab9a9ff8 393 const size_t linebuflen = buffer + buflen - data->linebuffer;
a1ffb40e 394 if (__glibc_unlikely ((size_t) (len + 1) > linebuflen))
6259ec0d
UD
395 {
396 free (result);
d71b808a 397 *errnop = ERANGE;
6259ec0d
UD
398 *h_errnop = NETDB_INTERNAL;
399 return NSS_STATUS_TRYAGAIN;
400 }
401
ab9a9ff8 402 char *p = strncpy (data->linebuffer, result, len);
6259ec0d
UD
403 data->linebuffer[len] = '\0';
404 while (isspace (*p))
405 ++p;
406 free (result);
407
ec255a97 408 int parse_res = parse_line (p, host, data, buflen, errnop, af);
a1ffb40e 409 if (__glibc_unlikely (parse_res < 1))
6259ec0d 410 {
60c96635 411 if (parse_res == -1)
6259ec0d
UD
412 {
413 *h_errnop = NETDB_INTERNAL;
414 return NSS_STATUS_TRYAGAIN;
415 }
416 else
417 {
418 *h_errnop = HOST_NOT_FOUND;
419 return NSS_STATUS_NOTFOUND;
420 }
421 }
422
423 *h_errnop = NETDB_SUCCESS;
424 return NSS_STATUS_SUCCESS;
425}
1e275b9e 426
1eb946b9 427
1e275b9e 428enum nss_status
1eb946b9
UD
429_nss_nis_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
430 char *buffer, size_t buflen, int *errnop,
431 int *herrnop, int32_t *ttlp)
1e275b9e 432{
1eb946b9
UD
433 char *domain;
434 if (yp_get_default_domain (&domain))
a682a1bf
UD
435 {
436 *herrnop = NO_DATA;
437 return NSS_STATUS_UNAVAIL;
438 }
1eb946b9
UD
439
440 /* Convert name to lowercase. */
441 size_t namlen = strlen (name);
315eb1d8
AS
442 /* Limit name length to the maximum size of an RPC packet. */
443 if (namlen > UDPMSGSIZE)
444 {
445 *errnop = ERANGE;
446 return NSS_STATUS_UNAVAIL;
447 }
448
1eb946b9
UD
449 char name2[namlen + 1];
450 size_t i;
451
452 for (i = 0; i < namlen; ++i)
453 name2[i] = tolower (name[i]);
454 name2[i] = '\0';
455
456 char *result;
457 int len;
458 int yperr = yp_match (domain, "hosts.byname", name2, namlen, &result, &len);
459
a1ffb40e 460 if (__glibc_unlikely (yperr != YPERR_SUCCESS))
1eb946b9
UD
461 {
462 enum nss_status retval = yperr2nss (yperr);
463
464 if (retval == NSS_STATUS_TRYAGAIN)
465 {
466 *herrnop = TRY_AGAIN;
467 *errnop = errno;
468 }
469 if (retval == NSS_STATUS_NOTFOUND)
470 *herrnop = HOST_NOT_FOUND;
471 return retval;
472 }
473
1eb946b9
UD
474 if (*pat == NULL)
475 {
476 uintptr_t pad = (-(uintptr_t) buffer
477 % __alignof__ (struct gaih_addrtuple));
478 buffer += pad;
479 buflen = buflen > pad ? buflen - pad : 0;
480
a1ffb40e 481 if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
1eb946b9
UD
482 {
483 erange:
484 free (result);
485 *errnop = ERANGE;
486 *herrnop = NETDB_INTERNAL;
487 return NSS_STATUS_TRYAGAIN;
488 }
489
490 *pat = (struct gaih_addrtuple *) buffer;
491 buffer += sizeof (struct gaih_addrtuple);
492 buflen -= sizeof (struct gaih_addrtuple);
493 }
494
e87946cc
UD
495 uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct parser_data);
496 buffer += pad;
497
498 struct parser_data *data = (void *) buffer;
499
a1ffb40e 500 if (__glibc_unlikely (buflen < sizeof *data + 1 + pad))
1eb946b9 501 goto erange;
e87946cc
UD
502 buflen -= pad;
503
504 struct hostent host;
ec255a97 505 int parse_res = parse_line (result, &host, data, buflen, errnop, AF_UNSPEC);
a1ffb40e 506 if (__glibc_unlikely (parse_res < 1))
e87946cc
UD
507 {
508 if (parse_res == -1)
509 {
510 *herrnop = NETDB_INTERNAL;
511 return NSS_STATUS_TRYAGAIN;
512 }
513 else
514 {
515 *herrnop = HOST_NOT_FOUND;
516 return NSS_STATUS_NOTFOUND;
517 }
518 }
519
520 (*pat)->next = NULL;
1eb946b9
UD
521 (*pat)->family = host.h_addrtype;
522 memcpy ((*pat)->addr, host.h_addr_list[0], host.h_length);
523 (*pat)->scopeid = 0;
524 assert (host.h_addr_list[1] == NULL);
525
e87946cc
UD
526 /* Undo the alignment for parser_data. */
527 buffer -= pad;
528 buflen += pad;
529
530 size_t h_name_len = strlen (host.h_name) + 1;
531 if (h_name_len >= buflen)
532 goto erange;
905ef0da 533 (*pat)->name = memcpy (buffer, host.h_name, h_name_len);
e87946cc 534
1eb946b9
UD
535 free (result);
536
537 return NSS_STATUS_SUCCESS;
1e275b9e 538}