xref: /freebsd/lib/libc/net/getnetnamadr.c (revision 036ae3dd790971f07f3cf41e19e087973d0de986)
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$");
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 
45 extern int _ht_getnetbyname(void *, void *, va_list);
46 extern int _dns_getnetbyname(void *, void *, va_list);
47 extern int _nis_getnetbyname(void *, void *, va_list);
48 extern int _ht_getnetbyaddr(void *, void *, va_list);
49 extern int _dns_getnetbyaddr(void *, void *, va_list);
50 extern int _nis_getnetbyaddr(void *, void *, va_list);
51 
52 /* Network lookup order if nsswitch.conf is broken or nonexistant */
53 static const ns_src default_src[] = {
54 	{ NSSRC_FILES, NS_SUCCESS },
55 	{ NSSRC_DNS, NS_SUCCESS },
56 	{ 0 }
57 };
58 
59 static struct netdata netdata;
60 static thread_key_t netdata_key;
61 static once_t netdata_init_once = ONCE_INITIALIZER;
62 static int netdata_thr_keycreated = 0;
63 
64 static void
65 netdata_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 
76 static void
77 netdata_keycreate(void)
78 {
79 	netdata_thr_keycreated =
80 	    (thr_keycreate(&netdata_key, netdata_free) == 0);
81 }
82 
83 struct 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 
103 int
104 getnetbyname_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 
122 int
123 getnetbyaddr_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 
141 void
142 setnetent_r(int stayopen, struct netent_data *ned)
143 {
144 	_setnethtent(stayopen, ned);
145 	_setnetdnsent(stayopen);
146 }
147 
148 void
149 endnetent_r(struct netent_data *ned)
150 {
151 	_endnethtent(ned);
152 	_endnetdnsent();
153 }
154 
155 struct netent *
156 getnetbyname(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 
167 struct netent *
168 #if __LONG_BIT == 64
169 getnetbyaddr(u_long addr, int af)		/* ABI compatibility */
170 #else
171 getnetbyaddr(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 
183 void
184 setnetent(int stayopen)
185 {
186 	struct netdata *nd;
187 
188 	if ((nd = __netdata_init()) == NULL)
189 		return;
190 	setnetent_r(stayopen, &nd->data);
191 }
192 
193 void
194 endnetent(void)
195 {
196 	struct netdata *nd;
197 
198 	if ((nd = __netdata_init()) == NULL)
199 		return;
200 	endnetent_r(&nd->data);
201 }
202