test version with the fixed bugs found by Luigi Auriemma

origin
stpohle 19 years ago
parent c7743b0538
commit 072107d037

@ -1,6 +1,23 @@
$Id: ChangeLog,v 1.107 2006/07/30 11:44:57 stpohle Exp $ $Id: ChangeLog,v 1.108 2006/08/13 21:26:50 stpohle Exp $
Version 0.11.7 (still in progress) Version 0.11.7 (still in progress)
- Testing: Security Problems found by Luigi Auriemma
Bugs: A] memcpy crash in rscache_add
B] information disclosure in send_pkg
C] simple error message termination
for more informations look here:
http://aluigi.altervista.org/adv/bcloneboom-adv.txt
Solutions to
A) rewrote the whole resend cache system, also send_mapinfo needed a
bad workaround for a bug i couldn't find out.
B) made sure that the size of a packet is set right before send over
the network. Found only the function (do_gameinfo) where something
like this occured.
do_pkg will also check the size of the incoming packet with the
p->h.len value.
C) accept the error packets only from the server of a game. Since only the
server will send such type of packets.
- Fixed: Security Problem found by Stefan Cornelius. - Fixed: Security Problem found by Stefan Cornelius.
For more information look here: For more information look here:
https://lists.uni-koeln.de/pipermail/sec-info/Week-of-Mon-20060313/006561.html https://lists.uni-koeln.de/pipermail/sec-info/Week-of-Mon-20060313/006561.html

@ -68,8 +68,7 @@ project.configure.options=
anjuta.program.arguments= anjuta.program.arguments=
preferences.build.option.jobs=0 preferences.build.option.jobs=0
preferences.build.option.silent=0 preferences.build.option.silent=0
preferences.build.option.autosave=0 preferences.build.option.autosave=1
preferences.anjuta.make.options=-k
preferences.make=make preferences.make=make
preferences.build.option.keep.going=0 preferences.build.option.keep.going=0
preferences.build.option.warn.undef=0 preferences.build.option.warn.undef=0

