summaryrefslogtreecommitdiff
path: root/sys/src/9
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2023-04-15 18:00:34 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2023-04-15 18:00:34 +0000
commita4fa14a9d8f604d3e1eb409091b4f0d879f9cf97 (patch)
tree025f770c4e149e7aceb29218e0530f5906ef8678 /sys/src/9
parentb76d35401c0a056911aa192d4e4e6d86a15efa50 (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.c39
-rw-r--r--sys/src/9/ip/ethermedium.c10
-rw-r--r--sys/src/9/ip/icmp6.c30
-rw-r--r--sys/src/9/ip/ip.h2
-rw-r--r--sys/src/9/ip/ipifc.c29
-rw-r--r--sys/src/9/ip/ipv6.h4
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,