code: plan9front

Download patch

ref: 0c2a74d5309f03f87e24b827bacee0ed58d37202
parent: 0f3953f95405ea694206f6ec41b9fd47358f03cd
parent: 3f52f47b9b698045b3948a9321264390b268b3d8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Nov 18 13:08:53 EST 2023

merge

--- a/sys/man/3/ip
+++ b/sys/man/3/ip
@@ -210,8 +210,8 @@
 .IR trampoline (8)
 to a different ip stack. 
 .TP
-.BI remove\  "local mask"
-Remove a local IP address from an interface.
+.BI del\  "local mask"
+Delete a local IP address from an interface.
 .TP
 .BI mtu\  n
 Set the maximum transfer unit for this device to
@@ -271,8 +271,8 @@
 .I Media-addr
 on this interface as a local address.
 .TP
-.BI remmulti\  Media-addr
-Remove the multicast address
+.BI delmulti\  Media-addr
+Delete the multicast address
 .I Media-addr
 from this interface.
 .TP
@@ -310,8 +310,8 @@
 .RE
 .PD
 .TP
-.B remove6
-Remove local IPv6 addresses that have expired ther
+.B del6
+Delete local IPv6 addresses that have expired ther
 valid life-time.
 .TP
 .BI "ra6 " "keyword value ..."
@@ -465,20 +465,20 @@
 .B "-"
 when unspecified.
 .TP
-.BI remove\  "target mask"
+.BI del\  "target mask"
 .TP
-.BI remove\  "target mask nexthop"
+.BI del\  "target mask nexthop"
 .TP
-.BI remove\  "target mask source smask"
+.BI del\  "target mask source smask"
 .TP
-.BI remove\  "target mask nexthop source smask"
+.BI del\  "target mask nexthop source smask"
 .TP
-.BI remove\  "target mask nexthop interface source smask"
+.BI del\  "target mask nexthop interface source smask"
 .TP
-.BI remove\  "target mask nexthop flags interface source smask"
+.BI del\  "target mask nexthop flags interface source smask"
 .TP
-.BI remove\  "target mask nexthop flags tag interface source smask"
-Remove the matching route.
+.BI del\  "target mask nexthop flags tag interface source smask"
+Delete the matching route.
 .
 .SS "Address resolution
 The file
@@ -662,7 +662,7 @@
 to receive incoming calls.
 .PP
 The following control messages are supported:
-.TF "\fLremmulti \fIip\fR"
+.TF "\fLdelmulti \fIip\fR"
 .PD
 .TP
 .BI connect\  ip-address ! port "!r " local
@@ -760,8 +760,8 @@
 is present,
 use it as the interface's multicast address.
 .TP
-.BI remmulti\  ip
-Remove the address
+.BI delmulti\  ip
+Delete the address
 .I ip
 from this multicast interface.
 .PP
--- a/sys/man/8/ipconfig
+++ b/sys/man/8/ipconfig
@@ -100,7 +100,7 @@
 The verb (default
 .IR add )
 determines the action performed.  The usual verbs are:
-.TF remove
+.TF del
 .TP
 .B add
 if the device is not bound to the IP stack, bind it.
@@ -107,8 +107,8 @@
 Add the given local address, mask, and remote address to the interface.
 An interface may have multiple addresses.
 .TP
-.B remove
-remove the address from the device interface.
+.B del
+delete the address from the device interface.
 .TP
 .B unbind
 unbind the device interface and all its addresses from the
@@ -253,7 +253,7 @@
 .TP
 .B u
 disable IPv6 duplicate discovery detection,
-which removes any existing ARP table entry for one of our IPv6 addresses
+which deletes any existing ARP table entry for one of our IPv6 addresses
 before adding new ones.
 .TP
 .B f
@@ -309,7 +309,7 @@
 If DHCP is requested, a process is forked
 off to renew the lease before it
 runs out.  If the lease does run out, this
-process will remove any configured addresses
+process will delete any configured addresses
 from the interface.
 .PP
 .I Rip
--- a/sys/src/9/ip/arp.c
+++ b/sys/src/9/ip/arp.c
@@ -494,7 +494,6 @@
 		}
 		if((ifc = findipifc(fs, ia, ia, Runi)) == nil)
 			error("no interface");
