code: plan9front

Download patch

ref: 7742661aebb96a26f1cb34a68bcf631065913806
parent: 9702f740ab5532e392fc9c1fd83000d206af4dc5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed May 10 13:25:20 EDT 2023

ip/ppp: Implement echo request timeout, terminate

Send lcp echo request every 5 seconds
and terminate if we do not get any reply
after 12 seconds.

On protocol termination, exit all the processes
using a note and log a reason.

Cleanup.

--- a/sys/src/cmd/ip/ppp/mppc.c
+++ b/sys/src/cmd/ip/ppp/mppc.c
@@ -487,7 +487,7 @@
 	*protop = 0;
 	s = ppp->uncstate;
 	if(BLEN(b) < 2){
-		syslog(0, "ppp", ": mppc: short packet");
+		syslog(0, LOG, ": mppc: short packet");
 		freeb(b);
 		return nil;
 	}
@@ -506,7 +506,7 @@
 	}
 
 	if(BLEN(b) < 2){
-		syslog(0, "ppp", ": mppc: short packet");
+		syslog(0, LOG, ": mppc: short packet");
 		freeb(b);
 		*protop = 0;
 		return nil;
@@ -559,7 +559,7 @@
 		n += 16;
 //netlog("mppc count = %ux oldcount %ux n = %d\n", count, s->count, n);
 	if(n < 0 || n > 1) {
-		syslog(0, "ppp", ": mppc bad count %ux, %ux", count, s->count);
+		syslog(0, LOG, ": mppc bad count %ux, %ux", count, s->count);
 		freeb(b);
 		return nil;
 	}
--- a/sys/src/cmd/ip/ppp/ppp.c
+++ b/sys/src/cmd/ip/ppp/ppp.c
@@ -111,7 +111,7 @@
 static	void		sendechoreq(PPP*, Pstate*);
 static	void		sendtermreq(PPP*, Pstate*);
 static	void		setphase(PPP*, int);
-static	void		terminate(PPP*, int);
+static	void		terminate(PPP*, char *);
 static	int		validv4(Ipaddr);
 static  void		dmppkt(char *s, uchar *a, int na);
 
@@ -152,8 +152,8 @@
 		sysfatal("forking mediainproc");
 	case 0:
 		mediainproc(ppp);
-		terminate(ppp, 1);
-		_exits(0);
+		terminate(ppp, "mediainproc");
+		exits(nil);
 	}
 }
 
@@ -200,7 +200,7 @@
 			sysfatal("forking ppptimer");
 		case 0:
 			ppptimer(ppp);
-			_exits(0);
+			exits(nil);
 		}
 	}
 
@@ -221,9 +221,7 @@
 	default:
 		sysfatal("ppp: unknown phase %d", phase);
 	case Pdead:
-		/* restart or exit? */
-		pinit(ppp, ppp->lcp);
-		setphase(ppp, Plink);
+		terminate(ppp, "protocol");
 		break;
 	case Plink:
 		/* link down */
@@ -263,9 +261,6 @@
 		pinit(ppp, ppp->ccp);
 		pinit(ppp, ppp->ipcp);
 		break;
-	case Pterm:
-		/* what? */
-		break;
 	}
 }
 
@@ -293,6 +288,7 @@
 			p->optmask &= ~Fpc;
 			ppp->ipcp->optmask &= ~Fipcompress;
 		}
+		p->echoack = 0;
 		p->echotimeout = 0;
 
 		/* quality goo */
@@ -342,7 +338,7 @@
 		p->proto, snames[p->state], snames[state], ppp->rctlmap,
 		ppp->xctlmap, p->flags,
 		ppp->mtu, ppp->mru);
