Linux HLSW LAN Master
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

178 lines
4.9 KiB

  1. /***************************************************************************
  2. * Copyright (C) 03/2005 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; either version 2 of the License, or *
  8. * (at your option) any later version. *
  9. * *
  10. * This program is distributed in the hope that it will be useful, *
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  13. * GNU General Public License for more details. *
  14. * *
  15. * You should have received a copy of the GNU General Public License *
  16. * along with this program; if not, write to the *
  17. * Free Software Foundation, Inc., *
  18. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  19. ***************************************************************************/
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <unistd.h>
  23. #include <string.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #include <netinet/ip.h>
  27. #include <arpa/inet.h>
  28. #include <sys/ioctl.h>
  29. #include "event.h"
  30. #include "netpkt.h"
  31. #include "configfile.h"
  32. #include "plugin.h"
  33. #include "scanner.h"
  34. #include "logging.h"
  35. #include "gamelist.h"
  36. static LIST_HEAD(tx_queue);
  37. static int scan_sock;
  38. int pkt_send(struct in_addr *dstip, unsigned int dstport, char *buf, unsigned int size)
  39. {
  40. struct net_pkt *pkt = malloc(sizeof(struct net_pkt) + size);
  41. if (pkt == NULL) {
  42. log_print(LOG_WARN, "pkt_send(): out of memory");
  43. return -1;
  44. }
  45. pkt->addr.sin_family = AF_INET;
  46. pkt->addr.sin_port = htons(dstport);
  47. pkt->addr.sin_addr.s_addr = (dstip ? dstip->s_addr : 0xFFFFFFFF);
  48. memcpy(pkt->buf, buf, size);
  49. pkt->size = size;
  50. list_add_tail(&pkt->list, &tx_queue);
  51. return 0;
  52. }
  53. static int scanner_transmit(void *privdata)
  54. {
  55. if (list_empty(&tx_queue))
  56. return -1;
  57. struct net_pkt *pkt;
  58. pkt = list_entry(tx_queue.next, struct net_pkt, list);
  59. list_del(&pkt->list);
  60. int ret = sendto(scan_sock, pkt->buf, pkt->size, 0, (struct sockaddr *)&pkt->addr, sizeof(pkt->addr));
  61. if (ret <= 0)
  62. log_print(LOG_WARN, "scanner_transmit(): sendto()");
  63. return 0;
  64. }
  65. static int scanner_scan(void *privdata)
  66. {
  67. plugins_scan();
  68. struct timeval tv;
  69. tv.tv_sec = 0;
  70. tv.tv_usec = 10000;
  71. event_add_timeout(&tv, scanner_transmit, NULL);
  72. return 0;
  73. }
  74. static int scanner_receive(int fd, void *privdata)
  75. {
  76. int recvsize;
  77. if (ioctl(fd, FIONREAD, &recvsize) == -1) {
  78. log_print(LOG_WARN, "scanner_receive(): ioctl(FIONREAD)");
  79. return 0;
  80. }
  81. struct net_pkt *pkt = malloc(sizeof(struct net_pkt) + recvsize);
  82. if (pkt == NULL) {
  83. log_print(LOG_WARN, "scanner_receive(): out of memory");
  84. return 0;
  85. }
  86. unsigned int i = sizeof(struct sockaddr_in);
  87. pkt->size = recvfrom(fd, pkt->buf, recvsize, 0, (struct sockaddr *)&pkt->addr, &i);
  88. if (pkt->size < 0) {
  89. log_print(LOG_WARN, "scanner_receive(): recvfrom()");
  90. free(pkt);
  91. return 0;
  92. }
  93. switch (plugins_parse(pkt)) {
  94. case PARSE_REJECT: {
  95. char *pkt_str = pkt_print(pkt);
  96. log_print(LOG_INFO, "scanner_receive(): unknown packet: %s:%d size:%d\n%s",
  97. inet_ntoa(pkt->addr.sin_addr),
  98. ntohs(pkt->addr.sin_port),
  99. pkt->size, pkt_str);
  100. free(pkt_str);
  101. }
  102. case PARSE_ACCEPT:
  103. free(pkt);
  104. case PARSE_ACCEPT_FREED:
  105. break;
  106. }
  107. return 0;
  108. }
  109. int scanner_init()
  110. {
  111. scan_sock = socket(PF_INET, SOCK_DGRAM, 0);
  112. if (scan_sock < 0) {
  113. log_print(LOG_ERROR, "scan_init(): socket()");
  114. return -1;
  115. }
  116. struct sockaddr_in src;
  117. char *addr = config_get_string("global", "scanner_src", "0.0.0.0:7130");
  118. if (parse_saddr(addr, &src) != 0) {
  119. log_print(LOG_ERROR, "server_init(): invalid scanner_src '%s'", addr);
  120. return -1;
  121. }
  122. if (bind(scan_sock, (struct sockaddr *)&src, sizeof(src)) < 0) {
  123. log_print(LOG_ERROR, "scan_init(): bind()");
  124. return -1;
  125. }
  126. int j = 1;
  127. if (setsockopt(scan_sock, SOL_SOCKET, SO_BROADCAST, &j, sizeof(j))) {
  128. log_print(LOG_ERROR, "scan_init(): setsockopt(SO_BROADCAST)");
  129. return -1;
  130. }
  131. int rxsize = 1<<20;
  132. if (setsockopt(scan_sock, SOL_SOCKET, SO_RCVBUF, &rxsize, sizeof(rxsize))) {
  133. log_print(LOG_ERROR, "scan_init(): setsockopt(SO_RCVBUF)");
  134. return -1;
  135. }
  136. event_add_readfd(scan_sock, scanner_receive, NULL);
  137. log_print(LOG_INFO, "scan socket initialized (%s:%d)", inet_ntoa(src.sin_addr), ntohs(src.sin_port));
  138. struct timeval tv;
  139. tv.tv_sec = config_get_int("global", "scan_interval", 60);
  140. tv.tv_usec = 0;
  141. event_add_timeout(&tv, scanner_scan, NULL);
  142. scanner_scan(NULL);
  143. return 0;
  144. }