-		rlock(ifc);
 		if(!ipv6local(ifc, ia, 0, ip) || arpenter(fs, V6, ip, mac, n, ia, ifc, 0) < 0){
 			runlock(ifc);
 			error("destination unreachable");
@@ -522,8 +521,6 @@
 
 		if((ifc = findipifc(fs, ip, ip, Runi)) == nil)
 			error("no interface");
-
-		rlock(ifc);
 		if(waserror()){
 			runlock(ifc);
 			nexterror();
--- a/sys/src/9/ip/devip.c
+++ b/sys/src/9/ip/devip.c
@@ -571,7 +571,7 @@
 	cv->perm = 0660;
 
 	while((mp = cv->multi) != nil)
-		ipifcremmulti(cv, mp->ma, mp->ia);
+		ipifcdelmulti(cv, mp->ma, mp->ia);
 
 	if(cv->p->close != nil)
 		(*cv->p->close)(cv);
@@ -1210,15 +1210,16 @@
 					error(Ebadip);
 				ipifcaddmulti(c, ma, ia);
 			}
-		} else if(strcmp(cb->f[0], "remmulti") == 0){
+		} else if (strcmp(cb->f[0], "delmulti") == 0
+			|| strcmp(cb->f[0], "remmulti") == 0){
 			if(cb->nf < 2)
-				error("remmulti needs interface address");
+				error("delmulti needs interface address");
 			if (parseip(ia, cb->f[1]) == -1)
 				error(Ebadip);
 			if(ipcmp(c->raddr, IPnoaddr) == 0 || ipismulticast(c->laddr))
-				ipifcremmulti(c, c->laddr, ia);
+				ipifcdelmulti(c, c->laddr, ia);
 			else
-				ipifcremmulti(c, c->raddr, ia);
+				ipifcdelmulti(c, c->raddr, ia);
 		} else if(x->ctl != nil) {
 			p = (*x->ctl)(c, cb->f, cb->nf);
 			if(p != nil)
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -23,7 +23,7 @@
 static void	etherunbind(Ipifc *ifc);
 static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip, Routehint *rh);
 static void	etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
-static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
+static void	etherdelmulti(Ipifc *ifc, uchar *a, uchar *ia);
 static void	etherareg(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *ip);
 static Block*	multicastarp(Fs *f, Arpent *a, uchar *mac, Routehint *rh);
 static Block*	newEARP(void);
@@ -43,7 +43,7 @@
 .unbind=	etherunbind,
 .bwrite=	etherbwrite,
 .addmulti=	etheraddmulti,
-.remmulti=	etherremmulti,
+.delmulti=	etherdelmulti,
 .areg=		etherareg,
 .pref2addr=	etherpref2addr,
 };
@@ -59,7 +59,7 @@
 .unbind=	etherunbind,
 .bwrite=	etherbwrite,
 .addmulti=	etheraddmulti,
-.remmulti=	etherremmulti,
+.delmulti=	etherdelmulti,
 .areg=		etherareg,
 .pref2addr=	etherpref2addr,
 };
@@ -419,7 +419,7 @@
 }
 
 static void
-etherremmulti(Ipifc *ifc, uchar *a, uchar *)
+etherdelmulti(Ipifc *ifc, uchar *a, uchar *)
 {
 	uchar mac[6];
 	char buf[64];
@@ -436,7 +436,7 @@
 		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
 		break;
 	default:
-		panic("etherremmulti: version %d", version);
+		panic("etherdelmulti: version %d", version);
 	}
 }
 
@@ -734,10 +734,10 @@
 	ipv62smcast(a, ip);
 	addroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
 	if(waserror()){
-		remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
+		delroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
 		nexterror();
 	}
 	icmpns6(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac, 6);
 	poperror();
-	remroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
+	delroute(f, a, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
 }
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -309,7 +309,7 @@
 
 	/* for arming interfaces to receive multicast */
 	void	(*addmulti)(Ipifc *ifc, uchar *a, uchar *ia);
-	void	(*remmulti)(Ipifc *ifc, uchar *a, uchar *ia);
+	void	(*delmulti)(Ipifc *ifc, uchar *a, uchar *ia);
 
 	/* process packets written to 'data' */
 	void	(*pktin)(Fs *f, Ipifc *ifc, Block *bp);
@@ -478,7 +478,7 @@
 	int	np;
 	Proto*	p[Maxproto+1];		/* list of supported protocols */
 	Proto*	t2p[256];		/* vector of all protocols */
-	Proto*	ipifc;			/* kludge for ipifcremroute & ipifcaddroute */
+	Proto*	ipifc;			/* kludge for findipifc */
 	Proto*	ipmux;			/* kludge for finding an ip multiplexor */
 
 	IP	*ip;
@@ -623,7 +623,7 @@
 };
 
 extern void	addroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag);
-extern void	remroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag);
+extern void	delroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag);
 extern Route*	v4lookup(Fs *f, uchar *a, uchar *s, Routehint *rh);
 extern Route*	v6lookup(Fs *f, uchar *a, uchar *s, Routehint *rh);
 extern Route*	v4source(Fs *f, uchar *a, uchar *s);
@@ -734,13 +734,13 @@
 extern Iplifc*	iplocalonifc(Ipifc *ifc, uchar *ip);
 extern Iplifc*	ipremoteonifc(Ipifc *ifc, uchar *ip);
 extern Ipmulti*	ipifcgetmulti(Fs *f, Ipifc *ifc, uchar *ma);