-	syslog(0, "ppp", "%ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld",
+	syslog(0, LOG, "%ux %s->%s ctlmap %lux/%lux flags %lux mtu %ld mru %ld",
 		p->proto, snames[p->state], snames[state], ppp->rctlmap,
 		ppp->xctlmap, p->flags,
 		ppp->mtu, ppp->mru);
@@ -710,7 +706,7 @@
 		break;
 	case Pipcp:
 		if(p->optmask & Fipaddr){
-			syslog(0, "ppp", "requesting %I", ppp->local);
+			syslog(0, LOG, "requesting %I", ppp->local);
 			putv4o(b, Oipaddr, ppp->local);
 		}
 		primary = 1;
@@ -1117,7 +1113,7 @@
 		case Pipcp:
 			switch(o->type){
 			case Oipaddr:
-syslog(0, "ppp", "rejected addr %I with %V", ppp->local, o->data);
+				syslog(0, LOG, "rejected addr %I with %V", ppp->local, o->data);
 				/* if we're a server, don't let other end change our addr */
 				if(ppp->localfrozen){
 					dropoption(p, o);
@@ -1456,12 +1452,26 @@
 	if(ppp->chap->id < 21)
 		putpaprequest(ppp);
 	else {
-		terminate(ppp, 0);
 		netlog("ppp: pap timed out--not authorized\n");
+		terminate(ppp, "pap timeout");
 	}
 }
 
+static void
+pingtimer(PPP* ppp)
+{
+	if(ppp->lcp->echotimeout == 0 || ppp->lcp->echoack)
+		ppp->lcp->echotimeout = (3*4*1000+Period-1)/Period;
+	else if(--(ppp->lcp->echotimeout) <= 0){
+		netlog("ppp: echo request timeout\n");
+		terminate(ppp, "echo timeout");
+		return;
+	}
+	ppp->lcp->echoack = 0;
+	sendechoreq(ppp, ppp->lcp);
+}
 
+
 /*
  *  timer for ppp
  */
@@ -1479,6 +1489,8 @@
 			case Pnet:
 				ptimer(ppp, ppp->ccp);
 				ptimer(ppp, ppp->ipcp);
+
+				pingtimer(ppp);
 				break;
 			case Pauth:
 				authtimer(ppp);
@@ -1567,8 +1579,8 @@
 			sysfatal("forking ipinproc");
 		case 0:
 			ipinproc(ppp);
-			terminate(ppp, 1);
-			_exits(0);
+			terminate(ppp, "ipinproc");
+			exits(nil);
 		}
 	} else {
 		/* we may have changed addresses */
@@ -1578,14 +1590,14 @@
 			snprint(buf, sizeof buf, "remove %I 255.255.255.255 %I",
 			    ppp->curlocal, ppp->curremote);
 			if(fprint(ppp->ipcfd, "%s", buf) < 0)
-				syslog(0, "ppp", "can't %s: %r", buf);
+				syslog(0, LOG, "can't %s: %r", buf);
 			snprint(buf, sizeof buf, "add %I 255.255.255.255 %I %lud proxy",
 			    ppp->local, ppp->remote, ppp->mtu-10);
 			if(fprint(ppp->ipcfd, "%s", buf) < 0)
-				syslog(0, "ppp", "can't %s: %r", buf);
+				syslog(0, LOG, "can't %s: %r", buf);
 			defroute(ppp->net, "add", ppp->remote, ppp->local);
 		}
-		syslog(0, "ppp", "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,
+		syslog(0, LOG, "%I/%I -> %I/%I", ppp->curlocal, ppp->curremote,
 		   ppp->local, ppp->remote);
 	}
 	ipmove(ppp->curlocal, ppp->local);
@@ -1744,8 +1756,16 @@
 }
 
 static void
-terminate(PPP *ppp, int kill)
+terminate(PPP *ppp, char *why)
 {
+	if(dying++)
+		return;
+
+	syslog(0, LOG, "ppp: terminated: %s", why);
+
+	if(ppp->net != nil && validv4(ppp->curremote) && validv4(ppp->curlocal))
+		defroute(ppp->net, "remove", ppp->curremote, ppp->curlocal);
+
 	close(ppp->ipfd);
 	ppp->ipfd = -1;
 	close(ppp->ipcfd);
@@ -1754,10 +1774,7 @@
 	close(ppp->mediaout);
 	ppp->mediain = -1;
 	ppp->mediaout = -1;
-	dying = 1;
-
-	if(kill)
-		postnote(PNGROUP, getpid(), "die");
+	postnote(PNGROUP, getpid(), "die");
 }
 
 typedef struct Iphdr Iphdr;
@@ -2172,7 +2189,7 @@
 			n = snprint((char*)resp, sizeof(resp), "S=%.20H", c->ai->secret+16);
 			if(len - 4 < n || tsmemcmp(m->data, resp, n) != 0){
 				netlog("ppp: chap: bad authenticator\n");
-				terminate(ppp, 0);
+				terminate(ppp, "chap: bad authenticator");
 				break;
 			}
 		}
