getnetnamadr.c revision 157779
1/*-
2 * Copyright (c) 1994, Garrett Wollman
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/lib/libc/net/getnetnamadr.c 157779 2006-04-15 16:20:27Z ume $");
28
29#include "namespace.h"
30#include "reentrant.h"
31#include <sys/param.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34#include <arpa/inet.h>
35#include <netdb.h>
36#include <stdio.h>
37#include <ctype.h>
38#include <errno.h>
39#include <stdlib.h>
40#include <string.h>
41#include <stdarg.h>
42#include <nsswitch.h>
43#include "un-namespace.h"
44#include "netdb_private.h"
45
46extern int _ht_getnetbyname(void *, void *, va_list);
47extern int _dns_getnetbyname(void *, void *, va_list);
48extern int _nis_getnetbyname(void *, void *, va_list);
49extern int _ht_getnetbyaddr(void *, void *, va_list);
50extern int _dns_getnetbyaddr(void *, void *, va_list);
51extern int _nis_getnetbyaddr(void *, void *, va_list);
52
53/* Network lookup order if nsswitch.conf is broken or nonexistant */
54static const ns_src default_src[] = {
55	{ NSSRC_FILES, NS_SUCCESS },
56	{ NSSRC_DNS, NS_SUCCESS },
57	{ 0 }
58};
59
60NETDB_THREAD_ALLOC(netent_data)
61NETDB_THREAD_ALLOC(netdata)
62
63static void
64netent_data_free(void *ptr)
65{
66	struct netent_data *ned = ptr;
67
68	if (ned == NULL)
69		return;
70	ned->stayopen = 0;
71	_endnethtent(ned);
72	free(ned);
73}
74
75static void
76netdata_free(void *ptr)
77{
78	free(ptr);
79}
80
81int
82__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
83{
84	char *cp;
85	int i, n;
86	int numptr, len;
87
88	/* Find out the amount of space required to store the answer. */
89	numptr = 1; /* NULL ptr */
90	len = (char *)ALIGN(buf) - buf;
91	for (i = 0; ne->n_aliases[i]; i++, numptr++) {
92		len += strlen(ne->n_aliases[i]) + 1;
93	}
94	len += strlen(ne->n_name) + 1;
95	len += numptr * sizeof(char*);
96
97	if (len > (int)buflen) {
98		errno = ERANGE;
99		return (-1);
100	}
101
102	/* copy net value and type */
103	nptr->n_addrtype = ne->n_addrtype;
104	nptr->n_net = ne->n_net;
105
106	cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
107
108	/* copy official name */
109	n = strlen(ne->n_name) + 1;
110	strcpy(cp, ne->n_name);
111	nptr->n_name = cp;
112	cp += n;
113
114	/* copy aliases */
115	nptr->n_aliases = (char **)ALIGN(buf);
116	for (i = 0 ; ne->n_aliases[i]; i++) {
117		n = strlen(ne->n_aliases[i]) + 1;
118		strcpy(cp, ne->n_aliases[i]);
119		nptr->n_aliases[i] = cp;
120		cp += n;
121	}
122	nptr->n_aliases[i] = NULL;
123
124	return (0);
125}
126
127int
128getnetbyname_r(const char *name, struct netent *ne, char *buffer,
129    size_t buflen, struct netent **result, int *h_errorp)
130{
131	int rval, ret_errno;
132
133	static const ns_dtab dtab[] = {
134		NS_FILES_CB(_ht_getnetbyname, NULL)
135		{ NSSRC_DNS, _dns_getnetbyname, NULL },
136		NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
137		{ 0 }
138	};
139
140	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
141	    "getnetbyname_r", default_src, name, ne, buffer, buflen,
142	    &ret_errno, h_errorp);
143
144	return ((rval == NS_SUCCESS) ? 0 : -1);
145}
146
147int
148getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
149    size_t buflen, struct netent **result, int *h_errorp)
150{
151	int rval, ret_errno;
152
153	static const ns_dtab dtab[] = {
154		NS_FILES_CB(_ht_getnetbyaddr, NULL)
155		{ NSSRC_DNS, _dns_getnetbyaddr, NULL },
156		NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
157		{ 0 }
158	};
159
160	rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
161	    "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
162	    &ret_errno, h_errorp);
163
164	return ((rval == NS_SUCCESS) ? 0 : -1);
165}
166
167struct netent *
168getnetbyname(const char *name)
169{
170	struct netdata *nd;
171	struct netent *rval;
172	int ret_h_errno;
173
174	if ((nd = __netdata_init()) == NULL)
175		return (NULL);
176	if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
177	    &ret_h_errno) != 0)
178		return (NULL);
179	return (rval);
180}
181
182struct netent *
183getnetbyaddr(uint32_t addr, int af)
184{
185	struct netdata *nd;
186	struct netent *rval;
187	int ret_h_errno;
188
189	if ((nd = __netdata_init()) == NULL)
190		return (NULL);
191	if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
192	    &rval, &ret_h_errno) != 0)
193		return (NULL);
194	return (rval);
195}
196
197void
198setnetent(int stayopen)
199{
200	struct netent_data *ned;
201
202	if ((ned = __netent_data_init()) == NULL)
203		return;
204	_setnethtent(stayopen, ned);
205	_setnetdnsent(stayopen);
206}
207
208void
209endnetent(void)
210{
211	struct netent_data *ned;
212
213	if ((ned = __netent_data_init()) == NULL)
214		return;
215	_endnethtent(ned);
216	_endnetdnsent();
217}
218