symuxnet.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /* $Id: symuxnet.c,v 1.16 2004/02/29 21:23:19 dijkstra Exp $ */
  2. /*
  3. * Copyright (c) 2001-2004 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. switch (errno) {
  77. case EADDRNOTAVAIL:
  78. warning("mux address %.200s is not a local address", mux->addr);
  79. break;
  80. case EADDRINUSE:
  81. warning("mux address %.200s %.200s already in use", mux->addr, mux->port);
  82. break;
  83. case EACCES:
  84. warning("mux port %.200s is restricted from current user", mux->port);
  85. break;
  86. }
  87. close(mux->symonsocket[family]);
  88. mux->symonsocket[family] = 0;
  89. } else {
  90. if (get_numeric_name(&sockaddr)) {
  91. info("getnameinfo error - cannot determine numeric hostname and service");
  92. info("listening for incoming symon traffic for family %d", family);
  93. } else
  94. info("listening for incoming symon traffic on udp %.200s %.200s",
  95. res_host, res_service);
  96. nsocks++;
  97. }
  98. }
  99. }
  100. }
  101. return nsocks;
  102. }
  103. /* Obtain a listen socket for new clients */
  104. int
  105. get_client_socket(struct mux * mux)
  106. {
  107. struct addrinfo hints, *res;
  108. int error, sock;
  109. if ((sock = socket(mux->sockaddr.ss_family, SOCK_STREAM, 0)) == -1)
  110. fatal("could not obtain socket: %.200s", strerror(errno));
  111. bzero((void *) &hints, sizeof(struct addrinfo));
  112. hints.ai_family = mux->sockaddr.ss_family;
  113. hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  114. hints.ai_socktype = SOCK_STREAM;
  115. if ((error = getaddrinfo(mux->addr, mux->port, &hints, &res)) != 0)
  116. fatal("could not get address information for %.200s:%.200s - %.200s",
  117. mux->addr, mux->port, gai_strerror(error));
  118. if (bind(sock, (struct sockaddr *) res->ai_addr, res->ai_addrlen) == -1)
  119. fatal("could not bind socket: %.200s", strerror(errno));
  120. freeaddrinfo(res);
  121. if (listen(sock, SYMUX_TCPBACKLOG) == -1)
  122. fatal("could not listen to socket: %.200s", strerror(errno));
  123. fcntl(sock, O_NONBLOCK);
  124. mux->clientsocket = sock;
  125. info("listening for incoming connections on tcp %.200s %.200s",
  126. mux->addr, mux->port);
  127. return sock;
  128. }
  129. /*
  130. * Wait for traffic (symon reports from a source in sourclist | clients trying to connect
  131. * Returns the <source> and <packet>
  132. * Silently forks off clienthandlers
  133. */
  134. void
  135. wait_for_traffic(struct mux * mux, struct source ** source,
  136. struct symonpacket * packet)
  137. {
  138. fd_set readset;
  139. int i;
  140. int socksactive;
  141. int maxsock;
  142. for (;;) { /* FOREVER - until a valid symon packet is
  143. * received */
  144. FD_ZERO(&readset);
  145. FD_SET(mux->clientsocket, &readset);
  146. maxsock = mux->clientsocket;
  147. for (i = 0; i < AF_MAX; i++) {
  148. if (mux->symonsocket[i] > 0) {
  149. FD_SET(mux->symonsocket[i], &readset);
  150. maxsock = ((maxsock < mux->symonsocket[i]) ? mux->symonsocket[i] :
  151. maxsock);
  152. }
  153. }
  154. maxsock++;
  155. socksactive = select(maxsock, &readset, NULL, NULL, NULL);
  156. if (socksactive != -1) {
  157. if (FD_ISSET(mux->clientsocket, &readset)) {
  158. spawn_client(mux->clientsocket);
  159. }
  160. for (i = 0; i < AF_MAX; i++)
  161. if (FD_ISSET(mux->symonsocket[i], &readset)) {
  162. if (recv_symon_packet(mux, i, source, packet))
  163. return;
  164. }
  165. } else {
  166. if (errno == EINTR)
  167. return; /* signal received while waiting, bail out */
  168. }
  169. }
  170. }
  171. /* Receive a symon packet for mux. Checks if the source is allowed and returns the source found.
  172. * return 0 if no valid packet found
  173. */
  174. int
  175. recv_symon_packet(struct mux * mux, int socknr, struct source ** source,
  176. struct symonpacket * packet)
  177. {
  178. struct sockaddr_storage sind;
  179. socklen_t sl;
  180. int size, tries;
  181. unsigned int received;
  182. u_int32_t crc;
  183. received = 0;
  184. tries = 0;
  185. do {
  186. sl = sizeof(sind);
  187. size = recvfrom(mux->symonsocket[socknr],
  188. (void *) (packet->data + received),
  189. sizeof(struct symonpacket) - received,
  190. 0, (struct sockaddr *) &sind, &sl);
  191. if (size > 0)
  192. received += size;
  193. tries++;
  194. } while ((size == -1) &&
  195. (errno == EAGAIN || errno == EINTR) &&
  196. (tries < SYMUX_MAXREADTRIES) &&
  197. (received < sizeof(packet->data)));
  198. if ((size == -1) &&
  199. errno)
  200. warning("recvfrom failed: %.200s", strerror(errno));
  201. *source = find_source_sockaddr(&mux->sol, (struct sockaddr *) &sind);
  202. get_numeric_name(&sind);
  203. if (*source == NULL) {
  204. debug("ignored data from %.200s:%.200s", res_host, res_service);
  205. return 0;
  206. } else {
  207. /* get header stream */
  208. mux->offset = getheader(packet->data, &packet->header);
  209. /* check crc */
  210. crc = packet->header.crc;
  211. packet->header.crc = 0;
  212. setheader(packet->data, &packet->header);
  213. crc ^= crc32(packet->data, received);
  214. if (crc != 0) {
  215. warning("ignored packet with bad crc from %.200s:%.200s",
  216. res_host, res_service);
  217. return 0;
  218. }
  219. /* check packet version */
  220. if (packet->header.symon_version != SYMON_PACKET_VER) {
  221. warning("ignored packet with wrong version %d from %.200s:%.200s",
  222. packet->header.symon_version, res_host, res_service);
  223. return 0;
  224. } else {
  225. if (flag_debug) {
  226. debug("good data received from %.200s:%.200s", res_host, res_service);
  227. }
  228. return 1; /* good packet received */
  229. }
  230. }
  231. }
  232. int
  233. accept_connection(int sock)
  234. {
  235. struct sockaddr_storage sind;
  236. socklen_t len;
  237. int clientsock;
  238. if ((clientsock = accept(sock, (struct sockaddr *) &sind, &len)) < 0)
  239. fatal("failed to accept an incoming connection. (%.200s)",
  240. strerror(errno));
  241. get_numeric_name(&sind);
  242. return clientsock;
  243. }