arp.c 12 KB

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