main.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935
  1. /*
  2. * ipconfig - configure parameters of an ip stack
  3. */
  4. #include <u.h>
  5. #include <libc.h>
  6. #include <ip.h>
  7. #include <bio.h>
  8. #include <ndb.h>
  9. #include "../dhcp.h"
  10. #include "ipconfig.h"
  11. #define DEBUG if(debug)warning
  12. /* possible verbs */
  13. enum
  14. {
  15. /* commands */
  16. Vadd,
  17. Vremove,
  18. Vunbind,
  19. Vaddpref6,
  20. Vra6,
  21. /* media */
  22. Vether,
  23. Vgbe,
  24. Vppp,
  25. Vloopback,
  26. Vtorus,
  27. Vtree,
  28. };
  29. enum
  30. {
  31. Taddr,
  32. Taddrs,
  33. Tstr,
  34. Tbyte,
  35. Tulong,
  36. Tvec,
  37. };
  38. typedef struct Option Option;
  39. struct Option
  40. {
  41. char *name;
  42. int type;
  43. };
  44. /*
  45. * I was too lazy to look up the types for each of these
  46. * options. If someone feels like it, please mail me a
  47. * corrected array -- presotto
  48. */
  49. Option option[256] =
  50. {
  51. [OBmask] { "ipmask", Taddr },
  52. [OBtimeoff] { "timeoff", Tulong },
  53. [OBrouter] { "ipgw", Taddrs },
  54. [OBtimeserver] { "time", Taddrs },
  55. [OBnameserver] { "name", Taddrs },
  56. [OBdnserver] { "dns", Taddrs },
  57. [OBlogserver] { "log", Taddrs },
  58. [OBcookieserver] { "cookie", Taddrs },
  59. [OBlprserver] { "lpr", Taddrs },
  60. [OBimpressserver] { "impress", Taddrs },
  61. [OBrlserver] { "rl", Taddrs },
  62. [OBhostname] { "sys", Tstr },
  63. [OBbflen] { "bflen", Tulong },
  64. [OBdumpfile] { "dumpfile", Tstr },
  65. [OBdomainname] { "dom", Tstr },
  66. [OBswapserver] { "swap", Taddrs },
  67. [OBrootpath] { "rootpath", Tstr },
  68. [OBextpath] { "extpath", Tstr },
  69. [OBipforward] { "ipforward", Taddrs },
  70. [OBnonlocal] { "nonlocal", Taddrs },
  71. [OBpolicyfilter] { "policyfilter", Taddrs },
  72. [OBmaxdatagram] { "maxdatagram", Tulong },
  73. [OBttl] { "ttl", Tulong },
  74. [OBpathtimeout] { "pathtimeout", Taddrs },
  75. [OBpathplateau] { "pathplateau", Taddrs },
  76. [OBmtu] { "mtu", Tulong },
  77. [OBsubnetslocal] { "subnetslocal", Taddrs },
  78. [OBbaddr] { "baddr", Taddrs },
  79. [OBdiscovermask] { "discovermask", Taddrs },
  80. [OBsupplymask] { "supplymask", Taddrs },
  81. [OBdiscoverrouter] { "discoverrouter", Taddrs },
  82. [OBrsserver] { "rs", Taddrs },
  83. [OBstaticroutes] { "staticroutes", Taddrs },
  84. [OBtrailerencap] { "trailerencap", Taddrs },
  85. [OBarptimeout] { "arptimeout", Tulong },
  86. [OBetherencap] { "etherencap", Taddrs },
  87. [OBtcpttl] { "tcpttl", Tulong },
  88. [OBtcpka] { "tcpka", Tulong },
  89. [OBtcpkag] { "tcpkag", Tulong },
  90. [OBnisdomain] { "nisdomain", Tstr },
  91. [OBniserver] { "ni", Taddrs },
  92. [OBntpserver] { "ntp", Taddrs },
  93. [OBnetbiosns] { "netbiosns", Taddrs },
  94. [OBnetbiosdds] { "netbiosdds", Taddrs },
  95. [OBnetbiostype] { "netbiostype", Taddrs },
  96. [OBnetbiosscope] { "netbiosscope", Taddrs },
  97. [OBxfontserver] { "xfont", Taddrs },
  98. [OBxdispmanager] { "xdispmanager", Taddrs },
  99. [OBnisplusdomain] { "nisplusdomain", Tstr },
  100. [OBnisplusserver] { "nisplus", Taddrs },
  101. [OBhomeagent] { "homeagent", Taddrs },
  102. [OBsmtpserver] { "smtp", Taddrs },
  103. [OBpop3server] { "pop3", Taddrs },
  104. [OBnntpserver] { "nntp", Taddrs },
  105. [OBwwwserver] { "www", Taddrs },
  106. [OBfingerserver] { "finger", Taddrs },
  107. [OBircserver] { "irc", Taddrs },
  108. [OBstserver] { "st", Taddrs },
  109. [OBstdaserver] { "stdar", Taddrs },
  110. [ODipaddr] { "ipaddr", Taddr },
  111. [ODlease] { "lease", Tulong },
  112. [ODoverload] { "overload", Taddr },
  113. [ODtype] { "type", Tbyte },
  114. [ODserverid] { "serverid", Taddr },
  115. [ODparams] { "params", Tvec },
  116. [ODmessage] { "message", Tstr },
  117. [ODmaxmsg] { "maxmsg", Tulong },
  118. [ODrenewaltime] { "renewaltime", Tulong },
  119. [ODrebindingtime] { "rebindingtime", Tulong },
  120. [ODvendorclass] { "vendorclass", Tvec },
  121. [ODclientid] { "clientid", Tvec },
  122. [ODtftpserver] { "tftp", Taddr },
  123. [ODbootfile] { "bootfile", Tstr },
  124. };
  125. uchar defrequested[] = {
  126. OBmask, OBrouter, OBdnserver, OBhostname, OBdomainname, OBntpserver,
  127. };
  128. uchar requested[256];
  129. int nrequested;
  130. int Oflag;
  131. int beprimary = -1;
  132. Conf conf;
  133. int debug;
  134. int dodhcp;
  135. int dolog;
  136. int dondbconfig = 0;
  137. int dupl_disc = 1; /* flag: V6 duplicate neighbor discovery */
  138. Ctl *firstctl, **ctll;
  139. Ipifc *ifc;
  140. int ipv6auto = 0;
  141. int myifc = -1;
  142. char *ndboptions;
  143. int nip;
  144. int noconfig;
  145. int nodhcpwatch;
  146. char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 };
  147. int plan9 = 1;
  148. int sendhostname;
  149. static char logfile[] = "ipconfig";
  150. char *verbs[] = {
  151. [Vadd] "add",
  152. [Vremove] "remove",
  153. [Vunbind] "unbind",
  154. [Vether] "ether",
  155. [Vgbe] "gbe",
  156. [Vppp] "ppp",
  157. [Vloopback] "loopback",
  158. [Vaddpref6] "add6",
  159. [Vra6] "ra6",
  160. [Vtorus] "torus",
  161. [Vtree] "tree",
  162. };
  163. void adddefroute(char*, uchar*);
  164. int addoption(char*);
  165. void binddevice(void);
  166. void bootprequest(void);
  167. void controldevice(void);
  168. void dhcpquery(int, int);
  169. void dhcprecv(void);
  170. void dhcpsend(int);
  171. int dhcptimer(void);
  172. void dhcpwatch(int);
  173. void doadd(int);
  174. void doremove(void);
  175. void dounbind(void);
  176. int getndb(void);
  177. void getoptions(uchar*);
  178. int ip4cfg(void);
  179. int ip6cfg(int a);
  180. void lookforip(char*);
  181. void mkclientid(void);
  182. void ndbconfig(void);
  183. int nipifcs(char*);
  184. int openlisten(void);
  185. uchar* optaddaddr(uchar*, int, uchar*);
  186. uchar* optaddbyte(uchar*, int, int);
  187. uchar* optaddstr(uchar*, int, char*);
  188. uchar* optadd(uchar*, int, void*, int);
  189. uchar* optaddulong(uchar*, int, ulong);
  190. uchar* optaddvec(uchar*, int, uchar*, int);
  191. int optgetaddrs(uchar*, int, uchar*, int);
  192. int optgetp9addrs(uchar*, int, uchar*, int);
  193. int optgetaddr(uchar*, int, uchar*);
  194. int optgetbyte(uchar*, int);
  195. int optgetstr(uchar*, int, char*, int);
  196. uchar* optget(uchar*, int, int*);
  197. ulong optgetulong(uchar*, int);
  198. int optgetvec(uchar*, int, uchar*, int);
  199. char* optgetx(uchar*, uchar);
  200. Bootp* parsebootp(uchar*, int);
  201. int parseoptions(uchar *p, int n);
  202. int parseverb(char*);
  203. void pppbinddev(void);
  204. void putndb(void);
  205. void tweakservers(void);
  206. void usage(void);
  207. int validip(uchar*);
  208. void writendb(char*, int, int);
  209. void
  210. usage(void)
  211. {
  212. fprint(2, "usage: %s [-6dDGnNOpPruX][-b baud][-c ctl]* [-g gw]"
  213. "[-h host][-m mtu]\n"
  214. "\t[-x mtpt][-o dhcpopt] type dev [verb] [laddr [mask "
  215. "[raddr [fs [auth]]]]]\n", argv0);
  216. exits("usage");
  217. }
  218. void
  219. warning(char *fmt, ...)
  220. {
  221. char buf[1024];
  222. va_list arg;
  223. va_start(arg, fmt);
  224. vseprint(buf, buf + sizeof buf, fmt, arg);
  225. va_end(arg);
  226. if (dolog)
  227. syslog(0, logfile, "%s", buf);
  228. else
  229. fprint(2, "%s: %s\n", argv0, buf);
  230. }
  231. static void
  232. parsenorm(int argc, char **argv)
  233. {
  234. switch(argc){
  235. case 5:
  236. if (parseip(conf.auth, argv[4]) == -1)
  237. usage();
  238. /* fall through */
  239. case 4:
  240. if (parseip(conf.fs, argv[3]) == -1)
  241. usage();
  242. /* fall through */
  243. case 3:
  244. if (parseip(conf.raddr, argv[2]) == -1)
  245. usage();
  246. /* fall through */
  247. case 2:
  248. /*
  249. * can't test for parseipmask()==-1 cuz 255.255.255.255
  250. * looks like that.
  251. */
  252. if (strcmp(argv[1], "0") != 0)
  253. parseipmask(conf.mask, argv[1]);
  254. /* fall through */
  255. case 1:
  256. if (parseip(conf.laddr, argv[0]) == -1)
  257. usage();
  258. /* fall through */
  259. case 0:
  260. break;
  261. default:
  262. usage();
  263. }
  264. }
  265. static void
  266. parse6pref(int argc, char **argv)
  267. {
  268. switch(argc){
  269. case 6:
  270. conf.preflt = strtoul(argv[5], 0, 10);
  271. /* fall through */
  272. case 5:
  273. conf.validlt = strtoul(argv[4], 0, 10);
  274. /* fall through */
  275. case 4:
  276. conf.autoflag = (atoi(argv[3]) != 0);
  277. /* fall through */
  278. case 3:
  279. conf.onlink = (atoi(argv[2]) != 0);
  280. /* fall through */
  281. case 2:
  282. conf.prefixlen = atoi(argv[1]);
  283. /* fall through */
  284. case 1:
  285. parseip(conf.v6pref, argv[0]);
  286. break;
  287. }
  288. DEBUG("parse6pref: pref %I len %d", conf.v6pref, conf.prefixlen);
  289. }
  290. /* parse router advertisement (keyword, value) pairs */
  291. static void
  292. parse6ra(int argc, char **argv)
  293. {
  294. int i, argsleft;
  295. char *kw, *val;
  296. if (argc % 2 != 0)
  297. usage();
  298. i = 0;
  299. for (argsleft = argc; argsleft > 1; argsleft -= 2) {
  300. kw = argv[i];
  301. val = argv[i+1];
  302. if (strcmp(kw, "recvra") == 0)
  303. conf.recvra = (atoi(val) != 0);
  304. else if (strcmp(kw, "sendra") == 0)
  305. conf.sendra = (atoi(val) != 0);
  306. else if (strcmp(kw, "mflag") == 0)
  307. conf.mflag = (atoi(val) != 0);
  308. else if (strcmp(kw, "oflag") == 0)
  309. conf.oflag = (atoi(val) != 0);
  310. else if (strcmp(kw, "maxraint") == 0)
  311. conf.maxraint = atoi(val);
  312. else if (strcmp(kw, "minraint") == 0)
  313. conf.minraint = atoi(val);
  314. else if (strcmp(kw, "linkmtu") == 0)
  315. conf.linkmtu = atoi(val);
  316. else if (strcmp(kw, "reachtime") == 0)
  317. conf.reachtime = atoi(val);
  318. else if (strcmp(kw, "rxmitra") == 0)
  319. conf.rxmitra = atoi(val);
  320. else if (strcmp(kw, "ttl") == 0)
  321. conf.ttl = atoi(val);
  322. else if (strcmp(kw, "routerlt") == 0)
  323. conf.routerlt = atoi(val);
  324. else {
  325. warning("bad ra6 keyword %s", kw);
  326. usage();
  327. }
  328. i += 2;
  329. }
  330. /* consistency check */
  331. if (conf.maxraint < conf.minraint)
  332. sysfatal("maxraint %d < minraint %d",
  333. conf.maxraint, conf.minraint);
  334. }
  335. static void
  336. init(void)
  337. {
  338. srand(truerand());
  339. fmtinstall('E', eipfmt);
  340. fmtinstall('I', eipfmt);
  341. fmtinstall('M', eipfmt);
  342. fmtinstall('V', eipfmt);
  343. nsec(); /* make sure time file is open before forking */
  344. setnetmtpt(conf.mpoint, sizeof conf.mpoint, nil);
  345. conf.cputype = getenv("cputype");
  346. if(conf.cputype == nil)
  347. conf.cputype = "386";
  348. ctll = &firstctl;
  349. v6paraminit(&conf);
  350. /* init set of requested dhcp parameters with the default */
  351. nrequested = sizeof defrequested;
  352. memcpy(requested, defrequested, nrequested);
  353. }
  354. static int
  355. parseargs(int argc, char **argv)
  356. {
  357. char *p;
  358. int action, verb;
  359. /* default to any host name we already have */
  360. if(*conf.hostname == 0){
  361. p = getenv("sysname");
  362. if(p == nil || *p == 0)
  363. p = sysname();
  364. if(p != nil)
  365. strncpy(conf.hostname, p, sizeof conf.hostname-1);
  366. }
  367. /* defaults */
  368. conf.type = "ether";
  369. conf.dev = "/net/ether0";
  370. action = Vadd;
  371. /* get optional medium and device */
  372. if (argc > 0){
  373. verb = parseverb(*argv);
  374. switch(verb){
  375. case Vether:
  376. case Vgbe:
  377. case Vppp:
  378. case Vloopback:
  379. case Vtorus:
  380. case Vtree:
  381. conf.type = *argv++;
  382. argc--;
  383. if(argc > 0){
  384. conf.dev = *argv++;
  385. argc--;
  386. } else if(verb == Vppp)
  387. conf.dev = "/dev/eia0";
  388. break;
  389. }
  390. }
  391. /* get optional verb */
  392. if (argc > 0){
  393. verb = parseverb(*argv);
  394. switch(verb){
  395. case Vether:
  396. case Vgbe:
  397. case Vppp:
  398. case Vloopback:
  399. case Vtorus:
  400. case Vtree:
  401. sysfatal("medium %s already specified", conf.type);
  402. case Vadd:
  403. case Vremove:
  404. case Vunbind:
  405. case Vaddpref6:
  406. case Vra6:
  407. argv++;
  408. argc--;
  409. action = verb;
  410. break;
  411. }
  412. }
  413. /* get verb-dependent arguments */
  414. switch (action) {
  415. case Vadd:
  416. case Vremove:
  417. case Vunbind:
  418. parsenorm(argc, argv);
  419. break;
  420. case Vaddpref6:
  421. parse6pref(argc, argv);
  422. break;
  423. case Vra6:
  424. parse6ra(argc, argv);
  425. break;
  426. }
  427. return action;
  428. }
  429. void
  430. main(int argc, char **argv)
  431. {
  432. int retry, action;
  433. Ctl *cp;
  434. init();
  435. retry = 0;
  436. ARGBEGIN {
  437. case '6': /* IPv6 auto config */
  438. ipv6auto = 1;
  439. break;
  440. case 'b':
  441. conf.baud = EARGF(usage());
  442. break;
  443. case 'c':
  444. cp = malloc(sizeof *cp);
  445. if(cp == nil)
  446. sysfatal("%r");
  447. *ctll = cp;
  448. ctll = &cp->next;
  449. cp->next = nil;
  450. cp->ctl = EARGF(usage());
  451. break;
  452. case 'd':
  453. dodhcp = 1;
  454. break;
  455. case 'D':
  456. debug = 1;
  457. break;
  458. case 'g':
  459. if (parseip(conf.gaddr, EARGF(usage())) == -1)
  460. usage();
  461. break;
  462. case 'G':
  463. plan9 = 0;
  464. break;
  465. case 'h':
  466. snprint(conf.hostname, sizeof conf.hostname, "%s",
  467. EARGF(usage()));
  468. sendhostname = 1;
  469. break;
  470. case 'm':
  471. conf.mtu = atoi(EARGF(usage()));
  472. break;
  473. case 'n':
  474. noconfig = 1;
  475. break;
  476. case 'N':
  477. dondbconfig = 1;
  478. break;
  479. case 'o':
  480. if(addoption(EARGF(usage())) < 0)
  481. usage();
  482. break;
  483. case 'O':
  484. Oflag = 1;
  485. break;
  486. case 'p':
  487. beprimary = 1;
  488. break;
  489. case 'P':
  490. beprimary = 0;
  491. break;
  492. case 'r':
  493. retry = 1;
  494. break;
  495. case 'u': /* IPv6: duplicate neighbour disc. off */
  496. dupl_disc = 0;
  497. break;
  498. case 'x':
  499. setnetmtpt(conf.mpoint, sizeof conf.mpoint, EARGF(usage()));
  500. break;
  501. case 'X':
  502. nodhcpwatch = 1;
  503. break;
  504. default:
  505. usage();
  506. } ARGEND;
  507. argv0 = "ipconfig"; /* boot invokes us as tcp? */
  508. action = parseargs(argc, argv);
  509. switch(action){
  510. case Vadd:
  511. doadd(retry);
  512. break;
  513. case Vremove:
  514. doremove();
  515. break;
  516. case Vunbind:
  517. dounbind();
  518. break;
  519. case Vaddpref6:
  520. case Vra6:
  521. doipv6(action);
  522. break;
  523. }
  524. exits(0);
  525. }
  526. int
  527. havendb(char *net)
  528. {
  529. Dir *d;
  530. char buf[128];
  531. snprint(buf, sizeof buf, "%s/ndb", net);
  532. if((d = dirstat(buf)) == nil)
  533. return 0;
  534. if(d->length == 0){
  535. free(d);
  536. return 0;
  537. }
  538. free(d);
  539. return 1;
  540. }
  541. void
  542. doadd(int retry)
  543. {
  544. int tries, ppp;
  545. ppp = strcmp(conf.type, "ppp") == 0;
  546. /* get number of preexisting interfaces */
  547. nip = nipifcs(conf.mpoint);
  548. if(beprimary == -1 && (nip == 0 || !havendb(conf.mpoint)))
  549. beprimary = 1;
  550. /* get ipifc into name space and condition device for ip */
  551. if(!noconfig){
  552. lookforip(conf.mpoint);
  553. controldevice();
  554. binddevice();
  555. }
  556. if (ipv6auto && !ppp) {
  557. if (ip6cfg(ipv6auto) < 0)
  558. sysfatal("can't automatically start IPv6 on %s",
  559. conf.dev);
  560. // return;
  561. } else if (validip(conf.laddr) && !isv4(conf.laddr)) {
  562. if (ip6cfg(0) < 0)
  563. sysfatal("can't start IPv6 on %s, address %I",
  564. conf.dev, conf.laddr);
  565. // return;
  566. }
  567. if(!validip(conf.laddr) && !ppp)
  568. if(dondbconfig)
  569. ndbconfig();
  570. else
  571. dodhcp = 1;
  572. /* run dhcp if we need something */
  573. if(dodhcp){
  574. mkclientid();
  575. for(tries = 0; tries < 6; tries++){
  576. dhcpquery(!noconfig, Sselecting);
  577. if(conf.state == Sbound)
  578. break;
  579. sleep(1000);
  580. }
  581. }
  582. if(!validip(conf.laddr))
  583. if(retry && dodhcp && !noconfig){
  584. warning("couldn't determine ip address, retrying");
  585. dhcpwatch(1);
  586. return;
  587. } else
  588. sysfatal("no success with DHCP");
  589. if(!noconfig)
  590. if(ip4cfg() < 0)
  591. sysfatal("can't start ip");
  592. else if(dodhcp && conf.lease != Lforever)
  593. dhcpwatch(0);
  594. /* leave everything we've learned somewhere other procs can find it */
  595. if(beprimary == 1){
  596. putndb();
  597. tweakservers();
  598. }
  599. }
  600. void
  601. doremove(void)
  602. {
  603. char file[128];
  604. int cfd;
  605. Ipifc *nifc;
  606. Iplifc *lifc;
  607. if(!validip(conf.laddr))
  608. sysfatal("remove requires an address");
  609. ifc = readipifc(conf.mpoint, ifc, -1);
  610. for(nifc = ifc; nifc != nil; nifc = nifc->next){
  611. if(strcmp(nifc->dev, conf.dev) != 0)
  612. continue;
  613. for(lifc = nifc->lifc; lifc != nil; lifc = lifc->next){
  614. if(ipcmp(conf.laddr, lifc->ip) != 0)
  615. continue;
  616. if (validip(conf.mask) &&
  617. ipcmp(conf.mask, lifc->mask) != 0)
  618. continue;
  619. if (validip(conf.raddr) &&
  620. ipcmp(conf.raddr, lifc->net) != 0)
  621. continue;
  622. snprint(file, sizeof file, "%s/ipifc/%d/ctl",
  623. conf.mpoint, nifc->index);
  624. cfd = open(file, ORDWR);
  625. if(cfd < 0){
  626. warning("can't open %s: %r", conf.mpoint);
  627. continue;
  628. }
  629. if(fprint(cfd, "remove %I %M", lifc->ip, lifc->mask) < 0)
  630. warning("can't remove %I %M from %s: %r",
  631. lifc->ip, lifc->mask, file);
  632. }
  633. }
  634. }
  635. void
  636. dounbind(void)
  637. {
  638. Ipifc *nifc;
  639. char file[128];
  640. int cfd;
  641. ifc = readipifc(conf.mpoint, ifc, -1);
  642. for(nifc = ifc; nifc != nil; nifc = nifc->next){
  643. if(strcmp(nifc->dev, conf.dev) == 0){
  644. snprint(file, sizeof file, "%s/ipifc/%d/ctl",
  645. conf.mpoint, nifc->index);
  646. cfd = open(file, ORDWR);
  647. if(cfd < 0){
  648. warning("can't open %s: %r", conf.mpoint);
  649. break;
  650. }
  651. if(fprint(cfd, "unbind") < 0)
  652. warning("can't unbind from %s: %r", file);
  653. break;
  654. }
  655. }
  656. }
  657. /* set the default route */
  658. void
  659. adddefroute(char *mpoint, uchar *gaddr)
  660. {
  661. char buf[256];
  662. int cfd;
  663. sprint(buf, "%s/iproute", mpoint);
  664. cfd = open(buf, ORDWR);
  665. if(cfd < 0)
  666. return;
  667. if(isv4(gaddr))
  668. fprint(cfd, "add 0 0 %I", gaddr);
  669. else
  670. fprint(cfd, "add :: /0 %I", gaddr);
  671. close(cfd);
  672. }
  673. /* create a client id */
  674. void
  675. mkclientid(void)
  676. {
  677. if(strcmp(conf.type, "ether") == 0 || strcmp(conf.type, "gbe") == 0)
  678. if(myetheraddr(conf.hwa, conf.dev) == 0){
  679. conf.hwalen = 6;
  680. conf.hwatype = 1;
  681. conf.cid[0] = conf.hwatype;
  682. memmove(&conf.cid[1], conf.hwa, conf.hwalen);
  683. conf.cidlen = conf.hwalen+1;
  684. } else {
  685. conf.hwatype = -1;
  686. snprint((char*)conf.cid, sizeof conf.cid,
  687. "plan9_%ld.%d", lrand(), getpid());
  688. conf.cidlen = strlen((char*)conf.cid);
  689. }
  690. }
  691. /* bind ip into the namespace */
  692. void
  693. lookforip(char *net)
  694. {
  695. char proto[64];
  696. snprint(proto, sizeof proto, "%s/ipifc", net);
  697. if(access(proto, 0) == 0)
  698. return;
  699. sysfatal("no ip stack bound onto %s", net);
  700. }
  701. /* send some ctls to a device */
  702. void
  703. controldevice(void)
  704. {
  705. char ctlfile[256];
  706. int fd;
  707. Ctl *cp;
  708. if (firstctl == nil ||
  709. strcmp(conf.type, "ether") != 0 && strcmp(conf.type, "gbe") != 0)
  710. return;
  711. snprint(ctlfile, sizeof ctlfile, "%s/clone", conf.dev);
  712. fd = open(ctlfile, ORDWR);
  713. if(fd < 0)
  714. sysfatal("can't open %s", ctlfile);
  715. for(cp = firstctl; cp != nil; cp = cp->next){
  716. if(write(fd, cp->ctl, strlen(cp->ctl)) < 0)
  717. sysfatal("ctl message %s: %r", cp->ctl);
  718. seek(fd, 0, 0);
  719. }
  720. // close(fd); /* or does it need to be left hanging? */
  721. }
  722. /* bind an ip stack to a device, leave the control channel open */
  723. void
  724. binddevice(void)
  725. {
  726. char buf[256];
  727. if(strcmp(conf.type, "ppp") == 0)
  728. pppbinddev();
  729. else if(myifc < 0){
  730. /* get a new ip interface */
  731. snprint(buf, sizeof buf, "%s/ipifc/clone", conf.mpoint);
  732. conf.cfd = open(buf, ORDWR);
  733. if(conf.cfd < 0)
  734. sysfatal("opening %s/ipifc/clone: %r", conf.mpoint);
  735. /* specify medium as ethernet, bind the interface to it */
  736. if(fprint(conf.cfd, "bind %s %s", conf.type, conf.dev) < 0)
  737. sysfatal("%s: bind %s %s: %r", buf, conf.type, conf.dev);
  738. } else {
  739. /* open the old interface */
  740. snprint(buf, sizeof buf, "%s/ipifc/%d/ctl", conf.mpoint, myifc);
  741. conf.cfd = open(buf, ORDWR);
  742. if(conf.cfd < 0)
  743. sysfatal("open %s: %r", buf);
  744. }
  745. }
  746. /* add a logical interface to the ip stack */
  747. int
  748. ip4cfg(void)
  749. {
  750. char buf[256];
  751. int n;
  752. if(!validip(conf.laddr))
  753. return -1;
  754. n = sprint(buf, "add");
  755. n += snprint(buf+n, sizeof buf-n, " %I", conf.laddr);
  756. if(!validip(conf.mask))
  757. ipmove(conf.mask, defmask(conf.laddr));
  758. n += snprint(buf+n, sizeof buf-n, " %I", conf.mask);
  759. if(validip(conf.raddr)){
  760. n += snprint(buf+n, sizeof buf-n, " %I", conf.raddr);
  761. if(conf.mtu != 0)
  762. n += snprint(buf+n, sizeof buf-n, " %d", conf.mtu);
  763. }
  764. if(write(conf.cfd, buf, n) < 0){
  765. warning("write(%s): %r", buf);
  766. return -1;
  767. }
  768. if(beprimary==1 && validip(conf.gaddr))
  769. adddefroute(conf.mpoint, conf.gaddr);
  770. return 0;
  771. }
  772. /* remove a logical interface to the ip stack */
  773. void
  774. ipunconfig(void)
  775. {
  776. char buf[256];
  777. int n;
  778. if(!validip(conf.laddr))
  779. return;
  780. DEBUG("couldn't renew IP lease, releasing %I", conf.laddr);
  781. n = sprint(buf, "remove");
  782. n += snprint(buf+n, sizeof buf-n, " %I", conf.laddr);
  783. if(!validip(conf.mask))
  784. ipmove(conf.mask, defmask(conf.laddr));
  785. n += snprint(buf+n, sizeof buf-n, " %I", conf.mask);
  786. write(conf.cfd, buf, n);
  787. ipmove(conf.laddr, IPnoaddr);
  788. ipmove(conf.raddr, IPnoaddr);
  789. ipmove(conf.mask, IPnoaddr);
  790. /* forget configuration info */
  791. if(beprimary==1)
  792. writendb("", 0, 0);
  793. }
  794. void
  795. ding(void*, char *msg)
  796. {
  797. if(strstr(msg, "alarm"))
  798. noted(NCONT);
  799. noted(NDFLT);
  800. }
  801. void
  802. dhcpquery(int needconfig, int startstate)
  803. {
  804. if(needconfig)
  805. fprint(conf.cfd, "add %I %I", IPnoaddr, IPnoaddr);
  806. conf.fd = openlisten();
  807. if(conf.fd < 0){
  808. conf.state = Sinit;
  809. return;
  810. }
  811. notify(ding);
  812. /* try dhcp for 10 seconds */
  813. conf.xid = lrand();
  814. conf.starttime = time(0);
  815. conf.state = startstate;
  816. switch(startstate){
  817. case Sselecting:
  818. conf.offered = 0;
  819. dhcpsend(Discover);
  820. break;
  821. case Srenewing:
  822. dhcpsend(Request);
  823. break;
  824. default:
  825. sysfatal("internal error 0");
  826. }
  827. conf.resend = 0;
  828. conf.timeout = time(0) + 4;
  829. while(conf.state != Sbound){
  830. dhcprecv();
  831. if(dhcptimer() < 0)
  832. break;
  833. if(time(0) - conf.starttime > 10)
  834. break;
  835. }
  836. close(conf.fd);
  837. if(needconfig)
  838. fprint(conf.cfd, "remove %I %I", IPnoaddr, IPnoaddr);
  839. }
  840. enum {
  841. /*
  842. * was an hour, needs to be less for the ARM/GS1 until the timer
  843. * code has been cleaned up (pb).
  844. */
  845. Maxsleep = 450,
  846. };
  847. void
  848. dhcpwatch(int needconfig)
  849. {
  850. int secs, s;
  851. ulong t;
  852. if(nodhcpwatch)
  853. return;
  854. switch(rfork(RFPROC|RFFDG|RFNOWAIT|RFNOTEG)){
  855. default:
  856. return;
  857. case 0:
  858. break;
  859. }
  860. dolog = 1; /* log, don't print */
  861. procsetname("dhcpwatch");
  862. /* keep trying to renew the lease */
  863. for(;;){
  864. if(conf.lease == 0)
  865. secs = 5;
  866. else
  867. secs = conf.lease >> 1;
  868. /* avoid overflows */
  869. for(s = secs; s > 0; s -= t){
  870. if(s > Maxsleep)
  871. t = Maxsleep;
  872. else
  873. t = s;
  874. sleep(t*1000);
  875. }
  876. if(conf.lease > 0){
  877. /*
  878. * during boot, the starttime can be bogus so avoid
  879. * spurious ipinconfig's
  880. */
  881. t = time(0) - conf.starttime;
  882. if(t > (3*secs)/2)
  883. t = secs;
  884. if(t >= conf.lease){
  885. conf.lease = 0;
  886. if(!noconfig){
  887. ipunconfig();
  888. needconfig = 1;
  889. }
  890. } else
  891. conf.lease -= t;
  892. }
  893. dhcpquery(needconfig, needconfig? Sselecting: Srenewing);
  894. if(needconfig && conf.state == Sbound){
  895. if(ip4cfg() < 0)
  896. sysfatal("can't start ip: %r");
  897. needconfig = 0;
  898. /*
  899. * leave everything we've learned somewhere that
  900. * other procs can find it.
  901. */
  902. if(beprimary==1){
  903. putndb();
  904. tweakservers();
  905. }
  906. }
  907. }
  908. }
  909. int
  910. dhcptimer(void)
  911. {
  912. ulong now;
  913. now = time(0);
  914. if(now < conf.timeout)
  915. return 0;
  916. switch(conf.state) {
  917. default:
  918. sysfatal("dhcptimer: unknown state %d", conf.state);
  919. case Sinit:
  920. case Sbound:
  921. break;
  922. case Sselecting:
  923. case Srequesting:
  924. case Srebinding:
  925. dhcpsend(conf.state == Sselecting? Discover: Request);
  926. conf.timeout = now + 4;
  927. if(++conf.resend > 5) {
  928. conf.state = Sinit;
  929. return -1;
  930. }
  931. break;
  932. case Srenewing:
  933. dhcpsend(Request);
  934. conf.timeout = now + 1;
  935. if(++conf.resend > 3) {
  936. conf.state = Srebinding;
  937. conf.resend = 0;
  938. }
  939. break;
  940. }
  941. return 0;
  942. }
  943. void
  944. dhcpsend(int type)
  945. {
  946. Bootp bp;
  947. uchar *p;
  948. int n;
  949. uchar vendor[64];
  950. Udphdr *up = (Udphdr*)bp.udphdr;
  951. memset(&bp, 0, sizeof bp);
  952. hnputs(up->rport, 67);
  953. bp.op = Bootrequest;
  954. hnputl(bp.xid, conf.xid);
  955. hnputs(bp.secs, time(0)-conf.starttime);
  956. hnputs(bp.flags, 0);
  957. memmove(bp.optmagic, optmagic, 4);
  958. if(conf.hwatype >= 0 && conf.hwalen < sizeof bp.chaddr){
  959. memmove(bp.chaddr, conf.hwa, conf.hwalen);
  960. bp.hlen = conf.hwalen;
  961. bp.htype = conf.hwatype;
  962. }
  963. p = bp.optdata;
  964. p = optaddbyte(p, ODtype, type);
  965. p = optadd(p, ODclientid, conf.cid, conf.cidlen);
  966. switch(type) {
  967. default:
  968. sysfatal("dhcpsend: unknown message type: %d", type);
  969. case Discover:
  970. ipmove(up->raddr, IPv4bcast); /* broadcast */
  971. if(*conf.hostname && sendhostname)
  972. p = optaddstr(p, OBhostname, conf.hostname);
  973. if(plan9){
  974. n = snprint((char*)vendor, sizeof vendor,
  975. "plan9_%s", conf.cputype);
  976. p = optaddvec(p, ODvendorclass, vendor, n);
  977. }
  978. p = optaddvec(p, ODparams, requested, nrequested);
  979. if(validip(conf.laddr))
  980. p = optaddaddr(p, ODipaddr, conf.laddr);
  981. break;
  982. case Request:
  983. switch(conf.state){
  984. case Srenewing:
  985. ipmove(up->raddr, conf.server);
  986. v6tov4(bp.ciaddr, conf.laddr);
  987. break;
  988. case Srebinding:
  989. ipmove(up->raddr, IPv4bcast); /* broadcast */
  990. v6tov4(bp.ciaddr, conf.laddr);
  991. break;
  992. case Srequesting:
  993. ipmove(up->raddr, IPv4bcast); /* broadcast */
  994. p = optaddaddr(p, ODipaddr, conf.laddr);
  995. p = optaddaddr(p, ODserverid, conf.server);
  996. break;
  997. }
  998. p = optaddulong(p, ODlease, conf.offered);
  999. if(plan9){
  1000. n = snprint((char*)vendor, sizeof vendor,
  1001. "plan9_%s", conf.cputype);
  1002. p = optaddvec(p, ODvendorclass, vendor, n);
  1003. }
  1004. p = optaddvec(p, ODparams, requested, nrequested);
  1005. if(*conf.hostname && sendhostname)
  1006. p = optaddstr(p, OBhostname, conf.hostname);
  1007. break;
  1008. case Release:
  1009. ipmove(up->raddr, conf.server);
  1010. v6tov4(bp.ciaddr, conf.laddr);
  1011. p = optaddaddr(p, ODipaddr, conf.laddr);
  1012. p = optaddaddr(p, ODserverid, conf.server);
  1013. break;
  1014. }
  1015. *p++ = OBend;
  1016. n = p - (uchar*)&bp;
  1017. USED(n);
  1018. /*
  1019. * We use a maximum size DHCP packet to survive the
  1020. * All_Aboard NAT package from Internet Share. It
  1021. * always replies to DHCP requests with a packet of the
  1022. * same size, so if the request is too short the reply
  1023. * is truncated.
  1024. */
  1025. if(write(conf.fd, &bp, sizeof bp) != sizeof bp)
  1026. warning("dhcpsend: write failed: %r");
  1027. }
  1028. void
  1029. dhcprecv(void)
  1030. {
  1031. int i, n, type;
  1032. ulong lease;
  1033. char err[ERRMAX];
  1034. uchar buf[8000], vopts[256], taddr[IPaddrlen];
  1035. Bootp *bp;
  1036. alarm(1000);
  1037. n = read(conf.fd, buf, sizeof buf);
  1038. alarm(0);
  1039. if(n < 0){
  1040. errstr(err, sizeof err);
  1041. if(strstr(err, "interrupt") == nil)
  1042. warning("dhcprecv: bad read: %s", err);
  1043. else
  1044. DEBUG("dhcprecv: read timed out");
  1045. return;
  1046. }
  1047. bp = parsebootp(buf, n);
  1048. if(bp == 0) {
  1049. DEBUG("parsebootp failed: dropping packet");
  1050. return;
  1051. }
  1052. type = optgetbyte(bp->optdata, ODtype);
  1053. switch(type) {
  1054. default:
  1055. warning("dhcprecv: unknown type: %d", type);
  1056. break;
  1057. case Offer:
  1058. DEBUG("got offer from %V ", bp->siaddr);
  1059. if(conf.state != Sselecting){
  1060. // DEBUG("");
  1061. break;
  1062. }
  1063. lease = optgetulong(bp->optdata, ODlease);
  1064. if(lease == 0){
  1065. /*
  1066. * The All_Aboard NAT package from Internet Share
  1067. * doesn't give a lease time, so we have to assume one.
  1068. */
  1069. warning("Offer with %lud lease, using %d", lease, MinLease);
  1070. lease = MinLease;
  1071. }
  1072. DEBUG("lease=%lud ", lease);
  1073. if(!optgetaddr(bp->optdata, ODserverid, conf.server)) {
  1074. warning("Offer from server with invalid serverid");
  1075. break;
  1076. }
  1077. v4tov6(conf.laddr, bp->yiaddr);
  1078. memmove(conf.sname, bp->sname, sizeof conf.sname);
  1079. conf.sname[sizeof conf.sname-1] = 0;
  1080. DEBUG("server=%I sname=%s", conf.server, conf.sname);
  1081. conf.offered = lease;
  1082. conf.state = Srequesting;
  1083. dhcpsend(Request);
  1084. conf.resend = 0;
  1085. conf.timeout = time(0) + 4;
  1086. break;
  1087. case Ack:
  1088. DEBUG("got ack from %V ", bp->siaddr);
  1089. if (conf.state != Srequesting && conf.state != Srenewing &&
  1090. conf.state != Srebinding)
  1091. break;
  1092. /* ignore a bad lease */
  1093. lease = optgetulong(bp->optdata, ODlease);
  1094. if(lease == 0){
  1095. /*
  1096. * The All_Aboard NAT package from Internet Share
  1097. * doesn't give a lease time, so we have to assume one.
  1098. */
  1099. warning("Ack with %lud lease, using %d", lease, MinLease);
  1100. lease = MinLease;
  1101. }
  1102. DEBUG("lease=%lud ", lease);
  1103. /* address and mask */
  1104. if(!validip(conf.laddr) || !Oflag)
  1105. v4tov6(conf.laddr, bp->yiaddr);
  1106. if(!validip(conf.mask) || !Oflag){
  1107. if(!optgetaddr(bp->optdata, OBmask, conf.mask))
  1108. ipmove(conf.mask, IPnoaddr);
  1109. }
  1110. DEBUG("ipaddr=%I ipmask=%M ", conf.laddr, conf.mask);
  1111. /*
  1112. * get a router address either from the router option
  1113. * or from the router that forwarded the dhcp packet
  1114. */
  1115. if(validip(conf.gaddr) && Oflag) {
  1116. DEBUG("ipgw=%I ", conf.gaddr);
  1117. } else if(optgetaddr(bp->optdata, OBrouter, conf.gaddr)){
  1118. DEBUG("ipgw=%I ", conf.gaddr);
  1119. } else if(memcmp(bp->giaddr, IPnoaddr+IPv4off, IPv4addrlen)!=0){
  1120. v4tov6(conf.gaddr, bp->giaddr);
  1121. DEBUG("giaddr=%I ", conf.gaddr);
  1122. }
  1123. /* get dns servers */
  1124. memset(conf.dns, 0, sizeof conf.dns);
  1125. n = optgetaddrs(bp->optdata, OBdnserver, conf.dns,
  1126. sizeof conf.dns/IPaddrlen);
  1127. for(i = 0; i < n; i++)
  1128. DEBUG("dns=%I ", conf.dns + i*IPaddrlen);
  1129. /* get ntp servers */
  1130. memset(conf.ntp, 0, sizeof conf.ntp);
  1131. n = optgetaddrs(bp->optdata, OBntpserver, conf.ntp,
  1132. sizeof conf.ntp/IPaddrlen);
  1133. for(i = 0; i < n; i++)
  1134. DEBUG("ntp=%I ", conf.ntp + i*IPaddrlen);
  1135. /* get names */
  1136. optgetstr(bp->optdata, OBhostname,
  1137. conf.hostname, sizeof conf.hostname);
  1138. optgetstr(bp->optdata, OBdomainname,
  1139. conf.domainname, sizeof conf.domainname);
  1140. /* get anything else we asked for */
  1141. getoptions(bp->optdata);
  1142. /* get plan9-specific options */
  1143. n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1);
  1144. if(n > 0 && parseoptions(vopts, n) == 0){
  1145. if(validip(conf.fs) && Oflag)
  1146. n = 1;
  1147. else {
  1148. n = optgetp9addrs(vopts, OP9fs, conf.fs, 2);
  1149. if (n == 0)
  1150. n = optgetaddrs(vopts, OP9fsv4,
  1151. conf.fs, 2);
  1152. }
  1153. for(i = 0; i < n; i++)
  1154. DEBUG("fs=%I ", conf.fs + i*IPaddrlen);
  1155. if(validip(conf.auth) && Oflag)
  1156. n = 1;
  1157. else {
  1158. n = optgetp9addrs(vopts, OP9auth, conf.auth, 2);
  1159. if (n == 0)
  1160. n = optgetaddrs(vopts, OP9authv4,
  1161. conf.auth, 2);
  1162. }
  1163. for(i = 0; i < n; i++)
  1164. DEBUG("auth=%I ", conf.auth + i*IPaddrlen);
  1165. n = optgetp9addrs(vopts, OP9ipaddr, taddr, 1);
  1166. if (n > 0)
  1167. memmove(conf.laddr, taddr, IPaddrlen);
  1168. n = optgetp9addrs(vopts, OP9ipmask, taddr, 1);
  1169. if (n > 0)
  1170. memmove(conf.mask, taddr, IPaddrlen);
  1171. n = optgetp9addrs(vopts, OP9ipgw, taddr, 1);
  1172. if (n > 0)
  1173. memmove(conf.gaddr, taddr, IPaddrlen);
  1174. DEBUG("new ipaddr=%I new ipmask=%M new ipgw=%I",
  1175. conf.laddr, conf.mask, conf.gaddr);
  1176. }
  1177. conf.lease = lease;
  1178. conf.state = Sbound;
  1179. DEBUG("server=%I sname=%s", conf.server, conf.sname);
  1180. break;
  1181. case Nak:
  1182. conf.state = Sinit;
  1183. warning("recved dhcpnak on %s", conf.mpoint);
  1184. break;
  1185. }
  1186. }
  1187. /* return pseudo-random integer in range low...(hi-1) */
  1188. ulong
  1189. randint(ulong low, ulong hi)
  1190. {
  1191. if (hi < low)
  1192. return low;
  1193. return low + nrand(hi - low);
  1194. }
  1195. long
  1196. jitter(void) /* compute small pseudo-random delay in ms */
  1197. {
  1198. return randint(0, 10*1000);
  1199. }
  1200. int
  1201. openlisten(void)
  1202. {
  1203. int n, fd, cfd;
  1204. char data[128], devdir[40];
  1205. if (validip(conf.laddr) &&
  1206. (conf.state == Srenewing || conf.state == Srebinding))
  1207. sprint(data, "%s/udp!%I!68", conf.mpoint, conf.laddr);
  1208. else
  1209. sprint(data, "%s/udp!*!68", conf.mpoint);
  1210. for (n = 0; (cfd = announce(data, devdir)) < 0; n++) {
  1211. if(!noconfig)
  1212. sysfatal("can't announce for dhcp: %r");
  1213. /* might be another client - wait and try again */
  1214. warning("can't announce %s: %r", data);
  1215. sleep(jitter());
  1216. if(n > 10)
  1217. return -1;
  1218. }
  1219. if(fprint(cfd, "headers") < 0)
  1220. sysfatal("can't set header mode: %r");
  1221. sprint(data, "%s/data", devdir);
  1222. fd = open(data, ORDWR);
  1223. if(fd < 0)
  1224. sysfatal("open %s: %r", data);
  1225. close(cfd);
  1226. return fd;
  1227. }
  1228. uchar*
  1229. optadd(uchar *p, int op, void *d, int n)
  1230. {
  1231. p[0] = op;
  1232. p[1] = n;
  1233. memmove(p+2, d, n);
  1234. return p+n+2;
  1235. }
  1236. uchar*
  1237. optaddbyte(uchar *p, int op, int b)
  1238. {
  1239. p[0] = op;
  1240. p[1] = 1;
  1241. p[2] = b;
  1242. return p+3;
  1243. }
  1244. uchar*
  1245. optaddulong(uchar *p, int op, ulong x)
  1246. {
  1247. p[0] = op;
  1248. p[1] = 4;
  1249. hnputl(p+2, x);
  1250. return p+6;
  1251. }
  1252. uchar *
  1253. optaddaddr(uchar *p, int op, uchar *ip)
  1254. {
  1255. p[0] = op;
  1256. p[1] = 4;
  1257. v6tov4(p+2, ip);
  1258. return p+6;
  1259. }
  1260. /* add dhcp option op with value v of length n to dhcp option array p */
  1261. uchar *
  1262. optaddvec(uchar *p, int op, uchar *v, int n)
  1263. {
  1264. p[0] = op;
  1265. p[1] = n;
  1266. memmove(p+2, v, n);
  1267. return p+2+n;
  1268. }
  1269. uchar *
  1270. optaddstr(uchar *p, int op, char *v)
  1271. {
  1272. int n;
  1273. n = strlen(v)+1; /* microsoft leaves on the NUL, so we do too */
  1274. p[0] = op;
  1275. p[1] = n;
  1276. memmove(p+2, v, n);
  1277. return p+2+n;
  1278. }
  1279. /*
  1280. * parse p, looking for option `op'. if non-nil, np points to minimum length.
  1281. * return nil if option is too small, else ptr to opt, and
  1282. * store actual length via np if non-nil.
  1283. */
  1284. uchar*
  1285. optget(uchar *p, int op, int *np)
  1286. {
  1287. int len, code;
  1288. while ((code = *p++) != OBend) {
  1289. if(code == OBpad)
  1290. continue;
  1291. len = *p++;
  1292. if(code != op) {
  1293. p += len;
  1294. continue;
  1295. }
  1296. if(np != nil){
  1297. if(*np > len) {
  1298. return 0;
  1299. }
  1300. *np = len;
  1301. }
  1302. return p;
  1303. }
  1304. return 0;
  1305. }
  1306. int
  1307. optgetbyte(uchar *p, int op)
  1308. {
  1309. int len;
  1310. len = 1;
  1311. p = optget(p, op, &len);
  1312. if(p == nil)
  1313. return 0;
  1314. return *p;
  1315. }
  1316. ulong
  1317. optgetulong(uchar *p, int op)
  1318. {
  1319. int len;
  1320. len = 4;
  1321. p = optget(p, op, &len);
  1322. if(p == nil)
  1323. return 0;
  1324. return nhgetl(p);
  1325. }
  1326. int
  1327. optgetaddr(uchar *p, int op, uchar *ip)
  1328. {
  1329. int len;
  1330. len = 4;
  1331. p = optget(p, op, &len);
  1332. if(p == nil)
  1333. return 0;
  1334. v4tov6(ip, p);
  1335. return 1;
  1336. }
  1337. /* expect at most n addresses; ip[] only has room for that many */
  1338. int
  1339. optgetaddrs(uchar *p, int op, uchar *ip, int n)
  1340. {
  1341. int len, i;
  1342. len = 4;
  1343. p = optget(p, op, &len);
  1344. if(p == nil)
  1345. return 0;
  1346. len /= IPv4addrlen;
  1347. if(len > n)
  1348. len = n;
  1349. for(i = 0; i < len; i++)
  1350. v4tov6(&ip[i*IPaddrlen], &p[i*IPv4addrlen]);
  1351. return i;
  1352. }
  1353. /* expect at most n addresses; ip[] only has room for that many */
  1354. int
  1355. optgetp9addrs(uchar *ap, int op, uchar *ip, int n)
  1356. {
  1357. int len, i, slen, addrs;
  1358. char *p;
  1359. len = 1; /* minimum bytes needed */
  1360. p = (char *)optget(ap, op, &len);
  1361. if(p == nil)
  1362. return 0;
  1363. addrs = *p++; /* first byte is address count */
  1364. for (i = 0; i < n && i < addrs && len > 0; i++) {
  1365. slen = strlen(p) + 1;
  1366. parseip(&ip[i*IPaddrlen], p);
  1367. DEBUG("got plan 9 option %d addr %I (%s)",
  1368. op, &ip[i*IPaddrlen], p);
  1369. p += slen;
  1370. len -= slen;
  1371. }
  1372. return addrs;
  1373. }
  1374. int
  1375. optgetvec(uchar *p, int op, uchar *v, int n)
  1376. {
  1377. int len;
  1378. len = 1;
  1379. p = optget(p, op, &len);
  1380. if(p == nil)
  1381. return 0;
  1382. if(len > n)
  1383. len = n;
  1384. memmove(v, p, len);
  1385. return len;
  1386. }
  1387. int
  1388. optgetstr(uchar *p, int op, char *s, int n)
  1389. {
  1390. int len;
  1391. len = 1;
  1392. p = optget(p, op, &len);
  1393. if(p == nil)
  1394. return 0;
  1395. if(len >= n)
  1396. len = n-1;
  1397. memmove(s, p, len);
  1398. s[len] = 0;
  1399. return len;
  1400. }
  1401. /*
  1402. * sanity check options area
  1403. * - options don't overflow packet
  1404. * - options end with an OBend
  1405. */
  1406. int
  1407. parseoptions(uchar *p, int n)
  1408. {
  1409. int code, len, nin = n;
  1410. while (n > 0) {
  1411. code = *p++;
  1412. n--;
  1413. if(code == OBend)
  1414. return 0;
  1415. if(code == OBpad)
  1416. continue;
  1417. if(n == 0) {
  1418. warning("parseoptions: bad option: 0x%ux: truncated: "
  1419. "opt length = %d", code, nin);
  1420. return -1;
  1421. }
  1422. len = *p++;
  1423. n--;
  1424. DEBUG("parseoptions: %s(%d) len %d, bytes left %d",
  1425. option[code].name, code, len, n);
  1426. if(len > n) {
  1427. warning("parseoptions: bad option: 0x%ux: %d > %d: "
  1428. "opt length = %d", code, len, n, nin);
  1429. return -1;
  1430. }
  1431. p += len;
  1432. n -= len;
  1433. }
  1434. /* make sure packet ends with an OBend after all the optget code */
  1435. *p = OBend;
  1436. return 0;
  1437. }
  1438. /*
  1439. * sanity check received packet:
  1440. * - magic is dhcp magic
  1441. * - options don't overflow packet
  1442. */
  1443. Bootp *
  1444. parsebootp(uchar *p, int n)
  1445. {
  1446. Bootp *bp;
  1447. bp = (Bootp*)p;
  1448. if(n < bp->optmagic - p) {
  1449. warning("parsebootp: short bootp packet");
  1450. return nil;
  1451. }
  1452. if(conf.xid != nhgetl(bp->xid))
  1453. return nil;
  1454. if(bp->op != Bootreply) {
  1455. warning("parsebootp: bad op %d", bp->op);
  1456. return nil;
  1457. }
  1458. n -= bp->optmagic - p;
  1459. p = bp->optmagic;
  1460. if(n < 4) {
  1461. warning("parsebootp: no option data");
  1462. return nil;
  1463. }
  1464. if(memcmp(optmagic, p, 4) != 0) {
  1465. warning("parsebootp: bad opt magic %ux %ux %ux %ux",
  1466. p[0], p[1], p[2], p[3]);
  1467. return nil;
  1468. }
  1469. p += 4;
  1470. n -= 4;
  1471. DEBUG("parsebootp: new packet");
  1472. if(parseoptions(p, n) < 0)
  1473. return nil;
  1474. return bp;
  1475. }
  1476. /* write out an ndb entry */
  1477. void
  1478. writendb(char *s, int n, int append)
  1479. {
  1480. char file[64];
  1481. int fd;
  1482. snprint(file, sizeof file, "%s/ndb", conf.mpoint);
  1483. if(append){
  1484. fd = open(file, OWRITE);
  1485. seek(fd, 0, 2);
  1486. } else
  1487. fd = open(file, OWRITE|OTRUNC);
  1488. write(fd, s, n);
  1489. close(fd);
  1490. }
  1491. /* put server addresses into the ndb entry */
  1492. char*
  1493. putaddrs(char *p, char *e, char *attr, uchar *a, int len)
  1494. {
  1495. int i;
  1496. for(i = 0; i < len && validip(a); i += IPaddrlen, a += IPaddrlen)
  1497. p = seprint(p, e, "%s=%I\n", attr, a);
  1498. return p;
  1499. }
  1500. /* make an ndb entry and put it into /net/ndb for the servers to see */
  1501. void
  1502. putndb(void)
  1503. {
  1504. int append;
  1505. char buf[1024];
  1506. char *p, *e, *np;
  1507. p = buf;
  1508. e = buf + sizeof buf;
  1509. if(getndb() == 0)
  1510. append = 1;
  1511. else {
  1512. append = 0;
  1513. p = seprint(p, e, "ip=%I ipmask=%M ipgw=%I\n",
  1514. conf.laddr, conf.mask, conf.gaddr);
  1515. }
  1516. if(np = strchr(conf.hostname, '.')){
  1517. if(*conf.domainname == 0)
  1518. strcpy(conf.domainname, np+1);
  1519. *np = 0;
  1520. }
  1521. if(*conf.hostname)
  1522. p = seprint(p, e, "\tsys=%s\n", conf.hostname);
  1523. if(*conf.domainname)
  1524. p = seprint(p, e, "\tdom=%s.%s\n",
  1525. conf.hostname, conf.domainname);
  1526. if(validip(conf.fs))
  1527. p = putaddrs(p, e, "\tfs", conf.fs, sizeof conf.fs);
  1528. if(validip(conf.auth))
  1529. p = putaddrs(p, e, "\tauth", conf.auth, sizeof conf.auth);
  1530. if(validip(conf.dns))
  1531. p = putaddrs(p, e, "\tdns", conf.dns, sizeof conf.dns);
  1532. if(validip(conf.ntp))
  1533. p = putaddrs(p, e, "\tntp", conf.ntp, sizeof conf.ntp);
  1534. if(ndboptions)
  1535. p = seprint(p, e, "%s\n", ndboptions);
  1536. if(p > buf)
  1537. writendb(buf, p-buf, append);
  1538. }
  1539. /* get an ndb entry someone else wrote */
  1540. int
  1541. getndb(void)
  1542. {
  1543. char buf[1024];
  1544. int fd, n;
  1545. char *p;
  1546. snprint(buf, sizeof buf, "%s/ndb", conf.mpoint);
  1547. fd = open(buf, OREAD);
  1548. n = read(fd, buf, sizeof buf-1);
  1549. close(fd);
  1550. if(n <= 0)
  1551. return -1;
  1552. buf[n] = 0;
  1553. p = strstr(buf, "ip=");
  1554. if(p == nil)
  1555. return -1;
  1556. parseip(conf.laddr, p+3);
  1557. return 0;
  1558. }
  1559. /* tell a server to refresh */
  1560. void
  1561. tweakserver(char *server)
  1562. {
  1563. int fd;
  1564. char file[64];
  1565. snprint(file, sizeof file, "%s/%s", conf.mpoint, server);
  1566. fd = open(file, ORDWR);
  1567. if(fd < 0)
  1568. return;
  1569. fprint(fd, "refresh");
  1570. close(fd);
  1571. }
  1572. /* tell all servers to refresh their information */
  1573. void
  1574. tweakservers(void)
  1575. {
  1576. tweakserver("dns");
  1577. tweakserver("cs");
  1578. }
  1579. /* return number of networks */
  1580. int
  1581. nipifcs(char *net)
  1582. {
  1583. int n;
  1584. Ipifc *nifc;
  1585. Iplifc *lifc;
  1586. n = 0;
  1587. ifc = readipifc(net, ifc, -1);
  1588. for(nifc = ifc; nifc != nil; nifc = nifc->next){
  1589. /*
  1590. * ignore loopback devices when trying to
  1591. * figure out if we're the primary interface.
  1592. */
  1593. if(strcmp(nifc->dev, "/dev/null") != 0)
  1594. for(lifc = nifc->lifc; lifc != nil; lifc = lifc->next)
  1595. if(validip(lifc->ip)){
  1596. n++;
  1597. break;
  1598. }
  1599. if(strcmp(nifc->dev, conf.dev) == 0)
  1600. myifc = nifc->index;
  1601. }
  1602. return n;
  1603. }
  1604. /* return true if this is a valid v4 address */
  1605. int
  1606. validip(uchar *addr)
  1607. {
  1608. return ipcmp(addr, IPnoaddr) != 0 && ipcmp(addr, v4prefix) != 0;
  1609. }
  1610. /* look for an action */
  1611. int
  1612. parseverb(char *name)
  1613. {
  1614. int i;
  1615. for(i = 0; i < nelem(verbs); i++)
  1616. if(verbs[i] != nil && strcmp(name, verbs[i]) == 0)
  1617. return i;
  1618. return -1;
  1619. }
  1620. /* get everything out of ndb */
  1621. void
  1622. ndbconfig(void)
  1623. {
  1624. int nattr, nauth = 0, ndns = 0, nfs = 0;
  1625. char etheraddr[32];
  1626. char *attrs[10];
  1627. Ndb *db;
  1628. Ndbtuple *t, *nt;
  1629. db = ndbopen(0);
  1630. if(db == nil)
  1631. sysfatal("can't open ndb: %r");
  1632. if (strcmp(conf.type, "ether") != 0 && strcmp(conf.type, "gbe") != 0 ||
  1633. myetheraddr(conf.hwa, conf.dev) != 0)
  1634. sysfatal("can't read hardware address");
  1635. sprint(etheraddr, "%E", conf.hwa);
  1636. nattr = 0;
  1637. attrs[nattr++] = "ip";
  1638. attrs[nattr++] = "ipmask";
  1639. attrs[nattr++] = "ipgw";
  1640. /* the @ triggers resolution to an IP address; see ndb(2) */
  1641. attrs[nattr++] = "@dns";
  1642. attrs[nattr++] = "@ntp";
  1643. attrs[nattr++] = "@fs";
  1644. attrs[nattr++] = "@auth";
  1645. attrs[nattr] = nil;
  1646. t = ndbipinfo(db, "ether", etheraddr, attrs, nattr);
  1647. for(nt = t; nt != nil; nt = nt->entry)
  1648. if(strcmp(nt->attr, "ip") == 0)
  1649. parseip(conf.laddr, nt->val);
  1650. else if(strcmp(nt->attr, "ipmask") == 0)
  1651. parseipmask(conf.mask, nt->val);
  1652. else if(strcmp(nt->attr, "ipgw") == 0)
  1653. parseip(conf.gaddr, nt->val);
  1654. else if(ndns < 2 && strcmp(nt->attr, "dns") == 0)
  1655. parseip(conf.dns+IPaddrlen*ndns, nt->val);
  1656. else if(strcmp(nt->attr, "ntp") == 0)
  1657. parseip(conf.ntp, nt->val);
  1658. else if(nfs < 2 && strcmp(nt->attr, "fs") == 0)
  1659. parseip(conf.fs+IPaddrlen*nfs, nt->val);
  1660. else if(nauth < 2 && strcmp(nt->attr, "auth") == 0)
  1661. parseip(conf.auth+IPaddrlen*nauth, nt->val);
  1662. ndbfree(t);
  1663. if(!validip(conf.laddr))
  1664. sysfatal("address not found in ndb");
  1665. }
  1666. int
  1667. addoption(char *opt)
  1668. {
  1669. int i;
  1670. Option *o;
  1671. if(opt == nil)
  1672. return -1;
  1673. for(o = option; o < &option[nelem(option)]; o++)
  1674. if(o->name && strcmp(opt, o->name) == 0){
  1675. i = o - option;
  1676. if(memchr(requested, i, nrequested) == 0 &&
  1677. nrequested < nelem(requested))
  1678. requested[nrequested++] = i;
  1679. return 0;
  1680. }
  1681. return -1;
  1682. }
  1683. char*
  1684. optgetx(uchar *p, uchar opt)
  1685. {
  1686. int i, n;
  1687. ulong x;
  1688. char *s, *ns;
  1689. char str[256];
  1690. uchar ip[IPaddrlen], ips[16*IPaddrlen], vec[256];
  1691. Option *o;
  1692. o = &option[opt];
  1693. if(o->name == nil)
  1694. return nil;
  1695. s = nil;
  1696. switch(o->type){
  1697. case Taddr:
  1698. if(optgetaddr(p, opt, ip))
  1699. s = smprint("%s=%I", o->name, ip);
  1700. break;
  1701. case Taddrs:
  1702. n = optgetaddrs(p, opt, ips, 16);
  1703. if(n > 0)
  1704. s = smprint("%s=%I", o->name, ips);
  1705. for(i = 1; i < n; i++){
  1706. ns = smprint("%s %s=%I", s, o->name, &ips[i*IPaddrlen]);
  1707. free(s);
  1708. s = ns;
  1709. }
  1710. break;
  1711. case Tulong:
  1712. x = optgetulong(p, opt);
  1713. if(x != 0)
  1714. s = smprint("%s=%lud", o->name, x);
  1715. break;
  1716. case Tbyte:
  1717. x = optgetbyte(p, opt);
  1718. if(x != 0)
  1719. s = smprint("%s=%lud", o->name, x);
  1720. break;
  1721. case Tstr:
  1722. if(optgetstr(p, opt, str, sizeof str))
  1723. s = smprint("%s=%s", o->name, str);
  1724. break;
  1725. case Tvec:
  1726. n = optgetvec(p, opt, vec, sizeof vec);
  1727. if(n > 0)
  1728. /* what's %H? it's not installed */
  1729. s = smprint("%s=%.*H", o->name, n, vec);
  1730. break;
  1731. }
  1732. return s;
  1733. }
  1734. void
  1735. getoptions(uchar *p)
  1736. {
  1737. int i;
  1738. char *s, *t;
  1739. for(i = nelem(defrequested); i < nrequested; i++){
  1740. s = optgetx(p, requested[i]);
  1741. if(s != nil)
  1742. DEBUG("%s ", s);
  1743. if(ndboptions == nil)
  1744. ndboptions = smprint("\t%s", s);
  1745. else{
  1746. t = ndboptions;
  1747. ndboptions = smprint("\t%s%s", s, ndboptions);
  1748. free(t);
  1749. }
  1750. free(s);
  1751. }
  1752. }