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