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 | |
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.
-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, |