Updated to fedora-glibc-20041207T1331
[glibc.git] / glibc-compat / nss_nis / nis-hosts.c
blobc6c413c55d599addfee5aea9fd404d09275ea801
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <nss.h>
21 #include <ctype.h>
22 #include <glibc-compat/include/netdb.h>
23 #include <string.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <resolv.h>
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
31 #include "nss-nis.h"
33 /* Get implementation for some internal functions. */
34 #include "../../resolv/mapv4v6addr.h"
35 #include "../../resolv/mapv4v6hostent.h"
37 #define ENTNAME hostent
38 #define DATABASE "hosts"
39 #define NEED_H_ERRNO
41 #define ENTDATA hostent_data
42 struct hostent_data
44 unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
45 char *h_addr_ptrs[2]; /* Points to that and null terminator. */
48 #define TRAILING_LIST_MEMBER h_aliases
49 #define TRAILING_LIST_SEPARATOR_P isspace
50 #include "../nss_files/files-parse.c"
51 LINE_PARSER
52 ("#",
54 char *addr;
56 STRING_FIELD (addr, isspace, 1);
58 /* Parse address. */
59 if ((_res.options & RES_USE_INET6)
60 && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
62 result->h_addrtype = AF_INET6;
63 result->h_length = IN6ADDRSZ;
65 else
66 if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
68 if (_res.options & RES_USE_INET6)
70 map_v4v6_address ((char *) entdata->host_addr,
71 (char *) entdata->host_addr);
72 result->h_addrtype = AF_INET6;
73 result->h_length = IN6ADDRSZ;
75 else
77 result->h_addrtype = AF_INET;
78 result->h_length = INADDRSZ;
81 else
82 /* Illegal address: ignore line. */
83 return 0;
85 /* Store a pointer to the address in the expected form. */
86 entdata->h_addr_ptrs[0] = entdata->host_addr;
87 entdata->h_addr_ptrs[1] = NULL;
88 result->h_addr_list = entdata->h_addr_ptrs;
90 /* If we need the host entry in IPv6 form change it now. */
91 if (_res.options & RES_USE_INET6)
93 char *bufptr = data->linebuffer;
94 size_t buflen = (char *) data + datalen - bufptr;
95 int ibuflen = buflen; /* Use this for machines with size_t > int. */
96 map_v4v6_hostent (result, &bufptr, &ibuflen);
97 buflen = ibuflen;
100 STRING_FIELD (result->h_name, isspace, 1);
104 __libc_lock_define_initialized (static, lock)
106 static bool_t new_start = 1;
107 static char *oldkey = NULL;
108 static int oldkeylen = 0;
110 enum nss_status
111 _nss_nis_sethostent (void)
113 __libc_lock_lock (lock);
115 new_start = 1;
116 if (oldkey != NULL)
118 free (oldkey);
119 oldkey = NULL;
120 oldkeylen = 0;
123 __libc_lock_unlock (lock);
125 return NSS_STATUS_SUCCESS;
128 enum nss_status
129 _nss_nis_endhostent (void)
131 __libc_lock_lock (lock);
133 new_start = 1;
134 if (oldkey != NULL)
136 free (oldkey);
137 oldkey = NULL;
138 oldkeylen = 0;
141 __libc_lock_unlock (lock);
143 return NSS_STATUS_SUCCESS;
146 static enum nss_status
147 internal_nis_gethostent_r (struct hostent *host, char *buffer,
148 size_t buflen, int *h_errnop)
150 char *domain;
151 char *result;
152 int len, parse_res;
153 char *outkey;
154 int keylen;
155 struct parser_data *data = (void *) buffer;
156 size_t linebuflen = buffer + buflen - data->linebuffer;
158 if (yp_get_default_domain (&domain))
159 return NSS_STATUS_UNAVAIL;
161 if (buflen < sizeof *data + 1)
163 __set_errno (ERANGE);
164 *h_errnop = NETDB_INTERNAL;
165 return NSS_STATUS_TRYAGAIN;
168 /* Get the next entry until we found a correct one. */
171 enum nss_status retval;
172 char *p;
174 if (new_start)
175 retval = yperr2nss (yp_first (domain, "hosts.byname",
176 &outkey, &keylen, &result, &len));
177 else
178 retval = yperr2nss ( yp_next (domain, "hosts.byname",
179 oldkey, oldkeylen,
180 &outkey, &keylen, &result, &len));
182 if (retval != NSS_STATUS_SUCCESS)
184 switch (retval)
186 case NSS_STATUS_TRYAGAIN:
187 __set_errno (EAGAIN);
188 *h_errnop = TRY_AGAIN;
189 break;
190 case NSS_STATUS_NOTFOUND:
191 *h_errnop = HOST_NOT_FOUND;
192 break;
193 default:
194 *h_errnop = NO_RECOVERY;
195 break;
197 return retval;
200 if ((size_t) (len + 1) > linebuflen)
202 free (result);
203 *h_errnop = NETDB_INTERNAL;
204 __set_errno (ERANGE);
205 return NSS_STATUS_TRYAGAIN;
208 p = strncpy (data->linebuffer, result, len);
209 data->linebuffer[len] = '\0';
210 while (isspace (*p))
211 ++p;
212 free (result);
214 parse_res = parse_line (p, host, data, buflen);
215 if (parse_res == -1 && errno == ERANGE)
217 *h_errnop = NETDB_INTERNAL;;
218 return NSS_STATUS_TRYAGAIN;
220 free (oldkey);
221 oldkey = outkey;
222 oldkeylen = keylen;
223 new_start = 0;
225 while (!parse_res);
227 *h_errnop = NETDB_SUCCESS;
228 return NSS_STATUS_SUCCESS;
232 _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
233 int *h_errnop)
235 int status;
237 __libc_lock_lock (lock);
239 status = internal_nis_gethostent_r (host, buffer, buflen, h_errnop);
241 __libc_lock_unlock (lock);
243 return status;
246 enum nss_status
247 _nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
248 char *buffer, size_t buflen, int *h_errnop)
250 enum nss_status retval;
251 char *domain, *result, *p;
252 int len, parse_res;
253 struct parser_data *data = (void *) buffer;
254 size_t linebuflen = buffer + buflen - data->linebuffer;
256 if (name == NULL)
258 __set_errno (EINVAL);
259 return NSS_STATUS_UNAVAIL;
262 if (yp_get_default_domain (&domain))
263 return NSS_STATUS_UNAVAIL;
265 if (buflen < sizeof *data + 1)
267 *h_errnop = NETDB_INTERNAL;
268 __set_errno (ERANGE);
269 return NSS_STATUS_TRYAGAIN;
271 else
273 /* Convert name to lowercase. */
274 size_t namelen = strlen (name);
275 char name2[namelen + 1];
276 int i;
278 for (i = 0; i < namelen; ++i)
279 name2[i] = tolower (name[i]);
280 name2[i] = '\0';
282 retval = yperr2nss (yp_match (domain, "hosts.byname", name2,
283 namelen, &result, &len));
287 if (retval != NSS_STATUS_SUCCESS)
289 if (retval == NSS_STATUS_TRYAGAIN)
291 *h_errnop = TRY_AGAIN;
292 __set_errno (EAGAIN);
294 if (retval == NSS_STATUS_NOTFOUND)
295 *h_errnop = HOST_NOT_FOUND;
296 return retval;
299 if ((size_t) (len + 1) > linebuflen)
301 free (result);
302 *h_errnop = NETDB_INTERNAL;
303 __set_errno (ERANGE);
304 return NSS_STATUS_TRYAGAIN;
307 p = strncpy (data->linebuffer, result, len);
308 data->linebuffer[len] = '\0';
309 while (isspace (*p))
310 ++p;
311 free (result);
313 parse_res = parse_line (p, host, data, buflen);
315 if (parse_res == -1 && errno == ERANGE)
317 *h_errnop = NETDB_INTERNAL;
318 return NSS_STATUS_TRYAGAIN;
321 if (parse_res == 0 || host->h_addrtype != af)
323 *h_errnop = HOST_NOT_FOUND;
324 return NSS_STATUS_NOTFOUND;
327 *h_errnop = NETDB_SUCCESS;
328 return NSS_STATUS_SUCCESS;
331 enum nss_status
332 _nss_nis_gethostbyname_r (const char *name, struct hostent *host,
333 char *buffer, size_t buflen, int *h_errnop)
335 if (_res.options & RES_USE_INET6)
337 enum nss_status status;
339 status = _nss_nis_gethostbyname2_r (name, AF_INET6, host, buffer, buflen,
340 h_errnop);
341 if (status == NSS_STATUS_SUCCESS)
342 return status;
345 return _nss_nis_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
346 h_errnop);
349 enum nss_status
350 _nss_nis_gethostbyaddr_r (char *addr, int addrlen, int type,
351 struct hostent *host, char *buffer, size_t buflen,
352 int *h_errnop)
354 enum nss_status retval;
355 char *domain, *result, *p;
356 int len, parse_res;
357 char *buf;
358 struct parser_data *data = (void *) buffer;
359 size_t linebuflen = buffer + buflen - data->linebuffer;
361 if (yp_get_default_domain (&domain))
362 return NSS_STATUS_UNAVAIL;
364 if (buflen < sizeof *data + 1)
366 __set_errno (ERANGE);
367 *h_errnop = NETDB_INTERNAL;
368 return NSS_STATUS_TRYAGAIN;
371 buf = inet_ntoa (*(struct in_addr *) addr);
373 retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
374 strlen (buf), &result, &len));
376 if (retval != NSS_STATUS_SUCCESS)
378 if (retval == NSS_STATUS_TRYAGAIN)
380 *h_errnop = TRY_AGAIN;
381 __set_errno (EAGAIN);
383 if (retval == NSS_STATUS_NOTFOUND)
384 *h_errnop = HOST_NOT_FOUND;
385 return retval;
388 if ((size_t) (len + 1) > linebuflen)
390 free (result);
391 __set_errno (ERANGE);
392 *h_errnop = NETDB_INTERNAL;
393 return NSS_STATUS_TRYAGAIN;
396 p = strncpy (data->linebuffer, result, len);
397 data->linebuffer[len] = '\0';
398 while (isspace (*p))
399 ++p;
400 free (result);
402 parse_res = parse_line (p, host, data, buflen);
404 if (parse_res == -1 && errno == ERANGE)
406 *h_errnop = NETDB_INTERNAL;
407 return NSS_STATUS_TRYAGAIN;
409 else if (parse_res == 0)
411 *h_errnop = HOST_NOT_FOUND;
412 return NSS_STATUS_NOTFOUND;
415 *h_errnop = NETDB_SUCCESS;
416 return NSS_STATUS_SUCCESS;