ref: 74272a8364547a7451f5e13f3988c75eb69ba3d7
parent: 0311f011228a5d26a7a73128c489782870b69693
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Sep 22 22:08:59 EDT 2018
ip/ipconfig: remove expired default routes on router advertisement
--- a/sys/src/cmd/ip/ipconfig/ipconfig.h
+++ b/sys/src/cmd/ip/ipconfig/ipconfig.h
@@ -119,7 +119,7 @@
void ipunconfig(void);
void adddefroute(uchar*, uchar*, uchar*, uchar*);
-void removedefroute(int, uchar*, uchar*);
+void removedefroute(uchar*, uchar*, uchar*, uchar*);
long jitter(void);
void procsetname(char *fmt, ...);
--- a/sys/src/cmd/ip/ipconfig/ipv6.c
+++ b/sys/src/cmd/ip/ipconfig/ipv6.c
@@ -545,23 +545,6 @@
}
static int
-seen(Conf *cf)
-{
- static uchar tab[SHA1dlen*100], *w;
- uchar hash[SHA1dlen], *r;
-
- sha1((uchar*)cf, sizeof(*cf), hash, nil);
- if(w == nil || w == &tab[sizeof(tab)])
- w = tab;
- for(r = tab; r < w; r += SHA1dlen)
- if(memcmp(r, hash, SHA1dlen) == 0)
- return 1;
- memmove(w, hash, SHA1dlen);
- w += SHA1dlen;
- return 0;
-}
-
-static int
pnames(uchar *d, int nd, char *s)
{
uchar *de = d + nd;
@@ -621,6 +604,25 @@
return d - (de - nd);
}
+typedef struct Route Route;
+struct Route
+{
+ Route *next;
+ ulong time;
+
+ ulong prefixlt;
+ ulong routerlt;
+
+ uchar src[IPaddrlen];
+ uchar gaddr[IPaddrlen];
+ uchar laddr[IPaddrlen];
+ uchar mask[IPaddrlen];
+
+ uchar hash[SHA1dlen];
+};
+
+static Route *routelist;
+
/*
* host receiving a router advertisement calls this
*/
@@ -628,12 +630,15 @@
recvrahost(uchar buf[], int pktlen)
{
char dnsdomain[sizeof(conf.dnsdomain)];
- int m, n, optype;
+ int m, n, optype, seen;
Lladdropt *llao;
Mtuopt *mtuo;
Prefixopt *prfo;
Ipaddrsopt *addrso;
Routeradv *ra;
+ uchar hash[SHA1dlen];
+ Route *r, **rr;
+ ulong now;
m = sizeof *ra;
ra = (Routeradv*)buf;
@@ -709,6 +714,26 @@
}
issuebasera6(&conf);
+ /* remove expired default routes */
+ m = 0;
+ now = time(nil);
+ for(rr = &routelist; (r = *rr) != nil;){
+ if(m > 100
+ || r->prefixlt != ~0UL && now > r->time+r->prefixlt
+ || r->routerlt != ~0UL && now > r->time+r->routerlt
+ || ipcmp(r->src, ra->src) == 0 && r->routerlt != 0 && conf.routerlt == 0){
+ if(validip(r->gaddr))
+ removedefroute(r->gaddr, conf.lladdr, r->laddr, r->mask);
+ *rr = r->next;
+ r->next = nil;
+ free(r);
+ continue;
+ }
+
+ rr = &r->next;
+ m++;
+ }
+
/* process prefixes */
m = sizeof *ra;
while(pktlen - m >= 8) {
@@ -741,6 +766,36 @@
ipmove(conf.gaddr, prfo->pref);
else
ipmove(conf.gaddr, ra->src);
+
+ seen = 0;
+ 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;
+ r->next = nil;
+ break;
+ }
+ }
+ if(r == nil)
+ r = malloc(sizeof(*r));
+
+ memmove(r->hash, hash, SHA1dlen);
+
+ 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;
+ if(r->prefixlt != ~0UL)
+ r->prefixlt /= 1000;
+
+ r->next = routelist;
+ routelist = r;
if(conf.prefixlen < 1
|| conf.prefixlen > 64
@@ -749,7 +804,7 @@
|| ipcmp(conf.v6pref, v6loopback) == 0
|| ISIPV6MCAST(conf.v6pref)
|| ISIPV6LINKLOCAL(conf.v6pref)){
- if(!seen(&conf))
+ if(!seen)
warning("igoring bogus prefix from %I on %s; pfx %I %M",
ra->src, conf.dev, conf.v6pref, conf.mask);
continue;
@@ -759,7 +814,7 @@
issueadd6(&conf);
/* report this prefix configuration only once */
- if(seen(&conf))
+ if(seen)
continue;
DEBUG("got RA from %I on %s; pfx %I %M",
--- a/sys/src/cmd/ip/ipconfig/main.c
+++ b/sys/src/cmd/ip/ipconfig/main.c
@@ -704,33 +704,21 @@
return isv4(src)? memcmp(smask+IPv4off, IPnoaddr+IPv4off, 4): ipcmp(smask, IPnoaddr);
}
-void
-addroute(uchar *dst, uchar *mask, uchar *gate, uchar *ia, uchar *src, uchar *smask)
+static void
+routectl(char *cmd, uchar *dst, uchar *mask, uchar *gate, uchar *ia, uchar *src, uchar *smask)
{
- char *cmd;
+ char *ctl;
if(issrcspec(src, smask))
- cmd = "add %I %M %I %I %I %M";
+ ctl = "%s %I %M %I %I %I %M";
else
- cmd = "add %I %M %I %I";
- fprint(conf.rfd, cmd, dst, mask, gate, ia, src, smask);
+ ctl = "%s %I %M %I %I";
+ fprint(conf.rfd, ctl, cmd, dst, mask, gate, ia, src, smask);
}
-void
-removeroute(uchar *dst, uchar *mask, uchar *src, uchar *smask)
+static void
+defroutectl(char *cmd, uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
{
- char *cmd;
-
- if(issrcspec(src, smask))
- cmd = "remove %I %M %I %M";
- else
- cmd = "remove %I %M";
- fprint(conf.rfd, cmd, dst, mask, src, smask);
-}
-
-void
-adddefroute(uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
-{
uchar dst[IPaddrlen], mask[IPaddrlen];
if(isv4(gaddr)){
@@ -748,11 +736,23 @@
if(smask == nil)
smask = IPnoaddr;
}
- addroute(dst, mask, gaddr, ia, src, smask);
+ routectl(cmd, dst, mask, gaddr, ia, src, smask);
/* also add a source specific route */
if(ipcmp(src, IPnoaddr) != 0 && ipcmp(src, v4prefix) != 0)
- addroute(dst, mask, gaddr, ia, src, IPallbits);
+ routectl(cmd, dst, mask, gaddr, ia, src, IPallbits);
+}
+
+void
+adddefroute(uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
+{
+ defroutectl("add", gaddr, ia, src, smask);
+}
+
+void
+removedefroute(uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
+{
+ defroutectl("remove", gaddr, ia, src, smask);
}
void