shithub: riscv

Download patch

ref: 547f60b4c507778099635f5d2ec4919e1beb6a57
parent: 20cbb88e32ece30dd984ab658c365f574790d6ba
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 18 21:11:08 EDT 2018

devip: pick source address for neighbor solicitations as of rfc4861 7.2.2, cleanup

rfc4861 7.2.2:

If the source address of the packet prompting the solicitation is the
same as one of the addresses assigned to the outgoing interface, that
address SHOULD be placed in the IP Source Address of the outgoing
solicitation.

this change adds ndbsendsol() which handles the source address selection
and also handles the arp table locking; avoiding access to the arp entry
after the arp table is unlocked.

cleanups:

- use ipmove() instead of memmove().
- useless extern qualifiers

--- a/sys/src/9/ip/arp.c
+++ b/sys/src/9/ip/arp.c
@@ -47,7 +47,7 @@
 
 #define haship(s) ((s)[IPaddrlen-1]%NHASH)
 
-extern int 	ReTransTimer = RETRANS_TIMER;
+int 	ReTransTimer = RETRANS_TIMER;
 
 static void 	rxmitproc(void *v);
 
@@ -223,7 +223,7 @@
 	qlock(arp);
 	hash = haship(ip);
 	for(a = arp->hash[hash]; a != nil; a = a->hash){
-		if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
+		if(ipcmp(ip, a->ip) == 0)
 		if(type == a->type)
 			break;
 	}
@@ -536,13 +536,35 @@
 	return n;
 }
 
-extern int
+void
+ndpsendsol(Fs *f, Ipifc *ifc, Arpent *a)
+{
+	uchar targ[IPaddrlen], src[IPaddrlen];
+
+	ipmove(targ, a->ip);
+
+	if(a->last != nil){
+		ipmove(src, ((Ip6hdr*)a->last->rp)->src);
+		arprelease(f->arp, a);
+
+		if(iplocalonifc(ifc, src) || ipproxyifc(f, ifc, src))
+			goto send;
+	} else {
+		arprelease(f->arp, a);
+	}
+
+	if(!ipv6local(ifc, src, targ))
+		return;
+send:
+	icmpns(f, src, SRC_UNI, targ, TARG_MULTI, ifc->mac);
+}
+
+int
 rxmitsols(Arp *arp)
 {
 	Block *next, *xp;
 	Arpent *a, *b, **l;
 	Fs *f;
-	uchar ipsrc[IPaddrlen];
 	Ipifc *ifc = nil;
 	long nrxt;
 
@@ -579,10 +601,7 @@
 	if(a == nil)
 		goto dodrops;
 
-
-	qunlock(arp);	/* for icmpns */
-	if(ipv6local(ifc, ipsrc, a->ip)) 
-		icmpns(f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac); 
+	ndpsendsol(f, ifc, a);	/* unlocks arp */
 
 	runlock(ifc);
 	qlock(arp);	
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -498,7 +498,6 @@
 {
 	Block *bp;
 	Etherrock *er = ifc->arg;
-	uchar ipsrc[IPaddrlen];
 
 	/* don't do anything if it's been less than a second since the last */
 	if(NOW - a->ctime < ReTransTimer){
@@ -523,10 +522,7 @@
 	}
 
 	a->rxtsrem--;
-	arprelease(er->f->arp, a);
-
-	if(ipv6local(ifc, ipsrc, a->ip))
-		icmpns(er->f, ipsrc, SRC_UNI, a->ip, TARG_MULTI, ifc->mac);
+	ndpsendsol(er->f, ifc, a);	/* unlocks arp */
 }
 
 /*
@@ -610,7 +606,7 @@
 
 	case ARPREQUEST:
 		/* don't answer arps till we know who we are */
-		if(ifc->lifc == 0)
+		if(ifc->lifc == nil)
 			break;
 
 		/* check for machine using my ip or ether address */
--- a/sys/src/9/ip/icmp.c
+++ b/sys/src/9/ip/icmp.c
@@ -113,7 +113,7 @@
 	c->wq = qbypass(icmpkick, c);
 }
 
-extern char*
+char*
 icmpconnect(Conv *c, char **argv, int argc)
 {
 	char *e;
@@ -126,7 +126,7 @@
 	return nil;
 }
 
-extern int
+int
 icmpstate(Conv *c, char *state, int n)
 {
 	USED(c);
@@ -137,7 +137,7 @@
 	);
 }
 
