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