📄 ipconfig.c
字号:
#include <u.h>#include <libc.h>#include <ip.h>#include <bio.h>#include <ndb.h>#include "dhcp.h"int noconfig;int debug;int dodhcp;int nip;int myifc = -1;int plan9 = 1;int beprimary = -1;int nodhcpwatch;int sendhostname;int dondbconfig = 0;int Oflag;char *ndboptions;Ipifc *ifc;// possible verbsenum{ Vadd, Vremove, Vunbind, Vether, Vloopback,};struct { // locally generated char *type; char *dev; char mpoint[32]; int cfd; // ifc control channel 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;enum{ Taddr, Taddrs, Tstr, Tbyte, Tulong, Tvec,};typedef struct Option Option;struct Option{ char *name; int type;};// I was too lazy to look up the types for each of these// options. If someone feels like it, please mail me a// corrected array -- presottoOption option[256] ={[OBmask] { "ipmask", Taddr },[OBtimeoff] { "timeoff", Tulong },[OBrouter] { "ipgw", Taddrs },[OBtimeserver] { "time", Taddrs },[OBnameserver] { "name", Taddrs },[OBdnserver] { "dns", Taddrs },[OBlogserver] { "log", Taddrs },[OBcookieserver] { "cookie", Taddrs },[OBlprserver] { "lpr", Taddrs },[OBimpressserver] { "impress", Taddrs },[OBrlserver] { "rl", Taddrs },[OBhostname] { "sys", Tstr },[OBbflen] { "bflen", Tulong },[OBdumpfile] { "dumpfile", Tstr },[OBdomainname] { "dom", Tstr },[OBswapserver] { "swap", Taddrs },[OBrootpath] { "rootpath", Tstr },[OBextpath] { "extpath", Tstr },[OBipforward] { "ipforward", Taddrs },[OBnonlocal] { "nonlocal", Taddrs },[OBpolicyfilter] { "policyfilter", Taddrs },[OBmaxdatagram] { "maxdatagram", Tulong },[OBttl] { "ttl", Tulong },[OBpathtimeout] { "pathtimeout", Taddrs },[OBpathplateau] { "pathplateau", Taddrs },[OBmtu] { "mtu", Tulong },[OBsubnetslocal] { "subnetslocal", Taddrs },[OBbaddr] { "baddr", Taddrs },[OBdiscovermask] { "discovermask", Taddrs },[OBsupplymask] { "supplymask", Taddrs },[OBdiscoverrouter] { "discoverrouter", Taddrs },[OBrsserver] { "rs", Taddrs },[OBstaticroutes] { "staticroutes", Taddrs },[OBtrailerencap] { "trailerencap", Taddrs },[OBarptimeout] { "arptimeout", Tulong },[OBetherencap] { "etherencap", Taddrs },[OBtcpttl] { "tcpttl", Tulong },[OBtcpka] { "tcpka", Tulong },[OBtcpkag] { "tcpkag", Tulong },[OBnisdomain] { "nisdomain", Tstr },[OBniserver] { "ni", Taddrs },[OBntpserver] { "ntp", Taddrs },[OBnetbiosns] { "netbiosns", Taddrs },[OBnetbiosdds] { "netbiosdds", Taddrs },[OBnetbiostype] { "netbiostype", Taddrs },[OBnetbiosscope] { "netbiosscope", Taddrs },[OBxfontserver] { "xfont", Taddrs },[OBxdispmanager] { "xdispmanager", Taddrs },[OBnisplusdomain] { "nisplusdomain", Tstr },[OBnisplusserver] { "nisplus", Taddrs },[OBhomeagent] { "homeagent", Taddrs },[OBsmtpserver] { "smtp", Taddrs },[OBpop3server] { "pop3", Taddrs },[OBnntpserver] { "nntp", Taddrs },[OBwwwserver] { "www", Taddrs },[OBfingerserver] { "finger", Taddrs },[OBircserver] { "irc", Taddrs },[OBstserver] { "st", Taddrs },[OBstdaserver] { "stdar", Taddrs },[ODipaddr] { "ipaddr", Taddr },[ODlease] { "lease", Tulong },[ODoverload] { "overload", Taddr },[ODtype] { "type", Tbyte },[ODserverid] { "serverid", Taddr },[ODparams] { "params", Tvec },[ODmessage] { "message", Tstr },[ODmaxmsg] { "maxmsg", Tulong },[ODrenewaltime] { "renewaltime", Tulong },[ODrebindingtime] { "rebindingtime", Tulong },[ODvendorclass] { "vendorclass", Tvec },[ODclientid] { "clientid", Tvec },[ODtftpserver] { "tftp", Taddr },[ODbootfile] { "bootfile", Tstr },};uchar defrequested[] = { OBmask, OBrouter, OBdnserver, OBhostname, OBdomainname, OBntpserver,};uchar requested[256];int nrequested;void adddefroute(char*, uchar*);int addoption(char*);void binddevice(void);void bootprequest(void);void controldevice(void);void dhcpquery(int, int);void dhcprecv(void);void dhcpsend(int);int dhcptimer(void);void dhcpwatch(int);void doadd(int);void doremove(void);void dounbind(void);int getndb(void);void getoptions(uchar*);int ipconfig(void);void lookforip(char*);void mkclientid(void);void ndbconfig(void);int nipifcs(char*);int openlisten(void);uchar* optadd(uchar*, int, void*, int);uchar* optaddaddr(uchar*, int, uchar*);uchar* optaddbyte(uchar*, int, int);uchar* optaddstr(uchar*, int, char*);uchar* optaddulong(uchar*, int, ulong);uchar* optaddvec(uchar*, int, uchar*, int);uchar* optget(uchar*, int, int*);int optgetaddr(uchar*, int, uchar*);int optgetaddrs(uchar*, int, uchar*, int);int optgetbyte(uchar*, int);int optgetstr(uchar*, int, char*, int);ulong optgetulong(uchar*, int);int optgetvec(uchar*, int, uchar*, int);char* optgetx(uchar*, uchar);Bootp* parsebootp(uchar*, int);int parseoptions(uchar *p, int n);int parseverb(char*);void putndb(void);void tweakservers(void);void usage(void);int validip(uchar*);void writendb(char*, int, int);char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 };#define DEBUG if(debug)printtypedef struct Ctl Ctl;struct Ctl{ Ctl *next; char *ctl;};Ctl *firstctl, **ctll;voidusage(void){ fprint(2, "usage: %s [-ndDrGX] [-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, action; 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; // init set of requested parameters with the default nrequested = sizeof(defrequested); memcpy(requested, defrequested, nrequested); ARGBEGIN { case 'D': debug = 1; break; case 'G': plan9 = 0; break; case 'N': dondbconfig = 1; break; case 'O': Oflag = 1; break; case 'p': beprimary = 1; break; case 'P': beprimary = 0; case 'b': p = ARGF(); if(p == nil) usage(); conf.baud = p; break; 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': dodhcp = 1; break; case 'g': p = ARGF(); if(p == nil) usage(); parseip(conf.gaddr, p); break; case 'h': p = ARGF(); if(p == nil) usage(); snprint(conf.hostname, sizeof(conf.hostname), "%s", p); sendhostname = 1; break; case 'n': noconfig = 1; break; case 'm': p = ARGF(); if(p == nil) usage(); conf.mtu = atoi(p); break; case 'r': retry = 1; break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(conf.mpoint, sizeof(conf.mpoint), p); break; case 'X': nodhcpwatch = 1; break; case 'o': if(addoption(ARGF()) < 0) usage(); break; } ARGEND; // default to any host name we already have if(*conf.hostname == 0){ p = getenv("sysname"); if(p == nil || *p == 0) p = sysname(); if(p != nil) strncpy(conf.hostname, p, sizeof(conf.hostname)-1); } // default conf.type = "ether"; conf.dev = "/net/ether0"; action = Vadd; // get verb, default is "add" while(argc > 0){ verb = parseverb(argv[0]); switch(verb){ case Vadd: case Vremove: case Vunbind: action = verb; break; case Vether: case Vloopback: conf.type = argv[0]; if(argc > 1){ conf.dev = argv[1]; argc--, argv++; } break; } if(verb < 0) break; argc--, argv++; } // 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: if(strcmp(argv[1], "0") != 0) parseipmask(conf.mask, argv[1]); /* fall through */ case 1: parseip(conf.laddr, argv[0]); break; } switch(action){ case Vadd: doadd(retry); break; case Vremove: doremove(); break; case Vunbind: dounbind(); break; } exits(0);}inthavendb(char *net){ Dir *d; char buf[128]; snprint(buf, sizeof buf, "%s/ndb", net); if((d = dirstat("/net/ndb")) == nil) return 0; if(d->length == 0){ free(d); return 0; } free(d); return 1;}voiddoadd(int retry){ int tries; // get number of preexisting interfaces nip = nipifcs(conf.mpoint); if(beprimary == -1 && (nip == 0 || !havendb(conf.mpoint))) beprimary = 1; // get ipifc into name space and condition device for ip if(!noconfig){ lookforip(conf.mpoint); controldevice(); binddevice(); } if(!validip(conf.laddr)){ if(dondbconfig) ndbconfig(); else 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(beprimary == 1){ 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 %M", 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; if(isv4(gaddr)) fprint(cfd, "add 0 0 %I", gaddr); else fprint(cfd, "add :: :: %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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -