/* * ipconfig - configure parameters of an ip stack */#include <u.h>#include <libc.h>#include <ip.h>#include <bio.h>#include <ndb.h>#include "../dhcp.h"#include "ipconfig.h" #define DEBUG if(debug)warning /* possible verbs */enum{ /* commands */ Vadd, Vremove, Vunbind, Vaddpref6, Vra6, /* media */ Vether, Vgbe, Vppp, Vloopback, Vtorus, Vtree, Vpkt,}; 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 -- presotto */Option 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; int Oflag;int beprimary = -1;Conf conf;int debug;int dodhcp;int dolog;int dondbconfig = 0;int dupl_disc = 1; /* flag: V6 duplicate neighbor discovery */Ctl *firstctl, **ctll;Ipifc *ifc;int ipv6auto = 0;int myifc = -1;char *ndboptions;int nip;int noconfig;int nodhcpwatch;char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 };int plan9 = 1;int sendhostname; static char logfile[] = "ipconfig"; char *verbs[] = {[Vadd] "add",[Vremove] "remove",[Vunbind] "unbind",[Vether] "ether",[Vgbe] "gbe",[Vppp] "ppp",[Vloopback] "loopback",[Vaddpref6] "add6",[Vra6] "ra6",[Vtorus] "torus",[Vtree] "tree",[Vpkt] "pkt",}; 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 ip4cfg(void);int ip6cfg(int a);void lookforip(char*);void mkclientid(void);void ndbconfig(void);int nipifcs(char*);int openlisten(void);uchar* optaddaddr(uchar*, int, uchar*);uchar* optaddbyte(uchar*, int, int);uchar* optaddstr(uchar*, int, char*);uchar* optadd(uchar*, int, void*, int);uchar* optaddulong(uchar*, int, ulong);uchar* optaddvec(uchar*, int, uchar*, int);int optgetaddrs(uchar*, int, uchar*, int);int optgetp9addrs(uchar*, int, uchar*, int);int optgetaddr(uchar*, int, uchar*);int optgetbyte(uchar*, int);int optgetstr(uchar*, int, char*, int);uchar* optget(uchar*, int, 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 pppbinddev(void);void putndb(void);void tweakservers(void);void usage(void);int validip(uchar*);void writendb(char*, int, int); voidusage(void){ fprint(2, "usage: %s [-6dDGnNOpPruX][-b baud][-c ctl]* [-g gw]" "[-h host][-m mtu]\n" "\t[-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask " "[raddr [fs [auth]]]]]\n", argv0); exits("usage");} voidwarning(char *fmt, ...){ char buf[1024]; va_list arg; va_start(arg, fmt); vseprint(buf, buf + sizeof buf, fmt, arg); va_end(arg); if (dolog) syslog(0, logfile, "%s", buf); else fprint(2, "%s: %s\n", argv0, buf);} static voidparsenorm(int argc, char **argv){ switch(argc){ case 5: if (parseip(conf.auth, argv[4]) == -1) usage(); /* fall through */ case 4: if (parseip(conf.fs, argv[3]) == -1) usage(); /* fall through */ case 3: if (parseip(conf.raddr, argv[2]) == -1) usage(); /* fall through */ case 2: /* * can't test for parseipmask()==-1 cuz 255.255.255.255 * looks like that. */ if (strcmp(argv[1], "0") != 0) parseipmask(conf.mask, argv[1]); /* fall through */ case 1: if (parseip(conf.laddr, argv[0]) == -1) usage(); /* fall through */ case 0: break; default: usage(); }} static voidparse6pref(int argc, char **argv){ switch(argc){ case 6: conf.preflt = strtoul(argv[5], 0, 10); /* fall through */ case 5: conf.validlt = strtoul(argv[4], 0, 10); /* fall through */ case 4: conf.autoflag = (atoi(argv[3]) != 0); /* fall through */ case 3: conf.onlink = (atoi(argv[2]) != 0); /* fall through */ case 2: conf.prefixlen = atoi(argv[1]); /* fall through */ case 1: if (parseip(conf.v6pref, argv[0]) == -1) sysfatal("bad address %s", argv[0]); break; } DEBUG("parse6pref: pref %I len %d", conf.v6pref, conf.prefixlen);} /* parse router advertisement (keyword, value) pairs */static voidparse6ra(int argc, char **argv){ int i, argsleft; char *kw, *val; if (argc % 2 != 0) usage(); i = 0; for (argsleft = argc; argsleft > 1; argsleft -= 2) { kw = argv[i]; val = argv[i+1]; if (strcmp(kw, "recvra") == 0) conf.recvra = (atoi(val) != 0); else if (strcmp(kw, "sendra") == 0) conf.sendra = (atoi(val) != 0); else if (strcmp(kw, "mflag") == 0) conf.mflag = (atoi(val) != 0); else if (strcmp(kw, "oflag") == 0) conf.oflag = (atoi(val) != 0); else if (strcmp(kw, "maxraint") == 0) conf.maxraint = atoi(val); else if (strcmp(kw, "minraint") == 0) conf.minraint = atoi(val); else if (strcmp(kw, "linkmtu") == 0) conf.linkmtu = atoi(val); else if (strcmp(kw, "reachtime") == 0) conf.reachtime = atoi(val); else if (strcmp(kw, "rxmitra") == 0) conf.rxmitra = atoi(val); else if (strcmp(kw, "ttl") == 0) conf.ttl = atoi(val); else if (strcmp(kw, "routerlt") == 0) conf.routerlt = atoi(val); else { warning("bad ra6 keyword %s", kw); usage(); } i += 2; } /* consistency check */ if (conf.maxraint < conf.minraint) sysfatal("maxraint %d < minraint %d", conf.maxraint, conf.minraint);} static voidinit(void){ srand(truerand()); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('V', eipfmt); nsec(); /* make sure time file is open before forking */ setnetmtpt(conf.mpoint, sizeof conf.mpoint, nil); conf.cputype = getenv("cputype"); if(conf.cputype == nil) conf.cputype = "386"; ctll = &firstctl; v6paraminit(&conf); /* init set of requested dhcp parameters with the default */ nrequested = sizeof defrequested; memcpy(requested, defrequested, nrequested);} static intparseargs(int argc, char **argv){ char *p; int action, verb; /* 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); } /* defaults */ conf.type = "ether"; conf.dev = "/net/ether0"; action = Vadd; /* get optional medium and device */ if (argc > 0){ verb = parseverb(*argv); switch(verb){ case Vether: case Vgbe: case Vppp: case Vloopback: case Vtorus: case Vtree: case Vpkt: conf.type = *argv++; argc--; if(argc > 0){ conf.dev = *argv++; argc--; } else if(verb == Vppp) conf.dev = "/dev/eia0"; break; } } /* get optional verb */ if (argc > 0){ verb = parseverb(*argv); switch(verb){ case Vether: case Vgbe: case Vppp: case Vloopback: case Vtorus: case Vtree: case Vpkt: sysfatal("medium %s already specified", conf.type); case Vadd: case Vremove: case Vunbind: case Vaddpref6: case Vra6: argv++; argc--; action = verb; break; } } /* get verb-dependent arguments */ switch (action) { case Vadd: case Vremove: case Vunbind: parsenorm(argc, argv); break; case Vaddpref6: parse6pref(argc, argv); break; case Vra6: parse6ra(argc, argv); break; } return action;} voidmain(int argc, char **argv){ int retry, action; Ctl *cp; init(); retry = 0; ARGBEGIN { case '6': /* IPv6 auto config */ ipv6auto = 1; break; case 'b': conf.baud = EARGF(usage()); break; case 'c': cp = malloc(sizeof *cp); if(cp == nil) sysfatal("%r"); *ctll = cp; ctll = &cp->next; cp->next = nil; cp->ctl = EARGF(usage()); break; case 'd': dodhcp = 1; break; case 'D': debug = 1; break; case 'g': if (parseip(conf.gaddr, EARGF(usage())) == -1) usage(); break; case 'G':Lines 1–500 of 1949. Load more
/* * ipconfig - configure parameters of an ip stack */ #include <u.h> #include <libc.h> #include <ip.h> #include <bio.h> #include <ndb.h> #include "../dhcp.h" #include "ipconfig.h" #define DEBUG if(debug)warning /* possible verbs */ enum { /* commands */ Vadd, Vremove, Vunbind, Vaddpref6, Vra6, /* media */ Vether, Vgbe, Vppp, Vloopback, Vtorus, Vtree, Vpkt, }; 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 -- presotto */ Option 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; int Oflag; int beprimary = -1; Conf conf; int debug; int dodhcp; int dolog; int dondbconfig = 0; int dupl_disc = 1; /* flag: V6 duplicate neighbor discovery */ Ctl *firstctl, **ctll; Ipifc *ifc; int ipv6auto = 0; int myifc = -1; char *ndboptions; int nip; int noconfig; int nodhcpwatch; char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 }; int plan9 = 1; int sendhostname; static char logfile[] = "ipconfig"; char *verbs[] = { [Vadd] "add", [Vremove] "remove", [Vunbind] "unbind", [Vether] "ether", [Vgbe] "gbe", [Vppp] "ppp", [Vloopback] "loopback", [Vaddpref6] "add6", [Vra6] "ra6", [Vtorus] "torus", [Vtree] "tree", [Vpkt] "pkt", }; 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 ip4cfg(void); int ip6cfg(int a); void lookforip(char*); void mkclientid(void); void ndbconfig(void); int nipifcs(char*); int openlisten(void); uchar* optaddaddr(uchar*, int, uchar*); uchar* optaddbyte(uchar*, int, int); uchar* optaddstr(uchar*, int, char*); uchar* optadd(uchar*, int, void*, int); uchar* optaddulong(uchar*, int, ulong); uchar* optaddvec(uchar*, int, uchar*, int); int optgetaddrs(uchar*, int, uchar*, int); int optgetp9addrs(uchar*, int, uchar*, int); int optgetaddr(uchar*, int, uchar*); int optgetbyte(uchar*, int); int optgetstr(uchar*, int, char*, int); uchar* optget(uchar*, int, 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 pppbinddev(void); void putndb(void); void tweakservers(void); void usage(void); int validip(uchar*); void writendb(char*, int, int); void usage(void) { fprint(2, "usage: %s [-6dDGnNOpPruX][-b baud][-c ctl]* [-g gw]" "[-h host][-m mtu]\n" "\t[-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask " "[raddr [fs [auth]]]]]\n", argv0); exits("usage"); } void warning(char *fmt, ...) { char buf[1024]; va_list arg; va_start(arg, fmt); vseprint(buf, buf + sizeof buf, fmt, arg); va_end(arg); if (dolog) syslog(0, logfile, "%s", buf); else fprint(2, "%s: %s\n", argv0, buf); } static void parsenorm(int argc, char **argv) { switch(argc){ case 5: if (parseip(conf.auth, argv[4]) == -1) usage(); /* fall through */ case 4: if (parseip(conf.fs, argv[3]) == -1) usage(); /* fall through */ case 3: if (parseip(conf.raddr, argv[2]) == -1) usage(); /* fall through */ case 2: /* * can't test for parseipmask()==-1 cuz 255.255.255.255 * looks like that. */ if (strcmp(argv[1], "0") != 0) parseipmask(conf.mask, argv[1]); /* fall through */ case 1: if (parseip(conf.laddr, argv[0]) == -1) usage(); /* fall through */ case 0: break; default: usage(); } } static void parse6pref(int argc, char **argv) { switch(argc){ case 6: conf.preflt = strtoul(argv[5], 0, 10); /* fall through */ case 5: conf.validlt = strtoul(argv[4], 0, 10); /* fall through */ case 4: conf.autoflag = (atoi(argv[3]) != 0); /* fall through */ case 3: conf.onlink = (atoi(argv[2]) != 0); /* fall through */ case 2: conf.prefixlen = atoi(argv[1]); /* fall through */ case 1: if (parseip(conf.v6pref, argv[0]) == -1) sysfatal("bad address %s", argv[0]); break; } DEBUG("parse6pref: pref %I len %d", conf.v6pref, conf.prefixlen); } /* parse router advertisement (keyword, value) pairs */ static void parse6ra(int argc, char **argv) { int i, argsleft; char *kw, *val; if (argc % 2 != 0) usage(); i = 0; for (argsleft = argc; argsleft > 1; argsleft -= 2) { kw = argv[i]; val = argv[i+1]; if (strcmp(kw, "recvra") == 0) conf.recvra = (atoi(val) != 0); else if (strcmp(kw, "sendra") == 0) conf.sendra = (atoi(val) != 0); else if (strcmp(kw, "mflag") == 0) conf.mflag = (atoi(val) != 0); else if (strcmp(kw, "oflag") == 0) conf.oflag = (atoi(val) != 0); else if (strcmp(kw, "maxraint") == 0) conf.maxraint = atoi(val); else if (strcmp(kw, "minraint") == 0) conf.minraint = atoi(val); else if (strcmp(kw, "linkmtu") == 0) conf.linkmtu = atoi(val); else if (strcmp(kw, "reachtime") == 0) conf.reachtime = atoi(val); else if (strcmp(kw, "rxmitra") == 0) conf.rxmitra = atoi(val); else if (strcmp(kw, "ttl") == 0) conf.ttl = atoi(val); else if (strcmp(kw, "routerlt") == 0) conf.routerlt = atoi(val); else { warning("bad ra6 keyword %s", kw); usage(); } i += 2; } /* consistency check */ if (conf.maxraint < conf.minraint) sysfatal("maxraint %d < minraint %d", conf.maxraint, conf.minraint); } static void init(void) { srand(truerand()); fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('M', eipfmt); fmtinstall('V', eipfmt); nsec(); /* make sure time file is open before forking */ setnetmtpt(conf.mpoint, sizeof conf.mpoint, nil); conf.cputype = getenv("cputype"); if(conf.cputype == nil) conf.cputype = "386"; ctll = &firstctl; v6paraminit(&conf); /* init set of requested dhcp parameters with the default */ nrequested = sizeof defrequested; memcpy(requested, defrequested, nrequested); } static int parseargs(int argc, char **argv) { char *p; int action, verb; /* 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); } /* defaults */ conf.type = "ether"; conf.dev = "/net/ether0"; action = Vadd; /* get optional medium and device */ if (argc > 0){ verb = parseverb(*argv); switch(verb){ case Vether: case Vgbe: case Vppp: case Vloopback: case Vtorus: case Vtree: case Vpkt: conf.type = *argv++; argc--; if(argc > 0){ conf.dev = *argv++; argc--; } else if(verb == Vppp) conf.dev = "/dev/eia0"; break; } } /* get optional verb */ if (argc > 0){ verb = parseverb(*argv); switch(verb){ case Vether: case Vgbe: case Vppp: case Vloopback: case Vtorus: case Vtree: case Vpkt: sysfatal("medium %s already specified", conf.type); case Vadd: case Vremove: case Vunbind: case Vaddpref6: case Vra6: argv++; argc--; action = verb; break; } } /* get verb-dependent arguments */ switch (action) { case Vadd: case Vremove: case Vunbind: parsenorm(argc, argv); break; case Vaddpref6: parse6pref(argc, argv); break; case Vra6: parse6ra(argc, argv); break; } return action; } void main(int argc, char **argv) { int retry, action; Ctl *cp; init(); retry = 0; ARGBEGIN { case '6': /* IPv6 auto config */ ipv6auto = 1; break; case 'b': conf.baud = EARGF(usage()); break; case 'c': cp = malloc(sizeof *cp); if(cp == nil) sysfatal("%r"); *ctll = cp; ctll = &cp->next; cp->next = nil; cp->ctl = EARGF(usage()); break; case 'd': dodhcp = 1; break; case 'D': debug = 1; break; case 'g': if (parseip(conf.gaddr, EARGF(usage())) == -1) usage(); break; case 'G':