-extern void	ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
 extern void	ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
-extern char*	ipifcrem(Ipifc *ifc, char **argv, int argc);
+extern void	ipifcdelmulti(Conv *c, uchar *ma, uchar *ia);
 extern char*	ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp);
+extern char*	ipifcdel(Ipifc *ifc, char **argv, int argc);
 extern long	ipselftabread(Fs*, char *a, ulong offset, int n);
 extern char*	ipifcadd6(Ipifc *ifc, char**argv, int argc);
-extern char*	ipifcremove6(Ipifc *ifc, char**argv, int argc);
+extern char*	ipifcdel6(Ipifc *ifc, char**argv, int argc);
 extern char*	mediumunbindifc(Ipifc *ifc);
 
 /*
--- a/sys/src/9/ip/ipifc.c
+++ b/sys/src/9/ip/ipifc.c
@@ -47,10 +47,10 @@
 static char tifc[] = "ifc ";
 
 static void	addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
-static void	remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
+static void	delselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
 static void	ipifcregisteraddr(Fs*, Ipifc*, Iplifc*, uchar*);
 static void	ipifcregisterproxy(Fs*, Ipifc*, uchar*, int);
-static char*	ipifcremlifc(Ipifc*, Iplifc**);
+static char*	ipifcdellifc(Ipifc*, Iplifc**);
 
 static char Ebound[] = "interface already bound";
 static char Eunbound[] = "interface not bound";
@@ -206,7 +206,7 @@
 
 	/* disassociate logical interfaces */
 	while(ifc->lifc != nil)
