Update.
[glibc.git] / nis / nss_nisplus / nisplus-hosts.c
blobe6d584dac8d28c7f1db45f3f00a5ab932a983911
1 /* Copyright (C) 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
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.
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.
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. */
20 #include <nss.h>
21 #include <netdb.h>
22 #include <errno.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <libc-lock.h>
28 #include <rpcsvc/nis.h>
29 #include <rpcsvc/nislib.h>
31 #include "nss-nisplus.h"
33 __libc_lock_define_initialized (static, lock)
35 static nis_result *result = NULL;
36 static nis_name *names = NULL;
38 #define NISENTRYVAL(idx,col,res) \
39 ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
41 #define NISENTRYLEN(idx,col,res) \
42 ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
44 /* Get implementation for some internal functions. */
45 #include "../../resolv/mapv4v6addr.h"
47 #define ENTNAME hostent
48 #define DATABASE "hosts"
49 #define NEED_H_ERRNO
51 #define ENTDATA hostent_data
52 struct hostent_data
54 unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
55 char *h_addr_ptrs[2]; /* Points to that and null terminator. */
58 #define TRAILING_LIST_MEMBER h_aliases
59 #define TRAILING_LIST_SEPARATOR_P isspace
60 #include "../../nss/nss_files/files-parse.c"
61 LINE_PARSER
62 ("#",
64 char *addr;
66 STRING_FIELD (addr, isspace, 1);
68 /* Parse address. */
69 if (inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
71 result->h_addrtype = AF_INET6;
72 result->h_length = IN6ADDRSZ;
74 else
75 if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
77 if (_res.options & RES_USE_INET6)
79 map_v4v6_address ((char *) entdata->host_addr,
80 (char *) entdata->host_addr);
81 result->h_addrtype = AF_INET6;
82 result->h_length = IN6ADDRSZ;
84 else
86 result->h_addrtype = AF_INET;
87 result->h_length = INADDRSZ;
90 else
91 /* Illegal address: ignore line. */
92 return 0;
94 /* Store a pointer to the address in the expected form. */
95 entdata->h_addr_ptrs[0] = entdata->host_addr;
96 entdata->h_addr_ptrs[1] = NULL;
97 result->h_addr_list = entdata->h_addr_ptrs;
99 STRING_FIELD (result->h_name, isspace, 1);
104 static int
105 _nss_nisplus_parse_hostent (nis_result *result, struct hostent *host,
106 char *buffer, size_t buflen)
108 char *p = buffer;
109 size_t room_left = buflen;
110 int parse_res;
111 unsigned int i;
112 struct parser_data *data = (void *) buffer;
114 if (result == NULL)
115 return 0;
117 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
118 result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
119 strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
120 "hosts_tbl") != 0 ||
121 result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
122 return 0;
124 memset (p, '\0', room_left);
126 /* Generate the hosts entry format and use the normal parser */
127 if (NISENTRYLEN (0, 2, result) + 1 > room_left)
129 __set_errno (ERANGE);
130 return 0;
132 strncpy (p, NISENTRYVAL (0, 2, result),
133 NISENTRYLEN (0, 2, result));
134 room_left -= (NISENTRYLEN (0, 2, result) + 1);
136 if (NISENTRYLEN (0, 0, result) + 1 > room_left)
138 __set_errno (ERANGE);
139 return 0;
141 strcat (p, "\t");
142 strncat (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
143 room_left -= (NISENTRYLEN (0, 0, result) + 1);
144 /* + 1: We overwrite the last \0 */
146 for (i = 1; i < result->objects.objects_len; i++)
148 if (NISENTRYLEN (i, 1, result) + 1 > room_left)
150 __set_errno (ERANGE);
151 return 0;
153 strcat (p, " ");
154 strcat (p, NISENTRYVAL (i, 1, result));
155 room_left -= (NISENTRYLEN (i, 1, result) + 1);
158 parse_res = parse_line (p, host, data, buflen);
160 return parse_res;
163 enum nss_status
164 _nss_nisplus_sethostent (void)
166 __libc_lock_lock (lock);
168 if (result)
169 nis_freeresult (result);
170 result = NULL;
171 if (names)
173 nis_freenames (names);
174 names = NULL;
177 __libc_lock_unlock (lock);
179 return NSS_STATUS_SUCCESS;
182 enum nss_status
183 _nss_nisplus_endhostent (void)
185 __libc_lock_lock (lock);
187 if (result)
188 nis_freeresult (result);
189 result = NULL;
190 if (names)
192 nis_freenames (names);
193 names = NULL;
196 __libc_lock_unlock (lock);
198 return NSS_STATUS_SUCCESS;
201 static enum nss_status
202 internal_nisplus_gethostent_r (struct hostent *host, char *buffer,
203 size_t buflen, int *herrnop)
205 int parse_res;
207 /* Get the next entry until we found a correct one. */
210 if (result == NULL)
212 names = nis_getnames("hosts.org_dir");
213 if (names == NULL || names[0] == NULL)
214 return NSS_STATUS_UNAVAIL;
216 result = nis_first_entry(names[0]);
217 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
219 int retval;
221 retval = niserr2nss (result->status);
222 if (retval == NSS_STATUS_TRYAGAIN)
224 *herrnop = NETDB_INTERNAL;
225 __set_errno (EAGAIN);
227 return retval;
231 else
233 nis_result *res2;
235 res2 = nis_next_entry(names[0], &result->cookie);
236 nis_freeresult (result);
237 result = res2;
238 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
240 int retval;
242 retval = niserr2nss (result->status);
243 if (retval == NSS_STATUS_TRYAGAIN)
245 *herrnop = NETDB_INTERNAL;
246 __set_errno (EAGAIN);
248 return retval;
252 parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
253 if (!parse_res && errno == ERANGE)
255 *herrnop = NETDB_INTERNAL;
256 return NSS_STATUS_TRYAGAIN;
259 } while (!parse_res);
261 return NSS_STATUS_SUCCESS;
264 enum nss_status
265 _nss_nisplus_gethostent_r (struct hostent *result, char *buffer,
266 size_t buflen, int *herrnop)
268 int status;
270 __libc_lock_lock (lock);
272 status = internal_nisplus_gethostent_r (result, buffer, buflen, herrnop);
274 __libc_lock_unlock (lock);
276 return status;
279 enum nss_status
280 _nss_nisplus_gethostbyname2_r (const char *name, int af, struct hostent *host,
281 char *buffer, size_t buflen, int *herrnop)
283 int parse_res, retval;
285 if (name == NULL)
287 __set_errno (EINVAL);
288 *herrnop = NETDB_INTERNAL;
289 return NSS_STATUS_NOTFOUND;
291 else
293 nis_result *result;
294 char buf[strlen (name) + 255];
296 /* Search at first in the alias list, and use the correct name
297 for the next search */
298 sprintf(buf, "[name=%s],hosts.org_dir", name);
299 result = nis_list(buf, EXPAND_NAME, NULL, NULL);
301 /* If we do not find it, try it as original name. But if the
302 database is correct, we should find it in the first case, too */
303 if ((result->status != NIS_SUCCESS &&
304 result->status != NIS_S_SUCCESS) ||
305 result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
306 strcmp(result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
307 "hosts_tbl") != 0 ||
308 result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len
309 < 3)
310 sprintf(buf, "[cname=%s],hosts.org_dir", name);
311 else
312 sprintf(buf, "[cname=%s],hosts.org_dir", NISENTRYVAL(0, 0, result));
314 nis_freeresult (result);
315 result = nis_list(buf, EXPAND_NAME, NULL, NULL);
317 retval = niserr2nss (result->status);
318 if (retval != NSS_STATUS_SUCCESS)
320 if (retval == NSS_STATUS_TRYAGAIN)
322 __set_errno (EAGAIN);
323 *herrnop = NETDB_INTERNAL;
325 nis_freeresult (result);
326 return retval;
329 parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
331 nis_freeresult (result);
333 if (parse_res)
334 return NSS_STATUS_SUCCESS;
336 *herrnop = NETDB_INTERNAL;
337 if (!parse_res && errno == ERANGE)
338 return NSS_STATUS_TRYAGAIN;
339 else
340 return NSS_STATUS_NOTFOUND;
344 enum nss_status
345 _nss_nisplus_gethostbyname_r (const char *name, struct hostent *host,
346 char *buffer, size_t buflen, int *h_errnop)
348 if (_res.options & RES_USE_INET6)
350 enum nss_status status;
352 status = _nss_nisplus_gethostbyname2_r (name, AF_INET6, host, buffer,
353 buflen, h_errnop);
354 if (status == NSS_STATUS_SUCCESS)
355 return status;
358 return _nss_nisplus_gethostbyname2_r (name, AF_INET, host, buffer,
359 buflen, h_errnop);
362 enum nss_status
363 _nss_nisplus_gethostbyaddr_r (const char *addr, struct hostent *host,
364 char *buffer, size_t buflen, int *herrnop)
366 if (addr == NULL)
367 return NSS_STATUS_NOTFOUND;
368 else
370 nis_result *result;
371 char buf[24 + strlen (addr)];
372 int retval, parse_res;
374 sprintf(buf, "[addr=%s],hosts.org_dir", addr);
376 result = nis_list(buf, EXPAND_NAME, NULL, NULL);
378 retval = niserr2nss (result->status);
379 if (retval != NSS_STATUS_SUCCESS)
381 if (retval == NSS_STATUS_TRYAGAIN)
383 __set_errno (EAGAIN);
384 *herrnop = NETDB_INTERNAL;
386 nis_freeresult (result);
387 return retval;
390 parse_res = _nss_nisplus_parse_hostent (result, host, buffer, buflen);
392 nis_freeresult (result);
394 if (parse_res)
395 return NSS_STATUS_SUCCESS;
397 *herrnop = NETDB_INTERNAL;
398 if (!parse_res && errno == ERANGE)
399 return NSS_STATUS_TRYAGAIN;
400 else
401 return NSS_STATUS_NOTFOUND;