shithub: riscv

Download patch

ref: 87b61fddf25d5a3278509e636ab7328ac582d9a0
parent: 278caaf11931ec0c71fc13fd4c4794fae325c404
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon May 22 15:54:56 EDT 2023

ip/ppp: and its GONE.

blocklists are completely useless for the ppp code and
therefore: GONE.

custom checksum code (just use libip's version): GONE.

custom block allocator is also completely avoidable.

for the data receive and transmit path, we can just
reuse the same buffer without ever needing do free
and re-allocate. for this, i made freeb() check that
the data area is next to the Block header, if its not
i consider it a "static" buffer that should not be
freed. Provide resetb() to re-initialize a buffer.
so yeah, custom block allocator: GONE.

most of the block functions where not needed at all.
now we only have: allocb(), resetb(), freeb()
and BLEN() and BALLOC() macros. the rest is: GONE.

putframe() used to always COPY all the data for no
reason... like why where they even using Block buffers
then? .... FIXED.

--- a/sys/src/cmd/ip/ppp/block.c
+++ b/sys/src/cmd/ip/ppp/block.c
@@ -7,360 +7,35 @@
 enum
 {
 	PAD	= 128,
-	NLIST	= (1<<5),
-	BPOW	= 10,
 };
 
-typedef struct Barena Barena;
-struct Barena
-{
-	QLock;
-	Block*	list[NLIST];
-};
-static Barena area;
-
-#define ADEBUG if(0)
-
-
-/*
- *  allocation tracing
- */
-enum
-{
-	Npc=	64,
-};
-typedef struct Arefent Arefent;
-struct Arefent
-{
-	uint	pc;
-	uint	n;
-};
-typedef struct Aref Aref;
-struct  Aref
-{
-	Arefent	tab[Npc];
-	QLock;
-};
-Aref arefblock;
-
-static ulong	callerpc(void*);
-static void	aref(Aref*, ulong);
-static void	aunref(Aref*, ulong);
-
 Block*
-allocb(int len)
+resetb(Block *bp)
 {
-	int sz;
-	Block *bp, **l;
-
-	len += PAD;
-	sz = (len>>BPOW)&(NLIST-1);
-	
-	qlock(&area);
-	l = &area.list[sz];
-	for(bp = *l; bp; bp = bp->flist) {
-		if(bp->bsz >= len) {
-			*l = bp->flist;
-			qunlock(&area);
-
-			bp->next = nil;
-			bp->list = nil;
-			bp->flist = nil;
-			bp->base = (uchar*)bp+sizeof(Block);
-			bp->rptr = bp->base+PAD;
-			bp->wptr = bp->rptr;
-			bp->lim  = bp->base+bp->bsz;
-			bp->flow = nil;
-			bp->flags= 0;
-			ADEBUG {
-				bp->pc = callerpc(&len);
-				aref(&arefblock, bp->pc);
-			}
-			return bp;
-		}
-		l = &bp->flist;
-	}
-
-	qunlock(&area);
-
-	bp = mallocz(sizeof(Block)+len, 1);
-
-	bp->bsz  = len;
-	bp->base = (uchar*)bp+sizeof(Block);
 	bp->rptr = bp->base+PAD;
 	bp->wptr = bp->rptr;
-	bp->lim  = bp->base+len;
-	ADEBUG {
-		bp->pc = callerpc(&len);
-		aref(&arefblock, bp->pc);
-	}
 	return bp;
 }
 
-void
-freeb(Block *bp)
-{
-	int sz;
-	Block **l, *next;
-
-	qlock(&area);
-	while(bp) {
-		sz = (bp->bsz>>BPOW)&(NLIST-1);
-
-		l = &area.list[sz];
-		bp->flist = *l;
-		*l = bp;
-
-		next = bp->next;
-
-		/* to catch use after free */
-		bp->rptr = (uchar*)0xdeadbabe;
-		bp->wptr = (uchar*)0xdeadbabe;
-		bp->next = (Block*)0xdeadbabe;
-		bp->list = (Block*)0xdeadbabe;
-
-		ADEBUG aunref(&arefblock, bp->pc);
-
-		bp = next;
-	}
-	qunlock(&area);
-}
-
-/*
- *  concatenate a list of blocks into a single one and make sure
- *  the result is at least min uchars
- */
 Block*
-concat(Block *bp)
+allocb(int len)
 {
-	int len;
-	Block *nb, *f;
-
-	nb = allocb(blen(bp));
-	for(f = bp; f; f = f->next) {
-		len = BLEN(f);
-		memmove(nb->wptr, f->rptr, len);
-		nb->wptr += len;
-	}
-	freeb(bp);
-	return nb;
-}
-
-int
-blen(Block *bp)
-{
-	int len;
-
-	len = 0;
-	while(bp) {
-		len += BLEN(bp);
-		bp = bp->next;
-	}
-	return len;
-}
-
-Block *
-pullup(Block *bp, int n)
-{
-	int i;
-	Block *nbp;
-
-	/*
-	 *  this should almost always be true, the rest it
-	 *  just for to avoid every caller checking.
-	 */
-	if(BLEN(bp) >= n)
-		return bp;
-
-	/*
-	 *  if not enough room in the first block,
-	 *  add another to the front of the list.
-	 */
-	if(bp->lim - bp->rptr < n){
-		nbp = allocb(n);
-		nbp->next = bp;
-		bp = nbp;
-	}
-
-	/*
-	 *  copy uchars from the trailing blocks into the first
-	 */
-	n -= BLEN(bp);
-	while(nbp = bp->next){
-		i = BLEN(nbp);
-		if(i >= n) {
-			memmove(bp->wptr, nbp->rptr, n);
-			bp->wptr += n;
-			nbp->rptr += n;
-			return bp;
-		}
-		else {
-			memmove(bp->wptr, nbp->rptr, i);
-			bp->wptr += i;
-			bp->next = nbp->next;
-			nbp->next = nil;
-			freeb(nbp);
-			n -= i;
-		}
-	}
-	freeb(bp);
-	return nil;
-}
-
-/*
- *  Pad a block to the front with n uchars.  This is used to add protocol
- *  headers to the front of blocks.
- */
-Block*
-padb(Block *bp, int n)
-{
-	Block *nbp;
-
-	if(bp->rptr-bp->base >= n) {
-		bp->rptr -= n;
-		return bp;
-	}
-	else {
-		/* fprint(2, "padb: required %d PAD %d\n", n, PAD) = malloc(sizeof(*required %d PAD %d\n", n, PAD))); */
-		nbp = allocb(n);
-		nbp->wptr = nbp->lim;
-		nbp->rptr = nbp->wptr - n;
-		nbp->next = bp;
-		return nbp;
-	}
-} 
-
-Block *
-btrim(Block *bp, int offset, int len)
-{
-	ulong l;
-	Block *nb, *startb;
-
-	if(blen(bp) < offset+len) {
-		freeb(bp);
-		return nil;
-	}
-
-	while((l = BLEN(bp)) < offset) {
-		offset -= l;
-		nb = bp->next;
-		bp->next = nil;
-		freeb(bp);
-		bp = nb;
-	}
-
-	startb = bp;
-	bp->rptr += offset;
-
-	while((l = BLEN(bp)) < len) {
-		len -= l;
-		bp = bp->next;
-	}
-
-	bp->wptr -= (BLEN(bp) - len);
-	bp->flags |= S_DELIM;
-
-	if(bp->next) {
-		freeb(bp->next);
-		bp->next = nil;
-	}
-
-	return startb;
-}
-
-Block*
-copyb(Block *bp, int count)
-{
-	int l;
-	Block *nb, *head, **p;
-
-	p = &head;
-	head = nil;
-	while(bp != nil && count != 0) {
-		l = BLEN(bp);
-		if(count < l)
-			l = count;
-		nb = allocb(l);
-		memmove(nb->wptr, bp->rptr, l);
-		nb->wptr += l;
-		count -= l;
-		nb->flags = bp->flags;
-		*p = nb;
-		p = &nb->next;
-		bp = bp->next;
-	}
-	if(count) {
-		nb = allocb(count);
-		memset(nb->wptr, 0, count);
-		nb->wptr += count;
-		nb->flags |= S_DELIM;
-		*p = nb;
-	}
-	if(blen(head) == 0)
-		fprint(2, "copyb: zero length\n");
-
-	return head;
-}
-
-int
-pullb(Block **bph, int count)
-{
 	Block *bp;
-	int n, uchars;
 
-	uchars = 0;
-	if(bph == nil)
-		return 0;
-
-	while(*bph != nil && count != 0) {
-		bp = *bph;
-		n = BLEN(bp);
-		if(count < n)
-			n = count;
-		uchars += n;
-		count -= n;
-		bp->rptr += n;
-		if(BLEN(bp) == 0) {
-			*bph = bp->next;
-			bp->next = nil;
-			freeb(bp);
-		}
-	}
-	return uchars;
+	len += PAD;
+	bp = mallocz(sizeof(Block)+len, 0);
+	bp->base = (uchar*)bp+sizeof(Block);
+	bp->lim = bp->base+len;
+	return resetb(bp);
 }
 
-/*
- *  handy routines for keeping track of allocations
- */
-static ulong
-callerpc(void *a)
+void
+freeb(Block *bp)
 {
-	return ((ulong*)a)[-1];
-}
-static void
-aref(Aref *ap, ulong pc)
-{
-	Arefent *a, *e;
-
-	e = &ap->tab[Npc-1];
-	qlock(ap);
-	for(a = ap->tab; a < e; a++)
-		if(a->pc == pc || a->pc == 0)
-			break;
-	a->pc = pc;
-	a->n++;
-	qunlock(ap);
-}
-static void
-aunref(Aref *ap, ulong pc)
-{
-	Arefent *a, *e;
-
-	e = &ap->tab[Npc-1];
-	qlock(ap);
-	for(a = ap->tab; a < e; a++)
-		if(a->pc == pc || a->pc == 0)
-			break;
-	a->n--;
-	qunlock(ap);
+	if(bp == nil)
+		return;
+	bp->rptr = (void*)0xdeadbabe;
+	bp->wptr = (void*)0xdeadbabe;
+	if(bp->base == (uchar*)bp + sizeof(Block))
+		free(bp);
 }
--- a/sys/src/cmd/ip/ppp/compress.c
+++ b/sys/src/cmd/ip/ppp/compress.c
@@ -439,12 +439,8 @@
 	 *  We assume the packet we were handed has enough space to prepend
 	 *  up to 128 uchars of header.
 	 */
-	b->rptr = cp;
-	if(b->rptr - b->base < len){
-		b = padb(b, len);
-		b = pullup(b, blen(b));
-	} else
-		b->rptr -= len;
+	b->rptr = cp - len;
+	assert(b->rptr >= b->base);
 	hnputs(ip->length, BLEN(b));
 	memmove(b->rptr, ip, len);
 	
--- a/sys/src/cmd/ip/ppp/ipaux.c
+++ b/sys/src/cmd/ip/ppp/ipaux.c
@@ -4,126 +4,19 @@
 #include <auth.h>
 #include "ppp.h"
 
-static	ushort	endian	= 1;
-static	uchar*	aendian	= (uchar*)&endian;
-#define	LITTLE	*aendian
-
 ushort
-ptclbsum(uchar *addr, int len)
-{
-	ulong losum, hisum, mdsum, x;
-	ulong t1, t2;
-
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((uintptr)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return losum & 0xffff;
-}
-
-ushort
 ptclcsum(Block *bp, int offset, int len)
 {
 	uchar *addr;
-	ulong losum, hisum;
-	ushort csum;
-	int odd, blen, x;
+	int blen;
 
-	/* Correct to front of data area */
-	while(bp != nil && offset && offset >= BLEN(bp)) {
-		offset -= BLEN(bp);
-		bp = bp->next;
-	}
-	if(bp == nil)
+	if(bp == nil || bp->rptr + offset >= bp->wptr)
 		return 0;
-
 	addr = bp->rptr + offset;
 	blen = BLEN(bp) - offset;
-
-	if(bp->next == nil) {
-		if(blen < len)
-			len = blen;
-		return ~ptclbsum(addr, len) & 0xffff;
-	}
-
-	losum = 0;
-	hisum = 0;
-
-	odd = 0;
-	while(len) {
-		x = blen;
-		if(len < x)
-			x = len;
-
-		csum = ptclbsum(addr, x);
-		if(odd)
-			hisum += csum;
-		else
-			losum += csum;
-		odd = (odd+x) & 1;
-		len -= x;
-
-		bp = bp->next;
-		if(bp == nil)
-			break;
-		blen = BLEN(bp);
-		addr = bp->rptr;
-	}
-
-	losum += hisum>>8;
-	losum += (hisum&0xff)<<8;
-	while((csum = losum>>16) != 0)
-		losum = csum + (losum & 0xffff);
-
-	return ~losum & 0xffff;
+	if(blen < len)
+		len = blen;
+	return ~ptclbsum(addr, len) & 0xffff;
 }
 
 ushort
--- a/sys/src/cmd/ip/ppp/ppp.c
+++ b/sys/src/cmd/ip/ppp/ppp.c
@@ -170,42 +170,28 @@
 static void
 init(PPP* ppp)
 {
-	if(ppp->inbuf == nil){
-		ppp->inbuf = allocb(4096);
-		if(ppp->inbuf == nil)
-			abort();
+	if(ppp->lcp == nil){
+		/* prevent them from being free'd */
+		ppp->inbuf[0] = *allocb(Buflen);
+		ppp->outbuf[0] = *allocb(Buflen);
 
-		ppp->outbuf = allocb(4096);
-		if(ppp->outbuf == nil)
-			abort();
-
 		ppp->lcp = mallocz(sizeof(*ppp->lcp), 1);
-		if(ppp->lcp == nil)
-			abort();
 		ppp->lcp->proto = Plcp;
 		ppp->lcp->state = Sclosed;
 
 		ppp->ccp = mallocz(sizeof(*ppp->ccp), 1);
-		if(ppp->ccp == nil)
-			abort();
 		ppp->ccp->proto = Pccp;
 		ppp->ccp->state = Sclosed;
 
 		ppp->ipcp = mallocz(sizeof(*ppp->ipcp), 1);
-		if(ppp->ipcp == nil)
-			abort();
 		ppp->ipcp->proto = Pipcp;
 		ppp->ipcp->state = Sclosed;
 
 		ppp->ipv6cp = mallocz(sizeof(*ppp->ipv6cp), 1);
-		if(ppp->ipv6cp == nil)
-			abort();
 		ppp->ipv6cp->proto = Pipv6cp;
 		ppp->ipv6cp->state = Sclosed;
 
 		ppp->chap = mallocz(sizeof(*ppp->chap), 1);
-		if(ppp->chap == nil)
-			abort();
 		ppp->chap->proto = APmschapv2;
 		ppp->chap->state = Cunauth;
 		auth_freechal(ppp->chap->cs);
@@ -402,12 +388,14 @@
 	p->state = state;
 }
 
-/* returns (protocol, information) */
+/*
+ * getframe returns (protocol, information)
+ */
 static Block*
 getframe(PPP *ppp, int *protop)
 {
 	uchar *p, *from, *to;
-	int n, len, proto;
+	int n, proto;
 	ulong c;
 	ushort fcs;
 	Block *buf, *b;
@@ -414,35 +402,28 @@
 
 	*protop = 0;
 	if(ppp->framing == 0) {
-		/* assume data is already framed */
-		b = allocb(2000);
-		len = b->lim - b->wptr;
-		n = read(ppp->mediain, b->wptr, len);
- 		dmppkt("RX", b->wptr, n);
-		if(n <= 0 || n == len){
-			freeb(b);
+		/* reuse inbuf to avoid allocation */
+		b = resetb(ppp->inbuf);
 
+		n = read(ppp->mediain, b->wptr, BALLOC(b));
+		if(n <= 0){
+			syslog(0, LOG, "medium read returns %d: %r", n);
 			return nil;
 		}
+		dmppkt("RX", b->wptr, n);
 		b->wptr += n;
 
-		/* should probably copy to another block if small */
-
 		if(pppframing && b->rptr[0] == PPP_addr && b->rptr[1] == PPP_ctl)
 			b->rptr += 2;
 		proto = *b->rptr++;
 		if((proto & 0x1) == 0)
 			proto = (proto<<8) | *b->rptr++;
-
-		if(b->rptr >= b->wptr){
-			freeb(b);
+		if(b->rptr >= b->wptr)
 			return nil;
-		}
 
 		ppp->in.uchars += n;
 		ppp->in.packets++;
 		*protop = proto;
-		netlog("getframe 0x%x\n", proto);
 		return b;
 	}
 
@@ -455,9 +436,7 @@
 					break;
 			if(p != buf->wptr)
 				break;
-
-			len = buf->lim - buf->wptr;
-			n = read(ppp->mediain, buf->wptr, len);
+			n = read(ppp->mediain, buf->wptr, BALLOC(buf));
 			if(n <= 0){
 				syslog(0, LOG, "medium read returns %d: %r", n);
 				buf->wptr = buf->rptr;
@@ -501,7 +480,6 @@
 				ppp->in.uchars += n;
 				ppp->in.packets++;
 				*protop = proto;
-				netlog("getframe 0x%x\n", proto);
 				return b;
 			}
 		} else if(BLEN(b) > 0){
@@ -521,12 +499,10 @@
 static int
 putframe(PPP *ppp, int proto, Block *b)
 {
-	Block *buf;
 	uchar *to, *from;
 	ushort fcs;
 	ulong ctlmap;
 	uchar c;
-	Block *bp;
 
 	ppp->out.packets++;
 
@@ -536,10 +512,7 @@
 		ctlmap = ppp->xctlmap;
 
 	/* make sure we have head room */
-	if(b->rptr - b->base < 4){
-		b = padb(b, 4);
-		b->rptr += 4;
-	}
+	assert(b->rptr - b->base >= 4);
 
 	netlog("ppp: putframe 0x%ux %zd\n", proto, BLEN(b));
 
@@ -554,37 +527,26 @@
 	}
 
 	qlock(&ppp->outlock);
-	buf = ppp->outbuf;
+	if(ppp->framing == 0)
+		to = b->wptr;
+	else {
+		to = ppp->outbuf->rptr;
 
-	if(ppp->framing == 0) {
-		to = buf->rptr;
-		for(bp = b; bp; bp = bp->next){
-			if(bp != b)
-				from = bp->rptr;
-			memmove(to, from, bp->wptr-from);
-			to += bp->wptr-from;
-		}
-	} else {
 		/* escape and checksum the body */
 		fcs = PPP_initfcs;
-		to = buf->rptr;
 	
 		/* add frame marker */
 		*to++ = HDLC_frame;
 
-		for(bp = b; bp; bp = bp->next){
-			if(bp != b)
-				from = bp->rptr;
-			for(; from < bp->wptr; from++){
-				c = *from;
-				if(c == HDLC_frame || c == HDLC_esc
-				   || (c < 0x20 && ((1<<c) & ctlmap))){
-					*to++ = HDLC_esc;
-					*to++ = c ^ 0x20;
-				} else 
-					*to++ = c;
-				fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
-			}
+		for(; from < b->wptr; from++){
+			c = *from;
+			if(c == HDLC_frame || c == HDLC_esc
+			   || (c < 0x20 && ((1<<c) & ctlmap))){
+				*to++ = HDLC_esc;
+				*to++ = c ^ 0x20;
+			} else 
+				*to++ = c;
+			fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
 		}
 
 		/* add on and escape the checksum */
@@ -606,17 +568,16 @@
 	
 		/* add frame marker */
 		*to++ = HDLC_frame;
-	}
 
-	/* send */
-	buf->wptr = to;
- 	dmppkt("TX", buf->rptr, BLEN(buf));
-	if(write(ppp->mediaout, buf->rptr, BLEN(buf)) < 0){
+		from = ppp->outbuf->rptr;
+ 	}
+
+	dmppkt("TX", from, to - from);
+	if(write(ppp->mediaout, from, to - from) < 0){
 		qunlock(&ppp->outlock);
 		return -1;
 	}
-	ppp->out.uchars += BLEN(buf);
-
+	ppp->out.uchars += to - from;
 	qunlock(&ppp->outlock);
 	return 0;
 }
@@ -1774,48 +1735,29 @@
 		b = getframe(ppp, &proto);
 		if(b == nil)
 			return nil;
-
+		netlog("ppp: getframe 0x%ux %zd\n", proto, BLEN(b));
 Again:
 		switch(proto){
-		case Plcp:
-			rcv(ppp, ppp->lcp, b);
-			break;
-		case Pccp:
-			rcv(ppp, ppp->ccp, b);
-			break;
-		case Pipcp:
-			rcv(ppp, ppp->ipcp, b);
-			break;
-		case Pipv6cp:
-			rcv(ppp, ppp->ipv6cp, b);
-			break;
 		case Pip:
 			if(ppp->ipcp->state == Sopened)
 				return b;
-			freeb(b);
 			netlog("ppp: IP recved: link not up\n");
-			break;
+			freeb(b);
+			continue;
+
 		case Pipv6:
 			if(ppp->ipv6cp->state == Sopened)
 				return b;
-			freeb(b);
 			netlog("ppp: IPv6 recved: link not up\n");
-			break;
-		case Plqm:
-			getlqm(ppp, b);
-			break;
-		case Pchap:
-			getchap(ppp, b);
-			break;
-		case Ppasswd:
-			getpap(ppp, b);
-			break;
+			freeb(b);
+			continue;
+
 		case Pvjctcp:
 		case Pvjutcp:
 			if(ppp->ipcp->state != Sopened){
 				netlog("ppp: VJ tcp recved: link not up\n");
 				freeb(b);
-				break;
+				continue;
 			}
 			ppp->stat.vjin++;
 			b = tcpuncompress(ppp->ctcp, b, proto);
@@ -1822,20 +1764,22 @@
 			if(b != nil)
 				return b;
 			ppp->stat.vjfail++;
-			break;
+			continue;
+
 		case Pcdata:
 			ppp->stat.uncomp++;
 			if(ppp->ccp->state != Sopened){
 				netlog("ppp: compressed data recved: link not up\n");
 				freeb(b);
-				break;
+				continue;
 			}
 			if(ppp->unctype == nil) {
 				netlog("ppp: compressed data recved: no compression\n");
 				freeb(b);
-				break;
+				continue;
 			}
 			len = BLEN(b);
+			reply = nil;
 			b = (*ppp->unctype->uncompress)(ppp, b, &proto, &reply);
 			if(reply != nil){
 				/* send resetreq */
@@ -1844,11 +1788,36 @@
 				freeb(reply);
 			}
 			if(b == nil)
-				break;
+				continue;
 			ppp->stat.uncompin += len;
 			ppp->stat.uncompout += BLEN(b);
-/* netlog("ppp: uncompressed frame %ux %d %d (%d uchars)\n", proto, b->rptr[0], b->rptr[1], BLEN(b)); /* */
-			goto Again;	
+			netlog("ppp: uncompressed frame %ux %d %d (%zd uchars)\n",
+				proto, b->rptr[0], b->rptr[1], BLEN(b));
+			goto Again;
+		}
+
+		switch(proto){
+		case Plcp:
+			rcv(ppp, ppp->lcp, b);
+			break;
+		case Pccp:
+			rcv(ppp, ppp->ccp, b);
+			break;
+		case Pipcp:
+			rcv(ppp, ppp->ipcp, b);
+			break;
+		case Pipv6cp:
+			rcv(ppp, ppp->ipv6cp, b);
+			break;
+		case Plqm:
+			getlqm(ppp, b);
+			break;
+		case Pchap:
+			getchap(ppp, b);
+			break;
+		case Ppasswd:
+			getpap(ppp, b);
+			break;
 		default:
 			syslog(0, LOG, "unknown proto %ux", proto);
 			if(ppp->lcp->state == Sopened){
@@ -1892,7 +1861,7 @@
 	Iphdr *ip;
 	Ip6hdr *ip6;
 
-	len = blen(b);
+	len = BLEN(b);
 	ip = (Iphdr*)b->rptr;
 	switch(ip->vihl & 0xF0){
 	default:
@@ -1902,9 +1871,9 @@
 	case IP_VER4:
 		if(len < IPV4HDR_LEN || (tot = nhgets(ip->length)) < IPV4HDR_LEN)
 			goto Badhdr;
-		b = btrim(b, 0, tot);
-		if(b == nil)
-			return len;
+		if(b->wptr < (uchar*)ip + tot)
+			goto Badhdr;
+		b->wptr = (uchar*)ip + tot;
 
 		qlock(ppp);
 		if(ppp->ipcp->state != Sopened)
@@ -1912,10 +1881,8 @@
 		proto = Pip;
 		if(ppp->ipcp->flags & Fipcompress){
 			b = compress(ppp->ctcp, b, &proto);
-			if(b == nil){
-				qunlock(ppp);
-				return len;
-			}
+			if(b == nil)
+				goto Drop;
 			if(proto != Pip)
 				ppp->stat.vjout++;
 		}
@@ -1924,9 +1891,10 @@
 		if(len < IPV6HDR_LEN)
 			goto Badhdr;
 		ip6 = (Ip6hdr*)ip;
-		b = btrim(b, 0, IPV6HDR_LEN + nhgets(ip6->ploadlen));
-		if(b == nil)
-			return len;
+		tot = IPV6HDR_LEN + nhgets(ip6->ploadlen);
+		if(b->wptr < (uchar*)ip6 + tot)
+			goto Badhdr;
+		b->wptr = (uchar*)ip6 + tot;
 
 		qlock(ppp);
 		if(ppp->ipv6cp->state != Sopened)
@@ -1941,15 +1909,12 @@
 		if(proto == Pcdata) {
 			ppp->stat.comp++;
 			ppp->stat.compin += len;
-			ppp->stat.compout += blen(b);
+			ppp->stat.compout += BLEN(b);
 		}
 	} 
 
-	if(putframe(ppp, proto, b) < 0) {
-		qunlock(ppp);
-		freeb(b);
-		return -1;
-	}
+	if(putframe(ppp, proto, b) < 0)
+		len = -1;
 Drop:
 	qunlock(ppp);
 	freeb(b);
@@ -1988,19 +1953,17 @@
 static void
 ipinproc(PPP *ppp)
 {
-	Block *b;
+	Block b[1] = *allocb(Buflen);
 	int n;
 
 	while(!dying){
-		b = allocb(Buflen);
-		n = read(ppp->ipfd, b->wptr, b->lim-b->wptr);
-		if(n < 1){
-			freeb(b);
+		n = read(ppp->ipfd, b->wptr, BALLOC(b));
+		if(n <= 0)
 			break;
-		}
 		b->wptr += n;
 		if(pppwrite(ppp, b) < 0)
 			break;
+		resetb(b);
 	}
 }
 
@@ -2051,12 +2014,11 @@
 		}
 		ppp->stat.iprecv++;
 		if(debug > 1){
-			netlog("ip write pkt %p %d\n", b->rptr, blen(b));
-			hexdump(b->rptr, blen(b));
+			netlog("ip write pkt %p %zd\n", b->rptr, BLEN(b));
+			hexdump(b->rptr, BLEN(b));
 		}
-		if(write(ppp->ipfd, b->rptr, blen(b)) < 0) {
+		if(write(ppp->ipfd, b->rptr, BLEN(b)) < 0) {
 			syslog(0, LOG, "error writing to pktifc");
-			freeb(b);
 			break;
 		}
 		freeb(b);
--- a/sys/src/cmd/ip/ppp/ppp.h
+++ b/sys/src/cmd/ip/ppp/ppp.h
@@ -19,41 +19,17 @@
  */
 struct Block
 {
-	Block	*next;
-	Block	*flist;
-	Block	*list;			/* chain of block lists */
 	uchar	*rptr;			/* first unconsumed uchar */
 	uchar	*wptr;			/* first empty uchar */
 	uchar	*lim;			/* 1 past the end of the buffer */
 	uchar	*base;			/* start of the buffer */
-	uchar	flags;
-	void	*flow;
-	ulong	pc;
-	ulong	bsz;
 };
 #define BLEN(b)	((b)->wptr-(b)->rptr)
+#define BALLOC(b) ((b)->lim-(b)->wptr)
 
-enum
-{
-	/* block flags */
-	S_DELIM 	= (1<<0),
-	S_HANGUP	= (1<<1),
-	S_RHANGUP	= (1<<2),
-
-	/* queue states */
-	QHUNGUP		= (1<<0),
-	QFLOW		= (1<<1),	/* queue is flow controlled */
-};
-
 Block*	allocb(int);
+Block*	resetb(Block*);
 void	freeb(Block*);
-Block*	concat(Block*);
-int	blen(Block*);
-Block*	pullup(Block*, int);
-Block*	padb(Block*, int);
-Block*	btrim(Block*, int, int);
-Block*	copyb(Block*, int);
-int	pullb(Block**, int);
 
 enum {
 	HDLC_frame=	0x7e,
@@ -289,8 +265,9 @@
 	Ipaddr		dns[2];		/* dns servers */
 	Ipaddr		wins[2];	/* wins servers */
 
-	Block*		inbuf;		/* input buffer */
-	Block*		outbuf;		/* output buffer */
+	Block		inbuf[1];	/* input buffer - never free'd */
+	Block		outbuf[1];	/* output buffer - never free'd */
+
 	QLock		outlock;	/*  and its lock */
 	ulong		magic;		/* magic number to detect loop backs */
 	ulong		rctlmap;	/* map of chars to ignore in rcvr */
@@ -392,7 +369,6 @@
 extern Block*	tcpuncompress(Tcpc*, Block*, int);
 extern Block*	alloclcp(int, int, int, Lcpmsg**);
 extern ushort	ptclcsum(Block*, int, int);
-extern ushort	ptclbsum(uchar*, int);
 extern ushort	ipcsum(uchar*);
 
 void getasymkey(uchar *key, uchar *masterkey, int send, int server);