ipconfig(8): add -t flag to enable source address translation

This commit is contained in:
cinap_lenrek 2022-03-13 17:29:16 +00:00
parent 6e4a1fda8c
commit c8507f428f
4 changed files with 62 additions and 28 deletions

View file

@ -5,7 +5,7 @@ ipconfig, rip, linklocal \- Internet configuration and routing
.in +0.25i .in +0.25i
.ti -0.25i .ti -0.25i
.B ip/ipconfig .B ip/ipconfig
.RB [ -6DGNOPdnpruX ] .RB [ -6DGNOPdnprtuX ]
.RB [ -b .RB [ -b
.IR baud ] .IR baud ]
.RB [ -c .RB [ -c
@ -223,6 +223,10 @@ This option directs
.I ipconfig .I ipconfig
instead to fork a background process that keeps trying forever. instead to fork a background process that keeps trying forever.
.TP .TP
.B t
enable source address translation on the interface and default route.
(only usefull for IPv4).
.TP
.B u .B u
disable IPv6 duplicate discovery detection, disable IPv6 duplicate discovery detection,
which removes any existing ARP table entry for one of our IPv6 addresses which removes any existing ARP table entry for one of our IPv6 addresses

View file

@ -116,6 +116,7 @@ void usage(void);
int ip4cfg(void); int ip4cfg(void);
void ipunconfig(void); void ipunconfig(void);
void setroutetag(char*);
void adddefroute(uchar*, uchar*, uchar*, uchar*); void adddefroute(uchar*, uchar*, uchar*, uchar*);
void removedefroute(uchar*, uchar*, uchar*, uchar*); void removedefroute(uchar*, uchar*, uchar*, uchar*);

View file

@ -354,8 +354,8 @@ arpcheck(uchar *ip)
int int
ip6cfg(void) ip6cfg(void)
{ {
int tentative, n;
char buf[256]; char buf[256];
int tentative, n;
if(!validip(conf.laddr) || isv4(conf.laddr)) if(!validip(conf.laddr) || isv4(conf.laddr))
return -1; return -1;
@ -372,12 +372,12 @@ Again:
if(!validip(conf.mask)) if(!validip(conf.mask))
ipmove(conf.mask, defmask(conf.laddr)); ipmove(conf.mask, defmask(conf.laddr));
n += snprint(buf+n, sizeof buf-n, " %M", conf.mask); n += snprint(buf+n, sizeof buf-n, " %M", conf.mask);
if(validip(conf.raddr)){ if(!validip(conf.raddr) || isv4(conf.raddr))
n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr); maskip(conf.laddr, conf.mask, conf.raddr);
if(conf.mtu != 0) n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu); n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
}
DEBUG("ip6cfg: %.*s", n, buf);
if(write(conf.cfd, buf, n) < 0){ if(write(conf.cfd, buf, n) < 0){
warning("write(%s): %r", buf); warning("write(%s): %r", buf);
return -1; return -1;
@ -1134,8 +1134,7 @@ startra6(void)
void void
doipv6(int what) doipv6(int what)
{ {
fprint(conf.rfd, "tag ra6"); setroutetag("ra6");
switch (what) { switch (what) {
default: default:
sysfatal("unknown IPv6 verb"); sysfatal("unknown IPv6 verb");

View file

@ -24,6 +24,7 @@ int dolog;
int plan9 = 1; int plan9 = 1;
int Oflag; int Oflag;
int rflag; int rflag;
int tflag;
int dodhcp; int dodhcp;
int nodhcpwatch; int nodhcpwatch;
@ -53,7 +54,7 @@ static int Ufmt(Fmt*);
void void
usage(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" "[-h host][-m mtu]\n"
"\t[-f dbfile][-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask " "\t[-f dbfile][-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask "
"[raddr [fs [auth]]]]]\n", argv0); "[raddr [fs [auth]]]]]\n", argv0);
@ -383,6 +384,9 @@ main(int argc, char **argv)
case 'r': case 'r':
rflag = 1; rflag = 1;
break; break;
case 't':
tflag = 1;
break;
case 'u': /* IPv6: duplicate neighbour disc. off */ case 'u': /* IPv6: duplicate neighbour disc. off */
dupl_disc = 0; dupl_disc = 0;
break; break;
@ -462,7 +466,7 @@ doadd(void)
/* run dhcp if we need something */ /* run dhcp if we need something */
if(dodhcp){ if(dodhcp){
fprint(conf.rfd, "tag dhcp"); setroutetag("dhcp");
dhcpquery(!noconfig, Sselecting); dhcpquery(!noconfig, Sselecting);
} }
@ -587,12 +591,14 @@ ip4cfg(void)
ipmove(conf.mask, defmask(conf.laddr)); ipmove(conf.mask, defmask(conf.laddr));
n += snprint(buf+n, sizeof buf-n, " %M", conf.mask); n += snprint(buf+n, sizeof buf-n, " %M", conf.mask);
if(validip(conf.raddr)){ if(!validip(conf.raddr) || !isv4(conf.raddr))
n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr); maskip(conf.laddr, conf.mask, conf.raddr);
if(conf.mtu != 0) n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu); 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){ if(write(conf.cfd, buf, n) < 0){
warning("write(%s): %r", buf); warning("write(%s): %r", buf);
return -1; return -1;
@ -602,6 +608,9 @@ ip4cfg(void)
&& ipcmp(conf.gaddr, conf.laddr) != 0) && ipcmp(conf.gaddr, conf.laddr) != 0)
adddefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask); adddefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask);
if(tflag)
fprint(conf.cfd, "iprouting 1");
return 0; return 0;
} }
@ -726,6 +735,15 @@ putndb(void)
close(fd); close(fd);
} }
static char *routetag = "none";
void
setroutetag(char *tag)
{
routetag = tag;
fprint(conf.rfd, "tag %s", routetag);
}
static int static int
issrcspec(uchar *src, uchar *smask) issrcspec(uchar *src, uchar *smask)
{ {
@ -733,18 +751,22 @@ issrcspec(uchar *src, uchar *smask)
} }
static void 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; char *ctl;
if(issrcspec(src, smask)) if(*flags == '\0'){
ctl = "%s %I %M %I %I %I %M"; if(!issrcspec(src, smask))
else ctl = "%s %I %M %I %I";
ctl = "%s %I %M %I %I"; else
DEBUG(ctl, cmd, dst, mask, gate, ia, src, smask); ctl = "%s %I %M %I %I %I %M";
if(conf.rfd < 0) DEBUG(ctl, cmd, dst, mask, gate, ia, src, smask);
fprint(conf.rfd, ctl, cmd, dst, mask, gate, ia, src, smask);
return; 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 static void
@ -765,11 +787,18 @@ defroutectl(char *cmd, uchar *gaddr, uchar *ia, uchar *src, uchar *smask)
if(smask == nil) if(smask == nil)
smask = IPnoaddr; smask = IPnoaddr;
} }
routectl(cmd, dst, mask, gaddr, ia, src, smask);
/* also add a source specific route */ if(tflag && isv4(gaddr)){
if(ipcmp(src, IPnoaddr) != 0 && ipcmp(src, v4prefix) != 0) /* add route for everyone with source translation */
routectl(cmd, dst, mask, gaddr, ia, src, IPallbits); 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 void
@ -1016,6 +1045,7 @@ ndb2conf(Ndb *db, uchar *myip)
ipmove(conf.mask, defmask(conf.laddr)); ipmove(conf.mask, defmask(conf.laddr));
memset(conf.raddr, 0, sizeof(conf.raddr));
memset(conf.gaddr, 0, sizeof(conf.gaddr)); memset(conf.gaddr, 0, sizeof(conf.gaddr));
memset(conf.dns, 0, sizeof(conf.dns)); memset(conf.dns, 0, sizeof(conf.dns));
memset(conf.ntp, 0, sizeof(conf.ntp)); memset(conf.ntp, 0, sizeof(conf.ntp));