summaryrefslogtreecommitdiff
path: root/sys/src/9/port
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-09-17 13:32:58 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-09-17 13:32:58 +0000
commit5a1c1b590d319d58a178c6d299e99142bf7d4433 (patch)
tree7dd34e3085dae2fb95317c0d0c0d15081b11a03a /sys/src/9/port
parent05b08f6665b8b0c14c0cb4caa42929db8d26c6c9 (diff)
devip: do tcp mss clamping when forwarding packets
when forwarding packets (gating), unconditionally check tcp-syn packets for the mss-size option and reduce it to fit the mtu of the outgoing interface. this is done by exporting a new tcpmssclamp() function from ip/tcp.c that takes an ip packet and its buffer size and the effective mtu of the interface and adjusts the mss value of tcp syn options. this function is now also used by devbridge, enforcing a tcp mss below the tunnel mtu.
Diffstat (limited to 'sys/src/9/port')
-rw-r--r--sys/src/9/port/devbridge.c100
1 files changed, 1 insertions, 99 deletions
diff --git a/sys/src/9/port/devbridge.c b/sys/src/9/port/devbridge.c
index d4413cf71..4fcd7c392 100644
--- a/sys/src/9/port/devbridge.c
+++ b/sys/src/9/port/devbridge.c
@@ -40,7 +40,6 @@ enum {
CacheTimeout= 5*60, /* timeout for cache entry in seconds */
MaxMTU= IP_MAX, /* allow for jumbo frames and large UDP */
- TcpMssMax = 1300, /* max desirable Tcp MSS value */
TunnelMtu = 1400,
};
@@ -153,27 +152,6 @@ struct Port
uchar member[0x1000/8];
};
-enum {
- EOLOPT = 0,
- NOOPOPT = 1,
- MSSOPT = 2,
- MSS_LENGTH = 4, /* Mean segment size */
- SYN = 0x02, /* Pkt. is synchronise */
- TCPHDR = 20,
-};
-
-struct Tcphdr
-{
- uchar sport[2];
- uchar dport[2];
- uchar seq[4];
- uchar ack[4];
- uchar flag[2];
- uchar win[2];
- uchar cksum[2];
- uchar urg[2];
-};
-
static Bridge *bridgetab[Maxbridge];
static int bridgegen(Chan *c, char*, Dirtab*, int, int s, Dir *dp);
@@ -1011,89 +989,13 @@ ethermultiwrite(Bridge *b, Block *bp, int portid, ushort tag)
static void
tcpmsshack(Etherpkt *epkt, int n)
{
- int hl, optlen;
- Tcphdr *tcphdr;
- ulong mss, cksum;
- uchar *optr;
-
/* ignore non-ip packets */
switch(nhgets(epkt->type)){
case ETIP4:
case ETIP6:
+ tcpmssclamp(epkt->data, n-ETHERHDRSIZE, TunnelMtu-ETHERHDRSIZE);
break;
- default:
- return;
- }
- n -= ETHERHDRSIZE;
- if(n < 1)
- return;
- switch(epkt->data[0]&0xF0){
- case IP_VER4:
- hl = (epkt->data[0]&15)<<2;
- if(n < hl+TCPHDR || hl < IP4HDR || epkt->data[9] != TCP)
- return;
- n -= hl;
- tcphdr = (Tcphdr*)(epkt->data + hl);
- break;
- case IP_VER6:
- if(n < IP6HDR+TCPHDR || epkt->data[6] != TCP)
- return;
- n -= IP6HDR;
- tcphdr = (Tcphdr*)(epkt->data + IP6HDR);
- break;
- default:
- return;
- }
-
- /* MSS can only appear in SYN packet */
- if(!(tcphdr->flag[1] & SYN))
- return;
- hl = (tcphdr->flag[0] & 0xf0)>>2;
- if(n < hl)
- return;
-
- /* check for MSS option */
- optr = (uchar*)tcphdr + TCPHDR;
- n = hl - TCPHDR;
- for(;;) {
- if(n <= 0 || *optr == EOLOPT)
- return;
- if(*optr == NOOPOPT) {
- n--;
- optr++;
- continue;
- }
- optlen = optr[1];
- if(optlen < 2 || optlen > n)
- return;
- if(*optr == MSSOPT && optlen == MSS_LENGTH)
- break;
- n -= optlen;
- optr += optlen;
- }
-
- mss = nhgets(optr+2);
- if(mss <= TcpMssMax)
- return;
-
- /* fix checksum */
- cksum = nhgets(tcphdr->cksum);
- if(optr-(uchar*)tcphdr & 1) {
- // odd alignments are a pain
- cksum += nhgets(optr+1);
- cksum -= (optr[1]<<8)|(TcpMssMax>>8);
- cksum += (cksum>>16);
- cksum &= 0xffff;
- cksum += nhgets(optr+3);
- cksum -= ((TcpMssMax&0xff)<<8)|optr[4];
- cksum += (cksum>>16);
- } else {
- cksum += mss;
- cksum -= TcpMssMax;
- cksum += (cksum>>16);
}
- hnputs(tcphdr->cksum, cksum);
- hnputs(optr+2, TcpMssMax);
}
/*