-		ipifcremlifc(ifc, &ifc->lifc);
+		ipifcdellifc(ifc, &ifc->lifc);
 
 	/* disassociate device */
 	if(m->unbind != nil){
@@ -693,7 +693,7 @@
  *	called with ifc wlock'd
  */
 static char*
-ipifcremlifc(Ipifc *ifc, Iplifc **l)
+ipifcdellifc(Ipifc *ifc, Iplifc **l)
 {
 	Iplifc *lifc = *l;
 	Fs *f = ifc->conv->p->f;
@@ -704,15 +704,15 @@
 
 	/* disassociate any addresses */
 	while(lifc->link != nil)
-		remselfcache(f, ifc, lifc, lifc->link->self->a);
+		delselfcache(f, ifc, lifc, lifc->link->self->a);
 
 	/* remove the route for this logical interface */
 	if(lifc->onlink){
-		remroute(f, lifc->remote, lifc->mask,
+		delroute(f, lifc->remote, lifc->mask,
 			lifc->local, IPallbits,
 			lifc->remote, lifc->type&~Rtrans, ifc, tifc);
 		if(v6addrtype(lifc->local) != linklocalv6)
-			remroute(f, lifc->remote, lifc->mask,
+			delroute(f, lifc->remote, lifc->mask,
 				lifc->local, IPnoaddr,
 				lifc->remote, lifc->type, ifc, tifc);
 	}
@@ -731,11 +731,11 @@
 	/* remove route for all nodes multicast */
 	if((lifc->type & Rv4) == 0){
 		if(ipcmp(lifc->local, v6loopback) == 0){
-			remroute(f, v6allnodesN, v6allnodesNmask,
+			delroute(f, v6allnodesN, v6allnodesNmask,
 				lifc->local, IPallbits,
 				v6allnodesN, Rmulti, ifc, tifc);
 		}
-		remroute(f, v6allnodesL, v6allnodesLmask,
+		delroute(f, v6allnodesL, v6allnodesLmask,
 			lifc->local, IPallbits,
 			v6allnodesL, Rmulti, ifc, tifc);
 	}
@@ -749,7 +749,7 @@
  *  remove an address from an interface.
  */
 char*
-ipifcrem(Ipifc *ifc, char **argv, int argc)
+ipifcdel(Ipifc *ifc, char **argv, int argc)
 {
 	uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
 	Iplifc *lifc, **l;
@@ -778,7 +778,7 @@
 			break;
 		l = &lifc->next;
 	}
-	err = ipifcremlifc(ifc, l);
+	err = ipifcdellifc(ifc, l);
 	wunlock(ifc);
 	return err;
 }
@@ -796,7 +796,7 @@
 
 	wlock(ifc);
 	while(ifc->lifc != nil)
-		ipifcremlifc(ifc, &ifc->lifc);
+		ipifcdellifc(ifc, &ifc->lifc);
 	wunlock(ifc);
 
 	err = ipifcadd(ifc, argv, argc, 0, nil);
@@ -882,14 +882,14 @@
 		err = ipifcadd(ifc, argv, argc, 0, nil);
 	else if(strcmp(argv[0], "try") == 0)
 		err = ipifcadd(ifc, argv, argc, 1, nil);
-	else if(strcmp(argv[0], "remove") == 0)
-		err = ipifcrem(ifc, argv, argc);
+	else if(strcmp(argv[0], "del") == 0 || strcmp(argv[0], "remove") == 0)
+		err = ipifcdel(ifc, argv, argc);
 	else if(strcmp(argv[0], "unbind") == 0)
 		err = ipifcunbind(ifc);
 	else if(strcmp(argv[0], "add6") == 0)
 		err = ipifcadd6(ifc, argv, argc);
-	else if(strcmp(argv[0], "remove6") == 0)
-		err = ipifcremove6(ifc, argv, argc);
+	else if(strcmp(argv[0], "del6") == 0 || strcmp(argv[0], "remove6") == 0)
+		err = ipifcdel6(ifc, argv, argc);
 	else {
 		wlock(ifc);
 		if(ifc->m == nil || ifc->m == &unboundmedium){
@@ -944,7 +944,7 @@
 	ipifc->nc = Maxmedia;
 	ipifc->ptclsize = sizeof(Ipifc);
 
-	f->ipifc = ipifc;	/* hack for ipifcremroute, findipifc, ... */
+	f->ipifc = ipifc;
 	f->self = smalloc(sizeof(Ipselftab));	/* hack for ipforme */
 
 	Fsproto(f, ipifc);
@@ -1086,7 +1086,7 @@
  *  Unlink from selftab if this is the last ref.
  */
 static void
-remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
+delselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
 {
 	Ipself *p, **l;
 	Iplink *link, **l_self, **l_lifc;
@@ -1130,7 +1130,7 @@
 	}
 
 	if(link == nil)
-		panic("remselfcache");
+		panic("delselfcache");
 
 	if(--(link->ref) != 0)
 		goto out;
@@ -1147,9 +1147,9 @@
 				poperror();
 			}
 		}
-		if(ifc->m->remmulti != nil){
+		if(ifc->m->delmulti != nil){
 			if(!waserror()){
-				(*ifc->m->remmulti)(ifc, a, lifc->local);
+				(*ifc->m->delmulti)(ifc, a, lifc->local);
 				poperror();
 			}
 		}
@@ -1156,7 +1156,7 @@
 	}
 
 	/* remove from routing table */
-	remroute(f, a, IPallbits,
+	delroute(f, a, IPallbits,
 		lifc->local, 
 		((p->type & (Rbcast|Rmulti)) != 0 || v6addrtype(a) == linklocalv6) ?
 			IPallbits : IPnoaddr,
@@ -1228,8 +1228,8 @@
 }
 
 /*
- *  find the ifc on same net as the remote system.  If none,
- *  return nil.
+ *  find the ifc on same net as the remote system.
+ *  returns the rlocked ifc, otherwise nil.
  */
 Ipifc*
 findipifc(Fs *f, uchar *local, uchar *remote, int type)
@@ -1236,11 +1236,13 @@
 {
 	uchar gnet[IPaddrlen];
 	int spec, xspec;
-	Ipifc *ifc, *x;
+	uchar xifcid;
+	Ipifc *x, *ifc;
 	Iplifc *lifc;
 	Conv **cp;
 
 	x = nil;
+	xifcid = 0;
 	xspec = 0;
 	for(cp = f->ipifc->conv; *cp != nil; cp++){
 		ifc = (Ipifc*)(*cp)->ptcl;
@@ -1248,14 +1250,11 @@
 			continue;
 		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
 			if(type & Runi){
-				if(ipcmp(remote, lifc->local) == 0){
-				Found:
-					runlock(ifc);
+				if(ipcmp(remote, lifc->local) == 0)
 					return ifc;
-				}
 			} else if(type & (Rbcast|Rmulti)) {
 				if(ipcmp(local, lifc->local) == 0)
-					goto Found;
+					return ifc;
 			}
 			maskip(remote, lifc->mask, gnet);
 			if(ipcmp(gnet, lifc->net) == 0){
@@ -1262,6 +1261,7 @@
 				spec = comprefixlen(remote, lifc->local, IPaddrlen);
 				if(spec > xspec){
 					x = ifc;
+					xifcid = ifc->ifcid;
 					xspec = spec;
 				}
 			}
@@ -1268,7 +1268,12 @@
 		}
 		runlock(ifc);
 	}
-	return x;
+	if(x != nil && canrlock(x)){
+		if(x->ifcid == xifcid)
+			return x;
+		runlock(x);
+	}
+	return nil;
 }
 
 Ipifc*
@@ -1275,20 +1280,25 @@
 findipifcstr(Fs *f, char *s)
 {
 	uchar ip[IPaddrlen];
+	Ipifc *ifc;
 	Conv *c;
 	char *p;
 	long x;
 
+	ifc = nil;
 	x = strtol(s, &p, 10);
 	if(p > s && *p == '\0'){
 		if(x < 0)
 			return nil;
-		if(x < f->ipifc->nc && (c = f->ipifc->conv[x]) != nil && ipifcinuse(c))
-			return (Ipifc*)c->ptcl;
-	}
-	if(parseip(ip, s) != -1)
-		return findipifc(f, ip, ip, Runi);
-	return nil;
+		if(x < f->ipifc->nc && (c = f->ipifc->conv[x]) != nil){
+			if(ipifcinuse(c)){
+				ifc = (Ipifc*)c->ptcl;
+				rlock(ifc);
+			}
+		}
+	} else if(parseip(ip, s) != -1)
+		ifc = findipifc(f, ip, ip, Runi);
+	return ifc;
 }
 
 /*
@@ -1590,7 +1600,6 @@
 
 	f = c->p->f;
 	if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){
-		rlock(ifc);
 		if(waserror()){
 			runlock(ifc);
 			nexterror();
@@ -1618,7 +1627,7 @@
  *  remove a multicast address from an interface.
  */
 void
-ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
+ipifcdelmulti(Conv *c, uchar *ma, uchar *ia)
 {
 	Ipmulti *multi, **l;
 	Iplifc *lifc;
@@ -1638,15 +1647,14 @@
 
 	f = c->p->f;
 	if((ifc = findipifc(f, ia, ma, Rmulti)) != nil){
-		rlock(ifc);
 		if(!waserror()){
 			if((lifc = iplocalonifc(ifc, ia)) != nil)
-				remselfcache(f, ifc, lifc, ma);
+				delselfcache(f, ifc, lifc, ma);
 			poperror();
 		}
 		if(!isv4(ia) && !islinklocal(ia) && !waserror()){
 			if((lifc = iplinklocalifc(ifc)) != nil)
-				remselfcache(f, ifc, lifc, ma);
+				delselfcache(f, ifc, lifc, ma);
 			poperror();
 		}
 		runlock(ifc);
@@ -1694,7 +1702,7 @@
 			if(add)
 				addselfcache(f, nifc, lifc, a, Rmulti);
 			else
-				remselfcache(f, nifc, lifc, a);
+				delselfcache(f, nifc, lifc, a);
 		}
 		if(add)
 			ipifcregisteraddr(f, nifc, lifc, ip);
@@ -1773,7 +1781,7 @@
 }
 
 char*
-ipifcremove6(Ipifc *ifc, char**, int argc)
+ipifcdel6(Ipifc *ifc, char**, int argc)
 {
 	Iplifc *lifc, **l;
 	ulong now;
@@ -1786,7 +1794,7 @@
 	for(l = &ifc->lifc; (lifc = *l) != nil;) {
 		if((lifc->type & Rv4) == 0)
 		if(lifc->validlt != ~0UL && lifc->validlt < now-lifc->origint)
-			if(ipifcremlifc(ifc, l) == nil)
+			if(ipifcdellifc(ifc, l) == nil)
 				continue;
 		l = &lifc->next;
 	}
--- a/sys/src/9/ip/iproute.c
+++ b/sys/src/9/ip/iproute.c
@@ -425,7 +425,7 @@
 }
 
 static void
-routerem(Fs *f, Route *r)
+routedel(Fs *f, Route *r)
 {
 	Route **h, **e, **l, *p, *q;
 
@@ -464,7 +464,7 @@
 }
 
 static Route
-mkroute(uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag)
+mkroute(uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, uchar ifcid, char *tag)
 {
 	ulong x, y;
 	Route r;
@@ -508,7 +508,7 @@
 
 	if(ifc != nil){
 		r.ifc = ifc;
-		r.ifcid = ifc->ifcid;
+		r.ifcid = ifcid;
 	}
 
 	if(tag != nil)
@@ -520,7 +520,7 @@
 void
 addroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag)
 {
-	Route r = mkroute(a, mask, s, smask, gate, type, ifc, tag);
+	Route r = mkroute(a, mask, s, smask, gate, type, ifc, ifc->ifcid, tag);
 	wlock(&routelock);
 	routeadd(f, &r);
 	wunlock(&routelock);
@@ -527,15 +527,18 @@
 }
 
 void
-remroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag)
+delroute(Fs *f, uchar *a, uchar *mask, uchar *s, uchar *smask, uchar *gate, int type, Ipifc *ifc, char *tag)
 {
-	Route r = mkroute(a, mask, s, smask, gate, type, ifc, tag);
+	Route r = mkroute(a, mask, s, smask, gate, type, ifc, ifc->ifcid, tag);
 	wlock(&routelock);
-	routerem(f, &r);
+	routedel(f, &r);
 	wunlock(&routelock);
 }
 
-/* get the outgoing interface for route r */
+/*
+ * get the outgoing interface for route r,
+ * interface is returned rlocked.
+ */
 static Ipifc*
 routefindipifc(Route *r, Fs *f)
 {
@@ -544,8 +547,12 @@
 	int i;
 
 	ifc = r->ifc;
-	if(ifc != nil && ifc->ifcid == r->ifcid)
-		return ifc;
+	if(ifc != nil && canrlock(ifc)){
+		if(ifc->ifcid == r->ifcid)
+			return ifc;
+		runlock(ifc);
+		r->ifc = nil;
+	}
 
 	if(r->type & Rsrc) {
 		if(r->type & Rv4) {
@@ -574,11 +581,11 @@
 			ipmove(gate, r->v6.gate);
 	}
 
-	if((ifc = findipifc(f, local, gate, r->type)) == nil)
-		return nil;
-
-	r->ifc = ifc;
-	r->ifcid = ifc->ifcid;
+	ifc = findipifc(f, local, gate, r->type);
+	if(ifc != nil) {
+		r->ifc = ifc;
+		r->ifcid = ifc->ifcid;
+	}
 	return ifc;
 }
 
@@ -633,11 +640,15 @@
 		p = p->mid;
 	}
 	if(q != nil){
-		if(routefindipifc(q, f) == nil)
+		ifc = routefindipifc(q, f);
+		if(ifc == nil)
 			q = nil;
-		else if(rh != nil){
-			rh->r = q;
-			rh->rgen = v4routegeneration;
+		else {
+			if(rh != nil){
+				rh->r = q;
+				rh->rgen = v4routegeneration;
+			}
+			runlock(ifc);
 		}
 	}
 	runlock(&routelock);
@@ -726,11 +737,15 @@
 next:		;
 	}
 	if(q != nil){
-		if(routefindipifc(q, f) == nil)
+		ifc = routefindipifc(q, f);
+		if(ifc == nil)
 			q = nil;
-		else if(rh != nil){
-			rh->r = q;
-			rh->rgen = v6routegeneration;
+		else {
+			if(rh != nil){
+				rh->r = q;
+				rh->rgen = v6routegeneration;
+			}
+			runlock(ifc);
 		}
 	}
 	runlock(&routelock);
@@ -767,6 +782,12 @@
 			p = p->right;
 			continue;
 		}
+
+		ifc = routefindipifc(p, f);
+		if(ifc == nil){
+			p = p->mid;
+			continue;
+		}
 		splen = 0;
 		if(p->type & Rsrc){
 			/* calculate local prefix length for source specific routes */
@@ -774,12 +795,13 @@
 				splen++;
 			hnputl(src, p->v4.source);
 		}
-		if((ifc = routefindipifc(p, f)) == nil
-		|| !ipv4local(ifc, src, splen, (p->type & (Rifc|Rbcast|Rmulti|Rv4))==Rv4? p->v4.gate: a)){
+		if(!ipv4local(ifc, src, splen, (p->type & (Rifc|Rbcast|Rmulti|Rv4))==Rv4? p->v4.gate: a)){
+			runlock(ifc);
 			p = p->mid;
 			continue;
 		}
 		memmove(s, src, IPv4addrlen);
+		runlock(ifc);
 		q = p;
 		p = p->mid;
 	}
@@ -823,6 +845,12 @@
 			}
 			break;
 		}
+
+		ifc = routefindipifc(p, f);
+		if(ifc == nil){
+			p = p->mid;
+			continue;
+		}
 		splen = 0;
 		if(p->type & Rsrc){
 			/* calculate local prefix length for source specific routes */
@@ -836,12 +864,13 @@
 				splen += 32;
 			}
 		}
