/*************************************************************************** * Copyright (C) 04/2005 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "plugin_helper.h" struct net_entry { struct in_addr ip; struct in_addr mask; }; static struct net_entry *net_arr = NULL; static int net_arr_size = 0; static struct scan_ports port_arr[] = { { 27015, 27024, 1 }, /* cs/hl */ { 0, 0, 0 } }; static char scanmsg1[] = "\xff\xff\xff\xff" "details"; static char scanmsg2[] = "\xff\xff\xff\xff\x54"; static int scan(void) { pkt_send_portarr(NULL, port_arr, scanmsg1, strlen(scanmsg1)); pkt_send_portarr(NULL, port_arr, scanmsg2, strlen(scanmsg2)); return 1; } static int parse(struct net_pkt *pkt) { struct in_addr tmp; int port, count, pos, i; if (!pkt_check_portarr(pkt, port_arr)) return PARSE_REJECT; // check 0xFF 0xFF 0xFF 0xFF if (pkt_memcmp(pkt, 0, scanmsg1, 4)) return PARSE_REJECT; /* check for short answer without ip/port */ if (pkt->size >= 5 && pkt->buf[4] == 'm' && pkt->buf[5] == 0x00) { server_add_pkt(1, pkt); return PARSE_ACCEPT; } /* second query?! */ if (pkt->size >= 5 && pkt->buf[4] == 'I' && pkt->buf[5] == 0x07) { server_add_pkt(40, pkt); return PARSE_ACCEPT; } /* parse server IP */ pos = 5; if ((count = pkt_parse_ip(pkt, pos, &tmp)) == 0) return PARSE_REJECT; /* parse server port */ pos += count +1; if ((count = pkt_parse_int(pkt, pos, &port)) == 0) return PARSE_REJECT; /* check server IP */ for (i = 0; i < net_arr_size; i++) { if (((net_arr[i].ip.s_addr ^ tmp.s_addr) & net_arr[i].mask.s_addr) == 0) { server_add(1, tmp.s_addr, port, 0); return PARSE_ACCEPT; } } server_add(1, pkt->addr.sin_addr.s_addr, port, 0); return PARSE_ACCEPT; } static int parse_net(char *buf, struct net_entry *net) { char *p; /* valid_net x.x.x.x */ if ((p = strchr(buf, '/')) == NULL) { /* ip */ if (inet_pton(AF_INET, buf, &net->ip) <= 0) return 0; /* mask */ net->mask.s_addr = 0xFFFFFFFF; return 1; /* valid_net x.x.x.x/x.x.x.x oder x.x.x.x/xx */ } else { int retval, mask; *p = 0x00; /* ip */ if (inet_pton(AF_INET, buf, &net->ip) <= 0) { retval = 0; /* x.x.x.x/x.x.x.x */ } else if (inet_pton(AF_INET, p+1, &net->mask) > 0) { retval = 1; /* x.x.x.x/xx */ } else { mask = atoi(p+1); if (mask >= 0 && mask <= 32) { net->mask.s_addr = htonl(0xFFFFFFFF << (32 - mask)); retval = 1; } else { retval = 0; } } *p = '/'; return retval; } } static int init(struct conf_section *section) { struct conf_tupel *tupel; static char buf[32]; int i = 0, j; list_for_each_entry(tupel, §ion->tupel, list) if (!strcmp(tupel->option, "valid_net")) i++; if (i == 0 || !(net_arr = malloc(sizeof(struct net_entry) * i))) return 0; i = 0; list_for_each_entry(tupel, §ion->tupel, list) { if (strcmp(tupel->option, "valid_net")) continue; if (parse_net(tupel->parameter, &net_arr[i])) { j = sprintf(buf, " adding: %s", inet_ntoa(net_arr[i].ip)); sprintf(buf + j, "/%s", inet_ntoa(net_arr[i].mask)); log_print(buf); i++; } else { log_print(" invalid net: %s", tupel->parameter); } } net_arr_size = i; return 1; } static int fini() { if (net_arr_size > 0 && net_arr) free(net_arr); } struct hlswmaster_plugin plugin = { .name = "halflife", .scan = &scan, .parse = &parse, .init = &init, .fini = &fini, };