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