getnetnamadr.c revision 146244
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 146244 2005-05-15 20:15:15Z 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 <stdlib.h>
39#include <string.h>
40#include <stdarg.h>
41#include <nsswitch.h>
42#include "un-namespace.h"
43#include "netdb_private.h"
44
45extern int _ht_getnetbyname(void *, void *, va_list);
46extern int _dns_getnetbyname(void *, void *, va_list);
47extern int _nis_getnetbyname(void *, void *, va_list);
48extern int _ht_getnetbyaddr(void *, void *, va_list);
49extern int _dns_getnetbyaddr(void *, void *, va_list);
50extern int _nis_getnetbyaddr(void *, void *, va_list);
51
52/* Network lookup order if nsswitch.conf is broken or nonexistant */
53static const ns_src default_src[] = {
54	{ NSSRC_FILES, NS_SUCCESS },
55	{ NSSRC_DNS, NS_SUCCESS },
56	{ 0 }
57};
58
59static struct netdata netdata;
60static thread_key_t netdata_key;
61static once_t netdata_init_once = ONCE_INITIALIZER;
62static int netdata_thr_keycreated = 0;
63
64static void
65netdata_free(void *ptr)
66{
67	struct netdata *nd = ptr;
68
69	if (nd == NULL)
70		return;
71	nd->data.stayopen = 0;
72	_endnethtent(&nd->data);
73	free(nd);
74}
75
76static void
77netdata_keycreate(void)
78{
79	netdata_thr_keycreated =
80	    (thr_keycreate(&netdata_key, netdata_free) == 0);
81}
82
83struct netdata *
84__netdata_init(void)
85{
86	struct netdata *nd;
87
88	if (thr_main() != 0)
89		return &netdata;
90	if (thr_once(&netdata_init_once, netdata_keycreate) != 0 ||
91	    !netdata_thr_keycreated)
92		return NULL;
93	if ((nd = thr_getspecific(netdata_key)) != NULL)
94		return nd;
95	if ((nd = calloc(1, sizeof(*nd))) == NULL)
96		return NULL;
97	if (thr_setspecific(netdata_key, nd) == 0)
98		return nd;
99	free(nd);
100	return NULL;
101}
102
103int
104getnetbyname_r(const char *name, struct netent *ne, struct netent_data *ned)
105{
106	int rval;
107
108
109	static const ns_dtab dtab[] = {
110		NS_FILES_CB(_ht_getnetbyname, NULL)
111		{ NSSRC_DNS, _dns_getnetbyname, NULL },
112		NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
113		{ 0 }
114	};
115
116	rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyname",
117	    default_src, name, ne, ned);
118
119	return (rval == NS_SUCCESS) ? 0 : -1;
120}
121
122int
123getnetbyaddr_r(uint32_t addr, int af, struct netent *ne,
124    struct netent_data *ned)
125{
126	int rval;
127
128	static const ns_dtab dtab[] = {
129		NS_FILES_CB(_ht_getnetbyaddr, NULL)
130		{ NSSRC_DNS, _dns_getnetbyaddr, NULL },
131		NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
132		{ 0 }
133	};
134
135	rval = _nsdispatch(NULL, dtab, NSDB_NETWORKS, "getnetbyaddr",
136	    default_src, addr, af, ne, ned);
137
138	return (rval == NS_SUCCESS) ? 0 : -1;
139}
140
141void
142setnetent_r(int stayopen, struct netent_data *ned)
143{
144	_setnethtent(stayopen, ned);
145	_setnetdnsent(stayopen);
146}
147
148void
149endnetent_r(struct netent_data *ned)
150{
151	_endnethtent(ned);
152	_endnetdnsent();
153}
154
155struct netent *
156getnetbyname(const char *name)
157{
158	struct netdata *nd;
159
160	if ((nd = __netdata_init()) == NULL)
161		return NULL;
162	if (getnetbyname_r(name, &nd->net, &nd->data) != 0)
163		return NULL;
164	return &nd->net;
165}
166
167struct netent *
168#if __LONG_BIT == 64
169getnetbyaddr(u_long addr, int af)		/* ABI compatibility */
170#else
171getnetbyaddr(uint32_t addr, int af)
172#endif
173{
174	struct netdata *nd;
175
176	if ((nd = __netdata_init()) == NULL)
177		return NULL;
178	if (getnetbyaddr_r((uint32_t)addr, af, &nd->net, &nd->data) != 0)
179		return NULL;
180	return &nd->net;
181}
182
183void
184setnetent(int stayopen)
185{
186	struct netdata *nd;
187
188	if ((nd = __netdata_init()) == NULL)
189		return;
190	setnetent_r(stayopen, &nd->data);
191}
192
193void
194endnetent(void)
195{
196	struct netdata *nd;
197
198	if ((nd = __netdata_init()) == NULL)
199		return;
200	endnetent_r(&nd->data);
201}
202