[net] Move found host caching into net_main

This unifies all the checks and plugs a set of potential buffer
overflows.
This commit is contained in:
Bill Currie 2021-04-04 18:38:14 +09:00
parent a630c95eb6
commit 9fb337fac4
4 changed files with 85 additions and 72 deletions

View file

@ -262,8 +262,9 @@ typedef struct {
netadr_t addr;
} hostcache_t;
extern int hostCacheCount;
extern hostcache_t hostcache[HOSTCACHESIZE];
void NET_AddCachedHost (const char *name, const char *map, const char *cname,
int users, int maxusers, int driver, int ldriver,
const netadr_t *addr);
extern double net_time;
extern struct msg_s *net_message;

View file

@ -97,9 +97,11 @@ qboolean recording = false;
int net_driverlevel;
double net_time;
static int hostCacheCount = 0;
static hostcache_t hostcache[HOSTCACHESIZE];
double
SetNetTime (void)
{
@ -265,6 +267,58 @@ PrintSlistHeader (void)
slistLastShown = 0;
}
void
NET_AddCachedHost (const char *name, const char *map, const char *cname,
int users, int maxusers, int driver, int ldriver,
const netadr_t *addr)
{
if (hostCacheCount == HOSTCACHESIZE) {
return;
}
for (int i = 0; i < hostCacheCount; i++) {
// addr will be 0 for loopback, and there can be only one loopback
// server.
if (!addr || !memcmp (addr, &hostcache[i].addr, sizeof (netadr_t))) {
return;
}
}
const int namesize = sizeof (hostcache[0].name) - 1;
const int mapsize = sizeof (hostcache[0].map) - 1;
const int cnamesize = sizeof (hostcache[0].cname) - 1;
hostcache_t *host = &hostcache[hostCacheCount++];
strncpy (host->name, name, namesize);
strncpy (host->map, map, mapsize);
strncpy (host->cname, cname, cnamesize);
host->name[namesize] = 0;
host->map[mapsize] = 0;
host->cname[cnamesize] = 0;
host->users = users;
host->maxusers = maxusers;
host->driver = driver;
host->ldriver = ldriver;
if (addr) {
host->addr = *addr;
} else {
memset (&host->addr, 0, sizeof (host->addr));
}
// check for and resolve name conflicts
for (int i = 0; i < hostCacheCount - 1; i++) {
if (strcasecmp (host->name, hostcache[i].name) == 0) {
int len = strlen (host->name);
if (len < namesize && host->name[len - 1] > '8') {
host->name[len] = '0';
host->name[len + 1] = 0;
} else {
host->name[len - 1]++;
}
i = -1; // restart loop
}
}
}
static void
PrintSlist (void)
@ -359,10 +413,6 @@ Slist_Poll (void *unused)
slistLocal = true;
}
int hostCacheCount = 0;
hostcache_t hostcache[HOSTCACHESIZE];
qsocket_t *
NET_Connect (const char *host)
{

View file

@ -880,8 +880,6 @@ static void
_Datagram_SearchForHosts (qboolean xmit)
{
int ret;
int n;
int i;
netadr_t readaddr;
netadr_t myaddr;
int control;
@ -914,11 +912,6 @@ _Datagram_SearchForHosts (qboolean xmit)
continue;
}
// is the cache full?
if (hostCacheCount == HOSTCACHESIZE) {
continue;
}
MSG_BeginReading (net_message);
control = MSG_ReadLongBE (net_message);
if (control == -1) {
@ -935,53 +928,25 @@ _Datagram_SearchForHosts (qboolean xmit)
continue;
}
dfunc.GetAddrFromName (MSG_ReadString (net_message), &readaddr);
// search the cache for this server
for (n = 0; n < hostCacheCount; n++) {
if (dfunc.AddrCompare (&readaddr, &hostcache[n].addr) == 0) {
break;
}
const char *addrstr = MSG_ReadString (net_message);
dfunc.GetAddrFromName (addrstr, &readaddr);
const char *name = MSG_ReadString (net_message);
const char *map = MSG_ReadString (net_message);
int users = MSG_ReadByte (net_message);
int maxusers = MSG_ReadByte (net_message);
int protocol = MSG_ReadByte (net_message);
const char *cname = dfunc.AddrToString (&readaddr);
if (protocol != NET_PROTOCOL_VERSION) {
char *new_name = alloca (strlen (name) + 2);
new_name[0] = '*';
strcpy (new_name + 1, name);
name = new_name;
}
// is it already there?
if (n < hostCacheCount) {
continue;
}
// add it
hostCacheCount++;
strcpy (hostcache[n].name, MSG_ReadString (net_message));
strcpy (hostcache[n].map, MSG_ReadString (net_message));
hostcache[n].users = MSG_ReadByte (net_message);
hostcache[n].maxusers = MSG_ReadByte (net_message);
if (MSG_ReadByte (net_message) != NET_PROTOCOL_VERSION) {
strcpy (hostcache[n].cname, hostcache[n].name);
hostcache[n].cname[14] = 0;
strcpy (hostcache[n].name, "*");
strcat (hostcache[n].name, hostcache[n].cname);
}
memcpy (&hostcache[n].addr, &readaddr, sizeof (netadr_t));
hostcache[n].driver = net_driverlevel;
hostcache[n].ldriver = net_landriverlevel;
strcpy (hostcache[n].cname, dfunc.AddrToString (&readaddr));
// check for a name conflict
for (i = 0; i < hostCacheCount; i++) {
if (i == n) {
continue;
}
if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0) {
i = strlen (hostcache[n].name);
if (i < 15 && hostcache[n].name[i - 1] > '8') {
hostcache[n].name[i] = '0';
hostcache[n].name[i + 1] = 0;
} else {
hostcache[n].name[i - 1]++;
}
i = -1;
}
}
NET_AddCachedHost (name, map, cname, users, maxusers, net_driverlevel,
net_landriverlevel, &readaddr);
}
}
@ -990,9 +955,6 @@ Datagram_SearchForHosts (qboolean xmit)
{
for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers;
net_landriverlevel++) {
if (hostCacheCount == HOSTCACHESIZE) {
break;
}
if (net_landrivers[net_landriverlevel].initialized) {
_Datagram_SearchForHosts (xmit);
}

View file

@ -69,16 +69,16 @@ Loop_SearchForHosts (qboolean xmit)
if (!sv.active)
return;
hostCacheCount = 1;
if (strcmp (hostname->string, "UNNAMED") == 0)
strcpy (hostcache[0].name, "local");
else
strcpy (hostcache[0].name, hostname->string);
strcpy (hostcache[0].map, sv.name);
hostcache[0].users = net_activeconnections;
hostcache[0].maxusers = svs.maxclients;
hostcache[0].driver = net_driverlevel;
strcpy (hostcache[0].cname, "local");
const char *name = "local";
if (strcmp (hostname->string, "UNNAMED") != 0) {
name = hostname->string;
}
const char *map = sv.name;
int users = net_activeconnections;
int maxusers = svs.maxclients;
const char *cname = "local";
NET_AddCachedHost (name, map, cname, users, maxusers, net_driverlevel,
0, 0);
}