@ -1,4 +1,4 @@
/* $Id: basic.h,v 1.34 2006/07/30 11:44:57 stpohle Exp $ */ /* $Id: basic.h,v 1.35 2006/08/13 21:26:50 stpohle Exp $ */
/* basic types which we need everywhere */ /* basic types which we need everywhere */
#ifndef _BC_BASIC_H_ #ifndef _BC_BASIC_H_
@ -192,7 +192,7 @@ enum _help_page {
struct { struct {
Sint16 x; Sint16 x;
Sint16 y; Sint16 y;
} typedef _point; } __attribute__((packed)) typedef _point;
struct { struct {

@ -1,4 +1,4 @@
/* $Id: network.h,v 1.23 2004/12/26 04:19:21 stpohle Exp $ /* $Id: network.h,v 1.24 2006/08/13 21:26:50 stpohle Exp $
* network.h file... for everything what have to do with the network stuff * network.h file... for everything what have to do with the network stuff
*/ */
@ -9,7 +9,7 @@
#define _NETWORK_H_ #define _NETWORK_H_
#define MAX_UDPDATA 1024 #define MAX_UDPDATA 1024
#define PKG_RESENDCACHE_SIZE (64*1024) #define PKG_RESENDCACHE_SIZE 64
#define PKG_IN_INDEX_NUM 512 #define PKG_IN_INDEX_NUM 512
#define RESENDCACHE_TIMEOUT 400 #define RESENDCACHE_TIMEOUT 400
#define RESENDCACHE_TIMEOUT_MENU 3000 #define RESENDCACHE_TIMEOUT_MENU 3000
@ -61,7 +61,7 @@ struct { // this holds the network data
char host[LEN_SERVERNAME]; char host[LEN_SERVERNAME];
char port[LEN_PORT]; char port[LEN_PORT];
struct _sockaddr sAddr; struct _sockaddr sAddr;
signed char pl_nr; // pl_nr so we know it in the pkgcahce. signed char pl_nr; // pl_nr so we know it in the pkgcache.
} typedef _net_addr; } typedef _net_addr;

@ -1,4 +1,4 @@
/* $Id: packets.h,v 1.32 2005/03/27 01:31:50 stpohle Exp $ /* $Id: packets.h,v 1.33 2006/08/13 21:26:50 stpohle Exp $
* network packets.. */ * network packets.. */
#ifndef _PACKETS_H_ #ifndef _PACKETS_H_
@ -55,47 +55,40 @@ struct pkgheader {
unsigned char flags; unsigned char flags;
Sint16 id; Sint16 id;
Sint16 len; Sint16 len;
}; } __attribute__((packed));
struct pkg { struct pkg {
struct pkgheader h; struct pkgheader h;
char data[0]; char data[0];
}; } __attribute__((packed));
struct pkg_bcmservchat { struct pkg_bcmservchat {
char typ; char typ;
char data[128]; char data[128];
}; } __attribute__((packed));
struct pkg_tunneldata { struct pkg_tunneldata {
struct pkgheader h; struct pkgheader h;
signed char tunnel_nr; signed char tunnel_nr;
_point target; _point target;
}; } __attribute__((packed));
struct pkg_pkgack { struct pkg_pkgack {
struct pkgheader h; struct pkgheader h;
char typ; char typ;
Sint16 id; Sint16 id;
}; } __attribute__((packed));
struct pkg_ping { struct pkg_ping {
struct pkgheader h; struct pkgheader h;
Sint32 data; Sint32 data;
}; } __attribute__((packed));
struct pkg_contest { struct pkg_contest {
struct pkgheader h; struct pkgheader h;
signed char from; signed char from;
signed char to; signed char to;
}; } __attribute__((packed));
struct pkg_teamdata { struct pkg_teamdata {
struct pkgheader h; struct pkgheader h;
@ -103,14 +96,13 @@ struct pkg_teamdata {
signed char col; signed char col;
signed char wins; signed char wins;
char name[LEN_PLAYERNAME]; char name[LEN_PLAYERNAME];
}; } __attribute__((packed));
struct pkgdropitemelemt { struct pkgdropitemelemt {
signed char x; signed char x;
signed char y; signed char y;
unsigned char typ; unsigned char typ;
}; } __attribute__((packed));
struct pkg_dropitem { struct pkg_dropitem {
struct pkgheader h; struct pkgheader h;
@ -118,8 +110,7 @@ struct pkg_dropitem {
signed char pl_nr; // playernumber -1 if the server jsut dropped something signed char pl_nr; // playernumber -1 if the server jsut dropped something
unsigned char count; // number of elements unsigned char count; // number of elements
struct pkgdropitemelemt items[0]; // elements struct pkgdropitemelemt items[0]; // elements
}; } __attribute__((packed));
struct pkg_field { struct pkg_field {
struct pkgheader h; struct pkgheader h;
@ -134,17 +125,15 @@ struct pkg_field {
unsigned char frame; unsigned char frame;
unsigned char bomb_b; unsigned char bomb_b;
unsigned char bomb_p; unsigned char bomb_p;
} ex[4]; // count up every explosion there is on this field for ever direction } ex[4]; // count up every explosion there is on this field for ever direction
Sint32 ex_nr; // number to identify the explosion. Sint32 ex_nr; // number to identify the explosion.
}; } __attribute__((packed));
struct pkg_error { struct pkg_error {
struct pkgheader h; struct pkgheader h;
unsigned char nr; unsigned char nr;
char text[128]; char text[128];
}; } __attribute__((packed));
struct pkg_servermode { struct pkg_servermode {
struct pkgheader h; struct pkgheader h;
@ -164,8 +153,7 @@ struct pkg_servermode {
signed char p_nr; /* if the server sends this to a client... signed char p_nr; /* if the server sends this to a client...
it will be the clients in_nr number it will be the clients in_nr number
(-1) for not set */ (-1) for not set */
}; } __attribute__((packed));
struct pkg_joingame { struct pkg_joingame {
struct pkgheader h; struct pkgheader h;
@ -175,8 +163,7 @@ struct pkg_joingame {
signed char secondplayer; // this is the second player signed char secondplayer; // this is the second player
char name[LEN_PLAYERNAME]; char name[LEN_PLAYERNAME];
char password[LEN_PASSWORD]; char password[LEN_PASSWORD];
}; } __attribute__((packed));
struct pkg_playerid { struct pkg_playerid {
struct pkgheader h; struct pkgheader h;
@ -192,8 +179,7 @@ struct pkg_playerid {
signed char team_nr; // team number signed char team_nr; // team number
Sint16 team_points; // team points Sint16 team_points; // team points
Sint16 team_wins; // team wins Sint16 team_wins; // team wins
}; } __attribute__((packed));
struct pkg_playerdata { struct pkg_playerdata {
struct pkgheader h; struct pkgheader h;
@ -210,8 +196,7 @@ struct pkg_playerdata {
unsigned char frame; unsigned char frame;
signed char dead_by; signed char dead_by;
signed char ready; // if the player is ready for the game signed char ready; // if the player is ready for the game
}; } __attribute__((packed));
struct pkg_playermove { struct pkg_playermove {
struct pkgheader h; struct pkgheader h;
@ -221,8 +206,7 @@ struct pkg_playermove {
Sint16 speed; Sint16 speed;
Sint16 tunnelto; Sint16 tunnelto;
_point pos; _point pos;
}; } __attribute__((packed));
struct pkg_bombdata { struct pkg_bombdata {
struct pkgheader h; struct pkgheader h;
@ -237,50 +221,45 @@ struct pkg_bombdata {
Uint16 destx; Uint16 destx;
Uint16 desty; Uint16 desty;
Sint16 speed; Sint16 speed;
}; } __attribute__((packed));
struct pkg_quit { struct pkg_quit {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
signed char new_server; signed char new_server;
}; } __attribute__((packed));
struct pkg_getfield { struct pkg_getfield {
struct pkgheader h; struct pkgheader h;
signed char line; signed char line;
}; } __attribute__((packed));
struct pkg_playerstatus { struct pkg_playerstatus {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
signed char net_istep; signed char net_istep;
signed char status; signed char status;
}; } __attribute__((packed));
struct pkg_fieldline { struct pkg_fieldline {
struct pkgheader h; struct pkgheader h;
signed char line; signed char line;
unsigned char type[MAX_FIELDSIZE_X]; unsigned char type[MAX_FIELDSIZE_X];
unsigned char special[MAX_FIELDSIZE_X]; unsigned char special[MAX_FIELDSIZE_X];
}; } __attribute__((packed));
struct pkg_ill { struct pkg_ill {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
Sint32 to[PI_max]; Sint32 to[PI_max];
}; } __attribute__((packed));
struct pkg_updateinfo { struct pkg_updateinfo {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
unsigned char step[MAX_PLAYERS]; unsigned char step[MAX_PLAYERS];
unsigned char status[MAX_PLAYERS]; unsigned char status[MAX_PLAYERS];
}; } __attribute__((packed));
struct pkg_respawn { struct pkg_respawn {
struct pkgheader h; struct pkgheader h;
@ -288,28 +267,24 @@ struct pkg_respawn {
signed char x; signed char x;
signed char y; signed char y;
unsigned char state; unsigned char state;
}; } __attribute__((packed));
struct pkg_getplayerdata { struct pkg_getplayerdata {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
}; } __attribute__((packed));
struct pkg_chat { struct pkg_chat {
struct pkgheader h; struct pkgheader h;
char text[128]; char text[128];
}; } __attribute__((packed));
struct pkg_special { struct pkg_special {
struct pkgheader h; struct pkgheader h;
signed char pl_nr; signed char pl_nr;
Sint32 ex_nr; Sint32 ex_nr;
unsigned char typ; unsigned char typ;
}; } __attribute__((packed));
struct pkg_mapinfo { struct pkg_mapinfo {
struct pkgheader h; struct pkgheader h;
@ -330,8 +305,7 @@ struct pkg_mapinfo {
unsigned char start_range; unsigned char start_range;
char start_speed[8]; // to make sure there will be no difference char start_speed[8]; // to make sure there will be no difference
char bomb_tickingtime[8]; // to make sure there will be no difference char bomb_tickingtime[8]; // to make sure there will be no difference
}; } __attribute__((packed));
/* this packet type is also used in netsrvlist.c */ /* this packet type is also used in netsrvlist.c */
struct pkg_gameinfo { struct pkg_gameinfo {
@ -343,34 +317,29 @@ struct pkg_gameinfo {
char version[LEN_VERSION]; char version[LEN_VERSION];
char broadcast; char broadcast;
signed char password; /* if password == -1, we do a game request */ signed char password; /* if password == -1, we do a game request */
}; } __attribute__((packed));
/* structures needed by the resend cache */
struct _rscache_entry { struct _rscache_entry {
signed char pl_nr; // playernumber to whom this data should go
Sint16 len; // size of the entry
Uint32 timestamp; // pointer to the timestamp Uint32 timestamp; // pointer to the timestamp
signed char retry; // retry's how many times we tryed this signed char retry; // retry's how many times we tryed this
_net_addr addr; // pointer to the address _net_addr addr; // the address
struct pkg packet; // pointer to the packet struct pkg packet; // the packet
}; char data[MAX_UDPDATA]; // packet data without header
} __attribute__((packed));
struct _resend_cache { struct _resend_cache {
char *data; // will hold the pointer to out cache struct _rscache_entry entry[PKG_RESENDCACHE_SIZE]; // pointer to our data
struct _rscache_entry *entry; // pointer to our data int count;
Sint32 fill; // how much we have used
}; };
struct _inpkg_index { struct _inpkg_index {
signed char pl_nr; signed char pl_nr;
unsigned char typ; unsigned char typ;
Sint16 id; Sint16 id;
}; };
extern void do_error (struct pkg_error *data, _net_addr *addr);
extern int do_error (struct pkg_error *data, _net_addr *addr);
extern void do_playerid (struct pkg_playerid *p_id, _net_addr *addr); extern void do_playerid (struct pkg_playerid *p_id, _net_addr *addr);
extern void do_servermode (struct pkg_servermode *s_mod, _net_addr *addr); extern void do_servermode (struct pkg_servermode *s_mod, _net_addr *addr);
extern void do_joingame (struct pkg_joingame *p_jg, _net_addr * addr); extern void do_joingame (struct pkg_joingame *p_jg, _net_addr * addr);
@ -387,7 +356,7 @@ extern void do_getplayerdata (struct pkg_getplayerdata *gp_dat, _net_addr *addr)
extern void do_playerstatus (struct pkg_playerstatus *gp_dat, _net_addr *addr); extern void do_playerstatus (struct pkg_playerstatus *gp_dat, _net_addr *addr);
extern void do_pkgack (struct pkg_pkgack *p_ack, _net_addr *addr); extern void do_pkgack (struct pkg_pkgack *p_ack, _net_addr *addr);
extern void do_chat (struct pkg_chat *chat_pkg, _net_addr *addr); extern void do_chat (struct pkg_chat *chat_pkg, _net_addr *addr);
extern int do_pkg (struct pkg *packet, _net_addr *addr); extern void do_pkg (struct pkg *packet, _net_addr *addr, int len);
extern void do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr *addr); extern void do_bcmservchat (struct pkg_bcmservchat *packet, _net_addr *addr);
extern void do_ill (struct pkg_ill *ill_pkg, _net_addr *addr); extern void do_ill (struct pkg_ill *ill_pkg, _net_addr *addr);
extern void do_special (struct pkg_special *sp_pkg, _net_addr *addr); extern void do_special (struct pkg_special *sp_pkg, _net_addr *addr);
@ -434,12 +403,11 @@ extern int inpkg_check (unsigned char typ, short int id, _net_addr *addr);
extern void inpkg_delplayer (int pl_nr); extern void inpkg_delplayer (int pl_nr);
/* this functions will be defined in pkgcache.c */ /* this functions will be defined in pkgcache.c */
extern int rscache_add (_net_addr *addr, struct pkg *packet); extern void rscache_init ();
extern void rscache_del (); extern void rscache_add (_net_addr *addr, struct pkg *packet);
extern int rscache_getpos (_net_addr *addr, unsigned char typ, short int id); extern void rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id);
extern int rscache_getcurlen ();
extern void rscache_loop (); extern void rscache_loop ();
extern struct _resend_cache resend_cache; extern struct _resend_cache rscache;
#endif #endif

@ -1,4 +1,4 @@
/* $Id: configuration.c,v 1.78 2006/08/13 21:20:54 patty21 Exp $ /* $Id: configuration.c,v 1.79 2006/08/13 21:26:50 stpohle Exp $
* configuration */ * configuration */
#include <SDL.h> #include <SDL.h>
@ -93,8 +93,7 @@ config_init (int argc, char **argv)
sprintf (bman.port, "%d", DEFAULT_UDPPORT); sprintf (bman.port, "%d", DEFAULT_UDPPORT);
sprintf (bman.ogcserver, DEFAULT_GAMECACHE); sprintf (bman.ogcserver, DEFAULT_GAMECACHE);
sprintf (bman.ogc_port, DEFAULT_GAMECACHEPORT); sprintf (bman.ogc_port, DEFAULT_GAMECACHEPORT);
resend_cache.data = NULL; rscache.count = 0;
resend_cache.fill = -1;
bman.notifygamemaster = 1; bman.notifygamemaster = 1;
bman.broadcast = 1; bman.broadcast = 1;
bman.autostart = AUTOSTART; bman.autostart = AUTOSTART;

@ -40,7 +40,7 @@ void d_playerdetail (char *head) {
d_printf ("---------------> %s\n", head); d_printf ("---------------> %s\n", head);
d_printf ("Nr Name GFX Sta Pkt Win Team net_flag [Addr]\n"); d_printf ("Nr Name GFX Sta Pkt Win Team net_flag [Addr]\n");
for (i = 0; i < MAX_PLAYERS; i++) for (i = 0; i < MAX_PLAYERS; i++)
d_printf ("%2d %16s %3d %3d %3d %3d %4d %3d [%s:%s]\n",i, players[i].name, players[i].gfx_nr, players[i].state, players[i].points, players[i].wins, players[i].team_nr, players[i].net.flags, players[i].net.addr.host, players[i].net.addr.port); d_printf ("%2d %16s %3d %3d %3d %3d %4d %3d %p[%s:%s]\n",i, players[i].name, players[i].gfx_nr, players[i].state, players[i].points, players[i].wins, players[i].team_nr, players[i].net.flags, players[i].net.addr.host, &players[i].net.addr, players[i].net.addr.port);
}; };

@ -1,4 +1,4 @@
/* $Id: network.c,v 1.76 2005/08/07 17:46:21 stpohle Exp $ */ /* $Id: network.c,v 1.77 2006/08/13 21:26:50 stpohle Exp $ */
/* /*
network routines. network routines.
*/ */
@ -133,9 +133,8 @@ network_init ()
} }
// we have got our socket.. so now allocate the memory for the resend_cache // we have got our socket.. so now allocate the memory for the resend_cache
resend_cache.data = (char *) malloc (PKG_RESENDCACHE_SIZE); rscache_init ();
resend_cache.fill = 0;
return 0; return 0;
}; };
@ -180,12 +179,6 @@ network_shutdown ()
udp_close (bman.sock); udp_close (bman.sock);
if (resend_cache.data != NULL)
free (resend_cache.data);
resend_cache.data = NULL;
resend_cache.fill = -1;
bman.p_nr = -1; bman.p_nr = -1;
bman.sock = -1; bman.sock = -1;
#ifdef _WIN32 #ifdef _WIN32
@ -250,7 +243,7 @@ network_loop ()
&addr.sAddr); &addr.sAddr);
while (inlen > 0) { while (inlen > 0) {
do_pkg (packet, &addr); do_pkg (packet, &addr, inlen);
// printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen); // printf ("Network : inlen (%d) typ (%d) Size (%d)\n", inlen, packet->typ, pkglen);
inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family); inlen = udp_get (bman.sock, data, MAX_UDPDATA, &addr.sAddr, bman.net_ai_family);

@ -61,19 +61,19 @@ send_error (_net_addr * addr, char *text)
}; };
int void
do_error (struct pkg_error *data, _net_addr * addr) do_error (struct pkg_error *data, _net_addr * addr)
{ {
d_printf ("Network Error from %s:%s : '%s'\n", addr->host, addr->port, data->text); d_printf ("Network Error from %s:%s : '%s'\n", addr->host, addr->port, data->text);
network_shutdown (); /* check if the packet comes from the server, the server
* never gets errormessages from a client, if a client has
menu_displaymessage ("Network Error", "Got Error from: %s:%s\nMessage:%s", addr->host, * some trouble the client will just disconnect */
addr->port, data->text); if (GT_MP_PTPS && addr->pl_nr == bman.p_servnr) {
if (data->nr == 1) menu_displaymessage ("Network Error", "Got Error from: %s:%s\nMessage:%s", addr->host,
return -1; addr->port, data->text);
else network_shutdown ();
return 0; }
}; };
@ -98,7 +98,7 @@ do_joingame (struct pkg_joingame *p_jg, _net_addr * addr)
vsu; vsu;
char text[255]; char text[255];
d_printf ("do_joingame (From:%s:%s Player(name:%s)\n", addr->host, addr->port, p_jg->name); d_printf ("do_joingame (From:%s:%s Player(name:%s) addr:%p\n", addr->host, addr->port, p_jg->name, addr);
sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu); sscanf (VERSION, "%d.%d.%d", &vma, &vmi, &vsu);
@ -185,9 +185,12 @@ do_joingame (struct pkg_joingame *p_jg, _net_addr * addr)
bman.players_nr_s++; bman.players_nr_s++;
/* send to the new client the servermode and the complete playerlist */ /* send to the new client the servermode and the complete playerlist */
printf ("ADDR: %p\n", addr);
if ((!p_jg->secondplayer) && !(players[j].net.flags & NETF_local2)) if ((!p_jg->secondplayer) && !(players[j].net.flags & NETF_local2))
send_mapinfo (addr); send_mapinfo (addr);
printf ("ADDR: %p\n", addr);
send_servermode (addr, i); // with this packet the client know it'S pl_nr send_servermode (addr, i); // with this packet the client know it'S pl_nr
printf ("ADDR: %p\n", addr);
addr->pl_nr = i; addr->pl_nr = i;
} }
@ -611,30 +614,32 @@ void
send_servermode (_net_addr * addr, int pl_nr) send_servermode (_net_addr * addr, int pl_nr)
{ {
struct pkg_servermode s_mod; struct pkg_servermode s_mod;
switch (bman.state) { switch (bman.state) {
case (GS_startup): case (GS_startup):
d_printf ("Send ServerMode : startup\n"); d_printf ("Send ServerMode : startup");
break; break;
case (GS_ready): case (GS_ready):
d_printf ("Send ServerMode : ready\n"); d_printf ("Send ServerMode : ready");
break; break;
case (GS_running): case (GS_running):
d_printf ("Send ServerMode : running\n"); d_printf ("Send ServerMode : running");
break; break;
case (GS_quit): case (GS_quit):
d_printf ("Send ServerMode : quit\n"); d_printf ("Send ServerMode : quit");
break; break;
case (GS_wait): case (GS_wait):
d_printf ("Send ServerMode : wait\n"); d_printf ("Send ServerMode : wait");
break; break;
case (GS_update): case (GS_update):
d_printf ("Send ServerMode : update\n"); d_printf ("Send ServerMode : update");
break; break;
default: default:
d_printf ("Send ServerMode : mode %d\n", s_mod.state); d_printf ("Send ServerMode : mode %d", s_mod.state);
} }
d_printf ("Addr: %p\n", addr);
s_mod.h.typ = PKG_servermode; s_mod.h.typ = PKG_servermode;
s_mod.h.len = HTON16 (sizeof (struct pkg_servermode)); s_mod.h.len = HTON16 (sizeof (struct pkg_servermode));
s_mod.h.flags = PKGF_ackreq; s_mod.h.flags = PKGF_ackreq;
@ -1467,10 +1472,7 @@ void
do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr) do_pkgack (struct pkg_pkgack *p_ack, _net_addr * addr)
{ {
d_printf ("do_pkgack (%s:%s)\n", addr->host, addr->port); d_printf ("do_pkgack (%s:%s)\n", addr->host, addr->port);
if (rscache_getpos (addr, p_ack->typ, NTOH16 (p_ack->id)) == -1) rscache_del (addr, p_ack->typ, NTOH16 (p_ack->id));
return;
rscache_del ();
}; };
@ -1573,7 +1575,9 @@ void
send_mapinfo (_net_addr * addr) send_mapinfo (_net_addr * addr)
{ {
struct pkg_mapinfo map_pkg; struct pkg_mapinfo map_pkg;
#ifndef BUG_MAPINFO
_net_addr *test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
#endif
map_pkg.h.typ = PKG_mapinfo; map_pkg.h.typ = PKG_mapinfo;
map_pkg.h.len = HTON16 (sizeof (struct pkg_mapinfo)); map_pkg.h.len = HTON16 (sizeof (struct pkg_mapinfo));
map_pkg.h.flags = PKGF_ackreq; map_pkg.h.flags = PKGF_ackreq;
@ -1589,17 +1593,25 @@ send_mapinfo (_net_addr * addr)
map_pkg.sp_push = map.sp_push; map_pkg.sp_push = map.sp_push;
map_pkg.start_bombs = bman.start_bombs; map_pkg.start_bombs = bman.start_bombs;
map_pkg.start_range = bman.start_range; map_pkg.start_range = bman.start_range;
sprintf (map_pkg.start_speed, "%6f", bman.start_speed); sprintf (map_pkg.start_speed, "%4f", bman.start_speed);
sprintf (map_pkg.bomb_tickingtime, "%6f", bman.bomb_tickingtime); sprintf (map_pkg.bomb_tickingtime, "%4f", bman.bomb_tickingtime);
if (map.random_tileset) if (map.random_tileset)
map_pkg.tileset[0] = 0; map_pkg.tileset[0] = 0;
else else
strcpy (map_pkg.tileset, map.tileset); strncpy (map_pkg.tileset, map.tileset, LEN_TILESETNAME);
map_pkg.map_selection = map.map_selection; map_pkg.map_selection = map.map_selection;
strcpy (map_pkg.mapname, map.map); strncpy (map_pkg.mapname, map.map, LEN_FILENAME);
d_printf ("send_mapinfo: Tileset: %s\n", map.tileset); d_printf ("send_mapinfo: Tileset: %s\n", map.tileset);
#ifndef BUG_MAPINFO
test = addr; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
send_pkg ((struct pkg *) &map_pkg, addr); send_pkg ((struct pkg *) &map_pkg, addr);
addr = test; // VERY DIRTY WORKAROUND WHY IS HERE A BUG
#else
printf ("Addr before send: %p\n", addr);
send_pkg ((struct pkg *) &map_pkg, addr);
printf ("Addr after send: %p\n", addr);
#endif
}; };
@ -1618,9 +1630,9 @@ do_mapinfo (struct pkg_mapinfo *map_pkg, _net_addr * addr)
} }
else { else {
map.random_tileset = 0; map.random_tileset = 0;
strcpy (map.tileset, map_pkg->tileset); strncpy (map.tileset, map_pkg->tileset, LEN_TILESETNAME);
} }
strcpy (map.map, map_pkg->mapname); strncpy (map.map, map_pkg->mapname, LEN_FILENAME);
map.map_selection = map_pkg->map_selection; map.map_selection = map_pkg->map_selection;
map.size.x = map_pkg->size_x; map.size.x = map_pkg->size_x;
map.size.y = map_pkg->size_y; map.size.y = map_pkg->size_y;
@ -1703,6 +1715,7 @@ do_gameinfo (struct pkg_gameinfo *pgi, _net_addr * addr)
strncpy (pgi->version, VERSION, LEN_VERSION); strncpy (pgi->version, VERSION, LEN_VERSION);
pgi->maxplayers = bman.maxplayer; pgi->maxplayers = bman.maxplayer;
pgi->curplayers = bman.players_nr_s; pgi->curplayers = bman.players_nr_s;
pgi->h.len = HTON16 (sizeof (struct pkg_gameinfo));
strncpy (pgi->gamename, bman.gamename, LEN_GAMENAME); strncpy (pgi->gamename, bman.gamename, LEN_GAMENAME);
send_pkg ((struct pkg *) pgi, addr); send_pkg ((struct pkg *) pgi, addr);
} }
@ -1711,7 +1724,6 @@ do_gameinfo (struct pkg_gameinfo *pgi, _net_addr * addr)
else else
d_printf ("do_gameinfo (from: %s:%s) ** WE ARE NOT THE MASTER OF THIS GAME **\n", d_printf ("do_gameinfo (from: %s:%s) ** WE ARE NOT THE MASTER OF THIS GAME **\n",
addr->host, addr->port); addr->host, addr->port);
} }
@ -1807,10 +1819,8 @@ send_pkg (struct pkg *packet, _net_addr * addr)
/* if PKGF_ackreq is set add the packet to the resendcache /* if PKGF_ackreq is set add the packet to the resendcache
* so we can resend it if no PKF_ackreq returned for the packet. */ * so we can resend it if no PKF_ackreq returned for the packet. */
if (packet->h.flags & PKGF_ackreq) { if (packet->h.flags & PKGF_ackreq)
if (rscache_add (addr, packet) == -1) rscache_add (addr, packet);
d_printf ("resend_cache overrun.... packet throw away.\n");
}
}; };
@ -1841,15 +1851,22 @@ fwd_pkg (struct pkg *packet, _net_addr * addr)
forward it to all needed functions, like inpkg_check()--> send answer if needed, forward it to all needed functions, like inpkg_check()--> send answer if needed,
if we are the server then forward the packet if needed if we are the server then forward the packet if needed
and go into the do_PACKETTYP function */ and go into the do_PACKETTYP function */
int void
do_pkg (struct pkg *packet, _net_addr * addr) do_pkg (struct pkg *packet, _net_addr * addr, int len)
{ {
d_printf ("do_pkg: addr %p, pkg %p\n", addr, packet);
if (((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET) if (((packet->h.flags & PKGF_ipv6) == 0 && bman.net_ai_family != PF_INET)
|| ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) { || ((packet->h.flags & PKGF_ipv6) != 0 && bman.net_ai_family == PF_INET)) {
d_printf ("do_pkg: packet comes from the wrong network type\n"); d_printf ("do_pkg: packet comes from the wrong network type\n");
return 0; return;
} }
/* Check the size of the incoming packet */
if (len != NTOH16(packet->h.len)) {
d_printf ("do_pkg: len of the incoming packet is not the same as in pkg->h.len\n");
return;
}
/* get the addr and set the ping timeout value /* get the addr and set the ping timeout value
* check if the packet is from a player in the game and not from someone else * check if the packet is from a player in the game and not from someone else
* this exception is only for PKG_joingame, PKG_error */ * this exception is only for PKG_joingame, PKG_error */
@ -1857,7 +1874,7 @@ do_pkg (struct pkg *packet, _net_addr * addr)
if ((addr->pl_nr < 0 || addr->pl_nr >= MAX_PLAYERS) && packet->h.typ > PKG_joingame if ((addr->pl_nr < 0 || addr->pl_nr >= MAX_PLAYERS) && packet->h.typ > PKG_joingame
&& PS_IS_netplayer (players[addr->pl_nr].state)) { && PS_IS_netplayer (players[addr->pl_nr].state)) {
d_printf ("do_pkg: error addr->pl_nr out of range\n"); d_printf ("do_pkg: error addr->pl_nr out of range\n");
return 0; return;
} }
if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) { if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) {
@ -1881,7 +1898,7 @@ do_pkg (struct pkg *packet, _net_addr * addr)
d_printf ("do_pkg: double packet ignoring addr->pl_nr=%d\n", addr->pl_nr); d_printf ("do_pkg: double packet ignoring addr->pl_nr=%d\n", addr->pl_nr);
if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS) if (addr->pl_nr >= 0 && addr->pl_nr < MAX_PLAYERS)
players[addr->pl_nr].net.pkgopt.to_2sec++; players[addr->pl_nr].net.pkgopt.to_2sec++;
return 0; return;
} }
} }
@ -1891,9 +1908,8 @@ do_pkg (struct pkg *packet, _net_addr * addr)
} }
switch (packet->h.typ) { switch (packet->h.typ) {
case (PKG_error): case (PKG_error):
if (do_error ((struct pkg_error *) packet, addr) < 0) do_error ((struct pkg_error *) packet, addr);
return -1;
break; break;
case (PKG_gameinfo): case (PKG_gameinfo):
do_gameinfo ((struct pkg_gameinfo *) packet, addr); do_gameinfo ((struct pkg_gameinfo *) packet, addr);
@ -1977,6 +1993,4 @@ do_pkg (struct pkg *packet, _net_addr * addr)
send_error (addr, "BomberClone: unknown data packet"); send_error (addr, "BomberClone: unknown data packet");
break; break;
} }
return 0;
}; };

