shithub: riscv

Download patch

ref: 3f0f52ab69a8e821fcd1ac66b8d509ee3074c266
parent: 7137060d85fe04cce4a1984550a636672df7df7d
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Dec 7 09:50:09 EST 2023

ether4330: dmat support

move dmatproxy() function in its own module so we can use it
independently of wifi.c.

--- a/sys/src/9/bcm/ether4330.c
+++ b/sys/src/9/bcm/ether4330.c
@@ -196,6 +196,7 @@
 	uchar	txwindow;
 	uchar	txseq;
 	uchar	rxseq;
+	DMAT	dmat;
 };
 
 enum{
@@ -1273,6 +1274,7 @@
 		b = qget(edev->oq);
 		if(b == nil)
 			break;
+		dmatproxy(b, 1, edev->ea, &ctl->dmat);
 		off = ((uintptr)b->rp & 3) + Sdpcmsz;
 		b = padblock(b, off + 4);
 		len = BLEN(b);
@@ -1377,6 +1379,7 @@
 				bdc = 4 + (b->rp[p->doffset + 3] << 2);
 				if(BLEN(b) >= p->doffset + bdc + ETHERHDRSIZE){
 					b->rp += p->doffset + bdc;	/* skip BDC header */
+					dmatproxy(b, 0, edev->ea, &ctl->dmat);
 					etheriq(edev, b);
 					continue;
 				}
--- a/sys/src/9/bcm64/pi3
+++ b/sys/src/9/bcm64/pi3
@@ -28,7 +28,7 @@
 link
 	archbcm3
 	usbdwc
-	ether4330
+	ether4330	dmat
 	ethermedium
 	loopbackmedium 
 	netdevmedium
--- a/sys/src/9/bcm64/pi4
+++ b/sys/src/9/bcm64/pi4
@@ -32,7 +32,7 @@
 	archbcm4	pci
 	usbxhcipci	pci usbxhci archbcm4 
 	ethergenet	ethermii
-	ether4330
+	ether4330	dmat
 	ethermedium
 	loopbackmedium
 	netdevmedium
--- a/sys/src/9/imx8/reform
+++ b/sys/src/9/imx8/reform
@@ -57,6 +57,7 @@
 	iomux
 	sdnvme	pci
 	sdmmc	usdhc
+	wifi	dmat
 port
 	int cpuserver = 0;
 bootdir
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -146,6 +146,8 @@
 	vgatvp3026	=cur
 	vgavesa
 	vgavmware	+cur
+
+	wifi		dmat
 	
 	dtracysys
 	dtracytimer
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -144,6 +144,8 @@
 	vgavesa
 #	vgavmware	+cur
 
+	wifi		dmat
+
 	dtracysys
 	dtracytimer
 	dtracydev
--- /dev/null
+++ b/sys/src/9/port/dmat.c
@@ -1,0 +1,196 @@
+/*
+ * Dynamic Mac Address Translation (DMAT)
+ *
+ * Wifi does not allow spoofing of the source mac which breaks
+ * bridging. To solve this we proxy mac addresses, maintaining
+ * a translation table from ip address to destination mac address.
+ * Upstream ARP and NDP packets get ther source mac address changed
+ * to proxy and a translation entry is added with the original mac
+ * for downstream translation. The proxy does not appear in the
+ * table.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/netif.h"
+#include "../port/etherif.h"
+#include "../ip/ip.h"
+#include "../ip/ipv6.h"
+
+void
+dmatproxy(Block *bp, int upstream, uchar proxy[Eaddrlen], DMAT *t)
+{
+	static uchar arp4[] = {
+		0x00, 0x01,
+		0x08, 0x00,
+		0x06, 0x04,
+		0x00,
+	};
+	uchar ip[IPaddrlen], mac[Eaddrlen], *targ, *end, *a, *o;
+	ulong csum, c, h;
+	Etherpkt *pkt;
+	int proto, i;
+	DMTE *te;
+
+	end = bp->wp;
+	pkt = (Etherpkt*)bp->rp;
+	a = pkt->data;
+	if(a >= end)
+		return;
+
+	if(upstream)
+		memmove(pkt->s, proxy, Eaddrlen);
+	else if(t->map == 0 || (pkt->d[0]&1) != 0 || memcmp(pkt->d, proxy, Eaddrlen) != 0)
+		return;
+
+	targ = nil;
+	switch(pkt->type[0]<<8 | pkt->type[1]){
+	default:
+		return;
+	case ETIP4:
+	case ETIP6:
+		switch(a[0]&0xF0){
+		default:
+			return;
+		case IP_VER4:
+			if(a+IP4HDR > end || (a[0]&15) < IP_HLEN4)
+				return;
+			v4tov6(ip, a+12+4*(upstream==0));
+			proto = a[9];
+			a += (a[0]&15)*4;
+			break;
+		case IP_VER6:
+			if(a+IP6HDR > end)
+				return;
+			memmove(ip, a+8+16*(upstream==0), 16);
+			proto = a[6];
+			a += IP6HDR;
+			break;
+		}
+		if(!upstream)
+			break;
+		switch(proto){
+		case ICMPv6:
+			if(a+8 > end)
+				return;
+			switch(a[0]){
+			default:
+				return;
+			case 133:	/* Router Solicitation */
+				o = a+8;
+				break;
+			case 134:	/* Router Advertisement */
+				o = a+8+8;
+				break;
+			case 136:	/* Neighbor Advertisement */
+				targ = a+8;
+				/* wet floor */
+			case 135:	/* Neighbor Solicitation */
+				o = a+8+16;
+				break;
+			case 137:	/* Redirect */
+				o = a+8+16+16;
+				break;
+			}
+			memset(mac, 0xFF, Eaddrlen);
+			csum = (a[2]<<8 | a[3])^0xFFFF;
+			while(o+8 <= end && o[1] != 0){
+				switch(o[0]){
+				case SRC_LLADDR:
+				case TARGET_LLADDR:
+					for(i=0; i<Eaddrlen; i += 2)
+						csum += (o[2+i]<<8 | o[3+i])^0xFFFF;
+					memmove(mac, o+2, Eaddrlen);
+					memmove(o+2, proxy, Eaddrlen);
+					for(i=0; i<Eaddrlen; i += 2)
+						csum += (o[2+i]<<8 | o[3+i]);
+					break;
+				}
+				o += o[1]*8;
+			}
+			while((c = csum >> 16) != 0)
+				csum = (csum & 0xFFFF) + c;
+			csum ^= 0xFFFF;
+			a[2] = csum>>8;
+			a[3] = csum;
+			break;
+		case UDP:	/* for BOOTP */
+			if(a+42 > end
+			|| (a[0]<<8 | a[1]) != 68
+			|| (a[2]<<8 | a[3]) != 67
+			|| a[8] != 1
+			|| a[9] != 1
+			|| a[10] != Eaddrlen
+			|| (a[18]&0x80) != 0
+			|| memcmp(a+36, proxy, Eaddrlen) == 0)
+				return;
+
+			csum = (a[6]<<8 | a[7])^0xFFFF;
+
+			/* set the broadcast flag so response reaches us */
+			csum += (a[18]<<8)^0xFFFF;
+			a[18] |= 0x80;
+			csum += (a[18]<<8);
+
+			while((c = csum >> 16) != 0)
+				csum = (csum & 0xFFFF) + c;
+			csum ^= 0xFFFF;
+
+			a[6] = csum>>8;
+			a[7] = csum;
+		default:
+			return;
+		}
+		break;
+	case ETARP:
+		if(a+26 > end || memcmp(a, arp4, sizeof(arp4)) != 0 || (a[7] != 1 && a[7] != 2))
+			return;
+		v4tov6(ip, a+14+10*(upstream==0));
+		if(upstream){
+			memmove(mac, a+8, Eaddrlen);
+			memmove(a+8, proxy, Eaddrlen);
+		}
+		break;
+	}
+
+Again:
+	h = (	(ip[IPaddrlen-1] ^ proxy[2])<<24 |
+		(ip[IPaddrlen-2] ^ proxy[3])<<16 |
+		(ip[IPaddrlen-3] ^ proxy[4])<<8  |
+		(ip[IPaddrlen-4] ^ proxy[5]) ) % nelem(t->tab);
+	te = &t->tab[h];
+	h &= 63;
+
+	if(upstream){
+		if((mac[0]&1) != 0 || memcmp(mac, proxy, Eaddrlen) == 0)
+			return;
+		for(i=0; te->valid && i<nelem(t->tab); i++){
+			if(memcmp(te->ip, ip, IPaddrlen) == 0)
+				break;
+			if(++te >= &t->tab[nelem(t->tab)])
+				te = t->tab;
+		}
+		memmove(te->mac, mac, Eaddrlen);
+		memmove(te->ip, ip, IPaddrlen);
+		te->valid = 1;
+		t->map |= 1ULL<<h;
+		if(targ != nil){
+			memmove(ip, targ, IPaddrlen);
+			targ = nil;
+			goto Again;
+		}
+	} else {
+		if((t->map>>h & 1) == 0)
+			return;
+		for(i=0; te->valid && i<nelem(t->tab); i++){
+			if(memcmp(te->ip, ip, IPaddrlen) == 0){
+				memmove(pkt->d, te->mac, Eaddrlen);
+				return;
+			}
+			if(++te >= &t->tab[nelem(t->tab)])
+				te = t->tab;
+		}
+	}
+}
--- a/sys/src/9/port/etherif.h
+++ b/sys/src/9/port/etherif.h
@@ -44,3 +44,20 @@
 #define PREV(x, l)	(((x) == 0) ? (l)-1: (x)-1)
 #define	HOWMANY(x, y)	(((x)+((y)-1))/(y))
 #define ROUNDUP(x, y)	(HOWMANY((x), (y))*(y))
