From 520c938f0b269be3c1909ddd9b8ed33af44fd299 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 17 Dec 2017 20:30:24 +0100 Subject: [PATCH] devbridge: fix mss clamping - use protocol constants from ip/ip.h and ip/ipv6.h - support mss clamping for ipv6 - fix padding bug on 64 bit machines (can't use sizeof(Tcphdr)) --- sys/src/9/port/devbridge.c | 94 +++++++++++++++++--------------------- sys/src/9/port/portmkfile | 1 + 2 files changed, 43 insertions(+), 52 deletions(-) diff --git a/sys/src/9/port/devbridge.c b/sys/src/9/port/devbridge.c index 4f5101040..faba1145b 100644 --- a/sys/src/9/port/devbridge.c +++ b/sys/src/9/port/devbridge.c @@ -1,5 +1,5 @@ /* - * IPv4 Ethernet bridge + * IP Ethernet bridge */ #include "u.h" #include "../port/lib.h" @@ -7,13 +7,13 @@ #include "dat.h" #include "fns.h" #include "../ip/ip.h" +#include "../ip/ipv6.h" #include "../port/netif.h" #include "../port/error.h" typedef struct Bridge Bridge; typedef struct Port Port; typedef struct Centry Centry; -typedef struct Iphdr Iphdr; typedef struct Tcphdr Tcphdr; enum @@ -138,27 +138,12 @@ struct Port }; enum { - IP_TCPPROTO = 6, EOLOPT = 0, NOOPOPT = 1, MSSOPT = 2, MSS_LENGTH = 4, /* Mean segment size */ SYN = 0x02, /* Pkt. is synchronise */ - IPHDR = 20, /* sizeof(Iphdr) */ -}; - -struct Iphdr -{ - uchar vihl; /* Version and header length */ - uchar tos; /* Type of service */ - uchar length[2]; /* packet length */ - uchar id[2]; /* ip->identification */ - uchar frag[2]; /* Fragment information */ - uchar ttl; /* Time to live */ - uchar proto; /* Protocol */ - uchar cksum[2]; /* Header checksum */ - uchar src[4]; /* IP source */ - uchar dst[4]; /* IP destination */ + TCPHDR = 20, }; struct Tcphdr @@ -864,34 +849,38 @@ static void tcpmsshack(Etherpkt *epkt, int n) { int hl, optlen; - Iphdr *iphdr; Tcphdr *tcphdr; ulong mss, cksum; uchar *optr; /* ignore non-ipv4 packets */ - if(nhgets(epkt->type) != ETIP4) + switch(nhgets(epkt->type)){ + case ETIP4: + case ETIP6: + break; + default: return; - iphdr = (Iphdr*)(epkt->data); + } n -= ETHERHDRSIZE; - if(n < IPHDR) + if(n < 1) return; - - /* ignore bad packets */ - if(iphdr->vihl != (IP_VER4|IP_HLEN4)) { - hl = (iphdr->vihl&0xF)<<2; - if((iphdr->vihl&0xF0) != IP_VER4 || hl < (IP_HLEN4<<2)) + 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; - } else - hl = IP_HLEN4<<2; - - /* ignore non-tcp packets */ - if(iphdr->proto != IP_TCPPROTO) + 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; - n -= hl; - if(n < sizeof(Tcphdr)) - return; - tcphdr = (Tcphdr*)((uchar*)(iphdr) + hl); + } // MSS can only appear in SYN packet if(!(tcphdr->flag[1] & SYN)) return; @@ -900,8 +889,8 @@ tcpmsshack(Etherpkt *epkt, int n) return; // check for MSS option - optr = (uchar*)tcphdr + sizeof(Tcphdr); - n = hl - sizeof(Tcphdr); + optr = (uchar*)tcphdr + TCPHDR; + n = hl - TCPHDR; for(;;) { if(n <= 0 || *optr == EOLOPT) return; @@ -922,10 +911,11 @@ tcpmsshack(Etherpkt *epkt, int n) mss = nhgets(optr+2); if(mss <= TcpMssMax) return; + // fit checksum cksum = nhgets(tcphdr->cksum); if(optr-(uchar*)tcphdr & 1) { -print("tcpmsshack: odd alignment!\n"); +// print("tcpmsshack: odd alignment!\n"); // odd alignments are a pain cksum += nhgets(optr+1); cksum -= (optr[1]<<8)|(TcpMssMax>>8); @@ -1028,7 +1018,7 @@ etherread(void *a) static int fragment(Etherpkt *epkt, int n) { - Iphdr *iphdr; + Ip4hdr *iphdr; if(n <= TunnelMtu) return 0; @@ -1036,14 +1026,14 @@ fragment(Etherpkt *epkt, int n) /* ignore non-ipv4 packets */ if(nhgets(epkt->type) != ETIP4) return 0; - iphdr = (Iphdr*)(epkt->data); + iphdr = (Ip4hdr*)(epkt->data); n -= ETHERHDRSIZE; /* * ignore: IP runt packets, bad packets (I don't handle IP * options for the moment), packets with don't-fragment set, * and short blocks. */ - if(n < IPHDR || iphdr->vihl != (IP_VER4|IP_HLEN4) || + if(n < IP4HDR || iphdr->vihl != (IP_VER4|IP_HLEN4) || iphdr->frag[0] & (IP_DF>>8) || nhgets(iphdr->length) > n) return 0; @@ -1053,7 +1043,7 @@ fragment(Etherpkt *epkt, int n) static void etherwrite(Port *port, Block *bp) { - Iphdr *eh, *feh; + Ip4hdr *eh, *feh; Etherpkt *epkt; int n, lid, len, seglen, dlen, blklen, mf; Block *nb; @@ -1075,26 +1065,26 @@ etherwrite(Port *port, Block *bp) return; } - seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7; - eh = (Iphdr*)(epkt->data); + seglen = (TunnelMtu - ETHERHDRSIZE - IP4HDR) & ~7; + eh = (Ip4hdr*)(epkt->data); len = nhgets(eh->length); frag = nhgets(eh->frag); mf = frag & IP_MF; frag <<= 3; - dlen = len - IPHDR; + dlen = len - IP4HDR; lid = nhgets(eh->id); - bp->rp += ETHERHDRSIZE+IPHDR; + bp->rp += ETHERHDRSIZE+IP4HDR; if(0) print("seglen=%d, dlen=%d, mf=%x, frag=%d\n", seglen, dlen, mf, frag); for(fragoff = 0; fragoff < dlen; fragoff += seglen) { - nb = allocb(ETHERHDRSIZE+IPHDR+seglen); + nb = allocb(ETHERHDRSIZE+IP4HDR+seglen); - feh = (Iphdr*)(nb->wp+ETHERHDRSIZE); + feh = (Ip4hdr*)(nb->wp+ETHERHDRSIZE); - memmove(nb->wp, epkt, ETHERHDRSIZE+IPHDR); - nb->wp += ETHERHDRSIZE+IPHDR; + memmove(nb->wp, epkt, ETHERHDRSIZE+IP4HDR); + nb->wp += ETHERHDRSIZE+IP4HDR; if((fragoff + seglen) >= dlen) { seglen = dlen - fragoff; @@ -1103,7 +1093,7 @@ etherwrite(Port *port, Block *bp) else hnputs(feh->frag, (frag+fragoff>>3) | IP_MF); - hnputs(feh->length, seglen + IPHDR); + hnputs(feh->length, seglen + IP4HDR); hnputs(feh->id, lid); if(seglen){ diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index d8b0ba395..1e15f04b1 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -79,6 +79,7 @@ trap.$O: ../port/systab.h devpipe.$O: ../port/netif.h netif.$O: ../port/netif.h devuart.$O: ../port/netif.h +devbridge.$O: ../port/netif.h ../ip/ip.h ../ip/ipv6.h devdraw.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/memlayer.h /sys/include/cursor.h devmouse.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h swcursor.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h