@ -1,4 +1,4 @@
/* $Id: pkgcache.c,v 1.9 2005/03/28 03:04:35 stpohle Exp $ /* $Id: pkgcache.c,v 1.10 2006/08/13 21:26:50 stpohle Exp $
* Resendcache work, We need this to resend lost packets over the network. * Resendcache work, We need this to resend lost packets over the network.
* we will keep every packet with the PKGF_ackreq flag as long as we haven't * we will keep every packet with the PKGF_ackreq flag as long as we haven't
* got any answer from the destination host. And resend the packet after a givin * got any answer from the destination host. And resend the packet after a givin
@ -10,162 +10,100 @@
#include "network.h" #include "network.h"
#include "packets.h" #include "packets.h"
/* struct _resend_cache rscache;
set pointers at the giving pos
*/
void
rscache_setpointer (int pos)
{
resend_cache.entry = (struct _rscache_entry *) (((char *) resend_cache.data) + pos);
};
/*
add a packet to the cache and sets the timestamp
*/
int
rscache_add (_net_addr * addr, struct pkg *packet)
{
int newlen;
/* maybe we forgot to check here something? i don't know but it seems
* that i forgot to calculate the packetsize into this.
* (i'll add the packet len to this calculation) */
if (resend_cache.fill + sizeof (struct _rscache_entry) + packet->h.len > PKG_RESENDCACHE_SIZE)
return -1;
rscache_setpointer (resend_cache.fill);
resend_cache.entry->retry = 0;
resend_cache.entry->timestamp = timestamp;
memcpy (&resend_cache.entry->addr, addr, sizeof (_net_addr));
memcpy (&resend_cache.entry->packet, packet, NTOH16 (packet->h.len));
newlen = resend_cache.fill + rscache_getcurlen (); /* reset the counter for the resendcache */
void rscache_init () {
resend_cache.fill = newlen; rscache.count = 0;
return 0;
}; };
/* /* add a new packet to the list
deletes the packet at current pointer in the cache
*/
void
rscache_del ()
{
int len,
size;
char *pos1;
/* check if we are able to delete */
if ((char *) resend_cache.data > (char *) resend_cache.entry ||
(char *) resend_cache.entry > (char *) resend_cache.data + resend_cache.fill ||
resend_cache.fill == -1 || resend_cache.data == NULL) {
d_printf ("rscache_del: something wrong with the cache\n");
exit (1);
return;
}
/* newlen = size of the cacheentry we are going to delete */
len = rscache_getcurlen ();
if (resend_cache.fill <= len) /* something wrong?, fill is smaler as the cacheentry, delete the cache */ struct _rscache_entry {
resend_cache.fill = 0; Uint32 timestamp; // pointer to the timestamp
else { signed char retry; // retry's how many times we tryed this
pos1 = (char *) resend_cache.entry + len; _net_addr addr; // the address
size = PKG_RESENDCACHE_SIZE - (pos1 - resend_cache.data); char packet[MAX_UDPDATA]; // the packet
} __attribute__((packed));
if (resend_cache.fill < PKG_RESENDCACHE_SIZE) {
memmove (resend_cache.entry, pos1, size);
resend_cache.fill = resend_cache.fill - len;
}
}
};
/*
get the position in the cache where our needed packet is
*/ */
int void rscache_add (_net_addr *addr, struct pkg *packet) {
rscache_getpos (_net_addr * addr, unsigned char typ, short int id) int len;
{
int len, d_printf ("rscache_add: addr %p, pkg %p\n", addr, packet);
pos, /* check if there is still some free space left. */
done = 0; if (rscache.count >= PKG_RESENDCACHE_SIZE) {
d_printf ("rscache_add no free rscache entry left.\n");
for (pos = 0; (pos < resend_cache.fill && done == 0);) { return;
}
rscache_setpointer (pos);
/* copy all the data we need. */
/* get size of the cacheentry */ rscache.entry[rscache.count].timestamp = timestamp;
len = rscache_getcurlen (); rscache.entry[rscache.count].retry = 0;
memcpy (&rscache.entry[rscache.count].addr, addr, sizeof (_net_addr));
if (strcmp (addr->host, resend_cache.entry->addr.host) == 0 && len = NTOH16 (packet->h.len);
strcmp (addr->port, resend_cache.entry->addr.port) == 0 && if (MAX_UDPDATA < len) len = MAX_UDPDATA;
typ == resend_cache.entry->packet.h.typ && id == NTOH16 (resend_cache.entry->packet.h.id)) memcpy (&rscache.entry[rscache.count].packet, packet, MAX_UDPDATA);
done = 1; /* we have found the old packet */ rscache.count ++;
else
pos = pos + len;
}
if (done == 0) /* we have found nothing */
return -1;
return pos;
}; };
/* get the len of the current entry */
int
rscache_getcurlen ()
{
int len;
len = sizeof (struct _rscache_entry) - sizeof (struct pkg) + NTOH16 (resend_cache.entry->packet.h.len);
return len; /* delete the packet from the cache */
void rscache_del (_net_addr *addr, unsigned char typ, short unsigned int id) {
int i;
d_printf ("rscache_del: addr %p\n", addr);
for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) {
if (rscache.entry[i].addr.pl_nr == addr->pl_nr &&
NTOH16(rscache.entry[i].packet.h.id) == id &&
((struct pkg)rscache.entry[i].packet).h.typ == typ) { // found element
int a;
for (a = i; a < rscache.count - 1; a++)
rscache.entry[i] = rscache.entry[i+1];
rscache.count--;
break;
}
}
}; };
/* test for old packets where we haven't got a ackreq packet for.
/* * If the timeout is up resend the packet again until RESENDCACHE_RETRY
the loop for the cache.. to see what will have to be resend * has reached then delete the packet. */
*/ void rscache_loop () {
void int i;
rscache_loop () int timeout;
{
int len,
pos,
timeout;
if (bman.state==GS_running) timeout = RESENDCACHE_TIMEOUT; else timeout=RESENDCACHE_TIMEOUT_MENU; if (bman.state==GS_running) timeout = RESENDCACHE_TIMEOUT; else timeout=RESENDCACHE_TIMEOUT_MENU;
for (pos = 0; pos < resend_cache.fill && pos < PKG_RESENDCACHE_SIZE && pos >= 0;) {
rscache_setpointer (pos);
len = rscache_getcurlen ();
if (timestamp - resend_cache.entry->timestamp >= timeout for (i = 0; (i < rscache.count) && (i < PKG_RESENDCACHE_SIZE); i++) {
&& resend_cache.entry->retry < RESENDCACHE_RETRY) { if (timestamp - rscache.entry[i].timestamp >= timeout
&& rscache.entry[i].retry < RESENDCACHE_RETRY) {
/* send it again */ /* send it again */
d_printf d_printf
("Data Send Timeout (%s:%s) Resend now Package Fill %d, Pos %d\n", ("Data Send Timeout (%s:%s) Resend now Package Fill %d, Pos %d\n",
resend_cache.entry->addr.host, resend_cache.entry->addr.port, resend_cache.fill,pos); rscache.entry[i].addr.host, rscache.entry[i].addr.port, rscache.count,i);
udp_send (bman.sock, (char *) &resend_cache.entry->packet,
NTOH16 (resend_cache.entry->packet.h.len), &resend_cache.entry->addr.sAddr, udp_send (bman.sock, (char *) &rscache.entry[i].packet,
bman.net_ai_family); NTOH16 (rscache.entry[i].packet.h.len),
resend_cache.entry->timestamp = timestamp; &rscache.entry[i].addr.sAddr,
resend_cache.entry->retry++; bman.net_ai_family);
if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) rscache.entry[i].timestamp = timestamp;
players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++; rscache.entry[i].retry++;
if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS)
players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++;
} }
if (timestamp - resend_cache.entry->timestamp >= timeout if (timestamp - rscache.entry[i].timestamp >= timeout
&& resend_cache.entry->retry >= RESENDCACHE_RETRY) { && rscache.entry[i].retry >= RESENDCACHE_RETRY) {
d_printf ("Data Send Timeout (%s:%s) Delete now Package Fill %d, Pos %d\n", d_printf ("Data Send Timeout (%s:%s) Delete now Package Fill %d, Pos %d\n",
resend_cache.entry->addr.host, resend_cache.entry->addr.port, rscache.entry[i].addr.host, rscache.entry[i].addr.port, rscache.count, i);
resend_cache.fill, pos); if (rscache.entry[i].addr.pl_nr >= 0 && rscache.entry[i].addr.pl_nr < MAX_PLAYERS)
if (resend_cache.entry->addr.pl_nr >= 0 && resend_cache.entry->addr.pl_nr < MAX_PLAYERS) players[rscache.entry[i].addr.pl_nr].net.pkgopt.to_2sec++;
players[resend_cache.entry->addr.pl_nr].net.pkgopt.to_2sec++;
rscache_del (); rscache_del (&rscache.entry[i].addr, rscache.entry[i].packet.h.typ,
NTOH16(rscache.entry[i].packet.h.id));
} }
else }
pos = pos + len;
}
}; };

Loading…
Cancel
Save