shithub: front

Download patch

ref: e4373dd1038fd8e0369d595283b032d011f28e59
parent: aeb857e367df5f414707fe054edc487386adbe54
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Nov 7 16:24:27 EST 2024

ip/pppoe: properly zero-pad ethernet frames, optimize framing, limit mtu

we should properly zero-pad the ethernet frames we send out
instead of sending random garbage.

for ppp -> ethernet, the ethernet header is fixed, so we
can generate it once before the read()/write() loop.

Use a 1514 byte buffer for all ethernet frames as the
maximum, and limit the mtu to 1514-14-8 -> 1492.

--- a/sys/src/cmd/ip/pppoe.c
+++ b/sys/src/cmd/ip/pppoe.c
@@ -7,6 +7,70 @@
 #include <libc.h>
 #include <ip.h>
 
+typedef struct Etherhdr Etherhdr;
+struct Etherhdr {
+	uchar dst[6];
+	uchar src[6];
+	uchar type[2];
+};
+
+enum {
+	EtherHdrSz = 6+6+2,
+	EtherMintu = 60,
+	EtherMaxtu = 1500+EtherHdrSz,
+
+	EtherPppoeDiscovery = 0x8863,
+	EtherPppoeSession = 0x8864,
+};
+
+uchar etherbcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+typedef struct Pppoehdr Pppoehdr;
+struct Pppoehdr {
+	uchar verstype;
+	uchar code;
+	uchar sessid[2];
+	uchar length[2];	/* of payload */
+};
+
+enum {
+	PppoeHdrSz = 1+1+2+2,
+	Hdr = EtherHdrSz+PppoeHdrSz,
+	Maxmtu = EtherMaxtu - (Hdr+2),	/* 2 bytes for PPP header */
+};
+
+enum {
+	VersType = 0x11,
+
+	/* Discovery codes */
+	CodeDiscInit = 0x09,	/* discovery init */
+	CodeDiscOffer = 0x07,	/* discovery offer */
+	CodeDiscReq = 0x19,	/* discovery request */
+	CodeDiscSess = 0x65,	/* session confirmation */
+	CodeDiscTerm = 0xa7,
+
+	/* Session codes */
+	CodeSession = 0x00,
+};
+
+typedef struct Taghdr Taghdr;
+struct Taghdr {
+	uchar type[2];
+	uchar length[2];	/* of value */
+};
+
+enum {
+	TagEnd = 0x0000,		/* end of tag list */
+	TagSrvName = 0x0101,	/* service name */
+	TagAcName = 0x0102,	/* access concentrator name */
+	TagHostUniq = 0x0103,	/* nonce */
+	TagAcCookie = 0x0104,	/* a.c. cookie */
+	TagVendSpec = 0x0105,	/* vendor specific */
+	TagRelaySessId = 0x0110,	/* relay session id */
+	TagSrvNameErr = 0x0201,	/* service name error (ascii) */
+	TagAcSysErr = 0x0202,	/* a.c. system error */
+};
+
 void dumppkt(uchar*);
 uchar *findtag(uchar*, int, int*, int);
 void hexdump(uchar*, int);
@@ -32,7 +96,7 @@
 int cookielen;
 uchar etherdst[6];
 uchar ethersrc[6];
-int mtu = 1492;
+int mtu = Maxmtu;
 int pktcompress, hdrcompress;
 char *baud;
 
@@ -97,6 +161,8 @@
 		break;
 	case 'm':
 		mtu = atoi(EARGF(usage()));
+		if(mtu > Maxmtu)
+			mtu = Maxmtu;
 		break;
 	case 'i':
 		ipnet4 = EARGF(usage());
@@ -150,23 +216,6 @@
 	execppp(pppoe(dev));
 }
 
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr {
-	uchar dst[6];
-	uchar src[6];
-	uchar type[2];
-};
-
-enum {
-	EtherHdrSz = 6+6+2,
-	EtherMintu = 60,
-
-	EtherPppoeDiscovery = 0x8863,
-	EtherPppoeSession = 0x8864,
-};
-
-uchar etherbcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
 int
 etherhdr(uchar *pkt, uchar *dst, int type)
 {
@@ -178,33 +227,6 @@
 	return EtherHdrSz;
 }
 
