blob: 9049f97af738b4bcf08d6f68f5656413c0376937 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
4 *
5 * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
6 */
7
8/* /etc/networks
9# network-name number [aliases ...]
10loopback 127.0.0.0 # optional aliases
11
12network-name: symbolic name of the netwkork
13number: official number of the network in dotted quad
14aliases: case sensitive optional space or tab separated list of other names
15*/
16
17#include <features.h>
18#include <netdb.h>
19#include <string.h>
20#include <stdlib.h>
21#include <netinet/in.h>
22#include <arpa/inet.h>
23#include <errno.h>
24#include <unistd.h>
25#include "internal/parse_config.h"
26
27#include <bits/uClibc_mutex.h>
28__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
29
30#define MINTOKENS 2
31#define MAXALIASES 8
32#define MAXTOKENS (MINTOKENS + MAXALIASES + 1)
33#define BUFSZ (255) /* one line */
34#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS))
35
36static parser_t *netp = NULL;
37static struct netent nete;
38static char *netbuf = NULL;
39static smallint net_stayopen;
40
41void setnetent(int stayopen)
42{
43 __UCLIBC_MUTEX_LOCK(mylock);
44 if (netp)
45 config_close(netp);
46 netp = config_open(_PATH_NETWORKS);
47 if (stayopen)
48 net_stayopen = 1;
49 __UCLIBC_MUTEX_UNLOCK(mylock);
50}
51libc_hidden_def(setnetent)
52
53void endnetent(void)
54{
55 __UCLIBC_MUTEX_LOCK(mylock);
56 if (netp) {
57 config_close(netp);
58 netp = NULL;
59 }
60 net_stayopen = 0;
61 __UCLIBC_MUTEX_UNLOCK(mylock);
62}
63libc_hidden_def(endnetent)
64
65int getnetent_r(struct netent *result_buf,
66 char *buf, size_t buflen, struct netent **result,
67 int *h_errnop
68 )
69{
70 char **tok = NULL;
71 const size_t aliaslen = sizeof(char *) * MAXTOKENS;
72 int ret = ERANGE;
73
74 *result = NULL;
75 if (buflen < aliaslen
76 || (buflen - aliaslen) < BUFSZ + 1)
77 goto DONE_NOUNLOCK;
78
79 __UCLIBC_MUTEX_LOCK(mylock);
80 ret = ENOENT;
81 if (netp == NULL)
82 setnetent(net_stayopen);
83 if (netp == NULL)
84 goto DONE;
85 netp->data = buf;
86 netp->data_len = aliaslen;
87 netp->line_len = buflen - aliaslen;
88 /* <name>[[:space:]]<netnumber>[[:space:]][<aliases>] */
89 if (!config_read(netp, &tok, MAXTOKENS-1, MINTOKENS, "# \t/", PARSE_NORMAL)) {
90 goto DONE;
91 }
92 result_buf->n_name = *(tok++);
93 {
94 struct addrinfo hints, *addri;
95# define sa4_to_uint32(sa) \
96 (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr))
97#ifdef __UCLIBC_HAS_IPV6__
98# define sa6_to_uint8(sa) \
99 (ntohl(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr))
100#endif
101 memset(&hints, 0, sizeof(struct addrinfo));
102 hints.ai_family = AF_UNSPEC;
103 hints.ai_flags = AI_NUMERICHOST;
104 getaddrinfo(*(tok++), NULL, &hints, &addri);
105 result_buf->n_addrtype = addri->ai_family;
106 result_buf->n_net =
107#if 0 /*FIXME: implement me! def __UCLIBC_HAS_IPV6__ */
108 addri->ai_family == AF_INET6 ? sa6_to_uint8(addri->ai_addr) :
109#endif
110 sa4_to_uint32(addri->ai_addr);
111 freeaddrinfo(addri);
112 }
113 result_buf->n_aliases = tok;
114 *result = result_buf;
115 ret = 0;
116 DONE:
117 __UCLIBC_MUTEX_UNLOCK(mylock);
118 DONE_NOUNLOCK:
119 errno = ret;
120 return errno;
121}
122libc_hidden_def(getnetent_r)
123
124static void __initbuf(void)
125{
126 if (!netbuf) {
127 netbuf = malloc(SBUFSIZE);
128 if (!netbuf)
129 abort();
130 }
131}
132
133struct netent *getnetent(void)
134{
135 struct netent *result;
136 int herrnop;
137
138 __initbuf();
139 getnetent_r(&nete, netbuf, SBUFSIZE, &result, &herrnop);
140 return result;
141}
142
143int getnetbyname_r(const char *name,
144 struct netent *result_buf, char *buf, size_t buflen,
145 struct netent **result,
146 int *h_errnop
147 )
148{
149 register char **cp;
150 int ret, herrnop;
151
152 __UCLIBC_MUTEX_LOCK(mylock);
153 setnetent(net_stayopen);
154 while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) {
155 if (strcmp(name, result_buf->n_name) == 0)
156 break;
157 for (cp = result_buf->n_aliases; *cp; cp++)
158 if (strcmp(name, *cp) == 0)
159 goto gotname;
160 }
161 gotname:
162 if (!net_stayopen)
163 endnetent();
164 __UCLIBC_MUTEX_UNLOCK(mylock);
165 return *result ? 0 : ret;
166}
167libc_hidden_def(getnetbyname_r)
168
169struct netent *getnetbyname(const char *name)
170{
171 struct netent *result;
172 int herrnop;
173
174 __initbuf();
175 getnetbyname_r(name, &nete, netbuf, SBUFSIZE, &result, &herrnop);
176 return result;
177}
178
179int getnetbyaddr_r(uint32_t net, int type,
180 struct netent *result_buf, char *buf,
181 size_t buflen, struct netent **result,
182 int *h_errnop)
183{
184 int ret, herrnop;
185
186 __UCLIBC_MUTEX_LOCK(mylock);
187 setnetent(net_stayopen);
188 while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) {
189 if (net == result_buf->n_net && type == result_buf->n_addrtype)
190 break;
191 }
192 if (!net_stayopen)
193 endnetent();
194 __UCLIBC_MUTEX_UNLOCK(mylock);
195 return *result ? 0 : ret;
196}
197libc_hidden_def(getnetbyaddr_r)
198
199struct netent *getnetbyaddr(uint32_t net, int type)
200{
201 struct netent *result;
202 int herrnop;
203
204 __initbuf();
205 getnetbyaddr_r(net, type, &nete, netbuf, SBUFSIZE, &result, &herrnop);
206 return result;
207}
208