Version 0.60

- added receive-queue
- changed plugin_helper api from void* to uint offsets
- gamespy1 multi-packet response support
- q3engine plugin rewrite
- added halflife plugin
This commit is contained in:
Olaf Rempel 2006-02-02 16:47:20 +01:00
parent 861d41be08
commit 90d33bffbf
29 changed files with 881 additions and 269 deletions

View File

@ -1,5 +1,12 @@
* Sun 15 May 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.60
- added receive-queue
- changed plugin_helper api from void* to uint offsets
- gamespy1 multi-packet response support
- q3engine plugin rewrite
- added halflife plugin
* Tue 19 Apr 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.53 * Tue 19 Apr 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.53
- code cleanup (mostly doxygen tags) - code cleanup
- added doxygen file - added doxygen file
* Thu 31 Mar 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.52 * Thu 31 Mar 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.52

View File

@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
SUBDIRS = src plugins tools SUBDIRS = src plugins tools
EXTRA_DIST = TODO autogen.sh hlswmaster.conf contrib EXTRA_DIST = TODO autogen.sh hlswmaster.conf doc

View File

@ -174,7 +174,7 @@ sysconfdir = @sysconfdir@
target_alias = @target_alias@ target_alias = @target_alias@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
SUBDIRS = src plugins tools SUBDIRS = src plugins tools
EXTRA_DIST = TODO autogen.sh hlswmaster.conf contrib EXTRA_DIST = TODO autogen.sh hlswmaster.conf doc
all: config.h all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive $(MAKE) $(AM_MAKEFLAGS) all-recursive

3
TODO
View File

