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