-typedef struct Pppoehdr Pppoehdr;
-struct Pppoehdr {
-	uchar verstype;
-	uchar code;
-	uchar sessid[2];
-	uchar length[2];	/* of payload */
-};
-
-enum {
-	PppoeHdrSz = 1+1+2+2,
-	Hdr = EtherHdrSz+PppoeHdrSz,
-};
-
-enum {
-	VersType = 0x11,
-
-	/* Discovery codes */
-	CodeDiscInit = 0x09,	/* discovery init */
-	CodeDiscOffer = 0x07,	/* discovery offer */
-	CodeDiscReq = 0x19,	/* discovery request */
-	CodeDiscSess = 0x65,	/* session confirmation */
-	CodeDiscTerm = 0xa7,
-
-	/* Session codes */
-	CodeSession = 0x00,
-};
-
 int
 pppoehdr(uchar *pkt, int code, int sessid)
 {
@@ -217,24 +239,6 @@
 	return PppoeHdrSz;
 }
 
-typedef struct Taghdr Taghdr;
-struct Taghdr {
-	uchar type[2];
-	uchar length[2];	/* of value */
-};
-
-enum {
-	TagEnd = 0x0000,		/* end of tag list */
-	TagSrvName = 0x0101,	/* service name */
-	TagAcName = 0x0102,	/* access concentrator name */
-	TagHostUniq = 0x0103,	/* nonce */
-	TagAcCookie = 0x0104,	/* a.c. cookie */
-	TagVendSpec = 0x0105,	/* vendor specific */
-	TagRelaySessId = 0x0110,	/* relay session id */
-	TagSrvNameErr = 0x0201,	/* service name error (ascii) */
-	TagAcSysErr = 0x0202,	/* a.c. system error */
-};
-
 int
 tag(uchar *pkt, int type, void *value, int nvalue)
 {
@@ -473,11 +477,9 @@
 pppoe(char *ether)
 {
 	char buf[128];
-	uchar pkt[1520];
+	uchar pkt[EtherMaxtu];
 	int dfd, sfd, p[2], n, sz, timeout;
-	Pppoehdr *ph;
 
-	ph = (Pppoehdr*)(pkt+EtherHdrSz);
 	snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeDiscovery);
 	if((dfd = dial(buf, nil, nil, nil)) < 0)
 		fatal("dial %s: %r\n", buf);
@@ -549,16 +551,17 @@
 		break;
 	case 0:
 		close(dfd);
-		while((n = read(sfd, pkt, sizeof pkt)) > 0){
-			if(malformed(pkt, n, EtherPppoeSession)
-			|| ph->code != 0x00 || nhgets(ph->sessid) != sessid){
-				if(debug)
-					fprint(2, "malformed session pkt: %r\n");
-				if(debug)
-					dumppkt(pkt);
+
+		pppoehdr((uchar*)buf, 0x00, sessid);
+
+		while((sz = read(sfd, pkt, sizeof pkt)) > 0){
+			if(sz < Hdr
+			|| pkt[EtherHdrSz+1] != 0x00		/* code */
+			|| pkt[EtherHdrSz+2] != (uchar)buf[2]	/* sessid[0] */
+			|| pkt[EtherHdrSz+3] != (uchar)buf[3]	/* sessid[1] */
+			|| (n = nhgets(pkt+Hdr-2)) > sz-Hdr)
 				continue;
-			}
-			if(write(p[0], pkt+Hdr, nhgets(ph->length)) < 0){
+			if(write(p[0], pkt+Hdr, n) < 0){
 				if(debug)
 					fprint(2, "write to ppp failed: %r\n");
 				break;
@@ -574,17 +577,14 @@
 		break;
 	case 0:
 		close(dfd);
+
+		etherhdr(pkt, etherdst, EtherPppoeSession);
+		pppoehdr(pkt+EtherHdrSz, 0x00, sessid);
+
 		while((n = read(p[0], pkt+Hdr, sizeof pkt-Hdr)) > 0){
-			etherhdr(pkt, etherdst, EtherPppoeSession);
-			pppoehdr(pkt+EtherHdrSz, 0x00, sessid);
 			hnputs(pkt+Hdr-2, n);
-			sz = Hdr+n;
-			if(debug > 1){
-				dumppkt(pkt);
-				hexdump(pkt, sz);
-			}
-			if(sz < EtherMintu)
-				sz = EtherMintu;
+			for(sz = Hdr+n; sz < EtherMintu; sz++)
+				pkt[sz] = 0;
 			if(write(sfd, pkt, sz) < 0){
 				if(debug)
 					fprint(2, "write to ether failed: %r");
--