/* vi: set sw=4 ts=4: */ /* * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org> * * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. */ /* /etc/networks # 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 MINTOKENS 2 #define MAXALIASES 8 #define MAXTOKENS (MINTOKENS + MAXALIASES + 1) #define BUFSZ (255) /* one line */ #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) 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 **tok = NULL; const size_t aliaslen = sizeof(char *) * MAXTOKENS; 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; /* <name>[[:space:]]<netnumber>[[:space:]][<aliases>] */ if (!config_read(netp, &tok, MAXTOKENS-1, MINTOKENS, "# \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 /*FIXME: implement me! def __UCLIBC_HAS_IPV6__ */ addri->ai_family == AF_INET6 ? sa6_to_uint8(addri->ai_addr) : #endif sa4_to_uint32(addri->ai_addr); freeaddrinfo(addri); } result_buf->n_aliases = tok; *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; }