xref: /freebsd/sys/net/if_ethersubr.c (revision e627b39baccd1ec9129690167cf5e6d860509655)
1 /*
2  * Copyright (c) 1982, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	@(#)if_ethersubr.c	8.1 (Berkeley) 6/10/93
34  * $Id: if_ethersubr.c,v 1.23 1996/08/04 11:45:37 phk Exp $
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <sys/errno.h>
46 #include <sys/syslog.h>
47 #include <sys/sysctl.h>
48 
49 #include <net/if.h>
50 #include <net/netisr.h>
51 #include <net/route.h>
52 #include <net/if_llc.h>
53 #include <net/if_dl.h>
54 #include <net/if_types.h>
55 #include <net/ethernet.h>
56 
57 #ifdef INET
58 #include <netinet/in.h>
59 #include <netinet/in_var.h>
60 #endif
61 #include <netinet/if_ether.h>
62 
63 #ifdef IPX
64 #include <netipx/ipx.h>
65 #include <netipx/ipx_if.h>
66 #endif
67 
68 #ifdef NS
69 #include <netns/ns.h>
70 #include <netns/ns_if.h>
71 #endif
72 
73 #ifdef ISO
74 #include <netiso/argo_debug.h>
75 #include <netiso/iso.h>
76 #include <netiso/iso_var.h>
77 #include <netiso/iso_snpac.h>
78 #endif
79 
80 /*#ifdef LLC
81 #include <netccitt/dll.h>
82 #include <netccitt/llc_var.h>
83 #endif*/
84 
85 #if defined(LLC) && defined(CCITT)
86 extern struct ifqueue pkintrq;
87 #endif
88 
89 #ifdef NETATALK
90 #include <netatalk/at.h>
91 #include <netatalk/at_var.h>
92 #include <netatalk/at_extern.h>
93 
94 #define llc_snap_org_code llc_un.type_snap.org_code
95 #define llc_snap_ether_type llc_un.type_snap.ether_type
96 
97 extern u_char	at_org_code[ 3 ];
98 extern u_char	aarp_org_code[ 3 ];
99 #endif NETATALK
100 
101 u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
102 #define senderr(e) { error = (e); goto bad;}
103 
104 /*
105  * Ethernet output routine.
106  * Encapsulate a packet of type family for the local net.
107  * Use trailer local net encapsulation if enough data in first
108  * packet leaves a multiple of 512 bytes of data in remainder.
109  * Assumes that ifp is actually pointer to arpcom structure.
110  */
111 int
112 ether_output(ifp, m0, dst, rt0)
113 	register struct ifnet *ifp;
114 	struct mbuf *m0;
115 	struct sockaddr *dst;
116 	struct rtentry *rt0;
117 {
118 	short type;
119 	int s, error = 0;
120  	u_char edst[6];
121 	register struct mbuf *m = m0;
122 	register struct rtentry *rt;
123 	struct mbuf *mcopy = (struct mbuf *)0;
124 	register struct ether_header *eh;
125 	int off, len = m->m_pkthdr.len;
126 	struct arpcom *ac = (struct arpcom *)ifp;
127 #ifdef NETATALK
128 	struct at_ifaddr *aa;
129 #endif NETATALK
130 
131 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
132 		senderr(ENETDOWN);
133 	rt = rt0;
134 	if (rt) {
135 		if ((rt->rt_flags & RTF_UP) == 0) {
136 			rt0 = rt = rtalloc1(dst, 1, 0UL);
137 			if (rt0)
138 				rt->rt_refcnt--;
139 			else
140 				senderr(EHOSTUNREACH);
141 		}
142 		if (rt->rt_flags & RTF_GATEWAY) {
143 			if (rt->rt_gwroute == 0)
144 				goto lookup;
145 			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
146 				rtfree(rt); rt = rt0;
147 			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
148 							  0UL);
149 				if ((rt = rt->rt_gwroute) == 0)
150 					senderr(EHOSTUNREACH);
151 			}
152 		}
153 		if (rt->rt_flags & RTF_REJECT)
154 			if (rt->rt_rmx.rmx_expire == 0 ||
155 			    time.tv_sec < rt->rt_rmx.rmx_expire)
156 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
157 	}
158 	switch (dst->sa_family) {
159 
160 #ifdef INET
161 	case AF_INET:
162 		if (!arpresolve(ac, rt, m, dst, edst, rt0))
163 			return (0);	/* if not yet resolved */
164 		/* If broadcasting on a simplex interface, loopback a copy */
165 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
166 			mcopy = m_copy(m, 0, (int)M_COPYALL);
167 		off = m->m_pkthdr.len - m->m_len;
168 		type = htons(ETHERTYPE_IP);
169 		break;
170 #endif
171 #ifdef IPX
172 	case AF_IPX:
173 		type = htons(ETHERTYPE_IPX);
174  		bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
175 		    (caddr_t)edst, sizeof (edst));
176 		if (!bcmp((caddr_t)edst, (caddr_t)&ipx_thishost, sizeof(edst)))
177 			return (looutput(ifp, m, dst, rt));
178 		/* If broadcasting on a simplex interface, loopback a copy */
179 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
180 			mcopy = m_copy(m, 0, (int)M_COPYALL);
181 		break;
182 #endif
183 #ifdef NETATALK
184 	case AF_APPLETALK:
185             if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
186 #ifdef NETATALKDEBUG
187                 extern char *prsockaddr(struct sockaddr *);
188                 printf("aarpresolv: failed for %s\n", prsockaddr(dst));
189 #endif NETATALKDEBUG
190                 return (0);
191             }
192 	    /*
193 	     * ifaddr is the first thing in at_ifaddr
194 	     */
195 	    if ((aa = (struct at_ifaddr *)at_ifawithnet(
196 			(struct sockaddr_at *)dst, ifp->if_addrlist))
197 		== 0)
198 		goto bad;
199 
200 	    /*
201 	     * In the phase 2 case, we need to prepend an mbuf for the llc header.
202 	     * Since we must preserve the value of m, which is passed to us by
203 	     * value, we m_copy() the first mbuf, and use it for our llc header.
204 	     */
205 	    if ( aa->aa_flags & AFA_PHASE2 ) {
206 		struct llc llc;
207 
208 		M_PREPEND(m, sizeof(struct llc), M_WAIT);
209 		len += sizeof(struct llc);
210 		llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
211 		llc.llc_control = LLC_UI;
212 		bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
213 		llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
214 		bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
215 		type = htons(m->m_pkthdr.len);
216 	    } else {
217 		type = htons(ETHERTYPE_AT);
218 	    }
219 	    break;
220 #endif NETATALK
221 #ifdef NS
222 	case AF_NS:
223 		type = htons(ETHERTYPE_NS);
224  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
225 		    (caddr_t)edst, sizeof (edst));
226 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst)))
227 			return (looutput(ifp, m, dst, rt));
228 		/* If broadcasting on a simplex interface, loopback a copy */
229 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
230 			mcopy = m_copy(m, 0, (int)M_COPYALL);
231 		break;
232 #endif
233 #ifdef	ISO
234 	case AF_ISO: {
235 		int	snpalen;
236 		struct	llc *l;
237 		register struct sockaddr_dl *sdl;
238 
239 		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
240 		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
241 			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
242 		} else if (error =
243 			    iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
244 					    (char *)edst, &snpalen))
245 			goto bad; /* Not Resolved */
246 		/* If broadcasting on a simplex interface, loopback a copy */
247 		if (*edst & 1)
248 			m->m_flags |= (M_BCAST|M_MCAST);
249 		if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
250 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
251 			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
252 			if (mcopy) {
253 				eh = mtod(mcopy, struct ether_header *);
254 				bcopy((caddr_t)edst,
255 				      (caddr_t)eh->ether_dhost, sizeof (edst));
256 				bcopy((caddr_t)ac->ac_enaddr,
257 				      (caddr_t)eh->ether_shost, sizeof (edst));
258 			}
259 		}
260 		M_PREPEND(m, 3, M_DONTWAIT);
261 		if (m == NULL)
262 			return (0);
263 		type = htons(m->m_pkthdr.len);
264 		l = mtod(m, struct llc *);
265 		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
266 		l->llc_control = LLC_UI;
267 		len += 3;
268 		IFDEBUG(D_ETHER)
269 			int i;
270 			printf("unoutput: sending pkt to: ");
271 			for (i=0; i<6; i++)
272 				printf("%x ", edst[i] & 0xff);
273 			printf("\n");
274 		ENDDEBUG
275 		} break;
276 #endif /* ISO */
277 #ifdef	LLC
278 /*	case AF_NSAP: */
279 	case AF_CCITT: {
280 		register struct sockaddr_dl *sdl =
281 			(struct sockaddr_dl *) rt -> rt_gateway;
282 
283 		if (sdl && sdl->sdl_family == AF_LINK
284 		    && sdl->sdl_alen > 0) {
285 			bcopy(LLADDR(sdl), (char *)edst,
286 				sizeof(edst));
287 		} else goto bad; /* Not a link interface ? Funny ... */
288 		if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
289 		    (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
290 			M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
291 			if (mcopy) {
292 				eh = mtod(mcopy, struct ether_header *);
293 				bcopy((caddr_t)edst,
294 				      (caddr_t)eh->ether_dhost, sizeof (edst));
295 				bcopy((caddr_t)ac->ac_enaddr,
296 				      (caddr_t)eh->ether_shost, sizeof (edst));
297 			}
298 		}
299 		type = htons(m->m_pkthdr.len);
300 #ifdef LLC_DEBUG
301 		{
302 			int i;
303 			register struct llc *l = mtod(m, struct llc *);
304 
305 			printf("ether_output: sending LLC2 pkt to: ");
306 			for (i=0; i<6; i++)
307 				printf("%x ", edst[i] & 0xff);
308 			printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
309 			       type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
310 			       l->llc_control & 0xff);
311 
312 		}
313 #endif /* LLC_DEBUG */
314 		} break;
315 #endif /* LLC */
316 
317 	case AF_UNSPEC:
318 		eh = (struct ether_header *)dst->sa_data;
319  		(void)memcpy(edst, eh->ether_dhost, sizeof (edst));
320 		type = eh->ether_type;
321 		break;
322 
323 	default:
324 		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
325 			dst->sa_family);
326 		senderr(EAFNOSUPPORT);
327 	}
328 
329 
330 	if (mcopy)
331 		(void) looutput(ifp, mcopy, dst, rt);
332 	/*
333 	 * Add local net header.  If no space in first mbuf,
334 	 * allocate another.
335 	 */
336 	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
337 	if (m == 0)
338 		senderr(ENOBUFS);
339 	eh = mtod(m, struct ether_header *);
340 	(void)memcpy(&eh->ether_type, &type,
341 		sizeof(eh->ether_type));
342  	(void)memcpy(eh->ether_dhost, edst, sizeof (edst));
343  	(void)memcpy(eh->ether_shost, ac->ac_enaddr,
344 	    sizeof(eh->ether_shost));
345 	s = splimp();
346 	/*
347 	 * Queue message on interface, and start output if interface
348 	 * not yet active.
349 	 */
350 	if (IF_QFULL(&ifp->if_snd)) {
351 		IF_DROP(&ifp->if_snd);
352 		splx(s);
353 		senderr(ENOBUFS);
354 	}
355 	IF_ENQUEUE(&ifp->if_snd, m);
356 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
357 		(*ifp->if_start)(ifp);
358 	splx(s);
359 	ifp->if_obytes += len + sizeof (struct ether_header);
360 	if (m->m_flags & M_MCAST)
361 		ifp->if_omcasts++;
362 	return (error);
363 
364 bad:
365 	if (m)
366 		m_freem(m);
367 	return (error);
368 }
369 
370 /*
371  * Process a received Ethernet packet;
372  * the packet is in the mbuf chain m without
373  * the ether header, which is provided separately.
374  */
375 void
376 ether_input(ifp, eh, m)
377 	struct ifnet *ifp;
378 	register struct ether_header *eh;
379 	struct mbuf *m;
380 {
381 	register struct ifqueue *inq;
382 	u_short ether_type;
383 	int s;
384 #if defined (ISO) || defined (LLC) || defined(NETATALK)
385 	register struct llc *l;
386 #endif
387 
388 	if ((ifp->if_flags & IFF_UP) == 0) {
389 		m_freem(m);
390 		return;
391 	}
392 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
393 	if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
394 	    sizeof(etherbroadcastaddr)) == 0)
395 		m->m_flags |= M_BCAST;
396 	else if (eh->ether_dhost[0] & 1)
397 		m->m_flags |= M_MCAST;
398 	if (m->m_flags & (M_BCAST|M_MCAST))
399 		ifp->if_imcasts++;
400 
401 	ether_type = ntohs(eh->ether_type);
402 
403 	switch (ether_type) {
404 #ifdef INET
405 	case ETHERTYPE_IP:
406 		schednetisr(NETISR_IP);
407 		inq = &ipintrq;
408 		break;
409 
410 	case ETHERTYPE_ARP:
411 		schednetisr(NETISR_ARP);
412 		inq = &arpintrq;
413 		break;
414 #endif
415 #ifdef IPX
416 	case ETHERTYPE_IPX:
417 		schednetisr(NETISR_IPX);
418 		inq = &ipxintrq;
419 		break;
420 #endif
421 #ifdef NS
422 	case ETHERTYPE_NS:
423 		schednetisr(NETISR_NS);
424 		inq = &nsintrq;
425 		break;
426 #endif
427 #ifdef NETATALK
428         case ETHERTYPE_AT:
429                 schednetisr(NETISR_ATALK);
430                 inq = &atintrq1;
431                 break;
432         case ETHERTYPE_AARP:
433 		/* probably this should be done with a NETISR as well */
434                 aarpinput((struct arpcom *)ifp, m); /* XXX */
435                 return;
436 #endif NETATALK
437 	default:
438 #if defined (ISO) || defined (LLC) || defined(NETATALK)
439 		if (ether_type > ETHERMTU)
440 			goto dropanyway;
441 		l = mtod(m, struct llc *);
442 		switch (l->llc_dsap) {
443 #ifdef NETATALK
444 		case LLC_SNAP_LSAP:
445 		    switch (l->llc_control) {
446 		    case LLC_UI:
447 			if (l->llc_ssap != LLC_SNAP_LSAP)
448 			    goto dropanyway;
449 
450 			if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
451 				   sizeof(at_org_code)) == 0 &&
452 			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
453 			    inq = &atintrq2;
454 			    m_adj( m, sizeof( struct llc ));
455 			    schednetisr(NETISR_ATALK);
456 			    break;
457 			}
458 
459 			if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
460 				   sizeof(aarp_org_code)) == 0 &&
461 			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
462 			    m_adj( m, sizeof( struct llc ));
463 			    aarpinput((struct arpcom *)ifp, m); /* XXX */
464 			    return;
465 			}
466 
467 		    default:
468 			goto dropanyway;
469 		    }
470 		    break;
471 #endif NETATALK
472 #ifdef	ISO
473 		case LLC_ISO_LSAP:
474 			switch (l->llc_control) {
475 			case LLC_UI:
476 				/* LLC_UI_P forbidden in class 1 service */
477 				if ((l->llc_dsap == LLC_ISO_LSAP) &&
478 				    (l->llc_ssap == LLC_ISO_LSAP)) {
479 					/* LSAP for ISO */
480 					if (m->m_pkthdr.len > ether_type)
481 						m_adj(m, ether_type - m->m_pkthdr.len);
482 					m->m_data += 3;		/* XXX */
483 					m->m_len -= 3;		/* XXX */
484 					m->m_pkthdr.len -= 3;	/* XXX */
485 					M_PREPEND(m, sizeof *eh, M_DONTWAIT);
486 					if (m == 0)
487 						return;
488 					*mtod(m, struct ether_header *) = *eh;
489 					IFDEBUG(D_ETHER)
490 						printf("clnp packet");
491 					ENDDEBUG
492 					schednetisr(NETISR_ISO);
493 					inq = &clnlintrq;
494 					break;
495 				}
496 				goto dropanyway;
497 
498 			case LLC_XID:
499 			case LLC_XID_P:
500 				if(m->m_len < 6)
501 					goto dropanyway;
502 				l->llc_window = 0;
503 				l->llc_fid = 9;
504 				l->llc_class = 1;
505 				l->llc_dsap = l->llc_ssap = 0;
506 				/* Fall through to */
507 			case LLC_TEST:
508 			case LLC_TEST_P:
509 			{
510 				struct sockaddr sa;
511 				register struct ether_header *eh2;
512 				int i;
513 				u_char c = l->llc_dsap;
514 
515 				l->llc_dsap = l->llc_ssap;
516 				l->llc_ssap = c;
517 				if (m->m_flags & (M_BCAST | M_MCAST))
518 					bcopy((caddr_t)ac->ac_enaddr,
519 					      (caddr_t)eh->ether_dhost, 6);
520 				sa.sa_family = AF_UNSPEC;
521 				sa.sa_len = sizeof(sa);
522 				eh2 = (struct ether_header *)sa.sa_data;
523 				for (i = 0; i < 6; i++) {
524 					eh2->ether_shost[i] = c = eh->ether_dhost[i];
525 					eh2->ether_dhost[i] =
526 						eh->ether_dhost[i] = eh->ether_shost[i];
527 					eh->ether_shost[i] = c;
528 				}
529 				ifp->if_output(ifp, m, &sa, NULL);
530 				return;
531 			}
532 			default:
533 				m_freem(m);
534 				return;
535 			}
536 			break;
537 #endif /* ISO */
538 #ifdef LLC
539 		case LLC_X25_LSAP:
540 		{
541 			if (m->m_pkthdr.len > ether_type)
542 				m_adj(m, ether_type - m->m_pkthdr.len);
543 			M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
544 			if (m == 0)
545 				return;
546 			if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
547 					    eh->ether_dhost, LLC_X25_LSAP, 6,
548 					    mtod(m, struct sdl_hdr *)))
549 				panic("ETHER cons addr failure");
550 			mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
551 #ifdef LLC_DEBUG
552 				printf("llc packet\n");
553 #endif /* LLC_DEBUG */
554 			schednetisr(NETISR_CCITT);
555 			inq = &llcintrq;
556 			break;
557 		}
558 #endif /* LLC */
559 		dropanyway:
560 		default:
561 			m_freem(m);
562 			return;
563 		}
564 #else /* ISO || LLC || NETATALK */
565 	    m_freem(m);
566 	    return;
567 #endif /* ISO || LLC || NETATALK */
568 	}
569 
570 	s = splimp();
571 	if (IF_QFULL(inq)) {
572 		IF_DROP(inq);
573 		m_freem(m);
574 	} else
575 		IF_ENQUEUE(inq, m);
576 	splx(s);
577 }
578 
579 /*
580  * Perform common duties while attaching to interface list
581  */
582 void
583 ether_ifattach(ifp)
584 	register struct ifnet *ifp;
585 {
586 	register struct ifaddr *ifa;
587 	register struct sockaddr_dl *sdl;
588 
589 	ifp->if_type = IFT_ETHER;
590 	ifp->if_addrlen = 6;
591 	ifp->if_hdrlen = 14;
592 	ifp->if_mtu = ETHERMTU;
593 	if (ifp->if_baudrate == 0)
594 	    ifp->if_baudrate = 10000000;
595 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
596 		if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
597 		    sdl->sdl_family == AF_LINK) {
598 			sdl->sdl_type = IFT_ETHER;
599 			sdl->sdl_alen = ifp->if_addrlen;
600 			bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
601 			      LLADDR(sdl), ifp->if_addrlen);
602 			break;
603 		}
604 }
605 
606 static u_char ether_ipmulticast_min[6] =
607 	{ 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
608 static u_char ether_ipmulticast_max[6] =
609 	{ 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
610 /*
611  * Add an Ethernet multicast address or range of addresses to the list for a
612  * given interface.
613  */
614 int
615 ether_addmulti(ifr, ac)
616 	struct ifreq *ifr;
617 	register struct arpcom *ac;
618 {
619 	register struct ether_multi *enm;
620 	struct sockaddr_in *sin;
621 	u_char addrlo[6];
622 	u_char addrhi[6];
623         int set_allmulti = 0;
624 	int s = splimp();
625 
626 	switch (ifr->ifr_addr.sa_family) {
627 
628 	case AF_UNSPEC:
629 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
630 		bcopy(addrlo, addrhi, 6);
631 		break;
632 
633 #ifdef INET
634 	case AF_INET:
635 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
636 		if (sin->sin_addr.s_addr == INADDR_ANY) {
637 			/*
638 			 * An IP address of INADDR_ANY means listen to all
639 			 * of the Ethernet multicast addresses used for IP.
640 			 * (This is for the sake of IP multicast routers.)
641 			 */
642 			bcopy(ether_ipmulticast_min, addrlo, 6);
643 			bcopy(ether_ipmulticast_max, addrhi, 6);
644                       set_allmulti = 1;
645 		}
646 		else {
647 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
648 			bcopy(addrlo, addrhi, 6);
649 		}
650 		break;
651 #endif
652 
653 	default:
654 		splx(s);
655 		return (EAFNOSUPPORT);
656 	}
657 
658 	/*
659 	 * Verify that we have valid Ethernet multicast addresses.
660 	 */
661 	if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
662 		splx(s);
663 		return (EINVAL);
664 	}
665 	/*
666 	 * See if the address range is already in the list.
667 	 */
668 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
669 	if (enm != NULL) {
670 		/*
671 		 * Found it; just increment the reference count.
672 		 */
673 		++enm->enm_refcount;
674 		splx(s);
675 		return (0);
676 	}
677 	/*
678 	 * New address or range; malloc a new multicast record
679 	 * and link it into the interface's multicast list.
680 	 */
681 	enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
682 	if (enm == NULL) {
683 		splx(s);
684 		return (ENOBUFS);
685 	}
686 	bcopy(addrlo, enm->enm_addrlo, 6);
687 	bcopy(addrhi, enm->enm_addrhi, 6);
688 	enm->enm_ac = ac;
689 	enm->enm_refcount = 1;
690 	enm->enm_next = ac->ac_multiaddrs;
691 	ac->ac_multiaddrs = enm;
692 	ac->ac_multicnt++;
693 	splx(s);
694         if (set_allmulti)
695         	ac->ac_if.if_flags |= IFF_ALLMULTI;
696 
697 	/*
698 	 * Return ENETRESET to inform the driver that the list has changed
699 	 * and its reception filter should be adjusted accordingly.
700 	 */
701 	return (ENETRESET);
702 }
703 
704 /*
705  * Delete a multicast address record.
706  */
707 int
708 ether_delmulti(ifr, ac)
709 	struct ifreq *ifr;
710 	register struct arpcom *ac;
711 {
712 	register struct ether_multi *enm;
713 	register struct ether_multi **p;
714 	struct sockaddr_in *sin;
715 	u_char addrlo[6];
716 	u_char addrhi[6];
717       int unset_allmulti = 0;
718 	int s = splimp();
719 
720 	switch (ifr->ifr_addr.sa_family) {
721 
722 	case AF_UNSPEC:
723 		bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
724 		bcopy(addrlo, addrhi, 6);
725 		break;
726 
727 #ifdef INET
728 	case AF_INET:
729 		sin = (struct sockaddr_in *)&(ifr->ifr_addr);
730 		if (sin->sin_addr.s_addr == INADDR_ANY) {
731 			/*
732 			 * An IP address of INADDR_ANY means stop listening
733 			 * to the range of Ethernet multicast addresses used
734 			 * for IP.
735 			 */
736 			bcopy(ether_ipmulticast_min, addrlo, 6);
737 			bcopy(ether_ipmulticast_max, addrhi, 6);
738                       unset_allmulti = 1;
739 		}
740 		else {
741 			ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
742 			bcopy(addrlo, addrhi, 6);
743 		}
744 		break;
745 #endif
746 
747 	default:
748 		splx(s);
749 		return (EAFNOSUPPORT);
750 	}
751 
752 	/*
753 	 * Look up the address in our list.
754 	 */
755 	ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
756 	if (enm == NULL) {
757 		splx(s);
758 		return (ENXIO);
759 	}
760 	if (--enm->enm_refcount != 0) {
761 		/*
762 		 * Still some claims to this record.
763 		 */
764 		splx(s);
765 		return (0);
766 	}
767 	/*
768 	 * No remaining claims to this record; unlink and free it.
769 	 */
770 	for (p = &enm->enm_ac->ac_multiaddrs;
771 	     *p != enm;
772 	     p = &(*p)->enm_next)
773 		continue;
774 	*p = (*p)->enm_next;
775 	free(enm, M_IFMADDR);
776 	ac->ac_multicnt--;
777 	splx(s);
778       if (unset_allmulti)
779               ac->ac_if.if_flags &= ~IFF_ALLMULTI;
780 
781 	/*
782 	 * Return ENETRESET to inform the driver that the list has changed
783 	 * and its reception filter should be adjusted accordingly.
784 	 */
785 	return (ENETRESET);
786 }
787 
788 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
789 
790 void
791 ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
792 {
793 	struct ifaddr *ifa = (struct ifaddr *) data;
794 	struct ifreq *ifr = (struct ifreq *) data;
795 
796 	switch (command) {
797 	case SIOCSIFADDR:
798 		ifp->if_flags |= IFF_UP;
799 
800 		switch (ifa->ifa_addr->sa_family) {
801 #ifdef INET
802 		case AF_INET:
803 			ifp->if_init(ifp->if_softc);	/* before arpwhohas */
804 			arp_ifinit((struct arpcom *)ifp, ifa);
805 			break;
806 #endif
807 #ifdef IPX
808 		/*
809 		 * XXX - This code is probably wrong
810 		 */
811 		case AF_IPX:
812 			{
813 			register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
814 			struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
815 
816 			if (ipx_nullhost(*ina))
817 				ina->x_host =
818 				    *(union ipx_host *)
819 			            ac->ac_enaddr;
820 			else {
821 				bcopy((caddr_t) ina->x_host.c_host,
822 				      (caddr_t) ac->ac_enaddr,
823 				      sizeof(ac->ac_enaddr));
824 			}
825 
826 			/*
827 			 * Set new address
828 			 */
829 			ifp->if_init(ifp->if_softc);
830 			break;
831 			}
832 #endif
833 #ifdef NS
834 		/*
835 		 * XXX - This code is probably wrong
836 		 */
837 		case AF_NS:
838 		{
839 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
840 			struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
841 
842 			if (ns_nullhost(*ina))
843 				ina->x_host =
844 				    *(union ns_host *) (ac->ac_enaddr);
845 			else {
846 				bcopy((caddr_t) ina->x_host.c_host,
847 				      (caddr_t) ac->ac_enaddr,
848 				      sizeof(ac->ac_enaddr));
849 			}
850 
851 			/*
852 			 * Set new address
853 			 */
854 			ifp->if_init(ifp->if_softc);
855 			break;
856 		}
857 #endif
858 		default:
859 			ifp->if_init(ifp->if_softc);
860 			break;
861 		}
862 		break;
863 
864 	case SIOCGIFADDR:
865 		{
866 			struct sockaddr *sa;
867 
868 			sa = (struct sockaddr *) & ifr->ifr_data;
869 			bcopy((caddr_t) ifp->if_softc,
870 			      (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
871 		}
872 		break;
873 	}
874 	return;
875 }
876