arp.c 11 KB

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