diff --git a/Makefile b/Makefile index 85105ca..40177d1 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,24 @@ # Toplevel Makefile MASTER_SRC := src/client.c src/daemon.c src/logging.c src/main.c src/plugin.c src/plugin_helper.c src/scanner.c src/serverlist.c -PLUGIN_SRC := plugins/quake3.c - -CFLAGS := -Wall -I. -I./include -g -fPIC - -DEPFILES := $(PLUGIN_SRC:%.c=%.d) $(MASTER_SRC:%.c=%.d) +PLUGIN_SRC := plugins/hlswproxy.c plugins/quake3.c +CFLAGS := -Wall -I. -I./include -g # ############################ -all: $(DEPFILES) $(PLUGIN_SRC:%.c=%.so) src/hlswmaster +all: $(PLUGIN_SRC:%.c=%.so) src/hlswmaster src/hlswmaster: $(MASTER_SRC:%.c=%.o) gcc -ldl -lpthread -rdynamic $^ -o $@ -%.d: %.c - @-$(CC) -M -MG $(CFLAGS) $< > $@ - -%.o: %.c %.d +%.o: %.c $(CC) $(CFLAGS) -o $@ -c $< -%.so: %.o +%_sh.o: %.c + $(CC) $(CFLAGS) -fPIC -o $@ -c $< + +%.so: %_sh.o $(LD) -shared -o $@ $< clean: - rm -rf src/hlswmaster src/*.o plugins/*.so plugins/*.o $(DEPFILES) - --include $(DEPFILES) + rm -rf src/hlswmaster src/*.o plugins/*.so plugins/*.o \ No newline at end of file diff --git a/include/hlswmaster.h b/include/hlswmaster.h index d251997..92a4f8e 100644 --- a/include/hlswmaster.h +++ b/include/hlswmaster.h @@ -5,16 +5,15 @@ #include "netpkt.h" struct game_server { - /* must be first */ struct list_head list; + unsigned long modtime; u_int16_t gameid; u_int32_t ip; u_int16_t port1; u_int16_t port2; - unsigned long modtime; -}; +} __attribute__ ((packed)); /* daemon.c */ void daemonize(char *pw_name); diff --git a/include/netpkt.h b/include/netpkt.h index b5e29ba..ab9bd64 100644 --- a/include/netpkt.h +++ b/include/netpkt.h @@ -8,13 +8,11 @@ #include "list.h" struct net_pkt { - /* must be first */ struct list_head list; struct sockaddr_in addr; unsigned int size; unsigned char buf[0]; - }; #endif diff --git a/include/plugin.h b/include/plugin.h index a9caefc..c03b116 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -4,7 +4,7 @@ #include "netpkt.h" #include "list.h" -extern int server_add(unsigned int gameid, struct in_addr *ip, u_int16_t port1, u_int16_t port2); +extern int server_add(u_int16_t gameid, u_int32_t ip, u_int16_t port1, u_int16_t port2); struct scan_ports { unsigned short portlo; @@ -17,9 +17,13 @@ extern int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, c 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 void * pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size); extern int server_add_pkt(unsigned int gameid, struct net_pkt *pkt); +extern char * pkt_ntoa(struct net_pkt *pkt); +extern unsigned short pkt_getport(struct net_pkt *pkt); + struct hlswmaster_plugin { /* must be first */ struct list_head list; diff --git a/plugins/hlswproxy.c b/plugins/hlswproxy.c new file mode 100644 index 0000000..a65f9c2 --- /dev/null +++ b/plugins/hlswproxy.c @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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 "plugin.h" + +static char scanmsg[] = "\xff\xff\xff\xffHLSWLANSEARCH"; + +struct _entry { + u_int16_t gameid; + u_int32_t ip; + u_int16_t port1; + u_int16_t port2; +} __attribute__ ((packed)); + +int scan(void) { + pkt_send(NULL, 7140, scanmsg, sizeof(scanmsg)); + return 1; +} + +int parse(struct net_pkt *pkt) { + struct _entry *server; + if (pkt_getport(pkt) != 7140) + return 0; + + server = (void *)pkt->buf + sizeof(scanmsg); + + while ((void *)server < ((void *)pkt->buf + pkt->size)) { + server_add(server->gameid, server->ip, server->port1, server->port2); + server++; + } + return 1; +} + +static struct hlswmaster_plugin hlswproxy_plugin = { + .name = "hlswproxy", + .scan = &scan, + .parse = &parse, +}; + +void _init(void) { + register_plugin(&hlswproxy_plugin); +} + +void _fini(void) { + unregister_plugin(&hlswproxy_plugin); +} diff --git a/plugins/quake3.c b/plugins/quake3.c index 14752ce..85fafac 100644 --- a/plugins/quake3.c +++ b/plugins/quake3.c @@ -21,11 +21,8 @@ #include "plugin.h" 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 */ + { 27960, 27963, 6 }, /* Quake3 (razzor) */ + { 28960, 28964, 31 }, /* Call of Duty (ove) */ { 0,0,0 } }; @@ -42,7 +39,7 @@ int parse(struct net_pkt *pkt) { if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg))) return 0; - + if (!(gameid = pkt_check_portarr(pkt, port_arr))) return 0; diff --git a/src/client.c b/src/client.c index 1111059..87ee21b 100644 --- a/src/client.c +++ b/src/client.c @@ -33,7 +33,8 @@ #define HLSW_HEADER "\xFF\xFF\xFF\xFFHLSWLANSEARCH\x00" #define HLSW_HEADER_LEN 0x12 -#define MAX_PKT_LEN (HLSW_HEADER_LEN + 1400) +#define HLSW_ENTRY_LEN 10 +#define MAX_PKT_LEN (HLSW_HEADER_LEN + HLSW_ENTRY_LEN * 140) struct client_pkt { struct list_head list; @@ -56,7 +57,7 @@ static pthread_mutex_t pkt_list_lock = PTHREAD_MUTEX_INITIALIZER; * @param void *b * @return true wenn das paket noch nicht voll ist */ -static inline int pkt_not_full(const struct client_pkt *a, void *b) { +static inline int cpkt_not_full(const struct client_pkt *a, void *b) { return (a->size < MAX_PKT_LEN); } @@ -76,8 +77,9 @@ static struct client_pkt * client_pkt_add_real(struct list_head *list) { INIT_LIST_HEAD(&new->list); - new->size = HLSW_HEADER_LEN; + /* kopier den hlsw header in das client paket */ memcpy(new->buf, HLSW_HEADER, HLSW_HEADER_LEN); + new->size = HLSW_HEADER_LEN; list_add_tail(&new->list, list); return new; @@ -90,33 +92,18 @@ static struct client_pkt * client_pkt_add_real(struct list_head *list) { * * @param struct game_server *server * @return false bei fehler (malloc) - * - * TODO: memcpy() durch pointer ops ersetzen? */ int client_pkt_add(struct game_server *server) { - struct client_pkt *pkt; + struct client_pkt *cpkt; - char *src, *dst; - - pkt = LIST_FIND(&client_pkt_prepare, pkt_not_full, struct client_pkt *, NULL); - if (!pkt && !(pkt = client_pkt_add_real(&client_pkt_prepare))) + cpkt = LIST_FIND(&client_pkt_prepare, cpkt_not_full, struct client_pkt *, NULL); + if (!cpkt && !(cpkt = client_pkt_add_real(&client_pkt_prepare))) return 0; - dst = (char *)&pkt->buf + pkt->size; + /* kopiert den server eintrag in das client paket */ + memcpy((void *)&cpkt->buf + cpkt->size, &server->gameid, HLSW_ENTRY_LEN); + cpkt->size += HLSW_ENTRY_LEN; - src = (char *)&server->gameid; - memcpy(dst, src, 2); - - src = (char *)&server->ip; - memcpy(dst +2, src, 4); - - src = (char *)&server->port1; - memcpy(dst +6, src, 4); - - src = (char *)&server->port2; - memcpy(dst +8, src, 4); - - pkt->size += 10; return 1; } diff --git a/src/main.c b/src/main.c index d205d78..1577d9a 100644 --- a/src/main.c +++ b/src/main.c @@ -79,15 +79,15 @@ int main(int argc, char *argv[]) { plugin_load("plugins/quake3.so"); + plugin_load("plugins/hlswproxy.so"); scan_init(); - 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); - +// 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 ab533f0..f36a6cb 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -38,7 +38,7 @@ static pthread_mutex_t plugin_lock = PTHREAD_MUTEX_INITIALIZER; * * @param char *name * @return false on error - * + * * TODO: pfadname als parameter (config-file?) * TODO: referenz speichern? wo? wie? */ @@ -69,7 +69,7 @@ int plugin_unload(char *name) { * ruft die scan() Funktionen der Plugins auf (wenn vorhanden) * * @return true - */ + */ int plugins_scan(void) { struct hlswmaster_plugin *plugin; @@ -89,7 +89,7 @@ int plugins_scan(void) { * * @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; @@ -111,7 +111,9 @@ int plugins_parse(struct net_pkt *pkt) { * * @param unsigned long timeout * @return true - */ + * + * TODO: wird noch nicht benutzt + */ int plugins_gc(unsigned long timeout) { struct hlswmaster_plugin *plugin; @@ -133,7 +135,7 @@ int plugins_gc(unsigned long timeout) { void register_plugin(struct hlswmaster_plugin *me) { if (!me->init || (me->init(NULL))) { pthread_mutex_lock(&plugin_lock); - list_add((struct list_head *)me, &plugin_list); + list_add_tail((struct list_head *)me, &plugin_list); pthread_mutex_unlock(&plugin_lock); } } diff --git a/src/plugin_helper.c b/src/plugin_helper.c index be52875..a240350 100644 --- a/src/plugin_helper.c +++ b/src/plugin_helper.c @@ -20,7 +20,10 @@ #include #include #include + +#define __USE_GNU #include + #include #include #include @@ -74,13 +77,12 @@ int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *bu 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 @@ -95,7 +97,7 @@ int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr) { for (port = portarr->portlo; port <= portarr->porthi; port++) if (port == ntohs(pkt->addr.sin_port)) return portarr->gameid; - + portarr++; } return 0; @@ -119,7 +121,24 @@ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned if (offset + size >= pkt->size) size = pkt->size - offset; - return memcmp(pkt->buf, search, size); + return memcmp(pkt->buf + offset, search, size); +} + +/** + * pkt_memmem() + * sucht einen Speicherbereich in dem Paket + * + * @param struct net_pkt *pkt + * @param unsigned int offset + * @param char *search + * @param unsigned int size + * @return pointer auf den string im Paket + */ +void * pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { + if (offset >= pkt->size) + return NULL; + + return memmem(pkt->buf + offset, pkt->size, search, size); } /** @@ -131,6 +150,27 @@ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned * @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); + return server_add(gameid, pkt->addr.sin_addr.s_addr, ntohs(pkt->addr.sin_port), 0); } +/** + * pkt_ntoa() + * gibt die IP des Pakets als String zurueck + * + * @param struct net_pkt *pkt + * @return pointer auf String + */ +char * pkt_ntoa(struct net_pkt *pkt) { + return inet_ntoa(pkt->addr.sin_addr); +} + +/** + * pkt_getport() + * gibt den Port des Pakets als short zurueck + * + * @param struct net_pkt *pkt + * @return portnr + */ +unsigned short pkt_getport(struct net_pkt *pkt) { + return ntohs(pkt->addr.sin_port); +} diff --git a/src/scanner.c b/src/scanner.c index 98143a0..f6d48b7 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -39,7 +39,7 @@ static int scan_sock; /** * _pkt_queue() * packt ein paket in die sender queue - * @param struct net_pkt *pkt + * @param struct net_pkt *pkt */ void pkt_queue(struct net_pkt *pkt) { list_add_tail(&pkt->list, &send_queue); @@ -112,7 +112,7 @@ void scan_receive(void) { * initialisiert den socket fuer den server scan * @return false on error * - * TODO: src ip/port als parameter (config-file?) + * TODO: src ip als parameter (config-file?) */ int scan_init() { struct sockaddr_in dst; diff --git a/src/serverlist.c b/src/serverlist.c index 89f384f..d723948 100644 --- a/src/serverlist.c +++ b/src/serverlist.c @@ -62,13 +62,13 @@ 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(u_int16_t gameid, u_int32_t ip, u_int16_t port1, u_int16_t port2) { struct game_server server, *nserver; server.gameid = gameid; - server.ip = ip->s_addr; - server.port1 = ntohs(port1); - server.port2 = ntohs(port2); + server.ip = ip; + server.port1 = port1; + server.port2 = port2; pthread_mutex_lock(&server_list_lock); @@ -117,6 +117,7 @@ void server_collector(void) { client_pkt_add(server); } pthread_mutex_unlock(&server_list_lock); + client_pkt_commit(); } }