1/*
2 * Copyright (c) 1983, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
31 *	Dep. Matematica Universidade de Coimbra, Portugal, Europe
32 *
33 * Permission to use, copy, modify, and distribute this software for any
34 * purpose with or without fee is hereby granted, provided that the above
35 * copyright notice and this permission notice appear in all copies.
36 *
37 * from getnetent.c	1.1 (Coimbra) 93/06/02
38 */
39
40#if defined(LIBC_SCCS) && !defined(lint)
41static char sccsid[] = "@(#)getnetent.c	8.1 (Berkeley) 6/4/93";
42static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp";
43#endif /* LIBC_SCCS and not lint */
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD$");
46
47#include <sys/types.h>
48#include <sys/socket.h>
49#include <netinet/in.h>
50#include <arpa/inet.h>
51#include <arpa/nameser.h>
52#include <errno.h>
53#include <netdb.h>
54#include <resolv.h>
55#include <stdio.h>
56#include <string.h>
57#include <stdarg.h>
58#include <nsswitch.h>
59#include "netdb_private.h"
60
61void
62_setnethtent(int f, struct netent_data *ned)
63{
64
65	if (ned->netf == NULL)
66		ned->netf = fopen(_PATH_NETWORKS, "re");
67	else
68		rewind(ned->netf);
69	ned->stayopen |= f;
70}
71
72void
73_endnethtent(struct netent_data *ned)
74{
75
76	if (ned->netf) {
77		fclose(ned->netf);
78		ned->netf = NULL;
79	}
80	ned->stayopen = 0;
81}
82
83static int
84getnetent_p(struct netent *ne, struct netent_data *ned)
85{
86	char *p, *bp, *ep;
87	char *cp, **q;
88	int len;
89	char line[BUFSIZ + 1];
90
91	if (ned->netf == NULL &&
92	    (ned->netf = fopen(_PATH_NETWORKS, "re")) == NULL)
93		return (-1);
94again:
95	p = fgets(line, sizeof line, ned->netf);
96	if (p == NULL)
97		return (-1);
98	if (*p == '#')
99		goto again;
100	cp = strpbrk(p, "#\n");
101	if (cp != NULL)
102		*cp = '\0';
103	bp = ned->netbuf;
104	ep = ned->netbuf + sizeof ned->netbuf;
105	ne->n_name = bp;
106	cp = strpbrk(p, " \t");
107	if (cp == NULL)
108		goto again;
109	*cp++ = '\0';
110	len = strlen(p) + 1;
111	if (ep - bp < len) {
112		RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
113		return (-1);
114	}
115	strlcpy(bp, p, ep - bp);
116	bp += len;
117	while (*cp == ' ' || *cp == '\t')
118		cp++;
119	p = strpbrk(cp, " \t");
120	if (p != NULL)
121		*p++ = '\0';
122	ne->n_net = inet_network(cp);
123	ne->n_addrtype = AF_INET;
124	q = ne->n_aliases = ned->net_aliases;
125	if (p != NULL) {
126		cp = p;
127		while (cp && *cp) {
128			if (*cp == ' ' || *cp == '\t') {
129				cp++;
130				continue;
131			}
132			if (q >= &ned->net_aliases[_MAXALIASES - 1])
133				break;
134			p = strpbrk(cp, " \t");
135			if (p != NULL)
136				*p++ = '\0';
137			len = strlen(cp) + 1;
138			if (ep - bp < len)
139				break;
140			strlcpy(bp, cp, ep - bp);
141			*q++ = bp;
142			bp += len;
143			cp = p;
144		}
145	}
146	*q = NULL;
147	return (0);
148}
149
150int
151getnetent_r(struct netent *nptr, char *buffer, size_t buflen,
152    struct netent **result, int *h_errnop)
153{
154	struct netent_data *ned;
155	struct netent ne;
156	res_state statp;
157
158	statp = __res_state();
159	if ((ned = __netent_data_init()) == NULL) {
160		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
161		*h_errnop = statp->res_h_errno;
162		return (-1);
163	}
164	if (getnetent_p(&ne, ned) != 0)
165		return (-1);
166	if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
167		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
168		*h_errnop = statp->res_h_errno;
169		return ((errno != 0) ? errno : -1);
170	}
171	*result = nptr;
172	return (0);
173}
174
175struct netent *
176getnetent(void)
177{
178	struct netdata *nd;
179	struct netent *rval;
180	int ret_h_errno;
181
182	if ((nd = __netdata_init()) == NULL)
183		return (NULL);
184	if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval,
185	    &ret_h_errno) != 0)
186		return (NULL);
187	return (rval);
188}
189
190int
191_ht_getnetbyname(void *rval, void *cb_data, va_list ap)
192{
193	const char *name;
194	char *buffer;
195	size_t buflen;
196	int *errnop, *h_errnop;
197	struct netent *nptr, ne;
198	struct netent_data *ned;
199	char **cp;
200	res_state statp;
201	int error;
202
203	name = va_arg(ap, const char *);
204	nptr = va_arg(ap, struct netent *);
205	buffer = va_arg(ap, char *);
206	buflen = va_arg(ap, size_t);
207	errnop = va_arg(ap, int *);
208	h_errnop = va_arg(ap, int *);
209
210	statp = __res_state();
211	if ((ned = __netent_data_init()) == NULL) {
212		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
213		*h_errnop = statp->res_h_errno;
214		return (NS_UNAVAIL);
215	}
216
217	_setnethtent(ned->stayopen, ned);
218	while ((error = getnetent_p(&ne, ned)) == 0) {
219		if (strcasecmp(ne.n_name, name) == 0)
220			break;
221		for (cp = ne.n_aliases; *cp != 0; cp++)
222			if (strcasecmp(*cp, name) == 0)
223				goto found;
224	}
225found:
226	if (!ned->stayopen)
227		_endnethtent(ned);
228	if (error != 0) {
229		*h_errnop = statp->res_h_errno;
230		return (NS_NOTFOUND);
231	}
232	if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
233		*errnop = errno;
234		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
235		*h_errnop = statp->res_h_errno;
236		return (NS_RETURN);
237	}
238	*((struct netent **)rval) = nptr;
239	return (NS_SUCCESS);
240}
241
242int
243_ht_getnetbyaddr(void *rval, void *cb_data, va_list ap)
244{
245	uint32_t net;
246	int type;
247	char *buffer;
248	size_t buflen;
249	int *errnop, *h_errnop;
250	struct netent *nptr, ne;
251	struct netent_data *ned;
252	res_state statp;
253	int error;
254
255	net = va_arg(ap, uint32_t);
256	type = va_arg(ap, int);
257	nptr = va_arg(ap, struct netent *);
258	buffer = va_arg(ap, char *);
259	buflen = va_arg(ap, size_t);
260	errnop = va_arg(ap, int *);
261	h_errnop = va_arg(ap, int *);
262
263	statp = __res_state();
264	if ((ned = __netent_data_init()) == NULL) {
265		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
266		*h_errnop = statp->res_h_errno;
267		return (NS_UNAVAIL);
268	}
269
270	_setnethtent(ned->stayopen, ned);
271	while ((error = getnetent_p(&ne, ned)) == 0)
272		if (ne.n_addrtype == type && ne.n_net == net)
273			break;
274	if (!ned->stayopen)
275		_endnethtent(ned);
276	if (error != 0) {
277		*h_errnop = statp->res_h_errno;
278		return (NS_NOTFOUND);
279	}
280	if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
281		*errnop = errno;
282		RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
283		*h_errnop = statp->res_h_errno;
284		return (NS_RETURN);
285	}
286	*((struct netent **)rval) = nptr;
287	return (NS_SUCCESS);
288}
289