#include <u.h>#include <libc.h>#include <ip.h>#include "dhcp.h" int noconfig;int debug;int dodhcp;int nip;int myifc;int plan9 = 1;Ipifc *ifc; // possible verbsenum{ Vadd, Vremove, Vunbind}; struct { // locally generated char *type; char *dev; char mpoint[32]; int cfd; // ifc control channel int dfd; // ifc data channel (for ppp) char *cputype; uchar hwa[32]; // hardware address int hwatype; int hwalen; uchar cid[32]; int cidlen; char *baud; // learned info uchar gaddr[IPaddrlen]; uchar laddr[IPaddrlen]; uchar mask[IPaddrlen]; uchar raddr[IPaddrlen]; uchar dns[2*IPaddrlen]; uchar fs[2*IPaddrlen]; uchar auth[2*IPaddrlen]; uchar ntp[IPaddrlen]; int mtu; // dhcp specific int state; int fd; ulong xid; ulong starttime; char sname[64]; char hostname[32]; char domainname[64]; uchar server[IPaddrlen]; /* server IP address */ ulong offered; /* offered lease time */ ulong lease; /* lease time */ ulong resend; /* number of resends for current state */ ulong timeout; /* time to timeout - seconds */} conf; void adddefroute(char*, uchar*);void binddevice(void);void controldevice(void);void bootprequest(void);void dhcprecv(void);void dhcpsend(int);int dhcptimer(void);void dhcpquery(int, int);void dhcpwatch(int);int getndb(void);int ipconfig(void);void lookforip(char*);uchar *optadd(uchar*, int, void*, int);uchar *optaddbyte(uchar*, int, int);uchar *optaddulong(uchar*, int, ulong);uchar *optaddaddr(uchar*, int, uchar*);uchar *optaddstr(uchar*, int, char*);uchar *optaddvec(uchar*, int, uchar*, int);uchar *optget(uchar*, int, int*);int optgetbyte(uchar*, int);ulong optgetulong(uchar*, int);int optgetaddr(uchar*, int, uchar*);int optgetaddrs(uchar*, int, uchar*, int);int optgetstr(uchar*, int, char*, int);int optgetvec(uchar*, int, uchar*, int);void mkclientid(void);int nipifcs(char*);int openlisten(void);int parseoptions(uchar *p, int n);Bootp *parsebootp(uchar*, int);void putndb(void);void tweakservers(void);void writendb(char*, int, int);void usage(void);int validip(uchar*);int parseverb(char*);void doadd(int);void doremove(void);void dounbind(void); char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 }; #define DEBUG if(debug)print typedef struct Ctl Ctl;struct Ctl{ Ctl *next; char *ctl;};Ctl *firstctl, **ctll; voidusage(void){ fprint(2, "usage: %s [-ndDrG] [-x netmtpt] [-m mtu] [-b baud] [-g gateway] [-h hostname] [-c control-string]* type device [verb] [localaddr [mask [remoteaddr [fsaddr [authaddr]]]]]\n", argv0); exits("usage");} voidmain(int argc, char **argv){ char *p; int retry, verb; Ctl *cp; srand(truerand()); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('V', eipfmt); setnetmtpt(conf.mpoint, sizeof(conf.mpoint), nil); conf.cputype = getenv("cputype"); if(conf.cputype == nil) conf.cputype = "386"; retry = 0; ctll = &firstctl; ARGBEGIN { case 'c': p = ARGF(); if(p == nil) usage(); cp = malloc(sizeof(*cp)); if(cp == nil) sysfatal("%r"); *ctll = cp; ctll = &cp->next; cp->next = nil; cp->ctl = p; break; case 'D': debug = 1; break; case 'd': dodhcp = 1; break; case 'h': p = ARGF(); if(p == nil) usage(); snprint(conf.hostname, sizeof(conf.hostname), "%s", p); break; case 'n': noconfig = 1; break; case 'm': p = ARGF(); if(p == nil) usage(); conf.mtu = atoi(p); break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(conf.mpoint, sizeof(conf.mpoint), p); break; case 'g': p = ARGF(); if(p == nil) usage(); parseip(conf.gaddr, p); break; case 'b': p = ARGF(); if(p == nil) usage(); conf.baud = p; break; case 'r': retry = 1; break; case 'G': plan9 = 0; break; } ARGEND; // get medium, default is ether switch(argc){ default: conf.dev = argv[1]; conf.type = argv[0]; argc -= 2; argv += 2; break; case 1: conf.type = argv[0]; if(strcmp(conf.type, "ether") == 0) conf.dev = "/net/ether0"; else if(strcmp(conf.type, "ppp") == 0) conf.dev = "/dev/eia0"; else usage(); argc -= 1; argv += 1; break; case 0: conf.type = "ether"; conf.dev = "/net/ether0"; break; } // get verb, default is "add" verb = Vadd; if(argc > 0){ verb = parseverb(argv[0]); if(verb >= 0){ argc--; argv++; } else verb = Vadd; } // get addresses switch(argc){ case 5: parseip(conf.auth, argv[4]); /* fall through */ case 4: parseip(conf.fs, argv[3]); /* fall through */ case 3: parseip(conf.raddr, argv[2]); /* fall through */ case 2: parseipmask(conf.mask, argv[1]); /* fall through */ case 1: parseip(conf.laddr, argv[0]); break; } switch(verb){ case Vadd: doadd(retry); break; case Vremove: doremove(); break; case Vunbind: dounbind(); break; } exits(0);} voiddoadd(int retry){ int tries; // get number of preexisting interfaces nip = nipifcs(conf.mpoint); // get ipifc into name space and condition device for ip if(!noconfig){ lookforip(conf.mpoint); controldevice(); binddevice(); } if(!validip(conf.laddr) && strcmp(conf.type, "ppp") != 0) dodhcp = 1; // run dhcp if we need something if(dodhcp){ mkclientid(); for(tries = 0; tries < 6; tries++){ dhcpquery(!noconfig, Sselecting); if(conf.state == Sbound) break; sleep(1000); } } if(!validip(conf.laddr)){ if(retry && dodhcp && !noconfig){ fprint(2, "%s: couldn't determine ip address, retrying\n", argv0); dhcpwatch(1); return; } else { fprint(2, "%s: no success with DHCP\n", argv0); exits("failed"); } } if(!noconfig){ if(ipconfig() < 0) sysfatal("can't start ip"); if(dodhcp && conf.lease != Lforever) dhcpwatch(0); } // leave everything we've learned somewhere other procs can find it if(nip == 0){ putndb(); tweakservers(); }} voiddoremove(void){ char file[128]; int cfd; Ipifc *nifc; Iplifc *lifc; if(!validip(conf.laddr)){ fprint(2, "%s: remove requires an address\n", argv0); exits("usage"); } ifc = readipifc(conf.mpoint, ifc, -1); for(nifc = ifc; nifc != nil; nifc = nifc->next){ if(strcmp(nifc->dev, conf.dev) != 0) continue; for(lifc = nifc->lifc; lifc != nil; lifc = lifc->next){ if(ipcmp(conf.laddr, lifc->ip) != 0) continue; if(validip(conf.mask) && ipcmp(conf.mask, lifc->mask) != 0) continue; if(validip(conf.raddr) && ipcmp(conf.raddr, lifc->net) != 0) continue; snprint(file, sizeof(file), "%s/ipifc/%d/ctl", conf.mpoint, nifc->index); cfd = open(file, ORDWR); if(cfd < 0){ fprint(2, "%s: can't open %s: %r\n", argv0, conf.mpoint); continue; } if(fprint(cfd, "remove %I %I", lifc->ip, lifc->mask) < 0) fprint(2, "%s: can't remove %I %I from %s: %r\n", argv0, lifc->ip, lifc->mask, file); } }} voiddounbind(void){ Ipifc *nifc; char file[128]; int cfd; ifc = readipifc(conf.mpoint, ifc, -1); for(nifc = ifc; nifc != nil; nifc = nifc->next){ if(strcmp(nifc->dev, conf.dev) == 0){ snprint(file, sizeof(file), "%s/ipifc/%d/ctl", conf.mpoint, nifc->index); cfd = open(file, ORDWR); if(cfd < 0){ fprint(2, "%s: can't open %s: %r\n", argv0, conf.mpoint); break; } if(fprint(cfd, "unbind") < 0) fprint(2, "%s: can't unbind from %s: %r\n", argv0, file); break; } }} // set the default routevoidadddefroute(char *mpoint, uchar *gaddr){ char buf[256]; int cfd; sprint(buf, "%s/iproute", mpoint); cfd = open(buf, ORDWR); if(cfd < 0) return; fprint(cfd, "add 0 0 %I", gaddr); close(cfd);} // create a client idvoidmkclientid(void){ if(strcmp(conf.type, "ether") == 0) if(myetheraddr(conf.hwa, conf.dev) == 0){ conf.hwalen = 6; conf.hwatype = 1; conf.cid[0] = conf.hwatype; memmove(&conf.cid[1], conf.hwa, conf.hwalen); conf.cidlen = conf.hwalen+1; } 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]; int ac, pid; char *av[12]; Waitmsg *w; if(strcmp(conf.type, "ppp") == 0){ // ppp does the binding // start with an empty config file if(nip == 0) writendb("", 0, 0); switch(pid = rfork(RFPROC|RFFDG|RFMEM)){ case -1: sysfatal("can't start ppp: %r"); break; case 0: ac = 0; av[ac++] = "ppp"; av[ac++] = "-uf"; av[ac++] = "-p"; av[ac++] = conf.dev; av[ac++] = "-x"; av[ac++] = conf.mpoint; if(conf.baud != nil){ av[ac++] = "-b"; av[ac++] = conf.baud; } av[ac] = 0; exec("/bin/ip/ppp", av); exec("/ppp", av); sysfatal("execing /ppp: %r"); default: break; } // wait for ppp to finish connecting and configuringLines 1–500 of 1454. Load more
#include <u.h> #include <libc.h> #include <ip.h> #include "dhcp.h" int noconfig; int debug; int dodhcp; int nip; int myifc; int plan9 = 1; Ipifc *ifc; // possible verbs enum { Vadd, Vremove, Vunbind }; struct { // locally generated char *type; char *dev; char mpoint[32]; int cfd; // ifc control channel int dfd; // ifc data channel (for ppp) char *cputype; uchar hwa[32]; // hardware address int hwatype; int hwalen; uchar cid[32]; int cidlen; char *baud; // learned info uchar gaddr[IPaddrlen]; uchar laddr[IPaddrlen]; uchar mask[IPaddrlen]; uchar raddr[IPaddrlen]; uchar dns[2*IPaddrlen]; uchar fs[2*IPaddrlen]; uchar auth[2*IPaddrlen]; uchar ntp[IPaddrlen]; int mtu; // dhcp specific int state; int fd; ulong xid; ulong starttime; char sname[64]; char hostname[32]; char domainname[64]; uchar server[IPaddrlen]; /* server IP address */ ulong offered; /* offered lease time */ ulong lease; /* lease time */ ulong resend; /* number of resends for current state */ ulong timeout; /* time to timeout - seconds */ } conf; void adddefroute(char*, uchar*); void binddevice(void); void controldevice(void); void bootprequest(void); void dhcprecv(void); void dhcpsend(int); int dhcptimer(void); void dhcpquery(int, int); void dhcpwatch(int); int getndb(void); int ipconfig(void); void lookforip(char*); uchar *optadd(uchar*, int, void*, int); uchar *optaddbyte(uchar*, int, int); uchar *optaddulong(uchar*, int, ulong); uchar *optaddaddr(uchar*, int, uchar*); uchar *optaddstr(uchar*, int, char*); uchar *optaddvec(uchar*, int, uchar*, int); uchar *optget(uchar*, int, int*); int optgetbyte(uchar*, int); ulong optgetulong(uchar*, int); int optgetaddr(uchar*, int, uchar*); int optgetaddrs(uchar*, int, uchar*, int); int optgetstr(uchar*, int, char*, int); int optgetvec(uchar*, int, uchar*, int); void mkclientid(void); int nipifcs(char*); int openlisten(void); int parseoptions(uchar *p, int n); Bootp *parsebootp(uchar*, int); void putndb(void); void tweakservers(void); void writendb(char*, int, int); void usage(void); int validip(uchar*); int parseverb(char*); void doadd(int); void doremove(void); void dounbind(void); char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 }; #define DEBUG if(debug)print typedef struct Ctl Ctl; struct Ctl { Ctl *next; char *ctl; }; Ctl *firstctl, **ctll; void usage(void) { fprint(2, "usage: %s [-ndDrG] [-x netmtpt] [-m mtu] [-b baud] [-g gateway] [-h hostname] [-c control-string]* type device [verb] [localaddr [mask [remoteaddr [fsaddr [authaddr]]]]]\n", argv0); exits("usage"); } void main(int argc, char **argv) { char *p; int retry, verb; Ctl *cp; srand(truerand()); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('V', eipfmt); setnetmtpt(conf.mpoint, sizeof(conf.mpoint), nil); conf.cputype = getenv("cputype"); if(conf.cputype == nil) conf.cputype = "386"; retry = 0; ctll = &firstctl; ARGBEGIN { case 'c': p = ARGF(); if(p == nil) usage(); cp = malloc(sizeof(*cp)); if(cp == nil) sysfatal("%r"); *ctll = cp; ctll = &cp->next; cp->next = nil; cp->ctl = p; break; case 'D': debug = 1; break; case 'd': dodhcp = 1; break; case 'h': p = ARGF(); if(p == nil) usage(); snprint(conf.hostname, sizeof(conf.hostname), "%s", p); break; case 'n': noconfig = 1; break; case 'm': p = ARGF(); if(p == nil) usage(); conf.mtu = atoi(p); break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(conf.mpoint, sizeof(conf.mpoint), p); break; case 'g': p = ARGF(); if(p == nil) usage(); parseip(conf.gaddr, p); break; case 'b': p = ARGF(); if(p == nil) usage(); conf.baud = p; break; case 'r': retry = 1; break; case 'G': plan9 = 0; break; } ARGEND; // get medium, default is ether switch(argc){ default: conf.dev = argv[1]; conf.type = argv[0]; argc -= 2; argv += 2; break; case 1: conf.type = argv[0]; if(strcmp(conf.type, "ether") == 0) conf.dev = "/net/ether0"; else if(strcmp(conf.type, "ppp") == 0) conf.dev = "/dev/eia0"; else usage(); argc -= 1; argv += 1; break; case 0: conf.type = "ether"; conf.dev = "/net/ether0"; break; } // get verb, default is "add" verb = Vadd; if(argc > 0){ verb = parseverb(argv[0]); if(verb >= 0){ argc--; argv++; } else verb = Vadd; } // get addresses switch(argc){ case 5: parseip(conf.auth, argv[4]); /* fall through */ case 4: parseip(conf.fs, argv[3]); /* fall through */ case 3: parseip(conf.raddr, argv[2]); /* fall through */ case 2: parseipmask(conf.mask, argv[1]); /* fall through */ case 1: parseip(conf.laddr, argv[0]); break; } switch(verb){ case Vadd: doadd(retry); break; case Vremove: doremove(); break; case Vunbind: dounbind(); break; } exits(0); } void doadd(int retry) { int tries; // get number of preexisting interfaces nip = nipifcs(conf.mpoint); // get ipifc into name space and condition device for ip if(!noconfig){ lookforip(conf.mpoint); controldevice(); binddevice(); } if(!validip(conf.laddr) && strcmp(conf.type, "ppp") != 0) dodhcp = 1; // run dhcp if we need something if(dodhcp){ mkclientid(); for(tries = 0; tries < 6; tries++){ dhcpquery(!noconfig, Sselecting); if(conf.state == Sbound) break; sleep(1000); } } if(!validip(conf.laddr)){ if(retry && dodhcp && !noconfig){ fprint(2, "%s: couldn't determine ip address, retrying\n", argv0); dhcpwatch(1); return; } else { fprint(2, "%s: no success with DHCP\n", argv0); exits("failed"); } } if(!noconfig){ if(ipconfig() < 0) sysfatal("can't start ip"); if(dodhcp && conf.lease != Lforever) dhcpwatch(0); } // leave everything we've learned somewhere other procs can find it if(nip == 0){ putndb(); tweakservers(); } } void doremove(void) { char file[128]; int cfd; Ipifc *nifc; Iplifc *lifc; if(!validip(conf.laddr)){ fprint(2, "%s: remove requires an address\n", argv0); exits("usage"); } ifc = readipifc(conf.mpoint, ifc, -1); for(nifc = ifc; nifc != nil; nifc = nifc->next){ if(strcmp(nifc->dev, conf.dev) != 0) continue; for(lifc = nifc->lifc; lifc != nil; lifc = lifc->next){ if(ipcmp(conf.laddr, lifc->ip) != 0) continue; if(validip(conf.mask) && ipcmp(conf.mask, lifc->mask) != 0) continue; if(validip(conf.raddr) && ipcmp(conf.raddr, lifc->net) != 0) continue; snprint(file, sizeof(file), "%s/ipifc/%d/ctl", conf.mpoint, nifc->index); cfd = open(file, ORDWR); if(cfd < 0){ fprint(2, "%s: can't open %s: %r\n", argv0, conf.mpoint); continue; } if(fprint(cfd, "remove %I %I", lifc->ip, lifc->mask) < 0) fprint(2, "%s: can't remove %I %I from %s: %r\n", argv0, lifc->ip, lifc->mask, file); } } } void dounbind(void) { Ipifc *nifc; char file[128]; int cfd; ifc = readipifc(conf.mpoint, ifc, -1); for(nifc = ifc; nifc != nil; nifc = nifc->next){ if(strcmp(nifc->dev, conf.dev) == 0){ snprint(file, sizeof(file), "%s/ipifc/%d/ctl", conf.mpoint, nifc->index); cfd = open(file, ORDWR); if(cfd < 0){ fprint(2, "%s: can't open %s: %r\n", argv0, conf.mpoint); break; } if(fprint(cfd, "unbind") < 0) fprint(2, "%s: can't unbind from %s: %r\n", argv0, file); break; } } } // set the default route void adddefroute(char *mpoint, uchar *gaddr) { char buf[256]; int cfd; sprint(buf, "%s/iproute", mpoint); cfd = open(buf, ORDWR); if(cfd < 0) return; fprint(cfd, "add 0 0 %I", gaddr); close(cfd); } // create a client id void mkclientid(void) { if(strcmp(conf.type, "ether") == 0) if(myetheraddr(conf.hwa, conf.dev) == 0){ conf.hwalen = 6; conf.hwatype = 1; conf.cid[0] = conf.hwatype; memmove(&conf.cid[1], conf.hwa, conf.hwalen); conf.cidlen = conf.hwalen+1; } 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 namespace void lookforip(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 device void controldevice(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 open void binddevice(void) { char buf[256]; int ac, pid; char *av[12]; Waitmsg *w; if(strcmp(conf.type, "ppp") == 0){ // ppp does the binding // start with an empty config file if(nip == 0) writendb("", 0, 0); switch(pid = rfork(RFPROC|RFFDG|RFMEM)){ case -1: sysfatal("can't start ppp: %r"); break; case 0: ac = 0; av[ac++] = "ppp"; av[ac++] = "-uf"; av[ac++] = "-p"; av[ac++] = conf.dev; av[ac++] = "-x"; av[ac++] = conf.mpoint; if(conf.baud != nil){ av[ac++] = "-b"; av[ac++] = conf.baud; } av[ac] = 0; exec("/bin/ip/ppp", av); exec("/ppp", av); sysfatal("execing /ppp: %r"); default: break; } // wait for ppp to finish connecting and configuring