-		if((ifc = routefindipifc(p, f)) == nil
-		|| !ipv6local(ifc, src, splen, a)){
+		if(!ipv6local(ifc, src, splen, a)){
+			runlock(ifc);
 			p = p->mid;
 			continue;
 		}
 		ipmove(s, src);
+		runlock(ifc);
 		q = p;
 		p = p->mid;
 next:		;
@@ -1045,13 +1074,13 @@
  *	7	add	addr	mask	gate			ifc	src	smask
  *	8	add	addr	mask	gate	type		ifc	src	smask
  *	9	add	addr	mask	gate	type	tag	ifc	src	smask
- *	3	remove	addr	mask
- *	4	remove	addr	mask	gate
- *	5	remove	addr	mask					src	smask
- *	6	remove	addr	mask	gate				src	smask
- *	7	remove	addr	mask	gate			ifc	src	smask
- *	8	remove	addr	mask	gate	type		ifc	src	smask
- *	9	remove	addr	mask	gate	type	tag	ifc	src	smask
+ *	3	del	addr	mask
+ *	4	del	addr	mask	gate
+ *	5	del	addr	mask					src	smask
+ *	6	del	addr	mask	gate				src	smask
+ *	7	del	addr	mask	gate			ifc	src	smask
+ *	8	del	addr	mask	gate	type		ifc	src	smask
+ *	9	del	addr	mask	gate	type	tag	ifc	src	smask
  */
 static Route
 parseroute(Fs *f, char **argv, int argc)
@@ -1060,6 +1089,7 @@
 	uchar src[IPaddrlen], smask[IPaddrlen];
 	uchar gate[IPaddrlen];
 	Ipifc *ifc;
+	uchar ifcid;
 	char *tag;
 	int type;
 
@@ -1066,6 +1096,7 @@
 	type = 0;
 	tag = nil;
 	ifc = nil;
+	ifcid = 0;
 	ipmove(gate, IPnoaddr);
 	ipmove(src, IPnoaddr);
 	ipmove(smask, IPnoaddr);
@@ -1092,6 +1123,10 @@
 		ifc = findipifcstr(f, argv[4]);
 	if(argc > 6)
 		ifc = findipifcstr(f, argv[argc-3]);
+	if(ifc != nil){
+		ifcid = ifc->ifcid;
+		runlock(ifc);
+	}
 
 	if(argc > 7 && (type = parseroutetype(argv[4])) < 0)
 		error(Ebadctl);
@@ -1113,7 +1148,7 @@
 			error(Ebadip);
 	}
 
