if_ethersubr.c revision 72175
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 * $FreeBSD: head/sys/net/if_ethersubr.c 72175 2001-02-08 17:56:49Z archie $
35 */
36
37#include "opt_atalk.h"
38#include "opt_inet.h"
39#include "opt_inet6.h"
40#include "opt_ipx.h"
41#include "opt_bdg.h"
42#include "opt_netgraph.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/kernel.h>
47#include <sys/malloc.h>
48#include <sys/mbuf.h>
49#include <sys/socket.h>
50#include <sys/sockio.h>
51#include <sys/sysctl.h>
52
53#include <net/if.h>
54#include <net/netisr.h>
55#include <net/route.h>
56#include <net/if_llc.h>
57#include <net/if_dl.h>
58#include <net/if_types.h>
59#include <net/bpf.h>
60#include <net/ethernet.h>
61
62#if defined(INET) || defined(INET6)
63#include <netinet/in.h>
64#include <netinet/in_var.h>
65#include <netinet/if_ether.h>
66#endif
67#ifdef INET6
68#include <netinet6/nd6.h>
69#endif
70
71#ifdef IPX
72#include <netipx/ipx.h>
73#include <netipx/ipx_if.h>
74int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
75int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
76		struct sockaddr *dst, short *tp, int *hlen);
77#endif
78
79#ifdef NS
80#include <netns/ns.h>
81#include <netns/ns_if.h>
82ushort ns_nettype;
83int ether_outputdebug = 0;
84int ether_inputdebug = 0;
85#endif
86
87#ifdef NETATALK
88#include <netatalk/at.h>
89#include <netatalk/at_var.h>
90#include <netatalk/at_extern.h>
91
92#define llc_snap_org_code llc_un.type_snap.org_code
93#define llc_snap_ether_type llc_un.type_snap.ether_type
94
95extern u_char	at_org_code[3];
96extern u_char	aarp_org_code[3];
97#endif /* NETATALK */
98
99#ifdef BRIDGE
100#include <net/bridge.h>
101#endif
102
103#include "vlan.h"
104#if NVLAN > 0
105#include <net/if_vlan_var.h>
106#endif /* NVLAN > 0 */
107
108/* netgraph node hooks for ng_ether(4) */
109void	(*ng_ether_input_p)(struct ifnet *ifp,
110		struct mbuf **mp, struct ether_header *eh);
111void	(*ng_ether_input_orphan_p)(struct ifnet *ifp,
112		struct mbuf *m, struct ether_header *eh);
113int	(*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
114void	(*ng_ether_attach_p)(struct ifnet *ifp);
115void	(*ng_ether_detach_p)(struct ifnet *ifp);
116
117static	int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
118				    struct sockaddr *));
119u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
120#define senderr(e) do { error = (e); goto bad;} while (0)
121#define IFP2AC(IFP) ((struct arpcom *)IFP)
122
123/*
124 * Ethernet output routine.
125 * Encapsulate a packet of type family for the local net.
126 * Use trailer local net encapsulation if enough data in first
127 * packet leaves a multiple of 512 bytes of data in remainder.
128 * Assumes that ifp is actually pointer to arpcom structure.
129 */
130int
131ether_output(ifp, m, dst, rt0)
132	register struct ifnet *ifp;
133	struct mbuf *m;
134	struct sockaddr *dst;
135	struct rtentry *rt0;
136{
137	short type;
138	int error = 0, hdrcmplt = 0;
139 	u_char esrc[6], edst[6];
140	register struct rtentry *rt;
141	register struct ether_header *eh;
142	int off, loop_copy = 0;
143	int hlen;	/* link layer header lenght */
144	struct arpcom *ac = IFP2AC(ifp);
145
146	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
147		senderr(ENETDOWN);
148	rt = rt0;
149	if (rt) {
150		if ((rt->rt_flags & RTF_UP) == 0) {
151			rt0 = rt = rtalloc1(dst, 1, 0UL);
152			if (rt0)
153				rt->rt_refcnt--;
154			else
155				senderr(EHOSTUNREACH);
156		}
157		if (rt->rt_flags & RTF_GATEWAY) {
158			if (rt->rt_gwroute == 0)
159				goto lookup;
160			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
161				rtfree(rt); rt = rt0;
162			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
163							  0UL);
164				if ((rt = rt->rt_gwroute) == 0)
165					senderr(EHOSTUNREACH);
166			}
167		}
168		if (rt->rt_flags & RTF_REJECT)
169			if (rt->rt_rmx.rmx_expire == 0 ||
170			    time_second < rt->rt_rmx.rmx_expire)
171				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
172	}
173	hlen = ETHER_HDR_LEN;
174	switch (dst->sa_family) {
175#ifdef INET
176	case AF_INET:
177		if (!arpresolve(ac, rt, m, dst, edst, rt0))
178			return (0);	/* if not yet resolved */
179		off = m->m_pkthdr.len - m->m_len;
180		type = htons(ETHERTYPE_IP);
181		break;
182#endif
183#ifdef INET6
184	case AF_INET6:
185		if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
186			/* this must be impossible, so we bark */
187			printf("nd6_storelladdr failed\n");
188			return(0);
189		}
190		off = m->m_pkthdr.len - m->m_len;
191		type = htons(ETHERTYPE_IPV6);
192		break;
193#endif
194#ifdef IPX
195	case AF_IPX:
196		if (ef_outputp) {
197		    error = ef_outputp(ifp, &m, dst, &type, &hlen);
198		    if (error)
199			goto bad;
200		} else
201		    type = htons(ETHERTYPE_IPX);
202 		bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
203		    (caddr_t)edst, sizeof (edst));
204		break;
205#endif
206#ifdef NETATALK
207	case AF_APPLETALK:
208	  {
209	    struct at_ifaddr *aa;
210
211	    if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
212		    goto bad;
213	    }
214	    if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
215		    return (0);
216	    /*
217	     * In the phase 2 case, need to prepend an mbuf for the llc header.
218	     * Since we must preserve the value of m, which is passed to us by
219	     * value, we m_copy() the first mbuf, and use it for our llc header.
220	     */
221	    if ( aa->aa_flags & AFA_PHASE2 ) {
222		struct llc llc;
223
224		M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
225		llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
226		llc.llc_control = LLC_UI;
227		bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
228		llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
229		bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
230		type = htons(m->m_pkthdr.len);
231		hlen = sizeof(struct llc) + ETHER_HDR_LEN;
232	    } else {
233		type = htons(ETHERTYPE_AT);
234	    }
235	    break;
236	  }
237#endif NETATALK
238#ifdef NS
239	case AF_NS:
240		switch(ns_nettype){
241		default:
242		case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
243			type = 0x8137;
244			break;
245		case 0x0: /* Novell 802.3 */
246			type = htons( m->m_pkthdr.len);
247			break;
248		case 0xe0e0: /* Novell 802.2 and Token-Ring */
249			M_PREPEND(m, 3, M_TRYWAIT);
250			type = htons( m->m_pkthdr.len);
251			cp = mtod(m, u_char *);
252			*cp++ = 0xE0;
253			*cp++ = 0xE0;
254			*cp++ = 0x03;
255			break;
256		}
257 		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
258		    (caddr_t)edst, sizeof (edst));
259		/*
260		 * XXX if ns_thishost is the same as the node's ethernet
261		 * address then just the default code will catch this anyhow.
262		 * So I'm not sure if this next clause should be here at all?
263		 * [JRE]
264		 */
265		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
266			m->m_pkthdr.rcvif = ifp;
267			inq = &nsintrq;
268			if (IF_HANDOFF(inq, m, NULL))
269				schednetisr(NETISR_NS);
270			return (error);
271		}
272		if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
273			m->m_flags |= M_BCAST;
274		}
275		break;
276#endif /* NS */
277
278	case pseudo_AF_HDRCMPLT:
279		hdrcmplt = 1;
280		eh = (struct ether_header *)dst->sa_data;
281		(void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
282		/* FALLTHROUGH */
283
284	case AF_UNSPEC:
285		loop_copy = -1; /* if this is for us, don't do it */
286		eh = (struct ether_header *)dst->sa_data;
287 		(void)memcpy(edst, eh->ether_dhost, sizeof (edst));
288		type = eh->ether_type;
289		break;
290
291	default:
292		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
293			dst->sa_family);
294		senderr(EAFNOSUPPORT);
295	}
296
297	/*
298	 * Add local net header.  If no space in first mbuf,
299	 * allocate another.
300	 */
301	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
302	if (m == 0)
303		senderr(ENOBUFS);
304	eh = mtod(m, struct ether_header *);
305	(void)memcpy(&eh->ether_type, &type,
306		sizeof(eh->ether_type));
307 	(void)memcpy(eh->ether_dhost, edst, sizeof (edst));
308	if (hdrcmplt)
309		(void)memcpy(eh->ether_shost, esrc,
310			sizeof(eh->ether_shost));
311	else
312		(void)memcpy(eh->ether_shost, ac->ac_enaddr,
313			sizeof(eh->ether_shost));
314
315	/*
316	 * If a simplex interface, and the packet is being sent to our
317	 * Ethernet address or a broadcast address, loopback a copy.
318	 * XXX To make a simplex device behave exactly like a duplex
319	 * device, we should copy in the case of sending to our own
320	 * ethernet address (thus letting the original actually appear
321	 * on the wire). However, we don't do that here for security
322	 * reasons and compatibility with the original behavior.
323	 */
324	if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
325		if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
326			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
327
328			(void) if_simloop(ifp, n, dst->sa_family, hlen);
329		} else if (bcmp(eh->ether_dhost,
330		    eh->ether_shost, ETHER_ADDR_LEN) == 0) {
331			(void) if_simloop(ifp, m, dst->sa_family, hlen);
332			return (0);	/* XXX */
333		}
334	}
335
336	/* Handle ng_ether(4) processing, if any */
337	if (ng_ether_output_p != NULL) {
338		if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) {
339bad:			if (m != NULL)
340				m_freem(m);
341			return (error);
342		}
343		if (m == NULL)
344			return (0);
345	}
346
347	/* Continue with link-layer output */
348	return ether_output_frame(ifp, m);
349}
350
351/*
352 * Ethernet link layer output routine to send a raw frame to the device.
353 *
354 * This assumes that the 14 byte Ethernet header is present and contiguous
355 * in the first mbuf (if BRIDGE'ing).
356 */
357int
358ether_output_frame(ifp, m)
359	struct ifnet *ifp;
360	struct mbuf *m;
361{
362	int error = 0;
363
364#ifdef BRIDGE
365	if (do_bridge && BDG_USED(ifp) ) {
366		struct ether_header *eh; /* a ptr suffices */
367		struct ifnet *oifp = ifp ;
368
369		m->m_pkthdr.rcvif = NULL;
370		eh = mtod(m, struct ether_header *);
371		m_adj(m, ETHER_HDR_LEN);
372		ifp = bridge_dst_lookup(eh);
373		if (ifp > BDG_FORWARD && !BDG_SAMECLUSTER(ifp, oifp)) {
374			printf("ether_out_frame: bad output if\n");
375		}
376		m = bdg_forward(m, eh, ifp);
377		if (m != NULL)
378			m_freem(m);
379		return (0);
380	}
381#endif
382
383	/*
384	 * Queue message on interface, update output statistics if
385	 * successful, and start output if interface not yet active.
386	 */
387	if (! IF_HANDOFF(&ifp->if_snd, m, ifp))
388		return (ENOBUFS);
389	return (error);
390}
391
392/*
393 * Process a received Ethernet packet;
394 * the packet is in the mbuf chain m without
395 * the ether header, which is provided separately.
396 *
397 * NOTA BENE: for many drivers "eh" is a pointer into the first mbuf or
398 * cluster, right before m_data. So be very careful when working on m,
399 * as you could destroy *eh !!
400 * A (probably) more convenient and efficient interface to ether_input
401 * is to have the whole packet (with the ethernet header) into the mbuf:
402 * modules which do not need the ethernet header can easily drop it, while
403 * others (most noticeably bridge and ng_ether) do not need to do additional
404 * work to put the ethernet header back into the mbuf.
405 *
406 * First we perform any link layer operations, then continue
407 * to the upper layers with ether_demux().
408 */
409void
410ether_input(ifp, eh, m)
411	struct ifnet *ifp;
412	struct ether_header *eh;
413	struct mbuf *m;
414{
415#ifdef BRIDGE
416	struct ether_header save_eh;
417#endif
418
419	/* Check for a BPF tap */
420	if (ifp->if_bpf != NULL) {
421		struct m_hdr mh;
422
423		/* This kludge is OK; BPF treats the "mbuf" as read-only */
424		mh.mh_next = m;
425		mh.mh_data = (char *)eh;
426		mh.mh_len = ETHER_HDR_LEN;
427		bpf_mtap(ifp, (struct mbuf *)&mh);
428	}
429
430	/* Handle ng_ether(4) processing, if any */
431	if (ng_ether_input_p != NULL) {
432		(*ng_ether_input_p)(ifp, &m, eh);
433		if (m == NULL)
434			return;
435	}
436
437#ifdef BRIDGE
438	/* Check for bridging mode */
439	if (do_bridge && BDG_USED(ifp) ) {
440		struct ifnet *bif;
441
442		/* Check with bridging code */
443		if ((bif = bridge_in(ifp, eh)) == BDG_DROP) {
444			m_freem(m);
445			return;
446		}
447		if (bif != BDG_LOCAL) {
448			struct mbuf *oldm = m ;
449
450			save_eh = *eh ; /* because it might change */
451			m = bdg_forward(&m, eh, bif);	/* needs forwarding */
452			/*
453			 * Do not continue if bdg_forward() processed our
454			 * packet (and cleared the mbuf pointer m) or if
455			 * it dropped (m_free'd) the packet itself.
456			 */
457			if (m == NULL) {
458			    if (bif == BDG_BCAST || bif == BDG_MCAST)
459				printf("bdg_forward drop MULTICAST PKT\n");
460			    return;
461			}
462			if (m != oldm) /* m changed! */
463			    eh = &save_eh ;
464		}
465		if (bif == BDG_LOCAL
466		    || bif == BDG_BCAST
467		    || bif == BDG_MCAST)
468			goto recvLocal;			/* receive locally */
469
470		/* If not local and not multicast, just drop it */
471		if (m != NULL)
472		    m_freem(m);
473		return;
474       }
475#endif
476
477#ifdef BRIDGE
478recvLocal:
479#endif
480	/* Continue with upper layer processing */
481	ether_demux(ifp, eh, m);
482}
483
484/*
485 * Upper layer processing for a received Ethernet packet.
486 */
487void
488ether_demux(ifp, eh, m)
489	struct ifnet *ifp;
490	struct ether_header *eh;
491	struct mbuf *m;
492{
493	struct ifqueue *inq;
494	u_short ether_type;
495#if defined(NETATALK)
496	register struct llc *l;
497#endif
498
499	/* Discard packet if upper layers shouldn't see it because it was
500	   unicast to a different Ethernet address. If the driver is working
501	   properly, then this situation can only happen when the interface
502	   is in promiscuous mode. */
503	if ((ifp->if_flags & IFF_PROMISC) != 0
504	    && (eh->ether_dhost[0] & 1) == 0
505	    && bcmp(eh->ether_dhost,
506	      IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) {
507		m_freem(m);
508		return;
509	}
510
511	/* Discard packet if interface is not up */
512	if ((ifp->if_flags & IFF_UP) == 0) {
513		m_freem(m);
514		return;
515	}
516	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
517	if (eh->ether_dhost[0] & 1) {
518		if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
519			 sizeof(etherbroadcastaddr)) == 0)
520			m->m_flags |= M_BCAST;
521		else
522			m->m_flags |= M_MCAST;
523	}
524	if (m->m_flags & (M_BCAST|M_MCAST))
525		ifp->if_imcasts++;
526
527	ether_type = ntohs(eh->ether_type);
528
529#if NVLAN > 0
530	if (ether_type == vlan_proto) {
531		if (vlan_input(eh, m) < 0)
532			ifp->if_data.ifi_noproto++;
533		return;
534	}
535#endif /* NVLAN > 0 */
536
537	switch (ether_type) {
538#ifdef INET
539	case ETHERTYPE_IP:
540		if (ipflow_fastforward(m))
541			return;
542		schednetisr(NETISR_IP);
543		inq = &ipintrq;
544		break;
545
546	case ETHERTYPE_ARP:
547		schednetisr(NETISR_ARP);
548		inq = &arpintrq;
549		break;
550#endif
551#ifdef IPX
552	case ETHERTYPE_IPX:
553		if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
554			return;
555		schednetisr(NETISR_IPX);
556		inq = &ipxintrq;
557		break;
558#endif
559#ifdef INET6
560	case ETHERTYPE_IPV6:
561		schednetisr(NETISR_IPV6);
562		inq = &ip6intrq;
563		break;
564#endif
565#ifdef NS
566	case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
567		schednetisr(NETISR_NS);
568		inq = &nsintrq;
569		break;
570
571#endif /* NS */
572#ifdef NETATALK
573        case ETHERTYPE_AT:
574                schednetisr(NETISR_ATALK);
575                inq = &atintrq1;
576                break;
577        case ETHERTYPE_AARP:
578		/* probably this should be done with a NETISR as well */
579                aarpinput(IFP2AC(ifp), m); /* XXX */
580                return;
581#endif NETATALK
582	default:
583#ifdef IPX
584		if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
585			return;
586#endif /* IPX */
587#ifdef NS
588		checksum = mtod(m, ushort *);
589		/* Novell 802.3 */
590		if ((ether_type <= ETHERMTU) &&
591			((*checksum == 0xffff) || (*checksum == 0xE0E0))){
592			if(*checksum == 0xE0E0) {
593				m->m_pkthdr.len -= 3;
594				m->m_len -= 3;
595				m->m_data += 3;
596			}
597				schednetisr(NETISR_NS);
598				inq = &nsintrq;
599				break;
600		}
601#endif /* NS */
602#if defined(NETATALK)
603		if (ether_type > ETHERMTU)
604			goto dropanyway;
605		l = mtod(m, struct llc *);
606		switch (l->llc_dsap) {
607		case LLC_SNAP_LSAP:
608		    switch (l->llc_control) {
609		    case LLC_UI:
610			if (l->llc_ssap != LLC_SNAP_LSAP)
611			    goto dropanyway;
612
613			if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
614				   sizeof(at_org_code)) == 0 &&
615			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
616			    inq = &atintrq2;
617			    m_adj( m, sizeof( struct llc ));
618			    schednetisr(NETISR_ATALK);
619			    break;
620			}
621
622			if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
623				   sizeof(aarp_org_code)) == 0 &&
624			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
625			    m_adj( m, sizeof( struct llc ));
626			    aarpinput(IFP2AC(ifp), m); /* XXX */
627			    return;
628			}
629
630		    default:
631			goto dropanyway;
632		    }
633		    break;
634		dropanyway:
635		default:
636			if (ng_ether_input_orphan_p != NULL)
637				(*ng_ether_input_orphan_p)(ifp, m, eh);
638			else
639				m_freem(m);
640			return;
641		}
642#else /* NETATALK */
643		if (ng_ether_input_orphan_p != NULL)
644			(*ng_ether_input_orphan_p)(ifp, m, eh);
645		else
646			m_freem(m);
647		return;
648#endif /* NETATALK */
649	}
650
651	(void) IF_HANDOFF(inq, m, NULL);
652}
653
654/*
655 * Perform common duties while attaching to interface list
656 */
657void
658ether_ifattach(ifp, bpf)
659	register struct ifnet *ifp;
660	int bpf;
661{
662	register struct ifaddr *ifa;
663	register struct sockaddr_dl *sdl;
664
665	if_attach(ifp);
666	ifp->if_type = IFT_ETHER;
667	ifp->if_addrlen = 6;
668	ifp->if_hdrlen = 14;
669	ifp->if_mtu = ETHERMTU;
670	ifp->if_resolvemulti = ether_resolvemulti;
671	if (ifp->if_baudrate == 0)
672	    ifp->if_baudrate = 10000000;
673	ifa = ifnet_addrs[ifp->if_index - 1];
674	KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__));
675	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
676	sdl->sdl_type = IFT_ETHER;
677	sdl->sdl_alen = ifp->if_addrlen;
678	bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
679	if (bpf)
680		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
681	if (ng_ether_attach_p != NULL)
682		(*ng_ether_attach_p)(ifp);
683#ifdef BRIDGE
684	bdgtakeifaces();
685#endif
686}
687
688/*
689 * Perform common duties while detaching an Ethernet interface
690 */
691void
692ether_ifdetach(ifp, bpf)
693	struct ifnet *ifp;
694	int bpf;
695{
696	if (ng_ether_detach_p != NULL)
697		(*ng_ether_detach_p)(ifp);
698	if (bpf)
699		bpfdetach(ifp);
700	if_detach(ifp);
701#ifdef BRIDGE
702	bdgtakeifaces();
703#endif
704}
705
706SYSCTL_DECL(_net_link);
707SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
708
709int
710ether_ioctl(ifp, command, data)
711	struct ifnet *ifp;
712	int command;
713	caddr_t data;
714{
715	struct ifaddr *ifa = (struct ifaddr *) data;
716	struct ifreq *ifr = (struct ifreq *) data;
717	int error = 0;
718
719	switch (command) {
720	case SIOCSIFADDR:
721		ifp->if_flags |= IFF_UP;
722
723		switch (ifa->ifa_addr->sa_family) {
724#ifdef INET
725		case AF_INET:
726			ifp->if_init(ifp->if_softc);	/* before arpwhohas */
727			arp_ifinit(IFP2AC(ifp), ifa);
728			break;
729#endif
730#ifdef IPX
731		/*
732		 * XXX - This code is probably wrong
733		 */
734		case AF_IPX:
735			{
736			register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
737			struct arpcom *ac = IFP2AC(ifp);
738
739			if (ipx_nullhost(*ina))
740				ina->x_host =
741				    *(union ipx_host *)
742			            ac->ac_enaddr;
743			else {
744				bcopy((caddr_t) ina->x_host.c_host,
745				      (caddr_t) ac->ac_enaddr,
746				      sizeof(ac->ac_enaddr));
747			}
748
749			/*
750			 * Set new address
751			 */
752			ifp->if_init(ifp->if_softc);
753			break;
754			}
755#endif
756#ifdef NS
757		/*
758		 * XXX - This code is probably wrong
759		 */
760		case AF_NS:
761		{
762			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
763			struct arpcom *ac = IFP2AC(ifp);
764
765			if (ns_nullhost(*ina))
766				ina->x_host =
767				    *(union ns_host *) (ac->ac_enaddr);
768			else {
769				bcopy((caddr_t) ina->x_host.c_host,
770				      (caddr_t) ac->ac_enaddr,
771				      sizeof(ac->ac_enaddr));
772			}
773
774			/*
775			 * Set new address
776			 */
777			ifp->if_init(ifp->if_softc);
778			break;
779		}
780#endif
781		default:
782			ifp->if_init(ifp->if_softc);
783			break;
784		}
785		break;
786
787	case SIOCGIFADDR:
788		{
789			struct sockaddr *sa;
790
791			sa = (struct sockaddr *) & ifr->ifr_data;
792			bcopy(IFP2AC(ifp)->ac_enaddr,
793			      (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
794		}
795		break;
796
797	case SIOCSIFMTU:
798		/*
799		 * Set the interface MTU.
800		 */
801		if (ifr->ifr_mtu > ETHERMTU) {
802			error = EINVAL;
803		} else {
804			ifp->if_mtu = ifr->ifr_mtu;
805		}
806		break;
807	}
808	return (error);
809}
810
811int
812ether_resolvemulti(ifp, llsa, sa)
813	struct ifnet *ifp;
814	struct sockaddr **llsa;
815	struct sockaddr *sa;
816{
817	struct sockaddr_dl *sdl;
818	struct sockaddr_in *sin;
819#ifdef INET6
820	struct sockaddr_in6 *sin6;
821#endif
822	u_char *e_addr;
823
824	switch(sa->sa_family) {
825	case AF_LINK:
826		/*
827		 * No mapping needed. Just check that it's a valid MC address.
828		 */
829		sdl = (struct sockaddr_dl *)sa;
830		e_addr = LLADDR(sdl);
831		if ((e_addr[0] & 1) != 1)
832			return EADDRNOTAVAIL;
833		*llsa = 0;
834		return 0;
835
836#ifdef INET
837	case AF_INET:
838		sin = (struct sockaddr_in *)sa;
839		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
840			return EADDRNOTAVAIL;
841		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
842		       M_WAITOK);
843		sdl->sdl_len = sizeof *sdl;
844		sdl->sdl_family = AF_LINK;
845		sdl->sdl_index = ifp->if_index;
846		sdl->sdl_type = IFT_ETHER;
847		sdl->sdl_nlen = 0;
848		sdl->sdl_alen = ETHER_ADDR_LEN;
849		sdl->sdl_slen = 0;
850		e_addr = LLADDR(sdl);
851		ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
852		*llsa = (struct sockaddr *)sdl;
853		return 0;
854#endif
855#ifdef INET6
856	case AF_INET6:
857		sin6 = (struct sockaddr_in6 *)sa;
858		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
859			/*
860			 * An IP6 address of 0 means listen to all
861			 * of the Ethernet multicast address used for IP6.
862			 * (This is used for multicast routers.)
863			 */
864			ifp->if_flags |= IFF_ALLMULTI;
865			*llsa = 0;
866			return 0;
867		}
868		if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
869			return EADDRNOTAVAIL;
870		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
871		       M_WAITOK);
872		sdl->sdl_len = sizeof *sdl;
873		sdl->sdl_family = AF_LINK;
874		sdl->sdl_index = ifp->if_index;
875		sdl->sdl_type = IFT_ETHER;
876		sdl->sdl_nlen = 0;
877		sdl->sdl_alen = ETHER_ADDR_LEN;
878		sdl->sdl_slen = 0;
879		e_addr = LLADDR(sdl);
880		ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
881		*llsa = (struct sockaddr *)sdl;
882		return 0;
883#endif
884
885	default:
886		/*
887		 * Well, the text isn't quite right, but it's the name
888		 * that counts...
889		 */
890		return EAFNOSUPPORT;
891	}
892}
893
894