xref: /freebsd/lib/libc/net/getnetnamadr.c (revision d3ac2b30d40b8257bbf8680487708e05e3de8ea7)
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 <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 
46 extern int _ht_getnetbyname(void *, void *, va_list);
47 extern int _dns_getnetbyname(void *, void *, va_list);
48 extern int _nis_getnetbyname(void *, void *, va_list);
49 extern int _ht_getnetbyaddr(void *, void *, va_list);
50 extern int _dns_getnetbyaddr(void *, void *, va_list);
51 extern int _nis_getnetbyaddr(void *, void *, va_list);
52 
53 /* Network lookup order if nsswitch.conf is broken or nonexistant */
54 static const ns_src default_src[] = {
55 	{ NSSRC_FILES, NS_SUCCESS },
56 	{ NSSRC_DNS, NS_SUCCESS },
57 	{ 0 }
58 };
59 
60 NETDB_THREAD_ALLOC(netent_data)
61 NETDB_THREAD_ALLOC(netdata)
62 
63 static void
64 netent_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 
75 static void
76 netdata_free(void *ptr)
77 {
78 	free(ptr);
79 }
80 
81 int
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 
127 int
128 getnetbyname_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 
147 int
148 getnetbyaddr_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 
167 struct netent *
168 getnetbyname(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 
182 struct netent *
183 getnetbyaddr(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 
197 void
198 setnetent(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 
208 void
209 endnetent(void)
210 {
211 	struct netent_data *ned;
212 
213 	if ((ned = __netent_data_init()) == NULL)
214 		return;
215 	_endnethtent(ned);
216 	_endnetdnsent();
217 }
218