@ -5,13 +5,11 @@
- auf mehreren/allen interfaces gleichzeitig scannen - auf mehreren/allen interfaces gleichzeitig scannen
geht das ueberhaupt? ohne root rechte? geht das ueberhaupt? ohne root rechte?
- threads ueberwachen - threads ueberwachen
- threadpool fuer client-thread?
- statistiken? webserver? gamespy-export? - statistiken? webserver? gamespy-export?
- Makefile: stripping binarys? - Makefile: stripping binarys?
und natuerlich: und natuerlich:
- weitere spiele finden: - weitere spiele finden:
Halflife
Quake 1 Quake 1
Command & Conquer Renegade Command & Conquer Renegade
Medal of Honor: Allied Assault Medal of Honor: Allied Assault
@ -26,7 +24,6 @@ und natuerlich:
Tribes 2 Tribes 2
Savage: The Battle for Newerth Savage: The Battle for Newerth
Pain Killer Pain Killer
Halflife 2
Tribes Vengeance Tribes Vengeance
- vorhandene parser debuggen & verbessern - vorhandene parser debuggen & verbessern

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.59 for hlswmaster 0.53. # Generated by GNU Autoconf 2.59 for hlswmaster 0.60.
# #
# Report bugs to <Olaf Rempel <razzor@kopf-tisch.de>>. # Report bugs to <Olaf Rempel <razzor@kopf-tisch.de>>.
# #
@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='hlswmaster' PACKAGE_NAME='hlswmaster'
PACKAGE_TARNAME='hlswmaster' PACKAGE_TARNAME='hlswmaster'
PACKAGE_VERSION='0.53' PACKAGE_VERSION='0.60'
PACKAGE_STRING='hlswmaster 0.53' PACKAGE_STRING='hlswmaster 0.60'
PACKAGE_BUGREPORT='Olaf Rempel <razzor@kopf-tisch.de>' PACKAGE_BUGREPORT='Olaf Rempel <razzor@kopf-tisch.de>'
# Factoring default headers for most tests. # Factoring default headers for most tests.
@ -953,7 +953,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures hlswmaster 0.53 to adapt to many kinds of systems. \`configure' configures hlswmaster 0.60 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1019,7 +1019,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of hlswmaster 0.53:";; short | recursive ) echo "Configuration of hlswmaster 0.60:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1160,7 +1160,7 @@ fi
test -n "$ac_init_help" && exit 0 test -n "$ac_init_help" && exit 0
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
hlswmaster configure 0.53 hlswmaster configure 0.60
generated by GNU Autoconf 2.59 generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc. Copyright (C) 2003 Free Software Foundation, Inc.
@ -1174,7 +1174,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by hlswmaster $as_me 0.53, which was It was created by hlswmaster $as_me 0.60, which was
generated by GNU Autoconf 2.59. Invocation command line was generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@ $ $0 $@
@ -1818,7 +1818,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE=hlswmaster PACKAGE=hlswmaster
VERSION=0.53 VERSION=0.60
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -21419,7 +21419,7 @@ _ASBOX
} >&5 } >&5
cat >&5 <<_CSEOF cat >&5 <<_CSEOF
This file was extended by hlswmaster $as_me 0.53, which was This file was extended by hlswmaster $as_me 0.60, which was
generated by GNU Autoconf 2.59. Invocation command line was generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -21482,7 +21482,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
hlswmaster config.status 0.53 hlswmaster config.status 0.60
configured by $0, generated by GNU Autoconf 2.59, configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -1,8 +1,8 @@
dnl projekname, version, bugsto dnl projekname, version, bugsto
AC_INIT(hlswmaster, 0.53, [Olaf Rempel <razzor@kopf-tisch.de>]) AC_INIT(hlswmaster, 0.60, [Olaf Rempel <razzor@kopf-tisch.de>])
dnl same for automake dnl same for automake
AM_INIT_AUTOMAKE(hlswmaster, 0.53) AM_INIT_AUTOMAKE(hlswmaster, 0.60)
dnl do not rebuild configure dnl do not rebuild configure
AM_MAINTAINER_MODE AM_MAINTAINER_MODE

View File

@ -5,7 +5,7 @@
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
PROJECT_NAME = hlswmaster PROJECT_NAME = hlswmaster
PROJECT_NUMBER = 0.53 PROJECT_NUMBER = 0.53
OUTPUT_DIRECTORY = ../doc OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO USE_WINDOWS_ENCODING = NO

View File

@ -10,7 +10,7 @@ scan_interval 30
serverlist_interval 5 serverlist_interval 5
# server timeout after X seconds # server timeout after X seconds
serverlist_timeout 30 serverlist_timeout 60
# plugin data timeout every X seconds # plugin data timeout every X seconds
plugin_timeout 30 plugin_timeout 30
@ -19,7 +19,8 @@ plugin_timeout 30
master_ip 0.0.0.0 master_ip 0.0.0.0
# load these plugins # load these plugins
plugin plugins/.libs/hlswproxy.so #plugin plugins/.libs/hlswproxy.so
plugin plugins/.libs/halflife.so
plugin plugins/.libs/q3engine.so plugin plugins/.libs/q3engine.so
plugin plugins/.libs/quake2.so plugin plugins/.libs/quake2.so
plugin plugins/.libs/gamespy1.so plugin plugins/.libs/gamespy1.so
@ -30,6 +31,12 @@ plugin plugins/.libs/doom3.so
logfile hlswmaster.log logfile hlswmaster.log
[hlswproxy] [hlswproxy]
# ask these hlswmasters
scan_ip 10.10.0.1 scan_ip 10.10.0.1
scan_ip 10.10.0.2 scan_ip 10.10.0.2
[halflife]
# allow these nets
valid_net 10.10.0.0/16
valid_net 172.16.0.0/16

View File

@ -2,13 +2,13 @@
#define _LIST_H #define _LIST_H
/* /*
* stolen from linux kernel (2.6.11) * stolen from linux kernel 2.6.11 (http://kernel.org/)
* linux/include/linux/stddef.h (offsetoff) * linux/include/linux/stddef.h (offsetoff)
* linux/include/linux/kernel.h (container_of) * linux/include/linux/kernel.h (container_of)
* linux/include/linux/list.h (*list*) * linux/include/linux/list.h (*list*)
* linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND) * linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND)
* *
* modified by Olaf Rempel * modified by Olaf Rempel <razzor@kopf-tisch.de>
*/ */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

View File

@ -5,6 +5,15 @@
#include "configfile.h" #include "configfile.h"
#include "list.h" #include "list.h"
// paket nicht akzeptiert, free() muss noch aufgerufen werden
#define PARSE_REJECT 0
// paket akzeptiert, free() muss noch aufgerufen werden
#define PARSE_ACCEPT 1
// paket akzeptiert, free() wurde schon, oder darf noch aufgerufen werden
#define PARSE_ACCEPT_FREED 2
struct hlswmaster_plugin { struct hlswmaster_plugin {
struct list_head list; struct list_head list;

View File

@ -18,12 +18,16 @@ 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_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_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 pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size);
extern struct net_pkt * pkt_merge(struct net_pkt *pkt1, struct net_pkt *pkt2);
extern int server_add_pkt(unsigned int gameid, struct net_pkt *pkt); extern int server_add_pkt(unsigned int gameid, struct net_pkt *pkt);
extern char * pkt_ntoa(struct net_pkt *pkt); extern char * pkt_ntoa(struct net_pkt *pkt);
extern unsigned short pkt_getport(struct net_pkt *pkt); extern unsigned short pkt_getport(struct net_pkt *pkt);
extern int pkt_atoi(struct net_pkt *pkt, void *p); extern int pkt_sameaddr(struct net_pkt *pkt1, struct net_pkt *pkt2);
extern int pkt_parse_int(struct net_pkt *pkt, unsigned int offset, int *val);
extern int pkt_parse_ip(struct net_pkt *pkt, int offset, struct in_addr *ip);
extern char * pkt_print(struct net_pkt *pkt);
#endif /* _PLUGIN_HELPER_H */ #endif /* _PLUGIN_HELPER_H */

View File

@ -4,7 +4,7 @@ EXTRA_DIST = skel.c
INCLUDES = -I../include INCLUDES = -I../include
pkgdata_LTLIBRARIES = doom3.la gamespy1.la gamespy2.la hlswproxy.la q3engine.la quake2.la pkgdata_LTLIBRARIES = doom3.la gamespy1.la gamespy2.la halflife.la hlswproxy.la q3engine.la quake2.la
doom3_la_SOURCES = doom3.c doom3_la_SOURCES = doom3.c
doom3_la_LDFLAGS = -module -avoid-version doom3_la_LDFLAGS = -module -avoid-version
@ -15,6 +15,9 @@ gamespy1_la_LDFLAGS = -module -avoid-version
gamespy2_la_SOURCES = gamespy2.c gamespy2_la_SOURCES = gamespy2.c
gamespy2_la_LDFLAGS = -module -avoid-version gamespy2_la_LDFLAGS = -module -avoid-version
halflife_la_SOURCES = halflife.c
halflife_la_LDFLAGS = -module -avoid-version
hlswproxy_la_SOURCES = hlswproxy.c hlswproxy_la_SOURCES = hlswproxy.c
hlswproxy_la_LDFLAGS = -module -avoid-version hlswproxy_la_LDFLAGS = -module -avoid-version

View File

@ -14,7 +14,7 @@
@SET_MAKE@ @SET_MAKE@
SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) $(gamespy2_la_SOURCES) $(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) $(quake2_la_SOURCES) SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) $(gamespy2_la_SOURCES) $(halflife_la_SOURCES) $(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) $(quake2_la_SOURCES)
srcdir = @srcdir@ srcdir = @srcdir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
@ -65,6 +65,9 @@ gamespy1_la_OBJECTS = $(am_gamespy1_la_OBJECTS)
gamespy2_la_LIBADD = gamespy2_la_LIBADD =
am_gamespy2_la_OBJECTS = gamespy2.lo am_gamespy2_la_OBJECTS = gamespy2.lo
gamespy2_la_OBJECTS = $(am_gamespy2_la_OBJECTS) gamespy2_la_OBJECTS = $(am_gamespy2_la_OBJECTS)
halflife_la_LIBADD =
am_halflife_la_OBJECTS = halflife.lo
halflife_la_OBJECTS = $(am_halflife_la_OBJECTS)
hlswproxy_la_LIBADD = hlswproxy_la_LIBADD =
am_hlswproxy_la_OBJECTS = hlswproxy.lo am_hlswproxy_la_OBJECTS = hlswproxy.lo
hlswproxy_la_OBJECTS = $(am_hlswproxy_la_OBJECTS) hlswproxy_la_OBJECTS = $(am_hlswproxy_la_OBJECTS)
@ -86,11 +89,13 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@ $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \ SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \
$(gamespy2_la_SOURCES) $(hlswproxy_la_SOURCES) \ $(gamespy2_la_SOURCES) $(halflife_la_SOURCES) \
$(q3engine_la_SOURCES) $(quake2_la_SOURCES) $(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) \
$(quake2_la_SOURCES)
DIST_SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \ DIST_SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \
$(gamespy2_la_SOURCES) $(hlswproxy_la_SOURCES) \ $(gamespy2_la_SOURCES) $(halflife_la_SOURCES) \
$(q3engine_la_SOURCES) $(quake2_la_SOURCES) $(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) \
$(quake2_la_SOURCES)
ETAGS = etags ETAGS = etags
CTAGS = ctags CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -196,13 +201,15 @@ target_alias = @target_alias@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = skel.c EXTRA_DIST = skel.c
INCLUDES = -I../include INCLUDES = -I../include
pkgdata_LTLIBRARIES = doom3.la gamespy1.la gamespy2.la hlswproxy.la q3engine.la quake2.la pkgdata_LTLIBRARIES = doom3.la gamespy1.la gamespy2.la halflife.la hlswproxy.la q3engine.la quake2.la
doom3_la_SOURCES = doom3.c doom3_la_SOURCES = doom3.c
doom3_la_LDFLAGS = -module -avoid-version doom3_la_LDFLAGS = -module -avoid-version
gamespy1_la_SOURCES = gamespy1.c gamespy1_la_SOURCES = gamespy1.c
gamespy1_la_LDFLAGS = -module -avoid-version gamespy1_la_LDFLAGS = -module -avoid-version
gamespy2_la_SOURCES = gamespy2.c gamespy2_la_SOURCES = gamespy2.c
gamespy2_la_LDFLAGS = -module -avoid-version gamespy2_la_LDFLAGS = -module -avoid-version
halflife_la_SOURCES = halflife.c
halflife_la_LDFLAGS = -module -avoid-version
hlswproxy_la_SOURCES = hlswproxy.c hlswproxy_la_SOURCES = hlswproxy.c
hlswproxy_la_LDFLAGS = -module -avoid-version hlswproxy_la_LDFLAGS = -module -avoid-version
q3engine_la_SOURCES = q3engine.c q3engine_la_SOURCES = q3engine.c
@ -275,6 +282,8 @@ gamespy1.la: $(gamespy1_la_OBJECTS) $(gamespy1_la_DEPENDENCIES)
$(LINK) -rpath $(pkgdatadir) $(gamespy1_la_LDFLAGS) $(gamespy1_la_OBJECTS) $(gamespy1_la_LIBADD) $(LIBS) $(LINK) -rpath $(pkgdatadir) $(gamespy1_la_LDFLAGS) $(gamespy1_la_OBJECTS) $(gamespy1_la_LIBADD) $(LIBS)
gamespy2.la: $(gamespy2_la_OBJECTS) $(gamespy2_la_DEPENDENCIES) gamespy2.la: $(gamespy2_la_OBJECTS) $(gamespy2_la_DEPENDENCIES)
$(LINK) -rpath $(pkgdatadir) $(gamespy2_la_LDFLAGS) $(gamespy2_la_OBJECTS) $(gamespy2_la_LIBADD) $(LIBS) $(LINK) -rpath $(pkgdatadir) $(gamespy2_la_LDFLAGS) $(gamespy2_la_OBJECTS) $(gamespy2_la_LIBADD) $(LIBS)
halflife.la: $(halflife_la_OBJECTS) $(halflife_la_DEPENDENCIES)
$(LINK) -rpath $(pkgdatadir) $(halflife_la_LDFLAGS) $(halflife_la_OBJECTS) $(halflife_la_LIBADD) $(LIBS)
hlswproxy.la: $(hlswproxy_la_OBJECTS) $(hlswproxy_la_DEPENDENCIES) hlswproxy.la: $(hlswproxy_la_OBJECTS) $(hlswproxy_la_DEPENDENCIES)
$(LINK) -rpath $(pkgdatadir) $(hlswproxy_la_LDFLAGS) $(hlswproxy_la_OBJECTS) $(hlswproxy_la_LIBADD) $(LIBS) $(LINK) -rpath $(pkgdatadir) $(hlswproxy_la_LDFLAGS) $(hlswproxy_la_OBJECTS) $(hlswproxy_la_LIBADD) $(LIBS)
q3engine.la: $(q3engine_la_OBJECTS) $(q3engine_la_DEPENDENCIES) q3engine.la: $(q3engine_la_OBJECTS) $(q3engine_la_DEPENDENCIES)

View File

@ -28,22 +28,24 @@ static struct scan_ports port_arr[] = {
static char scanmsg[] = "\xff\xffgetInfo"; static char scanmsg[] = "\xff\xffgetInfo";
static char replymsg[] = "\xff\xffinfoResponse"; static char replymsg[] = "\xff\xffinfoResponse";
static int scan(void) { static int scan(void)
{
pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg)); pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt)
{
int gameid; int gameid;
if (!(gameid = pkt_check_portarr(pkt, port_arr))) if (!(gameid = pkt_check_portarr(pkt, port_arr)))
return 0; return PARSE_REJECT;
if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg))) if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg)))
return 0; return PARSE_REJECT;
server_add_pkt(gameid, pkt); server_add_pkt(gameid, pkt);
return 1; return PARSE_ACCEPT;
} }
struct hlswmaster_plugin plugin = { struct hlswmaster_plugin plugin = {

View File

@ -29,89 +29,227 @@ static struct scan_ports port_arr[] = {
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static char scanmsg[] = "\\status\\"; struct gs1_part {
static char ut_reply[] = "\\gamename\\ut\\"; struct list_head list;
static char ut2k3_reply[] = "\\gamename\\ut2\\"; unsigned long timeout;
static char ut2k4_reply[] = "\\gamename\\ut2004\\"; unsigned int queryid;
static char bf1942_reply[] = "\\gamename\\bfield1942\\"; unsigned int subid;
static char bfv_reply[] = "\\game_id\\bfvietnam\\"; struct net_pkt *pkt;
static char avp2_reply[] = "\\gamename\\avp2\\"; };
static char igi2_reply[] = "\\gamename\\projectigi2r\\";
static char hostport_search[] = "\\hostport\\";
static int scan(void) { static LIST_HEAD(gs1_partlist);
static char scanmsg[] = "\\status\\";
static char search_queryid[] = "\\queryid\\";
static char search_final[] = "\\final\\";
static char search_hostport[] = "\\hostport\\";
static char search_gamename[] = "\\gamename\\";
static char search_gameid[] = "\\game_id\\";
static char reply_ut[] = "ut\\";
static char reply_ut2k3[] = "ut2\\";
static char reply_ut2k4[] = "ut2004\\";
static char reply_bf1942[] = "bfield1942\\";
static char reply_bfv[] = "bfvietnam\\";
static char reply_poe[] = "poe\\";
static char reply_opk[] = "opk\\";
static char reply_avp2[] = "avp2\\";
static char reply_igi2[] = "projectigi2r\\";
static int scan(void)
{
pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg)); pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static struct net_pkt * gs1_pkt_merge(struct net_pkt *pkt, unsigned int queryid, unsigned int subid)
int gameid, port; {
void *p; struct net_pkt *retpkt = NULL;
struct gs1_part *part, *tmp;
unsigned int i = 1, found = 0, notfound = 0;
// wenn paket non-final ist, in liste speichern
// NULL zurueckgeben
if (pkt_memmem(pkt, 0, search_final, strlen(search_final)) == -1) {
part = malloc(sizeof(struct gs1_part));
part->timeout = time(NULL);
part->queryid = queryid;
part->subid = subid;
part->pkt = pkt;
if (!(gameid = pkt_check_portarr(pkt, port_arr))) // in liste packen
return 0; list_add_tail(&part->list, &gs1_partlist);
return NULL;
}
// wenn paket final ist, dann mit evtl. non-final paketen mergen
// komplettes Paket zurueckgeben
while (i < subid && notfound <= subid) {
found = 0;
list_for_each_entry_safe(part, tmp, &gs1_partlist, list) {
if (pkt_sameaddr(part->pkt, pkt) && (part->queryid == queryid) && part->subid == i) {
if (retpkt != NULL) {
struct net_pkt *retpkt2 = retpkt;
retpkt = pkt_merge(retpkt, part->pkt);
free(retpkt2);
free(part->pkt);
} else {
retpkt = part->pkt;
}
list_del(&part->list);
free(part);
found = 1;
i++;
}
}
if (found == 0)
notfound++;
}
/* merge error, eat last paket, cleanup */
if (i != subid || notfound > subid) {
log_print("gs1: merging error!");
free(pkt);
return NULL;
}
return (retpkt != NULL) ? pkt_merge(retpkt, pkt) : pkt;
}
static int parse_real(struct net_pkt *pkt, int gameid)
{
int port, offset, pos1, pos2;
pos1 = pkt_memmem(pkt, 0, search_gamename, strlen(search_gamename));
pos1 += strlen(search_gamename);
pos2 = pkt_memmem(pkt, 0, search_gameid, strlen(search_gameid));
pos2 += strlen(search_gameid);
switch (gameid) { switch (gameid) {
case 5:/* unreal tournament 2k3 */ case 5:/* unreal tournament */
if (pkt_memmem(pkt, 0, ut_reply, strlen(ut_reply))) if (!pkt_memcmp(pkt, pos1, reply_ut, strlen(reply_ut)))
gameid = 5; gameid = 5;
/* unreal tournament 2k3 */ /* unreal tournament 2k3 */
else if (pkt_memmem(pkt, 0, ut2k3_reply, strlen(ut2k3_reply))) else if (!pkt_memcmp(pkt, pos1, reply_ut2k3, strlen(reply_ut2k4)))
gameid = 14; gameid = 14;
/* unreal tournament 2k4 */ /* unreal tournament 2k4 */
else if (pkt_memmem(pkt, 0, ut2k4_reply, strlen(ut2k4_reply))) else if (!pkt_memcmp(pkt, pos1, reply_ut2k4, strlen(reply_ut2k4)))
gameid = 33; gameid = 33;
else else
return 0; return PARSE_REJECT;
break; break;
case 16:/* battlefield 1942 */ case 16:/* battlefield 1942 */
if (!pkt_memmem(pkt, 0, bf1942_reply, strlen(bf1942_reply))) case 35:/* battlefield vietnam */
return 0; if (!pkt_memcmp(pkt, pos1, reply_bf1942, strlen(reply_bf1942)))
gameid = 16;
else if (!pkt_memcmp(pkt, pos2, reply_bfv, strlen(reply_bfv)))
gameid = 35;
else if (!pkt_memcmp(pkt, pos2, reply_poe, strlen(reply_poe)))
gameid = 35;
else if (!pkt_memcmp(pkt, pos2, reply_opk, strlen(reply_opk)))
gameid = 35;
else
return PARSE_REJECT;
break; break;
case 17:/* alien vs. predator 2 */ case 17:/* alien vs. predator 2 */
if (!pkt_memmem(pkt, 0, avp2_reply, strlen(avp2_reply))) if (!pkt_memcmp(pkt, pos1, reply_avp2, strlen(reply_avp2)))
return 0; gameid = 17;
else
return PARSE_REJECT;
break; break;
case 19:/* project igi2 covert strike */ case 19:/* project igi2 covert strike */
if (!pkt_memmem(pkt, 0, igi2_reply, strlen(igi2_reply))) if (!pkt_memcmp(pkt, pos1, reply_igi2, strlen(reply_igi2)))
return 0; gameid = 19;
else
return PARSE_REJECT;
break; break;
case 35:/* battlefield vietnam */
if (!pkt_memmem(pkt, 0, bfv_reply, strlen(bfv_reply)))
return 0;
break;
default: default:
return 0; return PARSE_REJECT;
} }
/* hostport angabe suchen */ /* hostport angabe suchen */
p = pkt_memmem(pkt, 0, hostport_search, strlen(hostport_search)); offset = pkt_memmem(pkt, 0, search_hostport, strlen(search_hostport));
if (p) { if (offset != -1)
port = pkt_atoi(pkt, p + strlen(hostport_search)); pkt_parse_int(pkt, offset + strlen(search_hostport), &port);
}
/* wenn ein hostport angegeben wurde, und das nicht der src port ist /*
** beide ports in die serverliste uebernehmen * wenn ein hostport angegeben wurde, und das nicht der src port ist
*/ * beide ports in die serverliste uebernehmen
if (p && port != ntohs(pkt->addr.sin_port)) { */
if ((offset != -1) && (port != ntohs(pkt->addr.sin_port))) {
server_add(gameid, pkt->addr.sin_addr.s_addr, port, ntohs(pkt->addr.sin_port)); server_add(gameid, pkt->addr.sin_addr.s_addr, port, ntohs(pkt->addr.sin_port));
} else { } else {
server_add_pkt(gameid, pkt); server_add_pkt(gameid, pkt);
} }
return PARSE_ACCEPT;
}
static int parse(struct net_pkt *pkt)
{
struct net_pkt *pkt2;
int gameid, pos, offset, queryid, subid, retval;
return 1; if (!(gameid = pkt_check_portarr(pkt, port_arr)))
return PARSE_REJECT;
/* eat ut connection attemps */
if (gameid == 5 && pkt->size <= 6)
return PARSE_ACCEPT;
if ((offset = pkt_memmem(pkt, 0, search_queryid, strlen(search_queryid))) == -1)
return PARSE_REJECT;
pos = offset + strlen(search_queryid);
if ((offset = pkt_parse_int(pkt, pos, &queryid)) == 0)
return PARSE_REJECT;
pos += offset +1;
if ((offset = pkt_parse_int(pkt, pos, &subid)) == 0)
return PARSE_REJECT;
/* multipaket antworten zusammenfassen
* wenn paket non-final, dann einfach annehmen
*/
if ((pkt2 = gs1_pkt_merge(pkt, queryid, subid)) == NULL)
return PARSE_ACCEPT_FREED;
retval = parse_real(pkt2, gameid);
/* free merged packet */
if (pkt != pkt2)
free(pkt2);
return retval;
}
static int gc(int timeout) {
struct gs1_part *part, *tmp;
unsigned long now = time(NULL);
list_for_each_entry_safe(part, tmp, &gs1_partlist, list) {
if (part->timeout + timeout < now) {
log_print("gs1: removing dead fragment");
list_del(&part->list);
free(part->pkt);
free(part);
}
}
} }
struct hlswmaster_plugin plugin = { struct hlswmaster_plugin plugin = {
.name = "gamespy1", .name = "gamespy1",
.scan = &scan, .scan = &scan,
.parse = &parse, .parse = &parse,
.gc = &gc,
}; };

View File

@ -22,28 +22,31 @@
static struct scan_ports port_arr[] = { static struct scan_ports port_arr[] = {
{ 2302, 2302, 30 }, /* halo(30) */ { 2302, 2302, 30 }, /* halo(30) */
{ 3455, 3455, 37 }, /* painkiller(34) */
{ 0,0,0 } { 0,0,0 }
}; };
static char scanmsg[] = { 0xFE, 0xFD, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00 }; static char scanmsg[] = { 0xFE, 0xFD, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00 };
static char replymsg[] = { 0x00, 0xDE, 0xAD, 0xBE, 0xEF }; static char replymsg[] = { 0x00, 0xDE, 0xAD, 0xBE, 0xEF };
static int scan(void) { static int scan(void)
{
pkt_send_portarr(NULL, port_arr, scanmsg, sizeof(scanmsg)); pkt_send_portarr(NULL, port_arr, scanmsg, sizeof(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt)
{
int gameid; int gameid;
if (!(gameid = pkt_check_portarr(pkt, port_arr))) if (!(gameid = pkt_check_portarr(pkt, port_arr)))
return 0; return PARSE_REJECT;
if (pkt_memcmp(pkt, 0, replymsg, sizeof(replymsg))) if (pkt_memcmp(pkt, 0, replymsg, sizeof(replymsg)))
return 0; return PARSE_REJECT;
server_add_pkt(gameid, pkt); server_add_pkt(gameid, pkt);
return 1; return PARSE_ACCEPT;
} }
struct hlswmaster_plugin plugin = { struct hlswmaster_plugin plugin = {

180
plugins/halflife.c Normal file
View File

@ -0,0 +1,180 @@
/***************************************************************************
* 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 <string.h>
#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, &section->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, &section->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,
};

View File

@ -26,7 +26,7 @@
#include "plugin_helper.h" #include "plugin_helper.h"
struct _entry { struct hlsw_entry {
u_int16_t gameid; u_int16_t gameid;
u_int32_t ip; u_int32_t ip;
u_int16_t port1; u_int16_t port1;
@ -38,17 +38,19 @@ static int ip_arr_size = 0;
static char scanmsg[] = "\xff\xff\xff\xffHLSWLANSEARCH"; static char scanmsg[] = "\xff\xff\xff\xffHLSWLANSEARCH";
static int scan(void) { static int scan(void)
{
int i; int i;
for (i = 0; i < ip_arr_size; i++) for (i = 0; i < ip_arr_size; i++)
pkt_send(&ip_arr[i], 7140, scanmsg, sizeof(scanmsg)); pkt_send(&ip_arr[i], 7140, scanmsg, sizeof(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt)
struct _entry *server; {
struct hlsw_entry *server;
if (pkt_getport(pkt) != 7140) if (pkt_getport(pkt) != 7140)
return 0; return PARSE_REJECT;
server = (void *)pkt->buf + sizeof(scanmsg); server = (void *)pkt->buf + sizeof(scanmsg);
@ -56,10 +58,12 @@ static int parse(struct net_pkt *pkt) {
server_add(server->gameid, server->ip, server->port1, server->port2); server_add(server->gameid, server->ip, server->port1, server->port2);
server++; server++;
} }
return 1;
return PARSE_ACCEPT;
} }
static int init(struct conf_section *section) { static int init(struct conf_section *section)
{
struct conf_tupel *tupel; struct conf_tupel *tupel;
int i = 0; int i = 0;
list_for_each_entry(tupel, &section->tupel, list) list_for_each_entry(tupel, &section->tupel, list)
@ -81,11 +85,11 @@ static int init(struct conf_section *section) {
} }
} }
ip_arr_size = i; ip_arr_size = i;
log_print(" added %d master server(s)", i);
return 1; return 1;
} }
static int fini() { static int fini()
{
if (ip_arr_size > 0 && ip_arr) if (ip_arr_size > 0 && ip_arr)
free(ip_arr); free(ip_arr);
} }

View File

@ -22,82 +22,79 @@
static struct scan_ports port_arr[] = { static struct scan_ports port_arr[] = {
{ 27960, 27969, 6 }, /* q3(6), ef(7), et25), rtcw(8) */ { 27960, 27969, 6 }, /* q3(6), ef(7), et25), rtcw(8) */
{ 28070, 28070, 12 }, /* jk2(12) TODO: UNTESTED */ { 28070, 28070, 12 }, /* jk2(12) */
{ 28960, 28963, 31 }, /* cod(31), cod:uo(42) */ { 28960, 28963, 31 }, /* cod(31), cod:uo(42) */
{ 29070, 29070, 27 }, /* jk3(27) TODO: UNTESTED */ { 29070, 29070, 27 }, /* jk3(27) */
{ 0,0,0 } { 0,0,0 }
}; };
static char scanmsg[] = "\xff\xff\xff\xffgetStatus"; static char scanmsg[] = "\xff\xff\xff\xffgetStatus";
static char replymsg[] = "\xff\xff\xff\xffstatusResponse"; static char replymsg[] = "\xff\xff\xff\xffstatusResponse";
static char search_version[] = "\\version\\";
static char search_gamename[] = "\\gamename\\";
static char reply_q3[] = "Q3 ";
static char reply_ef[] = "ST:V HM ";
static char reply_rtcw[] = "Wolf ";
static char reply_et[] = "ET";
static char reply_jk2[] = "JK2MP";
static char reply_jk3[] = "JAmp";
static char reply_cod[] = "Call of Duty\\";
static char reply_coduo[] = "CoD:United Offensive\\";
static char q3_reply[] = "\\version\\Q3 "; static int scan(void)
static char ef_reply[] = "\\version\\ST:V HM "; {
static char rtcw_reply[] = "\\version\\Wolf ";
static char et_reply[] = "\\version\\ET ";
static char jk2_reply[] = "\\version\\JK2MP ";
static char jk3_reply[] = "\\version\\JAmp ";
static char cod_reply[] = "\\gamename\\Call of Duty\\";
static char coduo_reply[] = "\\gamename\\CoD:United Offensive\\";
static int scan(void) {
pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg)); pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt)
int gameid; {
int gameid = 0, pos1, pos2;
if (!(gameid = pkt_check_portarr(pkt, port_arr)))
return 0;
if (!pkt_check_portarr(pkt, port_arr))
return PARSE_REJECT;
if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg))) if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg)))
return 0; return PARSE_REJECT;
switch (gameid) { pos1 = pkt_memmem(pkt, 0, search_version, strlen(search_version));
case 6: /* q3, ef, et, rtcw */ pos2 = pkt_memmem(pkt, 0, search_gamename, strlen(search_gamename));
if (pkt_memmem(pkt, 0, q3_reply, strlen(q3_reply))) {
if (pos1 != -1) {
pos1 += strlen(search_version);
if (!pkt_memcmp(pkt, pos1, reply_q3, strlen(reply_q3)))
gameid = 6; gameid = 6;
} else if (pkt_memmem(pkt, 0, ef_reply, strlen(ef_reply))) { else if (!pkt_memcmp(pkt, pos1, reply_ef, strlen(reply_ef)))
gameid = 7; gameid = 7;
} else if (pkt_memmem(pkt, 0, rtcw_reply, strlen(rtcw_reply))) { else if (!pkt_memcmp(pkt, pos1, reply_rtcw, strlen(reply_rtcw)))
gameid = 8; gameid = 8;
} else if (pkt_memmem(pkt, 0, et_reply, strlen(et_reply))) { else if (!pkt_memcmp(pkt, pos1, reply_et, strlen(reply_et)))
gameid = 25; gameid = 25;
} else {
return 0;
}
break;
case 12: /* jedi knight 2 */ else if (!pkt_memcmp(pkt, pos1, reply_jk2, strlen(reply_jk2)))
if (!pkt_memmem(pkt, 0, jk2_reply, strlen(jk2_reply))) gameid = 12;
return 0;
break;
case 27: /* jedi knight 3 */
if (!pkt_memmem(pkt, 0, jk3_reply, strlen(jk3_reply)))
return 0;
break;
case 31: /* cod, cod:uo */
if (pkt_memmem(pkt, 0, cod_reply, strlen(cod_reply))) {
gameid = 31;
} else if (pkt_memmem(pkt, 0, coduo_reply, strlen(coduo_reply))) { else if (!pkt_memcmp(pkt, pos1, reply_jk3, strlen(reply_jk3)))
gameid = 42; gameid = 27;
} else {
return 0;
}
break;
} }
if (gameid == 0 && pos2 != -1) {
pos2 += strlen(search_gamename);
if (!pkt_memcmp(pkt, pos2, reply_cod, strlen(reply_cod)))
gameid = 31;
else if (!pkt_memcmp(pkt, pos2, reply_coduo, strlen(reply_coduo)))
gameid = 42;
}
if (gameid == 0)
return PARSE_REJECT;
server_add_pkt(gameid, pkt); server_add_pkt(gameid, pkt);
return 1; return PARSE_ACCEPT;
} }
struct hlswmaster_plugin plugin = { struct hlswmaster_plugin plugin = {

View File

@ -20,22 +20,24 @@
#include <string.h> #include <string.h>
#include "plugin_helper.h" #include "plugin_helper.h"
static char scanmsg[] = "\xff\xff\xff\xffinfo 34"; static char scanmsg[] = "\xff\xff\xff\xffinfo 34"; /* q2(3) */
static int scan(void) { static int scan(void)
{
pkt_send(NULL, 27910, scanmsg, strlen(scanmsg)); pkt_send(NULL, 27910, scanmsg, strlen(scanmsg));
return 1; return 1;
} }
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt)
{
if (pkt_getport(pkt) != 27910) if (pkt_getport(pkt) != 27910)
return 0; return PARSE_REJECT;
if (pkt_memcmp(pkt, 0, scanmsg, strlen(scanmsg))) if (pkt_memcmp(pkt, 0, scanmsg, strlen(scanmsg)))
return 0; return PARSE_REJECT;
server_add_pkt(3, pkt); server_add_pkt(3, pkt);
return 1; return PARSE_ACCEPT;
} }
struct hlswmaster_plugin plugin = { struct hlswmaster_plugin plugin = {

View File

@ -38,7 +38,7 @@ static int scan(void) {
struct in_addr tmp; struct in_addr tmp;
inet_aton("192.168.1.100", &tmp) inet_aton("192.168.1.100", &tmp)
pkt_send(&tmp, 8888, myscan, strlen(myscan)); pkt_send(&tmp, 8888, myscan, strlen(myscan));
/* an portrange(s) senden */ /* an portrange(s) senden */
struct scan_ports port_arr[] = { struct scan_ports port_arr[] = {
{ 27960, 27963, 0 }, /* von 27960-27963 scannen */ { 27960, 27963, 0 }, /* von 27960-27963 scannen */
@ -62,44 +62,48 @@ static int scan(void) {
static int parse(struct net_pkt *pkt) { static int parse(struct net_pkt *pkt) {
/* checken ob das paket vom richtigen port kommt: */ /* checken ob das paket vom richtigen port kommt: */
if (pkt_getport(pkt) != 27910) if (pkt_getport(pkt) != 27910)
return 0; return PARSE_REJECT;
/* bei einem port_arr checken ob es von einem der angefragten ports kommt */ /* bei einem port_arr checken ob es von einem der angefragten ports kommt */
int gameid; int gameid;
if (!(gameid = pkt_check_portarr(pkt, port_arr))) if (!(gameid = pkt_check_portarr(pkt, port_arr)))
return 0; return PARSE_REJECT;
/* gameid enthaelt nun den dritten wert einer passenden port_arr zeile */ /* gameid enthaelt nun den dritten wert einer passenden port_arr zeile */
/* paketinhalt checken (packet = "good morning dave\x00") */ /* paketinhalt checken (packet = "good morning dave\x00") */
char mycmp1[] = "good"; char mycmp1[] = "good";
if (pkt_memcmp(pkt, 0, mycmp1, strlen(mycmp1))) if (pkt_memcmp(pkt, 0, mycmp1, strlen(mycmp1)))
return 0; return PARSE_REJECT;
/* paketinhalt mit offset */ /* paketinhalt mit offset */
char mycmp2[] = "morning"; char mycmp2[] = "morning";
if (pkt_memcmp(pkt, 5, mycmp2, strlen(mycmp2))) if (pkt_memcmp(pkt, 5, mycmp2, strlen(mycmp2)))
return 0; return PARSE_REJECT;
/* suchen ob paketinhalt vorhanden ist (packet = "blablablablabla\hostport\7777\blablabla") */ /* suchen ob paketinhalt vorhanden ist (packet = "blablablablabla\hostport\7777\blablabla") */
char mymem[] = "\\hostport\\"; char mymem[] = "\\hostport\\";
void *p void *p
p = pkt_memmem(pkt, 0, mymem, strlen(mymem)); p = pkt_memmem(pkt, 0, mymem, strlen(mymem));
if (!p) if (p == -1)
return 0; return PARSE_REJECT;
/* ints aus paket parsen: */ /* ints aus paket parsen: */
p += strlen(mymem); int port2;
port2 = pkt_atoi(pkt, p);
if (pkt_parse_int(pkt, offset, &port2) == 0)
return PARSE_REJECT;
/* src ip des pakets */ /* src ip des pakets */
printf("server found: %s\n", pkt_ntoa(pkt)); printf("server found: %s\n", pkt_ntoa(pkt));
/* server zu interner liste hinzufuegen: (port1 = port, port2 = 0)*/ /* server zu interner liste hinzufuegen: (port1 = port, port2 = 0)*/
server_add_pkt(gameid, pkt); server_add_pkt(gameid, pkt);
/* server mit zwei ports zur liste hinzufuegen: */ /* server mit zwei ports zur liste hinzufuegen: */
server_add(gameid, pkt->addr.sin_addr.s_addr, port1, port2); server_add(gameid, pkt->addr.sin_addr.s_addr, port1, port2);
return PARSE_ACCEPT;
} }
/** /**

View File

@ -59,8 +59,9 @@ static pthread_mutex_t client_pkt_list_lock = PTHREAD_MUTEX_INITIALIZER;
* @param *unused * @param *unused
* @return true wenn das paket noch nicht voll ist * @return true wenn das paket noch nicht voll ist
*/ */
static inline int client_pkt_not_full(const struct client_pkt *cpkt, void *unused) { static inline int client_pkt_not_full(const struct client_pkt *cpkt, void *unused)
return (cpkt->size > (MAX_PKT_LEN - HLSW_ENTRY_LEN)); {
return (cpkt->size <= (MAX_PKT_LEN - HLSW_ENTRY_LEN));
} }
/** /**
@ -70,7 +71,8 @@ static inline int client_pkt_not_full(const struct client_pkt *cpkt, void *unuse
* @param *list liste die das neue paket aufnimmt * @param *list liste die das neue paket aufnimmt
* @return pointer auf ein neues paket oder NULL bei fehler * @return pointer auf ein neues paket oder NULL bei fehler
*/ */
static struct client_pkt * client_pkt_add_real(struct list_head *list) { static struct client_pkt * client_pkt_add_real(struct list_head *list)
{
struct client_pkt *cpkt; struct client_pkt *cpkt;
cpkt = malloc(sizeof(struct client_pkt) + MAX_PKT_LEN); cpkt = malloc(sizeof(struct client_pkt) + MAX_PKT_LEN);
@ -81,7 +83,7 @@ static struct client_pkt * client_pkt_add_real(struct list_head *list) {
memcpy(cpkt->buf, HLSW_HEADER, HLSW_HEADER_LEN); memcpy(cpkt->buf, HLSW_HEADER, HLSW_HEADER_LEN);
cpkt->size = HLSW_HEADER_LEN; cpkt->size = HLSW_HEADER_LEN;
/* am anfang eingliedern! */ /* am anfang eingliedern! (suche nach freien paket schneller) */
list_add(&cpkt->list, list); list_add(&cpkt->list, list);
} }
return cpkt; return cpkt;
@ -95,7 +97,8 @@ static struct client_pkt * client_pkt_add_real(struct list_head *list) {
* @param *server pointer den server * @param *server pointer den server
* @return false bei fehler * @return false bei fehler
*/ */
int client_pkt_add(struct game_server *server) { int client_pkt_add(struct game_server *server)
{
struct client_pkt *cpkt; struct client_pkt *cpkt;
/* sucht ein freies paket, oder erzeugt eins */ /* sucht ein freies paket, oder erzeugt eins */
@ -117,7 +120,8 @@ int client_pkt_add(struct game_server *server) {
* *
* @return true * @return true
*/ */
int client_pkt_commit() { int client_pkt_commit()
{
struct list_head old_list, *cpkt, *tmp; struct list_head old_list, *cpkt, *tmp;
/* wenn die liste leer ist, nur HLSW-header verschicken */ /* wenn die liste leer ist, nur HLSW-header verschicken */
@ -148,7 +152,8 @@ int client_pkt_commit() {
* client_handler() * client_handler()
* empfaengt und beantwortet die HLSW anfragen der clients * empfaengt und beantwortet die HLSW anfragen der clients
*/ */
void client_handler(void) { void client_handler(void)
{
struct client_pkt *cpkt; struct client_pkt *cpkt;
struct sockaddr_in dst; struct sockaddr_in dst;
int sock, i; int sock, i;

View File

@ -40,7 +40,8 @@ static LIST_HEAD(config_list);
* *
* @todo sectionname ist nicht eindeutig * @todo sectionname ist nicht eindeutig
*/ */
static struct conf_section * config_add_section(char *name) { static struct conf_section * config_add_section(char *name)
{
struct conf_section *section; struct conf_section *section;
if (!name) if (!name)
@ -66,7 +67,8 @@ static struct conf_section * config_add_section(char *name) {
* @param *parameter wert der option * @param *parameter wert der option
* @return false bei fehler * @return false bei fehler
*/ */
static int config_add_tupel(struct conf_section *section, char *option, char *parameter) { static int config_add_tupel(struct conf_section *section, char *option, char *parameter)
{
struct conf_tupel *tupel; struct conf_tupel *tupel;
if (!section || !option || !parameter) if (!section || !option || !parameter)
@ -88,7 +90,8 @@ static int config_add_tupel(struct conf_section *section, char *option, char *pa
* config_free() * config_free()
* entfernt die config_liste aus dem Speicher * entfernt die config_liste aus dem Speicher
*/ */
static void config_free() { static void config_free()
{
struct conf_section *section, *section_tmp; struct conf_section *section, *section_tmp;
struct conf_tupel *tupel, *tupel_tmp; struct conf_tupel *tupel, *tupel_tmp;
@ -111,7 +114,8 @@ static void config_free() {
* @param *config filename des configfiles * @param *config filename des configfiles
* @return false bei fehler * @return false bei fehler
*/ */
int config_parse(char *config) { int config_parse(char *config)
{
struct conf_section *section = NULL; struct conf_section *section = NULL;
FILE *fz; FILE *fz;
int i = 0, ret = 1; int i = 0, ret = 1;
@ -189,7 +193,8 @@ int config_parse(char *config) {
* @param *name name der section * @param *name name der section
* @return pointer auf die section, oder NULL bei fehler * @return pointer auf die section, oder NULL bei fehler
*/ */
struct conf_section * config_get_section(char *name) { struct conf_section * config_get_section(char *name)
{
struct conf_section *section; struct conf_section *section;
list_for_each_entry(section, &config_list, list) { list_for_each_entry(section, &config_list, list) {
@ -208,7 +213,8 @@ struct conf_section * config_get_section(char *name) {
* @param *option option name * @param *option option name
* @return pointer auf den parameter string oder NULL bei fehler * @return pointer auf den parameter string oder NULL bei fehler
*/ */
char * config_get_parameter(struct conf_section *section, char *option) { char * config_get_parameter(struct conf_section *section, char *option)
{
struct conf_tupel *tupel; struct conf_tupel *tupel;
list_for_each_entry(tupel, &section->tupel, list) { list_for_each_entry(tupel, &section->tupel, list) {
@ -227,7 +233,8 @@ char * config_get_parameter(struct conf_section *section, char *option) {
* @param *def default string * @param *def default string
* @return parameter string oder default string bei fehler * @return parameter string oder default string bei fehler
*/ */
char * config_get_string(char *section, char *option, char *def) { char * config_get_string(char *section, char *option, char *def)
{
struct conf_section *tmp; struct conf_section *tmp;
char *ret; char *ret;
@ -247,7 +254,8 @@ char * config_get_string(char *section, char *option, char *def) {
* @param *def default wert * @param *def default wert
* @return parameter wert oder default wert bei fehler * @return parameter wert oder default wert bei fehler
*/ */
int config_get_int(char *section, char *option, int def) { int config_get_int(char *section, char *option, int def)
{
char *ret; char *ret;
ret = config_get_string(section, option, NULL); ret = config_get_string(section, option, NULL);

View File

@ -37,9 +37,10 @@ static FILE *log_fd = NULL;
* *
* @todo code vereinfachen? * @todo code vereinfachen?
*/ */
void log_print(const char *fmt, ...) { void log_print(const char *fmt, ...)
{
va_list az; va_list az;
char buffer[256]; char *buffer = malloc(8192);
va_start(az, fmt); va_start(az, fmt);
vsprintf(buffer, fmt, az); vsprintf(buffer, fmt, az);
@ -69,13 +70,15 @@ void log_print(const char *fmt, ...) {
} }
} }
errno = 0; errno = 0;
free(buffer);
} }
/** /**
* log_close() * log_close()
* schliesst das logfile * schliesst das logfile
*/ */
static void log_close() { static void log_close()
{
fclose(log_fd); fclose(log_fd);
} }
@ -86,7 +89,8 @@ static void log_close() {
* @param logfile filename des logfiles * @param logfile filename des logfiles
* @return false bei fehler * @return false bei fehler
*/ */
int log_init(char *logfile) { int log_init(char *logfile)
{
if ((log_fd = fopen(logfile, "a" )) == NULL) { if ((log_fd = fopen(logfile, "a" )) == NULL) {
log_print("log_open('%s'): %s", logfile); log_print("log_open('%s'): %s", logfile);
return 0; return 0;

View File

@ -37,11 +37,12 @@ static struct option opts[] = {
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[])
{
pthread_t thread1, thread2, thread3; pthread_t thread1, thread2, thread3;
int arg = 0, code = 0, debug = 0; int arg = 0, code = 0, debug = 0;
char *config = NULL, *user = NULL, *logfile; char *config = NULL, *user = NULL, *logfile;
while (code != -1) { while (code != -1) {
code = getopt_long(argc, argv, "c:u:dh", opts, &arg); code = getopt_long(argc, argv, "c:u:dh", opts, &arg);
@ -85,7 +86,7 @@ int main(int argc, char *argv[]) {
log_print("unknown user: %s", user); log_print("unknown user: %s", user);
exit(-1); exit(-1);
} }
if (setgid(pwl->pw_gid) || setuid(pwl->pw_uid)) { if (setgid(pwl->pw_gid) || setuid(pwl->pw_uid)) {
log_print("setgid/setuid"); log_print("setgid/setuid");
exit(-1); exit(-1);
@ -102,13 +103,13 @@ int main(int argc, char *argv[]) {
/* start logging */ /* start logging */
if (!log_init(logfile)) if (!log_init(logfile))
exit(-1); exit(-1);
/* zum daemon mutieren */ /* zum daemon mutieren */
daemon(-1, 0); daemon(-1, 0);
} }
log_print("hlswmaster started (user: %s, pid: %d)", getpwuid(getuid())->pw_name, getpid()); log_print("hlswmaster started (user: %s, pid: %d)", getpwuid(getuid())->pw_name, getpid());
/* init scan engine */ /* init scan engine */
if (!scan_init()) if (!scan_init())
exit(-1); exit(-1);

View File

@ -40,7 +40,8 @@ static pthread_mutex_t plugin_lock = PTHREAD_MUTEX_INITIALIZER;
* @param *name filename des plugins * @param *name filename des plugins
* @return false on error * @return false on error
*/ */
int plugin_load(char *name) { int plugin_load(char *name)
{
struct hlswmaster_plugin *plugin; struct hlswmaster_plugin *plugin;
void *tmp; void *tmp;
struct conf_section *section; struct conf_section *section;
@ -82,7 +83,8 @@ int plugin_load(char *name) {
* *
* @return false on error * @return false on error
*/ */
int plugin_load_all() { int plugin_load_all()
{
struct conf_section *section; struct conf_section *section;
struct conf_tupel *tupel; struct conf_tupel *tupel;
@ -102,7 +104,8 @@ int plugin_load_all() {
* *
* @return false on error * @return false on error
*/ */
int plugin_unload_all() { int plugin_unload_all()
{
struct hlswmaster_plugin *plugin, *tmp; struct hlswmaster_plugin *plugin, *tmp;
pthread_mutex_lock(&plugin_lock); pthread_mutex_lock(&plugin_lock);
@ -125,7 +128,8 @@ int plugin_unload_all() {
* *
* @return true * @return true
*/ */
int plugins_scan(void) { int plugins_scan(void)
{
struct hlswmaster_plugin *plugin; struct hlswmaster_plugin *plugin;
pthread_mutex_lock(&plugin_lock); pthread_mutex_lock(&plugin_lock);
@ -144,22 +148,25 @@ int plugins_scan(void) {
* bis ein Plugin das Paket annimmt * bis ein Plugin das Paket annimmt
* *
* @param *pkt das zu parsene paket * @param *pkt das zu parsene paket
* @return false wenn kein Plugin das Paket angenommen hat * @return false wenn kein Plugin das Paket angenommen,
* sonst rueckgabewert des Plugins
*/ */
int plugins_parse(struct net_pkt *pkt) { int plugins_parse(struct net_pkt *pkt)
{
struct hlswmaster_plugin *plugin; struct hlswmaster_plugin *plugin;
int retval;
pthread_mutex_lock(&plugin_lock); pthread_mutex_lock(&plugin_lock);
list_for_each_entry(plugin, &plugin_list, list) { list_for_each_entry(plugin, &plugin_list, list) {
/* wenn vorhanden die parse funktion aufrufen */ /* wenn vorhanden die parse funktion aufrufen */
if (plugin->parse && plugin->parse(pkt)) { if (plugin->parse && (retval = plugin->parse(pkt))) {
pthread_mutex_unlock(&plugin_lock); pthread_mutex_unlock(&plugin_lock);
return 1; return retval;
} }
} }
pthread_mutex_unlock(&plugin_lock); pthread_mutex_unlock(&plugin_lock);
return 0; return PARSE_REJECT;
} }
/** /**
@ -169,7 +176,8 @@ int plugins_parse(struct net_pkt *pkt) {
* @param timeout timeout interval in sekunden * @param timeout timeout interval in sekunden
* @return true * @return true
*/ */
int plugins_gc(unsigned long timeout) { int plugins_gc(unsigned long timeout)
{
struct hlswmaster_plugin *plugin; struct hlswmaster_plugin *plugin;
pthread_mutex_lock(&plugin_lock); pthread_mutex_lock(&plugin_lock);

View File

@ -46,10 +46,11 @@
* @param size groesse der daten * @param size groesse der daten
* @return false bei fehler * @return false bei fehler
*/ */
int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *buf, unsigned int size) { int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *buf, unsigned int size)
{
unsigned short port; unsigned short port;
int ret = 1; int ret = 1;
while (portarr && portarr->portlo) { while (portarr && portarr->portlo) {
for (port = portarr->portlo; port <= portarr->porthi; port++) for (port = portarr->portlo; port <= portarr->porthi; port++)
if (!pkt_send(dstip, port, buf, size)) if (!pkt_send(dstip, port, buf, size))
@ -68,7 +69,8 @@ int pkt_send_portarr(struct in_addr *dstip, struct scan_ports *portarr, char *bu
* @param *portarr ports die angenommen werden * @param *portarr ports die angenommen werden
* @return die gameid der portrange oder 0 wenn nicht vorhanden * @return die gameid der portrange oder 0 wenn nicht vorhanden
*/ */
int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr) { int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr)
{
unsigned short port; unsigned short port;
while (portarr && portarr->portlo) { while (portarr && portarr->portlo) {
for (port = portarr->portlo; port <= portarr->porthi; port++) for (port = portarr->portlo; port <= portarr->porthi; port++)
@ -88,12 +90,13 @@ int pkt_check_portarr(struct net_pkt *pkt, struct scan_ports *portarr) {
* @param offset offset ab dem verglichen wird * @param offset offset ab dem verglichen wird
* @param *search daten nach denen gesucht wird * @param *search daten nach denen gesucht wird
* @param size laenge der daten * @param size laenge der daten
* @return true wenn gleich * @return false wenn gleich
* *
* @todo return false wenn offset + size >= pkt->size ? * @todo return false wenn offset + size >= pkt->size ?
*/ */
int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size)
{
if (offset >= pkt->size) if (offset >= pkt->size)
return 1; return 1;
@ -112,13 +115,42 @@ int pkt_memcmp(struct net_pkt *pkt, unsigned int offset, char *search, unsigned
* @param offset offset ab dem gesucht wird * @param offset offset ab dem gesucht wird
* @param *search daten nach denen gesucht wird * @param *search daten nach denen gesucht wird
* @param size laenge der daten * @param size laenge der daten
* @return pointer auf den string im Paket, oder NULL wenn nicht gefunden * @return offset auf den string im Paket, oder -1 wenn nicht gefunden
*/ */
void * pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size) { int pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size)
if (offset >= pkt->size) {
return NULL; void *found;
return memmem(pkt->buf + offset, pkt->size, search, size); if (offset >= pkt->size)
return -1;
found = memmem(pkt->buf + offset, pkt->size, search, size);
return (found == NULL) ? -1 : (found - (void *)pkt->buf);
}
/**
* pkt_merge()
* fuegt zwei pakete zu einem zusammen
* die header werden vom ersten Paket uebernommen
* die pakete werden nicht gefreed(!)
*
* @param *pkt1 erstes Paket
* @param *pkt2 zweites Paket
* @return zusammengefasstes Paket
*/
struct net_pkt * pkt_merge(struct net_pkt *pkt1, struct net_pkt *pkt2)
{
struct net_pkt *ret;
ret = malloc(sizeof(struct net_pkt) + pkt1->size + pkt2->size);
memcpy(&ret->addr, &pkt1->addr, sizeof(ret->addr));
ret->size = pkt1->size + pkt2->size;
memcpy(ret->buf, pkt1->buf, pkt1->size);
memcpy(ret->buf + pkt1->size, pkt2->buf, pkt2->size);
return ret;
} }
/** /**
@ -129,7 +161,8 @@ void * pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsign
* @param *pkt daten vom gameserver (fuer ip/port) * @param *pkt daten vom gameserver (fuer ip/port)
* @return false bei fehler * @return false bei fehler
*/ */
int server_add_pkt(unsigned int gameid, struct net_pkt *pkt) { int server_add_pkt(unsigned int gameid, struct net_pkt *pkt)
{
return server_add(gameid, pkt->addr.sin_addr.s_addr, ntohs(pkt->addr.sin_port), 0); return server_add(gameid, pkt->addr.sin_addr.s_addr, ntohs(pkt->addr.sin_port), 0);
} }
@ -140,7 +173,8 @@ int server_add_pkt(unsigned int gameid, struct net_pkt *pkt) {
* @param *pkt daten vom gameserver * @param *pkt daten vom gameserver
* @return pointer auf String * @return pointer auf String
*/ */
char * pkt_ntoa(struct net_pkt *pkt) { char * pkt_ntoa(struct net_pkt *pkt)
{
return inet_ntoa(pkt->addr.sin_addr); return inet_ntoa(pkt->addr.sin_addr);
} }
@ -151,31 +185,121 @@ char * pkt_ntoa(struct net_pkt *pkt) {
* @param *pkt daten vom gameserver * @param *pkt daten vom gameserver
* @return portnummer * @return portnummer
*/ */
unsigned short pkt_getport(struct net_pkt *pkt) { unsigned short pkt_getport(struct net_pkt *pkt)
{
return ntohs(pkt->addr.sin_port); return ntohs(pkt->addr.sin_port);
} }
/** /**
* pkt_atoi() * pkt_sameaddr()
* vergleicht die Adressen zweier Pakete
*
* @param *pkt1 Paket 1
* @param *pkt2 Paket 2
* @return true wenn Adressen gleich
*/
int pkt_sameaddr(struct net_pkt *pkt1, struct net_pkt *pkt2)
{
return (pkt1->addr.sin_addr.s_addr == pkt2->addr.sin_addr.s_addr) &&
(pkt1->addr.sin_port == pkt2->addr.sin_port);
}
/**
* pkt_parse_int()
* gibt die dezimalzahl in dem paket ab einer position zurueck * gibt die dezimalzahl in dem paket ab einer position zurueck
* *
* @param *pkt daten vom gameserver * @param *pkt daten vom gameserver
* @param *p pointer auf den begin des integers * @param offset offset auf den begin des integers
* @return wert des integers oder 0 bei fehler * @param *val pointer auf das ergebnis
* @return Anzahl der gelesenen Zeichen oder 0 bei fehler
*/ */
int pkt_atoi(struct net_pkt *pkt, void *p) { int pkt_parse_int(struct net_pkt *pkt, unsigned int offset, int *val)
int val = 0; {
void *max = ((void *)pkt->buf + pkt->size); unsigned char *max = pkt->buf + pkt->size;
char *c = p; unsigned char *c = pkt->buf + offset;
/* untere grenze abtesten */ /* untere grenze abtesten */
if ((void *)pkt->buf > p || p > max) if (pkt->buf > c || c > max)
return 0; return -1;
*val = 0;
/* ziffern einlesen */ /* ziffern einlesen */
while (isdigit(*c) && (void *)c < max) while (isdigit(*c) && c < max)
val = (val * 10) + (*c++ - 0x30); *val = (*val * 10) + (*c++ - 0x30);
return val; return (c - (pkt->buf + offset));
}
/**
* pkt_parse_ip()
* gibt die IP in *.*.*.* ab p als integer zurueck
*
* @param *pkt daten vom gameserver
* @param offset offset auf den begin der IP
* @param *ip pointer auf eine in_addr struct
* @return Anzahl der gelesenen Zeichen oder 0 bei Fehler
*/
int pkt_parse_ip(struct net_pkt *pkt, int offset, struct in_addr *ip)
{
int i, tmp, count, pos = offset;
ip->s_addr = 0;
for (i = 0; i < 4; i++) {
count = pkt_parse_int(pkt, pos, &tmp);
pos += count;
if (count == 0 || tmp < 0 || tmp > 255)
return 0;
ip->s_addr = ip->s_addr>>8 | tmp<<24;
if (i != 3 && pkt->buf[pos++] != '.')
return 0;
}
return pos - offset;
}
/**
* pkt_print()
* gibt ein paket als hex-dump aus
*
* @param *pkt daten vom gameserver
* @return char pointer auf hex-dump
*/
char * pkt_print(struct net_pkt *pkt)
{
int pos = 0, i = 0, j;
char *buf = malloc(pkt->size * 4 + 64);
while (pos < pkt->size) {
i += sprintf(buf + i, "%04X: ", pos);
for (j = 0; j < 16; j++) {
if (pos + j < pkt->size)
i += sprintf(buf + i, "%02X", pkt->buf[pos + j]);
else
i += sprintf(buf + i, " ");
if (j % 2)
buf[i++] = ' ';
}
for (j = 0; j < 16; j++) {
if (pos + j < pkt->size) {
unsigned char val = pkt->buf[pos + j];
if (val >= 0x20 && val < 0x80)
buf[i++] = val;
else
buf[i++] = '.';
} else {
buf[i++] = ' ';
}
}
pos += 16;
buf[i++] = '\r';
buf[i++] = '\n';
}
buf[i] = 0;
return buf;
} }

View File

@ -27,22 +27,39 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
#include <time.h> #include <time.h>
#include "list.h" #include "list.h"
#include "netpkt.h" #include "netpkt.h"
#include "configfile.h" #include "configfile.h"
#include "hlswmaster.h" #include "hlswmaster.h"
#include "plugin.h"
#include "plugin_helper.h"
#define DEBUG 1 #define DEBUG 1
struct rx_entry {
struct list_head list;
struct net_pkt *pkt;
};
/** rx packet liste */
static LIST_HEAD(rxlist);
/** sichert die rx liste */
static pthread_mutex_t rxlist_lock = PTHREAD_MUTEX_INITIALIZER;
/** anzahl der pakete in der rxlist */
static sem_t rxlist_sem;
/** interne serverliste */ /** interne serverliste */
static LIST_HEAD(serverlist); static LIST_HEAD(serverlist);
/** sichert die interne serverliste */ /** sichert die interne serverliste */
static pthread_mutex_t serverlist_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t serverlist_lock = PTHREAD_MUTEX_INITIALIZER;
/* scan socket */ /** scan socket */
static int scan_sock; static int scan_sock;
/** /**
@ -53,7 +70,8 @@ static int scan_sock;
* @param *b gameserver 2 * @param *b gameserver 2
* @return true wenn es sich um den selben server handelt * @return true wenn es sich um den selben server handelt
*/ */
static inline int server_cmp(const struct game_server *a, struct game_server *b) { static inline int server_cmp(const struct game_server *a, struct game_server *b)
{
return (a->gameid == b->gameid && a->ip == b->ip && return (a->gameid == b->gameid && a->ip == b->ip &&
a->port1 == b->port1 && a->port2 == b->port2); a->port1 == b->port1 && a->port2 == b->port2);
} }
@ -66,10 +84,11 @@ static inline int server_cmp(const struct game_server *a, struct game_server *b)
* @param gameid gameid des servers * @param gameid gameid des servers
* @param ip ip des servers * @param ip ip des servers
* @param port1 erster port * @param port1 erster port
* @param port2 zweiter port * @param port2 zweiter port
* @return false bei fehler * @return false bei fehler
*/ */
int server_add(u_int16_t gameid, u_int32_t 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; struct game_server server, *nserver;
server.gameid = gameid; server.gameid = gameid;
@ -99,7 +118,7 @@ int server_add(u_int16_t gameid, u_int32_t ip, u_int16_t port1, u_int16_t port2)
memcpy(nserver, &server, sizeof(struct game_server)); memcpy(nserver, &server, sizeof(struct game_server));
list_add_tail(&nserver->list, &serverlist); list_add_tail(&nserver->list, &serverlist);
} }
/* modtime anpassen */ /* modtime anpassen */
nserver->modtime = time(NULL); nserver->modtime = time(NULL);
@ -114,7 +133,8 @@ int server_add(u_int16_t gameid, u_int32_t ip, u_int16_t port1, u_int16_t port2)
* *
* @param timeout timeout in sekunden * @param timeout timeout in sekunden
*/ */
static void serverlist_refresh(long timeout) { static void serverlist_refresh(long timeout)
{
struct game_server *server, *tmp; struct game_server *server, *tmp;
long now = time(NULL); long now = time(NULL);
@ -151,35 +171,87 @@ static void serverlist_refresh(long timeout) {
* @param size groesse der daten * @param size groesse der daten
* @return false bei fehler * @return false bei fehler
*/ */
int pkt_send(struct in_addr *dstip, unsigned int dstport, char *buf, unsigned int size) { int pkt_send(struct in_addr *dstip, unsigned int dstport, char *buf, unsigned int size)
{
struct sockaddr_in addr; struct sockaddr_in addr;
int ret = 1; int ret = 1;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(dstport); addr.sin_port = htons(dstport);
addr.sin_addr.s_addr = (dstip ? dstip->s_addr : 0xFFFFFFFF); addr.sin_addr.s_addr = (dstip ? dstip->s_addr : 0xFFFFFFFF);
if (sendto(scan_sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (sendto(scan_sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
log_print("scan_send(): sendto()"); log_print("scan_send(): sendto()");
ret = 0; ret = 0;
} }
usleep(10000); usleep(10000);
return ret; return ret;
} }
/** /**
* scan_control() * scan_receive_real()
* triggert den scan der plugins * arbeitet die receive queue ab
* arbeitet dann die sender queue ab
* triggert den gc der plugins
*/ */
void scan_control(void) { void scan_receive_real(void)
struct net_pkt *pkt, *tmp; {
long now; struct rx_entry *rx;
struct net_pkt *pkt;
int cnt, retval;
do {
sem_wait(&rxlist_sem);
pthread_mutex_lock(&rxlist_lock);
rx = list_entry(rxlist.next, struct rx_entry, list);
list_del(&rx->list);
pthread_mutex_unlock(&rxlist_lock);
pkt = rx->pkt;
free(rx);
retval = plugins_parse(pkt);
switch (retval) {
case PARSE_REJECT:
log_print("scan_receive(): unknown packet: %s:%d size:%d",
inet_ntoa(pkt->addr.sin_addr),
ntohs(pkt->addr.sin_port),
pkt->size);
#if 0
{
char *p = pkt_print(pkt);
log_print("%s", p);
free(p);
}
#endif
case PARSE_ACCEPT:
free(pkt);
case PARSE_ACCEPT_FREED:
break;
}
sem_getvalue(&rxlist_sem, &cnt);
} while (cnt > 0);
}
/**
* scan_control()
* triggert den gc der plugins
* triggert den serverlist_refresh
* triggert den scan der plugins
* arbeitet die rx queue ab
*/
void scan_control(void)
{
long last_plugin_gc = 0, last_list_refresh = 0, last_scan = 0; long last_plugin_gc = 0, last_list_refresh = 0, last_scan = 0;
int plugin_timeout, list_timeout, list_refresh, scan_interval; int plugin_timeout, list_timeout, list_refresh, scan_interval;
int cnt;
long now;
plugin_timeout = config_get_int("global", "plugin_timeout", 30); plugin_timeout = config_get_int("global", "plugin_timeout", 30);
list_timeout = config_get_int("global", "serverlist_timeout", 30); list_timeout = config_get_int("global", "serverlist_timeout", 30);
list_refresh = config_get_int("global", "serverlist_refresh", 5); list_refresh = config_get_int("global", "serverlist_refresh", 5);
@ -190,10 +262,10 @@ void scan_control(void) {
log_print(" serverlist_refresh: %ds", list_refresh); log_print(" serverlist_refresh: %ds", list_refresh);
log_print(" serverlist_timeout: %ds", list_timeout); log_print(" serverlist_timeout: %ds", list_timeout);
log_print(" plugin_timeout: %d", plugin_timeout); log_print(" plugin_timeout: %d", plugin_timeout);
while (1) { while (1) {
now = time(NULL); now = time(NULL);
/* interne plugin daten aufraeumen */ /* interne plugin daten aufraeumen */
if (last_plugin_gc + plugin_timeout < now) { if (last_plugin_gc + plugin_timeout < now) {
last_plugin_gc = now; last_plugin_gc = now;
@ -205,29 +277,36 @@ void scan_control(void) {
last_list_refresh = now; last_list_refresh = now;
serverlist_refresh(list_timeout); serverlist_refresh(list_timeout);
} }
/* neuen scan ausloesen */ /* neuen scan ausloesen */
if (last_scan + scan_interval < now) { if (last_scan + scan_interval < now) {
last_scan = now; last_scan = now;
plugins_scan(); plugins_scan();
} }
sleep(1); /* empfangene daten parsen */
sem_getvalue(&rxlist_sem, &cnt);
if (cnt > 0)
scan_receive_real();
usleep(500000);
} }
} }
/** /**
* scan_receive() * scan_receive()
* wartet auf serverantworten und uebergibt die pakete den * wartet auf serverantworten und uebergibt die pakete der
* plugins zur auswertung * receive queue
*/ */
void scan_receive(void) { void scan_receive(void)
{
struct net_pkt *pkt; struct net_pkt *pkt;
struct rx_entry *rx;
fd_set fdsel, fdcpy; fd_set fdsel, fdcpy;
int recvsize, i; int recvsize, i;
log_print("thread_start: scan_receiver"); log_print("thread_start: scan_receiver");
FD_ZERO(&fdsel); FD_ZERO(&fdsel);
FD_SET(scan_sock, &fdsel); FD_SET(scan_sock, &fdsel);
@ -235,13 +314,11 @@ void scan_receive(void) {
memcpy(&fdcpy, &fdsel, sizeof(fdsel)); memcpy(&fdcpy, &fdsel, sizeof(fdsel));
select(FD_SETSIZE, &fdcpy, NULL, NULL, NULL); select(FD_SETSIZE, &fdcpy, NULL, NULL, NULL);
ioctl(scan_sock, FIONREAD, &recvsize); if (ioctl(scan_sock, FIONREAD, &recvsize) == -1) {
log_print("scan_receive(): ioctl()");
if (recvsize <= 0) {
log_print("scan_receive(): drop short packet");
continue; continue;
} }
if (!(pkt = malloc(sizeof(struct net_pkt) + recvsize))) { if (!(pkt = malloc(sizeof(struct net_pkt) + recvsize))) {
log_print("scan_receive(): malloc()"); log_print("scan_receive(): malloc()");
continue; continue;
@ -250,29 +327,40 @@ void scan_receive(void) {
i = sizeof(struct sockaddr_in); i = sizeof(struct sockaddr_in);
pkt->size = recvfrom(scan_sock, pkt->buf, recvsize, 0, (struct sockaddr *)&pkt->addr, &i); pkt->size = recvfrom(scan_sock, pkt->buf, recvsize, 0, (struct sockaddr *)&pkt->addr, &i);
if (!plugins_parse(pkt)) { if (pkt->size == 0) {
log_print("scan_receive(): unknown packet: %s:%d size:%d", free(pkt);
inet_ntoa(pkt->addr.sin_addr), ntohs(pkt->addr.sin_port), pkt->size); continue;
} }
rx = malloc(sizeof(struct rx_entry));
rx->pkt = pkt;
free(pkt); pthread_mutex_lock(&rxlist_lock);
list_add_tail(&rx->list, &rxlist);
pthread_mutex_unlock(&rxlist_lock);
sem_post(&rxlist_sem);
} }
} }
/** /**
* schliesst den server scan socket * schliesst den server scan socket
*/ */
static void scan_close() { static void scan_close()
{
close(scan_sock); close(scan_sock);
sem_destroy(&rxlist_sem);
} }
/** /**
* scan_init() * scan_init()
* initialisiert den socket fuer den server scan * initialisiert den socket fuer den server scan
* initialisiert die rxlist semaphore
* *
* @return false on error * @return false on error
*/ */
int scan_init() { int scan_init()
{
struct sockaddr_in dst; struct sockaddr_in dst;
int i = 1, port; int i = 1, port;
char *ip; char *ip;
@ -298,12 +386,15 @@ int scan_init() {
log_print("scan_init(): setsockopt()"); log_print("scan_init(): setsockopt()");
return 0; return 0;
} }
if (atexit(scan_close) != 0) { if (atexit(scan_close) != 0) {
log_print("scan_init(): atexit()"); log_print("scan_init(): atexit()");
return 0; return 0;
} }
log_print("scan socket initialized (%s:%d)", ip, port); log_print("scan socket initialized (%s:%d)", ip, port);
sem_init(&rxlist_sem, 0, 0);
return 1; return 1;
} }

View File

@ -68,7 +68,8 @@ static char *id2name[] = {
static int sock, verbose = 0; static int sock, verbose = 0;
static void parse_pkt(struct sockaddr_in *src, void *pkt, unsigned int size) { static void parse_pkt(struct sockaddr_in *src, void *pkt, unsigned int size)
{
struct _entry *server; struct _entry *server;
struct in_addr tmp; struct in_addr tmp;
@ -77,7 +78,7 @@ static void parse_pkt(struct sockaddr_in *src, void *pkt, unsigned int size) {
inet_ntoa(src->sin_addr), ntohs(src->sin_port), size); inet_ntoa(src->sin_addr), ntohs(src->sin_port), size);
} else { } else {
printf("received hlsw packet from: %15s:%-5d size=%d\n count=%d", printf("received hlsw packet from: %15s:%-5d size=%d count=%d\n",
inet_ntoa(src->sin_addr), ntohs(src->sin_port), size, inet_ntoa(src->sin_addr), ntohs(src->sin_port), size,
((size > sizeof(hlswheader)) ? (size - sizeof(hlswheader)) / sizeof(struct _entry) : 0)); ((size > sizeof(hlswheader)) ? (size - sizeof(hlswheader)) / sizeof(struct _entry) : 0));
@ -94,7 +95,8 @@ static void parse_pkt(struct sockaddr_in *src, void *pkt, unsigned int size) {
} }
} }
static int scan_init() { static int scan_init()
{
int i = 1; int i = 1;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
@ -110,7 +112,8 @@ static int scan_init() {
return 0; return 0;
} }
static int scan_transmit(struct sockaddr_in *dst) { static int scan_transmit(struct sockaddr_in *dst)
{
if (sendto(sock, hlswheader, sizeof(hlswheader), 0, (struct sockaddr *)dst, sizeof(struct sockaddr_in)) < 0) { if (sendto(sock, hlswheader, sizeof(hlswheader), 0, (struct sockaddr *)dst, sizeof(struct sockaddr_in)) < 0) {
perror("sendto()"); perror("sendto()");
return -1; return -1;
@ -119,7 +122,8 @@ static int scan_transmit(struct sockaddr_in *dst) {
return 0; return 0;
} }
static int scan_receive() { static int scan_receive()
{
struct sockaddr_in src; struct sockaddr_in src;
struct timeval tv; struct timeval tv;
fd_set fdsel; fd_set fdsel;
@ -171,7 +175,8 @@ static struct option opts[] = {
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[])
{
struct sockaddr_in dst; struct sockaddr_in dst;
int arg = 0, code = 0; int arg = 0, code = 0;
int freq = -1; int freq = -1;