summaryrefslogtreecommitdiff
path: root/appl/cmd/ip/dhcp.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/ip/dhcp.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/ip/dhcp.b')
-rw-r--r--appl/cmd/ip/dhcp.b162
1 files changed, 162 insertions, 0 deletions
diff --git a/appl/cmd/ip/dhcp.b b/appl/cmd/ip/dhcp.b
new file mode 100644
index 00000000..63ac2255
--- /dev/null
+++ b/appl/cmd/ip/dhcp.b
@@ -0,0 +1,162 @@
+implement Dhcp;
+
+#
+# configure an interface using DHCP
+#
+
+include "sys.m";
+ sys: Sys;
+
+include "draw.m";
+
+include "ip.m";
+ ip: IP;
+ IPv4off, IPaddrlen, OUdphdrlen: import IP;
+ IPaddr: import ip;
+ get2, get4, put2, put4: import ip;
+
+include "dhcp.m";
+ dhcpclient: Dhcpclient;
+ Bootconf, Lease: import dhcpclient;
+
+include "arg.m";
+
+Dhcp: module
+{
+ init: fn(nil: ref Draw->Context, nil: list of string);
+};
+
+RetryTime: con 10*1000; # msec
+
+init(nil: ref Draw->Context, args: list of string)
+{
+ sys = load Sys Sys->PATH;
+ ip = load IP IP->PATH;
+ dhcpclient = load Dhcpclient Dhcpclient->PATH;
+
+ sys->pctl(Sys->NEWFD|Sys->NEWPGRP, 0 :: 1 :: 2 :: nil);
+
+ arg := load Arg Arg->PATH;
+ arg->init(args);
+ arg->setusage("dhcp [-bdmnpr] [-g ipgw] [-h hostname] [-x /net] ifcdir [ip [ipmask]]");
+ trace := 0;
+ pcfg := 0;
+ bootp := 0;
+ monitor := 0;
+ retry := 0;
+ noctl := 0;
+ netdir := "/net";
+ cfg := Bootconf.new();
+ while((o := arg->opt()) != 0)
+ case o {
+ 'b' => bootp = 1;
+ 'd' => trace++;
+ 'g' => cfg.ipgw = arg->earg();
+ 'h' => cfg.puts(Dhcpclient->Ohostname, arg->earg());
+ 'm' => monitor = 1;
+ 'n' => noctl = 1;
+ 'p' => pcfg = 1;
+ 'r' => retry = 1;
+ 'x' => netdir = arg->earg();
+ * => arg->usage();
+ }
+ args = arg->argv();
+ if(len args == 0)
+ arg->usage();
+
+ ifcdir := hd args;
+ args = tl args;
+ if(args != nil){
+ cfg.ip = hd args;
+ args = tl args;
+ if(args != nil){
+ cfg.ipmask = hd args;
+ args = tl args;
+ if(args != nil)
+ arg->usage();
+ }
+ }
+ arg = nil;
+
+ ifcctl: ref Sys->FD;
+ if(noctl == 0){
+ ifcctl = sys->open(ifcdir+"/ctl", Sys->OWRITE);
+ if(ifcctl == nil)
+ err(sys->sprint("cannot open %s/ctl: %r", ifcdir));
+ }
+ etherdir := finddev(ifcdir);
+ if(etherdir == nil)
+ err(sys->sprint("cannot find network device in %s/status: %r", ifcdir));
+ if(etherdir[0] != '/' && etherdir[0] != '#')
+ etherdir = netdir+"/"+etherdir;
+
+ ip->init();
+ dhcpclient->init();
+ dhcpclient->tracing(trace);
+ e: string;
+ lease: ref Lease;
+ for(;;){
+ if(bootp){
+ (cfg, e) = dhcpclient->bootp(netdir, ifcctl, etherdir+"/addr", cfg);
+ if(e == nil){
+ if(cfg != nil)
+ dhcpclient->applycfg(netdir, ifcctl, cfg);
+ if(pcfg)
+ printcfg(cfg);
+ break;
+ }
+ }else{
+ (cfg, lease, e) = dhcpclient->dhcp(netdir, ifcctl, etherdir+"/addr", cfg, nil); # last is array of int options
+ if(e == nil){
+ if(pcfg)
+ printcfg(cfg);
+ if(cfg.lease > 0 && monitor)
+ leasemon(lease.configs, pcfg);
+ break;
+ }
+ }
+ if(!retry)
+ err("failed to configure network: "+e);
+ sys->fprint(sys->fildes(2), "dhcp: failed to configure network: %s; retrying", e);
+ sys->sleep(RetryTime);
+ }
+}
+
+leasemon(configs: chan of (ref Bootconf, string), pcfg: int)
+{
+ for(;;){
+ (cfg, e) := <-configs;
+ if(e != nil)
+ sys->fprint(sys->fildes(2), "dhcp: %s", e);
+ if(pcfg)
+ printcfg(cfg);
+ }
+}
+
+printcfg(cfg: ref Bootconf)
+{
+ sys->print("ip=%s ipmask=%s ipgw=%s iplease=%d\n", cfg.ip, cfg.ipmask, cfg.ipgw, cfg.lease);
+}
+
+finddev(ifcdir: string): string
+{
+ fd := sys->open(ifcdir+"/status", Sys->OREAD);
+ if(fd == nil)
+ return nil;
+ buf := array[1024] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ return nil;
+ (nf, l) := sys->tokenize(string buf[0:n], " \n");
+ if(nf < 2){
+ sys->werrstr("unexpected format for status file");
+ return nil;
+ }
+ return hd tl l;
+}
+
+err(s: string)
+{
+ sys->fprint(sys->fildes(2), "dhcp: %s\n", s);
+ raise "fail:error";
+}