-extern char*
+char*
 icmpannounce(Conv *c, char **argv, int argc)
 {
 	char *e;
@@ -150,7 +150,7 @@
 	return nil;
 }
 
-extern void
+void
 icmpclose(Conv *c)
 {
 	qclose(c->rq);
@@ -214,7 +214,7 @@
 	return (ipforme(f, addr) & Runi) != 0;
 }
 
-extern void
+void
 icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
 {
 	Block	*nbp;
@@ -270,13 +270,13 @@
 	ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
 }
 
-extern void
+void
 icmpnoconv(Fs *f, Block *bp)
 {
 	icmpunreachable(f, bp, 3, 0);
 }
 
-extern void
+void
 icmpcantfrag(Fs *f, Block *bp, int mtu)
 {
 	icmpunreachable(f, bp, 4, mtu);
--- a/sys/src/9/ip/icmp6.c
+++ b/sys/src/9/ip/icmp6.c
@@ -345,7 +345,7 @@
  *	tuni == TARG_MULTI => multicast for address resolution,
  * 	and tuni == TARG_UNI => neighbor reachability.
  */
-extern void
+void
 icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
 {
 	Block *nbp;
@@ -357,18 +357,18 @@
 	np = (Ndpkt*) nbp->rp;
 
 	if(suni == SRC_UNSPEC)
-		memmove(np->src, v6Unspecified, IPaddrlen);
+		ipmove(np->src, v6Unspecified);
 	else
-		memmove(np->src, src, IPaddrlen);
+		ipmove(np->src, src);
 
 	if(tuni == TARG_UNI)
-		memmove(np->dst, targ, IPaddrlen);
+		ipmove(np->dst, targ);
 	else
 		ipv62smcast(np->dst, targ);
 
 	np->type = NbrSolicit;
 	np->code = 0;
-	memmove(np->target, targ, IPaddrlen);
+	ipmove(np->target, targ);
 	if(suni != SRC_UNSPEC) {
 		np->otype = SRC_LLADDR;
 		np->olen = 1;		/* 1+1+6 = 8 = 1 8-octet */
@@ -388,7 +388,7 @@
 /*
  * sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
  */
-extern void
+void
 icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
 {
 	Block *nbp;
@@ -399,13 +399,13 @@
 	nbp = newIPICMP(NDPKTSZ);
 	np = (Ndpkt*)nbp->rp;
 
-	memmove(np->src, src, IPaddrlen);
-	memmove(np->dst, dst, IPaddrlen);
+	ipmove(np->src, src);
+	ipmove(np->dst, dst);
 
 	np->type = NbrAdvert;
 	np->code = 0;
 	np->icmpid[0] = flags;
-	memmove(np->target, targ, IPaddrlen);
+	ipmove(np->target, targ);
 
 	np->otype = TARGET_LLADDR;
 	np->olen = 1;
@@ -420,7 +420,7 @@
 	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
 }
 
-extern void
+void
 icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
 {
 	int osz = BLEN(bp);
@@ -449,7 +449,7 @@
 		goto freebl;
 	}
 
-	memmove(np->dst, p->src, IPaddrlen);
+	ipmove(np->dst, p->src);
 	np->type = UnreachableV6;
 	np->code = code;
 	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
@@ -468,7 +468,7 @@
 		freeblist(bp);
 }
 
-extern void
+void
 icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
 {
 	int osz = BLEN(bp);
@@ -496,7 +496,7 @@
 		return;
 	}
 
-	memmove(np->dst, p->src, IPaddrlen);
+	ipmove(np->dst, p->src);
 	np->type = TimeExceedV6;
 	np->code = 0;
 	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
@@ -507,7 +507,7 @@
 	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
 }
 
-extern void
+void
 icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
 {
 	int osz = BLEN(bp);
@@ -535,7 +535,7 @@
 		return;
 	}
 
-	memmove(np->dst, p->src, IPaddrlen);
+	ipmove(np->dst, p->src);
 	np->type = PacketTooBigV6;
 	np->code = 0;
 	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -628,6 +628,7 @@
 extern void	arprelease(Arp*, Arpent *a);
 extern Block*	arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
 extern void	arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
+extern void	ndpsendsol(Fs*, Ipifc*, Arpent*);
 
 /*
  * ipaux.c