ethermedium.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  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 "../port/netif.h"
  16. #include "ip.h"
  17. #include "ipv6.h"
  18. typedef struct Etherhdr Etherhdr;
  19. struct Etherhdr
  20. {
  21. uchar d[6];
  22. uchar s[6];
  23. uchar t[2];
  24. };
  25. static uchar ipbroadcast[IPaddrlen] = {
  26. 0xff,0xff,0xff,0xff,
  27. 0xff,0xff,0xff,0xff,
  28. 0xff,0xff,0xff,0xff,
  29. 0xff,0xff,0xff,0xff,
  30. };
  31. static uchar etherbroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  32. static void etherread4(void *a);
  33. static void etherread6(void *a);
  34. static void etherbind(Ipifc *ifc, int argc, char **argv);
  35. static void etherunbind(Ipifc *ifc);
  36. static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
  37. static void etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
  38. static void etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
  39. static Block* multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
  40. static void sendarp(Ipifc *ifc, Arpent *a);
  41. static void sendgarp(Ipifc *ifc, uchar*);
  42. static int multicastea(uchar *ea, uchar *ip);
  43. static void recvarpproc(void*);
  44. static void resolveaddr6(Ipifc *ifc, Arpent *a);
  45. static void etherpref2addr(uchar *pref, uchar *ea);
  46. Medium ethermedium =
  47. {
  48. .name= "ether",
  49. .hsize= 14,
  50. .mintu= 60,
  51. .maxtu= 1514,
  52. .maclen= 6,
  53. .bind= etherbind,
  54. .unbind= etherunbind,
  55. .bwrite= etherbwrite,
  56. .addmulti= etheraddmulti,
  57. .remmulti= etherremmulti,
  58. .ares= arpenter,
  59. .areg= sendgarp,
  60. .pref2addr= etherpref2addr,
  61. };
  62. Medium gbemedium =
  63. {
  64. .name= "gbe",
  65. .hsize= 14,
  66. .mintu= 60,
  67. .maxtu= 9014,
  68. .maclen= 6,
  69. .bind= etherbind,
  70. .unbind= etherunbind,
  71. .bwrite= etherbwrite,
  72. .addmulti= etheraddmulti,
  73. .remmulti= etherremmulti,
  74. .ares= arpenter,
  75. .areg= sendgarp,
  76. .pref2addr= etherpref2addr,
  77. };
  78. typedef struct Etherrock Etherrock;
  79. struct Etherrock
  80. {
  81. Fs *f; /* file system we belong to */
  82. Proc *arpp; /* arp process */
  83. Proc *read4p; /* reading process (v4)*/
  84. Proc *read6p; /* reading process (v6)*/
  85. Chan *mchan4; /* Data channel for v4 */
  86. Chan *achan; /* Arp channel */
  87. Chan *cchan4; /* Control channel for v4 */
  88. Chan *mchan6; /* Data channel for v6 */
  89. Chan *cchan6; /* Control channel for v6 */
  90. };
  91. /*
  92. * ethernet arp request
  93. */
  94. enum
  95. {
  96. ARPREQUEST = 1,
  97. ARPREPLY = 2,
  98. };
  99. typedef struct Etherarp Etherarp;
  100. struct Etherarp
  101. {
  102. uchar d[6];
  103. uchar s[6];
  104. uchar type[2];
  105. uchar hrd[2];
  106. uchar pro[2];
  107. uchar hln;
  108. uchar pln;
  109. uchar op[2];
  110. uchar sha[6];
  111. uchar spa[4];
  112. uchar tha[6];
  113. uchar tpa[4];
  114. };
  115. static char *nbmsg = "nonblocking";
  116. /*
  117. * called to bind an IP ifc to an ethernet device
  118. * called with ifc wlock'd
  119. */
  120. static void
  121. etherbind(Ipifc *ifc, int argc, char **argv)
  122. {
  123. Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;
  124. char addr[Maxpath]; //char addr[2*KNAMELEN];
  125. char dir[Maxpath]; //char dir[2*KNAMELEN];
  126. char *buf;
  127. int n;
  128. char *ptr;
  129. Etherrock *er;
  130. if(argc < 2)
  131. error(Ebadarg);
  132. mchan4 = cchan4 = achan = mchan6 = cchan6 = nil;
  133. buf = nil;
  134. if(waserror()){
  135. if(mchan4 != nil)
  136. cclose(mchan4);
  137. if(cchan4 != nil)
  138. cclose(cchan4);
  139. if(achan != nil)
  140. cclose(achan);
  141. if(mchan6 != nil)
  142. cclose(mchan6);
  143. if(cchan6 != nil)
  144. cclose(cchan6);
  145. if(buf != nil)
  146. free(buf);
  147. nexterror();
  148. }
  149. /*
  150. * open ipv4 conversation
  151. *
  152. * the dial will fail if the type is already open on
  153. * this device.
  154. */
  155. snprint(addr, sizeof(addr), "%s!0x800", argv[2]); /* ETIP4 */
  156. mchan4 = chandial(addr, nil, dir, &cchan4);
  157. /*
  158. * make it non-blocking
  159. */
  160. devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
  161. /*
  162. * get mac address and speed
  163. */
  164. snprint(addr, sizeof(addr), "%s/stats", argv[2]);
  165. buf = smalloc(512);
  166. schan = namec(addr, Aopen, OREAD, 0);
  167. if(waserror()){
  168. cclose(schan);
  169. nexterror();
  170. }
  171. n = devtab[schan->type]->read(schan, buf, 511, 0);
  172. cclose(schan);
  173. poperror();
  174. buf[n] = 0;
  175. ptr = strstr(buf, "addr: ");
  176. if(!ptr)
  177. error(Eio);
  178. ptr += 6;
  179. parsemac(ifc->mac, ptr, 6);
  180. ptr = strstr(buf, "mbps: ");
  181. if(ptr){
  182. ptr += 6;
  183. ifc->mbps = atoi(ptr);
  184. } else
  185. ifc->mbps = 100;
  186. /*
  187. * open arp conversation
  188. */
  189. snprint(addr, sizeof(addr), "%s!0x806", argv[2]); /* ETARP */
  190. achan = chandial(addr, nil, nil, nil);
  191. /*
  192. * open ipv6 conversation
  193. *
  194. * the dial will fail if the type is already open on
  195. * this device.
  196. */
  197. snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]); /* ETIP6 */
  198. mchan6 = chandial(addr, nil, dir, &cchan6);
  199. /*
  200. * make it non-blocking
  201. */
  202. devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
  203. er = smalloc(sizeof(*er));
  204. er->mchan4 = mchan4;
  205. er->cchan4 = cchan4;
  206. er->achan = achan;
  207. er->mchan6 = mchan6;
  208. er->cchan6 = cchan6;
  209. er->f = ifc->conv->p->f;
  210. ifc->arg = er;
  211. free(buf);
  212. poperror();
  213. kproc("etherread4", etherread4, ifc);
  214. kproc("recvarpproc", recvarpproc, ifc);
  215. kproc("etherread6", etherread6, ifc);
  216. }
  217. /*
  218. * called with ifc wlock'd
  219. */
  220. static void
  221. etherunbind(Ipifc *ifc)
  222. {
  223. Etherrock *er = ifc->arg;
  224. if(er->read4p)
  225. postnote(er->read4p, 1, "unbind", 0);
  226. if(er->read6p)
  227. postnote(er->read6p, 1, "unbind", 0);
  228. if(er->arpp)
  229. postnote(er->arpp, 1, "unbind", 0);
  230. /* wait for readers to die */
  231. while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0)
  232. tsleep(&up->sleep, return0, 0, 300);
  233. if(er->mchan4 != nil)
  234. cclose(er->mchan4);
  235. if(er->achan != nil)
  236. cclose(er->achan);
  237. if(er->cchan4 != nil)
  238. cclose(er->cchan4);
  239. if(er->mchan6 != nil)
  240. cclose(er->mchan6);
  241. if(er->cchan6 != nil)
  242. cclose(er->cchan6);
  243. free(er);
  244. }
  245. /*
  246. * called by ipoput with a single block to write with ifc rlock'd
  247. */
  248. static void
  249. etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
  250. {
  251. Etherhdr *eh;
  252. Arpent *a;
  253. uchar mac[6];
  254. Etherrock *er = ifc->arg;
  255. /* get mac address of destination */
  256. a = arpget(er->f->arp, bp, version, ifc, ip, mac);
  257. if(a){
  258. /* check for broadcast or multicast */
  259. bp = multicastarp(er->f, a, ifc->m, mac);
  260. if(bp==nil){
  261. switch(version){
  262. case V4:
  263. sendarp(ifc, a);
  264. break;
  265. case V6:
  266. resolveaddr6(ifc, a);
  267. break;
  268. default:
  269. panic("etherbwrite: version %d", version);
  270. }
  271. return;
  272. }
  273. }
  274. /* make it a single block with space for the ether header */
  275. bp = padblock(bp, ifc->m->hsize);
  276. if(bp->next)
  277. bp = concatblock(bp);
  278. if(BLEN(bp) < ifc->mintu)
  279. bp = adjustblock(bp, ifc->mintu);
  280. eh = (Etherhdr*)bp->rp;
  281. /* copy in mac addresses and ether type */
  282. memmove(eh->s, ifc->mac, sizeof(eh->s));
  283. memmove(eh->d, mac, sizeof(eh->d));
  284. switch(version){
  285. case V4:
  286. eh->t[0] = 0x08;
  287. eh->t[1] = 0x00;
  288. devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0);
  289. break;
  290. case V6:
  291. eh->t[0] = 0x86;
  292. eh->t[1] = 0xDD;
  293. devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);
  294. break;
  295. default:
  296. panic("etherbwrite2: version %d", version);
  297. }
  298. ifc->out++;
  299. }
  300. /*
  301. * process to read from the ethernet
  302. */
  303. static void
  304. etherread4(void *a)
  305. {
  306. Ipifc *ifc;
  307. Block *bp;
  308. Etherrock *er;
  309. ifc = a;
  310. er = ifc->arg;
  311. er->read4p = up; /* hide identity under a rock for unbind */
  312. if(waserror()){
  313. er->read4p = 0;
  314. pexit("hangup", 1);
  315. }
  316. for(;;){
  317. bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
  318. if(!canrlock(ifc)){
  319. freeb(bp);
  320. continue;
  321. }
  322. if(waserror()){
  323. runlock(ifc);
  324. nexterror();
  325. }
  326. ifc->in++;
  327. bp->rp += ifc->m->hsize;
  328. if(ifc->lifc == nil)
  329. freeb(bp);
  330. else
  331. ipiput4(er->f, ifc, bp);
  332. runlock(ifc);
  333. poperror();
  334. }
  335. }
  336. /*
  337. * process to read from the ethernet, IPv6
  338. */
  339. static void
  340. etherread6(void *a)
  341. {
  342. Ipifc *ifc;
  343. Block *bp;
  344. Etherrock *er;
  345. ifc = a;
  346. er = ifc->arg;
  347. er->read6p = up; /* hide identity under a rock for unbind */
  348. if(waserror()){
  349. er->read6p = 0;
  350. pexit("hangup", 1);
  351. }
  352. for(;;){
  353. bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
  354. if(!canrlock(ifc)){
  355. freeb(bp);
  356. continue;
  357. }
  358. if(waserror()){
  359. runlock(ifc);
  360. nexterror();
  361. }
  362. ifc->in++;
  363. bp->rp += ifc->m->hsize;
  364. if(ifc->lifc == nil)
  365. freeb(bp);
  366. else
  367. ipiput6(er->f, ifc, bp);
  368. runlock(ifc);
  369. poperror();
  370. }
  371. }
  372. static void
  373. etheraddmulti(Ipifc *ifc, uchar *a, uchar *)
  374. {
  375. uchar mac[6];
  376. char buf[64];
  377. Etherrock *er = ifc->arg;
  378. int version;
  379. version = multicastea(mac, a);
  380. snprint(buf, sizeof buf, "addmulti %E", mac);
  381. switch(version){
  382. case V4:
  383. devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
  384. break;
  385. case V6:
  386. devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
  387. break;
  388. default:
  389. panic("etheraddmulti: version %d", version);
  390. }
  391. }
  392. static void
  393. etherremmulti(Ipifc *ifc, uchar *a, uchar *)
  394. {
  395. uchar mac[6];
  396. char buf[64];
  397. Etherrock *er = ifc->arg;
  398. int version;
  399. version = multicastea(mac, a);
  400. snprint(buf, sizeof buf, "remmulti %E", mac);
  401. switch(version){
  402. case V4:
  403. devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
  404. break;
  405. case V6:
  406. devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
  407. break;
  408. default:
  409. panic("etherremmulti: version %d", version);
  410. }
  411. }
  412. /*
  413. * send an ethernet arp
  414. * (only v4, v6 uses the neighbor discovery, rfc1970)
  415. */
  416. static void
  417. sendarp(Ipifc *ifc, Arpent *a)
  418. {
  419. int n;
  420. Block *bp;
  421. Etherarp *e;
  422. Etherrock *er = ifc->arg;
  423. /* don't do anything if it's been less than a second since the last */
  424. if(NOW - a->ctime < 1000){
  425. arprelease(er->f->arp, a);
  426. return;
  427. }
  428. /* remove all but the last message */
  429. while((bp = a->hold) != nil){
  430. if(bp == a->last)
  431. break;
  432. a->hold = bp->list;
  433. freeblist(bp);
  434. }
  435. /* try to keep it around for a second more */
  436. a->ctime = NOW;
  437. arprelease(er->f->arp, a);
  438. n = sizeof(Etherarp);
  439. if(n < a->type->mintu)
  440. n = a->type->mintu;
  441. bp = allocb(n);
  442. memset(bp->rp, 0, n);
  443. e = (Etherarp*)bp->rp;
  444. memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa));
  445. ipv4local(ifc, e->spa);
  446. memmove(e->sha, ifc->mac, sizeof(e->sha));
  447. memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
  448. memmove(e->s, ifc->mac, sizeof(e->s));
  449. hnputs(e->type, ETARP);
  450. hnputs(e->hrd, 1);
  451. hnputs(e->pro, ETIP4);
  452. e->hln = sizeof(e->sha);
  453. e->pln = sizeof(e->spa);
  454. hnputs(e->op, ARPREQUEST);
  455. bp->wp += n;
  456. devtab[er->achan->type]->bwrite(er->achan, bp, 0);
  457. }
  458. static void
  459. resolveaddr6(Ipifc *ifc, Arpent *a)
  460. {
  461. int sflag;
  462. Block *bp;
  463. Etherrock *er = ifc->arg;
  464. uchar ipsrc[IPaddrlen];
  465. /* don't do anything if it's been less than a second since the last */
  466. if(NOW - a->ctime < ReTransTimer){
  467. arprelease(er->f->arp, a);
  468. return;
  469. }
  470. /* remove all but the last message */
  471. while((bp = a->hold) != nil){
  472. if(bp == a->last)
  473. break;
  474. a->hold = bp->list;
  475. freeblist(bp);
  476. }
  477. /* try to keep it around for a second more */
  478. a->ctime = NOW;
  479. a->rtime = NOW + ReTransTimer;
  480. if(a->rxtsrem <= 0) {
  481. arprelease(er->f->arp, a);
  482. return;
  483. }
  484. a->rxtsrem--;
  485. arprelease(er->f->arp, a);
  486. if(sflag = ipv6anylocal(ifc, ipsrc))
  487. icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
  488. }
  489. /*
  490. * send a gratuitous arp to refresh arp caches
  491. */
  492. static void
  493. sendgarp(Ipifc *ifc, uchar *ip)
  494. {
  495. int n;
  496. Block *bp;
  497. Etherarp *e;
  498. Etherrock *er = ifc->arg;
  499. /* don't arp for our initial non address */
  500. if(ipcmp(ip, IPnoaddr) == 0)
  501. return;
  502. n = sizeof(Etherarp);
  503. if(n < ifc->m->mintu)
  504. n = ifc->m->mintu;
  505. bp = allocb(n);
  506. memset(bp->rp, 0, n);
  507. e = (Etherarp*)bp->rp;
  508. memmove(e->tpa, ip+IPv4off, sizeof(e->tpa));
  509. memmove(e->spa, ip+IPv4off, sizeof(e->spa));
  510. memmove(e->sha, ifc->mac, sizeof(e->sha));
  511. memset(e->d, 0xff, sizeof(e->d)); /* ethernet broadcast */
  512. memmove(e->s, ifc->mac, sizeof(e->s));
  513. hnputs(e->type, ETARP);
  514. hnputs(e->hrd, 1);
  515. hnputs(e->pro, ETIP4);
  516. e->hln = sizeof(e->sha);
  517. e->pln = sizeof(e->spa);
  518. hnputs(e->op, ARPREQUEST);
  519. bp->wp += n;
  520. devtab[er->achan->type]->bwrite(er->achan, bp, 0);
  521. }
  522. static void
  523. recvarp(Ipifc *ifc)
  524. {
  525. int n;
  526. Block *ebp, *rbp;
  527. Etherarp *e, *r;
  528. uchar ip[IPaddrlen];
  529. static uchar eprinted[4];
  530. Etherrock *er = ifc->arg;
  531. ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
  532. if(ebp == nil)
  533. return;
  534. e = (Etherarp*)ebp->rp;
  535. switch(nhgets(e->op)) {
  536. default:
  537. break;
  538. case ARPREPLY:
  539. /* check for machine using my ip address */
  540. v4tov6(ip, e->spa);
  541. if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
  542. if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
  543. print("arprep: 0x%E/0x%E also has ip addr %V\n",
  544. e->s, e->sha, e->spa);
  545. break;
  546. }
  547. }
  548. /* make sure we're not entering broadcast addresses */
  549. if(ipcmp(ip, ipbroadcast) == 0 ||
  550. !memcmp(e->sha, etherbroadcast, sizeof(e->sha))){
  551. print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",
  552. e->s, e->sha, e->spa);
  553. break;
  554. }
  555. arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);
  556. break;
  557. case ARPREQUEST:
  558. /* don't answer arps till we know who we are */
  559. if(ifc->lifc == 0)
  560. break;
  561. /* check for machine using my ip or ether address */
  562. v4tov6(ip, e->spa);
  563. if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
  564. if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
  565. if (memcmp(eprinted, e->spa, sizeof(e->spa))){
  566. /* print only once */
  567. print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);
  568. memmove(eprinted, e->spa, sizeof(e->spa));
  569. }
  570. }
  571. } else {
  572. if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){
  573. print("arpreq: %V also has ether addr %E\n", e->spa, e->sha);
  574. break;
  575. }
  576. }
  577. /* refresh what we know about sender */
  578. arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);
  579. /* answer only requests for our address or systems we're proxying for */
  580. v4tov6(ip, e->tpa);
  581. if(!iplocalonifc(ifc, ip))
  582. if(!ipproxyifc(er->f, ifc, ip))
  583. break;
  584. n = sizeof(Etherarp);
  585. if(n < ifc->mintu)
  586. n = ifc->mintu;
  587. rbp = allocb(n);
  588. r = (Etherarp*)rbp->rp;
  589. memset(r, 0, sizeof(Etherarp));
  590. hnputs(r->type, ETARP);
  591. hnputs(r->hrd, 1);
  592. hnputs(r->pro, ETIP4);
  593. r->hln = sizeof(r->sha);
  594. r->pln = sizeof(r->spa);
  595. hnputs(r->op, ARPREPLY);
  596. memmove(r->tha, e->sha, sizeof(r->tha));
  597. memmove(r->tpa, e->spa, sizeof(r->tpa));
  598. memmove(r->sha, ifc->mac, sizeof(r->sha));
  599. memmove(r->spa, e->tpa, sizeof(r->spa));
  600. memmove(r->d, e->sha, sizeof(r->d));
  601. memmove(r->s, ifc->mac, sizeof(r->s));
  602. rbp->wp += n;
  603. devtab[er->achan->type]->bwrite(er->achan, rbp, 0);
  604. }
  605. freeb(ebp);
  606. }
  607. static void
  608. recvarpproc(void *v)
  609. {
  610. Ipifc *ifc = v;
  611. Etherrock *er = ifc->arg;
  612. er->arpp = up;
  613. if(waserror()){
  614. er->arpp = 0;
  615. pexit("hangup", 1);
  616. }
  617. for(;;)
  618. recvarp(ifc);
  619. }
  620. static int
  621. multicastea(uchar *ea, uchar *ip)
  622. {
  623. int x;
  624. switch(x = ipismulticast(ip)){
  625. case V4:
  626. ea[0] = 0x01;
  627. ea[1] = 0x00;
  628. ea[2] = 0x5e;
  629. ea[3] = ip[13] & 0x7f;
  630. ea[4] = ip[14];
  631. ea[5] = ip[15];
  632. break;
  633. case V6:
  634. ea[0] = 0x33;
  635. ea[1] = 0x33;
  636. ea[2] = ip[12];
  637. ea[3] = ip[13];
  638. ea[4] = ip[14];
  639. ea[5] = ip[15];
  640. break;
  641. }
  642. return x;
  643. }
  644. /*
  645. * fill in an arp entry for broadcast or multicast
  646. * addresses. Return the first queued packet for the
  647. * IP address.
  648. */
  649. static Block*
  650. multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac)
  651. {
  652. /* is it broadcast? */
  653. switch(ipforme(f, a->ip)){
  654. case Runi:
  655. return nil;
  656. case Rbcast:
  657. memset(mac, 0xff, 6);
  658. return arpresolve(f->arp, a, medium, mac);
  659. default:
  660. break;
  661. }
  662. /* if multicast, fill in mac */
  663. switch(multicastea(mac, a->ip)){
  664. case V4:
  665. case V6:
  666. return arpresolve(f->arp, a, medium, mac);
  667. }
  668. /* let arp take care of it */
  669. return nil;
  670. }
  671. void
  672. ethermediumlink(void)
  673. {
  674. addipmedium(&ethermedium);
  675. addipmedium(&gbemedium);
  676. }
  677. static void
  678. etherpref2addr(uchar *pref, uchar *ea)
  679. {
  680. pref[8] = ea[0] | 0x2;
  681. pref[9] = ea[1];
  682. pref[10] = ea[2];
  683. pref[11] = 0xFF;
  684. pref[12] = 0xFE;
  685. pref[13] = ea[3];
  686. pref[14] = ea[4];
  687. pref[15] = ea[5];
  688. }