gizzard.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <ctype.h>
  4. #include <bio.h>
  5. #include <ndb.h>
  6. #include <ip.h>
  7. Biobuf in;
  8. void
  9. usage(void)
  10. {
  11. fprint(2, "usage: %s [-x netroot]\n", argv0);
  12. exits("usage");
  13. }
  14. char *vec[] =
  15. {
  16. "ip",
  17. "ipmask",
  18. "dns",
  19. "dom",
  20. "auth",
  21. "authdom",
  22. "fs",
  23. "sys",
  24. "ipgw",
  25. "ntp",
  26. };
  27. char *outvec[] =
  28. {
  29. "ipgw",
  30. "dns",
  31. "auth",
  32. "fs",
  33. "ntp",
  34. 0
  35. };
  36. enum
  37. {
  38. Tnone,
  39. Tip,
  40. Tdom,
  41. Tmask,
  42. Tstring,
  43. };
  44. typedef struct Attribute Attribute;
  45. typedef void (Helper)(Attribute*);
  46. struct Attribute
  47. {
  48. char *attr;
  49. char *desc;
  50. int type;
  51. int multiple;
  52. Helper *helper;
  53. };
  54. Helper authdomhelper, authhelper, fshelper;
  55. Attribute expl[] =
  56. {
  57. { "ip", "ip address on this interface", Tip, 0, nil },
  58. { "ipmask", "ip mask on this interface", Tmask, 0, nil },
  59. { "dns", "domain name server", Tdom, 1, nil },
  60. { "dom", "domain name", Tdom, 0, nil },
  61. { "auth", "authentication server", Tdom, 0, authhelper },
  62. { "authdom", "authentication domain", Tstring, 0, authdomhelper },
  63. { "fs", "file server", Tdom, 0, fshelper },
  64. { "sys", "your system name", Tstring, 0, nil },
  65. { "ipgw", "ip gateway on this network", 0, nil },
  66. { "ntp", "network time server", Tdom, 0, nil },
  67. { 0 },
  68. };
  69. char *authserver;
  70. Ndbtuple*
  71. find(char *attr, Ndbtuple *t1, Ndbtuple *t2, Ndbtuple *t3)
  72. {
  73. for(; t1; t1 = t1->entry)
  74. if(strcmp(attr, t1->attr) == 0)
  75. return t1;
  76. for(; t2; t2 = t2->entry)
  77. if(strcmp(attr, t2->attr) == 0)
  78. return t2;
  79. for(; t3; t3 = t3->entry)
  80. if(strcmp(attr, t3->attr) == 0)
  81. return t3;
  82. return nil;
  83. }
  84. Ndbtuple*
  85. findnext(Ndbtuple *t, char *attr, Ndbtuple *t1, Ndbtuple *t2, Ndbtuple *t3)
  86. {
  87. if(t == nil)
  88. return find(attr, t1, t2, t3);
  89. for(; t1; t1 = t1->entry)
  90. if(t1 == t)
  91. return find(attr, t->entry, t2, t3);
  92. for(; t2; t2 = t2->entry)
  93. if(t2 == t)
  94. return find(attr, t->entry, t3, nil);
  95. for(; t3; t3 = t3->entry)
  96. if(t3 == t)
  97. return find(attr, t->entry, nil, nil);
  98. return nil;
  99. }
  100. Ndbtuple*
  101. newtuple(char *attr, char *val)
  102. {
  103. Ndbtuple *nt;
  104. nt = malloc(sizeof *nt);
  105. nt->entry = nt->line = nil;
  106. strncpy(nt->attr, attr, Ndbalen-1);
  107. nt->attr[Ndbalen-1] = 0;
  108. strncpy(nt->val, val, Ndbvlen-1);
  109. nt->attr[Ndbvlen-1] = 0;
  110. return nt;
  111. }
  112. Ndbtuple*
  113. duptuple(Ndbtuple *t)
  114. {
  115. Ndbtuple *nt;
  116. nt = malloc(sizeof *nt);
  117. nt->entry = nt->line = nil;
  118. strcpy(nt->val, t->val);
  119. strcpy(nt->attr, t->attr);
  120. return nt;
  121. }
  122. Ndbtuple*
  123. concat(Ndbtuple *t1, Ndbtuple *t2)
  124. {
  125. Ndbtuple *t;
  126. if(t1 == nil)
  127. return t2;
  128. if(t2 == nil)
  129. return t1;
  130. t = t1;
  131. for(; t1->entry != nil; t1 = t1->entry)
  132. ;
  133. t1->entry = t1->line = t2;
  134. return t;
  135. }
  136. void
  137. removetuple(Ndbtuple **l, Ndbtuple *nt)
  138. {
  139. Ndbtuple *t;
  140. while(*l != nil){
  141. t = *l;
  142. if(strcmp(t->attr, nt->attr) == 0
  143. && strcmp(t->val, nt->val) == 0){
  144. *l = t->entry;
  145. free(t);
  146. } else
  147. l = &t->entry;
  148. }
  149. }
  150. void
  151. help(Attribute *e)
  152. {
  153. if(e->helper){
  154. print("--------------------------------\n");
  155. (*e->helper)(e);
  156. print("--------------------------------\n");
  157. }
  158. }
  159. Ndbtuple*
  160. need(int must, char *attr)
  161. {
  162. char *p;
  163. uchar ip[IPaddrlen];
  164. int i;
  165. Attribute *e;
  166. Ndbtuple *first, **l, *t;
  167. e = nil;
  168. for(i = 0; expl[i].attr != nil; i++){
  169. if(strcmp(expl[i].attr, attr) == 0){
  170. e = &expl[i];
  171. break;
  172. }
  173. }
  174. if(e == nil)
  175. return nil;
  176. first = nil;
  177. l = &first;
  178. for(;;){
  179. if(first != nil)
  180. must = 0;
  181. print("Enter%s %s (type ? for help%s)? ", first!=nil ? " another" : "",
  182. e->desc, must!=0 ? "" : ", return to skip");
  183. p = Brdline(&in, '\n');
  184. p[Blinelen(&in)-1] = 0;
  185. while(*p == ' ' || *p == '\t')
  186. p++;
  187. if(*p == '?'){
  188. help(e);
  189. continue;
  190. }
  191. if(*p == 0){
  192. if(must)
  193. continue;
  194. else
  195. break;
  196. }
  197. t = nil;
  198. switch(e->type){
  199. case Tip:
  200. parseip(ip, p);
  201. if(ipcmp(ip, IPnoaddr) == 0){
  202. print("!not an IP address\n");
  203. break;
  204. }
  205. t = newtuple(attr, p);
  206. break;
  207. case Tdom:
  208. if(strchr(p, '.') == nil && strchr(p, ':') == nil){
  209. print("!not an IP address or domain name\n");
  210. break;
  211. }
  212. t = newtuple(attr, p);
  213. break;
  214. case Tmask:
  215. parseipmask(ip, p);
  216. if(ipcmp(ip, IPnoaddr) == 0){
  217. print("!not an IP mask\n");
  218. break;
  219. }
  220. t = newtuple(attr, p);
  221. break;
  222. case Tstring:
  223. if(strchr(p, ' ')){
  224. print("!the string cannot contain spaces\n");
  225. break;
  226. }
  227. t = newtuple(attr, p);
  228. break;
  229. }
  230. if(t != nil){
  231. *l = t;
  232. l = &t->entry;
  233. }
  234. }
  235. return first;
  236. }
  237. void
  238. printnet(Ndbtuple *ndb, Ndbtuple *local, Ndbtuple *added)
  239. {
  240. uchar ip[IPaddrlen];
  241. uchar mask[IPaddrlen];
  242. uchar net[IPaddrlen];
  243. Ndbtuple *t;
  244. char **l;
  245. /* some little calculations */
  246. t = find("ip", ndb, local, added);
  247. if(t == nil)
  248. return;
  249. parseip(ip, t->val);
  250. t = find("ipmask", ndb, local, added);
  251. if(t != nil)
  252. parseipmask(mask, t->val);
  253. else
  254. ipmove(mask, defmask(ip));
  255. maskip(ip, mask, net);
  256. /* print out a sample network database */
  257. print("ipnet=mynet ip=%I ipmask=%M\n", net, mask);
  258. for(l = outvec; *l; l++){
  259. t = nil;
  260. while((t = findnext(t, *l, added, ndb, local)) != nil)
  261. print(" %s=%s\n", t->attr, t->val);
  262. }
  263. }
  264. void
  265. printauthdom(Ndbtuple *ndb, Ndbtuple *local, Ndbtuple *added)
  266. {
  267. Ndbtuple *t, *nt;
  268. t = find("authdom", ndb, local, added);
  269. if(t == nil)
  270. return;
  271. nt = nil;
  272. print("authdom=%s\n", t->val);
  273. while((nt = findnext(nt, "auth", ndb, local, added)) != nil)
  274. print("\tauth=%s\n", nt->val);
  275. }
  276. void
  277. printhost(Ndbtuple *added)
  278. {
  279. uchar ip[IPaddrlen];
  280. Ndbtuple *t;
  281. char **l;
  282. t = find("ip", added, nil, nil);
  283. if(t == nil)
  284. return;
  285. parseip(ip, t->val);
  286. print("ip=%I\n", ip);
  287. for(l = outvec; *l; l++){
  288. t = nil;
  289. while((t = findnext(t, *l, added, nil, nil)) != nil)
  290. print(" %s=%s\n", t->attr, t->val);
  291. }
  292. }
  293. void
  294. main(int argc, char **argv)
  295. {
  296. Ndbs s;
  297. char *net;
  298. char ndbfile[128];
  299. char authdomval[Ndbvlen];
  300. Ndb *db, *netdb;
  301. Ndbtuple *ndb, *local, *added, *nt, *t, *xt;
  302. fmtinstall('I', eipfmt);
  303. fmtinstall('M', eipfmt);
  304. db = ndbopen("/lib/ndb/local");
  305. Binit(&in, 0, OREAD);
  306. net = "/net";
  307. ARGBEGIN {
  308. case 'x':
  309. net = ARGF();
  310. if(net == nil)
  311. usage();
  312. break;
  313. } ARGEND;
  314. /* see what ipconfig knows */
  315. snprint(ndbfile, sizeof ndbfile, "%s/ndb", net);
  316. netdb = ndbopen(ndbfile);
  317. ndb = ndbparse(netdb);
  318. added = nil;
  319. /* ask user for ip address */
  320. t = find("ip", ndb, added, nil);
  321. if(t == nil){
  322. t = need(1, "ip");
  323. added = concat(added, t);
  324. }
  325. if(t == nil)
  326. sysfatal("cannot continue without your ip address");
  327. /* see what the database knows */
  328. local = ndbipinfo(db, "ip", t->val, vec, nelem(vec));
  329. /* get hostname */
  330. t = find("sys", ndb, local, added);
  331. if(t == nil){
  332. t = need(1, "sys");
  333. added = concat(added, t);
  334. }
  335. /* get auth server */
  336. t = find("auth", ndb, local, added);
  337. if(t == nil){
  338. t = need(0, "auth");
  339. added = concat(added, t);
  340. }
  341. if(t != nil){
  342. authserver = t->val;
  343. xt = ndbgetval(db, &s, "auth", t->val, "authdom", authdomval);
  344. for(nt = find("authdom", xt, nil, nil); nt != nil;
  345. nt = find("authdom", nt->entry, nil, nil))
  346. local = concat(local, duptuple(nt));
  347. ndbfree(xt);
  348. if(xt == nil){
  349. t = need(1, "authdom");
  350. added = concat(added, t);
  351. }
  352. }
  353. /* look for things we need */
  354. if(find("ipmask", added, ndb, local) == nil){
  355. t = need(0, "ipmask");
  356. added = concat(added, t);
  357. }
  358. if(find("dns", added, ndb, local) == nil){
  359. t = need(0, "dns");
  360. added = concat(added, t);
  361. }
  362. if(find("ntp", added, ndb, local) == nil){
  363. t = need(0, "ntp");
  364. added = concat(added, t);
  365. }
  366. if(find("fs", added, ndb, local) == nil){
  367. t = need(0, "fs");
  368. added = concat(added, t);
  369. }
  370. /* remove redundancy */
  371. for(t = local; t != nil; t = t->entry)
  372. removetuple(&ndb, t);
  373. print("======================================\n");
  374. print("recomended additions to /lib/ndb/local\n");
  375. print("======================================\n");
  376. if(added != nil)
  377. printnet(ndb, local, added);
  378. printauthdom(ndb, local, added);
  379. printhost(added);
  380. exits(0);
  381. }
  382. void
  383. authentication(void)
  384. {
  385. print("\tPlan 9 systems that accept connections from other Plan 9\n");
  386. print("\tsystems need to authenticate to each other. A set of secrets\n");
  387. print("\tand authentication servers to validate those secrets is\n");
  388. print("\tidentified by a string called an 'authentication domain'.\n");
  389. print("\tIf you expect anyone to 'cpu' to or 'import' from your machine,\n");
  390. print("\tyour machine must know its authentication domain and the\n");
  391. print("\tauthentication server(s) that validate keys for it.\n");
  392. }
  393. void
  394. authdomhelper(Attribute *)
  395. {
  396. authentication();
  397. print("\n\tEnter the authentication domain that is served by the\n");
  398. print("\tauthentication server '%s'.\n", authserver);
  399. }
  400. void
  401. authhelper(Attribute *)
  402. {
  403. authentication();
  404. print("\n\tEnter the name or address of the default authentication server\n");
  405. print("\tto be used by this system.\n");
  406. }
  407. void
  408. fshelper(Attribute *)
  409. {
  410. print("\tThis is only important if you are going to run diskless from\n");
  411. print("\ta remote server, i.e., if you wish to answer 'il' or 'tcp' to the\n");
  412. print("\t'root is from:' boot prompt.\n");
  413. }