summaryrefslogtreecommitdiff
path: root/sys/src/9/ip/ethermedium.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-04-08 21:15:00 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-04-08 21:15:00 +0200
commitc2dd9b1da7659c9ac42e7612e5621e9426956c73 (patch)
tree8c191ea02792997669a87965419aac936243104f /sys/src/9/ip/ethermedium.c
parentdc8432d4593c7a4b0a187d0174d4e4e603e456f6 (diff)
devip: implement source specific routing
Diffstat (limited to 'sys/src/9/ip/ethermedium.c')
-rw-r--r--sys/src/9/ip/ethermedium.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c
index 9b1962450..0532457de 100644
--- a/sys/src/9/ip/ethermedium.c
+++ b/sys/src/9/ip/ethermedium.c
@@ -33,9 +33,9 @@ static void etherunbind(Ipifc *ifc);
static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
+static void etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy);
static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
static void sendarp(Ipifc *ifc, Arpent *a);
-static void sendgarp(Ipifc *ifc, uchar*);
static int multicastea(uchar *ea, uchar *ip);
static void recvarpproc(void*);
static void resolveaddr6(Ipifc *ifc, Arpent *a);
@@ -53,8 +53,7 @@ Medium ethermedium =
.bwrite= etherbwrite,
.addmulti= etheraddmulti,
.remmulti= etherremmulti,
-.ares= arpenter,
-.areg= sendgarp,
+.areg= etherareg,
.pref2addr= etherpref2addr,
};
@@ -70,8 +69,7 @@ Medium gbemedium =
.bwrite= etherbwrite,
.addmulti= etheraddmulti,
.remmulti= etherremmulti,
-.ares= arpenter,
-.areg= sendgarp,
+.areg= etherareg,
.pref2addr= etherpref2addr,
};
@@ -271,7 +269,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
/* get mac address of destination */
a = arpget(er->f->arp, bp, version, ifc, ip, mac);
- if(a){
+ if(a != nil){
/* check for broadcast or multicast */
bp = multicastarp(er->f, a, ifc->m, mac);
if(bp==nil){
@@ -471,8 +469,8 @@ sendarp(Ipifc *ifc, Arpent *a)
arprelease(er->f->arp, a);
n = sizeof(Etherarp);
- if(n < a->type->mintu)
- n = a->type->mintu;
+ if(n < ifc->m->mintu)
+ n = ifc->m->mintu;
bp = allocb(n);
memset(bp->rp, 0, n);
e = (Etherarp*)bp->rp;
@@ -536,10 +534,6 @@ sendgarp(Ipifc *ifc, uchar *ip)
Etherarp *e;
Etherrock *er = ifc->arg;
- /* don't arp for our initial non address */
- if(ipcmp(ip, IPnoaddr) == 0)
- return;
-
n = sizeof(Etherarp);
if(n < ifc->m->mintu)
n = ifc->m->mintu;
@@ -585,7 +579,7 @@ recvarp(Ipifc *ifc)
case ARPREPLY:
/* check for machine using my ip address */
v4tov6(ip, e->spa);
- if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
+ if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){
if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
print("arprep: 0x%E/0x%E also has ip addr %V\n",
e->s, e->sha, e->spa);
@@ -594,14 +588,13 @@ recvarp(Ipifc *ifc)
}
/* make sure we're not entering broadcast addresses */
- if(ipcmp(ip, ipbroadcast) == 0 ||
- !memcmp(e->sha, etherbroadcast, sizeof(e->sha))){
+ if(ipcmp(ip, ipbroadcast) == 0 || memcmp(e->sha, etherbroadcast, sizeof(e->sha)) == 0){
print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",
e->s, e->sha, e->spa);
break;
}
- arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);
+ arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), e->tpa, 0);
break;
case ARPREQUEST:
@@ -611,9 +604,9 @@ recvarp(Ipifc *ifc)
/* check for machine using my ip or ether address */
v4tov6(ip, e->spa);
- if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
+ if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){
if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
- if (memcmp(eprinted, e->spa, sizeof(e->spa))){
+ if(memcmp(eprinted, e->spa, sizeof(e->spa)) != 0){
/* print only once */
print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);
memmove(eprinted, e->spa, sizeof(e->spa));
@@ -627,12 +620,11 @@ recvarp(Ipifc *ifc)
}
/* refresh what we know about sender */
- arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);
+ arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), e->tpa, 1);
/* answer only requests for our address or systems we're proxying for */
v4tov6(ip, e->tpa);
- if(!iplocalonifc(ifc, ip))
- if(!ipproxyifc(er->f, ifc, ip))
+ if(iplocalonifc(ifc, ip) == nil && !ipproxyifc(er->f, ifc, ip))
break;
n = sizeof(Etherarp);
@@ -742,7 +734,7 @@ ethermediumlink(void)
static void
etherpref2addr(uchar *pref, uchar *ea)
{
- pref[8] = ea[0] | 0x2;
+ pref[8] = ea[0] ^ 0x2;
pref[9] = ea[1];
pref[10] = ea[2];
pref[11] = 0xFF;
@@ -751,3 +743,31 @@ etherpref2addr(uchar *pref, uchar *ea)
pref[14] = ea[4];
pref[15] = ea[5];
}
+
+static void
+etherareg(Fs *f, Ipifc *ifc, uchar *ip, uchar *proxy)
+{
+ static char tdad[] = "dad6";
+ uchar mcast[IPaddrlen];
+
+ if(ipcmp(ip, IPnoaddr) == 0)
+ return;
+
+ if(isv4(ip)){
+ sendgarp(ifc, ip);
+ return;
+ }
+
+ if(!iptentative(f, ip)){
+ icmpna(f, proxy, v6allnodesL, ip, ifc->mac, 1<<5);
+ return;
+ }
+
+ /* temporarily add route for duplicate address detection */
+ ipv62smcast(mcast, ip);
+ addroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
+
+ icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
+
+ remroute(f, mcast, IPallbits, v6Unspecified, IPallbits, ip, Rmulti, ifc, tdad);
+}