diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 1a755239d..8c239e521 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -2686,25 +2686,31 @@ void CL_Packet_f (void) } - if (Cmd_FromGamecode()) //some mvd servers stuffcmd a packet command which lets them know which ip the client is from. - { //unfortunatly, 50% of servers are badly configured. + if (Cmd_FromGamecode()) //some mvdsv servers stuffcmd a packet command which lets them know which ip the client is from. + { //unfortunatly, 50% of servers are badly configured resulting in them poking local services that THEY MUST NOT HAVE ACCESS TO. + char *addrdesc; + char *realdesc; if (cls.demoplayback) { Con_DPrintf ("Not sending realip packet from demo\n"); return; } - if (adr.type == NA_IP) - if ((adr.address.ip[0] == 127 && adr.address.ip[1] == 0 && adr.address.ip[2] == 0 && adr.address.ip[3] == 1) || - (adr.address.ip[0] == 0 && adr.address.ip[1] == 0 && adr.address.ip[2] == 0 && adr.address.ip[3] == 0)) + if (!NET_CompareAdr(&adr, &cls.netchan.remote_address)) + { + if (NET_ClassifyAddress(&adr, &addrdesc) < ASCOPE_LAN) { - adr.address.ip[0] = cls.netchan.remote_address.address.ip[0]; - adr.address.ip[1] = cls.netchan.remote_address.address.ip[1]; - adr.address.ip[2] = cls.netchan.remote_address.address.ip[2]; - adr.address.ip[3] = cls.netchan.remote_address.address.ip[3]; - adr.port = cls.netchan.remote_address.port; - Con_Printf (CON_WARNING "Server is broken. Trying to send to server instead.\n"); + if (NET_ClassifyAddress(&cls.netchan.remote_address, &realdesc) < ASCOPE_LAN) + { //this isn't necessarily buggy... but its still a potential exploit so we need to block it regardless. + Con_Printf (CON_WARNING "Ignoring buggy %s realip request for %s server.\n", addrdesc, realdesc); + } + else + { + adr = cls.netchan.remote_address; + Con_Printf (CON_WARNING "Ignoring buggy %s realip request, sending to %s server instead.\n", addrdesc, realdesc); + } } + } cls.realserverip = adr; Con_DPrintf ("Sending realip packet\n"); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index 1887a7df6..1ce6bf686 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -387,6 +387,16 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate) return false; } +int Netchan_CanBytes (netchan_t *chan, int rate) +{ + const double slop = 0.25; + if (chan->remote_address.type == NA_LOOPBACK) + return 0x7fffffff; //don't ever drop packets due to possible routing problems when there is no routing. + if (!rate) + return 0x7fffffff; + return ((realtime+slop)-chan->cleartime)*rate; +} + void Netchan_Block (netchan_t *chan, int bytes, int rate) { if (rate) @@ -583,6 +593,9 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) int i; neterr_t e; + int dupes = chan->dupe; + int availbytes = Netchan_CanBytes(chan, rate); + #ifdef NQPROT if (chan->isnqprotocol) { @@ -789,10 +802,11 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) #endif { int hsz = 10 + ((chan->sock == NS_CLIENT)?chan->qportsize:0); /*header size, if fragmentation is in use*/ + dupes = min(chan->dupe, availbytes / send.cursize); if ((!chan->pext_fragmentation))// || send.cursize < ((chan->mtu - hsz)&~7)) { //vanilla sends - for (i = -1; i < chan->dupe && e == NETERR_SENT; i++) + for (i = -1; i < dupes && e == NETERR_SENT; i++) e = NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address); send.cursize += send.cursize * i; @@ -809,6 +823,8 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) { //fte's fragmentaton protocol int offset = 0, no; qboolean more; + int outbytes = 0; + int fragbytes; /*FIXME: splurge over a number of frames, if we have an outgoing reliable*/ @@ -842,9 +858,11 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) if (e == NETERR_SENT) { - for (i = -1; i < chan->dupe && e == NETERR_SENT; i++) + for (i = -1; i < dupes && e == NETERR_SENT; i++) { - e = NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset, &chan->remote_address); + fragbytes = (no - offset) + hsz; + e = NET_SendPacket (chan->sock, fragbytes, send.data + offset, &chan->remote_address); + outbytes += fragbytes; if (e == NETERR_MTU && !offset && chan->mtu > 560) { chan->mtu -= 16; @@ -857,6 +875,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) } offset = no; } while(more); + send.cursize = outbytes; } } @@ -939,8 +958,8 @@ qboolean Netchan_Process (netchan_t *chan) reliable_message = sequence >> 31; reliable_ack = sequence_ack >> 31; - sequence &= ~(1<<31); - sequence_ack &= ~(1<<31); + sequence &= ~(1u<<31); + sequence_ack &= ~(1u<<31); if (showpackets.value) Con_Printf ("%f %s <-- s=%i(%i) a=%i(%i) %i%s\n" diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index d1ee2e12a..0274fc63a 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -159,7 +159,7 @@ static void QDECL NET_Enable_DTLS_Changed(struct cvar_s *var, char *oldvalue) } } } -cvar_t net_enable_dtls = CVARAFCD("net_enable_dtls", "", "sv_listen_dtls", 0, NET_Enable_DTLS_Changed, "Controls serverside dtls support.\n0: dtls blocked, not advertised.\n1: available in desired.\n2: used where possible (recommended setting).\n3: disallow non-dtls clients (sv_port_tcp should be eg tls://[::]:27500 to also disallow unencrypted tcp connections)."); +cvar_t net_enable_dtls = CVARAFCD("net_enable_dtls", "", "sv_listen_dtls", 0, NET_Enable_DTLS_Changed, "Controls serverside dtls support.\n0: dtls blocked, not advertised.\n1: clientside choice.\n2: used where possible (recommended setting).\n3: disallow non-dtls clients (sv_port_tcp should be eg tls://[::]:27500 to also disallow unencrypted tcp connections)."); #endif #ifdef HAVE_CLIENT @@ -372,6 +372,8 @@ qboolean NET_CompareAdr (netadr_t *a, netadr_t *b) if (a->type != b->type) { int i; + if (a->port != b->port) + return false; if (a->type == NA_IP && b->type == NA_IPV6) { for (i = 0; i < 10; i++) @@ -7193,6 +7195,28 @@ int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_gener return found; } +static enum addressscope_e NET_ClassifyAddressipv4(int ip, char **outdesc) +{ + int scope = ASCOPE_NET; + char *desc = NULL; + if ((ip&BigLong(0xffff0000)) == BigLong(0xA9FE0000)) //169.254.x.x/16 + scope = ASCOPE_LINK, desc = "link-local"; + else if ((ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8 + scope = ASCOPE_LAN, desc = "private"; + else if ((ip&BigLong(0xff000000)) == BigLong(0x7f000000)) //127.x.x.x/8 + scope = ASCOPE_HOST, desc = "localhost"; + else if ((ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12 + scope = ASCOPE_LAN, desc = "private"; + else if ((ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16 + scope = ASCOPE_LAN, desc = "private"; + else if ((ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //100.64.x.x/10 + scope = ASCOPE_LAN, desc = "CGNAT"; + else if (ip == BigLong(0x00000000)) //0.0.0.0/32 + scope = ASCOPE_LAN, desc = "any"; + + *outdesc = desc; + return scope; +} enum addressscope_e NET_ClassifyAddress(netadr_t *adr, char **outdesc) { int scope = ASCOPE_NET; @@ -7217,24 +7241,15 @@ enum addressscope_e NET_ClassifyAddress(netadr_t *adr, char **outdesc) scope = ASCOPE_HOST, desc = "localhost"; else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0) //:: scope = ASCOPE_NET, desc = "any"; + else if (memcmp(adr->address.ip6, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12) == 0) //::ffff:x.y.z.w + { + scope = NET_ClassifyAddressipv4(*(int*)(adr->address.ip6+12), &desc); + if (!desc) + desc = "vp-mapped"; + } } else if (adr->type == NA_IP) - { - if ((*(int*)adr->address.ip&BigLong(0xffff0000)) == BigLong(0xA9FE0000)) //169.254.x.x/16 - scope = ASCOPE_LINK, desc = "link-local"; - else if ((*(int*)adr->address.ip&BigLong(0xff000000)) == BigLong(0x0a000000)) //10.x.x.x/8 - scope = ASCOPE_LAN, desc = "private"; - else if ((*(int*)adr->address.ip&BigLong(0xff000000)) == BigLong(0x7f000000)) //127.x.x.x/8 - scope = ASCOPE_HOST, desc = "localhost"; - else if ((*(int*)adr->address.ip&BigLong(0xfff00000)) == BigLong(0xac100000)) //172.16.x.x/12 - scope = ASCOPE_LAN, desc = "private"; - else if ((*(int*)adr->address.ip&BigLong(0xffff0000)) == BigLong(0xc0a80000)) //192.168.x.x/16 - scope = ASCOPE_LAN, desc = "private"; - else if ((*(int*)adr->address.ip&BigLong(0xffc00000)) == BigLong(0x64400000)) //100.64.x.x/10 - scope = ASCOPE_LAN, desc = "CGNAT"; - else if (*(int*)adr->address.ip == BigLong(0x00000000)) //0.0.0.0/32 - scope = ASCOPE_LAN, desc = "any"; - } + scope = NET_ClassifyAddressipv4(*(int*)adr->address.ip, &desc); if (outdesc) *outdesc = desc; return scope; diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index 795ec1de1..f1524ca87 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -91,6 +91,7 @@ void R_NetGraph (void) int a, x, i; float y; float pi, po, bi, bo; + int errorbar; vec2_t p[4]; vec2_t tc[4]; @@ -120,10 +121,10 @@ void R_NetGraph (void) for (a=0 ; a= 0) - last = -last; +// else if (last >= 0) +// last = -last; R_LineGraph (NET_TIMINGS-1-a, last); } } @@ -188,6 +189,7 @@ void R_NetGraph (void) Vector2Set(p[3], 0,0); Vector4Set(rgba[2], 0,0,0,0); Vector4Set(rgba[3], 0,0,0,0); + errorbar = 1; //first is discontinuous for (a=0 ; a>0)&0xff)/255.0, ((ngraph[a].col>>8)&0xff)/255.0, ((ngraph[a].col>>16)&0xff)/255.0, ((ngraph[a].col>>24)&0xff)/255.0); Vector4Copy(rgba[2+0], rgba[2+1]); - if (a) - R2D_Image2dQuad((const vec2_t*)p, (const vec2_t*)tc, (const vec4_t*)rgba, shader_draw_fill); + if (ngraph[a].height==1) + errorbar = 2; //this one and the following should be discontiguous + if (errorbar --> 0) + { //if this is a full-height bar, break the smooth curve and just make it discontinuous + p[0][1] = p[3][1]; + p[1][1] = p[2][1]; + Vector4Copy(rgba[3], rgba[0]); + Vector4Copy(rgba[2], rgba[1]); + } + + R2D_Image2dQuad((const vec2_t*)p, (const vec2_t*)tc, (const vec4_t*)rgba, shader_draw_fill); } #endif } diff --git a/plugins/models/gltf.c b/plugins/models/gltf.c index 2f736bcc9..9f571930b 100644 --- a/plugins/models/gltf.c +++ b/plugins/models/gltf.c @@ -279,6 +279,30 @@ static qboolean JSON_Equals(json_t *t, const char *child, const char *expected) return false; } #include +static quintptr_t JSON_GetUInteger(json_t *t, const char *child, unsigned int fallback) +{ + if (child) + t = JSON_FindChild(t, child); + if (t) + { //copy it to another buffer. can probably skip that tbh. + char tmp[MAX_QPATH]; + char *trail; + size_t l = t->bodyend-t->bodystart; + quintptr_t r; + if (l > MAX_QPATH-1) + l = MAX_QPATH-1; + memcpy(tmp, t->bodystart, l); + tmp[l] = 0; + if (!strcmp(tmp, "false")) //special cases, for booleans + return 0u; + if (!strcmp(tmp, "true")) //special cases, for booleans + return 1u; + r = (quintptr_t)strtoull(tmp, &trail, 0); + if (!*trail) + return r; + } + return fallback; +} static qintptr_t JSON_GetInteger(json_t *t, const char *child, int fallback) { if (child) @@ -286,7 +310,9 @@ static qintptr_t JSON_GetInteger(json_t *t, const char *child, int fallback) if (t) { //copy it to another buffer. can probably skip that tbh. char tmp[MAX_QPATH]; + char *trail; size_t l = t->bodyend-t->bodystart; + qintptr_t r; if (l > MAX_QPATH-1) l = MAX_QPATH-1; memcpy(tmp, t->bodystart, l); @@ -295,7 +321,9 @@ static qintptr_t JSON_GetInteger(json_t *t, const char *child, int fallback) return 0; if (!strcmp(tmp, "true")) //special cases, for booleans return 1; - return (qintptr_t)strtoll(tmp, NULL, 0); + r = (qintptr_t)strtoll(tmp, &trail, 0); + if (!*trail) + return r; } return fallback; } @@ -588,7 +616,7 @@ static struct gltf_buffer *GLTF_GetBufferData(gltf_t *gltf, int bufferidx) { json_t *b = JSON_FindIndexedChild(gltf->r, "buffers", bufferidx); json_t *uri = JSON_FindChild(b, "uri"); - size_t length = JSON_GetInteger(b, "byteLength", 0); + size_t length = JSON_GetUInteger(b, "byteLength", 0); struct gltf_buffer *out; // JSON_WarnIfChild(b, "name"); @@ -649,9 +677,9 @@ static qboolean GLTF_GetBufferViewData(gltf_t *gltf, int bufferview, struct gltf buf = GLTF_GetBufferData(gltf, JSON_GetInteger(bv, "buffer", 0)); if (!buf) return false; - offset = JSON_GetInteger(bv, "byteOffset", 0); + offset = JSON_GetUInteger(bv, "byteOffset", 0); view->data = (char*)buf->data + offset; - view->length = JSON_GetInteger(bv, "byteLength", 0); //required + view->length = JSON_GetUInteger(bv, "byteLength", 0); //required view->bytestride = JSON_GetInteger(bv, "byteStride", 0); if (offset + view->length > buf->length) return false; @@ -691,7 +719,7 @@ static qboolean GLTF_GetAccessor(gltf_t *gltf, int accessorid, struct gltf_acces if (!GLTF_GetBufferViewData(gltf, JSON_GetInteger(a, "bufferView", 0), &bv)) return false; - offset = JSON_GetInteger(a, "byteOffset", 0); + offset = JSON_GetUInteger(a, "byteOffset", 0); if (offset > bv.length) return false; out->length = bv.length - offset;