From a518930c627b7bd5d2f9344cad6e8f880657238b Mon Sep 17 00:00:00 2001 From: zicodxx Date: Wed, 13 Apr 2011 00:19:46 +0200 Subject: [PATCH] Improved security for UDP protocol: Add checks for correct packet size and - if possible - valid sender address (valid player) and making sure Clients only accept packets meant for Clients and Hosts only accept packets meant for Hosts --- CHANGELOG.txt | 4 + main/net_udp.c | 384 ++++++++++++++++++++++++------------------------- main/net_udp.h | 108 +++++++------- 3 files changed, 250 insertions(+), 246 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9a63a619d..e50b6ddef 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,9 @@ D1X-Rebirth Changelog +20110413 +-------- +main/net_udp.c, main/net_udp.h: Improved security for UDP protocol: Add checks for correct packet size and - if possible - valid sender address (valid player) and making sure Clients only accept packets meant for Clients and Hosts only accept packets meant for Hosts + 20110412 -------- main/gauges.c, main/multi.h, main/net_udp.c, main/net_udp.h: Little fix for typing-indicator in multiplayer - was showing comma even if no player name was displayed; Removed team_vector from UDP lite_info structure - it's not needed; Increased UDP_NETGAMES_PAGES to actually show 3000 possible games diff --git a/main/net_udp.c b/main/net_udp.c index 6ade1ddc9..e2c1cb3f0 100644 --- a/main/net_udp.c +++ b/main/net_udp.c @@ -962,16 +962,16 @@ void net_udp_list_join_game() void net_udp_send_sequence_packet(UDP_sequence_packet seq, struct _sockaddr recv_addr) { int len = 0; - ubyte buf[UPKT_SEQUENCE_SIZE]; + ubyte buf[UPID_SEQUENCE_SIZE]; len = 0; memset(buf, 0, sizeof(buf)); - buf[0] = seq.type; len++; + buf[0] = seq.type; len++; memcpy(&buf[len], seq.player.callsign, CALLSIGN_LEN+1); len += CALLSIGN_LEN+1; - buf[len] = seq.player.version_major; len++; - buf[len] = seq.player.version_minor; len++; - buf[len] = seq.player.connected; len++; - buf[len] = seq.player.rank; len++; + buf[len] = seq.player.version_major; len++; + buf[len] = seq.player.version_minor; len++; + buf[len] = seq.player.connected; len++; + buf[len] = seq.player.rank; len++; sendto (UDP_Socket[0], buf, len, 0, (struct sockaddr *)&recv_addr, sizeof(struct _sockaddr)); } @@ -980,12 +980,12 @@ void net_udp_receive_sequence_packet(ubyte *data, UDP_sequence_packet *seq, stru { int len = 0; - seq->type = data[0]; len++; + seq->type = data[0]; len++; memcpy(seq->player.callsign, &(data[len]), CALLSIGN_LEN+1); len += CALLSIGN_LEN+1; - seq->player.version_major = data[len]; len++; - seq->player.version_minor = data[len]; len++; - seq->player.connected = data[len]; len++; - memcpy (&(seq->player.rank),&(data[len]),1); len++; + seq->player.version_major = data[len]; len++; + seq->player.version_minor = data[len]; len++; + seq->player.connected = data[len]; len++; + memcpy (&(seq->player.rank),&(data[len]),1); len++; if (multi_i_am_master()) memcpy(&seq->player.protocol.udp.addr, (struct _sockaddr *)&sender_addr, sizeof(struct _sockaddr)); @@ -1538,7 +1538,7 @@ void net_udp_stop_resync(UDP_sequence_packet *their) } } -ubyte object_buffer[UPKT_MAX_SIZE]; +ubyte object_buffer[UPID_MAX_SIZE]; void net_udp_send_objects(void) { @@ -1566,7 +1566,7 @@ void net_udp_send_objects(void) return; } - memset(object_buffer, 0, UPKT_MAX_SIZE); + memset(object_buffer, 0, UPID_MAX_SIZE); object_buffer[0] = UPID_OBJECT_DATA; loc = 5; @@ -1592,7 +1592,7 @@ void net_udp_send_objects(void) if ((Network_send_object_mode == 1) && ((object_owner[i] == -1) || (object_owner[i] == player_num))) continue; - if ( loc + sizeof(object_rw) + 9 > UPKT_MAX_SIZE-1 ) + if ( loc + sizeof(object_rw) + 9 > UPID_MAX_SIZE-1 ) break; // Not enough room for another object obj_count_frame++; @@ -1617,7 +1617,7 @@ void net_udp_send_objects(void) Network_send_objnum = i; PUT_INTEL_INT(object_buffer+1, obj_count_frame); - Assert(loc <= UPKT_MAX_SIZE); + Assert(loc <= UPID_MAX_SIZE); sendto (UDP_Socket[0], object_buffer, loc, 0, (struct sockaddr *)&UDP_sync_player.player.protocol.udp.addr, sizeof(struct _sockaddr)); } @@ -1927,7 +1927,7 @@ void net_udp_dump_player(struct _sockaddr dump_addr, int why) { // Inform player that he was not chosen for the netgame - ubyte buf[2]; + ubyte buf[UPID_DUMP_SIZE]; buf[0] = UPID_DUMP; buf[1] = why; @@ -1974,7 +1974,7 @@ void net_udp_send_endlevel_packet(void) if (multi_i_am_master()) { - ubyte buf[UPKT_MAX_SIZE]; + ubyte buf[UPID_MAX_SIZE]; memset(buf, 0, sizeof(buf)); @@ -2001,7 +2001,7 @@ void net_udp_send_endlevel_packet(void) } else { - ubyte buf[UPKT_MAX_SIZE]; + ubyte buf[UPID_MAX_SIZE]; memset(buf, 0, sizeof(buf)); @@ -2023,7 +2023,7 @@ void net_udp_send_endlevel_packet(void) void net_udp_send_version_deny(struct _sockaddr sender_addr) { - ubyte buf[7]; + ubyte buf[UPID_VERSION_DENY_SIZE]; buf[0] = UPID_VERSION_DENY; PUT_INTEL_SHORT(buf + 1, D1XMAJORi); @@ -2043,7 +2043,7 @@ void net_udp_process_version_deny(ubyte *data, struct _sockaddr sender_addr) void net_udp_request_game_info(struct _sockaddr game_addr, int lite) { - ubyte buf[UPKT_GAME_INFO_REQ_SIZE]; + ubyte buf[UPID_GAME_INFO_REQ_SIZE]; buf[0] = (lite?UPID_GAME_INFO_LITE_REQ:UPID_GAME_INFO_REQ); memcpy(&(buf[1]), UDP_REQ_ID, 4); @@ -2055,17 +2055,11 @@ void net_udp_request_game_info(struct _sockaddr game_addr, int lite) } // Check request for game info. Return 1 if sucessful; -1 if version mismatch; 0 if wrong game or some other error - do not process -int net_udp_check_game_info_request(ubyte *data, int data_len) +int net_udp_check_game_info_request(ubyte *data) { short sender_iver[3] = { 0, 0, 0 }; char sender_id[4] = ""; - if (!multi_i_am_master()) - return 0; - - if (data_len != UPKT_GAME_INFO_REQ_SIZE) - return 0; - memcpy(&sender_id, &(data[1]), 4); sender_iver[0] = GET_INTEL_SHORT(&(data[5])); sender_iver[1] = GET_INTEL_SHORT(&(data[7])); @@ -2092,23 +2086,23 @@ void net_udp_send_game_info(struct _sockaddr sender_addr, ubyte info_upid) if (info_upid == UPID_GAME_INFO_LITE) { - ubyte buf[UPKT_MAX_SIZE]; + ubyte buf[UPID_GAME_INFO_LITE_SIZE]; int tmpvar = 0; memset(buf, 0, sizeof(buf)); - buf[0] = info_upid; len++; - PUT_INTEL_SHORT(buf + len, D1XMAJORi); len += 2; - PUT_INTEL_SHORT(buf + len, D1XMINORi); len += 2; - PUT_INTEL_SHORT(buf + len, D1XMICROi); len += 2; - PUT_INTEL_INT(buf + len, Netgame.protocol.udp.GameID); len += 4; - memcpy(&(buf[len]), Netgame.game_name, NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); + buf[0] = info_upid; len++; + PUT_INTEL_SHORT(buf + len, D1XMAJORi); len += 2; + PUT_INTEL_SHORT(buf + len, D1XMINORi); len += 2; + PUT_INTEL_SHORT(buf + len, D1XMICROi); len += 2; + PUT_INTEL_INT(buf + len, Netgame.protocol.udp.GameID); len += 4; + memcpy(&(buf[len]), Netgame.game_name, NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); memcpy(&(buf[len]), Netgame.mission_title, MISSION_NAME_LEN+1); len += (MISSION_NAME_LEN+1); - memcpy(&(buf[len]), Netgame.mission_name, 9); len += 9; - PUT_INTEL_INT(buf + len, Netgame.levelnum); len += 4; - buf[len] = Netgame.gamemode; len++; - buf[len] = Netgame.RefusePlayers; len++; - buf[len] = Netgame.difficulty; len++; + memcpy(&(buf[len]), Netgame.mission_name, 9); len += 9; + PUT_INTEL_INT(buf + len, Netgame.levelnum); len += 4; + buf[len] = Netgame.gamemode; len++; + buf[len] = Netgame.RefusePlayers; len++; + buf[len] = Netgame.difficulty; len++; tmpvar = Netgame.game_status; if (Endlevel_sequence || Control_center_destroyed) tmpvar = NETSTAT_ENDLEVEL; @@ -2119,46 +2113,45 @@ void net_udp_send_game_info(struct _sockaddr sender_addr, ubyte info_upid) tmpvar = NETSTAT_ENDLEVEL; } } - buf[len] = tmpvar; len++; - buf[len] = Netgame.numconnected; len++; - buf[len] = Netgame.max_numplayers; len++; - buf[len] = Netgame.game_flags; len++; + buf[len] = tmpvar; len++; + buf[len] = Netgame.numconnected; len++; + buf[len] = Netgame.max_numplayers; len++; + buf[len] = Netgame.game_flags; len++; sendto (UDP_Socket[0], buf, len, 0, (struct sockaddr *)&sender_addr, sizeof(struct _sockaddr)); } else { - ubyte buf[UPKT_MAX_SIZE]; + ubyte buf[UPID_GAME_INFO_SIZE]; int i = 0, j = 0, tmpvar = 0; memset(buf, 0, sizeof(buf)); - buf[0] = info_upid; len++; - PUT_INTEL_SHORT(buf + len, D1XMAJORi); len += 2; - PUT_INTEL_SHORT(buf + len, D1XMINORi); len += 2; - PUT_INTEL_SHORT(buf + len, D1XMICROi); len += 2; - buf[len] = Netgame.version_major; len++; - buf[len] = Netgame.version_minor; len++; + buf[0] = info_upid; len++; + PUT_INTEL_SHORT(buf + len, D1XMAJORi); len += 2; + PUT_INTEL_SHORT(buf + len, D1XMINORi); len += 2; + PUT_INTEL_SHORT(buf + len, D1XMICROi); len += 2; + buf[len] = Netgame.version_major; len++; + buf[len] = Netgame.version_minor; len++; for (i = 0; i < MAX_PLAYERS+4; i++) { memcpy(&buf[len], Netgame.players[i].callsign, CALLSIGN_LEN+1); len += CALLSIGN_LEN+1; - buf[len] = Netgame.players[i].version_major; len++; - buf[len] = Netgame.players[i].version_minor; len++; - buf[len] = Netgame.players[i].connected; len++; - buf[len] = Netgame.players[i].rank; len++; + buf[len] = Netgame.players[i].version_major; len++; + buf[len] = Netgame.players[i].version_minor; len++; + buf[len] = Netgame.players[i].connected; len++; + buf[len] = Netgame.players[i].rank; len++; if (!memcmp((struct _sockaddr *)&sender_addr, (struct _sockaddr *)&Netgame.players[i].protocol.udp.addr, sizeof(struct _sockaddr))) buf[len] = 1; else - buf[len] = 0; - len++; + buf[len] = 0; len++; } - memcpy(&(buf[len]), Netgame.game_name, NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); + memcpy(&(buf[len]), Netgame.game_name, NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); memcpy(&(buf[len]), Netgame.mission_title, MISSION_NAME_LEN+1); len += (MISSION_NAME_LEN+1); memcpy(&(buf[len]), Netgame.mission_name, 9); len += 9; - PUT_INTEL_INT(buf + len, Netgame.levelnum); len += 4; - buf[len] = Netgame.gamemode; len++; - buf[len] = Netgame.RefusePlayers; len++; - buf[len] = Netgame.difficulty; len++; + PUT_INTEL_INT(buf + len, Netgame.levelnum); len += 4; + buf[len] = Netgame.gamemode; len++; + buf[len] = Netgame.RefusePlayers; len++; + buf[len] = Netgame.difficulty; len++; tmpvar = Netgame.game_status; if (Endlevel_sequence || Control_center_destroyed) tmpvar = NETSTAT_ENDLEVEL; @@ -2169,56 +2162,56 @@ void net_udp_send_game_info(struct _sockaddr sender_addr, ubyte info_upid) tmpvar = NETSTAT_ENDLEVEL; } } - buf[len] = tmpvar; len++; - buf[len] = Netgame.numplayers; len++; - buf[len] = Netgame.max_numplayers; len++; - buf[len] = Netgame.numconnected; len++; - buf[len] = Netgame.game_flags; len++; - buf[len] = Netgame.team_vector; len++; - PUT_INTEL_INT(buf + len, Netgame.AllowedItems); len += 4; - PUT_INTEL_SHORT(buf + len, Netgame.Allow_marker_view); len += 2; - PUT_INTEL_SHORT(buf + len, Netgame.AlwaysLighting); len += 2; - PUT_INTEL_SHORT(buf + len, Netgame.BrightPlayers); len += 2; - PUT_INTEL_SHORT(buf + len, Netgame.InvulAppear); len += 2; - memcpy(&buf[len], Netgame.team_name, 2*(CALLSIGN_LEN+1)); len += 2*(CALLSIGN_LEN+1); + buf[len] = tmpvar; len++; + buf[len] = Netgame.numplayers; len++; + buf[len] = Netgame.max_numplayers; len++; + buf[len] = Netgame.numconnected; len++; + buf[len] = Netgame.game_flags; len++; + buf[len] = Netgame.team_vector; len++; + PUT_INTEL_INT(buf + len, Netgame.AllowedItems); len += 4; + PUT_INTEL_SHORT(buf + len, Netgame.Allow_marker_view); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.AlwaysLighting); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.BrightPlayers); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.InvulAppear); len += 2; + memcpy(&buf[len], Netgame.team_name, 2*(CALLSIGN_LEN+1)); len += 2*(CALLSIGN_LEN+1); for (i = 0; i < MAX_PLAYERS; i++) { - PUT_INTEL_INT(buf + len, Netgame.locations[i]); len += 4; + PUT_INTEL_INT(buf + len, Netgame.locations[i]); len += 4; } for (i = 0; i < MAX_PLAYERS; i++) { for (j = 0; j < MAX_PLAYERS; j++) { - PUT_INTEL_SHORT(buf + len, Netgame.kills[i][j]); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.kills[i][j]); len += 2; } } - PUT_INTEL_SHORT(buf + len, Netgame.segments_checksum); len += 2; - PUT_INTEL_SHORT(buf + len, Netgame.team_kills[0]); len += 2; - PUT_INTEL_SHORT(buf + len, Netgame.team_kills[1]); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.segments_checksum); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.team_kills[0]); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.team_kills[1]); len += 2; for (i = 0; i < MAX_PLAYERS; i++) { - PUT_INTEL_SHORT(buf + len, Netgame.killed[i]); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.killed[i]); len += 2; } for (i = 0; i < MAX_PLAYERS; i++) { - PUT_INTEL_SHORT(buf + len, Netgame.player_kills[i]); len += 2; + PUT_INTEL_SHORT(buf + len, Netgame.player_kills[i]); len += 2; } - PUT_INTEL_INT(buf + len, Netgame.KillGoal); len += 4; - PUT_INTEL_INT(buf + len, Netgame.PlayTimeAllowed); len += 4; - PUT_INTEL_INT(buf + len, Netgame.level_time); len += 4; - PUT_INTEL_INT(buf + len, Netgame.control_invul_time); len += 4; - PUT_INTEL_INT(buf + len, Netgame.monitor_vector); len += 4; + PUT_INTEL_INT(buf + len, Netgame.KillGoal); len += 4; + PUT_INTEL_INT(buf + len, Netgame.PlayTimeAllowed); len += 4; + PUT_INTEL_INT(buf + len, Netgame.level_time); len += 4; + PUT_INTEL_INT(buf + len, Netgame.control_invul_time); len += 4; + PUT_INTEL_INT(buf + len, Netgame.monitor_vector); len += 4; for (i = 0; i < MAX_PLAYERS; i++) { - PUT_INTEL_INT(buf + len, Netgame.player_score[i]); len += 4; + PUT_INTEL_INT(buf + len, Netgame.player_score[i]); len += 4; } for (i = 0; i < MAX_PLAYERS; i++) { - buf[len] = Netgame.player_flags[i]; len++; + buf[len] = Netgame.player_flags[i]; len++; } - PUT_INTEL_SHORT(buf + len, Netgame.PacketsPerSec); len += 2; - buf[len] = Netgame.PacketLossPrevention; len++; - buf[len] = Netgame.NoFriendlyFire; len++; + PUT_INTEL_SHORT(buf + len, Netgame.PacketsPerSec); len += 2; + buf[len] = Netgame.PacketLossPrevention; len++; + buf[len] = Netgame.NoFriendlyFire; len++; sendto (UDP_Socket[0], buf, len, 0, (struct sockaddr *)&sender_addr, sizeof(struct _sockaddr)); } @@ -2270,14 +2263,11 @@ void net_udp_process_game_info(ubyte *data, int data_len, struct _sockaddr game_ { UDP_netgame_info_lite recv_game; - if (data_len > UPKT_MAX_SIZE) - return; - memcpy(&recv_game, &game_addr, sizeof(struct _sockaddr)); - len++; // skip UPID byte - recv_game.program_iver[0] = GET_INTEL_SHORT(&(data[len])); len += 2; - recv_game.program_iver[1] = GET_INTEL_SHORT(&(data[len])); len += 2; - recv_game.program_iver[2] = GET_INTEL_SHORT(&(data[len])); len += 2; + len++; // skip UPID byte + recv_game.program_iver[0] = GET_INTEL_SHORT(&(data[len])); len += 2; + recv_game.program_iver[1] = GET_INTEL_SHORT(&(data[len])); len += 2; + recv_game.program_iver[2] = GET_INTEL_SHORT(&(data[len])); len += 2; if ((recv_game.program_iver[0] != D1XMAJORi) || (recv_game.program_iver[1] != D1XMINORi) || (recv_game.program_iver[2] != D1XMICROi)) return; @@ -2285,15 +2275,15 @@ void net_udp_process_game_info(ubyte *data, int data_len, struct _sockaddr game_ recv_game.GameID = GET_INTEL_INT(&(data[len])); len += 4; memcpy(&recv_game.game_name, &(data[len]), NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); memcpy(&recv_game.mission_title, &(data[len]), MISSION_NAME_LEN+1); len += (MISSION_NAME_LEN+1); - memcpy(&recv_game.mission_name, &(data[len]), 9); len += 9; - recv_game.levelnum = GET_INTEL_INT(&(data[len])); len += 4; - recv_game.gamemode = data[len]; len++; - recv_game.RefusePlayers = data[len]; len++; - recv_game.difficulty = data[len]; len++; - recv_game.game_status = data[len]; len++; - recv_game.numconnected = data[len]; len++; - recv_game.max_numplayers = data[len]; len++; - recv_game.game_flags = data[len]; len++; + memcpy(&recv_game.mission_name, &(data[len]), 9); len += 9; + recv_game.levelnum = GET_INTEL_INT(&(data[len])); len += 4; + recv_game.gamemode = data[len]; len++; + recv_game.RefusePlayers = data[len]; len++; + recv_game.difficulty = data[len]; len++; + recv_game.game_status = data[len]; len++; + recv_game.numconnected = data[len]; len++; + recv_game.max_numplayers = data[len]; len++; + recv_game.game_flags = data[len]; len++; num_active_udp_changed = 1; @@ -2321,83 +2311,80 @@ void net_udp_process_game_info(ubyte *data, int data_len, struct _sockaddr game_ } else { - if (data_len > UPKT_MAX_SIZE) - return; - memcpy((struct _sockaddr *)&Netgame.players[0].protocol.udp.addr, (struct _sockaddr *)&game_addr, sizeof(struct _sockaddr)); - len++; // skip UPID byte - Netgame.protocol.udp.program_iver[0] = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.protocol.udp.program_iver[1] = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.protocol.udp.program_iver[2] = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.version_major = data[len]; len++; - Netgame.version_minor = data[len]; len++; + len++; // skip UPID byte + Netgame.protocol.udp.program_iver[0] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.protocol.udp.program_iver[1] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.protocol.udp.program_iver[2] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.version_major = data[len]; len++; + Netgame.version_minor = data[len]; len++; for (i = 0; i < MAX_PLAYERS+4; i++) { memcpy(&Netgame.players[i].callsign, &(data[len]), CALLSIGN_LEN+1); len += CALLSIGN_LEN+1; - Netgame.players[i].version_major = data[len]; len++; - Netgame.players[i].version_minor = data[len]; len++; - Netgame.players[i].connected = data[len]; len++; - Netgame.players[i].rank = data[len]; len++; - Netgame.players[i].protocol.udp.isyou = data[len]; len++; + Netgame.players[i].version_major = data[len]; len++; + Netgame.players[i].version_minor = data[len]; len++; + Netgame.players[i].connected = data[len]; len++; + Netgame.players[i].rank = data[len]; len++; + Netgame.players[i].protocol.udp.isyou = data[len]; len++; } memcpy(&Netgame.game_name, &(data[len]), NETGAME_NAME_LEN+1); len += (NETGAME_NAME_LEN+1); memcpy(&Netgame.mission_title, &(data[len]), MISSION_NAME_LEN+1); len += (MISSION_NAME_LEN+1); - memcpy(&Netgame.mission_name, &(data[len]), 9); len += 9; - Netgame.levelnum = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.gamemode = data[len]; len++; - Netgame.RefusePlayers = data[len]; len++; - Netgame.difficulty = data[len]; len++; - Netgame.game_status = data[len]; len++; - Netgame.numplayers = data[len]; len++; - Netgame.max_numplayers = data[len]; len++; - Netgame.numconnected = data[len]; len++; - Netgame.game_flags = data[len]; len++; - Netgame.team_vector = data[len]; len++; - Netgame.AllowedItems = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.Allow_marker_view = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.AlwaysLighting = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.BrightPlayers = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.InvulAppear = GET_INTEL_SHORT(&(data[len])); len += 2; + memcpy(&Netgame.mission_name, &(data[len]), 9); len += 9; + Netgame.levelnum = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.gamemode = data[len]; len++; + Netgame.RefusePlayers = data[len]; len++; + Netgame.difficulty = data[len]; len++; + Netgame.game_status = data[len]; len++; + Netgame.numplayers = data[len]; len++; + Netgame.max_numplayers = data[len]; len++; + Netgame.numconnected = data[len]; len++; + Netgame.game_flags = data[len]; len++; + Netgame.team_vector = data[len]; len++; + Netgame.AllowedItems = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.Allow_marker_view = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.AlwaysLighting = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.BrightPlayers = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.InvulAppear = GET_INTEL_SHORT(&(data[len])); len += 2; memcpy(Netgame.team_name, &(data[len]), 2*(CALLSIGN_LEN+1)); len += 2*(CALLSIGN_LEN+1); for (i = 0; i < MAX_PLAYERS; i++) { - Netgame.locations[i] = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.locations[i] = GET_INTEL_INT(&(data[len])); len += 4; } for (i = 0; i < MAX_PLAYERS; i++) { for (j = 0; j < MAX_PLAYERS; j++) { - Netgame.kills[i][j] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.kills[i][j] = GET_INTEL_SHORT(&(data[len])); len += 2; } } - Netgame.segments_checksum = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.team_kills[0] = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.team_kills[1] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.segments_checksum = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.team_kills[0] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.team_kills[1] = GET_INTEL_SHORT(&(data[len])); len += 2; for (i = 0; i < MAX_PLAYERS; i++) { - Netgame.killed[i] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.killed[i] = GET_INTEL_SHORT(&(data[len])); len += 2; } for (i = 0; i < MAX_PLAYERS; i++) { - Netgame.player_kills[i] = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.player_kills[i] = GET_INTEL_SHORT(&(data[len])); len += 2; } - Netgame.KillGoal = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.PlayTimeAllowed = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.level_time = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.control_invul_time = GET_INTEL_INT(&(data[len])); len += 4; - Netgame.monitor_vector = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.KillGoal = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.PlayTimeAllowed = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.level_time = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.control_invul_time = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.monitor_vector = GET_INTEL_INT(&(data[len])); len += 4; for (i = 0; i < MAX_PLAYERS; i++) { - Netgame.player_score[i] = GET_INTEL_INT(&(data[len])); len += 4; + Netgame.player_score[i] = GET_INTEL_INT(&(data[len])); len += 4; } for (i = 0; i < MAX_PLAYERS; i++) { - Netgame.player_flags[i] = data[len]; len++; + Netgame.player_flags[i] = data[len]; len++; } - Netgame.PacketsPerSec = GET_INTEL_SHORT(&(data[len])); len += 2; - Netgame.PacketLossPrevention = data[len]; len++; - Netgame.NoFriendlyFire = data[len]; len++; + Netgame.PacketsPerSec = GET_INTEL_SHORT(&(data[len])); len += 2; + Netgame.PacketLossPrevention = data[len]; len++; + Netgame.NoFriendlyFire = data[len]; len++; Netgame.protocol.udp.valid = 1; // This game is valid! YAY! } @@ -2449,12 +2436,16 @@ void net_udp_process_packet(ubyte *data, struct _sockaddr sender_addr, int lengt switch (data[0]) { case UPID_VERSION_DENY: + if (multi_i_am_master() || length != UPID_VERSION_DENY_SIZE) + break; net_udp_process_version_deny(data, sender_addr); break; case UPID_GAME_INFO_REQ: { int result = 0; - result = net_udp_check_game_info_request(data, length); + if (!multi_i_am_master() || length != UPID_GAME_INFO_REQ_SIZE) + break; + result = net_udp_check_game_info_request(data); if (result == -1) net_udp_send_version_deny(sender_addr); else if (result == 1) @@ -2462,26 +2453,36 @@ void net_udp_process_packet(ubyte *data, struct _sockaddr sender_addr, int lengt break; } case UPID_GAME_INFO: - if (multi_i_am_master()) + if (multi_i_am_master() || length != UPID_GAME_INFO_SIZE) break; net_udp_process_game_info(data, length, sender_addr, 0); break; case UPID_GAME_INFO_LITE_REQ: - if (net_udp_check_game_info_request(data, length) == 1) + if (!multi_i_am_master() || length != UPID_GAME_INFO_REQ_SIZE) + break; + if (net_udp_check_game_info_request(data) == 1) net_udp_send_game_info(sender_addr, UPID_GAME_INFO_LITE); break; case UPID_GAME_INFO_LITE: + if (multi_i_am_master() || length != UPID_GAME_INFO_LITE_SIZE) + break; net_udp_process_game_info(data, length, sender_addr, 1); break; case UPID_DUMP: + if (multi_i_am_master() || memcmp((struct _sockaddr *)&Netgame.players[0].protocol.udp.addr, (struct _sockaddr *)&sender_addr, sizeof(struct _sockaddr)) || length != UPID_DUMP_SIZE) + break; if ((Network_status == NETSTAT_WAITING) || (Network_status == NETSTAT_PLAYING)) net_udp_process_dump(data, length, sender_addr); break; case UPID_ADDPLAYER: + if (multi_i_am_master() || memcmp((struct _sockaddr *)&Netgame.players[0].protocol.udp.addr, (struct _sockaddr *)&sender_addr, sizeof(struct _sockaddr)) || length != UPID_SEQUENCE_SIZE) + break; net_udp_receive_sequence_packet(data, &their, sender_addr); net_udp_new_player(&their); break; case UPID_REQUEST: + if (!multi_i_am_master() || length != UPID_SEQUENCE_SIZE) + break; net_udp_receive_sequence_packet(data, &their, sender_addr); if (Network_status == NETSTAT_STARTING) { @@ -2503,6 +2504,8 @@ void net_udp_process_packet(ubyte *data, struct _sockaddr sender_addr, int lengt } break; case UPID_QUIT_JOINING: + if (!multi_i_am_master() || length != UPID_SEQUENCE_SIZE) + break; net_udp_receive_sequence_packet(data, &their, sender_addr); if (Network_status == NETSTAT_STARTING) net_udp_remove_player( &their ); @@ -2510,20 +2513,24 @@ void net_udp_process_packet(ubyte *data, struct _sockaddr sender_addr, int lengt net_udp_stop_resync( &their ); break; case UPID_SYNC: - if (Network_status == NETSTAT_WAITING) - net_udp_read_sync_packet(data, length, sender_addr); + if (multi_i_am_master() || length != UPID_GAME_INFO_SIZE || Network_status != NETSTAT_WAITING) + break; + net_udp_read_sync_packet(data, length, sender_addr); break; case UPID_OBJECT_DATA: - if (Network_status == NETSTAT_WAITING) - net_udp_read_object_packet(data); + if (multi_i_am_master() || length < UPID_MAX_SIZE || Network_status != NETSTAT_WAITING) + break; + net_udp_read_object_packet(data); break; case UPID_PING: - if (!multi_i_am_master()) - net_udp_process_ping(data, length, sender_addr); + if (multi_i_am_master() || length != UPID_PING_SIZE) + break; + net_udp_process_ping(data, length, sender_addr); break; case UPID_PONG: - if (multi_i_am_master()) - net_udp_process_pong(data, length, sender_addr); + if (!multi_i_am_master() || length != UPID_PONG_SIZE) + break; + net_udp_process_pong(data, length, sender_addr); break; case UPID_ENDLEVEL_H: if ((!multi_i_am_master()) && ((Network_status == NETSTAT_ENDLEVEL) || (Network_status == NETSTAT_PLAYING))) @@ -3860,46 +3867,46 @@ void net_udp_leave_game() void net_udp_flush() { - ubyte packet[UPKT_MAX_SIZE]; + ubyte packet[UPID_MAX_SIZE]; struct _sockaddr sender_addr; if (UDP_Socket[0] != -1) - while (udp_receive_packet( 0, packet, UPKT_MAX_SIZE, &sender_addr) > 0); + while (udp_receive_packet( 0, packet, UPID_MAX_SIZE, &sender_addr) > 0); if (UDP_Socket[1] != -1) - while (udp_receive_packet( 1, packet, UPKT_MAX_SIZE, &sender_addr) > 0); + while (udp_receive_packet( 1, packet, UPID_MAX_SIZE, &sender_addr) > 0); } void net_udp_listen() { int size; - ubyte packet[UPKT_MAX_SIZE]; + ubyte packet[UPID_MAX_SIZE]; struct _sockaddr sender_addr; if (UDP_Socket[0] != -1) { - size = udp_receive_packet( 0, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 0, packet, UPID_MAX_SIZE, &sender_addr ); while ( size > 0 ) { net_udp_process_packet( packet, sender_addr, size ); - size = udp_receive_packet( 0, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 0, packet, UPID_MAX_SIZE, &sender_addr ); } } if (UDP_Socket[1] != -1) { - size = udp_receive_packet( 1, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 1, packet, UPID_MAX_SIZE, &sender_addr ); while ( size > 0 ) { net_udp_process_packet( packet, sender_addr, size ); - size = udp_receive_packet( 1, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 1, packet, UPID_MAX_SIZE, &sender_addr ); } } #ifdef USE_TRACKER if( UDP_Socket[2] != -1 ) { - size = udp_receive_packet( 2, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 2, packet, UPID_MAX_SIZE, &sender_addr ); while ( size > 0 ) { net_udp_process_packet( packet, sender_addr, size ); - size = udp_receive_packet( 2, packet, UPKT_MAX_SIZE, &sender_addr ); + size = udp_receive_packet( 2, packet, UPID_MAX_SIZE, &sender_addr ); } } #endif @@ -3915,7 +3922,7 @@ void net_udp_send_data( ubyte * ptr, int len, int priority ) if (priority) PacketUrgent = 1; - if ((UDP_MData.mbuf_size+len) > UPKT_MBUF_SIZE ) + if ((UDP_MData.mbuf_size+len) > UPID_MDATA_BUF_SIZE ) { check = ptr[0]; net_udp_do_frame(1, 0); @@ -3924,7 +3931,7 @@ void net_udp_send_data( ubyte * ptr, int len, int priority ) Assert(check == ptr[0]); } - Assert(UDP_MData.mbuf_size+len <= UPKT_MBUF_SIZE); + Assert(UDP_MData.mbuf_size+len <= UPID_MDATA_BUF_SIZE); memcpy( &UDP_MData.mbuf[UDP_MData.mbuf_size], ptr, len ); UDP_MData.mbuf_size += len; @@ -4341,7 +4348,7 @@ void net_udp_send_mdata(int priority, fix64 time) UDP_MData.type = 0; UDP_MData.Player_num = 0; UDP_MData.mbuf_size = 0; - memset(&UDP_MData.mbuf, 0, sizeof(ubyte)*UPKT_MBUF_SIZE); + memset(&UDP_MData.mbuf, 0, sizeof(ubyte)*UPID_MDATA_BUF_SIZE); } void net_udp_process_mdata (ubyte *data, int data_len, struct _sockaddr sender_addr, int priority) @@ -4630,15 +4637,12 @@ void net_udp_ping_frame(fix64 time) { static fix64 PingTime = 0; - if (!multi_i_am_master()) - return; - if ((PingTime + F1_0) < time) { - ubyte buf[UPKT_PING_SIZE]; + ubyte buf[UPID_PING_SIZE]; int len = 0, i = 0; - memset(&buf, 0, sizeof(ubyte)*UPKT_PING_SIZE); + memset(&buf, 0, sizeof(ubyte)*UPID_PING_SIZE); buf[len] = UPID_PING; len++; memcpy(&buf[len], &time, 8); len += 8; for (i = 1; i < MAX_PLAYERS; i++) @@ -4660,15 +4664,12 @@ void net_udp_ping_frame(fix64 time) void net_udp_process_ping(ubyte *data, int data_len, struct _sockaddr sender_addr) { fix64 host_ping_time = 0; - ubyte buf[UPKT_PONG_SIZE]; + ubyte buf[UPID_PONG_SIZE]; int i, len = 0; - - if (data_len != UPKT_PING_SIZE) +// + if (memcmp((struct _sockaddr *)&Netgame.players[0].protocol.udp.addr, (struct _sockaddr *)&sender_addr, sizeof(struct _sockaddr))) return; - if (memcmp((struct _sockaddr *)&sender_addr, (struct _sockaddr *)&Netgame.players[0].protocol.udp.addr, sizeof(struct _sockaddr))) - return; - len++; // Skip UPID byte; memcpy(&host_ping_time, &data[len], 8); len += 8; for (i = 1; i < MAX_PLAYERS; i++) @@ -4689,15 +4690,12 @@ void net_udp_process_pong(ubyte *data, int data_len, struct _sockaddr sender_add fix64 client_pong_time = 0; int i = 0; - if (data_len != UPKT_PONG_SIZE) + if (memcmp((struct _sockaddr *)&sender_addr, (struct _sockaddr *)&Netgame.players[data[1]].protocol.udp.addr, sizeof(struct _sockaddr))) return; if (data[1] >= MAX_PLAYERS || data[1] < 1) return; - - if (memcmp((struct _sockaddr *)&sender_addr, (struct _sockaddr *)&Netgame.players[data[1]].protocol.udp.addr, sizeof(struct _sockaddr))) - return; - + if (i == MAX_PLAYERS) return; diff --git a/main/net_udp.h b/main/net_udp.h index b854cb788..e005ced4d 100644 --- a/main/net_udp.h +++ b/main/net_udp.h @@ -35,38 +35,40 @@ int net_udp_level_sync(); #define UDP_TIMEOUT (10*F1_0) // 10 seconds disconnect timeout #define UDP_MDATA_STOR_QUEUE_SIZE 500 // Store up to 500 MDATA packets -// Following are static defines for the buffer size of various packets. IF you change the packets, you must change the size, too. -#define UPKT_MAX_SIZE 1024 // Max size for a packet -#define UPKT_GAME_INFO_REQ_SIZE 11 -#define UPKT_SEQUENCE_SIZE 14 -#define UPKT_PING_SIZE 37 -#define UPKT_PONG_SIZE 10 -#define UPKT_MBUF_SIZE 454 - -// UDP-Packet identificators (ubyte) -#define UPID_VERSION_DENY 1 // Netgame join or info has been denied due to version difference. -#define UPID_GAME_INFO_REQ 2 // Requesting all info about a netgame. -#define UPID_GAME_INFO 3 // Packet containing all info about a netgame. -#define UPID_GAME_INFO_LITE_REQ 4 // Requesting lite info about a netgame. Used for discovering games. -#define UPID_GAME_INFO_LITE 5 // Packet containing lite netgame info. -#define UPID_DUMP 6 // Packet containing why player cannot join this game. -#define UPID_ADDPLAYER 7 // Packet from Host containing info about a new player. -#define UPID_REQUEST 8 // New player says: "I want to be inside of you!" (haha, sorry I could not resist) / Packet containing request to join the game actually. -#define UPID_QUIT_JOINING 9 // Packet from a player who suddenly quits joining. -#define UPID_SYNC 10 // Packet from host containing full netgame info to sync players up. -#define UPID_OBJECT_DATA 11 // Packet from host containing object buffer. -#define UPID_PING 12 // Packet from host containing his GameTime and the Ping list. Client returns this time to host as UPID_PONG and adapts the ping list. -#define UPID_PONG 13 // Packet answer from client to UPID_PING. Contains the time the initial ping packet was sent. -#define UPID_ENDLEVEL_H 14 // Packet from Host to all Clients containing connect-states and kills information about everyone in the game. -#define UPID_ENDLEVEL_C 15 // Packet from Client to Host containing connect-state and kills information from this Client. -#define UPID_PDATA_H 16 // Packet from Host to all Clients containing all players movement data. -#define UPID_PDATA_C 17 // Packet from Client to Host containing his movement data. -#define UPID_MDATA_P0 18 // Packet containing multi buffer from a player. Priority 0 - no ACK needed. -#define UPID_MDATA_P1 19 // Packet containing multi buffer from a player. Priority 1 - ACK needed. Also contains pkt_num -#define UPID_MDATA_ACK 20 // ACK packet for UPID_MDATA_P1. +// UDP-Packet identificators (ubyte) and their (max. sizes). +#define UPID_VERSION_DENY 1 // Netgame join or info has been denied due to version difference. +#define UPID_VERSION_DENY_SIZE 7 +#define UPID_GAME_INFO_REQ 2 // Requesting all info about a netgame. +#define UPID_GAME_INFO_REQ_SIZE 11 +#define UPID_GAME_INFO 3 // Packet containing all info about a netgame. +#define UPID_GAME_INFO_SIZE 529 +#define UPID_GAME_INFO_LITE_REQ 4 // Requesting lite info about a netgame. Used for discovering games. +#define UPID_GAME_INFO_LITE 5 // Packet containing lite netgame info. +#define UPID_GAME_INFO_LITE_SIZE 69 +#define UPID_DUMP 6 // Packet containing why player cannot join this game. +#define UPID_DUMP_SIZE 2 +#define UPID_ADDPLAYER 7 // Packet from Host containing info about a new player. +#define UPID_REQUEST 8 // New player says: "I want to be inside of you!" (haha, sorry I could not resist) / Packet containing request to join the game actually. +#define UPID_QUIT_JOINING 9 // Packet from a player who suddenly quits joining. +#define UPID_SEQUENCE_SIZE 14 +#define UPID_SYNC 10 // Packet from host containing full netgame info to sync players up. +#define UPID_OBJECT_DATA 11 // Packet from host containing object buffer. +#define UPID_PING 12 // Packet from host containing his GameTime and the Ping list. Client returns this time to host as UPID_PONG and adapts the ping list. +#define UPID_PING_SIZE 37 +#define UPID_PONG 13 // Packet answer from client to UPID_PING. Contains the time the initial ping packet was sent. +#define UPID_PONG_SIZE 10 +#define UPID_ENDLEVEL_H 14 // Packet from Host to all Clients containing connect-states and kills information about everyone in the game. +#define UPID_ENDLEVEL_C 15 // Packet from Client to Host containing connect-state and kills information from this Client. +#define UPID_PDATA_H 16 // Packet from Host to all Clients containing all players movement data. +#define UPID_PDATA_C 17 // Packet from Client to Host containing his movement data. +#define UPID_MDATA_P0 18 // Packet containing multi buffer from a player. Priority 0 - no ACK needed. +#define UPID_MDATA_P1 19 // Packet containing multi buffer from a player. Priority 1 - ACK needed. Also contains pkt_num +#define UPID_MDATA_ACK 20 // ACK packet for UPID_MDATA_P1. +#define UPID_MAX_SIZE 1024 // Max size for a packet +#define UPID_MDATA_BUF_SIZE 454 #ifdef USE_TRACKER -# define UPID_TRACKER_VERIFY 21 // The tracker has successfully gotten a hold of us -# define UPID_TRACKER_INCGAME 22 // The tracker is sending us some game info +# define UPID_TRACKER_VERIFY 21 // The tracker has successfully gotten a hold of us +# define UPID_TRACKER_INCGAME 22 // The tracker is sending us some game info #endif // Structure keeping lite game infos (for netlist, etc.) @@ -90,47 +92,47 @@ typedef struct UDP_netgame_info_lite typedef struct UDP_sequence_packet { - ubyte type; - netplayer_info player; + ubyte type; + netplayer_info player; } __pack__ UDP_sequence_packet; // player position packet structure typedef struct UDP_frame_info { - ubyte type; - ubyte Player_num; - ubyte connected; - ubyte obj_render_type; - shortpos pos; + ubyte type; + ubyte Player_num; + ubyte connected; + ubyte obj_render_type; + shortpos pos; } __pack__ UDP_frame_info; // packet structure for multi-buffer typedef struct UDP_mdata_info { - ubyte type; - ubyte Player_num; - uint32_t pkt_num; - ushort mbuf_size; - ubyte mbuf[UPKT_MBUF_SIZE]; + ubyte type; + ubyte Player_num; + uint32_t pkt_num; + ushort mbuf_size; + ubyte mbuf[UPID_MDATA_BUF_SIZE]; } __pack__ UDP_mdata_info; // structure to store MDATA to maybe resend typedef struct UDP_mdata_store { - int used; - fix64 pkt_initial_timestamp; // initial timestamp to see if packet is outdated - fix64 pkt_timestamp[MAX_PLAYERS]; // Packet timestamp - int pkt_num; // Packet number - ubyte Player_num; // sender of this packet - ubyte player_ack[MAX_PLAYERS]; // 0 if player has not ACK'd this packet, 1 if ACK'd or not connected - ubyte data[UPKT_MBUF_SIZE]; // extra data of a packet - contains all multibuf data we don't want to loose - ushort data_size; + int used; + fix64 pkt_initial_timestamp; // initial timestamp to see if packet is outdated + fix64 pkt_timestamp[MAX_PLAYERS]; // Packet timestamp + int pkt_num; // Packet number + ubyte Player_num; // sender of this packet + ubyte player_ack[MAX_PLAYERS]; // 0 if player has not ACK'd this packet, 1 if ACK'd or not connected + ubyte data[UPID_MDATA_BUF_SIZE]; // extra data of a packet - contains all multibuf data we don't want to loose + ushort data_size; } __pack__ UDP_mdata_store; // structure to keep track of MDATA packets we've already got typedef struct UDP_mdata_recv { - int pkt_num[UDP_MDATA_STOR_QUEUE_SIZE]; - int cur_slot; // index we can use for a new pkt_num + int pkt_num[UDP_MDATA_STOR_QUEUE_SIZE]; + int cur_slot; // index we can use for a new pkt_num } __pack__ UDP_mdata_recv;