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/