]> git.ipfire.org Git - thirdparty/glibc.git/blob - nis/nss_nis/nis-hosts.c
update from main archive 961211
[thirdparty/glibc.git] / nis / nss_nis / nis-hosts.c
1 /* Copyright (C) 1996 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.
4
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.
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 Library General Public License for more details.
14
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. */
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 <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 #include "../../resolv/mapv4v6hostent.h"
36
37 #define ENTNAME hostent
38 #define DATABASE "hosts"
39 #define NEED_H_ERRNO
40
41 #define ENTDATA hostent_data
42 struct hostent_data
43 {
44 unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
45 char *h_addr_ptrs[2]; /* Points to that and null terminator. */
46 };
47
48 #define TRAILING_LIST_MEMBER h_aliases
49 #define TRAILING_LIST_SEPARATOR_P isspace
50 #include "../../nss/nss_files/files-parse.c"
51 LINE_PARSER
52 ("#",
53 {
54 char *addr;
55
56 STRING_FIELD (addr, isspace, 1);
57
58 /* Parse address. */
59 if ((_res.options & RES_USE_INET6)
60 && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
61 {
62 result->h_addrtype = AF_INET6;
63 result->h_length = IN6ADDRSZ;
64 }
65 else
66 if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
67 {
68 if (_res.options & RES_USE_INET6)
69 {
70 map_v4v6_address ((char *) entdata->host_addr,
71 (char *) entdata->host_addr);
72 result->h_addrtype = AF_INET6;
73 result->h_length = IN6ADDRSZ;
74 }
75 else
76 {
77 result->h_addrtype = AF_INET;
78 result->h_length = INADDRSZ;
79 }
80 }
81 else
82 /* Illegal address: ignore line. */
83 return 0;
84
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;
89
90 /* If we need the host entry in IPv6 form change it now. */
91 if (_res.options & RES_USE_INET6)
92 {
93 char *bufptr = data->linebuffer;
94 size_t buflen = (char *) data + datalen - bufptr;
95 map_v4v6_hostent (result, &bufptr, &buflen);
96 }
97
98 STRING_FIELD (result->h_name, isspace, 1);
99 }
100 )
101
102 __libc_lock_define_initialized (static, lock)
103
104 static bool_t new_start = 1;
105 static char *oldkey = NULL;
106 static int oldkeylen = 0;
107
108 enum nss_status
109 _nss_nis_sethostent (void)
110 {
111 __libc_lock_lock (lock);
112
113 new_start = 1;
114 if (oldkey != NULL)
115 {
116 free (oldkey);
117 oldkey = NULL;
118 oldkeylen = 0;
119 }
120
121 __libc_lock_unlock (lock);
122
123 return NSS_STATUS_SUCCESS;
124 }
125
126 enum nss_status
127 _nss_nis_endhostent (void)
128 {
129 __libc_lock_lock (lock);
130
131 new_start = 1;
132 if (oldkey != NULL)
133 {
134 free (oldkey);
135 oldkey = NULL;
136 oldkeylen = 0;
137 }
138
139 __libc_lock_unlock (lock);
140
141 return NSS_STATUS_SUCCESS;
142 }
143
144 static enum nss_status
145 internal_nis_gethostent_r (struct hostent *host, char *buffer,
146 size_t buflen, int *h_errnop)
147 {
148 char *domain;
149 char *result;
150 int len, parse_res;
151 char *outkey;
152 int keylen;
153 struct parser_data *data = (void *) buffer;
154 size_t linebuflen = buffer + buflen - data->linebuffer;
155
156 if (yp_get_default_domain (&domain))
157 return NSS_STATUS_UNAVAIL;
158
159 if (buflen < sizeof *data + 1)
160 {
161 __set_errno (ERANGE);
162 *h_errnop = NETDB_INTERNAL;
163 return NSS_STATUS_TRYAGAIN;
164 }
165
166 /* Get the next entry until we found a correct one. */
167 do
168 {
169 enum nss_status retval;
170 char *p;
171
172 if (new_start)
173 retval = yperr2nss (yp_first (domain, "hosts.byname",
174 &outkey, &keylen, &result, &len));
175 else
176 retval = yperr2nss ( yp_next (domain, "hosts.byname",
177 oldkey, oldkeylen,
178 &outkey, &keylen, &result, &len));
179
180 if (retval != NSS_STATUS_SUCCESS)
181 {
182 switch (retval)
183 {
184 case NSS_STATUS_TRYAGAIN:
185 __set_errno (EAGAIN);
186 *h_errnop = TRY_AGAIN;
187 break;
188 case NSS_STATUS_NOTFOUND:
189 *h_errnop = HOST_NOT_FOUND;
190 break;
191 default:
192 *h_errnop = NO_RECOVERY;
193 break;
194 }
195 return retval;
196 }
197
198 if ((size_t) (len + 1) > linebuflen)
199 {
200 free (result);
201 *h_errnop = NETDB_INTERNAL;
202 __set_errno (ERANGE);
203 return NSS_STATUS_TRYAGAIN;
204 }
205
206 p = strncpy (data->linebuffer, result, len);
207 data->linebuffer[len] = '\0';
208 while (isspace (*p))
209 ++p;
210 free (result);
211
212 parse_res = parse_line (p, host, data, buflen);
213 if (!parse_res && errno == ERANGE)
214 {
215 *h_errnop = NETDB_INTERNAL;;
216 return NSS_STATUS_TRYAGAIN;
217 }
218 free (oldkey);
219 oldkey = outkey;
220 oldkeylen = keylen;
221 new_start = 0;
222 }
223 while (!parse_res);
224
225 *h_errnop = NETDB_SUCCESS;
226 return NSS_STATUS_SUCCESS;
227 }
228
229 int
230 _nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
231 int *h_errnop)
232 {
233 int status;
234
235 __libc_lock_lock (lock);
236
237 status = internal_nis_gethostent_r (host, buffer, buflen, h_errnop);
238
239 __libc_lock_unlock (lock);
240
241 return status;
242 }
243
244 enum nss_status
245 _nss_nis_gethostbyname_r (const char *name, struct hostent *host,
246 char *buffer, size_t buflen, int *h_errnop)
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 __set_errno (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 __set_errno (ERANGE);
267 return NSS_STATUS_TRYAGAIN;
268 }
269 retval = yperr2nss (yp_match (domain, "hosts.byname", name,
270 strlen (name), &result, &len));
271
272 if (retval != NSS_STATUS_SUCCESS)
273 {
274 if (retval == NSS_STATUS_TRYAGAIN)
275 {
276 *h_errnop = TRY_AGAIN;
277 __set_errno (EAGAIN);
278 }
279 if (retval == NSS_STATUS_NOTFOUND)
280 *h_errnop = HOST_NOT_FOUND;
281 return retval;
282 }
283
284 if ((size_t) (len + 1) > linebuflen)
285 {
286 free (result);
287 *h_errnop = NETDB_INTERNAL;
288 __set_errno (ERANGE);
289 return NSS_STATUS_TRYAGAIN;
290 }
291
292 p = strncpy (data->linebuffer, result, len);
293 data->linebuffer[len] = '\0';
294 while (isspace (*p))
295 ++p;
296 free (result);
297
298 parse_res = parse_line (p, host, data, buflen);
299
300 if (!parse_res)
301 {
302 if (errno == ERANGE)
303 {
304 *h_errnop = NETDB_INTERNAL;
305 return NSS_STATUS_TRYAGAIN;
306 }
307 else
308 {
309 *h_errnop = HOST_NOT_FOUND;
310 return NSS_STATUS_NOTFOUND;
311 }
312 }
313
314 *h_errnop = NETDB_SUCCESS;
315 return NSS_STATUS_SUCCESS;
316 }
317
318 enum nss_status
319 _nss_nis_gethostbyaddr_r (char *addr, int addrlen, int type,
320 struct hostent *host, char *buffer, size_t buflen,
321 int *h_errnop)
322 {
323 enum nss_status retval;
324 char *domain, *result, *p;
325 int len, parse_res;
326 char *buf;
327 struct parser_data *data = (void *) buffer;
328 size_t linebuflen = buffer + buflen - data->linebuffer;
329
330 if (yp_get_default_domain (&domain))
331 return NSS_STATUS_UNAVAIL;
332
333 if (buflen < sizeof *data + 1)
334 {
335 __set_errno (ERANGE);
336 *h_errnop = NETDB_INTERNAL;
337 return NSS_STATUS_TRYAGAIN;
338 }
339
340 buf = inet_ntoa (*(struct in_addr *) addr);
341
342 retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
343 strlen (buf), &result, &len));
344
345 if (retval != NSS_STATUS_SUCCESS)
346 {
347 if (retval == NSS_STATUS_TRYAGAIN)
348 {
349 *h_errnop = TRY_AGAIN;
350 __set_errno (EAGAIN);
351 }
352 if (retval == NSS_STATUS_NOTFOUND)
353 *h_errnop = HOST_NOT_FOUND;
354 return retval;
355 }
356
357 if ((size_t) (len + 1) > linebuflen)
358 {
359 free (result);
360 __set_errno (ERANGE);
361 *h_errnop = NETDB_INTERNAL;
362 return NSS_STATUS_TRYAGAIN;
363 }
364
365 p = strncpy (data->linebuffer, result, len);
366 data->linebuffer[len] = '\0';
367 while (isspace (*p))
368 ++p;
369 free (result);
370
371 parse_res = parse_line (p, host, data, buflen);
372
373 if (!parse_res)
374 {
375 if (errno == ERANGE)
376 {
377 *h_errnop = NETDB_INTERNAL;
378 return NSS_STATUS_TRYAGAIN;
379 }
380 else
381 {
382 *h_errnop = HOST_NOT_FOUND;
383 return NSS_STATUS_NOTFOUND;
384 }
385 }
386
387 *h_errnop = NETDB_SUCCESS;
388 return NSS_STATUS_SUCCESS;
389 }