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