]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nis/nis-hosts.c
Update.
[thirdparty/glibc.git] / nis / nss_nis / nis-hosts.c
CommitLineData
0d8733c4 1/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
6259ec0d
UD
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>
5107cf1d 27#include <bits/libc-lock.h>
6259ec0d
UD
28#include <rpcsvc/yp.h>
29#include <rpcsvc/ypclnt.h>
30
31#include "nss-nis.h"
32
33/* Get implementation for some internal functions. */
cf29ffbe 34#include <resolv/mapv4v6addr.h>
6259ec0d
UD
35
36#define ENTNAME hostent
37#define DATABASE "hosts"
38#define NEED_H_ERRNO
39
40#define ENTDATA hostent_data
41struct 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
cf29ffbe 49#include <nss/nss_files/files-parse.c>
6259ec0d
UD
50LINE_PARSER
51("#",
52 {
53 char *addr;
54
55 STRING_FIELD (addr, isspace, 1);
56
57 /* Parse address. */
714a562f 58 if (inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
6259ec0d
UD
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
6259ec0d
UD
88 STRING_FIELD (result->h_name, isspace, 1);
89 }
90)
91
92__libc_lock_define_initialized (static, lock)
93
94static bool_t new_start = 1;
95static char *oldkey = NULL;
96static int oldkeylen = 0;
97
98enum 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
116enum 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
134static enum nss_status
135internal_nis_gethostent_r (struct hostent *host, char *buffer,
136 size_t buflen, 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 __set_errno (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 __set_errno (EAGAIN);
176 *h_errnop = TRY_AGAIN;
177 break;
178 case NSS_STATUS_NOTFOUND:
179 *h_errnop = HOST_NOT_FOUND;
180 break;
181 default:
182 *h_errnop = NO_RECOVERY;
183 break;
184 }
185 return retval;
186 }
187
f8b87ef0 188 if ((size_t) (len + 1) > linebuflen)
6259ec0d
UD
189 {
190 free (result);
191 *h_errnop = NETDB_INTERNAL;
192 __set_errno (ERANGE);
193 return NSS_STATUS_TRYAGAIN;
194 }
195
196 p = strncpy (data->linebuffer, result, len);
197 data->linebuffer[len] = '\0';
198 while (isspace (*p))
199 ++p;
200 free (result);
201
202 parse_res = parse_line (p, host, data, buflen);
203 if (!parse_res && errno == ERANGE)
204 {
205 *h_errnop = NETDB_INTERNAL;;
206 return NSS_STATUS_TRYAGAIN;
207 }
208 free (oldkey);
209 oldkey = outkey;
210 oldkeylen = keylen;
211 new_start = 0;
212 }
213 while (!parse_res);
214
215 *h_errnop = NETDB_SUCCESS;
216 return NSS_STATUS_SUCCESS;
217}
218
219int
220_nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen,
221 int *h_errnop)
222{
223 int status;
224
225 __libc_lock_lock (lock);
226
227 status = internal_nis_gethostent_r (host, buffer, buflen, h_errnop);
228
229 __libc_lock_unlock (lock);
230
231 return status;
232}
233
234enum nss_status
0d8733c4 235_nss_nis_gethostbyname2_r (const char *name, int af, struct hostent *host,
6259ec0d
UD
236 char *buffer, size_t buflen, int *h_errnop)
237{
238 enum nss_status retval;
239 char *domain, *result, *p;
240 int len, parse_res;
241 struct parser_data *data = (void *) buffer;
242 size_t linebuflen = buffer + buflen - data->linebuffer;
243
244 if (name == NULL)
245 {
246 __set_errno (EINVAL);
247 return NSS_STATUS_UNAVAIL;
248 }
249
250 if (yp_get_default_domain (&domain))
251 return NSS_STATUS_UNAVAIL;
252
253 if (buflen < sizeof *data + 1)
254 {
255 *h_errnop = NETDB_INTERNAL;
256 __set_errno (ERANGE);
257 return NSS_STATUS_TRYAGAIN;
258 }
259 retval = yperr2nss (yp_match (domain, "hosts.byname", name,
260 strlen (name), &result, &len));
261
262 if (retval != NSS_STATUS_SUCCESS)
263 {
264 if (retval == NSS_STATUS_TRYAGAIN)
265 {
266 *h_errnop = TRY_AGAIN;
267 __set_errno (EAGAIN);
268 }
269 if (retval == NSS_STATUS_NOTFOUND)
270 *h_errnop = HOST_NOT_FOUND;
271 return retval;
272 }
273
f8b87ef0 274 if ((size_t) (len + 1) > linebuflen)
6259ec0d
UD
275 {
276 free (result);
277 *h_errnop = NETDB_INTERNAL;
278 __set_errno (ERANGE);
279 return NSS_STATUS_TRYAGAIN;
280 }
281
282 p = strncpy (data->linebuffer, result, len);
283 data->linebuffer[len] = '\0';
284 while (isspace (*p))
285 ++p;
286 free (result);
287
288 parse_res = parse_line (p, host, data, buflen);
289
0d8733c4 290 if (!parse_res || host->h_addrtype != af)
6259ec0d 291 {
0d8733c4 292 if (!parse_res && errno == ERANGE)
6259ec0d
UD
293 {
294 *h_errnop = NETDB_INTERNAL;
295 return NSS_STATUS_TRYAGAIN;
296 }
297 else
298 {
299 *h_errnop = HOST_NOT_FOUND;
300 return NSS_STATUS_NOTFOUND;
301 }
302 }
303
304 *h_errnop = NETDB_SUCCESS;
305 return NSS_STATUS_SUCCESS;
306}
307
0d8733c4
UD
308enum nss_status
309_nss_nis_gethostbyname_r (const char *name, struct hostent *host,
310 char *buffer, size_t buflen, int *h_errnop)
311{
312 if (_res.options & RES_USE_INET6)
313 {
314 enum nss_status status;
315
316 status = _nss_nis_gethostbyname2_r (name, AF_INET6, host, buffer, buflen,
317 h_errnop);
318 if (status == NSS_STATUS_SUCCESS)
319 return status;
320 }
321
322 return _nss_nis_gethostbyname2_r (name, AF_INET, host, buffer, buflen,
323 h_errnop);
324}
325
6259ec0d
UD
326enum nss_status
327_nss_nis_gethostbyaddr_r (char *addr, int addrlen, int type,
328 struct hostent *host, char *buffer, size_t buflen,
329 int *h_errnop)
330{
331 enum nss_status retval;
332 char *domain, *result, *p;
333 int len, parse_res;
334 char *buf;
335 struct parser_data *data = (void *) buffer;
336 size_t linebuflen = buffer + buflen - data->linebuffer;
337
338 if (yp_get_default_domain (&domain))
339 return NSS_STATUS_UNAVAIL;
340
341 if (buflen < sizeof *data + 1)
342 {
343 __set_errno (ERANGE);
344 *h_errnop = NETDB_INTERNAL;
345 return NSS_STATUS_TRYAGAIN;
346 }
347
348 buf = inet_ntoa (*(struct in_addr *) addr);
349
350 retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf,
351 strlen (buf), &result, &len));
352
353 if (retval != NSS_STATUS_SUCCESS)
354 {
355 if (retval == NSS_STATUS_TRYAGAIN)
356 {
357 *h_errnop = TRY_AGAIN;
358 __set_errno (EAGAIN);
359 }
360 if (retval == NSS_STATUS_NOTFOUND)
361 *h_errnop = HOST_NOT_FOUND;
362 return retval;
363 }
364
f8b87ef0 365 if ((size_t) (len + 1) > linebuflen)
6259ec0d
UD
366 {
367 free (result);
368 __set_errno (ERANGE);
369 *h_errnop = NETDB_INTERNAL;
370 return NSS_STATUS_TRYAGAIN;
371 }
372
373 p = strncpy (data->linebuffer, result, len);
374 data->linebuffer[len] = '\0';
375 while (isspace (*p))
376 ++p;
377 free (result);
378
379 parse_res = parse_line (p, host, data, buflen);
380
381 if (!parse_res)
382 {
383 if (errno == ERANGE)
384 {
385 *h_errnop = NETDB_INTERNAL;
386 return NSS_STATUS_TRYAGAIN;
387 }
388 else
389 {
390 *h_errnop = HOST_NOT_FOUND;
391 return NSS_STATUS_NOTFOUND;
392 }
393 }
394
395 *h_errnop = NETDB_SUCCESS;
396 return NSS_STATUS_SUCCESS;
397}