diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-05-21 17:48:42 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-05-21 17:48:42 +0000 |
commit | cbf5d3dc340da5b96cd1282e622a3f862c5b103e (patch) | |
tree | 9f8fbafdf6de49df2b503c335a2ce1e264bfbde7 | |
parent | 169aa63ec5a670d0c72b7e9fb747e16d76b718c3 (diff) |
ip/ipconfig: initial dhcpv6 support, clean default-routes and /net/ndb on remove
This adds a very basic (probably wrong) DHCPv6 client,
to handle the "managed"-flag in IPv6 router solicitations.
We add -U option to pass the DHCPv6 client id as well as
an -s flag to manually add a dns server (because ppp
is going to call ipconfig to handle all the configuration
and write-back to /net/ndb in the future).
Have the remove command also remove default routes and
/net/ndb entries. (needed by ppp).
-rw-r--r-- | sys/man/8/ipconfig | 30 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/dhcp.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/dhcpv6.c | 233 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/ipconfig.h | 11 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/ipv6.c | 82 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/main.c | 127 | ||||
-rw-r--r-- | sys/src/cmd/ip/ipconfig/mkfile | 1 |
7 files changed, 403 insertions, 83 deletions
diff --git a/sys/man/8/ipconfig b/sys/man/8/ipconfig index 5a86f4495..aef791541 100644 --- a/sys/man/8/ipconfig +++ b/sys/man/8/ipconfig @@ -6,6 +6,8 @@ ipconfig, rip, linklocal \- Internet configuration and routing .ti -0.25i .B ip/ipconfig .RB [ -6DGNOPdnprtuX ] +.RB [ -U +.IR duid ] .RB [ -b .IR baud ] .RB [ -c @@ -18,6 +20,8 @@ ipconfig, rip, linklocal \- Internet configuration and routing .IR mtu ] .RB [ -o .IR dhcp-opt ] +.RB [ -s +.IR dnsserver ] .RB [ -f .IR dbfile ] .RB [ -x @@ -160,6 +164,11 @@ May be repeated to specify multiple control writes. .TP .B d use DHCP to determine any unspecified configuration parameters. +For the +.B ra6 +verb with non-zero +.BR recvra , +this enables DHCPv6 address configuration. .TP .B D turn on debugging. @@ -197,7 +206,7 @@ for the IP parameters for the specified .I local IP address or if .I local -is omited and the device is an ethernet then all IP parameters +is omitted and the device is an ethernet then all IP parameters associated with the MAC address. IPv6 addresses are added only if a IPv6 link-local address exists on the interface or the .B 6 @@ -223,9 +232,24 @@ This option directs .I ipconfig instead to fork a background process that keeps trying forever. .TP +.B s +add +.I dnsserver +to the +.B /net/ndb +configuration. +.TP .B t enable source address translation on the interface and default route. -(only usefull for IPv4). +(only useful for IPv4). +.TP +.B U +specify the DHCPv6 client identifier. +When omitted, the MAC address is used to generate a link-layer +based duid (DUID-LL). +Note that the +.B -d +flag must also be given to enable DHCPv6. .TP .B u disable IPv6 duplicate discovery detection, @@ -247,7 +271,7 @@ don't fork a process to keep the DHCP lease alive. .TP .B o adds -.I dhcpoption +.I dhcp-opt to the list of paramters requested of the DHCP server. The result will appear in .B /net/ndb diff --git a/sys/src/cmd/ip/ipconfig/dhcp.c b/sys/src/cmd/ip/ipconfig/dhcp.c index d66360e95..035f7f4b6 100644 --- a/sys/src/cmd/ip/ipconfig/dhcp.c +++ b/sys/src/cmd/ip/ipconfig/dhcp.c @@ -287,7 +287,7 @@ dhcpwatch(int needconfig) * leave everything we've learned somewhere that * other procs can find it. */ - putndb(); + putndb(1); refresh(); } } diff --git a/sys/src/cmd/ip/ipconfig/dhcpv6.c b/sys/src/cmd/ip/ipconfig/dhcpv6.c new file mode 100644 index 000000000..ba31fb1e3 --- /dev/null +++ b/sys/src/cmd/ip/ipconfig/dhcpv6.c @@ -0,0 +1,233 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ip.h> +#include <ndb.h> +#include "ipconfig.h" + +enum { + SOLICIT = 1, + ADVERTISE, + REQUEST, + CONFIRM, + RENEW, + REBIND, + REPLY, + RELEASE, + DECLINE, + RECONFIGURE, + INFOREQ, + RELAYFORW, + RELAYREPL, +}; + +static uchar v6dhcpservers[IPaddrlen] = { + 0xff, 0x02, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 1, 0, 2, +}; + +static uchar sid[256]; +static int sidlen; + +static int +openlisten(void) +{ + int n, fd, cfd; + char data[128], devdir[40]; + + sprint(data, "%s/udp!%I!546", conf.mpoint, conf.lladdr); + for (n = 0; (cfd = announce(data, devdir)) < 0; n++) { + if(!noconfig) + sysfatal("can't announce for dhcp: %r"); + + /* might be another client - wait and try again */ + warning("can't announce %s: %r", data); + sleep(jitter()); + if(n > 10) + return -1; + } + + if(fprint(cfd, "headers") < 0) + sysfatal("can't set header mode: %r"); + + fprint(cfd, "ignoreadvice"); + + sprint(data, "%s/data", devdir); + fd = open(data, ORDWR); + if(fd < 0) + sysfatal("open %s: %r", data); + close(cfd); + return fd; +} + +static int +transaction(int fd, int type, int timeout) +{ + union { + Udphdr; + uchar buf[4096]; + } ipkt, opkt; + + uchar *p, *e, *x; + int tra, opt, len, sleepfor; + + tra = lrand() & 0xFFFFFF; + + ipmove(opkt.laddr, conf.lladdr); + ipmove(opkt.raddr, v6dhcpservers); + ipmove(opkt.ifcaddr, conf.lladdr); + hnputs(opkt.lport, 546); + hnputs(opkt.rport, 547); + + p = opkt.buf + Udphdrsize; + + *p++ = type; + *p++ = tra >> 16; + *p++ = tra >> 8; + *p++ = tra >> 0; + + /* client identifier */ + *p++ = 0x00; *p++ = 0x01; + /* len */ + *p++ = conf.duidlen >> 8; + *p++ = conf.duidlen; + memmove(p, conf.duid, conf.duidlen); + p += conf.duidlen; + + /* IA for non-temporary address */ + len = 12; + if(validip(conf.laddr)) + len += 4 + IPaddrlen + 2*4; + *p++ = 0x00; *p++ = 0x03; + *p++ = len >> 8; + *p++ = len; + /* IAID */ + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x01; + /* T1, T2 */ + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; + *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; + if(len > 12){ + *p++ = 0x00; *p++ = 0x05; + *p++ = 0x00; *p++ = IPaddrlen + 2*4; + memmove(p, conf.laddr, IPaddrlen); + p += IPaddrlen; + memset(p, 0xFF, 2*4); + p += 2*4; + } + + /* Option Request */ + *p++ = 0x00; *p++ = 0x06; + *p++ = 0x00; *p++ = 0x02; + *p++ = 0x00; *p++ = 0x17; /* DNS servers */ + + if(sidlen > 0){ + *p++ = 0x00; *p++ = 0x02; + /* len */ + *p++ = sidlen >> 8; + *p++ = sidlen;; + memmove(p, sid, sidlen); + p += sidlen; + } + + len = -1; + for(sleepfor = 500; timeout > 0; sleepfor <<= 1){ + DEBUG("sending dhcpv6 request %x", opkt.buf[Udphdrsize]); + + alarm(sleepfor); + if(len < 0) + write(fd, opkt.buf, p - opkt.buf); + + len = read(fd, ipkt.buf, sizeof(ipkt.buf)); + timeout += alarm(0); + timeout -= sleepfor; + if(len == 0) + break; + + if(len < Udphdrsize+4) + continue; + if(ipkt.buf[Udphdrsize+1] != ((tra>>16)&0xFF) + || ipkt.buf[Udphdrsize+2] != ((tra>>8)&0xFF) + || ipkt.buf[Udphdrsize+3] != ((tra>>0)&0xFF)) + continue; + + DEBUG("got dhcpv6 reply %x from %I on %I", ipkt.buf[Udphdrsize+0], ipkt.raddr, ipkt.ifcaddr); + + type |= (int)ipkt.buf[Udphdrsize+0]<<8; + switch(type){ + case ADVERTISE << 8 | SOLICIT: + case REPLY << 8 | REQUEST: + goto Response; + default: + return -1; + } + } + return -1; + +Response: + for(p = ipkt.buf + Udphdrsize + 4, e = ipkt.buf + len; p < e; p = x) { + if (p+4 > e) + return -1; + + opt = (int)p[0] << 8 | p[1]; + len = (int)p[2] << 8 | p[3]; + p += 4; + x = p+len; + if (x > e) + return -1; + + DEBUG("got dhcpv6 option %x: [%d] %.*H", opt, len, len, p); + + switch(opt){ + case 0x01: /* client identifier */ + continue; + case 0x02: /* server identifier */ + if(len < 1 || len > sizeof(sid)) + break; + sidlen = len; + memmove(sid, p, sidlen); + continue; + case 0x03: /* IA for non-temporary address */ + if(p+12+4+IPaddrlen+2*4 > x) + break; + /* skip IAID, T1, T2 */ + p += 12; + /* IA Addresss */ + if(p[0] != 0x00 || p[1] != 0x05 + || p[2] != 0x00 || p[3] != IPaddrlen+2*4) + break; + p += 4; + memset(conf.mask, 0xFF, IPaddrlen); + memmove(conf.laddr, p, IPaddrlen); + continue; + case 0x17: /* dns servers */ + if(len % IPaddrlen) + break; + addaddrs(conf.dns, sizeof(conf.dns), p, len); + continue; + default: + DEBUG("unknown dhcpv6 option %x", opt); + continue; + } + warning("dhcpv6: malformed option %x: [%d] %.*H", opt, len, len, x-len); + } + + return 0; +} + +void +dhcpv6query(void) +{ + int fd; + + fd = openlisten(); + if(transaction(fd, SOLICIT, 5000) < 0) + goto out; + if(!validip(conf.laddr)) + goto out; + if(transaction(fd, REQUEST, 10000) < 0) + goto out; +out: + close(fd); +} diff --git a/sys/src/cmd/ip/ipconfig/ipconfig.h b/sys/src/cmd/ip/ipconfig/ipconfig.h index 9445e4965..4e85b3e44 100644 --- a/sys/src/cmd/ip/ipconfig/ipconfig.h +++ b/sys/src/cmd/ip/ipconfig/ipconfig.h @@ -35,6 +35,8 @@ struct Conf int hwalen; uchar cid[32]; int cidlen; + uchar duid[2+128]; + int duidlen; char *baud; /* learned info */ @@ -99,6 +101,7 @@ struct Ctl extern Conf conf; extern int myifc; extern int noconfig; +extern int dodhcp; extern int debug; extern int dolog; @@ -129,7 +132,7 @@ int pnames(uchar*, int, char*); int gnames(char*, int, uchar*, int); Ndb* opendatabase(void); void ndb2conf(Ndb *db, uchar *ip); -void putndb(void); +void putndb(int); void refresh(void); ulong randint(ulong low, ulong hi); int validip(uchar*); @@ -155,3 +158,9 @@ void doipv6(int); void ea2lla(uchar *lla, uchar *ea); int findllip(uchar *ip, Ipifc *ifc); int ip6cfg(void); + +/* + * DHCPv6 + */ +void dhcpv6init(void); +void dhcpv6query(void); diff --git a/sys/src/cmd/ip/ipconfig/ipv6.c b/sys/src/cmd/ip/ipconfig/ipv6.c index 068da9693..f4ee4926c 100644 --- a/sys/src/cmd/ip/ipconfig/ipv6.c +++ b/sys/src/cmd/ip/ipconfig/ipv6.c @@ -448,25 +448,16 @@ sendrs(int fd, uchar *dst) } } -/* - * a router receiving a router adv from another - * router calls this; it is basically supposed to - * log the information in the ra and raise a flag - * if any parameter value is different from its configured values. - * - * doing nothing for now since I don't know where to log this yet. - */ -static void -recvrarouter(uchar buf[], int pktlen) -{ - USED(buf, pktlen); -} - static void ewrite(int fd, char *str) { int n; + if(noconfig){ + DEBUG("ewrite: %s\n", str); + return; + } + if(fd < 0) return; @@ -561,7 +552,7 @@ static Route *routelist; /* * host receiving a router advertisement calls this */ -static void +static int recvrahost(uchar buf[], int pktlen) { char dnsdomain[sizeof(conf.dnsdomain)]; @@ -578,19 +569,24 @@ recvrahost(uchar buf[], int pktlen) m = sizeof *ra; ra = (Routeradv*)buf; if(pktlen < m) - return; + return -1; if(!ISIPV6LINKLOCAL(ra->src)) - return; + return -1; conf.ttl = ra->cttl; - conf.mflag = (MFMASK & ra->mor); - conf.oflag = (OCMASK & ra->mor); + conf.mflag = (MFMASK & ra->mor) != 0; + conf.oflag = (OCMASK & ra->mor) != 0; conf.routerlt = nhgets(ra->routerlt); conf.reachtime = nhgetl(ra->rchbltime); conf.rxmitra = nhgetl(ra->rxmtimer); conf.linkmtu = DEFMTU; + if(conf.routerlt == 0) + ipmove(conf.gaddr, IPnoaddr); + else + ipmove(conf.gaddr, ra->src); + memset(conf.dns, 0, sizeof(conf.dns)); memset(conf.fs, 0, sizeof(conf.fs)); memset(conf.auth, 0, sizeof(conf.auth)); @@ -602,7 +598,7 @@ recvrahost(uchar buf[], int pktlen) optype = buf[n]; m += 8 * buf[n+1]; if(m <= n || pktlen < m) - return; + return -1; switch (optype) { case V6nd_srclladdr: @@ -660,7 +656,7 @@ recvrahost(uchar buf[], int pktlen) || ipcmp(r->src, ra->src) == 0 && r->routerlt != 0 && conf.routerlt == 0){ DEBUG("purging RA from %I on %s; pfx %I %M", r->src, conf.dev, r->laddr, r->mask); - if(validip(r->gaddr)) + if(!noconfig && validip(r->gaddr)) removedefroute(r->gaddr, conf.lladdr, r->laddr, r->mask); *rr = r->next; free(r); @@ -678,7 +674,7 @@ recvrahost(uchar buf[], int pktlen) optype = buf[n]; m += 8 * buf[n+1]; if(m <= n || pktlen < m) - return; + return -1; if(optype != V6nd_pfxinfo) continue; @@ -760,17 +756,19 @@ recvrahost(uchar buf[], int pktlen) DEBUG("got RA from %I on %s; pfx %I %M", ra->src, conf.dev, conf.v6pref, conf.mask); + if(noconfig) + continue; + if(validip(conf.gaddr) && ipcmp(conf.gaddr, conf.laddr) != 0 && ipcmp(conf.gaddr, conf.lladdr) != 0) adddefroute(conf.gaddr, conf.lladdr, conf.laddr, conf.mask); - if(noconfig) - continue; - - putndb(); + putndb(1); refresh(); } + + return 0; } /* @@ -838,7 +836,10 @@ recvra6(void) exits(nil); } - if(recvra6on(ifc) == IsHostNoRecv || noconfig && sendrscnt < 0){ + switch(recvra6on(ifc)){ + case IsHostRecv: + break; + default: warning("recvra6: recvra off, quitting on %s", conf.dev); if(recvracnt == 0) rendezvous(recvra6, (void*)-1); @@ -859,18 +860,27 @@ recvra6(void) continue; } - switch (recvra6on(ifc)) { - case IsRouter: - recvrarouter(buf, n); - break; - case IsHostRecv: - recvrahost(buf, n); - break; - } + if(recvrahost(buf, n) < 0) + continue; /* got at least initial ra; no whining */ - if(recvracnt == 0) + if(recvracnt == 0){ + if(dodhcp && conf.mflag){ + dhcpv6query(); + if(noconfig || !validip(conf.laddr)) + continue; + fprint(conf.rfd, "tag dhcp"); + if(ip6cfg() < 0){ + fprint(conf.rfd, "tag ra6"); + continue; + } + putndb(1); + refresh(); + rendezvous(recvra6, (void*)1); + exits(nil); + } rendezvous(recvra6, (void*)1); + } if(recvracnt < Maxv6initras) recvracnt++; diff --git a/sys/src/cmd/ip/ipconfig/main.c b/sys/src/cmd/ip/ipconfig/main.c index c1c20b4c5..9a9f6d0bc 100644 --- a/sys/src/cmd/ip/ipconfig/main.c +++ b/sys/src/cmd/ip/ipconfig/main.c @@ -39,6 +39,7 @@ char *dbfile; static char logfile[] = "ipconfig"; +static void openiproute(void); static void binddevice(void); static void controldevice(void); extern void pppbinddev(void); @@ -54,8 +55,8 @@ static int Ufmt(Fmt*); void usage(void) { - fprint(2, "usage: %s [-6dDGnNOpPrtuX][-b baud][-c ctl]* [-g gw]" - "[-h host][-m mtu]\n" + fprint(2, "usage: %s [-6dDGnNOpPrtuX][-b baud][-c ctl]* [-U duid] [-g gw]" + "[-h host][-m mtu][-s dns]...\n" "\t[-f dbfile][-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask " "[raddr [fs [auth]]]]]\n", argv0); exits("usage"); @@ -277,10 +278,10 @@ findifc(char *net, char *dev) Ipifc *nifc; ifc = readipifc(net, ifc, -1); - for(nifc = ifc; nifc != nil; nifc = nifc->next) + for(nifc = ifc; nifc != nil; nifc = nifc->next){ if(strcmp(nifc->dev, dev) == 0) return nifc->index; - + } return -1; } @@ -305,6 +306,15 @@ mkclientid(void) conf.cid[0] = conf.hwatype; memmove(&conf.cid[1], conf.hwa, conf.hwalen); conf.cidlen = conf.hwalen+1; + if(conf.duidlen == 0){ + /* DUID-LL */ + conf.duid[0] = 0x00; + conf.duid[1] = 0x03; + conf.duid[2] = conf.hwatype >> 8; + conf.duid[3] = conf.hwatype; + memmove(conf.duid+4, conf.hwa, conf.hwalen); + conf.duidlen = conf.hwalen+4; + } } else { conf.hwatype = -1; snprint((char*)conf.cid, sizeof conf.cid, @@ -318,8 +328,10 @@ mkclientid(void) void main(int argc, char **argv) { + uchar ip[IPaddrlen]; int action; Ctl *cp; + char *s; init(); ARGBEGIN { @@ -384,12 +396,23 @@ main(int argc, char **argv) case 'r': rflag = 1; break; + case 's': + if(parseip(ip, EARGF(usage())) == -1) + usage(); + addaddrs(conf.dns, sizeof(conf.dns), ip, sizeof(ip)); + break; case 't': tflag = 1; break; case 'u': /* IPv6: duplicate neighbour disc. off */ dupl_disc = 0; break; + case 'U': /* device unique id used for dhcpv6 */ + s = EARGF(usage()); + conf.duidlen = dec16(conf.duid, sizeof(conf.duid), s, strlen(s)); + if(conf.duidlen <= 0) + usage(); + break; case 'x': setnetmtpt(conf.mpoint, sizeof conf.mpoint, EARGF(usage())); break; @@ -399,13 +422,13 @@ main(int argc, char **argv) default: usage(); } ARGEND; - argv0 = "ipconfig"; /* boot invokes us as tcp? */ action = parseargs(argc, argv); - if(beprimary == -1 && (ipv6auto || parseverb(conf.type) == Vloopback)) + if(beprimary == -1 && (ipv6auto || ISIPV6LINKLOCAL(conf.laddr) || parseverb(conf.type) == Vloopback)) beprimary = 0; + openiproute(); myifc = findifc(conf.mpoint, conf.dev); if(myifc < 0) { switch(action){ @@ -416,9 +439,15 @@ main(int argc, char **argv) controldevice(); binddevice(); myifc = findifc(conf.mpoint, conf.dev); - case Vremove: case Vunbind: break; + case Vremove: + /* + * interface gone, just remove + * default route and ndb entries. + */ + doremove(); + exits(nil); } if(myifc < 0) sysfatal("interface not found for: %s", conf.dev); @@ -478,6 +507,7 @@ doadd(void) } else sysfatal("no success with DHCP"); } + DEBUG("adding address %I %M on %s", conf.laddr, conf.mask, conf.dev); if(noconfig) return; @@ -493,7 +523,7 @@ doadd(void) } /* leave everything we've learned somewhere other procs can find it */ - putndb(); + putndb(1); refresh(); } @@ -504,11 +534,18 @@ doremove(void) sysfatal("remove requires an address"); DEBUG("removing address %I %M on %s", conf.laddr, conf.mask, conf.dev); - if(conf.cfd < 0) + if(noconfig) return; - if(fprint(conf.cfd, "remove %I %M", conf.laddr, conf.mask) < 0) + if(validip(conf.gaddr)) + removedefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask); + + if(conf.cfd >= 0 && fprint(conf.cfd, "remove %I %M", conf.laddr, conf.mask) < 0) warning("can't remove %I %M: %r", conf.laddr, conf.mask); + + /* remove ndb entries matching our ip address */ + putndb(0); + refresh(); } static void @@ -521,6 +558,15 @@ dounbind(void) warning("can't unbind %s: %r", conf.dev); } +static void +openiproute(void) +{ + char buf[127]; + + snprint(buf, sizeof buf, "%s/iproute", conf.mpoint); + conf.rfd = open(buf, OWRITE); +} + /* send some ctls to a device */ static void controldevice(void) @@ -570,8 +616,6 @@ binddevice(void) if(fprint(conf.cfd, "bind %s %s", conf.type, conf.dev) < 0) sysfatal("%s: bind %s %s: %r", buf, conf.type, conf.dev); } - snprint(buf, sizeof buf, "%s/iproute", conf.mpoint); - conf.rfd = open(buf, OWRITE); } /* add a logical interface to the ip stack */ @@ -624,9 +668,6 @@ ipunconfig(void) if(!validip(conf.mask)) ipmove(conf.mask, defmask(conf.laddr)); - if(validip(conf.gaddr)) - removedefroute(conf.gaddr, conf.laddr, conf.laddr, conf.mask); - doremove(); ipmove(conf.laddr, IPnoaddr); @@ -671,7 +712,7 @@ putnames(char *p, char *e, char *attr, char *s) /* make an ndb entry and put it into /net/ndb for the servers to see */ void -putndb(void) +putndb(int doadd) { static char buf[16*1024]; char file[64], *p, *e, *np; @@ -684,32 +725,35 @@ putndb(void) p = buf; e = buf + sizeof buf; - p = seprint(p, e, "ip=%I ipmask=%M ipgw=%I\n", - conf.laddr, conf.mask, conf.gaddr); - if(np = strchr(conf.hostname, '.')){ - if(*conf.domainname == 0) - strcpy(conf.domainname, np+1); - *np = 0; + + if(doadd){ + p = seprint(p, e, "ip=%I ipmask=%M ipgw=%I\n", + conf.laddr, conf.mask, conf.gaddr); + if(np = strchr(conf.hostname, '.')){ + if(*conf.domainname == 0) + strcpy(conf.domainname, np+1); + *np = 0; + } + if(*conf.hostname) + p = seprint(p, e, "\tsys=%U\n", conf.hostname); + if(*conf.domainname) + p = seprint(p, e, "\tdom=%U.%U\n", + conf.hostname, conf.domainname); + if(*conf.dnsdomain) + p = putnames(p, e, "\tdnsdomain", conf.dnsdomain); + if(validip(conf.dns)) + p = putaddrs(p, e, "\tdns", conf.dns, sizeof conf.dns); + if(validip(conf.fs)) + p = putaddrs(p, e, "\tfs", conf.fs, sizeof conf.fs); + if(validip(conf.auth)) + p = putaddrs(p, e, "\tauth", conf.auth, sizeof conf.auth); + if(validip(conf.ntp)) + p = putaddrs(p, e, "\tntp", conf.ntp, sizeof conf.ntp); + if(ndboptions) + p = seprint(p, e, "%s\n", ndboptions); } - if(*conf.hostname) - p = seprint(p, e, "\tsys=%U\n", conf.hostname); - if(*conf.domainname) - p = seprint(p, e, "\tdom=%U.%U\n", - conf.hostname, conf.domainname); - if(*conf.dnsdomain) - p = putnames(p, e, "\tdnsdomain", conf.dnsdomain); - if(validip(conf.dns)) - p = putaddrs(p, e, "\tdns", conf.dns, sizeof conf.dns); - if(validip(conf.fs)) - p = putaddrs(p, e, "\tfs", conf.fs, sizeof conf.fs); - if(validip(conf.auth)) - p = putaddrs(p, e, "\tauth", conf.auth, sizeof conf.auth); - if(validip(conf.ntp)) - p = putaddrs(p, e, "\tntp", conf.ntp, sizeof conf.ntp); - if(ndboptions) - p = seprint(p, e, "%s\n", ndboptions); - - /* append preexisting entries not matching our ip */ + + /* write preexisting entries not matching our ip */ snprint(file, sizeof file, "%s/ndb", conf.mpoint); db = ndbopen(file); if(db != nil ){ @@ -728,7 +772,6 @@ putndb(void) } ndbclose(db); } - if((fd = open(file, OWRITE|OTRUNC)) < 0) return; write(fd, buf, p-buf); diff --git a/sys/src/cmd/ip/ipconfig/mkfile b/sys/src/cmd/ip/ipconfig/mkfile index cdeedb188..ce106682e 100644 --- a/sys/src/cmd/ip/ipconfig/mkfile +++ b/sys/src/cmd/ip/ipconfig/mkfile @@ -5,6 +5,7 @@ TARG=ipconfig\ OFILES=\ main.$O\ dhcp.$O\ + dhcpv6.$O\ ipv6.$O\ ppp.$O\ |