(INTDEFX): Define to get correct expansion order.
[glibc.git] / nis / nss_nis / nis-hosts.c
blobc855a0a7a314f5bdb9eb32523abb9f89d98d2ee7
1 /* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.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 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.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <nss.h>
21 #include <ctype.h>
22 #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>
36 #define ENTNAME hostent
37 #define DATABASE "hosts"
38 #define NEED_H_ERRNO
40 #define EXTRA_ARGS , af, flags
41 #define EXTRA_ARGS_DECL , int af, int flags
43 #define ENTDATA hostent_data
44 struct hostent_data
46 unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
47 char *h_addr_ptrs[2]; /* Points to that and null terminator. */
50 #define TRAILING_LIST_MEMBER h_aliases
51 #define TRAILING_LIST_SEPARATOR_P isspace
52 #include <nss/nss_files/files-parse.c>
53 LINE_PARSER
54 ("#",
56 char *addr;
58 STRING_FIELD (addr, isspace, 1);
60 /* Parse address. */
61 if (af == AF_INET && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
63 if (flags & AI_V4MAPPED)
65 map_v4v6_address ((char *) entdata->host_addr,
66 (char *) entdata->host_addr);
67 result->h_addrtype = AF_INET6;
68 result->h_length = IN6ADDRSZ;
70 else
72 result->h_addrtype = AF_INET;
73 result->h_length = INADDRSZ;
76 else if (af == AF_INET6
77 && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
79 result->h_addrtype = AF_INET6;
80 result->h_length = IN6ADDRSZ;
82 else
83 /* Illegal address: ignore line. */
84 return 0;
86 /* Store a pointer to the address in the expected form. */
87 entdata->h_addr_ptrs[0] = entdata->host_addr;
88 entdata->h_addr_ptrs[1] = NULL;
89 result->h_addr_list = entdata->h_addr_ptrs;
91 STRING_FIELD (result->h_name, isspace, 1);
95 __libc_lock_define_initialized (static, lock)
97 static bool_t new_start = 1;
98 static char *oldkey = NULL;
99 static int oldkeylen = 0;
101 enum nss_status
102 _nss_nis_sethostent (int stayopen)
104 __libc_lock_lock (lock);
106 new_start = 1;
107 if (oldkey != NULL)
109 free (oldkey);
110 oldkey = NULL;
111 oldkeylen = 0;
114 __libc_lock_unlock (lock);
116 return NSS_STATUS_SUCCESS;
119 enum nss_status
120 _nss_nis_endhostent (void)
122 __libc_lock_lock (lock);
124 new_start = 1;
125 if (oldkey != NULL)
127 free (oldkey);
128 oldkey = NULL;
129 oldkeylen = 0;
132 __libc_lock_unlock (lock);
134 return NSS_STATUS_SUCCESS;
137 /* The calling function always need to get a lock first. */
138 static enum nss_status
139 internal_nis_gethostent_r (struct hostent *host, char *buffer,
140 size_t buflen, int *errnop, int *h_errnop,
141 int af, int flags)
143 char *domain;
144 char *result;
145 int len, parse_res;
146 char *outkey;
147 int keylen;
148 struct parser_data *data = (void *) buffer;
149 size_t linebuflen = buffer + buflen - data->linebuffer;
151 if (yp_get_default_domain (&domain))
152 return NSS_STATUS_UNAVAIL;
154 if (buflen < sizeof *data + 1)
156 *errnop = ERANGE;
157 *h_errnop = NETDB_INTERNAL;
158 return NSS_STATUS_TRYAGAIN;
161 /* Get the next entry until we found a correct one. */
164 enum nss_status retval;
165 char *p;
167 if (new_start)
168 retval = yperr2nss (yp_first (domain, "hosts.byname",
169 &outkey, &keylen, &result, &len));
170 else
171 retval = yperr2nss ( yp_next (domain, "hosts.byname",
172 oldkey, oldkeylen,
173 &outkey, &keylen, &result, &len));
175 if (retval != NSS_STATUS_SUCCESS)
177 switch (retval)
179 case NSS_STATUS_TRYAGAIN:
180 *errnop = errno;
181 *h_errnop = TRY_AGAIN;
182 break;
183 case NSS_STATUS_NOTFOUND:
184 *errnop = ENOENT;
185 *h_errnop = HOST_NOT_FOUND;
186 break;
187 default:
188 *h_errnop = NO_RECOVERY;
189 break;
191 return retval;
194 if ((size_t) (len + 1) > linebuflen)
196 free (result);
197 *h_errnop = NETDB_INTERNAL;
198 *errnop = ERANGE;
199 return NSS_STATUS_TRYAGAIN;
202 p = strncpy (data->linebuffer, result, len);
203 data->linebuffer[len] = '\0';
204 while (isspace (*p))
205 ++p;
206 free (result);
208 parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
209 if (parse_res == -1)
211 free (outkey);
212 *h_errnop = NETDB_INTERNAL;
213 *errnop = ERANGE;
214 return NSS_STATUS_TRYAGAIN;
216 free (oldkey);
217 oldkey = outkey;
218 oldkeylen = keylen;
219 new_start = 0;
221 while (!parse_res);
223 *h_errnop = NETDB_SUCCESS;
224 return NSS_STATUS_SUCCESS;
227 enum nss_status
228 _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
229 int *errnop, int *h_errnop)
231 enum nss_status status;
233 __libc_lock_lock (lock);
235 status = internal_nis_gethostent_r (host, buffer, buflen, errnop, h_errnop,
236 ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET),
237 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0 ));
239 __libc_lock_unlock (lock);
241 return status;
244 static enum nss_status
245 internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
246 char *buffer, size_t buflen, int *errnop,
247 int *h_errnop, int flags)
249 enum nss_status retval;
250 char *domain, *result, *p;
251 int len, parse_res;
252 struct parser_data *data = (void *) buffer;
253 size_t linebuflen = buffer + buflen - data->linebuffer;
255 if (name == NULL)
257 *errnop = EINVAL;
258 return NSS_STATUS_UNAVAIL;
261 if (yp_get_default_domain (&domain))
262 return NSS_STATUS_UNAVAIL;
264 if (buflen < sizeof *data + 1)
266 *h_errnop = NETDB_INTERNAL;
267 *errnop = ERANGE;
268 return NSS_STATUS_TRYAGAIN;
270 else
272 /* Convert name to lowercase. */
273 size_t namlen = strlen (name);
274 char name2[namlen + 1];
275 int i;
277 for (i = 0; i < namlen; ++i)
278 name2[i] = tolower (name[i]);
279 name2[i] = '\0';
281 retval = yperr2nss (yp_match (domain, "hosts.byname", name2,
282 namlen, &result, &len));
286 if (retval != NSS_STATUS_SUCCESS)
288 if (retval == NSS_STATUS_TRYAGAIN)
290 *h_errnop = TRY_AGAIN;
291 *errnop = errno;
293 if (retval == NSS_STATUS_NOTFOUND)
294 *h_errnop = HOST_NOT_FOUND;
295 return retval;
298 if ((size_t) (len + 1) > linebuflen)
300 free (result);
301 *h_errnop = NETDB_INTERNAL;
302 *errnop = ERANGE;
303 return NSS_STATUS_TRYAGAIN;
306 p = strncpy (data->linebuffer, result, len);
307 data->linebuffer[len] = '\0';
308 while (isspace (*p))
309 ++p;
310 free (result);
312 parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
314 if (parse_res < 1 || host->h_addrtype != af)
316 if (parse_res == -1)
318 *h_errnop = NETDB_INTERNAL;
319 return NSS_STATUS_TRYAGAIN;
321 else
323 *h_errnop = HOST_NOT_FOUND;
324 *errnop = ENOENT;
325 return NSS_STATUS_NOTFOUND;
329 *h_errnop = NETDB_SUCCESS;
330 return NSS_STATUS_SUCCESS;
333 enum nss_status
334 _nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
335 char *buffer, size_t buflen, int *errnop,
336 int *h_errnop)
338 return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
339 h_errnop,
340 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
343 enum nss_status
344 _nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer,
345 size_t buflen, int *errnop, int *h_errnop)
347 if (_res.options & RES_USE_INET6)
349 enum nss_status status;
351 status = internal_gethostbyname2_r (name, AF_INET6, host, buffer, buflen,
352 errnop, h_errnop, AI_V4MAPPED);
353 if (status == NSS_STATUS_SUCCESS)
354 return status;
357 return internal_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
358 errnop, h_errnop, 0);
361 enum nss_status
362 _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
363 struct hostent *host, char *buffer, size_t buflen,
364 int *errnop, int *h_errnop)
366 enum nss_status retval;
367 char *domain, *result, *p;
368 int len, parse_res;
369 char *buf;
370 struct parser_data *data = (void *) buffer;
371 size_t linebuflen = buffer + buflen - data->linebuffer;
373 if (yp_get_default_domain (&domain))
374 return NSS_STATUS_UNAVAIL;
376 if (buflen < sizeof *data + 1)
378 *errnop = ERANGE;
379 *h_errnop = NETDB_INTERNAL;
380 return NSS_STATUS_TRYAGAIN;
383 buf = inet_ntoa (*(const struct in_addr *) addr);
385 retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
386 strlen (buf), &result, &len));
388 if (retval != NSS_STATUS_SUCCESS)
390 if (retval == NSS_STATUS_TRYAGAIN)
392 *h_errnop = TRY_AGAIN;
393 *errnop = errno;
395 if (retval == NSS_STATUS_NOTFOUND)
397 *h_errnop = HOST_NOT_FOUND;
398 *errnop = ENOENT;
400 return retval;
403 if ((size_t) (len + 1) > linebuflen)
405 free (result);
406 *errnop = ERANGE;
407 *h_errnop = NETDB_INTERNAL;
408 return NSS_STATUS_TRYAGAIN;
411 p = strncpy (data->linebuffer, result, len);
412 data->linebuffer[len] = '\0';
413 while (isspace (*p))
414 ++p;
415 free (result);
417 parse_res = parse_line (p, host, data, buflen, errnop, af,
418 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
419 if (parse_res < 1)
421 if (parse_res == -1)
423 *h_errnop = NETDB_INTERNAL;
424 return NSS_STATUS_TRYAGAIN;
426 else
428 *h_errnop = HOST_NOT_FOUND;
429 return NSS_STATUS_NOTFOUND;
433 *h_errnop = NETDB_SUCCESS;
434 return NSS_STATUS_SUCCESS;
437 #if 0
438 enum nss_status
439 _nss_nis_getipnodebyname_r (const char *name, int af, int flags,
440 struct hostent *result, char *buffer,
441 size_t buflen, int *errnop, int *herrnop)
443 return internal_gethostbyname2_r (name, af, result, buffer, buflen,
444 errnop, herrnop, flags);
446 #endif