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