diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-04-15 18:00:34 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-04-15 18:00:34 +0000 |
commit | a4fa14a9d8f604d3e1eb409091b4f0d879f9cf97 (patch) | |
tree | 025f770c4e149e7aceb29218e0530f5906ef8678 /sys/src/9 | |
parent | b76d35401c0a056911aa192d4e4e6d86a15efa50 (diff) |
ip: generalize Rproxy route handling, allowing non point-to-point arp proxy
Generalize the arp proxy code, so one can create
specific routes for ip ranges that we want to arp
proxy for, not just for point-to-point interface
routes.
as we have source specific routes, this also
gives some control over which requester we will
reply to.
one example for this is a vps where we booked
another ip address on the ethernet, that we want
to route into a vpn tunnel. the new ip is in
subnet of the public ethernet interface, so all
we now need todo is add a route for that ip into
the vpn tunnel and set the proxy flag "y", and
we will respond to arp for that ip on the public
ethernet interface.
Diffstat (limited to 'sys/src/9')
-rw-r--r-- | sys/src/9/ip/arp.c | 39 | ||||
-rw-r--r-- | sys/src/9/ip/ethermedium.c | 10 | ||||
-rw-r--r-- | sys/src/9/ip/icmp6.c | 30 | ||||
-rw-r--r-- | sys/src/9/ip/ip.h | 2 | ||||
-rw-r--r-- | sys/src/9/ip/ipifc.c | 29 | ||||
-rw-r--r-- | sys/src/9/ip/ipv6.h | 4 |
6 files changed, 56 insertions, 58 deletions
diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index 74d36b1ee..1efb5093d 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -383,6 +383,42 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *ia, Ipifc *if return 1; } +/* + * arpforme() checks if we should respond to arp/ndp on a specific interface. + * + * returns Runi if targ is a non-tentative local address on ifc. + * returns Rproxy if we have a proxy route for targ to another interface. + */ +int +arpforme(Fs *fs, int version, uchar *targ, uchar *src, Ipifc *ifc) +{ + uchar ipv6[IPaddrlen]; + Iplifc *lifc; + Route *r; + + if(version == V4) { + v4tov6(ipv6, targ); + targ = ipv6; + } + lifc = iplocalonifc(ifc, targ); + if(lifc != nil){ + if(lifc->tentative) + return 0; + return Runi; + } + if(ipremoteonifc(ifc, targ) == nil) + return 0; + if(version == V4){ + targ += IPv4off; + r = v4lookup(fs, targ, src, nil); + } else { + r = v6lookup(fs, targ, src, nil); + } + if(r == nil || r->ifc == ifc && r->ifcid == ifc->ifcid) + return 0; + return r->type & Rproxy; +} + int arpwrite(Fs *fs, char *s, int len) { @@ -552,8 +588,7 @@ ndpsendsol(Fs *f, Arpent *a) if(a->last != nil){ ipmove(src, ((Ip6hdr*)a->last->rp)->src); arpcontinue(f->arp, a); - - if(iplocalonifc(ifc, src) != nil || ipproxyifc(f, ifc, src)) + if(arpforme(f, V6, src, targ, ifc)) goto send; } else { arpcontinue(f->arp, a); diff --git a/sys/src/9/ip/ethermedium.c b/sys/src/9/ip/ethermedium.c index 999a65b5f..b2e04947a 100644 --- a/sys/src/9/ip/ethermedium.c +++ b/sys/src/9/ip/ethermedium.c @@ -508,7 +508,6 @@ recvarp(Ipifc *ifc) int forme; Block *ebp, *rbp; Etherarp *e, *r; - uchar ip[IPaddrlen]; static uchar eprinted[4]; Etherrock *er = ifc->arg; @@ -529,8 +528,7 @@ recvarp(Ipifc *ifc) break; /* check for machine using my ip address */ - v4tov6(ip, e->spa); - if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){ + if(arpforme(er->f, V4, e->spa, e->tpa, ifc)){ 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); @@ -552,8 +550,7 @@ recvarp(Ipifc *ifc) break; /* check for machine using my ip or ether address */ - v4tov6(ip, e->spa); - if(iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip)){ + if(arpforme(er->f, V4, e->spa, e->tpa, ifc)){ if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){ if(memcmp(eprinted, e->spa, sizeof(e->spa)) != 0){ /* print only once */ @@ -576,8 +573,7 @@ recvarp(Ipifc *ifc) * enter senders address into arp table and reply, otherwise just * refresh the senders address. */ - v4tov6(ip, e->tpa); - forme = iplocalonifc(ifc, ip) != nil || ipproxyifc(er->f, ifc, ip); + forme = arpforme(er->f, V4, e->tpa, e->spa, ifc); if(arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), e->tpa, ifc, !forme) < 0 || !forme) break; diff --git a/sys/src/9/ip/icmp6.c b/sys/src/9/ip/icmp6.c index 99c44134d..62f4bda90 100644 --- a/sys/src/9/ip/icmp6.c +++ b/sys/src/9/ip/icmp6.c @@ -636,21 +636,6 @@ err: return 0; } -static int -targettype(Fs *f, Ipifc *ifc, uchar *target) -{ - Iplifc *lifc; - int t; - - if((lifc = iplocalonifc(ifc, target)) != nil) - t = lifc->tentative? Tunitent: Tunirany; - else if(ipproxyifc(f, ifc, target)) - t = Tuniproxy; - else - t = 0; - return t; -} - static void icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) { @@ -745,12 +730,11 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) pktflags = 0; if(ifc->sendra6) pktflags |= Rflag; - switch (targettype(icmp->f, ifc, np->target)) { - case Tunirany: + switch(arpforme(icmp->f, V6, np->target, np->src, ifc)){ + case Runi: pktflags |= Oflag; - /* fall through */ - - case Tuniproxy: + /* wet floor */ + case Rproxy: if(ipv6local(ifc, ia, 0, np->src)) { if(arpenter(icmp->f, V6, np->src, np->lnaddr, 8*np->olen-2, ia, ifc, 0) < 0) break; @@ -760,12 +744,6 @@ icmpiput6(Proto *icmp, Ipifc *ifc, Block *bp) icmpna6(icmp->f, ia, (pktflags & Sflag)? np->src: v6allnodesL, np->target, ifc->mac, pktflags); break; - case Tunitent: - /* - * not clear what needs to be done. send up - * an icmp mesg saying don't use this address? - */ - break; } freeblist(bp); break; diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 8742b6309..e547b685f 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -668,6 +668,7 @@ extern void arprelease(Arp*, Arpent *a); extern void arpcontinue(Arp*, Arpent *a); extern Block* arpresolve(Arp*, Arpent *a, uchar *mac, Routehint *rh); extern int arpenter(Fs*, int version, uchar *ip, uchar *mac, int n, uchar *ia, Ipifc *ifc, int refresh); +extern int arpforme(Fs*, int version, uchar *targ, uchar *src, Ipifc *ifc); extern void ndpsendsol(Fs*, Arpent*); /* @@ -725,7 +726,6 @@ extern int ipv4local(Ipifc *ifc, uchar *local, int prefixlen, uchar *remote); extern int ipv6local(Ipifc *ifc, uchar *local, int prefixlen, uchar *remote); extern Iplifc* iplocalonifc(Ipifc *ifc, uchar *ip); extern Iplifc* ipremoteonifc(Ipifc *ifc, uchar *ip); -extern int ipproxyifc(Fs *f, 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); diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index 6256514f6..f1fa6486c 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -569,13 +569,17 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) addselfcache(f, ifc, lifc, ip, Runi); - /* register proxy */ + /* register point-to-point proxy */ if(type & Rptpt){ if(type & Rproxy) ipifcregisterproxy(f, ifc, rem, 1); goto done; } + /* register local ip if proxy */ + if(type & Rproxy) + ipifcregisterproxy(f, ifc, ip, 1); + if(type & Rv4) { /* add subnet directed broadcast address to the self cache */ for(i = 0; i < IPaddrlen; i++) @@ -667,13 +671,17 @@ ipifcremlifc(Ipifc *ifc, Iplifc **l) lifc->remote, lifc->type, ifc, tifc); } - /* unregister proxy */ + /* unregister point-to-point proxy */ if(lifc->type & Rptpt){ if(lifc->type & Rproxy) ipifcregisterproxy(f, ifc, lifc->remote, 0); goto done; } + /* unregister local ip if proxy */ + if(lifc->type & Rproxy) + ipifcregisterproxy(f, ifc, lifc->local, 0); + /* remove route for all nodes multicast */ if((lifc->type & Rv4) == 0){ if(ipcmp(lifc->local, v6loopback) == 0){ @@ -902,6 +910,7 @@ addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type) Ipself *p; int h; + if(type == Runi) type |= (lifc->type & Rproxy); type |= (lifc->type & Rv4); qlock(f->self); @@ -1451,22 +1460,6 @@ iplinklocalifc(Ipifc *ifc) } /* - * See if we're proxying for this address on this interface - */ -int -ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip) -{ - Route *r; - - /* see if this is a direct connected pt to pt address */ - r = v6lookup(f, ip, ip, nil); - if(r == nil || (r->type & (Rifc|Rproxy)) != (Rifc|Rproxy)) - return 0; - - return ipremoteonifc(ifc, ip) != nil; -} - -/* * Return a copy of the multicast addresses on the * specified interface and multicast address. */ diff --git a/sys/src/9/ip/ipv6.h b/sys/src/9/ip/ipv6.h index 578fefb1a..8f7a599a2 100644 --- a/sys/src/9/ip/ipv6.h +++ b/sys/src/9/ip/ipv6.h @@ -94,10 +94,6 @@ enum { TARG_UNI = 2, TARG_MULTI = 3, - Tunitent = 1, - Tuniproxy = 2, - Tunirany = 3, - /* Node constants */ MAX_MULTICAST_SOLICIT = 3, RETRANS_TIMER = 1000, |