Rework of the SP_BADVERSION packet which is sent to the client if the CP_SOCKET packet contains incorrect protocol version number, or when the queue has no free slots, or when a player is banned, or when a connection is dropped due to netrekd denied IP list. - add symbolic names for the reason codes, - prepare the packet buffer with zeros to avoid data leaks, - document the current state of client processing of reason codes. This patch does not change the behaviour of the server, apart from starting with a packet buffer which is clean. Sat Jun 21 12:59:10 EST 2008 quozl at us.netrek.org * SP_BADVERSION, avoid leak, symbolise diff -rN -u old-netrek-server/Vanilla/include/packets.h new-netrek-server/Vanilla/include/packets.h --- old-netrek-server/Vanilla/include/packets.h 2008-06-21 13:10:57.000000000 +1000 +++ new-netrek-server/Vanilla/include/packets.h 2008-06-21 13:10:57.000000000 +1000 @@ -408,6 +408,18 @@ char pad3; }; +/* numbering and ordering per current usage as at 2008-06-21 */ +#define BADVERSION_SOCKET 0 /* CP_SOCKET version does not match, exiting */ +#define BADVERSION_DENIED 1 /* access denied by netrekd */ +#define BADVERSION_NOSLOT 1 /* no slot on queue */ +#define BADVERSION_BANNED 2 /* banned */ +#define BADVERSION_DOWN 6 /* game shutdown by server */ +#define BADVERSION_SILENCE 6 /* daemon stalled */ +#define BADVERSION_SELECT 6 /* internal error */ +/* as at 2008-06-21 netrek-client-cow and netrek-client-xp report 0 as + invalid version, 1-6 as cannot play, others are not valid, and + netrek-client-xp uses a popup message box for 1-6 */ + struct hostile_spacket { /* SP_HOSTILE py-struct "!bbbb" #22 */ char type; char pnum; diff -rN -u old-netrek-server/Vanilla/newstartd/newstartd.c new-netrek-server/Vanilla/newstartd/newstartd.c --- old-netrek-server/Vanilla/newstartd/newstartd.c 2008-06-21 13:10:57.000000000 +1000 +++ new-netrek-server/Vanilla/newstartd/newstartd.c 2008-06-21 13:10:57.000000000 +1000 @@ -539,8 +539,10 @@ } /* issue a bad version packet to the client */ + memset(&packet, 0, sizeof(struct badversion_spacket)); packet.type = SP_BADVERSION; - packet.why = 1; +#define BADVERSION_DENIED 1 /* access denied by netrekd */ + packet.why = BADVERSION_DENIED; write (0, (char *) &packet, sizeof(packet)); sleep (2); diff -rN -u old-netrek-server/Vanilla/ntserv/input.c new-netrek-server/Vanilla/ntserv/input.c --- old-netrek-server/Vanilla/ntserv/input.c 2008-06-21 13:10:57.000000000 +1000 +++ new-netrek-server/Vanilla/ntserv/input.c 2008-06-21 13:10:57.000000000 +1000 @@ -62,18 +62,19 @@ #endif /*PING*/ } -static void gamedown() +static void gamedown(why) { struct badversion_spacket packet; + memset(&packet, 0, sizeof(struct badversion_spacket)); packet.type = SP_BADVERSION; - packet.why = 6; + packet.why = why; sendClientPacket(&packet); flushSockBuf(); } -static void panic() +static void panic(int why) { - gamedown(); + gamedown(why); freeslot(me); exit(0); } @@ -94,7 +95,7 @@ freeslot(me); exit(0); } - if (!(status -> gameup & GU_GAMEOK)) panic(); + if (!(status -> gameup & GU_GAMEOK)) panic(BADVERSION_DOWN); /* wait for activity on network socket or next daemon update */ while (1) { FD_ZERO(&readfds); @@ -111,10 +112,10 @@ poll.tv_usec = 0; rv = select(nfds+1, &readfds, 0, 0, &poll); if (rv > 0) break; - if (rv == 0) { panic(); /* daemon silence timeout */ } + if (rv == 0) { panic(BADVERSION_SILENCE); /* daemon timeout */ } if (errno == EINTR) continue; perror("select"); - panic(); + panic(BADVERSION_SELECT); } /* if daemon signalled us, perform the update only */ if (FD_ISSET(afd, &readfds)) { diff -rN -u old-netrek-server/Vanilla/ntserv/main.c new-netrek-server/Vanilla/ntserv/main.c --- old-netrek-server/Vanilla/ntserv/main.c 2008-06-21 13:10:57.000000000 +1000 +++ new-netrek-server/Vanilla/ntserv/main.c 2008-06-21 13:10:57.000000000 +1000 @@ -34,7 +34,7 @@ #endif /* file scope prototypes */ -static void noplay(); +static void noplay(int reason); static void reaper(int); static void printUsage(char *prog); static void sendMotd(void); @@ -149,7 +149,7 @@ if (host && ip) { if ((bans_check_permanent(login, host) == TRUE) || (bans_check_permanent(login, ip) == TRUE)) { - noplay(2); + noplay(BADVERSION_BANNED); ERROR(2,("ntserv/main.c: premature disconnect of %s due to permanent ban\n", ip)); exit(1); } @@ -188,7 +188,7 @@ /* wait for a slot to become free */ pno = findslot(w_queue); if (pno < 0) { - noplay(1); + noplay(BADVERSION_NOSLOT); ERROR(2,("ntserv/main.c: Quitting: No slot available on queue %d\n",w_queue)); exit(1); } @@ -420,11 +420,12 @@ } } -void noplay(int reason) +static void noplay(int reason) { /* trigger client's "Sorry, but you cannot play xtrek now. Try again later." */ struct badversion_spacket packet; + memset(&packet, 0, sizeof(struct badversion_spacket)); packet.type = SP_BADVERSION; packet.why = reason; sendClientPacket (&packet); diff -rN -u old-netrek-server/Vanilla/ntserv/socket.c new-netrek-server/Vanilla/ntserv/socket.c --- old-netrek-server/Vanilla/ntserv/socket.c 2008-06-21 13:10:57.000000000 +1000 +++ new-netrek-server/Vanilla/ntserv/socket.c 2008-06-21 13:10:57.000000000 +1000 @@ -1818,8 +1818,9 @@ struct badversion_spacket packet; if (userVersion != SOCKVERSION) { - packet.type=SP_BADVERSION; - packet.why=0; + memset(&packet, 0, sizeof(struct badversion_spacket)); + packet.type = SP_BADVERSION; + packet.why = BADVERSION_SOCKET; sendClientPacket((CVOID) &packet); flushSockBuf(); return 0; -- James Cameron mailto:quozl at us.netrek.org http://quozl.netrek.org/