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