xref: /plan9/sys/src/9/ip/ethermedium.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
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
etherbind(Ipifc * ifc,int argc,char ** argv)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
etherunbind(Ipifc * ifc)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
etherbwrite(Ipifc * ifc,Block * bp,int version,uchar * ip)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
etherread4(void * a)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
etherread6(void * a)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
etheraddmulti(Ipifc * ifc,uchar * a,uchar *)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 	snprint(buf, sizeof 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
etherremmulti(Ipifc * ifc,uchar * a,uchar *)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 	snprint(buf, sizeof 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
sendarp(Ipifc * ifc,Arpent * a)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
resolveaddr6(Ipifc * ifc,Arpent * a)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
sendgarp(Ipifc * ifc,uchar * ip)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
recvarp(Ipifc * ifc)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
recvarpproc(void * v)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
multicastea(uchar * ea,uchar * ip)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*
multicastarp(Fs * f,Arpent * a,Medium * medium,uchar * mac)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
ethermediumlink(void)747 ethermediumlink(void)
748 {
749 	addipmedium(&ethermedium);
750 	addipmedium(&gbemedium);
751 }
752 
753 
754 static void
etherpref2addr(uchar * pref,uchar * ea)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