]> git.ipfire.org Git - thirdparty/glibc.git/blob - nis/nss_nis/nis-hosts.c
Update.
[thirdparty/glibc.git] / nis / nss_nis / nis-hosts.c
1 /* Copyright (C) 1996,1997,1998,1999,2000,2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
4
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.
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
13 Lesser General Public License for more details.
14
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. */
19
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>
30
31 #include "nss-nis.h"
32
33 /* Get implementation for some internal functions. */
34 #include <resolv/mapv4v6addr.h>
35
36 #define ENTNAME hostent
37 #define DATABASE "hosts"
38 #define NEED_H_ERRNO
39
40 #define EXTRA_ARGS , af, flags
41 #define EXTRA_ARGS_DECL , int af, int flags
42
43 #define ENTDATA hostent_data
44 struct 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
52 #include <nss/nss_files/files-parse.c>
53 LINE_PARSER
54 ("#",
55 {
56 char *addr;
57
58 STRING_FIELD (addr, isspace, 1);
59
60 /* Parse address. */
61 if (af == AF_INET && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
62 {
63 if (flags & AI_V4MAPPED)
64 {
65 map_v4v6_address ((char *) entdata->host_addr,
66 (char *) entdata->host_addr);
67 result->h_addrtype = AF_INET6;
68 result->h_length = IN6ADDRSZ;
69 }
70 else
71 {
72 result->h_addrtype = AF_INET;
73 result->h_length = INADDRSZ;
74 }
75 }
76 else if (af == AF_INET6
77 && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
78 {
79 result->h_addrtype = AF_INET6;
80 result->h_length = IN6ADDRSZ;
81 }
82 else
83 /* Illegal address: ignore line. */
84 return 0;
85
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;
90
91 STRING_FIELD (result->h_name, isspace, 1);
92 })
93
94
95 __libc_lock_define_initialized (static, lock)
96
97 static bool_t new_start = 1;
98 static char *oldkey = NULL;
99 static int oldkeylen = 0;
100
101 enum nss_status
102 _nss_nis_sethostent (int stayopen)
103 {
104 __libc_lock_lock (lock);
105
106 new_start = 1;
107 if (oldkey != NULL)
108 {
109 free (oldkey);
110 oldkey = NULL;
111 oldkeylen = 0;
112 }
113
114 __libc_lock_unlock (lock);
115
116 return NSS_STATUS_SUCCESS;
117 }
118
119 enum nss_status
120 _nss_nis_endhostent (void)
121 {
122 __libc_lock_lock (lock);
123
124 new_start = 1;
125 if (oldkey != NULL)
126 {
127 free (oldkey);
128 oldkey = NULL;
129 oldkeylen = 0;
130 }
131
132 __libc_lock_unlock (lock);
133
134 return NSS_STATUS_SUCCESS;
135 }
136
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)
142 {
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;
150
151 if (yp_get_default_domain (&domain))
152 return NSS_STATUS_UNAVAIL;
153
154 if (buflen < sizeof *data + 1)
155 {
156 *errnop = ERANGE;
157 *h_errnop = NETDB_INTERNAL;
158 return NSS_STATUS_TRYAGAIN;
159 }
160
161 /* Get the next entry until we found a correct one. */
162 do
163 {
164 enum nss_status retval;
165 char *p;
166
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));
174
175 if (retval != NSS_STATUS_SUCCESS)
176 {
177 switch (retval)
178 {
179 case NSS_STATUS_TRYAGAIN:
180 *errnop = errno;
181 *h_errnop = TRY_AGAIN;
182 break;
183 case NSS_STATUS_NOTFOUND:
184 *h_errnop = HOST_NOT_FOUND;
185 break;
186 default:
187 *h_errnop = NO_RECOVERY;
188 break;
189 }
190 return retval;
191 }
192
193 if ((size_t) (len + 1) > linebuflen)
194 {
195 free (result);
196 *h_errnop = NETDB_INTERNAL;
197 *errnop = ERANGE;
198 return NSS_STATUS_TRYAGAIN;
199 }
200
201 p = strncpy (data->linebuffer, result, len);
202 data->linebuffer[len] = '\0';
203 while (isspace (*p))
204 ++p;
205 free (result);
206
207 parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
208 if (parse_res == -1)
209 {
210 free (outkey);
211 *h_errnop = NETDB_INTERNAL;
212 *errnop = ERANGE;
213 return NSS_STATUS_TRYAGAIN;
214 }
215 free (oldkey);
216 oldkey = outkey;
217 oldkeylen = keylen;
218 new_start = 0;
219 }
220 while (!parse_res);
221
222 *h_errnop = NETDB_SUCCESS;
223 return NSS_STATUS_SUCCESS;
224 }
225
226 enum nss_status
227 _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
228 int *errnop, int *h_errnop)
229 {
230 enum nss_status status;
231
232 __libc_lock_lock (lock);
233
234 status = internal_nis_gethostent_r (host, buffer, buflen, errnop, h_errnop,
235 ((_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET),
236 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0 ));
237
238 __libc_lock_unlock (lock);
239
240 return status;
241 }
242
243 static enum nss_status
244 internal_gethostbyname2_r (const char *name, int af, struct hostent *host,
245 char *buffer, size_t buflen, int *errnop,
246 int *h_errnop, int flags)
247 {
248 enum nss_status retval;
249 char *domain, *result, *p;
250 int len, parse_res;
251 struct parser_data *data = (void *) buffer;
252 size_t linebuflen = buffer + buflen - data->linebuffer;
253
254 if (name == NULL)
255 {
256 *errnop = EINVAL;
257 return NSS_STATUS_UNAVAIL;
258 }
259
260 if (yp_get_default_domain (&domain))
261 return NSS_STATUS_UNAVAIL;
262
263 if (buflen < sizeof *data + 1)
264 {
265 *h_errnop = NETDB_INTERNAL;
266 *errnop = ERANGE;
267 return NSS_STATUS_TRYAGAIN;
268 }
269 else
270 {
271 /* Convert name to lowercase. */
272 size_t namlen = strlen (name);
273 char name2[namlen + 1];
274 int i;
275
276 for (i = 0; i < namlen; ++i)
277 name2[i] = tolower (name[i]);
278 name2[i] = '\0';
279
280 retval = yperr2nss (yp_match (domain, "hosts.byname", name2,
281 namlen, &result, &len));
282
283 }
284
285 if (retval != NSS_STATUS_SUCCESS)
286 {
287 if (retval == NSS_STATUS_TRYAGAIN)
288 {
289 *h_errnop = TRY_AGAIN;
290 *errnop = errno;
291 }
292 if (retval == NSS_STATUS_NOTFOUND)
293 *h_errnop = HOST_NOT_FOUND;
294 return retval;
295 }
296
297 if ((size_t) (len + 1) > linebuflen)
298 {
299 free (result);
300 *h_errnop = NETDB_INTERNAL;
301 *errnop = ERANGE;
302 return NSS_STATUS_TRYAGAIN;
303 }
304
305 p = strncpy (data->linebuffer, result, len);
306 data->linebuffer[len] = '\0';
307 while (isspace (*p))
308 ++p;
309 free (result);
310
311 parse_res = parse_line (p, host, data, buflen, errnop, af, flags);
312
313 if (parse_res < 1 || host->h_addrtype != af)
314 {
315 if (parse_res == -1)
316 {
317 *h_errnop = NETDB_INTERNAL;
318 return NSS_STATUS_TRYAGAIN;
319 }
320 else
321 {
322 *h_errnop = HOST_NOT_FOUND;
323 return NSS_STATUS_NOTFOUND;
324 }
325 }
326
327 *h_errnop = NETDB_SUCCESS;
328 return NSS_STATUS_SUCCESS;
329 }
330
331 enum nss_status
332 _nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
333 char *buffer, size_t buflen, int *errnop,
334 int *h_errnop)
335 {
336 return internal_gethostbyname2_r (name, af, host, buffer, buflen, errnop,
337 h_errnop,
338 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
339 }
340
341 enum nss_status
342 _nss_nis_gethostbyname_r (const char *name, struct hostent *host, char *buffer,
343 size_t buflen, int *errnop, int *h_errnop)
344 {
345 if (_res.options & RES_USE_INET6)
346 {
347 enum nss_status status;
348
349 status = internal_gethostbyname2_r (name, AF_INET6, host, buffer, buflen,
350 errnop, h_errnop, AI_V4MAPPED);
351 if (status == NSS_STATUS_SUCCESS)
352 return status;
353 }
354
355 return internal_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
356 errnop, h_errnop, 0);
357 }
358
359 enum nss_status
360 _nss_nis_gethostbyaddr_r (const void *addr, socklen_t addrlen, int af,
361 struct hostent *host, char *buffer, size_t buflen,
362 int *errnop, int *h_errnop)
363 {
364 enum nss_status retval;
365 char *domain, *result, *p;
366 int len, parse_res;
367 char *buf;
368 struct parser_data *data = (void *) buffer;
369 size_t linebuflen = buffer + buflen - data->linebuffer;
370
371 if (yp_get_default_domain (&domain))
372 return NSS_STATUS_UNAVAIL;
373
374 if (buflen < sizeof *data + 1)
375 {
376 *errnop = ERANGE;
377 *h_errnop = NETDB_INTERNAL;
378 return NSS_STATUS_TRYAGAIN;
379 }
380
381 buf = inet_ntoa (*(const struct in_addr *) addr);
382
383 retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
384 strlen (buf), &result, &len));
385
386 if (retval != NSS_STATUS_SUCCESS)
387 {
388 if (retval == NSS_STATUS_TRYAGAIN)
389 {
390 *h_errnop = TRY_AGAIN;
391 *errnop = errno;
392 }
393 if (retval == NSS_STATUS_NOTFOUND)
394 *h_errnop = HOST_NOT_FOUND;
395
396 return retval;
397 }
398
399 if ((size_t) (len + 1) > linebuflen)
400 {
401 free (result);
402 *errnop = ERANGE;
403 *h_errnop = NETDB_INTERNAL;
404 return NSS_STATUS_TRYAGAIN;
405 }
406
407 p = strncpy (data->linebuffer, result, len);
408 data->linebuffer[len] = '\0';
409 while (isspace (*p))
410 ++p;
411 free (result);
412
413 parse_res = parse_line (p, host, data, buflen, errnop, af,
414 ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0));
415 if (parse_res < 1)
416 {
417 if (parse_res == -1)
418 {
419 *h_errnop = NETDB_INTERNAL;
420 return NSS_STATUS_TRYAGAIN;
421 }
422 else
423 {
424 *h_errnop = HOST_NOT_FOUND;
425 return NSS_STATUS_NOTFOUND;
426 }
427 }
428
429 *h_errnop = NETDB_SUCCESS;
430 return NSS_STATUS_SUCCESS;
431 }
432
433 #if 0
434 enum nss_status
435 _nss_nis_getipnodebyname_r (const char *name, int af, int flags,
436 struct hostent *result, char *buffer,
437 size_t buflen, int *errnop, int *herrnop)
438 {
439 return internal_gethostbyname2_r (name, af, result, buffer, buflen,
440 errnop, herrnop, flags);
441 }
442 #endif