symuxnet.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright (c) 2001-2007 Willem Dijkstra
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * - Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * - Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following
  13. * disclaimer in the documentation and/or other materials provided
  14. * with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  19. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  20. * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  22. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  26. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. */
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <errno.h>
  33. #include <fcntl.h>
  34. #include <netdb.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37. #include "conf.h"
  38. #include "data.h"
  39. #include "error.h"
  40. #include "symux.h"
  41. #include "symuxnet.h"
  42. #include "net.h"
  43. #include "xmalloc.h"
  44. #include "share.h"
  45. __BEGIN_DECLS
  46. int check_crc_packet(struct symonpacket *);
  47. __END_DECLS
  48. /* Obtain sockets for incoming symon traffic */
  49. int
  50. get_symon_sockets(struct mux * mux)
  51. {
  52. struct source *source;
  53. struct sockaddr_storage sockaddr;
  54. int family, nsocks, one = 1;
  55. nsocks = 0;
  56. /* generate the udp listen socket specified in the mux statement */
  57. get_mux_sockaddr(mux, SOCK_DGRAM);
  58. /* iterate over our sources to determine what types of sockets we need */
  59. SLIST_FOREACH(source, &mux->sol, sources) {
  60. if (!get_source_sockaddr(source, AF_INET)) {
  61. if (!get_source_sockaddr(source, AF_INET6)) {
  62. warning("cannot determine socket family for source %.200s", source->addr);
  63. }
  64. }
  65. family = source->sockaddr.ss_family;
  66. /* do we have a socket for this type of family */
  67. if (mux->symonsocket[family] <= 0) {
  68. if ((mux->symonsocket[family] = socket(family, SOCK_DGRAM, 0)) != -1) {
  69. /* attempt to set reuse, ignore errors */
  70. if (setsockopt(mux->symonsocket[family], SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
  71. warning ("could set socket options: %.200s", strerror(errno));
  72. }
  73. /*
  74. * does the mux statement specify a specific destination
  75. * address
  76. */
  77. if (mux->sockaddr.ss_family == family) {
  78. cpysock((struct sockaddr *) & mux->sockaddr, &sockaddr);
  79. } else {
  80. get_sockaddr(&sockaddr, family, SOCK_DGRAM, AI_PASSIVE, NULL, mux->port);
  81. }
  82. if (bind(mux->symonsocket[family], (struct sockaddr *) & sockaddr,
  83. SS_LEN(&sockaddr)) == -1) {
  84. switch (errno) {
  85. case EADDRNOTAVAIL:
  86. warning("mux address %.200s is not a local address", mux->addr);
  87. break;
  88. case EADDRINUSE:
  89. warning("mux address %.200s %.200s already in use", mux->addr, mux->port);
  90. break;
  91. case EACCES:
  92. warning("mux port %.200s is restricted from current user", mux->port);
  93. break;
  94. default:
  95. warning("mux port %.200s bind failed", mux->port);
  96. break;
  97. }
  98. close(mux->symonsocket[family]);
  99. mux->symonsocket[family] = 0;
  100. } else {
  101. if (get_numeric_name(&sockaddr)) {
  102. info("getnameinfo error - cannot determine numeric hostname and service");
  103. info("listening for incoming symon traffic for family %d", family);
  104. } else
  105. info("listening for incoming symon traffic on udp %.200s %.200s",
  106. res_host, res_service);
  107. nsocks++;
  108. }
  109. }
  110. }
  111. }
  112. return nsocks;
  113. }
  114. /* Obtain a listen socket for new clients */
  115. int
  116. get_client_socket(struct mux * mux)
  117. {
  118. struct addrinfo hints, *res;
  119. int error, sock, one = 1;
  120. if ((sock = socket(mux->sockaddr.ss_family, SOCK_STREAM, 0)) == -1)
  121. fatal("could not obtain socket: %.200s", strerror(errno));
  122. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
  123. fatal ("could set socket options: %.200s", strerror(errno));
  124. }
  125. bzero((void *) &hints, sizeof(struct addrinfo));
  126. hints.ai_family = mux->sockaddr.ss_family;
  127. hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  128. hints.ai_socktype = SOCK_STREAM;
  129. if ((error = getaddrinfo(mux->addr, mux->port, &hints, &res)) != 0)
  130. fatal("could not get address information for %.200s:%.200s - %.200s",
  131. mux->addr, mux->port, gai_strerror(error));
  132. if (bind(sock, (struct sockaddr *) res->ai_addr, res->ai_addrlen) == -1)
  133. fatal("could not bind socket: %.200s", strerror(errno));
  134. freeaddrinfo(res);
  135. if (listen(sock, SYMUX_TCPBACKLOG) == -1)
  136. fatal("could not listen to socket: %.200s", strerror(errno));
  137. fcntl(sock, O_NONBLOCK);
  138. mux->clientsocket = sock;
  139. info("listening for incoming connections on tcp %.200s %.200s",
  140. mux->addr, mux->port);
  141. return sock;
  142. }
  143. /*
  144. * Wait for traffic (symon reports from a source in sourclist | clients trying to connect
  145. * Returns the <source> and <packet>
  146. * Silently forks off clienthandlers
  147. */
  148. void
  149. wait_for_traffic(struct mux * mux, struct source ** source)
  150. {
  151. fd_set readset;
  152. int i;
  153. int socksactive;
  154. int maxsock;
  155. for (;;) { /* FOREVER - until a valid symon packet is
  156. * received */
  157. FD_ZERO(&readset);
  158. FD_SET(mux->clientsocket, &readset);
  159. maxsock = mux->clientsocket;
  160. for (i = 0; i < AF_MAX; i++) {
  161. if (mux->symonsocket[i] > 0) {
  162. FD_SET(mux->symonsocket[i], &readset);
  163. maxsock = ((maxsock < mux->symonsocket[i]) ? mux->symonsocket[i] :
  164. maxsock);
  165. }
  166. }
  167. maxsock++;
  168. socksactive = select(maxsock, &readset, NULL, NULL, NULL);
  169. if (socksactive != -1) {
  170. if (FD_ISSET(mux->clientsocket, &readset)) {
  171. spawn_client(mux->clientsocket);
  172. }
  173. for (i = 0; i < AF_MAX; i++)
  174. if (FD_ISSET(mux->symonsocket[i], &readset)) {
  175. if (recv_symon_packet(mux, i, source))
  176. return;
  177. }
  178. } else {
  179. if (errno == EINTR)
  180. return; /* signal received while waiting, bail out */
  181. }
  182. }
  183. }
  184. /* Receive a symon packet for mux. Checks if the source is allowed and returns the source found.
  185. * return 0 if no valid packet found
  186. */
  187. int
  188. recv_symon_packet(struct mux * mux, int socknr, struct source ** source)
  189. {
  190. struct sockaddr_storage sind;
  191. socklen_t sl;
  192. int size, tries;
  193. unsigned int received;
  194. u_int32_t crc;
  195. received = 0;
  196. tries = 0;
  197. do {
  198. sl = sizeof(sind);
  199. size = recvfrom(mux->symonsocket[socknr],
  200. (mux->packet.data + received),
  201. (mux->packet.size - received),
  202. 0, (struct sockaddr *) &sind, &sl);
  203. if (size > 0)
  204. received += size;
  205. tries++;
  206. } while ((size == -1) &&
  207. (errno == EAGAIN || errno == EINTR) &&
  208. (tries < SYMUX_MAXREADTRIES) &&
  209. (received < mux->packet.size));
  210. if ((size == -1) &&
  211. errno)
  212. warning("recvfrom failed: %.200s", strerror(errno));
  213. *source = find_source_sockaddr(&mux->sol, (struct sockaddr *) &sind);
  214. get_numeric_name(&sind);
  215. if (*source == NULL) {
  216. debug("ignored data from %.200s:%.200s", res_host, res_service);
  217. return 0;
  218. } else {
  219. /* get header stream */
  220. mux->packet.offset = getheader(mux->packet.data, &mux->packet.header);
  221. /* check crc */
  222. crc = mux->packet.header.crc;
  223. mux->packet.header.crc = 0;
  224. setheader(mux->packet.data, &mux->packet.header);
  225. crc ^= crc32(mux->packet.data, received);
  226. if (crc != 0) {
  227. if (mux->packet.header.length > mux->packet.size)
  228. warning("ignored oversized packet from %.200s:%.200s; client and server have different stream configurations",
  229. res_host, res_service);
  230. else
  231. warning("ignored packet with bad crc from %.200s:%.200s",
  232. res_host, res_service);
  233. return 0;
  234. }
  235. /* check packet version */
  236. if (mux->packet.header.symon_version > SYMON_PACKET_VER) {
  237. warning("ignored packet with unsupported version %d from %.200s:%.200s",
  238. mux->packet.header.symon_version, res_host, res_service);
  239. return 0;
  240. } else {
  241. if (flag_debug) {
  242. debug("good data received from %.200s:%.200s", res_host, res_service);
  243. }
  244. return 1; /* good packet received */
  245. }
  246. }
  247. }
  248. int
  249. accept_connection(int sock)
  250. {
  251. struct sockaddr_storage sind;
  252. socklen_t len;
  253. int clientsock;
  254. bzero(&sind, sizeof(struct sockaddr_storage));
  255. len = 0;
  256. if ((clientsock = accept(sock, (struct sockaddr *) &sind, &len)) < 0)
  257. fatal("failed to accept an incoming connection. (%.200s)",
  258. strerror(errno));
  259. get_numeric_name(&sind);
  260. return clientsock;
  261. }