+
+typedef struct	DMAT	DMAT;
+struct DMTE
+{
+	uchar	ip[16];
+	uchar	mac[Eaddrlen];
+	uchar	valid;
+};
+
+typedef struct	DMTE	DMTE;
+struct DMAT
+{
+	DMTE	tab[127];	/* prime */
+	uvlong	map;
+};
+
+extern void dmatproxy(Block*, int, uchar*, DMAT*);
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -110,12 +110,13 @@
 devtls.$O:	/sys/include/libsec.h
 devswap.$O:	/sys/include/libsec.h
 random.$O:	/sys/include/libsec.h
-wifi.$O:	/sys/include/libsec.h ../ip/ip.h ../ip/ipv6.h
+wifi.$O:	/sys/include/libsec.h 
+dmat.$O:	../ip/ip.h ../ip/ipv6.h
 devaoe.$O sdaoe.$O:	/sys/include/fis.h
 sysproc.$O:	/sys/include/a.out.h
 syscallfmt.$O:	/sys/src/libc/9syscall/sys.h
 devusb.$O usbxhci.$O usbxhcipci.$O:	../port/usb.h
 usbxhci.$O usbxhcipci.$O:	../port/usbxhci.h
-devether.$O ethersink.$O etheriwl.$O wifi.$O:	../port/netif.h ../port/etherif.h
+devether.$O ethersink.$O etheriwl.$O wifi.$O dmat.$O:	../port/netif.h ../port/etherif.h
 etheriwl.$O wifi.$O:	../port/wifi.h
 ethermii.$O:	../port/ethermii.h
