diff --git a/include/hlswmaster.h b/include/hlswmaster.h index d387153..d251997 100644 --- a/include/hlswmaster.h +++ b/include/hlswmaster.h @@ -32,6 +32,7 @@ int plugins_parse(struct net_pkt *pkt); int plugins_gc(unsigned long timeout); /* scanner.c */ +void pkt_queue(struct net_pkt *pkt); int scan_init(void); void scan_exit(void); void scan_transmit(void); diff --git a/include/plugin.h b/include/plugin.h index 1d3c9fd..a9caefc 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -4,13 +4,21 @@ #include "netpkt.h" #include "list.h" -extern void pkt_queue(struct net_pkt *pkt); -extern int server_add(unsigned int gameid, struct in_addr ip, u_int16_t port1, u_int16_t port2); +extern int server_add(unsigned int gameid, struct in_addr *ip, u_int16_t port1, u_int16_t port2); -extern struct net_pkt * pkt_factory(char *dstip, unsigned int dstport, char *buf, unsigned int size); +struct scan_ports { + unsigned short portlo; + unsigned short porthi; + unsigned short gameid; +}; +extern int pkt_send(struct in_addr *dstip, unsigned int dstport, char *buf, unsigned int size); +extern int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *buf, unsigned int size); + +extern int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr); extern int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size); -extern int pkt_strcmp(struct net_pkt *pkt, unsigned int offset, char *search); + +extern int server_add_pkt(unsigned int gameid, struct net_pkt *pkt); struct hlswmaster_plugin { /* must be first */ diff --git a/plugins/quake3.c b/plugins/quake3.c index 41c1a95..14752ce 100644 --- a/plugins/quake3.c +++ b/plugins/quake3.c @@ -1,41 +1,57 @@ +/*************************************************************************** + * Copyright (C) 03/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.h" -#define GAMEID_Q3 0x0006 +struct scan_ports port_arr[] = { + { 20099, 20110, 13 }, /* Soldier of Fortune 2 */ + { 27960, 27963, 6 }, /* Q3, Elite Force, RtCW, ET, CoD */ + { 28069, 28080, 12 }, /* Jedi Knight 2 */ + { 29069, 29080, 27 }, /* Jedi Knight 3 */ + { 29252, 29263, 26 }, /* Elite Force 2 */ + { 0,0,0 } +}; + +static char scanmsg[] = "\xff\xff\xff\xffgetstatus"; +static char replymsg[] = "\xff\xff\xff\xffstatusResponse"; int scan(void) { - struct net_pkt *scan; - unsigned int port; - char msg[] = "\xff\xff\xff\xffgetstatus"; - - for (port = 27960; port <= 27963; port++) { - if (!(scan = pkt_factory(NULL, port, msg, 13))) - return 0; - - pkt_queue(scan); - } + pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg)); return 1; } int parse(struct net_pkt *pkt) { - if (!pkt_strcmp(pkt, 0, "\xff\xff\xff\xffstatusResponse")) { - server_add(GAMEID_Q3, pkt->addr.sin_addr, pkt->addr.sin_port, 0); - return 1; - } - return 0; -} + int gameid; -int init(struct list_head *config) { - return 1; -} + if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg))) + return 0; + + if (!(gameid = pkt_check_portarr(pkt, port_arr))) + return 0; -int fini(void) { + server_add_pkt(gameid, pkt); return 1; } static struct hlswmaster_plugin quake3_plugin = { .name = "quake3", - .init = &init, - .fini = &fini, .scan = &scan, .parse = &parse, }; diff --git a/src/client.c b/src/client.c index 261e5d0..1111059 100644 --- a/src/client.c +++ b/src/client.c @@ -33,7 +33,7 @@ #define HLSW_HEADER "\xFF\xFF\xFF\xFFHLSWLANSEARCH\x00" #define HLSW_HEADER_LEN 0x12 -#define MAX_PKT_LEN (1400 + HLSW_HEADER_LEN) +#define MAX_PKT_LEN (HLSW_HEADER_LEN + 1400) struct client_pkt { struct list_head list; @@ -188,7 +188,7 @@ void client_handler(void) { pthread_mutex_lock(&pkt_list_lock); - /* unsere vorbereiteten pakete ausgeben */ + /* pakete aus der real list senden */ list_for_each_entry(pkt, &client_pkt_list, list) sendto(sock, pkt->buf, pkt->size, 0, (struct sockaddr *)&dst, sizeof(dst)); diff --git a/src/daemon.c b/src/daemon.c index 07c1508..df80852 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -1,3 +1,22 @@ +/*************************************************************************** + * Copyright (C) 03/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 #include @@ -5,6 +24,15 @@ #include "hlswmaster.h" +/** + * daemonize() + * macht den Prozess zu einen Daemon + * und fuehrt ihn unterem user aus + * + * @param char *pw_name + * + * TODO: hier schon logging benutzen? stderr? wann exit/return? + */ void daemonize(char *pw_name) { int fail = 0; pid_t pid; @@ -15,6 +43,7 @@ void daemonize(char *pw_name) { exit(-1); } else if (pid != 0) { + /* Elternprozess beenden */ exit(0); } else { diff --git a/src/logging.c b/src/logging.c index 1f4e95a..af5ed5f 100644 --- a/src/logging.c +++ b/src/logging.c @@ -1,3 +1,22 @@ +/*************************************************************************** + * Copyright (C) 03/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 #include @@ -7,10 +26,21 @@ static FILE *log_fd = NULL; +/** + * log_close() + * schliesst das logfile + */ void log_close() { fclose(log_fd); } +/** + * log_open() + * oeffnet ein logfile + * wenn der prozess sich beendet, wird das logfile auch wieder geschlossen + * + * @param char *logfile + */ void log_open(char *logfile) { if ((log_fd = fopen(logfile, "a" )) == NULL) { fprintf(stderr, "log_open(\"%s\"): %s\n", logfile, strerror(errno)); @@ -22,6 +52,13 @@ void log_open(char *logfile) { } } +/** + * log_print() + * schreibt eine Zeile ins Logfile oder auf stderr + * wenn errno gesetzt ist, wird der error-string mit ausgegeben + * + * @param variable parameterlist + */ void log_print(const char *fmt, ...) { va_list az; time_t tzgr; diff --git a/src/main.c b/src/main.c index df42034..d205d78 100644 --- a/src/main.c +++ b/src/main.c @@ -1,3 +1,22 @@ +/*************************************************************************** + * Copyright (C) 03/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 #include @@ -63,10 +82,11 @@ int main(int argc, char *argv[]) { scan_init(); - pthread_create(&thread1, NULL, (void *)&scan_transmit, NULL); - pthread_create(&thread2, NULL, (void *)&scan_receive, NULL); - pthread_create(&thread3, NULL, (void *)&server_collector, NULL); - pthread_create(&thread4, NULL, (void *)&client_handler, NULL); + scan_transmit(); +// pthread_create(&thread1, NULL, (void *)&scan_transmit, NULL); +// pthread_create(&thread2, NULL, (void *)&scan_receive, NULL); +// pthread_create(&thread3, NULL, (void *)&server_collector, NULL); +// pthread_create(&thread4, NULL, (void *)&client_handler, NULL); sleep(9999); diff --git a/src/plugin.c b/src/plugin.c index e860255..ab533f0 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -32,19 +32,44 @@ LIST_HEAD(plugin_list); /* sichert die plugin list UND die plugins ab */ static pthread_mutex_t plugin_lock = PTHREAD_MUTEX_INITIALIZER; +/** + * plugin_load() + * laedt ein plugin + * + * @param char *name + * @return false on error + * + * TODO: pfadname als parameter (config-file?) + * TODO: referenz speichern? wo? wie? + */ int plugin_load(char *name) { void *tmp; if (!(tmp = dlopen(name, RTLD_NOW))) log_print("unable to load plugin '%s'", name); - return 0; + return 1; } +/** + * plugin_unload() + * entfernt ein plugin + * + * @param char *name + * @return false on error + * + * TODO: implementieren? oder lieber nicht? + */ int plugin_unload(char *name) { - return 0; + return 1; } +/** + * plugins_scan() + * ruft die scan() Funktionen der Plugins auf (wenn vorhanden) + * + * @return true + */ int plugins_scan(void) { struct hlswmaster_plugin *plugin; @@ -57,6 +82,14 @@ int plugins_scan(void) { return 1; } +/** + * plugins_parse() + * ruft die parse() Funktionen der Plugins auf (wenn vorhanden) + * bis ein Plugin das Paket annimmt + * + * @param struct net_pkt *pkt + * @return false wenn kein Plugin das Paket angenommen hat + */ int plugins_parse(struct net_pkt *pkt) { struct hlswmaster_plugin *plugin; @@ -72,6 +105,13 @@ int plugins_parse(struct net_pkt *pkt) { return 0; } +/** + * plugins_gc() + * ruft die gc() Funktionen der Plugins auf (wenn vorhanden) + * + * @param unsigned long timeout + * @return true + */ int plugins_gc(unsigned long timeout) { struct hlswmaster_plugin *plugin; @@ -84,7 +124,12 @@ int plugins_gc(unsigned long timeout) { return 1; } -/* called vom plugin:_init() after local init */ +/** + * register_plugin() + * wird von den Plugins beim laden (durch _init())aufgerufen + * + * @param struct hlswmaster_plugin *me + */ void register_plugin(struct hlswmaster_plugin *me) { if (!me->init || (me->init(NULL))) { pthread_mutex_lock(&plugin_lock); @@ -93,7 +138,12 @@ void register_plugin(struct hlswmaster_plugin *me) { } } -/* called vom plugin:_fini() after local finish */ +/** + * register_plugin() + * wird von den Plugins beim entfernen (durch fini) aufgerufen + * + * @param struct hlswmaster_plugin *me + */ void unregister_plugin(struct hlswmaster_plugin *me) { pthread_mutex_lock(&plugin_lock); list_del((struct list_head *)me); diff --git a/src/plugin_helper.c b/src/plugin_helper.c index f833be3..be52875 100644 --- a/src/plugin_helper.c +++ b/src/plugin_helper.c @@ -1,3 +1,22 @@ +/*************************************************************************** + * Copyright (C) 03/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 #include @@ -7,31 +26,91 @@ #include #include +#include "hlswmaster.h" #include "plugin.h" #include "netpkt.h" -struct net_pkt * pkt_factory(char *dstip, unsigned int dstport, char *buf, unsigned int size) { +/** + * pkt_queue() + * erzeugt ein net_pkt aus den parametern und legt es in die send queue + * + * @param struct in_addr *dstip - pointer auf eine IP, wenn NULL wird broadcast angenommen + * @param unsigned int dstport - destination port + * @param char *buf - pointer auf den zu sendenen speicherbereich + * @param unsigned int size - groesse des speicherbereichs + * @return false bei fehler + */ +int pkt_send(struct in_addr *dstip, unsigned int dstport, char *buf, unsigned int size) { struct net_pkt *pkt; if (!(pkt = malloc(sizeof(struct net_pkt) + size))) - return NULL; + return 0; INIT_LIST_HEAD(&pkt->list); pkt->addr.sin_family = AF_INET; pkt->addr.sin_port = htons(dstport); - - if (dstip) - inet_aton(dstip, &pkt->addr.sin_addr); - else - inet_aton("255.255.255.255", &pkt->addr.sin_addr); + pkt->addr.sin_addr.s_addr = (dstip ? dstip->s_addr : 0xFFFFFFFF); pkt->size = size; memcpy(pkt->buf, buf, size); - return pkt; + pkt_queue(pkt); + return 1; } +/** + * pkt_queue_portarr() + * erzeugt ein net_pkt aus den parametern und legt es in die send queue + * + * @param char *dstip - pointer auf eine IP, wenn NULL wird broadcast angenommen + * @param struct scan_ports *port_arr + * @param char *buf - pointer auf den zu sendenen speicherbereich + * @param unsigned int size - groesse des speicherbereichs + * @return false bei fehler + */ +int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *buf, unsigned int size) { + unsigned short port; + while (portarr && portarr->portlo) { + for (port = portarr->portlo; port <= portarr->porthi; port++) + pkt_send(dstip, port, buf, size); + + portarr++; + } + return 1; +} + + +/** + * pkt_check_portarr() + * prueft ob der src-port des pakets in der portliste vorhanden ist + * + * @param struct net_pkt *pkt + * @param struct scan_ports *port_arr + * @return die gameid der portrange oder 0 wenn nicht vorhanden + */ +int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr) { + unsigned short port; + while (portarr && portarr->portlo) { + for (port = portarr->portlo; port <= portarr->porthi; port++) + if (port == ntohs(pkt->addr.sin_port)) + return portarr->gameid; + + portarr++; + } + return 0; +} + +/** + * pkt_memcmp() + * vergleicht das Paket mit einem Speicherbereich + * + * @param struct net_pkt *pkt + * @param unsigned int offset + * @param char *search + * @param unsigned int size + * @return true wenn gleich + */ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { if (offset >= pkt->size) @@ -43,6 +122,15 @@ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned return memcmp(pkt->buf, search, size); } -int pkt_strcmp(struct net_pkt *pkt, unsigned int offset, char *search) { - return pkt_memcmp(pkt, offset, search, strlen(search)); +/** + * server_add_pkt() + * fuegt der serverliste einen server hinzu + * + * @param unsigned int gameid + * @param struct net_pkt *pkt + * @return false bei fehler + */ +int server_add_pkt(unsigned int gameid, struct net_pkt *pkt) { + return server_add(gameid, &pkt->addr.sin_addr, pkt->addr.sin_port, 0); } + diff --git a/src/scanner.c b/src/scanner.c index e4a6d9e..98143a0 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -36,10 +36,23 @@ LIST_HEAD(send_queue); static int scan_sock; +/** + * _pkt_queue() + * packt ein paket in die sender queue + * @param struct net_pkt *pkt + */ void pkt_queue(struct net_pkt *pkt) { list_add_tail(&pkt->list, &send_queue); } +/** + * scan_transmit() + * triggert den scan der plugins + * arbeitet die sender queue ab + * + * TODO: ratelimiting + * TODO: interval als parameter (config file?) + */ void scan_transmit(void) { struct net_pkt *pkt, *tmp; @@ -52,12 +65,18 @@ void scan_transmit(void) { list_del(&pkt->list); free(pkt); + usleep(100000); } sleep(30); } } +/** + * scan_receive() + * wartet auf serverantworten und uebergibt die pakete den + * plugins zur auswertung + */ void scan_receive(void) { struct net_pkt *pkt; fd_set fdsel, fdcpy; @@ -88,6 +107,13 @@ void scan_receive(void) { } } +/** + * scan_init() + * initialisiert den socket fuer den server scan + * @return false on error + * + * TODO: src ip/port als parameter (config-file?) + */ int scan_init() { struct sockaddr_in dst; int i; @@ -114,6 +140,9 @@ int scan_init() { return 1; } +/** + * schliesst den server scan socket + */ void scan_exit() { close(scan_sock); } diff --git a/src/serverlist.c b/src/serverlist.c index 5edb1f2..89f384f 100644 --- a/src/serverlist.c +++ b/src/serverlist.c @@ -62,11 +62,11 @@ static inline int server_cmp(const struct game_server *a, struct game_server *b) * @param u_int16_t port2 * @return false bei fehler */ -int server_add(unsigned int gameid, struct in_addr ip, u_int16_t port1, u_int16_t port2) { +int server_add(unsigned int gameid, struct in_addr *ip, u_int16_t port1, u_int16_t port2) { struct game_server server, *nserver; server.gameid = gameid; - server.ip = ip.s_addr; + server.ip = ip->s_addr; server.port1 = ntohs(port1); server.port2 = ntohs(port2);