arp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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. #include "ipv6.h"
  17. /*
  18. * address resolution tables
  19. */
  20. enum {
  21. NHASH = (1 << 6),
  22. NCACHE = 256,
  23. AOK = 1,
  24. AWAIT = 2,
  25. };
  26. char *arpstate[] =
  27. {
  28. "UNUSED",
  29. "OK",
  30. "WAIT",
  31. };
  32. /*
  33. * one per Fs
  34. */
  35. struct Arp {
  36. QLock ql;
  37. Fs *f;
  38. Arpent *hash[NHASH];
  39. Arpent cache[NCACHE];
  40. Arpent *rxmt;
  41. Proc *rxmitp; /* neib sol re-transmit proc */
  42. Rendez rxmtq;
  43. Block *dropf, *dropl;
  44. };
  45. char *Ebadarp = "bad arp";
  46. #define haship(s) ((s)[IPaddrlen - 1] % NHASH)
  47. int ReTransTimer = RETRANS_TIMER;
  48. static void rxmitproc(void *v);
  49. void
  50. arpinit(Fs *f)
  51. {
  52. f->arp = smalloc(sizeof(Arp));
  53. f->arp->f = f;
  54. f->arp->rxmt = nil;
  55. f->arp->dropf = f->arp->dropl = nil;
  56. kproc("rxmitproc", rxmitproc, f->arp);
  57. }
  58. /*
  59. * create a new arp entry for an ip address.
  60. */
  61. static Arpent *
  62. newarp6(Arp *arp, u8 *ip, Ipifc *ifc, int addrxt)
  63. {
  64. u32 t;
  65. Block *next, *xp;
  66. Arpent *a, *e, *f, **l;
  67. Medium *medium = ifc->medium;
  68. int empty;
  69. /* find oldest entry */
  70. e = &arp->cache[NCACHE];
  71. a = arp->cache;
  72. t = a->utime;
  73. for(f = a; f < e; f++){
  74. if(f->utime < t){
  75. t = f->utime;
  76. a = f;
  77. }
  78. }
  79. /* dump waiting packets */
  80. xp = a->hold;
  81. a->hold = nil;
  82. if(isv4(a->ip)){
  83. while(xp){
  84. next = xp->list;
  85. freeblist(xp);
  86. xp = next;
  87. }
  88. } else { /* queue icmp unreachable for rxmitproc later on, w/o arp lock */
  89. if(xp){
  90. if(arp->dropl == nil)
  91. arp->dropf = xp;
  92. else
  93. arp->dropl->list = xp;
  94. for(next = xp->list; next; next = next->list)
  95. xp = next;
  96. arp->dropl = xp;
  97. wakeup(&arp->rxmtq);
  98. }
  99. }
  100. /* take out of current chain */
  101. l = &arp->hash[haship(a->ip)];
  102. for(f = *l; f; f = f->hash){
  103. if(f == a){
  104. *l = a->hash;
  105. break;
  106. }
  107. l = &f->hash;
  108. }
  109. /* insert into new chain */
  110. l = &arp->hash[haship(ip)];
  111. a->hash = *l;
  112. *l = a;
  113. memmove(a->ip, ip, sizeof(a->ip));
  114. a->utime = NOW;
  115. a->ctime = 0;
  116. a->type = medium;
  117. a->rtime = NOW + ReTransTimer;
  118. a->rxtsrem = MAX_MULTICAST_SOLICIT;
  119. a->ifc = ifc;
  120. a->ifcid = ifc->ifcid;
  121. /* put to the end of re-transmit chain; addrxt is 0 when isv4(a->ip) */
  122. if(!ipismulticast(a->ip) && addrxt){
  123. l = &arp->rxmt;
  124. empty = (*l == nil);
  125. for(f = *l; f; f = f->nextrxt){
  126. if(f == a){
  127. *l = a->nextrxt;
  128. break;
  129. }
  130. l = &f->nextrxt;
  131. }
  132. for(f = *l; f; f = f->nextrxt){
  133. l = &f->nextrxt;
  134. }
  135. *l = a;
  136. if(empty)
  137. wakeup(&arp->rxmtq);
  138. }
  139. a->nextrxt = nil;
  140. return a;
  141. }
  142. /* called with arp qlocked */
  143. void
  144. cleanarpent(Arp *arp, Arpent *a)
  145. {
  146. Arpent *f, **l;
  147. a->utime = 0;
  148. a->ctime = 0;
  149. a->type = 0;
  150. a->state = 0;
  151. /* take out of current chain */
  152. l = &arp->hash[haship(a->ip)];
  153. for(f = *l; f; f = f->hash){
  154. if(f == a){
  155. *l = a->hash;
  156. break;
  157. }
  158. l = &f->hash;
  159. }
  160. /* take out of re-transmit chain */
  161. l = &arp->rxmt;
  162. for(f = *l; f; f = f->nextrxt){
  163. if(f == a){
  164. *l = a->nextrxt;
  165. break;
  166. }
  167. l = &f->nextrxt;
  168. }
  169. a->nextrxt = nil;
  170. a->hash = nil;
  171. a->hold = nil;
  172. a->last = nil;
  173. a->ifc = nil;
  174. }
  175. /*
  176. * fill in the media address if we have it. Otherwise return an
  177. * Arpent that represents the state of the address resolution FSM
  178. * for ip. Add the packet to be sent onto the list of packets
  179. * waiting for ip->mac to be resolved.
  180. */
  181. Arpent *
  182. arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, u8 *ip, u8 *mac)
  183. {
  184. int hash;
  185. Arpent *a;
  186. Medium *type = ifc->medium;
  187. u8 v6ip[IPaddrlen];
  188. if(version == V4){
  189. v4tov6(v6ip, ip);
  190. ip = v6ip;
  191. }
  192. qlock(&arp->ql);
  193. hash = haship(ip);
  194. for(a = arp->hash[hash]; a; a = a->hash){
  195. if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
  196. if(type == a->type)
  197. break;
  198. }
  199. if(a == nil){
  200. a = newarp6(arp, ip, ifc, (version != V4));
  201. a->state = AWAIT;
  202. }
  203. a->utime = NOW;
  204. if(a->state == AWAIT){
  205. if(bp != nil){
  206. if(a->hold)
  207. a->last->list = bp;
  208. else
  209. a->hold = bp;
  210. a->last = bp;
  211. bp->list = nil;
  212. }
  213. return a; /* return with arp qlocked */
  214. }
  215. memmove(mac, a->mac, a->type->maclen);
  216. /* remove old entries */
  217. if(NOW - a->ctime > 15 * 60 * 1000)
  218. cleanarpent(arp, a);
  219. qunlock(&arp->ql);
  220. return nil;
  221. }
  222. /*
  223. * called with arp locked
  224. */
  225. void
  226. arprelease(Arp *arp, Arpent *arpen)
  227. {
  228. qunlock(&arp->ql);
  229. }
  230. /*
  231. * Copy out the mac address from the Arpent. Return the
  232. * block waiting to get sent to this mac address.
  233. *
  234. * called with arp locked
  235. */
  236. Block *
  237. arpresolve(Arp *arp, Arpent *a, Medium *type, u8 *mac)
  238. {
  239. Block *bp;
  240. Arpent *f, **l;
  241. if(!isv4(a->ip)){
  242. l = &arp->rxmt;
  243. for(f = *l; f; f = f->nextrxt){
  244. if(f == a){
  245. *l = a->nextrxt;
  246. break;
  247. }
  248. l = &f->nextrxt;
  249. }
  250. }
  251. memmove(a->mac, mac, type->maclen);
  252. a->type = type;
  253. a->state = AOK;
  254. a->utime = NOW;
  255. bp = a->hold;
  256. a->hold = nil;
  257. qunlock(&arp->ql);
  258. return bp;
  259. }
  260. void
  261. arpenter(Fs *fs, int version, u8 *ip, u8 *mac, int n, int refresh)
  262. {
  263. Proc *up = externup();
  264. Arp *arp;
  265. Route *r;
  266. Arpent *a, *f, **l;
  267. Ipifc *ifc;
  268. Medium *type;
  269. Block *bp, *next;
  270. u8 v6ip[IPaddrlen];
  271. arp = fs->arp;
  272. if(n != 6){
  273. // print("arp: len = %d\n", n);
  274. return;
  275. }
  276. switch(version){
  277. case V4:
  278. r = v4lookup(fs, ip, nil);
  279. v4tov6(v6ip, ip);
  280. ip = v6ip;
  281. break;
  282. case V6:
  283. r = v6lookup(fs, ip, nil);
  284. break;
  285. default:
  286. panic("arpenter: version %d", version);
  287. return; /* to supress warnings */
  288. }
  289. if(r == nil){
  290. // print("arp: no route for entry\n");
  291. return;
  292. }
  293. ifc = r->RouteTree.ifc;
  294. type = ifc->medium;
  295. qlock(&arp->ql);
  296. for(a = arp->hash[haship(ip)]; a; a = a->hash){
  297. if(a->type != type || (a->state != AWAIT && a->state != AOK))
  298. continue;
  299. if(ipcmp(a->ip, ip) == 0){
  300. a->state = AOK;
  301. memmove(a->mac, mac, type->maclen);
  302. if(version == V6){
  303. /* take out of re-transmit chain */
  304. l = &arp->rxmt;
  305. for(f = *l; f; f = f->nextrxt){
  306. if(f == a){
  307. *l = a->nextrxt;
  308. break;
  309. }
  310. l = &f->nextrxt;
  311. }
  312. }
  313. a->ifc = ifc;
  314. a->ifcid = ifc->ifcid;
  315. bp = a->hold;
  316. a->hold = nil;
  317. if(version == V4)
  318. ip += IPv4off;
  319. a->utime = NOW;
  320. a->ctime = a->utime;
  321. qunlock(&arp->ql);
  322. while(bp){
  323. next = bp->list;
  324. if(ifc != nil){
  325. if(waserror()){
  326. runlock(&ifc->rwl);
  327. nexterror();
  328. }
  329. rlock(&ifc->rwl);
  330. if(ifc->medium != nil)
  331. ifc->medium->bwrite(ifc, bp, version, ip);
  332. else
  333. freeb(bp);
  334. runlock(&ifc->rwl);
  335. poperror();
  336. } else
  337. freeb(bp);
  338. bp = next;
  339. }
  340. return;
  341. }
  342. }
  343. if(refresh == 0){
  344. a = newarp6(arp, ip, ifc, 0);
  345. a->state = AOK;
  346. a->type = type;
  347. a->ctime = NOW;
  348. memmove(a->mac, mac, type->maclen);
  349. }
  350. qunlock(&arp->ql);
  351. }
  352. int
  353. arpwrite(Fs *fs, char *s, int len)
  354. {
  355. int n;
  356. Route *r;
  357. Arp *arp;
  358. Block *bp;
  359. Arpent *a, *fl, **l;
  360. Medium *medium;
  361. char *f[4], buf[256];
  362. u8 ip[IPaddrlen], mac[MAClen];
  363. arp = fs->arp;
  364. if(len == 0)
  365. error(Ebadarp);
  366. if(len >= sizeof(buf))
  367. len = sizeof(buf) - 1;
  368. strncpy(buf, s, len);
  369. buf[len] = 0;
  370. if(len > 0 && buf[len - 1] == '\n')
  371. buf[len - 1] = 0;
  372. n = getfields(buf, f, 4, 1, " ");
  373. if(strcmp(f[0], "flush") == 0){
  374. qlock(&arp->ql);
  375. for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
  376. memset(a->ip, 0, sizeof(a->ip));
  377. memset(a->mac, 0, sizeof(a->mac));
  378. a->hash = nil;
  379. a->state = 0;
  380. a->utime = 0;
  381. while(a->hold != nil){
  382. bp = a->hold->list;
  383. freeblist(a->hold);
  384. a->hold = bp;
  385. }
  386. }
  387. memset(arp->hash, 0, sizeof(arp->hash));
  388. /* clear all pkts on these lists (rxmt, dropf/l) */
  389. arp->rxmt = nil;
  390. arp->dropf = nil;
  391. arp->dropl = nil;
  392. qunlock(&arp->ql);
  393. } else if(strcmp(f[0], "add") == 0){
  394. switch(n){
  395. default:
  396. error(Ebadarg);
  397. case 3:
  398. if(parseip(ip, f[1]) == -1)
  399. error(Ebadip);
  400. if(isv4(ip))
  401. r = v4lookup(fs, ip + IPv4off, nil);
  402. else
  403. r = v6lookup(fs, ip, nil);
  404. if(r == nil)
  405. error("Destination unreachable");
  406. medium = r->RouteTree.ifc->medium;
  407. n = parsemac(mac, f[2], medium->maclen);
  408. break;
  409. case 4:
  410. medium = ipfindmedium(f[1]);
  411. if(medium == nil)
  412. error(Ebadarp);
  413. if(parseip(ip, f[2]) == -1)
  414. error(Ebadip);
  415. n = parsemac(mac, f[3], medium->maclen);
  416. break;
  417. }
  418. if(medium->ares == nil)
  419. error(Ebadarp);
  420. medium->ares(fs, V6, ip, mac, n, 0);
  421. } else if(strcmp(f[0], "del") == 0){
  422. if(n != 2)
  423. error(Ebadarg);
  424. if(parseip(ip, f[1]) == -1)
  425. error(Ebadip);
  426. qlock(&arp->ql);
  427. l = &arp->hash[haship(ip)];
  428. for(a = *l; a; a = a->hash){
  429. if(memcmp(ip, a->ip, sizeof(a->ip)) == 0){
  430. *l = a->hash;
  431. break;
  432. }
  433. l = &a->hash;
  434. }
  435. if(a){
  436. /* take out of re-transmit chain */
  437. l = &arp->rxmt;
  438. for(fl = *l; fl; fl = fl->nextrxt){
  439. if(fl == a){
  440. *l = a->nextrxt;
  441. break;
  442. }
  443. l = &fl->nextrxt;
  444. }
  445. a->nextrxt = nil;
  446. a->hash = nil;
  447. a->hold = nil;
  448. a->last = nil;
  449. a->ifc = nil;
  450. memset(a->ip, 0, sizeof(a->ip));
  451. memset(a->mac, 0, sizeof(a->mac));
  452. }
  453. qunlock(&arp->ql);
  454. } else
  455. error(Ebadarp);
  456. return len;
  457. }
  458. enum {
  459. Alinelen = 90,
  460. };
  461. char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
  462. static void
  463. convmac(char *p, char *ep, u8 *mac, int n)
  464. {
  465. while(n-- > 0)
  466. p = seprint(p, ep, "%2.2x", *mac++);
  467. }
  468. int
  469. arpread(Arp *arp, char *p, u32 offset, int len)
  470. {
  471. Arpent *a;
  472. int n;
  473. char mac[2 * MAClen + 1];
  474. if(offset % Alinelen)
  475. return 0;
  476. offset = offset / Alinelen;
  477. len = len / Alinelen;
  478. n = 0;
  479. for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
  480. if(a->state == 0)
  481. continue;
  482. if(offset > 0){
  483. offset--;
  484. continue;
  485. }
  486. len--;
  487. qlock(&arp->ql);
  488. convmac(mac, &mac[sizeof mac], a->mac, a->type->maclen);
  489. n += snprint(p + n, Alinelen + 1, aformat, a->type->name,
  490. arpstate[a->state], a->ip, mac); /* +1 for NUL */
  491. qunlock(&arp->ql);
  492. }
  493. return n;
  494. }
  495. extern int
  496. rxmitsols(Arp *arp)
  497. {
  498. u32 sflag;
  499. Block *next, *xp;
  500. Arpent *a, *b, **l;
  501. Fs *f;
  502. u8 ipsrc[IPaddrlen];
  503. Ipifc *ifc = nil;
  504. i32 nrxt;
  505. qlock(&arp->ql);
  506. f = arp->f;
  507. a = arp->rxmt;
  508. if(a == nil){
  509. nrxt = 0;
  510. goto dodrops; /* return nrxt; */
  511. }
  512. nrxt = a->rtime - NOW;
  513. if(nrxt > 3 * ReTransTimer / 4)
  514. goto dodrops; /* return nrxt; */
  515. for(; a; a = a->nextrxt){
  516. ifc = a->ifc;
  517. assert(ifc != nil);
  518. if((a->rxtsrem <= 0) || !(canrlock(&ifc->rwl)) || (a->ifcid != ifc->ifcid)){
  519. xp = a->hold;
  520. a->hold = nil;
  521. if(xp){
  522. if(arp->dropl == nil)
  523. arp->dropf = xp;
  524. else
  525. arp->dropl->list = xp;
  526. }
  527. cleanarpent(arp, a);
  528. } else
  529. break;
  530. }
  531. if(a == nil)
  532. goto dodrops;
  533. qunlock(&arp->ql); /* for icmpns */
  534. if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC)
  535. icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
  536. runlock(&ifc->rwl);
  537. qlock(&arp->ql);
  538. /* put to the end of re-transmit chain */
  539. l = &arp->rxmt;
  540. for(b = *l; b; b = b->nextrxt){
  541. if(b == a){
  542. *l = a->nextrxt;
  543. break;
  544. }
  545. l = &b->nextrxt;
  546. }
  547. for(b = *l; b; b = b->nextrxt){
  548. l = &b->nextrxt;
  549. }
  550. *l = a;
  551. a->rxtsrem--;
  552. a->nextrxt = nil;
  553. a->rtime = NOW + ReTransTimer;
  554. a = arp->rxmt;
  555. if(a == nil)
  556. nrxt = 0;
  557. else
  558. nrxt = a->rtime - NOW;
  559. dodrops:
  560. xp = arp->dropf;
  561. arp->dropf = nil;
  562. arp->dropl = nil;
  563. qunlock(&arp->ql);
  564. for(; xp; xp = next){
  565. next = xp->list;
  566. icmphostunr(f, ifc, xp, Icmp6_adr_unreach, 1);
  567. }
  568. return nrxt;
  569. }
  570. static int
  571. rxready(void *v)
  572. {
  573. Arp *arp = (Arp *)v;
  574. int x;
  575. x = ((arp->rxmt != nil) || (arp->dropf != nil));
  576. return x;
  577. }
  578. static void
  579. rxmitproc(void *v)
  580. {
  581. Proc *up = externup();
  582. Arp *arp = v;
  583. i32 wakeupat;
  584. arp->rxmitp = up;
  585. //print("arp rxmitproc started\n");
  586. if(waserror()){
  587. arp->rxmitp = 0;
  588. pexit("hangup", 1);
  589. }
  590. for(;;){
  591. wakeupat = rxmitsols(arp);
  592. if(wakeupat == 0)
  593. sleep(&arp->rxmtq, rxready, v);
  594. else if(wakeupat > ReTransTimer / 4)
  595. tsleep(&arp->rxmtq, return0, 0, wakeupat);
  596. }
  597. }