--- a/sys/src/9/port/wifi.c
+++ b/sys/src/9/port/wifi.c
@@ -3,8 +3,6 @@
 #include "mem.h"
 #include "dat.h"
 #include "fns.h"
-#include "io.h"
-#include "ureg.h"
 #include "../port/error.h"
 #include "../port/netif.h"
 #include "../port/etherif.h"
@@ -49,8 +47,6 @@
 static Block* wifiencrypt(Wifi *, Wnode *, Block *);
 static void freewifikeys(Wifi *, Wnode *);
 
-static void dmatproxy(Block *bp, int upstream, uchar proxy[Eaddrlen], DMAT *t);
-
 static uchar*
 srcaddr(Wifipkt *w)
 {
@@ -1760,194 +1756,4 @@
 	return aesCCMdecrypt(2, 8, nonce, auth,
 		setupCCMP(w, tsc, nonce, auth),
 		b->rp, BLEN(b), (AESstate*)k->key);
-}
-
-/*
- * Dynamic Mac Address Translation (DMAT)
- *
- * Wifi does not allow spoofing of the source mac which breaks
- * bridging. To solve this we proxy mac addresses, maintaining
- * a translation table from ip address to destination mac address.
- * Upstream ARP and NDP packets get ther source mac address changed
- * to proxy and a translation entry is added with the original mac
- * for downstream translation. The proxy does not appear in the
- * table.
- */
-#include "../ip/ip.h"
-#include "../ip/ipv6.h"
-
-static void
-dmatproxy(Block *bp, int upstream, uchar proxy[Eaddrlen], DMAT *t)
-{
-	static uchar arp4[] = {
-		0x00, 0x01,
-		0x08, 0x00,
-		0x06, 0x04,
-		0x00,
-	};
-	uchar ip[IPaddrlen], mac[Eaddrlen], *targ, *end, *a, *o;
-	ulong csum, c, h;
-	Etherpkt *pkt;
-	int proto, i;
-	DMTE *te;
-
-	end = bp->wp;
-	pkt = (Etherpkt*)bp->rp;
-	a = pkt->data;
-	if(a >= end)
-		return;
-
-	if(upstream)
-		memmove(pkt->s, proxy, Eaddrlen);
-	else if(t->map == 0 || (pkt->d[0]&1) != 0 || memcmp(pkt->d, proxy, Eaddrlen) != 0)
-		return;
-
-	targ = nil;
-	switch(pkt->type[0]<<8 | pkt->type[1]){
-	default:
-		return;
-	case ETIP4:
-	case ETIP6:
-		switch(a[0]&0xF0){
-		default:
-			return;
-		case IP_VER4:
-			if(a+IP4HDR > end || (a[0]&15) < IP_HLEN4)
-				return;
-			v4tov6(ip, a+12+4*(upstream==0));
-			proto = a[9];
-			a += (a[0]&15)*4;
-			break;
-		case IP_VER6:
-			if(a+IP6HDR > end)
-				return;
-			memmove(ip, a+8+16*(upstream==0), 16);
-			proto = a[6];
-			a += IP6HDR;
-			break;
-		}
-		if(!upstream)
-			break;
-		switch(proto){
-		case ICMPv6:
-			if(a+8 > end)
-				return;
-			switch(a[0]){
-			default:
-				return;
-			case 133:	/* Router Solicitation */
-				o = a+8;
-				break;
-			case 134:	/* Router Advertisement */
-				o = a+8+8;
-				break;
-			case 136:	/* Neighbor Advertisement */
-				targ = a+8;
-				/* wet floor */
-			case 135:	/* Neighbor Solicitation */
-				o = a+8+16;
-				break;
-			case 137:	/* Redirect */
-				o = a+8+16+16;
-				break;
-			}
-			memset(mac, 0xFF, Eaddrlen);
-			csum = (a[2]<<8 | a[3])^0xFFFF;
-			while(o+8 <= end && o[1] != 0){
-				switch(o[0]){
-				case SRC_LLADDR:
-				case TARGET_LLADDR:
-					for(i=0; i<Eaddrlen; i += 2)
-						csum += (o[2+i]<<8 | o[3+i])^0xFFFF;
-					memmove(mac, o+2, Eaddrlen);
-					memmove(o+2, proxy, Eaddrlen);
-					for(i=0; i<Eaddrlen; i += 2)
-						csum += (o[2+i]<<8 | o[3+i]);
-					break;
-				}
-				o += o[1]*8;
-			}
-			while((c = csum >> 16) != 0)
-				csum = (csum & 0xFFFF) + c;
-			csum ^= 0xFFFF;
-			a[2] = csum>>8;
-			a[3] = csum;
-			break;
-		case UDP:	/* for BOOTP */
-			if(a+42 > end
-			|| (a[0]<<8 | a[1]) != 68
-			|| (a[2]<<8 | a[3]) != 67
-			|| a[8] != 1
-			|| a[9] != 1
-			|| a[10] != Eaddrlen
-			|| (a[18]&0x80) != 0
-			|| memcmp(a+36, proxy, Eaddrlen) == 0)
-				return;
-
-			csum = (a[6]<<8 | a[7])^0xFFFF;
-
-			/* set the broadcast flag so response reaches us */
-			csum += (a[18]<<8)^0xFFFF;
-			a[18] |= 0x80;
-			csum += (a[18]<<8);
-
-			while((c = csum >> 16) != 0)
-				csum = (csum & 0xFFFF) + c;
-			csum ^= 0xFFFF;
-
-			a[6] = csum>>8;
-			a[7] = csum;
-		default:
-			return;
-		}
-		break;
-	case ETARP:
-		if(a+26 > end || memcmp(a, arp4, sizeof(arp4)) != 0 || (a[7] != 1 && a[7] != 2))
-			return;
-		v4tov6(ip, a+14+10*(upstream==0));
-		if(upstream){
-			memmove(mac, a+8, Eaddrlen);
-			memmove(a+8, proxy, Eaddrlen);
-		}
-		break;
-	}
-
-Again:
-	h = (	(ip[IPaddrlen-1] ^ proxy[2])<<24 |
-		(ip[IPaddrlen-2] ^ proxy[3])<<16 |
-		(ip[IPaddrlen-3] ^ proxy[4])<<8  |
-		(ip[IPaddrlen-4] ^ proxy[5]) ) % nelem(t->tab);
-	te = &t->tab[h];
-	h &= 63;
-
-	if(upstream){
-		if((mac[0]&1) != 0 || memcmp(mac, proxy, Eaddrlen) == 0)
-			return;
-		for(i=0; te->valid && i<nelem(t->tab); i++){
-			if(memcmp(te->ip, ip, IPaddrlen) == 0)
-				break;
-			if(++te >= &t->tab[nelem(t->tab)])
-				te = t->tab;
-		}
-		memmove(te->mac, mac, Eaddrlen);
-		memmove(te->ip, ip, IPaddrlen);
-		te->valid = 1;
-		t->map |= 1ULL<<h;
-		if(targ != nil){
-			memmove(ip, targ, IPaddrlen);
-			targ = nil;
-			goto Again;
-		}
-	} else {
-		if((t->map>>h & 1) == 0)
-			return;
-		for(i=0; te->valid && i<nelem(t->tab); i++){
-			if(memcmp(te->ip, ip, IPaddrlen) == 0){
-				memmove(pkt->d, te->mac, Eaddrlen);
-				return;
-			}
-			if(++te >= &t->tab[nelem(t->tab)])
-				te = t->tab;
-		}
-	}
 }
--- a/sys/src/9/port/wifi.h
+++ b/sys/src/9/port/wifi.h
@@ -2,8 +2,6 @@
 typedef struct Wnode Wnode;
 typedef struct Wifi Wifi;
 typedef struct Wifipkt Wifipkt;
-typedef struct DMAT DMAT;
-typedef struct DMTE DMTE;
 
 enum {
 	Essidlen = 32,
@@ -59,19 +57,6 @@
 	int	channel;
 	int	brsnelen;
 	uchar	brsne[258];
-};
-
-struct DMTE
-{
-	uchar	ip[16];
-	uchar	mac[6];
-	uchar	valid;
-};
-
-struct DMAT
-{
-	DMTE	tab[127];	/* prime */
-	uvlong	map;
 };
 
 struct Wifi