getnetnamadr.c revision 158115
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: head/lib/libc/net/getnetnamadr.c 158115 2006-04-28 12:03:38Z ume $");
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
4965532Snectarextern int _ht_getnetbyname(void *, void *, va_list);
5065532Snectarextern int _dns_getnetbyname(void *, void *, va_list);
5165532Snectarextern int _nis_getnetbyname(void *, void *, va_list);
5265532Snectarextern int _ht_getnetbyaddr(void *, void *, va_list);
5365532Snectarextern int _dns_getnetbyaddr(void *, void *, va_list);
5465532Snectarextern int _nis_getnetbyaddr(void *, void *, va_list);
553070Spst
5665532Snectar/* Network lookup order if nsswitch.conf is broken or nonexistant */
57157779Sumestatic const ns_src default_src[] = {
5865532Snectar	{ NSSRC_FILES, NS_SUCCESS },
5965532Snectar	{ NSSRC_DNS, NS_SUCCESS },
6065532Snectar	{ 0 }
613070Spst};
623070Spst
63157779SumeNETDB_THREAD_ALLOC(netent_data)
64157779SumeNETDB_THREAD_ALLOC(netdata)
65145626Sume
66158115Sume#ifdef NS_CACHING
67158115Sumestatic int
68158115Sumenet_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
69158115Sume{
70158115Sume	char *name;
71158115Sume	uint32_t net;
72158115Sume	int type;
73158115Sume
74158115Sume	size_t desired_size, size;
75158115Sume	enum nss_lookup_type lookup_type;
76158115Sume	int res = NS_UNAVAIL;
77158115Sume
78158115Sume	lookup_type = (enum nss_lookup_type)cache_mdata;
79158115Sume	switch (lookup_type) {
80158115Sume	case nss_lt_name:
81158115Sume		name = va_arg(ap, char *);
82158115Sume
83158115Sume		size = strlen(name);
84158115Sume		desired_size = sizeof(enum nss_lookup_type) + size + 1;
85158115Sume		if (desired_size > *buffer_size) {
86158115Sume			res = NS_RETURN;
87158115Sume			goto fin;
88158115Sume		}
89158115Sume
90158115Sume		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
91158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
92158115Sume
93158115Sume		res = NS_SUCCESS;
94158115Sume		break;
95158115Sume	case nss_lt_id:
96158115Sume		net = va_arg(ap, uint32_t);
97158115Sume		type = va_arg(ap, int);
98158115Sume
99158115Sume		desired_size = sizeof(enum nss_lookup_type) +
100158115Sume		    sizeof(uint32_t) + sizeof(int);
101158115Sume		if (desired_size > *buffer_size) {
102158115Sume			res = NS_RETURN;
103158115Sume			goto fin;
104158115Sume		}
105158115Sume
106158115Sume		memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
107158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type), &net,
108158115Sume		    sizeof(uint32_t));
109158115Sume		memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t),
110158115Sume		    &type, sizeof(int));
111158115Sume
112158115Sume		res = NS_SUCCESS;
113158115Sume		break;
114158115Sume	default:
115158115Sume		/* should be unreachable */
116158115Sume		return (NS_UNAVAIL);
117158115Sume	}
118158115Sume
119158115Sumefin:
120158115Sume	*buffer_size = desired_size;
121158115Sume	return (res);
122158115Sume}
123158115Sume
124158115Sume
125158115Sumestatic int
126158115Sumenet_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
127158115Sume    void *cache_mdata)
128158115Sume{
129158115Sume	char *name;
130158115Sume	uint32_t net;
131158115Sume	int type;
132158115Sume	struct netent *ne;
133158115Sume	char *orig_buf;
134158115Sume	size_t orig_buf_size;
135158115Sume
136158115Sume	struct netent new_ne;
137158115Sume	size_t desired_size, size, aliases_size;
138158115Sume	char *p;
139158115Sume	char **alias;
140158115Sume
141158115Sume	switch ((enum nss_lookup_type)cache_mdata) {
142158115Sume	case nss_lt_name:
143158115Sume		name = va_arg(ap, char *);
144158115Sume		break;
145158115Sume	case nss_lt_id:
146158115Sume		net = va_arg(ap, uint32_t);
147158115Sume		type = va_arg(ap, int);
148158115Sume	break;
149158115Sume	case nss_lt_all:
150158115Sume		break;
151158115Sume	default:
152158115Sume		/* should be unreachable */
153158115Sume		return (NS_UNAVAIL);
154158115Sume	}
155158115Sume
156158115Sume	ne = va_arg(ap, struct netent *);
157158115Sume	orig_buf = va_arg(ap, char *);
158158115Sume	orig_buf_size = va_arg(ap, size_t);
159158115Sume
160158115Sume	desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *);
161158115Sume	if (ne->n_name != NULL)
162158115Sume		desired_size += strlen(ne->n_name) + 1;
163158115Sume
164158115Sume	if (ne->n_aliases != NULL) {
165158115Sume		aliases_size = 0;
166158115Sume		for (alias = ne->n_aliases; *alias; ++alias) {
167158115Sume			desired_size += strlen(*alias) + 1;
168158115Sume			++aliases_size;
169158115Sume		}
170158115Sume
171158115Sume		desired_size += _ALIGNBYTES +
172158115Sume		    (aliases_size + 1) * sizeof(char *);
173158115Sume	}
174158115Sume
175158115Sume	if (*buffer_size < desired_size) {
176158115Sume		/* this assignment is here for future use */
177158115Sume		*buffer_size = desired_size;
178158115Sume		return (NS_RETURN);
179158115Sume	}
180158115Sume
181158115Sume	memcpy(&new_ne, ne, sizeof(struct netent));
182158115Sume
183158115Sume	*buffer_size = desired_size;
184158115Sume	memset(buffer, 0, desired_size);
185158115Sume	p = buffer + sizeof(struct netent) + sizeof(char *);
186158115Sume	memcpy(buffer + sizeof(struct netent), &p, sizeof(char *));
187158115Sume	p = (char *)_ALIGN(p);
188158115Sume
189158115Sume	if (new_ne.n_name != NULL) {
190158115Sume		size = strlen(new_ne.n_name);
191158115Sume		memcpy(p, new_ne.n_name, size);
192158115Sume		new_ne.n_name = p;
193158115Sume		p += size + 1;
194158115Sume	}
195158115Sume
196158115Sume	if (new_ne.n_aliases != NULL) {
197158115Sume		p = (char *)_ALIGN(p);
198158115Sume		memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size);
199158115Sume		new_ne.n_aliases = (char **)p;
200158115Sume		p += sizeof(char *) * (aliases_size + 1);
201158115Sume
202158115Sume		for (alias = new_ne.n_aliases; *alias; ++alias) {
203158115Sume			size = strlen(*alias);
204158115Sume			memcpy(p, *alias, size);
205158115Sume			*alias = p;
206158115Sume			p += size + 1;
207158115Sume		}
208158115Sume	}
209158115Sume
210158115Sume	memcpy(buffer, &new_ne, sizeof(struct netent));
211158115Sume	return (NS_SUCCESS);
212158115Sume}
213158115Sume
214158115Sumestatic int
215158115Sumenet_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
216158115Sume    void *cache_mdata)
217158115Sume{
218158115Sume	char *name;
219158115Sume	uint32_t net;
220158115Sume	int type;
221158115Sume	struct netent *ne;
222158115Sume	char *orig_buf;
223158115Sume	size_t orig_buf_size;
224158115Sume	int *ret_errno;
225158115Sume
226158115Sume	char *p;
227158115Sume	char **alias;
228158115Sume
229158115Sume	switch ((enum nss_lookup_type)cache_mdata) {
230158115Sume	case nss_lt_name:
231158115Sume		name = va_arg(ap, char *);
232158115Sume		break;
233158115Sume	case nss_lt_id:
234158115Sume		net = va_arg(ap, uint32_t);
235158115Sume		type = va_arg(ap, int);
236158115Sume		break;
237158115Sume	case nss_lt_all:
238158115Sume		break;
239158115Sume	default:
240158115Sume		/* should be unreachable */
241158115Sume		return (NS_UNAVAIL);
242158115Sume	}
243158115Sume
244158115Sume	ne = va_arg(ap, struct netent *);
245158115Sume	orig_buf = va_arg(ap, char *);
246158115Sume	orig_buf_size = va_arg(ap, size_t);
247158115Sume	ret_errno = va_arg(ap, int *);
248158115Sume
249158115Sume	if (orig_buf_size <
250158115Sume	    buffer_size - sizeof(struct netent) - sizeof(char *)) {
251158115Sume		*ret_errno = ERANGE;
252158115Sume		return (NS_RETURN);
253158115Sume	}
254158115Sume
255158115Sume	memcpy(ne, buffer, sizeof(struct netent));
256158115Sume	memcpy(&p, buffer + sizeof(struct netent), sizeof(char *));
257158115Sume
258158115Sume	orig_buf = (char *)_ALIGN(orig_buf);
259158115Sume	memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) +
260158115Sume	    _ALIGN(p) - (size_t)p,
261158115Sume	    buffer_size - sizeof(struct netent) - sizeof(char *) -
262158115Sume	    _ALIGN(p) + (size_t)p);
263158115Sume	p = (char *)_ALIGN(p);
264158115Sume
265158115Sume	NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *);
266158115Sume	if (ne->n_aliases != NULL) {
267158115Sume		NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **);
268158115Sume
269158115Sume		for (alias = ne->n_aliases; *alias; ++alias)
270158115Sume			NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
271158115Sume	}
272158115Sume
273158115Sume	if (retval != NULL)
274158115Sume		*((struct netent **)retval) = ne;
275158115Sume
276158115Sume	return (NS_SUCCESS);
277158115Sume}
278158115Sume#endif /* NS_CACHING */
279158115Sume
280145626Sumestatic void
281157779Sumenetent_data_free(void *ptr)
2823070Spst{
283157779Sume	struct netent_data *ned = ptr;
284145626Sume
285157779Sume	if (ned == NULL)
286145626Sume		return;
287157779Sume	ned->stayopen = 0;
288157779Sume	_endnethtent(ned);
289157779Sume	free(ned);
290145626Sume}
291145626Sume
292145626Sumestatic void
293157779Sumenetdata_free(void *ptr)
294145626Sume{
295157779Sume	free(ptr);
296145626Sume}
297145626Sume
298157779Sumeint
299157779Sume__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
300145626Sume{
301157779Sume	char *cp;
302157779Sume	int i, n;
303157779Sume	int numptr, len;
304145626Sume
305157779Sume	/* Find out the amount of space required to store the answer. */
306157779Sume	numptr = 1; /* NULL ptr */
307157779Sume	len = (char *)ALIGN(buf) - buf;
308157779Sume	for (i = 0; ne->n_aliases[i]; i++, numptr++) {
309157779Sume		len += strlen(ne->n_aliases[i]) + 1;
310157779Sume	}
311157779Sume	len += strlen(ne->n_name) + 1;
312157779Sume	len += numptr * sizeof(char*);
313157779Sume
314157779Sume	if (len > (int)buflen) {
315157779Sume		errno = ERANGE;
316157779Sume		return (-1);
317157779Sume	}
318157779Sume
319157779Sume	/* copy net value and type */
320157779Sume	nptr->n_addrtype = ne->n_addrtype;
321157779Sume	nptr->n_net = ne->n_net;
322157779Sume
323157779Sume	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
324157779Sume
325157779Sume	/* copy official name */
326157779Sume	n = strlen(ne->n_name) + 1;
327157779Sume	strcpy(cp, ne->n_name);
328157779Sume	nptr->n_name = cp;
329157779Sume	cp += n;
330157779Sume
331157779Sume	/* copy aliases */
332157779Sume	nptr->n_aliases = (char **)ALIGN(buf);
333157779Sume	for (i = 0 ; ne->n_aliases[i]; i++) {
334157779Sume		n = strlen(ne->n_aliases[i]) + 1;
335157779Sume		strcpy(cp, ne->n_aliases[i]);
336157779Sume		nptr->n_aliases[i] = cp;
337157779Sume		cp += n;
338157779Sume	}
339157779Sume	nptr->n_aliases[i] = NULL;
340157779Sume
341157779Sume	return (0);
342145626Sume}
343145626Sume
344145626Sumeint
345157779Sumegetnetbyname_r(const char *name, struct netent *ne, char *buffer,
346157779Sume    size_t buflen, struct netent **result, int *h_errorp)
347145626Sume{
348158115Sume#ifdef NS_CACHING
349158115Sume	static const nss_cache_info cache_info =
350158115Sume    		NS_COMMON_CACHE_INFO_INITIALIZER(
351158115Sume		networks, (void *)nss_lt_name,
352158115Sume		net_id_func, net_marshal_func, net_unmarshal_func);
353158115Sume#endif
35465532Snectar	static const ns_dtab dtab[] = {
35565532Snectar		NS_FILES_CB(_ht_getnetbyname, NULL)
35665532Snectar		{ NSSRC_DNS, _dns_getnetbyname, NULL },
35765532Snectar		NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
358158115Sume#ifdef NS_CACHING
359158115Sume		NS_CACHE_CB(&cache_info)
360158115Sume#endif
36165532Snectar		{ 0 }
362145626Sume	};
363158115Sume	int rval, ret_errno;
36465532Snectar
365157779Sume	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
366157779Sume	    "getnetbyname_r", default_src, name, ne, buffer, buflen,
367157779Sume	    &ret_errno, h_errorp);
368145626Sume
369157779Sume	return ((rval == NS_SUCCESS) ? 0 : -1);
3703070Spst}
3713070Spst
372145626Sumeint
373157779Sumegetnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
374157779Sume    size_t buflen, struct netent **result, int *h_errorp)
3753070Spst{
376158115Sume#ifdef NS_CACHING
377158115Sume	static const nss_cache_info cache_info =
378158115Sume    		NS_COMMON_CACHE_INFO_INITIALIZER(
379158115Sume		networks, (void *)nss_lt_id,
380158115Sume		net_id_func, net_marshal_func, net_unmarshal_func);
381158115Sume#endif
38265532Snectar	static const ns_dtab dtab[] = {
38365532Snectar		NS_FILES_CB(_ht_getnetbyaddr, NULL)
38465532Snectar		{ NSSRC_DNS, _dns_getnetbyaddr, NULL },
38565532Snectar		NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
386158115Sume#ifdef NS_CACHING
387158115Sume		NS_CACHE_CB(&cache_info)
388158115Sume#endif
38965532Snectar		{ 0 }
390145626Sume	};
391158115Sume	int rval, ret_errno;
3923070Spst
393157779Sume	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
394157779Sume	    "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
395157779Sume	    &ret_errno, h_errorp);
39665532Snectar
397157779Sume	return ((rval == NS_SUCCESS) ? 0 : -1);
3983070Spst}
3993070Spst
400145626Sumestruct netent *
401145626Sumegetnetbyname(const char *name)
402145626Sume{
403145626Sume	struct netdata *nd;
404157779Sume	struct netent *rval;
405157779Sume	int ret_h_errno;
406145626Sume
407145626Sume	if ((nd = __netdata_init()) == NULL)
408157779Sume		return (NULL);
409157779Sume	if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
410157779Sume	    &ret_h_errno) != 0)
411157779Sume		return (NULL);
412157779Sume	return (rval);
413145626Sume}
414145626Sume
415145626Sumestruct netent *
416146244Sumegetnetbyaddr(uint32_t addr, int af)
417145626Sume{
418145626Sume	struct netdata *nd;
419157779Sume	struct netent *rval;
420157779Sume	int ret_h_errno;
421145626Sume
422145626Sume	if ((nd = __netdata_init()) == NULL)
423157779Sume		return (NULL);
424157779Sume	if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
425157779Sume	    &rval, &ret_h_errno) != 0)
426157779Sume		return (NULL);
427157779Sume	return (rval);
428145626Sume}
429145626Sume
430145626Sumevoid
431145626Sumesetnetent(int stayopen)
432145626Sume{
433157779Sume	struct netent_data *ned;
434145626Sume
435157779Sume	if ((ned = __netent_data_init()) == NULL)
436145626Sume		return;
437157779Sume	_setnethtent(stayopen, ned);
438157779Sume	_setnetdnsent(stayopen);
439145626Sume}
440145626Sume
441145626Sumevoid
442145626Sumeendnetent(void)
443145626Sume{
444157779Sume	struct netent_data *ned;
445145626Sume
446157779Sume	if ((ned = __netent_data_init()) == NULL)
447145626Sume		return;
448157779Sume	_endnethtent(ned);
449157779Sume	_endnetdnsent();
450145626Sume}
451