Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/net/getnetnamadr.c
39530 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 1994, Garrett Wollman
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include "namespace.h"
29
#include "reentrant.h"
30
#include <sys/param.h>
31
#include <sys/socket.h>
32
#include <netinet/in.h>
33
#include <arpa/inet.h>
34
#include <netdb.h>
35
#include <stdio.h>
36
#include <ctype.h>
37
#include <errno.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
#ifdef NS_CACHING
45
#include "nscache.h"
46
#endif
47
48
/* Network lookup order if nsswitch.conf is broken or nonexistent */
49
static const ns_src default_src[] = {
50
{ NSSRC_FILES, NS_SUCCESS },
51
{ NSSRC_DNS, NS_SUCCESS },
52
{ 0 }
53
};
54
55
NETDB_THREAD_ALLOC(netent_data)
56
NETDB_THREAD_ALLOC(netdata)
57
58
#ifdef NS_CACHING
59
static int
60
net_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
61
{
62
char *name;
63
uint32_t net;
64
int type;
65
66
size_t desired_size, size;
67
enum nss_lookup_type lookup_type;
68
int res = NS_UNAVAIL;
69
70
lookup_type = (enum nss_lookup_type)(uintptr_t)cache_mdata;
71
switch (lookup_type) {
72
case nss_lt_name:
73
name = va_arg(ap, char *);
74
75
size = strlen(name);
76
desired_size = sizeof(enum nss_lookup_type) + size + 1;
77
if (desired_size > *buffer_size) {
78
res = NS_RETURN;
79
goto fin;
80
}
81
82
memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
83
memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
84
85
res = NS_SUCCESS;
86
break;
87
case nss_lt_id:
88
net = va_arg(ap, uint32_t);
89
type = va_arg(ap, int);
90
91
desired_size = sizeof(enum nss_lookup_type) +
92
sizeof(uint32_t) + sizeof(int);
93
if (desired_size > *buffer_size) {
94
res = NS_RETURN;
95
goto fin;
96
}
97
98
memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
99
memcpy(buffer + sizeof(enum nss_lookup_type), &net,
100
sizeof(uint32_t));
101
memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t),
102
&type, sizeof(int));
103
104
res = NS_SUCCESS;
105
break;
106
default:
107
/* should be unreachable */
108
return (NS_UNAVAIL);
109
}
110
111
fin:
112
*buffer_size = desired_size;
113
return (res);
114
}
115
116
117
static int
118
net_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
119
void *cache_mdata)
120
{
121
char *name __unused;
122
uint32_t net __unused;
123
int type __unused;
124
struct netent *ne;
125
char *orig_buf __unused;
126
size_t orig_buf_size __unused;
127
128
struct netent new_ne;
129
size_t desired_size, size, aliases_size;
130
char *p;
131
char **alias;
132
133
switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
134
case nss_lt_name:
135
name = va_arg(ap, char *);
136
break;
137
case nss_lt_id:
138
net = va_arg(ap, uint32_t);
139
type = va_arg(ap, int);
140
break;
141
case nss_lt_all:
142
break;
143
default:
144
/* should be unreachable */
145
return (NS_UNAVAIL);
146
}
147
148
ne = va_arg(ap, struct netent *);
149
orig_buf = va_arg(ap, char *);
150
orig_buf_size = va_arg(ap, size_t);
151
152
desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *);
153
if (ne->n_name != NULL)
154
desired_size += strlen(ne->n_name) + 1;
155
156
if (ne->n_aliases != NULL) {
157
aliases_size = 0;
158
for (alias = ne->n_aliases; *alias; ++alias) {
159
desired_size += strlen(*alias) + 1;
160
++aliases_size;
161
}
162
163
desired_size += _ALIGNBYTES +
164
(aliases_size + 1) * sizeof(char *);
165
}
166
167
if (*buffer_size < desired_size) {
168
/* this assignment is here for future use */
169
*buffer_size = desired_size;
170
return (NS_RETURN);
171
}
172
173
memcpy(&new_ne, ne, sizeof(struct netent));
174
175
*buffer_size = desired_size;
176
memset(buffer, 0, desired_size);
177
p = buffer + sizeof(struct netent) + sizeof(char *);
178
memcpy(buffer + sizeof(struct netent), &p, sizeof(char *));
179
p = (char *)_ALIGN(p);
180
181
if (new_ne.n_name != NULL) {
182
size = strlen(new_ne.n_name);
183
memcpy(p, new_ne.n_name, size);
184
new_ne.n_name = p;
185
p += size + 1;
186
}
187
188
if (new_ne.n_aliases != NULL) {
189
p = (char *)_ALIGN(p);
190
memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size);
191
new_ne.n_aliases = (char **)p;
192
p += sizeof(char *) * (aliases_size + 1);
193
194
for (alias = new_ne.n_aliases; *alias; ++alias) {
195
size = strlen(*alias);
196
memcpy(p, *alias, size);
197
*alias = p;
198
p += size + 1;
199
}
200
}
201
202
memcpy(buffer, &new_ne, sizeof(struct netent));
203
return (NS_SUCCESS);
204
}
205
206
static int
207
net_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
208
void *cache_mdata)
209
{
210
char *name __unused;
211
uint32_t net __unused;
212
int type __unused;
213
struct netent *ne;
214
char *orig_buf;
215
size_t orig_buf_size;
216
int *ret_errno;
217
218
char *p;
219
char **alias;
220
221
switch ((enum nss_lookup_type)(uintptr_t)cache_mdata) {
222
case nss_lt_name:
223
name = va_arg(ap, char *);
224
break;
225
case nss_lt_id:
226
net = va_arg(ap, uint32_t);
227
type = va_arg(ap, int);
228
break;
229
case nss_lt_all:
230
break;
231
default:
232
/* should be unreachable */
233
return (NS_UNAVAIL);
234
}
235
236
ne = va_arg(ap, struct netent *);
237
orig_buf = va_arg(ap, char *);
238
orig_buf_size = va_arg(ap, size_t);
239
ret_errno = va_arg(ap, int *);
240
241
if (orig_buf_size <
242
buffer_size - sizeof(struct netent) - sizeof(char *)) {
243
*ret_errno = ERANGE;
244
return (NS_RETURN);
245
}
246
247
memcpy(ne, buffer, sizeof(struct netent));
248
memcpy(&p, buffer + sizeof(struct netent), sizeof(char *));
249
250
orig_buf = (char *)_ALIGN(orig_buf);
251
memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) +
252
_ALIGN(p) - (size_t)p,
253
buffer_size - sizeof(struct netent) - sizeof(char *) -
254
_ALIGN(p) + (size_t)p);
255
p = (char *)_ALIGN(p);
256
257
NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *);
258
if (ne->n_aliases != NULL) {
259
NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **);
260
261
for (alias = ne->n_aliases; *alias; ++alias)
262
NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
263
}
264
265
if (retval != NULL)
266
*((struct netent **)retval) = ne;
267
268
return (NS_SUCCESS);
269
}
270
#endif /* NS_CACHING */
271
272
static void
273
netent_data_free(void *ptr)
274
{
275
struct netent_data *ned = ptr;
276
277
if (ned == NULL)
278
return;
279
ned->stayopen = 0;
280
_endnethtent(ned);
281
free(ned);
282
}
283
284
static void
285
netdata_free(void *ptr)
286
{
287
free(ptr);
288
}
289
290
int
291
__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
292
{
293
char *cp;
294
int i, n;
295
int numptr, len;
296
297
/* Find out the amount of space required to store the answer. */
298
numptr = 1; /* NULL ptr */
299
len = (char *)ALIGN(buf) - buf;
300
for (i = 0; ne->n_aliases[i]; i++, numptr++) {
301
len += strlen(ne->n_aliases[i]) + 1;
302
}
303
len += strlen(ne->n_name) + 1;
304
len += numptr * sizeof(char*);
305
306
if (len > (int)buflen) {
307
errno = ERANGE;
308
return (-1);
309
}
310
311
/* copy net value and type */
312
nptr->n_addrtype = ne->n_addrtype;
313
nptr->n_net = ne->n_net;
314
315
cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
316
317
/* copy official name */
318
n = strlen(ne->n_name) + 1;
319
strcpy(cp, ne->n_name);
320
nptr->n_name = cp;
321
cp += n;
322
323
/* copy aliases */
324
nptr->n_aliases = (char **)ALIGN(buf);
325
for (i = 0 ; ne->n_aliases[i]; i++) {
326
n = strlen(ne->n_aliases[i]) + 1;
327
strcpy(cp, ne->n_aliases[i]);
328
nptr->n_aliases[i] = cp;
329
cp += n;
330
}
331
nptr->n_aliases[i] = NULL;
332
333
return (0);
334
}
335
336
int
337
getnetbyname_r(const char *name, struct netent *ne, char *buffer,
338
size_t buflen, struct netent **result, int *h_errorp)
339
{
340
#ifdef NS_CACHING
341
static const nss_cache_info cache_info =
342
NS_COMMON_CACHE_INFO_INITIALIZER(
343
networks, (void *)nss_lt_name,
344
net_id_func, net_marshal_func, net_unmarshal_func);
345
#endif
346
static const ns_dtab dtab[] = {
347
NS_FILES_CB(_ht_getnetbyname, NULL)
348
{ NSSRC_DNS, _dns_getnetbyname, NULL },
349
NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
350
#ifdef NS_CACHING
351
NS_CACHE_CB(&cache_info)
352
#endif
353
{ 0 }
354
};
355
int rval, ret_errno = 0;
356
357
rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
358
"getnetbyname_r", default_src, name, ne, buffer, buflen,
359
&ret_errno, h_errorp);
360
361
if (rval != NS_SUCCESS) {
362
errno = ret_errno;
363
return ((ret_errno != 0) ? ret_errno : -1);
364
}
365
return (0);
366
}
367
368
int
369
getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
370
size_t buflen, struct netent **result, int *h_errorp)
371
{
372
#ifdef NS_CACHING
373
static const nss_cache_info cache_info =
374
NS_COMMON_CACHE_INFO_INITIALIZER(
375
networks, (void *)nss_lt_id,
376
net_id_func, net_marshal_func, net_unmarshal_func);
377
#endif
378
static const ns_dtab dtab[] = {
379
NS_FILES_CB(_ht_getnetbyaddr, NULL)
380
{ NSSRC_DNS, _dns_getnetbyaddr, NULL },
381
NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
382
#ifdef NS_CACHING
383
NS_CACHE_CB(&cache_info)
384
#endif
385
{ 0 }
386
};
387
int rval, ret_errno = 0;
388
389
rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
390
"getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
391
&ret_errno, h_errorp);
392
393
if (rval != NS_SUCCESS) {
394
errno = ret_errno;
395
return ((ret_errno != 0) ? ret_errno : -1);
396
}
397
return (0);
398
}
399
400
struct netent *
401
getnetbyname(const char *name)
402
{
403
struct netdata *nd;
404
struct netent *rval;
405
int ret_h_errno;
406
407
if ((nd = __netdata_init()) == NULL)
408
return (NULL);
409
if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
410
&ret_h_errno) != 0)
411
return (NULL);
412
return (rval);
413
}
414
415
struct netent *
416
getnetbyaddr(uint32_t addr, int af)
417
{
418
struct netdata *nd;
419
struct netent *rval;
420
int ret_h_errno;
421
422
if ((nd = __netdata_init()) == NULL)
423
return (NULL);
424
if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
425
&rval, &ret_h_errno) != 0)
426
return (NULL);
427
return (rval);
428
}
429
430
void
431
setnetent(int stayopen)
432
{
433
struct netent_data *ned;
434
435
if ((ned = __netent_data_init()) == NULL)
436
return;
437
_setnethtent(stayopen, ned);
438
_setnetdnsent(stayopen);
439
}
440
441
void
442
endnetent(void)
443
{
444
struct netent_data *ned;
445
446
if ((ned = __netent_data_init()) == NULL)
447
return;
448
_endnethtent(ned);
449
_endnetdnsent();
450
}
451
452