server.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* Copyright StrongLoop, Inc. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "defs.h"
  22. #include <netinet/in.h> /* INET6_ADDRSTRLEN */
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifndef INET6_ADDRSTRLEN
  26. # define INET6_ADDRSTRLEN 63
  27. #endif
  28. typedef struct {
  29. uv_getaddrinfo_t getaddrinfo_req;
  30. server_config config;
  31. server_ctx *servers;
  32. uv_loop_t *loop;
  33. } server_state;
  34. static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *ai);
  35. static void on_connection(uv_stream_t *server, int status);
  36. int server_run(const server_config *cf, uv_loop_t *loop) {
  37. struct addrinfo hints;
  38. server_state state;
  39. int err;
  40. memset(&state, 0, sizeof(state));
  41. state.servers = NULL;
  42. state.config = *cf;
  43. state.loop = loop;
  44. /* Resolve the address of the interface that we should bind to.
  45. * The getaddrinfo callback starts the server and everything else.
  46. */
  47. memset(&hints, 0, sizeof(hints));
  48. hints.ai_family = AF_UNSPEC;
  49. hints.ai_socktype = SOCK_STREAM;
  50. hints.ai_protocol = IPPROTO_TCP;
  51. err = uv_getaddrinfo(loop,
  52. &state.getaddrinfo_req,
  53. do_bind,
  54. cf->bind_host,
  55. NULL,
  56. &hints);
  57. if (err != 0) {
  58. pr_err("getaddrinfo: %s", uv_strerror(err));
  59. return err;
  60. }
  61. /* Start the event loop. Control continues in do_bind(). */
  62. if (uv_run(loop, UV_RUN_DEFAULT)) {
  63. abort();
  64. }
  65. /* Please Valgrind. */
  66. uv_loop_delete(loop);
  67. free(state.servers);
  68. return 0;
  69. }
  70. /* Bind a server to each address that getaddrinfo() reported. */
  71. static void do_bind(uv_getaddrinfo_t *req, int status, struct addrinfo *addrs) {
  72. char addrbuf[INET6_ADDRSTRLEN + 1];
  73. unsigned int ipv4_naddrs;
  74. unsigned int ipv6_naddrs;
  75. server_state *state;
  76. server_config *cf;
  77. struct addrinfo *ai;
  78. const void *addrv;
  79. const char *what;
  80. uv_loop_t *loop;
  81. server_ctx *sx;
  82. unsigned int n;
  83. int err;
  84. union {
  85. struct sockaddr addr;
  86. struct sockaddr_in addr4;
  87. struct sockaddr_in6 addr6;
  88. } s;
  89. state = CONTAINER_OF(req, server_state, getaddrinfo_req);
  90. loop = state->loop;
  91. cf = &state->config;
  92. if (status < 0) {
  93. pr_err("getaddrinfo(\"%s\"): %s", cf->bind_host, uv_strerror(status));
  94. uv_freeaddrinfo(addrs);
  95. return;
  96. }
  97. ipv4_naddrs = 0;
  98. ipv6_naddrs = 0;
  99. for (ai = addrs; ai != NULL; ai = ai->ai_next) {
  100. if (ai->ai_family == AF_INET) {
  101. ipv4_naddrs += 1;
  102. } else if (ai->ai_family == AF_INET6) {
  103. ipv6_naddrs += 1;
  104. }
  105. }
  106. if (ipv4_naddrs == 0 && ipv6_naddrs == 0) {
  107. pr_err("%s has no IPv4/6 addresses", cf->bind_host);
  108. uv_freeaddrinfo(addrs);
  109. return;
  110. }
  111. state->servers =
  112. xmalloc((ipv4_naddrs + ipv6_naddrs) * sizeof(state->servers[0]));
  113. n = 0;
  114. for (ai = addrs; ai != NULL; ai = ai->ai_next) {
  115. if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
  116. continue;
  117. }
  118. if (ai->ai_family == AF_INET) {
  119. s.addr4 = *(const struct sockaddr_in *) ai->ai_addr;
  120. s.addr4.sin_port = htons(cf->bind_port);
  121. addrv = &s.addr4.sin_addr;
  122. } else if (ai->ai_family == AF_INET6) {
  123. s.addr6 = *(const struct sockaddr_in6 *) ai->ai_addr;
  124. s.addr6.sin6_port = htons(cf->bind_port);
  125. addrv = &s.addr6.sin6_addr;
  126. } else {
  127. UNREACHABLE();
  128. }
  129. if (uv_inet_ntop(s.addr.sa_family, addrv, addrbuf, sizeof(addrbuf))) {
  130. UNREACHABLE();
  131. }
  132. sx = state->servers + n;
  133. sx->loop = loop;
  134. sx->idle_timeout = state->config.idle_timeout;
  135. CHECK(0 == uv_tcp_init(loop, &sx->tcp_handle));
  136. what = "uv_tcp_bind";
  137. err = uv_tcp_bind(&sx->tcp_handle, &s.addr, 0);
  138. if (err == 0) {
  139. what = "uv_listen";
  140. err = uv_listen((uv_stream_t *) &sx->tcp_handle, 128, on_connection);
  141. }
  142. if (err != 0) {
  143. pr_err("%s(\"%s:%hu\"): %s",
  144. what,
  145. addrbuf,
  146. cf->bind_port,
  147. uv_strerror(err));
  148. while (n > 0) {
  149. n -= 1;
  150. uv_close((uv_handle_t *) (state->servers + n), NULL);
  151. }
  152. break;
  153. }
  154. pr_info("listening on %s:%hu", addrbuf, cf->bind_port);
  155. n += 1;
  156. }
  157. uv_freeaddrinfo(addrs);
  158. }
  159. static void on_connection(uv_stream_t *server, int status) {
  160. server_ctx *sx;
  161. client_ctx *cx;
  162. CHECK(status == 0);
  163. sx = CONTAINER_OF(server, server_ctx, tcp_handle);
  164. cx = xmalloc(sizeof(*cx));
  165. CHECK(0 == uv_tcp_init(sx->loop, &cx->incoming.handle.tcp));
  166. CHECK(0 == uv_accept(server, &cx->incoming.handle.stream));
  167. client_finish_init(sx, cx);
  168. }
  169. int can_auth_none(const server_ctx *sx, const client_ctx *cx) {
  170. return 1;
  171. }
  172. int can_auth_passwd(const server_ctx *sx, const client_ctx *cx) {
  173. return 0;
  174. }
  175. int can_access(const server_ctx *sx,
  176. const client_ctx *cx,
  177. const struct sockaddr *addr) {
  178. const struct sockaddr_in6 *addr6;
  179. const struct sockaddr_in *addr4;
  180. const uint32_t *p;
  181. uint32_t a;
  182. uint32_t b;
  183. uint32_t c;
  184. uint32_t d;
  185. /* TODO(bnoordhuis) Implement proper access checks. For now, just reject
  186. * traffic to localhost.
  187. */
  188. if (addr->sa_family == AF_INET) {
  189. addr4 = (const struct sockaddr_in *) addr;
  190. d = ntohl(addr4->sin_addr.s_addr);
  191. return (d >> 24) != 0x7F;
  192. }
  193. if (addr->sa_family == AF_INET6) {
  194. addr6 = (const struct sockaddr_in6 *) addr;
  195. p = (const uint32_t *) &addr6->sin6_addr.s6_addr;
  196. a = ntohl(p[0]);
  197. b = ntohl(p[1]);
  198. c = ntohl(p[2]);
  199. d = ntohl(p[3]);
  200. if (a == 0 && b == 0 && c == 0 && d == 1) {
  201. return 0; /* "::1" style address. */
  202. }
  203. if (a == 0 && b == 0 && c == 0xFFFF && (d >> 24) == 0x7F) {
  204. return 0; /* "::ffff:127.x.x.x" style address. */
  205. }
  206. return 1;
  207. }
  208. return 0;
  209. }