getnet.c 4.7 KB

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