13070Spst/*-
23070Spst * Copyright (c) 1994, Garrett Wollman
33070Spst *
43070Spst * Redistribution and use in source and binary forms, with or without
53070Spst * modification, are permitted provided that the following conditions
63070Spst * are met:
73070Spst * 1. Redistributions of source code must retain the above copyright
83070Spst *    notice, this list of conditions and the following disclaimer.
93070Spst * 2. Redistributions in binary form must reproduce the above copyright
103070Spst *    notice, this list of conditions and the following disclaimer in the
113070Spst *    documentation and/or other materials provided with the distribution.
123070Spst *
133070Spst * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
143070Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
153070Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
163070Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
173070Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
183070Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
193070Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
203070Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
213070Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
223070Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
233070Spst * SUCH DAMAGE.
243070Spst */
253070Spst
2692986Sobrien#include <sys/cdefs.h>
2792986Sobrien__FBSDID("$FreeBSD: stable/11/lib/libc/net/getnetnamadr.c 360415 2020-04-27 23:49:13Z brooks $");
283070Spst
29113977Snectar#include "namespace.h"
30145626Sume#include "reentrant.h"
313070Spst#include <sys/param.h>
323070Spst#include <sys/socket.h>
333070Spst#include <netinet/in.h>
343070Spst#include <arpa/inet.h>
353070Spst#include <netdb.h>
363070Spst#include <stdio.h>
373070Spst#include <ctype.h>
38157779Sume#include <errno.h>
39145626Sume#include <stdlib.h>
403070Spst#include <string.h>
4165532Snectar#include <stdarg.h>
4265532Snectar#include <nsswitch.h>
43113977Snectar#include "un-namespace.h"
44145602Sume#include "netdb_private.h"
45158115Sume#ifdef NS_CACHING
46158115Sume#include "nscache.h"
47158115Sume#endif
483070Spst
49298830Spfg/* Network lookup order if nsswitch.conf is broken or nonexistent */
50157779Sumestatic const ns_src default_src[] = {
5165532Snectar	{ NSSRC_FILES, NS_SUCCESS },
5265532Snectar	{ NSSRC_DNS, NS_SUCCESS },
5365532Snectar	{ 0 }
543070Spst};
553070Spst
56157779SumeNETDB_THREAD_ALLOC(netent_data)
57157779SumeNETDB_THREAD_ALLOC(netdata)
58145626Sume
59158115Sume#ifdef NS_CACHING
60158115Sumestatic int
61158115Sumenet_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
62158115Sume{
63158115Sume	char *name;
64158115Sume	uint32_t net;
65158115Sume	int type;
66158115Sume
67158115Sume	size_t desired_size, size;
68158115Sume	enum nss_lookup_type lookup_type;
69158115Sume	int res = NS_UNAVAIL;
70158115Sume
71360415Sbrooks	lookup_type = (enum nss_lookup_type)(uintptr_t)cache_mdata;
72158115Sume	switch (lookup_type) {
73158115Sume	case nss_lt_name:
74158115Sume		name = va_arg(ap, char *);
75158115Sume
76158115Sume		size = strlen(name);
77158115Sume		desired_size = sizeof(enum nss_lookup_type) + size + 1;
78158115Sume		if (desired_size > *buffer_size) {
79158115Sume			res = NS_RETURN;
80158115Sume			goto fin;
81158115Sume		}
82158115Sume
83158115Sume		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
84158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
85158115Sume
86158115Sume		res = NS_SUCCESS;
87158115Sume		break;
88158115Sume	case nss_lt_id:
89158115Sume		net = va_arg(ap, uint32_t);
90158115Sume		type = va_arg(ap, int);
91158115Sume
92158115Sume		desired_size = sizeof(enum nss_lookup_type) +
93158115Sume		    sizeof(uint32_t) + sizeof(int);
94158115Sume		if (desired_size > *buffer_size) {
95158115Sume			res = NS_RETURN;
96158115Sume			goto fin;
97158115Sume		}
98158115Sume
99158115Sume		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
100158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type), &net,
101158115Sume		    sizeof(uint32_t));
102158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t),
103158115Sume		    &type, sizeof(int));
104158115Sume
105158115Sume		res = NS_SUCCESS;
106158115Sume		break;
107158115Sume	default:
108158115Sume		/* should be unreachable */
109158115Sume		return (NS_UNAVAIL);
110158115Sume	}
111158115Sume
112158115Sumefin:
113158115Sume	*buffer_size = desired_size;
114158115Sume	return (res);
115158115Sume}
116158115Sume
117158115Sume
118158115Sumestatic int
119158115Sumenet_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
120158115Sume    void *cache_mdata)
121158115Sume{
122158115Sume	char *name;
123158115Sume	uint32_t net;
124158115Sume	int type;
125158115Sume	struct netent *ne;
126158115Sume	char *orig_buf;
127158115Sume	size_t orig_buf_size;
128158115Sume
129158115Sume	struct netent new_ne;
130158115Sume	size_t desired_size, size, aliases_size;
131158115Sume	char *p;
132158115Sume	char **alias;
133158115Sume
134360415Sbrooks	switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
135158115Sume	case nss_lt_name:
136158115Sume		name = va_arg(ap, char *);
137158115Sume		break;
138158115Sume	case nss_lt_id:
139158115Sume		net = va_arg(ap, uint32_t);
140158115Sume		type = va_arg(ap, int);
141158115Sume	break;
142158115Sume	case nss_lt_all:
143158115Sume		break;
144158115Sume	default:
145158115Sume		/* should be unreachable */
146158115Sume		return (NS_UNAVAIL);
147158115Sume	}
148158115Sume
149158115Sume	ne = va_arg(ap, struct netent *);
150158115Sume	orig_buf = va_arg(ap, char *);
151158115Sume	orig_buf_size = va_arg(ap, size_t);
152158115Sume
153158115Sume	desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *);
154158115Sume	if (ne->n_name != NULL)
155158115Sume		desired_size += strlen(ne->n_name) + 1;
156158115Sume
157158115Sume	if (ne->n_aliases != NULL) {
158158115Sume		aliases_size = 0;
159158115Sume		for (alias = ne->n_aliases; *alias; ++alias) {
160158115Sume			desired_size += strlen(*alias) + 1;
161158115Sume			++aliases_size;
162158115Sume		}
163158115Sume
164158115Sume		desired_size += _ALIGNBYTES +
165158115Sume		    (aliases_size + 1) * sizeof(char *);
166158115Sume	}
167158115Sume
168158115Sume	if (*buffer_size < desired_size) {
169158115Sume		/* this assignment is here for future use */
170158115Sume		*buffer_size = desired_size;
171158115Sume		return (NS_RETURN);
172158115Sume	}
173158115Sume
174158115Sume	memcpy(&new_ne, ne, sizeof(struct netent));
175158115Sume
176158115Sume	*buffer_size = desired_size;
177158115Sume	memset(buffer, 0, desired_size);
178158115Sume	p = buffer + sizeof(struct netent) + sizeof(char *);
179158115Sume	memcpy(buffer + sizeof(struct netent), &p, sizeof(char *));
180158115Sume	p = (char *)_ALIGN(p);
181158115Sume
182158115Sume	if (new_ne.n_name != NULL) {
183158115Sume		size = strlen(new_ne.n_name);
184158115Sume		memcpy(p, new_ne.n_name, size);
185158115Sume		new_ne.n_name = p;
186158115Sume		p += size + 1;
187158115Sume	}
188158115Sume
189158115Sume	if (new_ne.n_aliases != NULL) {
190158115Sume		p = (char *)_ALIGN(p);
191158115Sume		memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size);
192158115Sume		new_ne.n_aliases = (char **)p;
193158115Sume		p += sizeof(char *) * (aliases_size + 1);
194158115Sume
195158115Sume		for (alias = new_ne.n_aliases; *alias; ++alias) {
196158115Sume			size = strlen(*alias);
197158115Sume			memcpy(p, *alias, size);
198158115Sume			*alias = p;
199158115Sume			p += size + 1;
200158115Sume		}
201158115Sume	}
202158115Sume
203158115Sume	memcpy(buffer, &new_ne, sizeof(struct netent));
204158115Sume	return (NS_SUCCESS);
205158115Sume}
206158115Sume
207158115Sumestatic int
208158115Sumenet_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
209158115Sume    void *cache_mdata)
210158115Sume{
211158115Sume	char *name;
212158115Sume	uint32_t net;
213158115Sume	int type;
214158115Sume	struct netent *ne;
215158115Sume	char *orig_buf;
216158115Sume	size_t orig_buf_size;
217158115Sume	int *ret_errno;
218158115Sume
219158115Sume	char *p;
220158115Sume	char **alias;
221158115Sume
222360415Sbrooks	switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
223158115Sume	case nss_lt_name:
224158115Sume		name = va_arg(ap, char *);
225158115Sume		break;
226158115Sume	case nss_lt_id:
227158115Sume		net = va_arg(ap, uint32_t);
228158115Sume		type = va_arg(ap, int);
229158115Sume		break;
230158115Sume	case nss_lt_all:
231158115Sume		break;
232158115Sume	default:
233158115Sume		/* should be unreachable */
234158115Sume		return (NS_UNAVAIL);
235158115Sume	}
236158115Sume
237158115Sume	ne = va_arg(ap, struct netent *);
238158115Sume	orig_buf = va_arg(ap, char *);
239158115Sume	orig_buf_size = va_arg(ap, size_t);
240158115Sume	ret_errno = va_arg(ap, int *);
241158115Sume
242158115Sume	if (orig_buf_size <
243158115Sume	    buffer_size - sizeof(struct netent) - sizeof(char *)) {
244158115Sume		*ret_errno = ERANGE;
245158115Sume		return (NS_RETURN);
246158115Sume	}
247158115Sume
248158115Sume	memcpy(ne, buffer, sizeof(struct netent));
249158115Sume	memcpy(&p, buffer + sizeof(struct netent), sizeof(char *));
250158115Sume
251158115Sume	orig_buf = (char *)_ALIGN(orig_buf);
252158115Sume	memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) +
253158115Sume	    _ALIGN(p) - (size_t)p,
254158115Sume	    buffer_size - sizeof(struct netent) - sizeof(char *) -
255158115Sume	    _ALIGN(p) + (size_t)p);
256158115Sume	p = (char *)_ALIGN(p);
257158115Sume
258158115Sume	NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *);
259158115Sume	if (ne->n_aliases != NULL) {
260158115Sume		NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **);
261158115Sume
262158115Sume		for (alias = ne->n_aliases; *alias; ++alias)
263158115Sume			NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
264158115Sume	}
265158115Sume
266158115Sume	if (retval != NULL)
267158115Sume		*((struct netent **)retval) = ne;
268158115Sume
269158115Sume	return (NS_SUCCESS);
270158115Sume}
271158115Sume#endif /* NS_CACHING */
272158115Sume
273145626Sumestatic void
274157779Sumenetent_data_free(void *ptr)
2753070Spst{
276157779Sume	struct netent_data *ned = ptr;
277145626Sume
278157779Sume	if (ned == NULL)
279145626Sume		return;
280157779Sume	ned->stayopen = 0;
281157779Sume	_endnethtent(ned);
282157779Sume	free(ned);
283145626Sume}
284145626Sume
285145626Sumestatic void
286157779Sumenetdata_free(void *ptr)
287145626Sume{
288157779Sume	free(ptr);
289145626Sume}
290145626Sume
291157779Sumeint
292157779Sume__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
293145626Sume{
294157779Sume	char *cp;
295157779Sume	int i, n;
296157779Sume	int numptr, len;
297145626Sume
298157779Sume	/* Find out the amount of space required to store the answer. */
299157779Sume	numptr = 1; /* NULL ptr */
300157779Sume	len = (char *)ALIGN(buf) - buf;
301157779Sume	for (i = 0; ne->n_aliases[i]; i++, numptr++) {
302157779Sume		len += strlen(ne->n_aliases[i]) + 1;
303157779Sume	}
304157779Sume	len += strlen(ne->n_name) + 1;
305157779Sume	len += numptr * sizeof(char*);
306157779Sume
307157779Sume	if (len > (int)buflen) {
308157779Sume		errno = ERANGE;
309157779Sume		return (-1);
310157779Sume	}
311157779Sume
312157779Sume	/* copy net value and type */
313157779Sume	nptr->n_addrtype = ne->n_addrtype;
314157779Sume	nptr->n_net = ne->n_net;
315157779Sume
316157779Sume	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
317157779Sume
318157779Sume	/* copy official name */
319157779Sume	n = strlen(ne->n_name) + 1;
320157779Sume	strcpy(cp, ne->n_name);
321157779Sume	nptr->n_name = cp;
322157779Sume	cp += n;
323157779Sume
324157779Sume	/* copy aliases */
325157779Sume	nptr->n_aliases = (char **)ALIGN(buf);
326157779Sume	for (i = 0 ; ne->n_aliases[i]; i++) {
327157779Sume		n = strlen(ne->n_aliases[i]) + 1;
328157779Sume		strcpy(cp, ne->n_aliases[i]);
329157779Sume		nptr->n_aliases[i] = cp;
330157779Sume		cp += n;
331157779Sume	}
332157779Sume	nptr->n_aliases[i] = NULL;
333157779Sume
334157779Sume	return (0);
335145626Sume}
336145626Sume
337145626Sumeint
338157779Sumegetnetbyname_r(const char *name, struct netent *ne, char *buffer,
339157779Sume    size_t buflen, struct netent **result, int *h_errorp)
340145626Sume{
341158115Sume#ifdef NS_CACHING
342158115Sume	static const nss_cache_info cache_info =
343158115Sume    		NS_COMMON_CACHE_INFO_INITIALIZER(
344158115Sume		networks, (void *)nss_lt_name,
345158115Sume		net_id_func, net_marshal_func, net_unmarshal_func);
346158115Sume#endif
34765532Snectar	static const ns_dtab dtab[] = {
34865532Snectar		NS_FILES_CB(_ht_getnetbyname, NULL)
34965532Snectar		{ NSSRC_DNS, _dns_getnetbyname, NULL },
35065532Snectar		NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
351158115Sume#ifdef NS_CACHING
352158115Sume		NS_CACHE_CB(&cache_info)
353158115Sume#endif
35465532Snectar		{ 0 }
355145626Sume	};
356211276Sume	int rval, ret_errno = 0;
35765532Snectar
358157779Sume	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
359157779Sume	    "getnetbyname_r", default_src, name, ne, buffer, buflen,
360157779Sume	    &ret_errno, h_errorp);
361145626Sume
362211276Sume	if (rval != NS_SUCCESS) {
363211276Sume		errno = ret_errno;
364211276Sume		return ((ret_errno != 0) ? ret_errno : -1);
365211276Sume	}
366211276Sume	return (0);
3673070Spst}
3683070Spst
369145626Sumeint
370157779Sumegetnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
371157779Sume    size_t buflen, struct netent **result, int *h_errorp)
3723070Spst{
373158115Sume#ifdef NS_CACHING
374158115Sume	static const nss_cache_info cache_info =
375158115Sume    		NS_COMMON_CACHE_INFO_INITIALIZER(
376158115Sume		networks, (void *)nss_lt_id,
377158115Sume		net_id_func, net_marshal_func, net_unmarshal_func);
378158115Sume#endif
37965532Snectar	static const ns_dtab dtab[] = {
38065532Snectar		NS_FILES_CB(_ht_getnetbyaddr, NULL)
38165532Snectar		{ NSSRC_DNS, _dns_getnetbyaddr, NULL },
38265532Snectar		NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
383158115Sume#ifdef NS_CACHING
384158115Sume		NS_CACHE_CB(&cache_info)
385158115Sume#endif
38665532Snectar		{ 0 }
387145626Sume	};
388211276Sume	int rval, ret_errno = 0;
3893070Spst
390157779Sume	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
391157779Sume	    "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
392157779Sume	    &ret_errno, h_errorp);
39365532Snectar
394211276Sume	if (rval != NS_SUCCESS) {
395211276Sume		errno = ret_errno;
396211276Sume		return ((ret_errno != 0) ? ret_errno : -1);
397211276Sume	}
398211276Sume	return (0);
3993070Spst}
4003070Spst
401145626Sumestruct netent *
402145626Sumegetnetbyname(const char *name)
403145626Sume{
404145626Sume	struct netdata *nd;
405157779Sume	struct netent *rval;
406157779Sume	int ret_h_errno;
407145626Sume
408145626Sume	if ((nd = __netdata_init()) == NULL)
409157779Sume		return (NULL);
410157779Sume	if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
411157779Sume	    &ret_h_errno) != 0)
412157779Sume		return (NULL);
413157779Sume	return (rval);
414145626Sume}
415145626Sume
416145626Sumestruct netent *
417146244Sumegetnetbyaddr(uint32_t addr, int af)
418145626Sume{
419145626Sume	struct netdata *nd;
420157779Sume	struct netent *rval;
421157779Sume	int ret_h_errno;
422145626Sume
423145626Sume	if ((nd = __netdata_init()) == NULL)
424157779Sume		return (NULL);
425157779Sume	if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
426157779Sume	    &rval, &ret_h_errno) != 0)
427157779Sume		return (NULL);
428157779Sume	return (rval);
429145626Sume}
430145626Sume
431145626Sumevoid
432145626Sumesetnetent(int stayopen)
433145626Sume{
434157779Sume	struct netent_data *ned;
435145626Sume
436157779Sume	if ((ned = __netent_data_init()) == NULL)
437145626Sume		return;
438157779Sume	_setnethtent(stayopen, ned);
439157779Sume	_setnetdnsent(stayopen);
440145626Sume}
441145626Sume
442145626Sumevoid
443145626Sumeendnetent(void)
444145626Sume{
445157779Sume	struct netent_data *ned;
446145626Sume
447157779Sume	if ((ned = __netent_data_init()) == NULL)
448145626Sume		return;
449157779Sume	_endnethtent(ned);
450157779Sume	_endnetdnsent();
451145626Sume}
452