shithub: front

Download patch

ref: 82f44b3ffca7c854a3e1bb10aa42da7d5bffae7b
parent: 71d676a12ff86453491ab36c62835d5443903f68
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Jun 15 13:20:45 EDT 2024

ip/ipconfig: properly handle ipv6 address deprecations

do not add default route when address is
deprecated (preflt == 0).

delete previous default route on router change.

implement rfc4862 section 5.5.3 processing rules
in regard to remaining valid lifetime.

--- a/sys/src/cmd/ip/ipconfig/ipv6.c
+++ b/sys/src/cmd/ip/ipconfig/ipv6.c
@@ -655,9 +655,10 @@
 
 	issuebasera6(&conf);
 
+	now = time(nil);
+
 	/* remove expired default routes */
 	m = 0;
-	now = time(nil);
 	for(rr = &routelist; (r = *rr) != nil;){
 		if(m > 100
 		|| r->prefixlt != ~0UL && r->prefixlt < now-r->time
@@ -671,7 +672,6 @@
 			free(r);
 			continue;
 		}
-
 		rr = &r->next;
 		m++;
 	}
@@ -699,8 +699,19 @@
 			continue;
 
 		conf.prefixlen = prfo->plen & 127;
+		if(conf.prefixlen < 1
+		|| conf.prefixlen > 64)
+			continue;
+
 		genipmkask(conf.mask, conf.prefixlen);
 		maskip(prfo->pref, conf.mask, conf.v6pref);
+		if(!validip(conf.v6pref)
+		|| isv4(conf.v6pref)
+		|| ipcmp(conf.v6pref, v6loopback) == 0
+		|| ISIPV6MCAST(conf.v6pref)
+		|| ISIPV6LINKLOCAL(conf.v6pref))
+			continue;
+
 		memmove(conf.laddr, conf.v6pref, 8);
 		memmove(conf.laddr+8, conf.lladdr+8, 8);
 		ipmove(conf.gaddr, (prfo->lar & RFMASK) != 0? prfo->pref: ra->src);
@@ -708,61 +719,71 @@
 		conf.autoflag = (prfo->lar & AFMASK) != 0;
 		conf.validlt = nhgetl(prfo->validlt);
 		conf.preflt = nhgetl(prfo->preflt);
+		if(conf.preflt > conf.validlt)
+			continue;
 
-		seen = 0;
+		if(conf.routerlt == 0
+		|| conf.preflt == 0
+		|| isula(conf.laddr)
+		|| ipcmp(conf.gaddr, conf.laddr) == 0
+		|| ipcmp(conf.gaddr, conf.lladdr) == 0)
+			ipmove(conf.gaddr, IPnoaddr);
+
 		sha1((uchar*)&conf, sizeof(conf), hash, nil);
 		for(rr = &routelist; (r = *rr) != nil; rr = &r->next){
 			if(ipcmp(r->src, ra->src) == 0
 			&& ipcmp(r->laddr, conf.laddr) == 0){
-				seen = memcmp(r->hash, hash, SHA1dlen) == 0;
 				*rr = r->next;
 				break;
 			}
 		}
-		if(r == nil)
+		if(r != nil){
+			/* rfc4862, section 5.5.3, e) */
+			ulong remaining = r->prefixlt != ~0UL ? r->time + r->prefixlt : ~0UL;
+			ulong signaled = conf.validlt != ~0UL ? now + conf.validlt : ~0UL;
+			ulong timeout = now + 2*60*60;	/* 2 horus from now */
+			if(signaled <= timeout && signaled <= remaining) {
+				if(remaining <= timeout)
+					conf.validlt = remaining - now;
+				else
+					conf.validlt = timeout - now;
+				if (conf.preflt > conf.validlt)
+					conf.preflt = conf.validlt;
+			}
+			seen = memcmp(r->hash, hash, SHA1dlen) == 0;
+			if(!seen && validip(r->gaddr) && ipcmp(r->gaddr, conf.gaddr) != 0){
+				DEBUG("changing router %I->%I", r->gaddr, conf.gaddr);
+				if(!noconfig)
+					deldefroute(r->gaddr, conf.lladdr, r->laddr, r->mask);
+			}
+		} else {
+			seen = 0;
+			if(conf.preflt == 0)
+				continue;
 			r = malloc(sizeof(*r));
-
+		}
 		memmove(r->hash, hash, SHA1dlen);
 
-		if(conf.routerlt == 0
-		|| isula(conf.laddr)
-		|| ipcmp(conf.gaddr, conf.laddr) == 0
-		|| ipcmp(conf.gaddr, conf.lladdr) == 0)
-			ipmove(conf.gaddr, IPnoaddr);
-
+		r->time = now;
+		r->routerlt = conf.routerlt;
+		r->prefixlt = conf.validlt;
 		ipmove(r->src, ra->src);
 		ipmove(r->gaddr, conf.gaddr);
 		ipmove(r->laddr, conf.laddr);
 		ipmove(r->mask, conf.mask);
 
-		r->time = now;
-		r->routerlt = conf.routerlt;
-		r->prefixlt = conf.validlt;
-
 		r->next = routelist;
 		routelist = r;
 	
-		if(conf.prefixlen < 1
-		|| conf.prefixlen > 64
-		|| !validip(conf.v6pref)
-		|| isv4(conf.v6pref)
-		|| ipcmp(conf.v6pref, v6loopback) == 0
-		|| ISIPV6MCAST(conf.v6pref)
-		|| ISIPV6LINKLOCAL(conf.v6pref)){
-			if(!seen)
-				warning("igoring bogus prefix from %I on %s; pfx %I %M",
-					ra->src, conf.dev, conf.v6pref, conf.mask);
-
-			/* keep it arround so we wont comlain again */
-			r->prefixlt = r->routerlt = ~0UL;
-			continue;
-		}
-
 		/* add prefix and update parameters */
 		issueadd6(&conf);
 
-		/* report this prefix configuration only once */
+		/* report only once */
 		if(seen)
+			continue;
+
+		/* must not be deprecated */
+		if(conf.preflt == 0)
 			continue;
 
 		DEBUG("got RA from %I on %s; pfx %I %M",
--