|
@@ -0,0 +1,217 @@
|
|
|
+
|
|
|
+
|
|
|
+ * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>
|
|
|
+ *
|
|
|
+ * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+# network-name number [aliases ...]
|
|
|
+loopback 127.0.0.0 # optional aliases
|
|
|
+
|
|
|
+network-name: symbolic name of the netwkork
|
|
|
+number: official number of the network in dotted quad
|
|
|
+aliases: case sensitive optional space or tab separated list of other names
|
|
|
+*/
|
|
|
+
|
|
|
+#include <features.h>
|
|
|
+#include <netdb.h>
|
|
|
+#include <string.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <netinet/in.h>
|
|
|
+#include <arpa/inet.h>
|
|
|
+#include <errno.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include "internal/parse_config.h"
|
|
|
+
|
|
|
+#include <bits/uClibc_mutex.h>
|
|
|
+__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
|
|
|
+
|
|
|
+#define MAXALIASES 35
|
|
|
+#define BUFSZ (80)
|
|
|
+#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES))
|
|
|
+
|
|
|
+static parser_t *netp = NULL;
|
|
|
+static struct netent nete;
|
|
|
+static char *netbuf = NULL;
|
|
|
+static smallint net_stayopen;
|
|
|
+
|
|
|
+void setnetent(int stayopen)
|
|
|
+{
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ if (netp)
|
|
|
+ config_close(netp);
|
|
|
+ netp = config_open(_PATH_NETWORKS);
|
|
|
+ if (stayopen)
|
|
|
+ net_stayopen = 1;
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+}
|
|
|
+libc_hidden_def(setnetent)
|
|
|
+
|
|
|
+void endnetent(void)
|
|
|
+{
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ if (netp) {
|
|
|
+ config_close(netp);
|
|
|
+ netp = NULL;
|
|
|
+ }
|
|
|
+ net_stayopen = 0;
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+}
|
|
|
+libc_hidden_def(endnetent)
|
|
|
+
|
|
|
+int getnetent_r(struct netent *result_buf,
|
|
|
+ char *buf, size_t buflen, struct netent **result,
|
|
|
+ int *h_errnop
|
|
|
+ )
|
|
|
+{
|
|
|
+ char **alias, *cp = NULL;
|
|
|
+ char **net_aliases;
|
|
|
+ char **tok = NULL;
|
|
|
+ const size_t aliaslen = sizeof(*net_aliases) * MAXALIASES;
|
|
|
+ int ret = ERANGE;
|
|
|
+
|
|
|
+ *result = NULL;
|
|
|
+ if (buflen < aliaslen
|
|
|
+ || (buflen - aliaslen) < BUFSZ + 1)
|
|
|
+ goto DONE_NOUNLOCK;
|
|
|
+
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ ret = ENOENT;
|
|
|
+ if (netp == NULL)
|
|
|
+ setnetent(net_stayopen);
|
|
|
+ if (netp == NULL)
|
|
|
+ goto DONE;
|
|
|
+ netp->data = buf;
|
|
|
+ netp->data_len = aliaslen;
|
|
|
+ netp->line_len = buflen - aliaslen;
|
|
|
+
|
|
|
+ if (!config_read(netp, &tok, 3, 2, "# \t/", PARSE_NORMAL)) {
|
|
|
+ goto DONE;
|
|
|
+ }
|
|
|
+ result_buf->n_name = *(tok++);
|
|
|
+ {
|
|
|
+ struct addrinfo hints, *addri;
|
|
|
+# define sa4_to_uint32(sa) \
|
|
|
+ (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr))
|
|
|
+#ifdef __UCLIBC_HAS_IPV6__
|
|
|
+# define sa6_to_uint8(sa) \
|
|
|
+ (ntohl(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr))
|
|
|
+#endif
|
|
|
+ memset(&hints, 0, sizeof(struct addrinfo));
|
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
|
+ hints.ai_flags = AI_NUMERICHOST;
|
|
|
+ getaddrinfo(*(tok++), NULL, &hints, &addri);
|
|
|
+ result_buf->n_addrtype = addri->ai_family;
|
|
|
+ result_buf->n_net =
|
|
|
+#if 0
|
|
|
+ addri->ai_family == AF_INET6 ? sa6_to_uint8(addri->ai_addr) :
|
|
|
+#endif
|
|
|
+ sa4_to_uint32(addri->ai_addr);
|
|
|
+ freeaddrinfo(addri);
|
|
|
+ }
|
|
|
+ result_buf->n_aliases = alias = net_aliases = tok;
|
|
|
+ cp = *alias;
|
|
|
+ while (cp && *cp) {
|
|
|
+ if (alias < &net_aliases[MAXALIASES - 1])
|
|
|
+ *alias++ = cp;
|
|
|
+ cp = strpbrk(cp, " \t");
|
|
|
+ if (cp != NULL)
|
|
|
+ *cp++ = '\0';
|
|
|
+ }
|
|
|
+ *alias = NULL;
|
|
|
+ *result = result_buf;
|
|
|
+ ret = 0;
|
|
|
+ DONE:
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ DONE_NOUNLOCK:
|
|
|
+ errno = ret;
|
|
|
+ return errno;
|
|
|
+}
|
|
|
+libc_hidden_def(getnetent_r)
|
|
|
+
|
|
|
+static void __initbuf(void)
|
|
|
+{
|
|
|
+ if (!netbuf) {
|
|
|
+ netbuf = malloc(SBUFSIZE);
|
|
|
+ if (!netbuf)
|
|
|
+ abort();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct netent *getnetent(void)
|
|
|
+{
|
|
|
+ struct netent *result;
|
|
|
+ int herrnop;
|
|
|
+
|
|
|
+ __initbuf();
|
|
|
+ getnetent_r(&nete, netbuf, SBUFSIZE, &result, &herrnop);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+int getnetbyname_r(const char *name,
|
|
|
+ struct netent *result_buf, char *buf, size_t buflen,
|
|
|
+ struct netent **result,
|
|
|
+ int *h_errnop
|
|
|
+ )
|
|
|
+{
|
|
|
+ register char **cp;
|
|
|
+ int ret, herrnop;
|
|
|
+
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ setnetent(net_stayopen);
|
|
|
+ while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) {
|
|
|
+ if (strcmp(name, result_buf->n_name) == 0)
|
|
|
+ break;
|
|
|
+ for (cp = result_buf->n_aliases; *cp; cp++)
|
|
|
+ if (strcmp(name, *cp) == 0)
|
|
|
+ goto gotname;
|
|
|
+ }
|
|
|
+ gotname:
|
|
|
+ if (!net_stayopen)
|
|
|
+ endnetent();
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ return *result ? 0 : ret;
|
|
|
+}
|
|
|
+libc_hidden_def(getnetbyname_r)
|
|
|
+
|
|
|
+struct netent *getnetbyname(const char *name)
|
|
|
+{
|
|
|
+ struct netent *result;
|
|
|
+ int herrnop;
|
|
|
+
|
|
|
+ __initbuf();
|
|
|
+ getnetbyname_r(name, &nete, netbuf, SBUFSIZE, &result, &herrnop);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+int getnetbyaddr_r(uint32_t net, int type,
|
|
|
+ struct netent *result_buf, char *buf,
|
|
|
+ size_t buflen, struct netent **result,
|
|
|
+ int *h_errnop)
|
|
|
+{
|
|
|
+ int ret, herrnop;
|
|
|
+
|
|
|
+ __UCLIBC_MUTEX_LOCK(mylock);
|
|
|
+ setnetent(net_stayopen);
|
|
|
+ while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) {
|
|
|
+ if (net == result_buf->n_net && type == result_buf->n_addrtype)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (!net_stayopen)
|
|
|
+ endnetent();
|
|
|
+ __UCLIBC_MUTEX_UNLOCK(mylock);
|
|
|
+ return *result ? 0 : ret;
|
|
|
+}
|
|
|
+libc_hidden_def(getnetbyaddr_r)
|
|
|
+
|
|
|
+struct netent *getnetbyaddr(uint32_t net, int type)
|
|
|
+{
|
|
|
+ struct netent *result;
|
|
|
+ int herrnop;
|
|
|
+
|
|
|
+ __initbuf();
|
|
|
+ getnetbyaddr_r(net, type, &nete, netbuf, SBUFSIZE, &result, &herrnop);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|