symuxnet.c 7.6 KB

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