📄 ipconfig.c
字号:
} else { conf.hwatype = -1; snprint((char*)conf.cid, sizeof(conf.cid), "plan9_%ld.%d", lrand(), getpid()); conf.cidlen = strlen((char*)conf.cid); }}// bind ip into the namespacevoidlookforip(char *net){ char proto[64]; snprint(proto, sizeof(proto), "%s/ipifc", net); if(access(proto, 0) == 0) return; sysfatal("no ip stack bound onto %s", net);}// send some ctls to a devicevoidcontroldevice(void){ char ctlfile[256]; int fd; Ctl *cp; if(firstctl == nil) return; if(strcmp(conf.type, "ether") == 0) snprint(ctlfile, sizeof(ctlfile), "%s/clone", conf.dev); else return; fd = open(ctlfile, ORDWR); if(fd < 0) sysfatal("can't open %s", ctlfile); for(cp = firstctl; cp != nil; cp = cp->next){ if(write(fd, cp->ctl, strlen(cp->ctl)) < 0) sysfatal("ctl message %s: %r", cp->ctl); seek(fd, 0, 0); }}// bind an ip stack to a device, leave the control channel openvoidbinddevice(void){ char buf[256]; if(myifc < 0){ // get a new ip interface snprint(buf, sizeof(buf), "%s/ipifc/clone", conf.mpoint); conf.cfd = open(buf, ORDWR); if(conf.cfd < 0) sysfatal("opening %s/ipifc/clone: %r", conf.mpoint); // specify the medium as an ethernet, and bind the interface to it if(fprint(conf.cfd, "bind %s %s", conf.type, conf.dev) < 0) sysfatal("binding device: %r"); } else { // open the old interface snprint(buf, sizeof(buf), "%s/ipifc/%d/ctl", conf.mpoint, myifc); conf.cfd = open(buf, ORDWR); if(conf.cfd < 0) sysfatal("opening %s/ipifc/%d/ctl: %r", conf.mpoint, myifc); }}// add a logical interface to the ip stackintipconfig(void){ char buf[256]; int n; if(!validip(conf.laddr)) return -1; n = sprint(buf, "add"); n += snprint(buf+n, sizeof(buf)-n, " %I", conf.laddr); if(!validip(conf.mask)) ipmove(conf.mask, defmask(conf.laddr)); n += snprint(buf+n, sizeof(buf)-n, " %I", 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(write(conf.cfd, buf, n) < 0){ fprint(2, "ipconfig: write(%s): %r\n", buf); return -1; } if(beprimary==1 && validip(conf.gaddr)) adddefroute(conf.mpoint, conf.gaddr); return 0;}// remove a logical interface to the ip stackvoidipunconfig(void){ char buf[256]; int n; if(!validip(conf.laddr)) return; DEBUG("couldn't renew IP lease, releasing %I\n", conf.laddr); n = sprint(buf, "remove"); n += snprint(buf+n, sizeof(buf)-n, " %I", conf.laddr); if(!validip(conf.mask)) ipmove(conf.mask, defmask(conf.laddr)); n += snprint(buf+n, sizeof(buf)-n, " %I", conf.mask); write(conf.cfd, buf, n); ipmove(conf.laddr, IPnoaddr); ipmove(conf.raddr, IPnoaddr); ipmove(conf.mask, IPnoaddr); // forget configuration info if(beprimary==1) writendb("", 0, 0);}voidding(void*, char *msg){ if(strstr(msg, "alarm")) noted(NCONT); noted(NDFLT);}voiddhcpquery(int needconfig, int startstate){ if(needconfig) fprint(conf.cfd, "add %I %I", IPnoaddr, IPnoaddr); conf.fd = openlisten(); if(conf.fd < 0){ conf.state = Sinit; return; } notify(ding); // try dhcp for 10 seconds conf.xid = lrand(); conf.starttime = time(0); conf.state = startstate; switch(startstate){ case Sselecting: conf.offered = 0; dhcpsend(Discover); break; case Srenewing: dhcpsend(Request); break; default: sysfatal("internal error 0"); } conf.resend = 0; conf.timeout = time(0) + 4; while(conf.state != Sbound){ dhcprecv(); if(dhcptimer() < 0) break; if(time(0) - conf.starttime > 10) break; } close(conf.fd); if(needconfig) fprint(conf.cfd, "remove %I %I", IPnoaddr, IPnoaddr);}#define HOUR (60*60)voiddhcpwatch(int needconfig){ int secs, s; ulong t; if(nodhcpwatch) return; switch(rfork(RFPROC|RFFDG|RFNOWAIT|RFNOTEG)){ default: return; case 0: break; } // keep trying to renew the lease for(;;){ if(conf.lease == 0) secs = 5; else secs = conf.lease>>1; // avoid overflows for(s = secs; s > 0; s -= t){ if(s > HOUR) t = HOUR; else t = s; sleep(t*1000); } if(conf.lease > 0){ // during boot, the starttime can be bogus so avoid // spurious ipinconfig's t = time(0) - conf.starttime; if(t > (3*secs)/2) t = secs; if(t >= conf.lease){ conf.lease = 0; if(!noconfig){ ipunconfig(); needconfig = 1; } } else conf.lease -= t; } dhcpquery(needconfig, needconfig ? Sselecting : Srenewing); if(needconfig && conf.state == Sbound){ if(ipconfig() < 0) sysfatal("can't start ip: %r"); needconfig = 0; // leave everything we've learned somewhere other procs can find it if(beprimary==1){ putndb(); tweakservers(); } } }}intdhcptimer(void){ ulong now; now = time(0); if(now < conf.timeout) return 0; switch(conf.state) { default: sysfatal("dhcptimer: unknown state %d", conf.state); case Sinit: break; case Sselecting: dhcpsend(Discover); conf.timeout = now + 4; conf.resend++; if(conf.resend>5) goto err; break; case Srequesting: dhcpsend(Request); conf.timeout = now + 4; conf.resend++; if(conf.resend>5) goto err; break; case Srenewing: dhcpsend(Request); conf.timeout = now + 1; conf.resend++; if(conf.resend>3) { conf.state = Srebinding; conf.resend = 0; } break; case Srebinding: dhcpsend(Request); conf.timeout = now + 4; conf.resend++; if(conf.resend>5) goto err; break; case Sbound: break; } return 0;err: conf.state = Sinit; return -1;}voiddhcpsend(int type){ Bootp bp; uchar *p; int n; uchar vendor[64]; OUdphdr *up = (OUdphdr*)bp.udphdr; memset(&bp, 0, sizeof(bp)); hnputs(up->rport, 67); bp.op = Bootrequest; hnputl(bp.xid, conf.xid); hnputs(bp.secs, time(0)-conf.starttime); hnputs(bp.flags, 0); memmove(bp.optmagic, optmagic, 4); if(conf.hwatype >= 0 && conf.hwalen < sizeof(bp.chaddr)){ memmove(bp.chaddr, conf.hwa, conf.hwalen); bp.hlen = conf.hwalen; bp.htype = conf.hwatype; } p = bp.optdata; p = optaddbyte(p, ODtype, type); p = optadd(p, ODclientid, conf.cid, conf.cidlen); switch(type) { default: sysfatal("dhcpsend: unknown message type: %d", type); case Discover: ipmove(up->raddr, IPv4bcast); // broadcast if(*conf.hostname && sendhostname) p = optaddstr(p, OBhostname, conf.hostname); if(plan9){ n = snprint((char*)vendor, sizeof(vendor), "plan9_%s", conf.cputype); p = optaddvec(p, ODvendorclass, vendor, n); } p = optaddvec(p, ODparams, requested, nrequested); if(validip(conf.laddr)) p = optaddaddr(p, ODipaddr, conf.laddr); break; case Request: switch(conf.state){ case Srenewing: ipmove(up->raddr, conf.server); v6tov4(bp.ciaddr, conf.laddr); break; case Srebinding: ipmove(up->raddr, IPv4bcast); // broadcast v6tov4(bp.ciaddr, conf.laddr); break; case Srequesting: ipmove(up->raddr, IPv4bcast); // broadcast p = optaddaddr(p, ODipaddr, conf.laddr); p = optaddaddr(p, ODserverid, conf.server); break; } p = optaddulong(p, ODlease, conf.offered); if(plan9){ n = snprint((char*)vendor, sizeof(vendor), "plan9_%s", conf.cputype); p = optaddvec(p, ODvendorclass, vendor, n); } p = optaddvec(p, ODparams, requested, nrequested); if(*conf.hostname && sendhostname) p = optaddstr(p, OBhostname, conf.hostname); break; case Release: ipmove(up->raddr, conf.server); v6tov4(bp.ciaddr, conf.laddr); p = optaddaddr(p, ODipaddr, conf.laddr); p = optaddaddr(p, ODserverid, conf.server); break; } *p++ = OBend; n = p - (uchar*)&bp; USED(n); /* * We use a maximum size DHCP packet to survive the * All_Aboard NAT package from Internet Share. It * always replies to DHCP requests with a packet of the * same size, so if the request is too short the reply * is truncated. */ if(write(conf.fd, &bp, sizeof(bp)) != sizeof(bp)) fprint(2, "dhcpsend: write failed: %r\n");}voiddhcprecv(void){ uchar buf[8000]; Bootp *bp; int i, n, type; ulong lease; char err[ERRMAX]; uchar vopts[256]; alarm(1000); n = read(conf.fd, buf, sizeof(buf)); alarm(0); if(n < 0){ errstr(err, sizeof err); if(strstr(err, "interrupt") == nil) fprint(2, "ipconfig: bad read: %s\n", err); else DEBUG("read timed out\n"); return; } bp = parsebootp(buf, n); if(bp == 0) { DEBUG("parsebootp failed: dropping packet\n"); return; } type = optgetbyte(bp->optdata, ODtype); switch(type) { default: fprint(2, "%s: unknown type: %d\n", argv0, type); break; case Offer: DEBUG("got offer from %V ", bp->siaddr); if(conf.state != Sselecting){ DEBUG("\n"); break; } lease = optgetulong(bp->optdata, ODlease); if(lease == 0){ /* * The All_Aboard NAT package from Internet Share doesn't * give a lease time, so we have to assume one. */ fprint(2, "%s: Offer with %lud lease, using %d\n", argv0, lease, MinLease); lease = MinLease; } DEBUG("lease=%lud ", lease); if(!optgetaddr(bp->optdata, ODserverid, conf.server)) { fprint(2, "%s: Offer from server with invalid serverid\n", argv0); break; } v4tov6(conf.laddr, bp->yiaddr); memmove(conf.sname, bp->sname, sizeof(conf.sname)); conf.sname[sizeof(conf.sname)-1] = 0; DEBUG("server=%I sname=%s\n", conf.server, conf.sname); conf.offered = lease; conf.state = Srequesting; dhcpsend(Request); conf.resend = 0; conf.timeout = time(0) + 4; break; case Ack: DEBUG("got ack from %V ", bp->siaddr); if(conf.state != Srequesting) if(conf.state != Srenewing) if(conf.state != Srebinding) break; // ignore a bad lease lease = optgetulong(bp->optdata, ODlease); if(lease == 0){ /* * The All_Aboard NAT package from Internet Share doesn't * give a lease time, so we have to assume one. */ fprint(2, "%s: Ack with %lud lease, using %d\n", argv0, lease, MinLease); lease = MinLease; } DEBUG("lease=%lud ", lease); // address and mask if(!validip(conf.laddr) || !Oflag) v4tov6(conf.laddr, bp->yiaddr); if(!validip(conf.mask) || !Oflag){ if(!optgetaddr(bp->optdata, OBmask, conf.mask)) ipmove(conf.mask, IPnoaddr); } DEBUG("ipaddr=%I ipmask=%M ", conf.laddr, conf.mask); // get a router address either from the router option // or from the router that forwarded the dhcp packet if(!validip(conf.gaddr) || !Oflag){ if(optgetaddr(bp->optdata, OBrouter, conf.gaddr)){ DEBUG("ipgw=%I ", conf.gaddr); } else { if(memcmp(bp->giaddr, IPnoaddr+IPv4off, IPv4addrlen) != 0){ v4tov6(conf.gaddr, bp->giaddr); DEBUG("giaddr=%I ", conf.gaddr); } } } else DEBUG("ipgw=%I ", conf.gaddr); // get dns servers memset(conf.dns, 0, sizeof(conf.dns)); n = optgetaddrs(bp->optdata, OBdnserver, conf.dns, sizeof(conf.dns)/IPaddrlen); for(i = 0; i < n; i++) DEBUG("dns=%I ", conf.dns+i*IPaddrlen); // get ntp servers memset(conf.ntp, 0, sizeof(conf.ntp)); n = optgetaddrs(bp->optdata, OBntpserver, conf.ntp, sizeof(conf.ntp)/IPaddrlen); for(i = 0; i < n; i++) DEBUG("ntp=%I ", conf.ntp+i*IPaddrlen); // get names optgetstr(bp->optdata, OBhostname, conf.hostname, sizeof(conf.hostname)); optgetstr(bp->optdata, OBdomainname, conf.domainname, sizeof(conf.domainname)); // get anything else we asked for getoptions(bp->optdata); // get plan9 specific options n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof(vopts)-1); if(n > 0 && parseoptions(vopts, n) == 0){ if(validip(conf.fs) && Oflag) n = 1; else n = optgetaddrs(vopts, OP9fs, conf.fs, 2); for(i = 0; i < n; i++) DEBUG("fs=%I ", conf.fs+i*IPaddrlen); if(validip(conf.auth) && Oflag) n = 1; else n = optgetaddrs(vopts, OP9auth, conf.auth, 2); for(i = 0; i < n; i++) DEBUG("auth=%I ", conf.auth+i*IPaddrlen); } conf.lease = lease; conf.state = Sbound; DEBUG("server=%I sname=%s\n", conf.server, conf.sname); break; case Nak: conf.state = Sinit; fprint(2, "%s: recved dhcpnak on %s\n", argv0, conf.mpoint); break; }}intopenlisten(){ int fd, cfd; char data[128]; char devdir[40]; int n; if(validip(conf.laddr) && (conf.state == Srenewing || conf.state == Srebinding)) sprint(data, "%s/udp!%I!68", conf.mpoint, conf.laddr); else sprint(data, "%s/udp!*!68", conf.mpoint); for(n=0;;n++) { cfd = announce(data, devdir); if(cfd >= 0) break; if(!noconfig) sysfatal("can't announce for dhcp: %r"); // might be another client - wait and try again fprint(2, "%s: can't announce: %r\n", argv0); sleep((nrand(10)+1)*1000); if(n > 10) return -1; } if(fprint(cfd, "headers") < 0) sysfatal("can't set header mode: %r"); fprint(cfd, "oldheaders");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -