arp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  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->used;
  67. for(f = a; f < e; f++){
  68. if(f->used < t){
  69. t = f->used;
  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->used = NOW;
  110. a->time = 0;
  111. a->type = m;
  112. a->rxtat = 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->used = 0;
  143. a->time = 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->used = 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. qunlock(arp);
  212. return nil;
  213. }
  214. /*
  215. * called with arp locked
  216. */
  217. void
  218. arprelease(Arp *arp, Arpent*)
  219. {
  220. qunlock(arp);
  221. }
  222. /*
  223. * Copy out the mac address from the Arpent. Return the
  224. * block waiting to get sent to this mac address.
  225. *
  226. * called with arp locked
  227. */
  228. Block*
  229. arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
  230. {
  231. Block *bp;
  232. Arpent *f, **l;
  233. if(!isv4(a->ip)){
  234. l = &arp->rxmt;
  235. for(f = *l; f; f = f->nextrxt){
  236. if(f == a){
  237. *l = a->nextrxt;
  238. break;
  239. }
  240. l = &f->nextrxt;
  241. }
  242. }
  243. memmove(a->mac, mac, type->maclen);
  244. a->type = type;
  245. a->state = AOK;
  246. a->used = NOW;
  247. bp = a->hold;
  248. a->hold = nil;
  249. qunlock(arp);
  250. return bp;
  251. }
  252. void
  253. arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
  254. {
  255. Arp *arp;
  256. Route *r;
  257. Arpent *a, *f, **l;
  258. Ipifc *ifc;
  259. Medium *type;
  260. Block *bp, *next;
  261. uchar v6ip[IPaddrlen];
  262. arp = fs->arp;
  263. if(n != 6){
  264. // print("arp: len = %d\n", n);
  265. return;
  266. }
  267. switch(version){
  268. case V4:
  269. r = v4lookup(fs, ip);
  270. v4tov6(v6ip, ip);
  271. ip = v6ip;
  272. break;
  273. case V6:
  274. r = v6lookup(fs, ip);
  275. break;
  276. default:
  277. panic("arpenter: version %d", version);
  278. return; /* to supress warnings */
  279. }
  280. if(r == nil){
  281. // print("arp: no route for entry\n");
  282. return;
  283. }
  284. ifc = r->ifc;
  285. type = ifc->m;
  286. qlock(arp);
  287. for(a = arp->hash[haship(ip)]; a; a = a->hash){
  288. if(a->type != type || (a->state != AWAIT && a->state != AOK))
  289. continue;
  290. if(ipcmp(a->ip, ip) == 0){
  291. a->state = AOK;
  292. memmove(a->mac, mac, type->maclen);
  293. if(version == V6){
  294. /* take out of re-transmit chain */
  295. l = &arp->rxmt;
  296. for(f = *l; f; f = f->nextrxt){
  297. if(f == a){
  298. *l = a->nextrxt;
  299. break;
  300. }
  301. l = &f->nextrxt;
  302. }
  303. }
  304. a->hold = nil;
  305. a->ifc = ifc;
  306. a->ifcid = ifc->ifcid;
  307. bp = a->hold;
  308. a->hold = nil;
  309. if(version == V4)
  310. ip += IPv4off;
  311. qunlock(arp);
  312. while(bp){
  313. next = bp->list;
  314. if(ifc != nil){
  315. if(waserror()){
  316. runlock(ifc);
  317. nexterror();
  318. }
  319. rlock(ifc);
  320. if(ifc->m != nil)
  321. ifc->m->bwrite(ifc, bp, version, ip);
  322. else
  323. freeb(bp);
  324. runlock(ifc);
  325. poperror();
  326. } else
  327. freeb(bp);
  328. bp = next;
  329. }
  330. a->used = NOW;
  331. return;
  332. }
  333. }
  334. if(refresh == 0){
  335. a = newarp6(arp, ip, ifc, 0);
  336. a->state = AOK;
  337. a->type = type;
  338. memmove(a->mac, mac, type->maclen);
  339. }
  340. qunlock(arp);
  341. }
  342. int
  343. arpwrite(Fs *fs, char *s, int len)
  344. {
  345. int n;
  346. Route *r;
  347. Arp *arp;
  348. Block *bp;
  349. Arpent *a;
  350. Medium *m;
  351. char *f[4], buf[256];
  352. uchar ip[IPaddrlen], mac[MAClen];
  353. arp = fs->arp;
  354. if(len == 0)
  355. error(Ebadarp);
  356. if(len >= sizeof(buf))
  357. len = sizeof(buf)-1;
  358. strncpy(buf, s, len);
  359. buf[len] = 0;
  360. if(len > 0 && buf[len-1] == '\n')
  361. buf[len-1] = 0;
  362. n = getfields(buf, f, 4, 1, " ");
  363. if(strcmp(f[0], "flush") == 0){
  364. qlock(arp);
  365. for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
  366. memset(a->ip, 0, sizeof(a->ip));
  367. memset(a->mac, 0, sizeof(a->mac));
  368. a->hash = nil;
  369. a->state = 0;
  370. a->used = 0;
  371. while(a->hold != nil){
  372. bp = a->hold->list;
  373. freeblist(a->hold);
  374. a->hold = bp;
  375. }
  376. }
  377. memset(arp->hash, 0, sizeof(arp->hash));
  378. // clear all pkts on these lists (rxmt, dropf/l)
  379. arp->rxmt = nil;
  380. arp->dropf = nil;
  381. arp->dropl = nil;
  382. qunlock(arp);
  383. } else if(strcmp(f[0], "add") == 0){
  384. switch(n){
  385. default:
  386. error(Ebadarg);
  387. case 3:
  388. parseip(ip, f[1]);
  389. if(isv4(ip))
  390. r = v4lookup(fs, ip+IPv4off);
  391. else
  392. r = v6lookup(fs, ip);
  393. if(r == nil)
  394. error("Destination unreachable");
  395. m = r->ifc->m;
  396. n = parsemac(mac, f[2], m->maclen);
  397. break;
  398. case 4:
  399. m = ipfindmedium(f[1]);
  400. if(m == nil)
  401. error(Ebadarp);
  402. parseip(ip, f[2]);
  403. n = parsemac(mac, f[3], m->maclen);
  404. break;
  405. }
  406. if(m->ares == nil)
  407. error(Ebadarp);
  408. m->ares(fs, V6, ip, mac, n, 0);
  409. } else
  410. error(Ebadarp);
  411. return len;
  412. }
  413. enum
  414. {
  415. Alinelen= 90,
  416. };
  417. char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
  418. static void
  419. convmac(char *p, uchar *mac, int n)
  420. {
  421. while(n-- > 0)
  422. p += sprint(p, "%2.2ux", *mac++);
  423. }
  424. int
  425. arpread(Arp *arp, char *p, ulong offset, int len)
  426. {
  427. Arpent *a;
  428. int n;
  429. char mac[2*MAClen+1];
  430. if(offset % Alinelen)
  431. return 0;
  432. offset = offset/Alinelen;
  433. len = len/Alinelen;
  434. n = 0;
  435. for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
  436. if(a->state == 0)
  437. continue;
  438. if(offset > 0){
  439. offset--;
  440. continue;
  441. }
  442. len--;
  443. qlock(arp);
  444. convmac(mac, a->mac, a->type->maclen);
  445. n += sprint(p+n, aformat, a->type->name, arpstate[a->state], a->ip, mac);
  446. qunlock(arp);
  447. }
  448. return n;
  449. }
  450. extern int
  451. rxmitsols(Arp *arp)
  452. {
  453. uint sflag;
  454. Block *next, *xp;
  455. Arpent *a, *b, **l;
  456. Fs *f;
  457. uchar ipsrc[IPaddrlen];
  458. Ipifc *ifc = nil;
  459. long nrxt;
  460. qlock(arp);
  461. f = arp->f;
  462. a = arp->rxmt;
  463. if(a==nil){
  464. nrxt = 0;
  465. goto dodrops; //return nrxt;
  466. }
  467. nrxt = a->rxtat - NOW;
  468. if(nrxt > 3*ReTransTimer/4)
  469. goto dodrops; //return nrxt;
  470. for(; a; a = a->nextrxt){
  471. ifc = a->ifc;
  472. assert(ifc != nil);
  473. if((a->rxtsrem <= 0) || !(canrlock(ifc)) || (a->ifcid != ifc->ifcid)){
  474. xp = a->hold;
  475. a->hold = nil;
  476. if(xp){
  477. if(arp->dropl == nil)
  478. arp->dropf = xp;
  479. else
  480. arp->dropl->list = xp;
  481. }
  482. cleanarpent(arp, a);
  483. }
  484. else
  485. break;
  486. }
  487. /* need to unlock arp, else will deadlock when icmpns
  488. * wants to lock arp later.
  489. */
  490. qunlock(arp);
  491. if(a == nil)
  492. goto dodrops; // return 0;
  493. if(sflag = ipv6anylocal(ifc, ipsrc))
  494. icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
  495. runlock(ifc);
  496. /* grab lock on arp again */
  497. qlock(arp);
  498. /* put to the end of re-transmit chain */
  499. l = &arp->rxmt;
  500. for(b = *l; b; b = b->nextrxt){
  501. if(b == a){
  502. *l = a->nextrxt;
  503. break;
  504. }
  505. l = &b->nextrxt;
  506. }
  507. for(b = *l; b; b = b->nextrxt){
  508. l = &b->nextrxt;
  509. }
  510. *l = a;
  511. a->rxtsrem--;
  512. a->nextrxt = nil;
  513. a->time = NOW;
  514. a->rxtat = NOW + ReTransTimer;
  515. a = arp->rxmt;
  516. if(a==nil)
  517. nrxt = 0;
  518. else
  519. nrxt = a->rxtat - NOW;
  520. dodrops:
  521. xp = arp->dropf;
  522. arp->dropf = nil;
  523. arp->dropl = nil;
  524. qunlock(arp);
  525. for(; xp; xp = next){
  526. next = xp->list;
  527. icmphostunr(f, ifc, xp, icmp6_adr_unreach, 1);
  528. }
  529. return nrxt;
  530. }
  531. static int
  532. rxready(void *v)
  533. {
  534. Arp *arp = (Arp *) v;
  535. int x;
  536. x = ((arp->rxmt != nil) || (arp->dropf != nil));
  537. return x;
  538. }
  539. static void
  540. rxmitproc(void *v)
  541. {
  542. Arp *arp = v;
  543. long wakeupat;
  544. arp->rxmitp = up;
  545. //print("arp rxmitproc started\n");
  546. if(waserror()){
  547. arp->rxmitp = 0;
  548. pexit("hangup", 1);
  549. }
  550. for(;;){
  551. wakeupat = rxmitsols(arp);
  552. if(wakeupat == 0)
  553. sleep(&arp->rxmtq, rxready, v);
  554. else if(wakeupat > ReTransTimer/4)
  555. tsleep(&arp->rxmtq, return0, 0, wakeupat);
  556. }
  557. }