-	return mkroute(addr, mask, src, smask, gate, type, ifc, tag);	
+	return mkroute(addr, mask, src, smask, gate, type, ifc, ifcid, tag);	
 }
 
 long
@@ -1138,15 +1173,17 @@
 		for(h = 0; h < nelem(f->v4root); h++)
 			while((x = looknodetag(f->v4root[h], tag)) != nil){
 				memmove(&r, x, sizeof(RouteTree) + sizeof(V4route));
-				routerem(f, &r);
+				routedel(f, &r);
 			}
 		for(h = 0; h < nelem(f->v6root); h++)
 			while((x = looknodetag(f->v6root[h], tag)) != nil){
 				memmove(&r, x, sizeof(RouteTree) + sizeof(V6route));
-				routerem(f, &r);
+				routedel(f, &r);
 			}
 		wunlock(&routelock);
-	} else if(strcmp(cb->f[0], "add") == 0 || strcmp(cb->f[0], "remove") == 0){
+	} else if(strcmp(cb->f[0], "add") == 0
+		||strcmp(cb->f[0], "del") == 0
+		||strcmp(cb->f[0], "remove") == 0){
 		r = parseroute(f, cb->f, cb->nf);
 		if(*r.tag == 0){
 			a = c->aux;
@@ -1156,7 +1193,7 @@
 		if(strcmp(cb->f[0], "add") == 0)
 			routeadd(f, &r);
 		else
-			routerem(f, &r);
+			routedel(f, &r);
 		wunlock(&routelock);
 	} else if(strcmp(cb->f[0], "tag") == 0) {
 		if(cb->nf < 2)
--- a/sys/src/9/port/netif.c
+++ b/sys/src/9/port/netif.c
@@ -341,13 +341,14 @@
 		nif->bypass = f;
 	} else if(matchtoken(buf, "headersonly")){
 		f->headersonly = 1;
-	} else if((p = matchtoken(buf, "addmulti")) != 0){
+	} else if((p = matchtoken(buf, "addmulti")) != nil){
 		if(parseaddr(binaddr, p, nif->alen) < 0)
 			error("bad address");
 		p = netmulti(nif, f, binaddr, 1);
 		if(p)
 			error(p);
-	} else if((p = matchtoken(buf, "remmulti")) != 0){
+	} else if((p = matchtoken(buf, "delmulti")) != nil
+		||(p = matchtoken(buf, "remmulti")) != nil){
 		if(parseaddr(binaddr, p, nif->alen) < 0)
 			error("bad address");
 		p = netmulti(nif, f, binaddr, 0);
--- a/sys/src/cmd/ip/ipconfig/ipconfig.h
+++ b/sys/src/cmd/ip/ipconfig/ipconfig.h
@@ -3,7 +3,7 @@
 {
 	/* commands */
 	Vadd,
-	Vremove,
+	Vdel,
 	Vunbind,
 	Vaddpref6,
 	Vra6,
@@ -123,7 +123,7 @@
 void	ipunconfig(void);
 
 void	adddefroute(uchar*, uchar*, uchar*, uchar*);
-void	removedefroute(uchar*, uchar*, uchar*, uchar*);
+void	deldefroute(uchar*, uchar*, uchar*, uchar*);
 
 int	myip(Ipifc*, uchar*);
 int	isether(void);
--- a/sys/src/cmd/ip/ipconfig/ipv6.c
+++ b/sys/src/cmd/ip/ipconfig/ipv6.c
@@ -662,7 +662,7 @@
 			DEBUG("purging RA from %I on %s; pfx %I %M",
 				r->src, conf.dev, r->laddr, r->mask);
 			if(!noconfig && validip(r->gaddr))
-				removedefroute(r->gaddr, conf.lladdr, r->laddr, r->mask);
+				deldefroute(r->gaddr, conf.lladdr, r->laddr, r->mask);
 			*rr = r->next;
 			free(r);
 			continue;
--- a/sys/src/cmd/ip/ipconfig/main.c
+++ b/sys/src/cmd/ip/ipconfig/main.c
@@ -45,7 +45,7 @@
 extern void	pppbinddev(void);
 
 static void	doadd(void);
-static void	doremove(void);
+static void	dodel(void);
 static void	dounbind(void);
 static void	ndbconfig(void);
 
@@ -171,7 +171,7 @@
 {
 	static char *verbs[] = {
 		[Vadd]		"add",
-		[Vremove]	"remove",
+		[Vdel]		"del",
 		[Vunbind]	"unbind",
 		[Vether]	"ether",
 		[Vgbe]		"gbe",
@@ -188,6 +188,10 @@
 	for(i = 0; i < nelem(verbs); i++)
 		if(verbs[i] != nil && strcmp(name, verbs[i]) == 0)
 			return i;
+
+	if(strcmp(name, "remove")==0)
+		return Vdel;
+
 	return -1;
 }
 
@@ -248,7 +252,7 @@
 		case Vpkt:
 			sysfatal("medium %s already specified", conf.type);
 		case Vadd:
-		case Vremove:
+		case Vdel:
 		case Vunbind:
 		case Vaddpref6:
 		case Vra6:
@@ -262,7 +266,7 @@
 	/* get verb-dependent arguments */
 	switch (action) {
 	case Vadd:
-	case Vremove:
+	case Vdel:
 	case Vunbind:
 		parsenorm(argc, argv);
 		break;
@@ -462,12 +466,12 @@
 			findmyifc();
 		case Vunbind:
 			break;
-		case Vremove:
+		case Vdel:
 			/*
 			 * interface gone, just remove
 			 * default route and ndb entries.
 			 */
-			doremove();
+			dodel();
 			exits(nil);
 		}
 		if(myifc == nil)
@@ -493,8 +497,8 @@
 		mkclientid();
 		doipv6(action);
 		break;
-	case Vremove:
-		doremove();
+	case Vdel:
+		dodel();
 		break;
 	case Vunbind:
 		dounbind();
@@ -549,20 +553,21 @@
 }
 
 static void
-doremove(void)
+dodel(void)
 {
 	if(!validip(conf.laddr))
-		sysfatal("remove requires an address");
+		sysfatal("del requires an address");
 
-	DEBUG("removing address %I %M on %s", conf.laddr, conf.mask, conf.dev);
+	DEBUG("deleting address %I %M on %s", conf.laddr, conf.mask, conf.dev);
 	if(noconfig)
 		return;
 
 	if(validip(conf.gaddr))
-		removedefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask);
+		deldefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask);
 
+	/* use "remove" verb instead of "del" for older kernels */
 	if(conf.cfd >= 0 && fprint(conf.cfd, "remove %I %M", conf.laddr, conf.mask) < 0)
-		warning("can't remove %I %M: %r", conf.laddr, conf.mask);
+		warning("can't delete %I %M: %r", conf.laddr, conf.mask);
 
 	/* remove ndb entries matching our ip address */
 	putndb(0);
@@ -691,7 +696,7 @@
 	if(!validip(conf.mask))
 		ipmove(conf.mask, defmask(conf.laddr));
 
-	doremove();
+	dodel();
 
 	ipmove(conf.laddr, IPnoaddr);
 	ipmove(conf.raddr, IPnoaddr);
@@ -870,8 +875,9 @@
 }
 
 void
-removedefroute(uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
+deldefroute(uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
 {
+	/* use "remove" verb instead of "del" for older kernels */
 	defroutectl("remove", gaddr, ia, src, smask);
 }
 
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -421,7 +421,7 @@
 				if(nprom++ == 0 && eppromiscuous != nil)
 					(*eppromiscuous)(epctl, 1);
 			}
-		} else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){
+		} else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "delmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){
 			uchar ea[Eaddrlen];
 			int i;
 
@@ -431,7 +431,7 @@
 			}
 			i = activemulti(ea);
 			if(i >= 0){
-				if(*p == 'r'){
+				if(*p != 'a'){
 					memmove(multiaddr[i], multiaddr[--nmulti], Eaddrlen);
 					if(epmulticast != nil)
 						(*epmulticast)(epctl, ea, 0);