ref: c8507f428fc7f99da40fc59024742291e42136a7
parent: 6e4a1fda8c6105bc18aa7c26ff1fd28e18fec986
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Mar 13 13:29:16 EDT 2022
ipconfig(8): add -t flag to enable source address translation
--- a/sys/man/8/ipconfig
+++ b/sys/man/8/ipconfig
@@ -5,7 +5,7 @@
.in +0.25i
.ti -0.25i
.B ip/ipconfig
-.RB [ -6DGNOPdnpruX ]
+.RB [ -6DGNOPdnprtuX ]
.RB [ -b
.IR baud ]
.RB [ -c
@@ -222,6 +222,10 @@
This option directs
.I ipconfig
instead to fork a background process that keeps trying forever.
+.TP
+.B t
+enable source address translation on the interface and default route.
+(only usefull for IPv4).
.TP
.B u
disable IPv6 duplicate discovery detection,
--- a/sys/src/cmd/ip/ipconfig/ipconfig.h
+++ b/sys/src/cmd/ip/ipconfig/ipconfig.h
@@ -116,6 +116,7 @@
int ip4cfg(void);
void ipunconfig(void);
+void setroutetag(char*);
void adddefroute(uchar*, uchar*, uchar*, uchar*);
void removedefroute(uchar*, uchar*, uchar*, uchar*);
--- a/sys/src/cmd/ip/ipconfig/ipv6.c
+++ b/sys/src/cmd/ip/ipconfig/ipv6.c
@@ -354,8 +354,8 @@
int
ip6cfg(void)
{
- int tentative, n;
char buf[256];
+ int tentative, n;
if(!validip(conf.laddr) || isv4(conf.laddr))
return -1;
@@ -372,12 +372,12 @@
if(!validip(conf.mask))
ipmove(conf.mask, defmask(conf.laddr));
n += snprint(buf+n, sizeof buf-n, " %M", conf.mask);
- if(validip(conf.raddr)){
- n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
- if(conf.mtu != 0)
- n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
- }
+ if(!validip(conf.raddr) || isv4(conf.raddr))
+ maskip(conf.laddr, conf.mask, conf.raddr);
+ n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
+ n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
+ DEBUG("ip6cfg: %.*s", n, buf);
if(write(conf.cfd, buf, n) < 0){
warning("write(%s): %r", buf);
return -1;
@@ -1134,8 +1134,7 @@
void
doipv6(int what)
{
- fprint(conf.rfd, "tag ra6");
-
+ setroutetag("ra6");
switch (what) {
default:
sysfatal("unknown IPv6 verb");
--- a/sys/src/cmd/ip/ipconfig/main.c
+++ b/sys/src/cmd/ip/ipconfig/main.c
@@ -24,6 +24,7 @@
int plan9 = 1;
int Oflag;
int rflag;
+int tflag;
int dodhcp;
int nodhcpwatch;
@@ -53,7 +54,7 @@
void
usage(void)
{
- fprint(2, "usage: %s [-6dDGnNOpPruX][-b baud][-c ctl]* [-g gw]"
+ fprint(2, "usage: %s [-6dDGnNOpPrtuX][-b baud][-c ctl]* [-g gw]"
"[-h host][-m mtu]\n"
"\t[-f dbfile][-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask "
"[raddr [fs [auth]]]]]\n", argv0);
@@ -383,6 +384,9 @@
case 'r':
rflag = 1;
break;
+ case 't':
+ tflag = 1;
+ break;
case 'u': /* IPv6: duplicate neighbour disc. off */
dupl_disc = 0;
break;
@@ -462,7 +466,7 @@
/* run dhcp if we need something */
if(dodhcp){
- fprint(conf.rfd, "tag dhcp");
+ setroutetag("dhcp");
dhcpquery(!noconfig, Sselecting);
}
@@ -587,12 +591,14 @@
ipmove(conf.mask, defmask(conf.laddr));
n += snprint(buf+n, sizeof buf-n, " %M", conf.mask);
- if(validip(conf.raddr)){
- n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
- if(conf.mtu != 0)
- n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
- }
+ if(!validip(conf.raddr) || !isv4(conf.raddr))
+ maskip(conf.laddr, conf.mask, conf.raddr);
+ n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
+ n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
+ if(tflag)
+ n += snprint(buf+n, sizeof buf-n, " trans");
+ DEBUG("ip4cfg: %.*s", n, buf);
if(write(conf.cfd, buf, n) < 0){
warning("write(%s): %r", buf);
return -1;
@@ -602,6 +608,9 @@
&& ipcmp(conf.gaddr, conf.laddr) != 0)
adddefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask);
+ if(tflag)
+ fprint(conf.cfd, "iprouting 1");
+
return 0;
}
@@ -726,6 +735,15 @@
close(fd);
}
+static char *routetag = "none";
+
+void
+setroutetag(char *tag)
+{
+ routetag = tag;
+ fprint(conf.rfd, "tag %s", routetag);
+}
+
static int
issrcspec(uchar *src, uchar *smask)
{
@@ -733,18 +751,22 @@
}
static void
-routectl(char *cmd, uchar *dst, uchar *mask, uchar *gate, uchar *ia, uchar *src, uchar *smask)
+routectl(char *cmd, uchar *dst, uchar *mask, uchar *gate, char *flags, uchar *ia, uchar *src, uchar *smask)
{
char *ctl;
- if(issrcspec(src, smask))
- ctl = "%s %I %M %I %I %I %M";
- else
- ctl = "%s %I %M %I %I";
- DEBUG(ctl, cmd, dst, mask, gate, ia, src, smask);
- if(conf.rfd < 0)
+ if(*flags == '\0'){
+ if(!issrcspec(src, smask))
+ ctl = "%s %I %M %I %I";
+ else
+ ctl = "%s %I %M %I %I %I %M";
+ DEBUG(ctl, cmd, dst, mask, gate, ia, src, smask);
+ fprint(conf.rfd, ctl, cmd, dst, mask, gate, ia, src, smask);
return;
- fprint(conf.rfd, ctl, cmd, dst, mask, gate, ia, src, smask);
+ }
+ ctl = "%s %I %M %I %s %s %I %I %M";
+ DEBUG(ctl, cmd, dst, mask, gate, flags, routetag, ia, src, smask);
+ fprint(conf.rfd, ctl, cmd, dst, mask, gate, flags, routetag, ia, src, smask);
}
static void
@@ -765,11 +787,18 @@
if(smask == nil)
smask = IPnoaddr;
}
- routectl(cmd, dst, mask, gaddr, ia, src, smask);
- /* also add a source specific route */
- if(ipcmp(src, IPnoaddr) != 0 && ipcmp(src, v4prefix) != 0)
- routectl(cmd, dst, mask, gaddr, ia, src, IPallbits);
+ if(tflag && isv4(gaddr)){
+ /* add route for everyone with source translation */
+ routectl(cmd, dst, mask, gaddr, "4t", ia, dst, mask);
+ } else {
+ /* add route for subnet */
+ routectl(cmd, dst, mask, gaddr, "", ia, src, smask);
+ }
+
+ /* add source specific route for us */
+ if(validip(src))
+ routectl(cmd, dst, mask, gaddr, "", ia, src, IPallbits);
}
void
@@ -1016,6 +1045,7 @@
ipmove(conf.mask, defmask(conf.laddr));
+ memset(conf.raddr, 0, sizeof(conf.raddr));
memset(conf.gaddr, 0, sizeof(conf.gaddr));
memset(conf.dns, 0, sizeof(conf.dns));
memset(conf.ntp, 0, sizeof(conf.ntp));