diff --git a/sys/man/8/ipconfig b/sys/man/8/ipconfig index 767eebf4a..5a86f4495 100644 --- a/sys/man/8/ipconfig +++ b/sys/man/8/ipconfig @@ -5,7 +5,7 @@ ipconfig, rip, linklocal \- Internet configuration and routing .in +0.25i .ti -0.25i .B ip/ipconfig -.RB [ -6DGNOPdnpruX ] +.RB [ -6DGNOPdnprtuX ] .RB [ -b .IR baud ] .RB [ -c @@ -223,6 +223,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, which removes any existing ARP table entry for one of our IPv6 addresses diff --git a/sys/src/cmd/ip/ipconfig/ipconfig.h b/sys/src/cmd/ip/ipconfig/ipconfig.h index 9445e4965..9c4bdd922 100644 --- a/sys/src/cmd/ip/ipconfig/ipconfig.h +++ b/sys/src/cmd/ip/ipconfig/ipconfig.h @@ -116,6 +116,7 @@ void usage(void); int ip4cfg(void); void ipunconfig(void); +void setroutetag(char*); void adddefroute(uchar*, uchar*, uchar*, uchar*); void removedefroute(uchar*, uchar*, uchar*, uchar*); diff --git a/sys/src/cmd/ip/ipconfig/ipv6.c b/sys/src/cmd/ip/ipconfig/ipv6.c index 469501f5d..b16beadf2 100644 --- a/sys/src/cmd/ip/ipconfig/ipv6.c +++ b/sys/src/cmd/ip/ipconfig/ipv6.c @@ -354,8 +354,8 @@ arpcheck(uchar *ip) 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 @@ Again: 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 @@ startra6(void) void doipv6(int what) { - fprint(conf.rfd, "tag ra6"); - + setroutetag("ra6"); switch (what) { default: sysfatal("unknown IPv6 verb"); diff --git a/sys/src/cmd/ip/ipconfig/main.c b/sys/src/cmd/ip/ipconfig/main.c index e06b8404d..560b759a1 100644 --- a/sys/src/cmd/ip/ipconfig/main.c +++ b/sys/src/cmd/ip/ipconfig/main.c @@ -24,6 +24,7 @@ int dolog; int plan9 = 1; int Oflag; int rflag; +int tflag; int dodhcp; int nodhcpwatch; @@ -53,7 +54,7 @@ static int Ufmt(Fmt*); 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 @@ main(int argc, char **argv) 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 @@ doadd(void) /* run dhcp if we need something */ if(dodhcp){ - fprint(conf.rfd, "tag dhcp"); + setroutetag("dhcp"); dhcpquery(!noconfig, Sselecting); } @@ -587,12 +591,14 @@ ip4cfg(void) 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 @@ ip4cfg(void) && 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 @@ putndb(void) 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 @@ issrcspec(uchar *src, uchar *smask) } 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 @@ defroutectl(char *cmd, uchar *gaddr, uchar *ia, uchar *src, uchar *smask) 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 @@ ndb2conf(Ndb *db, uchar *myip) 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));