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:
parent
861d41be08
commit
90d33bffbf
|
@ -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
|
||||
- code cleanup (mostly doxygen tags)
|
||||
- code cleanup
|
||||
- added doxygen file
|
||||
|
||||
* Thu 31 Mar 2005 Olaf Rempel <razzor@kopf-tisch.de> 0.52
|
||||
|
|
|
@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
|
|||
|
||||
SUBDIRS = src plugins tools
|
||||
|
||||
EXTRA_DIST = TODO autogen.sh hlswmaster.conf contrib
|
||||
EXTRA_DIST = TODO autogen.sh hlswmaster.conf doc
|
||||
|
|
|
@ -174,7 +174,7 @@ sysconfdir = @sysconfdir@
|
|||
target_alias = @target_alias@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
SUBDIRS = src plugins tools
|
||||
EXTRA_DIST = TODO autogen.sh hlswmaster.conf contrib
|
||||
EXTRA_DIST = TODO autogen.sh hlswmaster.conf doc
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
||||
|
||||
|
|
3
TODO
3
TODO
|
@ -5,13 +5,11 @@
|
|||
- auf mehreren/allen interfaces gleichzeitig scannen
|
||||
geht das ueberhaupt? ohne root rechte?
|
||||
- threads ueberwachen
|
||||
- threadpool fuer client-thread?
|
||||
- statistiken? webserver? gamespy-export?
|
||||
- Makefile: stripping binarys?
|
||||
|
||||
und natuerlich:
|
||||
- weitere spiele finden:
|
||||
Halflife
|
||||
Quake 1
|
||||
Command & Conquer Renegade
|
||||
Medal of Honor: Allied Assault
|
||||
|
@ -26,7 +24,6 @@ und natuerlich:
|
|||
Tribes 2
|
||||
Savage: The Battle for Newerth
|
||||
Pain Killer
|
||||
Halflife 2
|
||||
Tribes Vengeance
|
||||
|
||||
- vorhandene parser debuggen & verbessern
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#! /bin/sh
|
||||
# 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>>.
|
||||
#
|
||||
|
@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='hlswmaster'
|
||||
PACKAGE_TARNAME='hlswmaster'
|
||||
PACKAGE_VERSION='0.53'
|
||||
PACKAGE_STRING='hlswmaster 0.53'
|
||||
PACKAGE_VERSION='0.60'
|
||||
PACKAGE_STRING='hlswmaster 0.60'
|
||||
PACKAGE_BUGREPORT='Olaf Rempel <razzor@kopf-tisch.de>'
|
||||
|
||||
# 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.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
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]...
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of hlswmaster 0.53:";;
|
||||
short | recursive ) echo "Configuration of hlswmaster 0.60:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1160,7 +1160,7 @@ fi
|
|||
test -n "$ac_init_help" && exit 0
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
hlswmaster configure 0.53
|
||||
hlswmaster configure 0.60
|
||||
generated by GNU Autoconf 2.59
|
||||
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
|
@ -1174,7 +1174,7 @@ cat >&5 <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
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
|
||||
|
||||
$ $0 $@
|
||||
|
@ -1818,7 +1818,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=hlswmaster
|
||||
VERSION=0.53
|
||||
VERSION=0.60
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -21419,7 +21419,7 @@ _ASBOX
|
|||
} >&5
|
||||
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
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -21482,7 +21482,7 @@ _ACEOF
|
|||
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
hlswmaster config.status 0.53
|
||||
hlswmaster config.status 0.60
|
||||
configured by $0, generated by GNU Autoconf 2.59,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
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
|
||||
AM_INIT_AUTOMAKE(hlswmaster, 0.53)
|
||||
AM_INIT_AUTOMAKE(hlswmaster, 0.60)
|
||||
|
||||
dnl do not rebuild configure
|
||||
AM_MAINTAINER_MODE
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = hlswmaster
|
||||
PROJECT_NUMBER = 0.53
|
||||
OUTPUT_DIRECTORY = ../doc
|
||||
OUTPUT_DIRECTORY = .
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
USE_WINDOWS_ENCODING = NO
|
|
@ -10,7 +10,7 @@ scan_interval 30
|
|||
serverlist_interval 5
|
||||
|
||||
# server timeout after X seconds
|
||||
serverlist_timeout 30
|
||||
serverlist_timeout 60
|
||||
|
||||
# plugin data timeout every X seconds
|
||||
plugin_timeout 30
|
||||
|
@ -19,7 +19,8 @@ plugin_timeout 30
|
|||
master_ip 0.0.0.0
|
||||
|
||||
# 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/quake2.so
|
||||
plugin plugins/.libs/gamespy1.so
|
||||
|
@ -30,6 +31,12 @@ plugin plugins/.libs/doom3.so
|
|||
logfile hlswmaster.log
|
||||
|
||||
[hlswproxy]
|
||||
# ask these hlswmasters
|
||||
scan_ip 10.10.0.1
|
||||
scan_ip 10.10.0.2
|
||||
|
||||
[halflife]
|
||||
# allow these nets
|
||||
valid_net 10.10.0.0/16
|
||||
valid_net 172.16.0.0/16
|
||||
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
#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/kernel.h (container_of)
|
||||
* linux/include/linux/list.h (*list*)
|
||||
* 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)
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@
|
|||
#include "configfile.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 list_head list;
|
||||
|
||||
|
|
|
@ -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_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 char * pkt_ntoa(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 */
|
||||
|
|
|
@ -4,7 +4,7 @@ EXTRA_DIST = skel.c
|
|||
|
||||
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_LDFLAGS = -module -avoid-version
|
||||
|
@ -15,6 +15,9 @@ gamespy1_la_LDFLAGS = -module -avoid-version
|
|||
gamespy2_la_SOURCES = gamespy2.c
|
||||
gamespy2_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
halflife_la_SOURCES = halflife.c
|
||||
halflife_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
hlswproxy_la_SOURCES = hlswproxy.c
|
||||
hlswproxy_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
@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@
|
||||
top_srcdir = @top_srcdir@
|
||||
|
@ -65,6 +65,9 @@ gamespy1_la_OBJECTS = $(am_gamespy1_la_OBJECTS)
|
|||
gamespy2_la_LIBADD =
|
||||
am_gamespy2_la_OBJECTS = gamespy2.lo
|
||||
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 =
|
||||
am_hlswproxy_la_OBJECTS = hlswproxy.lo
|
||||
hlswproxy_la_OBJECTS = $(am_hlswproxy_la_OBJECTS)
|
||||
|
@ -86,11 +89,13 @@ CCLD = $(CC)
|
|||
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \
|
||||
$(gamespy2_la_SOURCES) $(hlswproxy_la_SOURCES) \
|
||||
$(q3engine_la_SOURCES) $(quake2_la_SOURCES)
|
||||
$(gamespy2_la_SOURCES) $(halflife_la_SOURCES) \
|
||||
$(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) \
|
||||
$(quake2_la_SOURCES)
|
||||
DIST_SOURCES = $(doom3_la_SOURCES) $(gamespy1_la_SOURCES) \
|
||||
$(gamespy2_la_SOURCES) $(hlswproxy_la_SOURCES) \
|
||||
$(q3engine_la_SOURCES) $(quake2_la_SOURCES)
|
||||
$(gamespy2_la_SOURCES) $(halflife_la_SOURCES) \
|
||||
$(hlswproxy_la_SOURCES) $(q3engine_la_SOURCES) \
|
||||
$(quake2_la_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
@ -196,13 +201,15 @@ target_alias = @target_alias@
|
|||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
EXTRA_DIST = skel.c
|
||||
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_LDFLAGS = -module -avoid-version
|
||||
gamespy1_la_SOURCES = gamespy1.c
|
||||
gamespy1_la_LDFLAGS = -module -avoid-version
|
||||
gamespy2_la_SOURCES = gamespy2.c
|
||||
gamespy2_la_LDFLAGS = -module -avoid-version
|
||||
halflife_la_SOURCES = halflife.c
|
||||
halflife_la_LDFLAGS = -module -avoid-version
|
||||
hlswproxy_la_SOURCES = hlswproxy.c
|
||||
hlswproxy_la_LDFLAGS = -module -avoid-version
|
||||
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)
|
||||
gamespy2.la: $(gamespy2_la_OBJECTS) $(gamespy2_la_DEPENDENCIES)
|
||||
$(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)
|
||||
$(LINK) -rpath $(pkgdatadir) $(hlswproxy_la_LDFLAGS) $(hlswproxy_la_OBJECTS) $(hlswproxy_la_LIBADD) $(LIBS)
|
||||
q3engine.la: $(q3engine_la_OBJECTS) $(q3engine_la_DEPENDENCIES)
|
||||
|
|
|
@ -28,22 +28,24 @@ static struct scan_ports port_arr[] = {
|
|||
static char scanmsg[] = "\xff\xffgetInfo";
|
||||
static char replymsg[] = "\xff\xffinfoResponse";
|
||||
|
||||
static int scan(void) {
|
||||
static int scan(void)
|
||||
{
|
||||
pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
static int parse(struct net_pkt *pkt)
|
||||
{
|
||||
int gameid;
|
||||
|
||||
if (!(gameid = pkt_check_portarr(pkt, port_arr)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
server_add_pkt(gameid, pkt);
|
||||
return 1;
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
struct hlswmaster_plugin plugin = {
|
||||
|
|
|
@ -29,89 +29,227 @@ static struct scan_ports port_arr[] = {
|
|||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static char scanmsg[] = "\\status\\";
|
||||
static char ut_reply[] = "\\gamename\\ut\\";
|
||||
static char ut2k3_reply[] = "\\gamename\\ut2\\";
|
||||
static char ut2k4_reply[] = "\\gamename\\ut2004\\";
|
||||
static char bf1942_reply[] = "\\gamename\\bfield1942\\";
|
||||
static char bfv_reply[] = "\\game_id\\bfvietnam\\";
|
||||
static char avp2_reply[] = "\\gamename\\avp2\\";
|
||||
static char igi2_reply[] = "\\gamename\\projectigi2r\\";
|
||||
static char hostport_search[] = "\\hostport\\";
|
||||
struct gs1_part {
|
||||
struct list_head list;
|
||||
unsigned long timeout;
|
||||
unsigned int queryid;
|
||||
unsigned int subid;
|
||||
struct net_pkt *pkt;
|
||||
};
|
||||
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
int gameid, port;
|
||||
void *p;
|
||||
static struct net_pkt * gs1_pkt_merge(struct net_pkt *pkt, unsigned int queryid, unsigned int subid)
|
||||
{
|
||||
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)))
|
||||
return 0;
|
||||
// in liste packen
|
||||
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) {
|
||||
case 5:/* unreal tournament 2k3 */
|
||||
if (pkt_memmem(pkt, 0, ut_reply, strlen(ut_reply)))
|
||||
case 5:/* unreal tournament */
|
||||
if (!pkt_memcmp(pkt, pos1, reply_ut, strlen(reply_ut)))
|
||||
gameid = 5;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
||||
else
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
break;
|
||||
|
||||
case 16:/* battlefield 1942 */
|
||||
if (!pkt_memmem(pkt, 0, bf1942_reply, strlen(bf1942_reply)))
|
||||
return 0;
|
||||
case 35:/* battlefield vietnam */
|
||||
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;
|
||||
|
||||
case 17:/* alien vs. predator 2 */
|
||||
if (!pkt_memmem(pkt, 0, avp2_reply, strlen(avp2_reply)))
|
||||
return 0;
|
||||
if (!pkt_memcmp(pkt, pos1, reply_avp2, strlen(reply_avp2)))
|
||||
gameid = 17;
|
||||
else
|
||||
return PARSE_REJECT;
|
||||
break;
|
||||
|
||||
|
||||
case 19:/* project igi2 covert strike */
|
||||
if (!pkt_memmem(pkt, 0, igi2_reply, strlen(igi2_reply)))
|
||||
return 0;
|
||||
if (!pkt_memcmp(pkt, pos1, reply_igi2, strlen(reply_igi2)))
|
||||
gameid = 19;
|
||||
else
|
||||
return PARSE_REJECT;
|
||||
break;
|
||||
|
||||
case 35:/* battlefield vietnam */
|
||||
if (!pkt_memmem(pkt, 0, bfv_reply, strlen(bfv_reply)))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
}
|
||||
|
||||
/* hostport angabe suchen */
|
||||
p = pkt_memmem(pkt, 0, hostport_search, strlen(hostport_search));
|
||||
if (p) {
|
||||
port = pkt_atoi(pkt, p + strlen(hostport_search));
|
||||
}
|
||||
offset = pkt_memmem(pkt, 0, search_hostport, strlen(search_hostport));
|
||||
if (offset != -1)
|
||||
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
|
||||
*/
|
||||
if (p && port != ntohs(pkt->addr.sin_port)) {
|
||||
/*
|
||||
* wenn ein hostport angegeben wurde, und das nicht der src port ist
|
||||
* beide ports in die serverliste uebernehmen
|
||||
*/
|
||||
if ((offset != -1) && (port != ntohs(pkt->addr.sin_port))) {
|
||||
server_add(gameid, pkt->addr.sin_addr.s_addr, port, ntohs(pkt->addr.sin_port));
|
||||
} else {
|
||||
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 = {
|
||||
.name = "gamespy1",
|
||||
.scan = &scan,
|
||||
.parse = &parse,
|
||||
.gc = &gc,
|
||||
};
|
||||
|
|
|
@ -22,28 +22,31 @@
|
|||
|
||||
static struct scan_ports port_arr[] = {
|
||||
{ 2302, 2302, 30 }, /* halo(30) */
|
||||
{ 3455, 3455, 37 }, /* painkiller(34) */
|
||||
{ 0,0,0 }
|
||||
};
|
||||
|
||||
static char scanmsg[] = { 0xFE, 0xFD, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x00, 0x00 };
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
static int parse(struct net_pkt *pkt)
|
||||
{
|
||||
int gameid;
|
||||
|
||||
if (!(gameid = pkt_check_portarr(pkt, port_arr)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
if (pkt_memcmp(pkt, 0, replymsg, sizeof(replymsg)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
server_add_pkt(gameid, pkt);
|
||||
return 1;
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
struct hlswmaster_plugin plugin = {
|
||||
|
|
|
@ -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, §ion->tupel, list)
|
||||
if (!strcmp(tupel->option, "valid_net"))
|
||||
i++;
|
||||
|
||||
if (i == 0 || !(net_arr = malloc(sizeof(struct net_entry) * i)))
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
list_for_each_entry(tupel, §ion->tupel, list) {
|
||||
if (strcmp(tupel->option, "valid_net"))
|
||||
continue;
|
||||
|
||||
if (parse_net(tupel->parameter, &net_arr[i])) {
|
||||
j = sprintf(buf, " adding: %s", inet_ntoa(net_arr[i].ip));
|
||||
sprintf(buf + j, "/%s", inet_ntoa(net_arr[i].mask));
|
||||
log_print(buf);
|
||||
i++;
|
||||
} else {
|
||||
log_print(" invalid net: %s", tupel->parameter);
|
||||
}
|
||||
}
|
||||
net_arr_size = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fini()
|
||||
{
|
||||
if (net_arr_size > 0 && net_arr)
|
||||
free(net_arr);
|
||||
}
|
||||
|
||||
struct hlswmaster_plugin plugin = {
|
||||
.name = "halflife",
|
||||
.scan = &scan,
|
||||
.parse = &parse,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
};
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "plugin_helper.h"
|
||||
|
||||
struct _entry {
|
||||
struct hlsw_entry {
|
||||
u_int16_t gameid;
|
||||
u_int32_t ip;
|
||||
u_int16_t port1;
|
||||
|
@ -38,17 +38,19 @@ static int ip_arr_size = 0;
|
|||
|
||||
static char scanmsg[] = "\xff\xff\xff\xffHLSWLANSEARCH";
|
||||
|
||||
static int scan(void) {
|
||||
static int scan(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ip_arr_size; i++)
|
||||
pkt_send(&ip_arr[i], 7140, scanmsg, sizeof(scanmsg));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
struct _entry *server;
|
||||
static int parse(struct net_pkt *pkt)
|
||||
{
|
||||
struct hlsw_entry *server;
|
||||
if (pkt_getport(pkt) != 7140)
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
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++;
|
||||
}
|
||||
return 1;
|
||||
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
static int init(struct conf_section *section) {
|
||||
static int init(struct conf_section *section)
|
||||
{
|
||||
struct conf_tupel *tupel;
|
||||
int i = 0;
|
||||
list_for_each_entry(tupel, §ion->tupel, list)
|
||||
|
@ -81,11 +85,11 @@ static int init(struct conf_section *section) {
|
|||
}
|
||||
}
|
||||
ip_arr_size = i;
|
||||
log_print(" added %d master server(s)", i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int fini() {
|
||||
static int fini()
|
||||
{
|
||||
if (ip_arr_size > 0 && ip_arr)
|
||||
free(ip_arr);
|
||||
}
|
||||
|
|
|
@ -22,82 +22,79 @@
|
|||
|
||||
static struct scan_ports port_arr[] = {
|
||||
{ 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) */
|
||||
{ 29070, 29070, 27 }, /* jk3(27) TODO: UNTESTED */
|
||||
{ 29070, 29070, 27 }, /* jk3(27) */
|
||||
{ 0,0,0 }
|
||||
};
|
||||
|
||||
static char scanmsg[] = "\xff\xff\xff\xffgetStatus";
|
||||
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 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) {
|
||||
static int scan(void)
|
||||
{
|
||||
pkt_send_portarr(NULL, port_arr, scanmsg, strlen(scanmsg));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
int gameid;
|
||||
|
||||
if (!(gameid = pkt_check_portarr(pkt, port_arr)))
|
||||
return 0;
|
||||
static int parse(struct net_pkt *pkt)
|
||||
{
|
||||
int gameid = 0, pos1, pos2;
|
||||
|
||||
if (!pkt_check_portarr(pkt, port_arr))
|
||||
return PARSE_REJECT;
|
||||
|
||||
if (pkt_memcmp(pkt, 0, replymsg, strlen(replymsg)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
switch (gameid) {
|
||||
case 6: /* q3, ef, et, rtcw */
|
||||
if (pkt_memmem(pkt, 0, q3_reply, strlen(q3_reply))) {
|
||||
pos1 = pkt_memmem(pkt, 0, search_version, strlen(search_version));
|
||||
pos2 = pkt_memmem(pkt, 0, search_gamename, strlen(search_gamename));
|
||||
|
||||
if (pos1 != -1) {
|
||||
pos1 += strlen(search_version);
|
||||
if (!pkt_memcmp(pkt, pos1, reply_q3, strlen(reply_q3)))
|
||||
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;
|
||||
|
||||
} else if (pkt_memmem(pkt, 0, rtcw_reply, strlen(rtcw_reply))) {
|
||||
else if (!pkt_memcmp(pkt, pos1, reply_rtcw, strlen(reply_rtcw)))
|
||||
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;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: /* jedi knight 2 */
|
||||
if (!pkt_memmem(pkt, 0, jk2_reply, strlen(jk2_reply)))
|
||||
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_memcmp(pkt, pos1, reply_jk2, strlen(reply_jk2)))
|
||||
gameid = 12;
|
||||
|
||||
} else if (pkt_memmem(pkt, 0, coduo_reply, strlen(coduo_reply))) {
|
||||
gameid = 42;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
else if (!pkt_memcmp(pkt, pos1, reply_jk3, strlen(reply_jk3)))
|
||||
gameid = 27;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return 1;
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
struct hlswmaster_plugin plugin = {
|
||||
|
|
|
@ -20,22 +20,24 @@
|
|||
#include <string.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));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse(struct net_pkt *pkt) {
|
||||
static int parse(struct net_pkt *pkt)
|
||||
{
|
||||
if (pkt_getport(pkt) != 27910)
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
if (pkt_memcmp(pkt, 0, scanmsg, strlen(scanmsg)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
server_add_pkt(3, pkt);
|
||||
return 1;
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
struct hlswmaster_plugin plugin = {
|
||||
|
|
|
@ -38,7 +38,7 @@ static int scan(void) {
|
|||
struct in_addr tmp;
|
||||
inet_aton("192.168.1.100", &tmp)
|
||||
pkt_send(&tmp, 8888, myscan, strlen(myscan));
|
||||
|
||||
|
||||
/* an portrange(s) senden */
|
||||
struct scan_ports port_arr[] = {
|
||||
{ 27960, 27963, 0 }, /* von 27960-27963 scannen */
|
||||
|
@ -62,44 +62,48 @@ static int scan(void) {
|
|||
static int parse(struct net_pkt *pkt) {
|
||||
/* checken ob das paket vom richtigen port kommt: */
|
||||
if (pkt_getport(pkt) != 27910)
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
/* bei einem port_arr checken ob es von einem der angefragten ports kommt */
|
||||
int gameid;
|
||||
if (!(gameid = pkt_check_portarr(pkt, port_arr)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
/* gameid enthaelt nun den dritten wert einer passenden port_arr zeile */
|
||||
|
||||
|
||||
/* paketinhalt checken (packet = "good morning dave\x00") */
|
||||
char mycmp1[] = "good";
|
||||
if (pkt_memcmp(pkt, 0, mycmp1, strlen(mycmp1)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
/* paketinhalt mit offset */
|
||||
char mycmp2[] = "morning";
|
||||
if (pkt_memcmp(pkt, 5, mycmp2, strlen(mycmp2)))
|
||||
return 0;
|
||||
return PARSE_REJECT;
|
||||
|
||||
/* suchen ob paketinhalt vorhanden ist (packet = "blablablablabla\hostport\7777\blablabla") */
|
||||
char mymem[] = "\\hostport\\";
|
||||
void *p
|
||||
p = pkt_memmem(pkt, 0, mymem, strlen(mymem));
|
||||
if (!p)
|
||||
return 0;
|
||||
if (p == -1)
|
||||
return PARSE_REJECT;
|
||||
|
||||
/* ints aus paket parsen: */
|
||||
p += strlen(mymem);
|
||||
port2 = pkt_atoi(pkt, p);
|
||||
|
||||
int port2;
|
||||
|
||||
if (pkt_parse_int(pkt, offset, &port2) == 0)
|
||||
return PARSE_REJECT;
|
||||
|
||||
/* src ip des pakets */
|
||||
printf("server found: %s\n", pkt_ntoa(pkt));
|
||||
|
||||
/* server zu interner liste hinzufuegen: (port1 = port, port2 = 0)*/
|
||||
server_add_pkt(gameid, pkt);
|
||||
|
||||
|
||||
/* server mit zwei ports zur liste hinzufuegen: */
|
||||
server_add(gameid, pkt->addr.sin_addr.s_addr, port1, port2);
|
||||
|
||||
return PARSE_ACCEPT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
19
src/client.c
19
src/client.c
|
@ -59,8 +59,9 @@ static pthread_mutex_t client_pkt_list_lock = PTHREAD_MUTEX_INITIALIZER;
|
|||
* @param *unused
|
||||
* @return true wenn das paket noch nicht voll ist
|
||||
*/
|
||||
static inline int client_pkt_not_full(const struct client_pkt *cpkt, void *unused) {
|
||||
return (cpkt->size > (MAX_PKT_LEN - HLSW_ENTRY_LEN));
|
||||
static inline int client_pkt_not_full(const struct client_pkt *cpkt, void *unused)
|
||||
{
|
||||
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
|
||||
* @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;
|
||||
|
||||
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);
|
||||
cpkt->size = HLSW_HEADER_LEN;
|
||||
|
||||
/* am anfang eingliedern! */
|
||||
/* am anfang eingliedern! (suche nach freien paket schneller) */
|
||||
list_add(&cpkt->list, list);
|
||||
}
|
||||
return cpkt;
|
||||
|
@ -95,7 +97,8 @@ static struct client_pkt * client_pkt_add_real(struct list_head *list) {
|
|||
* @param *server pointer den server
|
||||
* @return false bei fehler
|
||||
*/
|
||||
int client_pkt_add(struct game_server *server) {
|
||||
int client_pkt_add(struct game_server *server)
|
||||
{
|
||||
struct client_pkt *cpkt;
|
||||
|
||||
/* sucht ein freies paket, oder erzeugt eins */
|
||||
|
@ -117,7 +120,8 @@ int client_pkt_add(struct game_server *server) {
|
|||
*
|
||||
* @return true
|
||||
*/
|
||||
int client_pkt_commit() {
|
||||
int client_pkt_commit()
|
||||
{
|
||||
struct list_head old_list, *cpkt, *tmp;
|
||||
|
||||
/* wenn die liste leer ist, nur HLSW-header verschicken */
|
||||
|
@ -148,7 +152,8 @@ int client_pkt_commit() {
|
|||
* client_handler()
|
||||
* empfaengt und beantwortet die HLSW anfragen der clients
|
||||
*/
|
||||
void client_handler(void) {
|
||||
void client_handler(void)
|
||||
{
|
||||
struct client_pkt *cpkt;
|
||||
struct sockaddr_in dst;
|
||||
int sock, i;
|
||||
|
|
24
src/config.c
24
src/config.c
|
@ -40,7 +40,8 @@ static LIST_HEAD(config_list);
|
|||
*
|
||||
* @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;
|
||||
|
||||
if (!name)
|
||||
|
@ -66,7 +67,8 @@ static struct conf_section * config_add_section(char *name) {
|
|||
* @param *parameter wert der option
|
||||
* @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;
|
||||
|
||||
if (!section || !option || !parameter)
|
||||
|
@ -88,7 +90,8 @@ static int config_add_tupel(struct conf_section *section, char *option, char *pa
|
|||
* config_free()
|
||||
* entfernt die config_liste aus dem Speicher
|
||||
*/
|
||||
static void config_free() {
|
||||
static void config_free()
|
||||
{
|
||||
struct conf_section *section, *section_tmp;
|
||||
struct conf_tupel *tupel, *tupel_tmp;
|
||||
|
||||
|
@ -111,7 +114,8 @@ static void config_free() {
|
|||
* @param *config filename des configfiles
|
||||
* @return false bei fehler
|
||||
*/
|
||||
int config_parse(char *config) {
|
||||
int config_parse(char *config)
|
||||
{
|
||||
struct conf_section *section = NULL;
|
||||
FILE *fz;
|
||||
int i = 0, ret = 1;
|
||||
|
@ -189,7 +193,8 @@ int config_parse(char *config) {
|
|||
* @param *name name der section
|
||||
* @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;
|
||||
|
||||
list_for_each_entry(section, &config_list, list) {
|
||||
|
@ -208,7 +213,8 @@ struct conf_section * config_get_section(char *name) {
|
|||
* @param *option option name
|
||||
* @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;
|
||||
|
||||
list_for_each_entry(tupel, §ion->tupel, list) {
|
||||
|
@ -227,7 +233,8 @@ char * config_get_parameter(struct conf_section *section, char *option) {
|
|||
* @param *def default string
|
||||
* @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;
|
||||
char *ret;
|
||||
|
||||
|
@ -247,7 +254,8 @@ char * config_get_string(char *section, char *option, char *def) {
|
|||
* @param *def default wert
|
||||
* @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;
|
||||
|
||||
ret = config_get_string(section, option, NULL);
|
||||
|
|
|
@ -37,9 +37,10 @@ static FILE *log_fd = NULL;
|
|||
*
|
||||
* @todo code vereinfachen?
|
||||
*/
|
||||
void log_print(const char *fmt, ...) {
|
||||
void log_print(const char *fmt, ...)
|
||||
{
|
||||
va_list az;
|
||||
char buffer[256];
|
||||
char *buffer = malloc(8192);
|
||||
|
||||
va_start(az, fmt);
|
||||
vsprintf(buffer, fmt, az);
|
||||
|
@ -69,13 +70,15 @@ void log_print(const char *fmt, ...) {
|
|||
}
|
||||
}
|
||||
errno = 0;
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* log_close()
|
||||
* schliesst das logfile
|
||||
*/
|
||||
static void log_close() {
|
||||
static void log_close()
|
||||
{
|
||||
fclose(log_fd);
|
||||
}
|
||||
|
||||
|
@ -86,7 +89,8 @@ static void log_close() {
|
|||
* @param logfile filename des logfiles
|
||||
* @return false bei fehler
|
||||
*/
|
||||
int log_init(char *logfile) {
|
||||
int log_init(char *logfile)
|
||||
{
|
||||
if ((log_fd = fopen(logfile, "a" )) == NULL) {
|
||||
log_print("log_open('%s'): %s", logfile);
|
||||
return 0;
|
||||
|
|
13
src/main.c
13
src/main.c
|
@ -37,11 +37,12 @@ static struct option opts[] = {
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pthread_t thread1, thread2, thread3;
|
||||
int arg = 0, code = 0, debug = 0;
|
||||
char *config = NULL, *user = NULL, *logfile;
|
||||
|
||||
|
||||
while (code != -1) {
|
||||
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);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
if (setgid(pwl->pw_gid) || setuid(pwl->pw_uid)) {
|
||||
log_print("setgid/setuid");
|
||||
exit(-1);
|
||||
|
@ -102,13 +103,13 @@ int main(int argc, char *argv[]) {
|
|||
/* start logging */
|
||||
if (!log_init(logfile))
|
||||
exit(-1);
|
||||
|
||||
|
||||
/* zum daemon mutieren */
|
||||
daemon(-1, 0);
|
||||
}
|
||||
|
||||
|
||||
log_print("hlswmaster started (user: %s, pid: %d)", getpwuid(getuid())->pw_name, getpid());
|
||||
|
||||
|
||||
/* init scan engine */
|
||||
if (!scan_init())
|
||||
exit(-1);
|
||||
|
|
28
src/plugin.c
28
src/plugin.c
|
@ -40,7 +40,8 @@ static pthread_mutex_t plugin_lock = PTHREAD_MUTEX_INITIALIZER;
|
|||
* @param *name filename des plugins
|
||||
* @return false on error
|
||||
*/
|
||||
int plugin_load(char *name) {
|
||||
int plugin_load(char *name)
|
||||
{
|
||||
struct hlswmaster_plugin *plugin;
|
||||
void *tmp;
|
||||
struct conf_section *section;
|
||||
|
@ -82,7 +83,8 @@ int plugin_load(char *name) {
|
|||
*
|
||||
* @return false on error
|
||||
*/
|
||||
int plugin_load_all() {
|
||||
int plugin_load_all()
|
||||
{
|
||||
struct conf_section *section;
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
|
@ -102,7 +104,8 @@ int plugin_load_all() {
|
|||
*
|
||||
* @return false on error
|
||||
*/
|
||||
int plugin_unload_all() {
|
||||
int plugin_unload_all()
|
||||
{
|
||||
struct hlswmaster_plugin *plugin, *tmp;
|
||||
|
||||
pthread_mutex_lock(&plugin_lock);
|
||||
|
@ -125,7 +128,8 @@ int plugin_unload_all() {
|
|||
*
|
||||
* @return true
|
||||
*/
|
||||
int plugins_scan(void) {
|
||||
int plugins_scan(void)
|
||||
{
|
||||
struct hlswmaster_plugin *plugin;
|
||||
|
||||
pthread_mutex_lock(&plugin_lock);
|
||||
|
@ -144,22 +148,25 @@ int plugins_scan(void) {
|
|||
* bis ein Plugin das Paket annimmt
|
||||
*
|
||||
* @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;
|
||||
int retval;
|
||||
|
||||
pthread_mutex_lock(&plugin_lock);
|
||||
list_for_each_entry(plugin, &plugin_list, list) {
|
||||
/* wenn vorhanden die parse funktion aufrufen */
|
||||
if (plugin->parse && plugin->parse(pkt)) {
|
||||
if (plugin->parse && (retval = plugin->parse(pkt))) {
|
||||
pthread_mutex_unlock(&plugin_lock);
|
||||
return 1;
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
* @return true
|
||||
*/
|
||||
int plugins_gc(unsigned long timeout) {
|
||||
int plugins_gc(unsigned long timeout)
|
||||
{
|
||||
struct hlswmaster_plugin *plugin;
|
||||
|
||||
pthread_mutex_lock(&plugin_lock);
|
||||
|
|
|
@ -46,10 +46,11 @@
|
|||
* @param size groesse der daten
|
||||
* @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;
|
||||
int ret = 1;
|
||||
|
||||
|
||||
while (portarr && portarr->portlo) {
|
||||
for (port = portarr->portlo; port <= portarr->porthi; port++)
|
||||
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
|
||||
* @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;
|
||||
while (portarr && portarr->portlo) {
|
||||
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 *search daten nach denen gesucht wird
|
||||
* @param size laenge der daten
|
||||
* @return true wenn gleich
|
||||
* @return false wenn gleich
|
||||
*
|
||||
* @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)
|
||||
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 *search daten nach denen gesucht wird
|
||||
* @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) {
|
||||
if (offset >= pkt->size)
|
||||
return NULL;
|
||||
int pkt_memmem(struct net_pkt *pkt, unsigned int offset, char *search, unsigned int size)
|
||||
{
|
||||
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)
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -140,7 +173,8 @@ int server_add_pkt(unsigned int gameid, struct net_pkt *pkt) {
|
|||
* @param *pkt daten vom gameserver
|
||||
* @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);
|
||||
}
|
||||
|
||||
|
@ -151,31 +185,121 @@ char * pkt_ntoa(struct net_pkt *pkt) {
|
|||
* @param *pkt daten vom gameserver
|
||||
* @return portnummer
|
||||
*/
|
||||
unsigned short pkt_getport(struct net_pkt *pkt) {
|
||||
unsigned short pkt_getport(struct net_pkt *pkt)
|
||||
{
|
||||
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
|
||||
*
|
||||
* @param *pkt daten vom gameserver
|
||||
* @param *p pointer auf den begin des integers
|
||||
* @return wert des integers oder 0 bei fehler
|
||||
* @param offset offset auf den begin des integers
|
||||
* @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 val = 0;
|
||||
void *max = ((void *)pkt->buf + pkt->size);
|
||||
char *c = p;
|
||||
int pkt_parse_int(struct net_pkt *pkt, unsigned int offset, int *val)
|
||||
{
|
||||
unsigned char *max = pkt->buf + pkt->size;
|
||||
unsigned char *c = pkt->buf + offset;
|
||||
|
||||
/* untere grenze abtesten */
|
||||
if ((void *)pkt->buf > p || p > max)
|
||||
return 0;
|
||||
if (pkt->buf > c || c > max)
|
||||
return -1;
|
||||
|
||||
*val = 0;
|
||||
|
||||
/* ziffern einlesen */
|
||||
while (isdigit(*c) && (void *)c < max)
|
||||
val = (val * 10) + (*c++ - 0x30);
|
||||
while (isdigit(*c) && c < max)
|
||||
*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;
|
||||
}
|
||||
|
||||
|
|
167
src/scanner.c
167
src/scanner.c
|
@ -27,22 +27,39 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "netpkt.h"
|
||||
#include "configfile.h"
|
||||
#include "hlswmaster.h"
|
||||
#include "plugin.h"
|
||||
#include "plugin_helper.h"
|
||||
|
||||
#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 */
|
||||
static LIST_HEAD(serverlist);
|
||||
|
||||
/** sichert die interne serverliste */
|
||||
static pthread_mutex_t serverlist_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* scan socket */
|
||||
/** scan socket */
|
||||
static int scan_sock;
|
||||
|
||||
/**
|
||||
|
@ -53,7 +70,8 @@ static int scan_sock;
|
|||
* @param *b gameserver 2
|
||||
* @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 &&
|
||||
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 ip ip des servers
|
||||
* @param port1 erster port
|
||||
* @param port2 zweiter port
|
||||
* @param port2 zweiter port
|
||||
* @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;
|
||||
|
||||
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));
|
||||
list_add_tail(&nserver->list, &serverlist);
|
||||
}
|
||||
|
||||
|
||||
/* modtime anpassen */
|
||||
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
|
||||
*/
|
||||
static void serverlist_refresh(long timeout) {
|
||||
static void serverlist_refresh(long timeout)
|
||||
{
|
||||
struct game_server *server, *tmp;
|
||||
long now = time(NULL);
|
||||
|
||||
|
@ -151,35 +171,87 @@ static void serverlist_refresh(long timeout) {
|
|||
* @param size groesse der daten
|
||||
* @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;
|
||||
int ret = 1;
|
||||
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(dstport);
|
||||
addr.sin_addr.s_addr = (dstip ? dstip->s_addr : 0xFFFFFFFF);
|
||||
|
||||
|
||||
if (sendto(scan_sock, buf, size, 0, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
log_print("scan_send(): sendto()");
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
|
||||
usleep(10000);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* scan_control()
|
||||
* triggert den scan der plugins
|
||||
* arbeitet dann die sender queue ab
|
||||
* triggert den gc der plugins
|
||||
* scan_receive_real()
|
||||
* arbeitet die receive queue ab
|
||||
*/
|
||||
void scan_control(void) {
|
||||
struct net_pkt *pkt, *tmp;
|
||||
long now;
|
||||
void scan_receive_real(void)
|
||||
{
|
||||
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;
|
||||
int plugin_timeout, list_timeout, list_refresh, scan_interval;
|
||||
|
||||
int cnt;
|
||||
long now;
|
||||
|
||||
plugin_timeout = config_get_int("global", "plugin_timeout", 30);
|
||||
list_timeout = config_get_int("global", "serverlist_timeout", 30);
|
||||
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_timeout: %ds", list_timeout);
|
||||
log_print(" plugin_timeout: %d", plugin_timeout);
|
||||
|
||||
|
||||
while (1) {
|
||||
now = time(NULL);
|
||||
|
||||
|
||||
/* interne plugin daten aufraeumen */
|
||||
if (last_plugin_gc + plugin_timeout < now) {
|
||||
last_plugin_gc = now;
|
||||
|
@ -205,29 +277,36 @@ void scan_control(void) {
|
|||
last_list_refresh = now;
|
||||
serverlist_refresh(list_timeout);
|
||||
}
|
||||
|
||||
|
||||
/* neuen scan ausloesen */
|
||||
if (last_scan + scan_interval < now) {
|
||||
last_scan = now;
|
||||
plugins_scan();
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
/* empfangene daten parsen */
|
||||
sem_getvalue(&rxlist_sem, &cnt);
|
||||
if (cnt > 0)
|
||||
scan_receive_real();
|
||||
|
||||
usleep(500000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* scan_receive()
|
||||
* wartet auf serverantworten und uebergibt die pakete den
|
||||
* plugins zur auswertung
|
||||
* wartet auf serverantworten und uebergibt die pakete der
|
||||
* receive queue
|
||||
*/
|
||||
void scan_receive(void) {
|
||||
void scan_receive(void)
|
||||
{
|
||||
struct net_pkt *pkt;
|
||||
struct rx_entry *rx;
|
||||
fd_set fdsel, fdcpy;
|
||||
int recvsize, i;
|
||||
|
||||
log_print("thread_start: scan_receiver");
|
||||
|
||||
|
||||
FD_ZERO(&fdsel);
|
||||
FD_SET(scan_sock, &fdsel);
|
||||
|
||||
|
@ -235,13 +314,11 @@ void scan_receive(void) {
|
|||
memcpy(&fdcpy, &fdsel, sizeof(fdsel));
|
||||
select(FD_SETSIZE, &fdcpy, NULL, NULL, NULL);
|
||||
|
||||
ioctl(scan_sock, FIONREAD, &recvsize);
|
||||
|
||||
if (recvsize <= 0) {
|
||||
log_print("scan_receive(): drop short packet");
|
||||
if (ioctl(scan_sock, FIONREAD, &recvsize) == -1) {
|
||||
log_print("scan_receive(): ioctl()");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!(pkt = malloc(sizeof(struct net_pkt) + recvsize))) {
|
||||
log_print("scan_receive(): malloc()");
|
||||
continue;
|
||||
|
@ -250,29 +327,40 @@ void scan_receive(void) {
|
|||
i = sizeof(struct sockaddr_in);
|
||||
pkt->size = recvfrom(scan_sock, pkt->buf, recvsize, 0, (struct sockaddr *)&pkt->addr, &i);
|
||||
|
||||
if (!plugins_parse(pkt)) {
|
||||
log_print("scan_receive(): unknown packet: %s:%d size:%d",
|
||||
inet_ntoa(pkt->addr.sin_addr), ntohs(pkt->addr.sin_port), pkt->size);
|
||||
if (pkt->size == 0) {
|
||||
free(pkt);
|
||||
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
|
||||
*/
|
||||
static void scan_close() {
|
||||
static void scan_close()
|
||||
{
|
||||
close(scan_sock);
|
||||
sem_destroy(&rxlist_sem);
|
||||
}
|
||||
|
||||
/**
|
||||
* scan_init()
|
||||
* initialisiert den socket fuer den server scan
|
||||
* initialisiert die rxlist semaphore
|
||||
*
|
||||
* @return false on error
|
||||
*/
|
||||
int scan_init() {
|
||||
int scan_init()
|
||||
{
|
||||
struct sockaddr_in dst;
|
||||
int i = 1, port;
|
||||
char *ip;
|
||||
|
@ -298,12 +386,15 @@ int scan_init() {
|
|||
log_print("scan_init(): setsockopt()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (atexit(scan_close) != 0) {
|
||||
log_print("scan_init(): atexit()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print("scan socket initialized (%s:%d)", ip, port);
|
||||
|
||||
sem_init(&rxlist_sem, 0, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,8 @@ static char *id2name[] = {
|
|||
|
||||
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 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);
|
||||
|
||||
} 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,
|
||||
((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;
|
||||
|
||||
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||
|
@ -110,7 +112,8 @@ static int scan_init() {
|
|||
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) {
|
||||
perror("sendto()");
|
||||
return -1;
|
||||
|
@ -119,7 +122,8 @@ static int scan_transmit(struct sockaddr_in *dst) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int scan_receive() {
|
||||
static int scan_receive()
|
||||
{
|
||||
struct sockaddr_in src;
|
||||
struct timeval tv;
|
||||
fd_set fdsel;
|
||||
|
@ -171,7 +175,8 @@ static struct option opts[] = {
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr_in dst;
|
||||
int arg = 0, code = 0;
|
||||
int freq = -1;
|
||||
|
|
Loading…
Reference in New Issue