ref: 3e9ae26c2ea9c1b0c1bfcc0ad02c58bc65cb5294
parent: d5fc608059dee5f65ddfdf3e230bb8d458ccf43f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Apr 6 12:17:40 EDT 2024
devip: handle interface spec correctly for writes to /net/iproute When the interface is specified as "-", we should find the interface based on the gateway and source ip. As another improvement, also allow specifying the interface as the bound device name (for example "/net/ether0").
--- a/sys/man/3/ip
+++ b/sys/man/3/ip
@@ -456,14 +456,21 @@
.TP
.BI add\ "target mask nexthop flags interface source smask"
.TP
-.BI add\ "target mask nexthop flags tag interface source smask"
+.BI add\ "target mask nexthop flags tag interface source smask".
Add the route to the table. If one already exists with the
-same target and mask, replace it. The
+same target and mask, replace it. The destination
.I interface
-can be given as either the interface number or a local
-IP address on the desired interface or as a
+can be specified as either
+the interface's /net/ipifc/n directory number,
+a local IP address on the desired interface,
+its bound device name or as
.B "-"
-when unspecified.
+when unspecified,
+in which case the interface will be choosen
+based on the
+.I source
+and
+.IR nexthop .
.TP
.BI del\ "target mask"
.TP
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -728,6 +728,7 @@
extern void ipifcoput(Ipifc *ifc, Block *bp, int version, uchar *ip, Routehint *rh);
extern int ipforme(Fs*, uchar *addr);
extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type);
+extern Ipifc* findipifcdev(Fs *f, char *dev);
extern Ipifc* findipifcstr(Fs *f, char *s);
extern void findlocalip(Fs*, uchar *local, uchar *remote);
extern int ipv4local(Ipifc *ifc, uchar *local, int prefixlen, uchar *remote);
--- a/sys/src/9/ip/ipifc.c
+++ b/sys/src/9/ip/ipifc.c
@@ -1279,7 +1279,36 @@
return nil;
}
+/*
+ * find the ifc bound to device name dev.
+ * returns the rlock'd ifc, otherwise nil.
+ */
Ipifc*
+findipifcdev(Fs *f, char *dev)
+{
+ Ipifc *ifc;
+ Conv **cp;
+
+ for(cp = f->ipifc->conv; *cp != nil; cp++){
+ ifc = (Ipifc*)(*cp)->ptcl;
+ rlock(ifc);
+ if(ifc->m != nil
+ && ifc->m != &unboundmedium
+ && strcmp(ifc->dev, dev) == 0)
+ return ifc;
+ runlock(ifc);
+ }
+ return nil;
+}
+
+/*
+ * find a ifc based on:
+ * - its /net/ipifc/X directory number
+ * - a local ip address on that interface
+ * - bound device name
+ * returns the rlock'd ifc, otherwise nil.
+ */
+Ipifc*
findipifcstr(Fs *f, char *s)
{
uchar ip[IPaddrlen];
@@ -1294,13 +1323,17 @@
if(x < 0)
return nil;
if(x < f->ipifc->nc && (c = f->ipifc->conv[x]) != nil){
- if(ipifcinuse(c)){
- ifc = (Ipifc*)c->ptcl;
- rlock(ifc);
+ ifc = (Ipifc*)c->ptcl;
+ rlock(ifc);
+ if(ifc->m == nil || ifc->m == &unboundmedium){
+ runlock(ifc);
+ ifc = nil;
}
}
} else if(parseip(ip, s) != -1)
ifc = findipifc(f, ip, ip, Runi);
+ else
+ ifc = findipifcdev(f, s);
return ifc;
}
--- a/sys/src/9/ip/iproute.c
+++ b/sys/src/9/ip/iproute.c
@@ -1129,7 +1129,7 @@
error(Ebadip);
}
- if(ifcstr != nil)
+ if(ifcstr != nil && strcmp(ifcstr, "-") != 0)
ifc = findipifcstr(f, ifcstr);
else
ifc = findipifc(f, src, gate, type);