@@ -2182,7 +2199,7 @@
 		break;
 	case Cfailure:
 		netlog("ppp: chap failed\n");
-		terminate(ppp, 0);
+		terminate(ppp, "chap failed");
 		break;
 	default:
 		syslog(0, LOG, "chap code %d?", m->code);
@@ -2270,7 +2287,7 @@
 		&& m->id <= ppp-> chap->id){
 			netlog("ppp: pap failed (%d:%.*s)\n",
 				m->data[0], utfnlen((char*)m->data+1, m->data[0]), (char*)m->data+1);
-			terminate(ppp, 0);
+			terminate(ppp, "pap failed");
 		}
 		break;
 	default:
@@ -2447,8 +2464,10 @@
 	Lcpmsg *m;
 
 	p->termid = ++(p->id);
-	b = alloclcp(Lechoreq, p->id, 4, &m);
-	hnputs(m->len, 4);
+	b = alloclcp(Lechoreq, p->id, 8, &m);
+	hnputl(b->wptr, ppp->magic);
+	b->wptr += 4;
+	hnputs(m->len, 8);
 	putframe(ppp, p->proto, b);
 	freeb(b);
 }
@@ -2593,7 +2612,7 @@
 		sysfatal("forking xfer");
 	case 0:
 		xfer(fd);
-		_exits(nil);
+		exits(nil);
 	}
 
 	for(;;){
@@ -2801,7 +2820,7 @@
 	if(primary)
 		putndb(ppp, net);
 
-	exits(0);
+	exits(nil);
 }
 
 void
--- a/sys/src/cmd/ip/ppp/ppp.h
+++ b/sys/src/cmd/ip/ppp/ppp.h
@@ -70,7 +70,6 @@
 	Plink,				/* doing LCP */
 	Pauth,				/* doing chap */
 	Pnet,				/* doing IPCP, CCP */
-	Pterm,				/* closing down */
 
 	/* PPP protocol types */
 	Pip=		0x21,		/* ip v4 */
--- a/sys/src/cmd/ip/ppp/testppp.c
+++ b/sys/src/cmd/ip/ppp/testppp.c
@@ -20,7 +20,7 @@
 	switch(fork()){
 	case -1:
 		fprint(2, "testppp: can't fork: %r\n");
-		exits(0);
+		exits("fork");
 	case 0:
 		return;
 	default:
@@ -89,7 +89,7 @@
 		n = read(from, buf, sizeof(buf));
 		if(n <= 0){
 			fprint(2, "%d -> %d EOF\n", from, to);
-			exits(0);
+			exits("read");
 		}
 		modified = 0;
 		if(errrate){
@@ -121,7 +121,7 @@
 		n = write(to, buf, n);
 		if(n < 0){
 			fprint(2, "%d -> %d write err\n", from, to);
-			exits(0);
+			exits("write");
 		}
 	}
 }
@@ -193,6 +193,6 @@
 
 	xfer(pfd1[1], pfd2[1]);
 	xfer(pfd2[1], pfd1[1]);
-	exits(0);
+	exits(nil);
 }
 
--- a/sys/src/cmd/ip/ppp/thw.c
+++ b/sys/src/cmd/ip/ppp/thw.c
@@ -253,7 +253,7 @@
 	uncs = ppp->uncstate;
 
 	if(BLEN(bb) < 4){
-		syslog(0, "ppp", ": thwack: short packet");
+		syslog(0, LOG, ": thwack: short packet");
 		freeb(bb);
 		return nil;
 	}
@@ -279,7 +279,7 @@
 			n = unthwack(&uncs->ut, b->wptr, ThwMaxBlock, bb->rptr, BLEN(bb), seq & ThwSeqMask);
 			freeb(bb);
 			if(n < 2){
-				syslog(0, "ppp", ": unthwack: short or corrupted packet %d seq=%ld", n, seq);
+				syslog(0, LOG, ": unthwack: short or corrupted packet %d seq=%ld", n, seq);
 				netlog("unthwack: short or corrupted packet n=%d seq=%ld: %s\n", n, seq, uncs->ut.err);
 				freeb(b);