ref: 520c938f0b269be3c1909ddd9b8ed33af44fd299
parent: 0affe02b61bd29c83404270323f8e7a8b8c40a14
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 17 15:30:24 EST 2017
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))
--- 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,6 +7,7 @@
#include "dat.h"
#include "fns.h"
#include "../ip/ip.h"
+#include "../ip/ipv6.h"
#include "../port/netif.h"
#include "../port/error.h"
@@ -13,7 +14,6 @@
typedef struct Bridge Bridge;
typedef struct Port Port;
typedef struct Centry Centry;
-typedef struct Iphdr Iphdr;
typedef struct Tcphdr Tcphdr;
enum
@@ -138,29 +138,14 @@
};
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) */
+ TCPHDR = 20,
};
-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 */
-};
-
struct Tcphdr
{
uchar sport[2];
@@ -864,34 +849,38 @@
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 @@
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 @@
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 @@
static int
fragment(Etherpkt *epkt, int n)
{
- Iphdr *iphdr;
+ Ip4hdr *iphdr;
if(n <= TunnelMtu)
return 0;
@@ -1036,7 +1026,7 @@
/* 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
@@ -1043,7 +1033,7 @@
* 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 @@
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 @@
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 @@
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){
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -79,6 +79,7 @@
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