getnet.c 4.9 KB

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