iproute.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "ip.h"
  16. static void walkadd(Fs*, Route**, Route*);
  17. static void addnode(Fs*, Route**, Route*);
  18. static void calcd(Route*);
  19. /* these are used for all instances of IP */
  20. static Route* v4freelist;
  21. static Route* v6freelist;
  22. static RWlock routelock;
  23. static uint32_t v4routegeneration, v6routegeneration;
  24. static void
  25. freeroute(Route *r)
  26. {
  27. Route **l;
  28. r->RouteTree.left = nil;
  29. r->RouteTree.right = nil;
  30. if(r->RouteTree.type & Rv4)
  31. l = &v4freelist;
  32. else
  33. l = &v6freelist;
  34. r->RouteTree.mid = *l;
  35. *l = r;
  36. }
  37. static Route*
  38. allocroute(int type)
  39. {
  40. Route *r;
  41. int n;
  42. Route **l;
  43. if(type & Rv4){
  44. n = sizeof(RouteTree) + sizeof(V4route);
  45. l = &v4freelist;
  46. } else {
  47. n = sizeof(RouteTree) + sizeof(V6route);
  48. l = &v6freelist;
  49. }
  50. r = *l;
  51. if(r != nil){
  52. *l = r->RouteTree.mid;
  53. } else {
  54. r = malloc(n);
  55. if(r == nil)
  56. panic("out of routing nodes");
  57. }
  58. memset(r, 0, n);
  59. r->RouteTree.type = type;
  60. r->RouteTree.ifc = nil;
  61. r->RouteTree.ref = 1;
  62. return r;
  63. }
  64. static void
  65. addqueue(Route **q, Route *r)
  66. {
  67. Route *l;
  68. if(r == nil)
  69. return;
  70. l = allocroute(r->RouteTree.type);
  71. l->RouteTree.mid = *q;
  72. *q = l;
  73. l->RouteTree.left = r;
  74. }
  75. /*
  76. * compare 2 v6 addresses
  77. */
  78. static int
  79. lcmp(uint32_t *a, uint32_t *b)
  80. {
  81. int i;
  82. for(i = 0; i < IPllen; i++){
  83. if(a[i] > b[i])
  84. return 1;
  85. if(a[i] < b[i])
  86. return -1;
  87. }
  88. return 0;
  89. }
  90. /*
  91. * compare 2 v4 or v6 ranges
  92. */
  93. enum
  94. {
  95. Rpreceeds,
  96. Rfollows,
  97. Requals,
  98. Rcontains,
  99. Rcontained,
  100. };
  101. static int
  102. rangecompare(Route *a, Route *b)
  103. {
  104. if(a->RouteTree.type & Rv4){
  105. if(a->v4.endaddress < b->v4.address)
  106. return Rpreceeds;
  107. if(a->v4.address > b->v4.endaddress)
  108. return Rfollows;
  109. if(a->v4.address <= b->v4.address
  110. && a->v4.endaddress >= b->v4.endaddress){
  111. if(a->v4.address == b->v4.address
  112. && a->v4.endaddress == b->v4.endaddress)
  113. return Requals;
  114. return Rcontains;
  115. }
  116. return Rcontained;
  117. }
  118. if(lcmp(a->v6.endaddress, b->v6.address) < 0)
  119. return Rpreceeds;
  120. if(lcmp(a->v6.address, b->v6.endaddress) > 0)
  121. return Rfollows;
  122. if(lcmp(a->v6.address, b->v6.address) <= 0
  123. && lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){
  124. if(lcmp(a->v6.address, b->v6.address) == 0
  125. && lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
  126. return Requals;
  127. return Rcontains;
  128. }
  129. return Rcontained;
  130. }
  131. static void
  132. copygate(Route *old, Route *new)
  133. {
  134. if(new->RouteTree.type & Rv4)
  135. memmove(old->v4.gate, new->v4.gate, IPv4addrlen);
  136. else
  137. memmove(old->v6.gate, new->v6.gate, IPaddrlen);
  138. }
  139. /*
  140. * walk down a tree adding nodes back in
  141. */
  142. static void
  143. walkadd(Fs *f, Route **root, Route *p)
  144. {
  145. Route *l, *r;
  146. l = p->RouteTree.left;
  147. r = p->RouteTree.right;
  148. p->RouteTree.left = 0;
  149. p->RouteTree.right = 0;
  150. addnode(f, root, p);
  151. if(l)
  152. walkadd(f, root, l);
  153. if(r)
  154. walkadd(f, root, r);
  155. }
  156. /*
  157. * calculate depth
  158. */
  159. static void
  160. calcd(Route *p)
  161. {
  162. Route *q;
  163. int d;
  164. if(p) {
  165. d = 0;
  166. q = p->RouteTree.left;
  167. if(q)
  168. d = q->RouteTree.depth;
  169. q = p->RouteTree.right;
  170. if(q && q->RouteTree.depth > d)
  171. d = q->RouteTree.depth;
  172. q = p->RouteTree.mid;
  173. if(q && q->RouteTree.depth > d)
  174. d = q->RouteTree.depth;
  175. p->RouteTree.depth = d+1;
  176. }
  177. }
  178. /*
  179. * balance the tree at the current node
  180. */
  181. static void
  182. balancetree(Route **cur)
  183. {
  184. Route *p, *l, *r;
  185. int dl, dr;
  186. /*
  187. * if left and right are
  188. * too out of balance,
  189. * rotate tree node
  190. */
  191. p = *cur;
  192. dl = 0; if((l = p->RouteTree.left) != nil) dl = l->RouteTree.depth;
  193. dr = 0; if((r = p->RouteTree.right) != nil) dr = r->RouteTree.depth;
  194. if(dl > dr+1) {
  195. p->RouteTree.left = l->RouteTree.right;
  196. l->RouteTree.right = p;
  197. *cur = l;
  198. calcd(p);
  199. calcd(l);
  200. } else
  201. if(dr > dl+1) {
  202. p->RouteTree.right = r->RouteTree.left;
  203. r->RouteTree.left = p;
  204. *cur = r;
  205. calcd(p);
  206. calcd(r);
  207. } else
  208. calcd(p);
  209. }
  210. /*
  211. * add a new node to the tree
  212. */
  213. static void
  214. addnode(Fs *f, Route **cur, Route *new)
  215. {
  216. Route *p;
  217. p = *cur;
  218. if(p == 0) {
  219. *cur = new;
  220. new->RouteTree.depth = 1;
  221. return;
  222. }
  223. switch(rangecompare(new, p)){
  224. case Rpreceeds:
  225. addnode(f, &p->RouteTree.left, new);
  226. break;
  227. case Rfollows:
  228. addnode(f, &p->RouteTree.right, new);
  229. break;
  230. case Rcontains:
  231. /*
  232. * if new node is superset
  233. * of tree node,
  234. * replace tree node and
  235. * queue tree node to be
  236. * merged into root.
  237. */
  238. *cur = new;
  239. new->RouteTree.depth = 1;
  240. addqueue(&f->queue, p);
  241. break;
  242. case Requals:
  243. /*
  244. * supercede the old entry if the old one isn't
  245. * a local interface.
  246. */
  247. if((p->RouteTree.type & Rifc) == 0){
  248. p->RouteTree.type = new->RouteTree.type;
  249. p->RouteTree.ifcid = -1;
  250. copygate(p, new);
  251. } else if(new->RouteTree.type & Rifc)
  252. p->RouteTree.ref++;
  253. freeroute(new);
  254. break;
  255. case Rcontained:
  256. addnode(f, &p->RouteTree.mid, new);
  257. break;
  258. }
  259. balancetree(cur);
  260. }
  261. #define V4H(a) ((a&0x07ffffff)>>(32-Lroot-5))
  262. void
  263. v4addroute(Fs *f, char *tag, uint8_t *a, uint8_t *mask, uint8_t *gate, int type)
  264. {
  265. Route *p;
  266. uint32_t sa;
  267. uint32_t m;
  268. uint32_t ea;
  269. int h, eh;
  270. m = nhgetl(mask);
  271. sa = nhgetl(a) & m;
  272. ea = sa | ~m;
  273. eh = V4H(ea);
  274. for(h=V4H(sa); h<=eh; h++) {
  275. p = allocroute(Rv4 | type);
  276. p->v4.address = sa;
  277. p->v4.endaddress = ea;
  278. memmove(p->v4.gate, gate, sizeof(p->v4.gate));
  279. memmove(p->RouteTree.tag, tag, sizeof(p->RouteTree.tag));
  280. wlock(&routelock);
  281. addnode(f, &f->v4root[h], p);
  282. while((p = f->queue) != nil){
  283. f->queue = p->RouteTree.mid;
  284. walkadd(f, &f->v4root[h], p->RouteTree.left);
  285. freeroute(p);
  286. }
  287. wunlock(&routelock);
  288. }
  289. v4routegeneration++;
  290. ipifcaddroute(f, Rv4, a, mask, gate, type);
  291. }
  292. #define V6H(a) (((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))
  293. #define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
  294. void
  295. v6addroute(Fs *f, char *tag, uint8_t *a, uint8_t *mask, uint8_t *gate, int type)
  296. {
  297. Route *p;
  298. uint32_t sa[IPllen], ea[IPllen];
  299. uint32_t x, y;
  300. int h, eh;
  301. /*
  302. if(ISDFLT(a, mask, tag))
  303. f->v6p->cdrouter = -1;
  304. */
  305. for(h = 0; h < IPllen; h++){
  306. x = nhgetl(a+4*h);
  307. y = nhgetl(mask+4*h);
  308. sa[h] = x & y;
  309. ea[h] = x | ~y;
  310. }
  311. eh = V6H(ea);
  312. for(h = V6H(sa); h <= eh; h++) {
  313. p = allocroute(type);
  314. memmove(p->v6.address, sa, IPaddrlen);
  315. memmove(p->v6.endaddress, ea, IPaddrlen);
  316. memmove(p->v6.gate, gate, IPaddrlen);
  317. memmove(p->RouteTree.tag, tag, sizeof(p->RouteTree.tag));
  318. wlock(&routelock);
  319. addnode(f, &f->v6root[h], p);
  320. while((p = f->queue) != nil){
  321. f->queue = p->RouteTree.mid;
  322. walkadd(f, &f->v6root[h], p->RouteTree.left);
  323. freeroute(p);
  324. }
  325. wunlock(&routelock);
  326. }
  327. v6routegeneration++;
  328. ipifcaddroute(f, 0, a, mask, gate, type);
  329. }
  330. Route**
  331. looknode(Route **cur, Route *r)
  332. {
  333. Route *p;
  334. for(;;){
  335. p = *cur;
  336. if(p == 0)
  337. return 0;
  338. switch(rangecompare(r, p)){
  339. case Rcontains:
  340. return 0;
  341. case Rpreceeds:
  342. cur = &p->RouteTree.left;
  343. break;
  344. case Rfollows:
  345. cur = &p->RouteTree.right;
  346. break;
  347. case Rcontained:
  348. cur = &p->RouteTree.mid;
  349. break;
  350. case Requals:
  351. return cur;
  352. }
  353. }
  354. }
  355. void
  356. v4delroute(Fs *f, uint8_t *a, uint8_t *mask, int dolock)
  357. {
  358. Route **r, *p;
  359. Route rt;
  360. int h, eh;
  361. uint32_t m;
  362. m = nhgetl(mask);
  363. rt.v4.address = nhgetl(a) & m;
  364. rt.v4.endaddress = rt.v4.address | ~m;
  365. rt.RouteTree.type = Rv4;
  366. eh = V4H(rt.v4.endaddress);
  367. for(h=V4H(rt.v4.address); h<=eh; h++) {
  368. if(dolock)
  369. wlock(&routelock);
  370. r = looknode(&f->v4root[h], &rt);
  371. if(r) {
  372. p = *r;
  373. if(--(p->RouteTree.ref) == 0){
  374. *r = 0;
  375. addqueue(&f->queue, p->RouteTree.left);
  376. addqueue(&f->queue, p->RouteTree.mid);
  377. addqueue(&f->queue, p->RouteTree.right);
  378. freeroute(p);
  379. while((p = f->queue) != nil){
  380. f->queue = p->RouteTree.mid;
  381. walkadd(f, &f->v4root[h], p->RouteTree.left);
  382. freeroute(p);
  383. }
  384. }
  385. }
  386. if(dolock)
  387. wunlock(&routelock);
  388. }
  389. v4routegeneration++;
  390. ipifcremroute(f, Rv4, a, mask);
  391. }
  392. void
  393. v6delroute(Fs *f, uint8_t *a, uint8_t *mask, int dolock)
  394. {
  395. Route **r, *p;
  396. Route rt;
  397. int h, eh;
  398. uint32_t x, y;
  399. for(h = 0; h < IPllen; h++){
  400. x = nhgetl(a+4*h);
  401. y = nhgetl(mask+4*h);
  402. rt.v6.address[h] = x & y;
  403. rt.v6.endaddress[h] = x | ~y;
  404. }
  405. rt.RouteTree.type = 0;
  406. eh = V6H(rt.v6.endaddress);
  407. for(h=V6H(rt.v6.address); h<=eh; h++) {
  408. if(dolock)
  409. wlock(&routelock);
  410. r = looknode(&f->v6root[h], &rt);
  411. if(r) {
  412. p = *r;
  413. if(--(p->RouteTree.ref) == 0){
  414. *r = 0;
  415. addqueue(&f->queue, p->RouteTree.left);
  416. addqueue(&f->queue, p->RouteTree.mid);
  417. addqueue(&f->queue, p->RouteTree.right);
  418. freeroute(p);
  419. while((p = f->queue) != nil){
  420. f->queue = p->RouteTree.mid;
  421. walkadd(f, &f->v6root[h], p->RouteTree.left);
  422. freeroute(p);
  423. }
  424. }
  425. }
  426. if(dolock)
  427. wunlock(&routelock);
  428. }
  429. v6routegeneration++;
  430. ipifcremroute(f, 0, a, mask);
  431. }
  432. Route*
  433. v4lookup(Fs *f, uint8_t *a, Conv *c)
  434. {
  435. Route *p, *q;
  436. uint32_t la;
  437. uint8_t gate[IPaddrlen];
  438. Ipifc *ifc;
  439. if(c != nil && c->r != nil && c->r->RouteTree.ifc != nil && c->rgen == v4routegeneration)
  440. return c->r;
  441. la = nhgetl(a);
  442. q = nil;
  443. for(p=f->v4root[V4H(la)]; p;)
  444. if(la >= p->v4.address) {
  445. if(la <= p->v4.endaddress) {
  446. q = p;
  447. p = p->RouteTree.mid;
  448. } else
  449. p = p->RouteTree.right;
  450. } else
  451. p = p->RouteTree.left;
  452. if(q && (q->RouteTree.ifc == nil || q->RouteTree.ifcid != q->RouteTree.ifc->ifcid)){
  453. if(q->RouteTree.type & Rifc) {
  454. hnputl(gate+IPv4off, q->v4.address);
  455. memmove(gate, v4prefix, IPv4off);
  456. } else
  457. v4tov6(gate, q->v4.gate);
  458. ifc = findipifc(f, gate, q->RouteTree.type);
  459. if(ifc == nil)
  460. return nil;
  461. q->RouteTree.ifc = ifc;
  462. q->RouteTree.ifcid = ifc->ifcid;
  463. }
  464. if(c != nil){
  465. c->r = q;
  466. c->rgen = v4routegeneration;
  467. }
  468. return q;
  469. }
  470. Route*
  471. v6lookup(Fs *f, uint8_t *a, Conv *c)
  472. {
  473. Route *p, *q;
  474. uint32_t la[IPllen];
  475. int h;
  476. uint32_t x, y;
  477. uint8_t gate[IPaddrlen];
  478. Ipifc *ifc;
  479. if(memcmp(a, v4prefix, IPv4off) == 0){
  480. q = v4lookup(f, a+IPv4off, c);
  481. if(q != nil)
  482. return q;
  483. }
  484. if(c != nil && c->r != nil && c->r->RouteTree.ifc != nil && c->rgen == v6routegeneration)
  485. return c->r;
  486. for(h = 0; h < IPllen; h++)
  487. la[h] = nhgetl(a+4*h);
  488. q = 0;
  489. for(p=f->v6root[V6H(la)]; p;){
  490. for(h = 0; h < IPllen; h++){
  491. x = la[h];
  492. y = p->v6.address[h];
  493. if(x == y)
  494. continue;
  495. if(x < y){
  496. p = p->RouteTree.left;
  497. goto next;
  498. }
  499. break;
  500. }
  501. for(h = 0; h < IPllen; h++){
  502. x = la[h];
  503. y = p->v6.endaddress[h];
  504. if(x == y)
  505. continue;
  506. if(x > y){
  507. p = p->RouteTree.right;
  508. goto next;
  509. }
  510. break;
  511. }
  512. q = p;
  513. p = p->RouteTree.mid;
  514. next: ;
  515. }
  516. if(q && (q->RouteTree.ifc == nil || q->RouteTree.ifcid != q->RouteTree.ifc->ifcid)){
  517. if(q->RouteTree.type & Rifc) {
  518. for(h = 0; h < IPllen; h++)
  519. hnputl(gate+4*h, q->v6.address[h]);
  520. ifc = findipifc(f, gate, q->RouteTree.type);
  521. } else
  522. ifc = findipifc(f, q->v6.gate, q->RouteTree.type);
  523. if(ifc == nil)
  524. return nil;
  525. q->RouteTree.ifc = ifc;
  526. q->RouteTree.ifcid = ifc->ifcid;
  527. }
  528. if(c != nil){
  529. c->r = q;
  530. c->rgen = v6routegeneration;
  531. }
  532. return q;
  533. }
  534. void
  535. routetype(int type, char *p)
  536. {
  537. memset(p, ' ', 4);
  538. p[4] = 0;
  539. if(type & Rv4)
  540. *p++ = '4';
  541. else
  542. *p++ = '6';
  543. if(type & Rifc)
  544. *p++ = 'i';
  545. if(type & Runi)
  546. *p++ = 'u';
  547. else if(type & Rbcast)
  548. *p++ = 'b';
  549. else if(type & Rmulti)
  550. *p++ = 'm';
  551. if(type & Rptpt)
  552. *p = 'p';
  553. }
  554. static char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
  555. void
  556. convroute(Route *r, uint8_t *addr, uint8_t *mask, uint8_t *gate, char *t, int *nifc)
  557. {
  558. int i;
  559. if(r->RouteTree.type & Rv4){
  560. memmove(addr, v4prefix, IPv4off);
  561. hnputl(addr+IPv4off, r->v4.address);
  562. memset(mask, 0xff, IPv4off);
  563. hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));
  564. memmove(gate, v4prefix, IPv4off);
  565. memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);
  566. } else {
  567. for(i = 0; i < IPllen; i++){
  568. hnputl(addr + 4*i, r->v6.address[i]);
  569. hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
  570. }
  571. memmove(gate, r->v6.gate, IPaddrlen);
  572. }
  573. routetype(r->RouteTree.type, t);
  574. if(r->RouteTree.ifc)
  575. *nifc = r->RouteTree.ifc->conv->x;
  576. else
  577. *nifc = -1;
  578. }
  579. /*
  580. * this code is not in rr to reduce stack size
  581. */
  582. static void
  583. sprintroute(Route *r, Routewalk *rw)
  584. {
  585. int nifc, n;
  586. char t[5], *iname, ifbuf[5];
  587. uint8_t addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
  588. char *p;
  589. convroute(r, addr, mask, gate, t, &nifc);
  590. iname = "-";
  591. if(nifc != -1) {
  592. iname = ifbuf;
  593. snprint(ifbuf, sizeof ifbuf, "%d", nifc);
  594. }
  595. p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->RouteTree.tag, iname);
  596. if(rw->o < 0){
  597. n = p - rw->p;
  598. if(n > -rw->o){
  599. memmove(rw->p, rw->p-rw->o, n+rw->o);
  600. rw->p = p + rw->o;
  601. }
  602. rw->o += n;
  603. } else
  604. rw->p = p;
  605. }
  606. /*
  607. * recurse descending tree, applying the function in Routewalk
  608. */
  609. static int
  610. rr(Route *r, Routewalk *rw)
  611. {
  612. int h;
  613. if(rw->e <= rw->p)
  614. return 0;
  615. if(r == nil)
  616. return 1;
  617. if(rr(r->RouteTree.left, rw) == 0)
  618. return 0;
  619. if(r->RouteTree.type & Rv4)
  620. h = V4H(r->v4.address);
  621. else
  622. h = V6H(r->v6.address);
  623. if(h == rw->h)
  624. rw->walk(r, rw);
  625. if(rr(r->RouteTree.mid, rw) == 0)
  626. return 0;
  627. return rr(r->RouteTree.right, rw);
  628. }
  629. void
  630. ipwalkroutes(Fs *f, Routewalk *rw)
  631. {
  632. rlock(&routelock);
  633. if(rw->e > rw->p) {
  634. for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)
  635. if(rr(f->v4root[rw->h], rw) == 0)
  636. break;
  637. }
  638. if(rw->e > rw->p) {
  639. for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)
  640. if(rr(f->v6root[rw->h], rw) == 0)
  641. break;
  642. }
  643. runlock(&routelock);
  644. }
  645. int32_t
  646. routeread(Fs *f, char *p, uint32_t offset, int n)
  647. {
  648. Routewalk rw;
  649. rw.p = p;
  650. rw.e = p+n;
  651. rw.o = -offset;
  652. rw.walk = sprintroute;
  653. ipwalkroutes(f, &rw);
  654. return rw.p - p;
  655. }
  656. /*
  657. * this code is not in routeflush to reduce stack size
  658. */
  659. void
  660. delroute(Fs *f, Route *r, int dolock)
  661. {
  662. uint8_t addr[IPaddrlen];
  663. uint8_t mask[IPaddrlen];
  664. uint8_t gate[IPaddrlen];
  665. char t[5];
  666. int nifc;
  667. convroute(r, addr, mask, gate, t, &nifc);
  668. if(r->RouteTree.type & Rv4)
  669. v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
  670. else
  671. v6delroute(f, addr, mask, dolock);
  672. }
  673. /*
  674. * recurse until one route is deleted
  675. * returns 0 if nothing is deleted, 1 otherwise
  676. */
  677. int
  678. routeflush(Fs *f, Route *r, char *tag)
  679. {
  680. if(r == nil)
  681. return 0;
  682. if(routeflush(f, r->RouteTree.mid, tag))
  683. return 1;
  684. if(routeflush(f, r->RouteTree.left, tag))
  685. return 1;
  686. if(routeflush(f, r->RouteTree.right, tag))
  687. return 1;
  688. if((r->RouteTree.type & Rifc) == 0){
  689. if(tag == nil || strncmp(tag, r->RouteTree.tag, sizeof(r->RouteTree.tag)) == 0){
  690. delroute(f, r, 0);
  691. return 1;
  692. }
  693. }
  694. return 0;
  695. }
  696. Route *
  697. iproute(Fs *fs, uint8_t *ip)
  698. {
  699. if(isv4(ip))
  700. return v4lookup(fs, ip+IPv4off, nil);
  701. else
  702. return v6lookup(fs, ip, nil);
  703. }
  704. static void
  705. printroute(Route *r)
  706. {
  707. int nifc;
  708. char t[5], *iname, ifbuf[5];
  709. uint8_t addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
  710. convroute(r, addr, mask, gate, t, &nifc);
  711. iname = "-";
  712. if(nifc != -1) {
  713. iname = ifbuf;
  714. snprint(ifbuf, sizeof ifbuf, "%d", nifc);
  715. }
  716. print(rformat, addr, mask, gate, t, r->RouteTree.tag, iname);
  717. }
  718. int32_t
  719. routewrite(Fs *f, Chan *c, char *p, int n)
  720. {
  721. Proc *up = externup();
  722. int h, changed;
  723. char *tag;
  724. Cmdbuf *cb;
  725. uint8_t addr[IPaddrlen];
  726. uint8_t mask[IPaddrlen];
  727. uint8_t gate[IPaddrlen];
  728. IPaux *a, *na;
  729. Route *q;
  730. cb = parsecmd(p, n);
  731. if(waserror()){
  732. free(cb);
  733. nexterror();
  734. }
  735. if(strcmp(cb->f[0], "flush") == 0){
  736. tag = cb->f[1];
  737. for(h = 0; h < nelem(f->v4root); h++)
  738. for(changed = 1; changed;){
  739. wlock(&routelock);
  740. changed = routeflush(f, f->v4root[h], tag);
  741. wunlock(&routelock);
  742. }
  743. for(h = 0; h < nelem(f->v6root); h++)
  744. for(changed = 1; changed;){
  745. wlock(&routelock);
  746. changed = routeflush(f, f->v6root[h], tag);
  747. wunlock(&routelock);
  748. }
  749. } else if(strcmp(cb->f[0], "remove") == 0){
  750. if(cb->nf < 3)
  751. error(Ebadarg);
  752. if (parseip(addr, cb->f[1]) == -1)
  753. error(Ebadip);
  754. parseipmask(mask, cb->f[2]);
  755. if(memcmp(addr, v4prefix, IPv4off) == 0)
  756. v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
  757. else
  758. v6delroute(f, addr, mask, 1);
  759. } else if(strcmp(cb->f[0], "add") == 0){
  760. if(cb->nf < 4)
  761. error(Ebadarg);
  762. if(parseip(addr, cb->f[1]) == -1 ||
  763. parseip(gate, cb->f[3]) == -1)
  764. error(Ebadip);
  765. parseipmask(mask, cb->f[2]);
  766. tag = "none";
  767. if(c != nil){
  768. a = c->aux;
  769. tag = a->tag;
  770. }
  771. if(memcmp(addr, v4prefix, IPv4off) == 0)
  772. v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
  773. else
  774. v6addroute(f, tag, addr, mask, gate, 0);
  775. } else if(strcmp(cb->f[0], "tag") == 0) {
  776. if(cb->nf < 2)
  777. error(Ebadarg);
  778. a = c->aux;
  779. na = newipaux(a->owner, cb->f[1]);
  780. c->aux = na;
  781. free(a);
  782. } else if(strcmp(cb->f[0], "route") == 0) {
  783. if(cb->nf < 2)
  784. error(Ebadarg);
  785. if (parseip(addr, cb->f[1]) == -1)
  786. error(Ebadip);
  787. q = iproute(f, addr);
  788. print("%I: ", addr);
  789. if(q == nil)
  790. print("no route\n");
  791. else
  792. printroute(q);
  793. }
  794. poperror();
  795. free(cb);
  796. return n;
  797. }