xref: /freebsd/sys/net/if_ethersubr.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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$
35  */
36 
37 #include "opt_atalk.h"
38 #include "opt_inet.h"
39 #include "opt_ipx.h"
40 #include "opt_bdg.h"
41 #include "opt_netgraph.h"
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.h>
51 
52 #include <net/if.h>
53 #include <net/netisr.h>
54 #include <net/route.h>
55 #include <net/if_llc.h>
56 #include <net/if_dl.h>
57 #include <net/if_types.h>
58 
59 #ifdef INET
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/if_ether.h>
63 #endif
64 
65 #ifdef IPX
66 #include <netipx/ipx.h>
67 #include <netipx/ipx_if.h>
68 #endif
69 
70 #ifdef NS
71 #include <netns/ns.h>
72 #include <netns/ns_if.h>
73 ushort ns_nettype;
74 int ether_outputdebug = 0;
75 int ether_inputdebug = 0;
76 #endif
77 
78 #ifdef ISO
79 #include <netiso/argo_debug.h>
80 #include <netiso/iso.h>
81 #include <netiso/iso_var.h>
82 #include <netiso/iso_snpac.h>
83 #endif
84 
85 /*#ifdef LLC
86 #include <netccitt/dll.h>
87 #include <netccitt/llc_var.h>
88 #endif*/
89 
90 #if defined(LLC) && defined(CCITT)
91 extern struct ifqueue pkintrq;
92 #endif
93 
94 #ifdef NETATALK
95 #include <netatalk/at.h>
96 #include <netatalk/at_var.h>
97 #include <netatalk/at_extern.h>
98 
99 #define llc_snap_org_code llc_un.type_snap.org_code
100 #define llc_snap_ether_type llc_un.type_snap.ether_type
101 
102 extern u_char	at_org_code[3];
103 extern u_char	aarp_org_code[3];
104 #endif /* NETATALK */
105 
106 #ifdef BRIDGE
107 #include <net/bridge.h>
108 #endif
109 
110 #include "vlan.h"
111 #if NVLAN > 0
112 #include <net/if_vlan_var.h>
113 #endif /* NVLAN > 0 */
114 
115 static	int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
116 				    struct sockaddr *));
117 u_char	etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
118 #define senderr(e) do { error = (e); goto bad;} while (0)
119 #define IFP2AC(IFP) ((struct arpcom *)IFP)
120 
121 #ifdef NETGRAPH
122 #include <netgraph/ng_ether.h>
123 #include <netgraph/ng_message.h>
124 #include <netgraph/netgraph.h>
125 
126 static	void	ngether_init(void* ignored);
127 static void	ngether_send(struct arpcom *ac,
128 			struct ether_header *eh, struct mbuf *m);
129 static	int	ngether_constructor(node_p *nodep);
130 static	int	ngether_rcvmsg(node_p node, struct ng_mesg *msg,
131 			const char *retaddr, struct ng_mesg **resp);
132 static	int	ngether_rmnode(node_p node);
133 static	int	ngether_newhook(node_p node, hook_p hook, const char *name);
134 /*static	hook_p	ngether_findhook(node_p node, char *name);*/
135 static	int	ngether_connect(hook_p hook);	/* already PARTLY linked */
136 static	int	ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta);
137 static	int	ngether_disconnect(hook_p hook);	/* notify on disconnect */
138 
139 static struct ng_type typestruct = {
140 	NG_VERSION,
141 	NG_ETHER_NODE_TYPE,
142 	NULL,
143 	ngether_constructor,
144 	ngether_rcvmsg,
145 	ngether_rmnode,
146 	ngether_newhook,
147 	NULL,
148 	ngether_connect,
149 	ngether_rcvdata,
150 	ngether_rcvdata,
151 	ngether_disconnect
152 };
153 
154 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
155 #define NGEF_DIVERT NGF_TYPE1	/* all packets sent to netgraph */
156 #endif /* NETGRAPH */
157 
158 /*
159  * Ethernet output routine.
160  * Encapsulate a packet of type family for the local net.
161  * Use trailer local net encapsulation if enough data in first
162  * packet leaves a multiple of 512 bytes of data in remainder.
163  * Assumes that ifp is actually pointer to arpcom structure.
164  */
165 int
166 ether_output(ifp, m0, dst, rt0)
167 	register struct ifnet *ifp;
168 	struct mbuf *m0;
169 	struct sockaddr *dst;
170 	struct rtentry *rt0;
171 {
172 	short type;
173 	int s, error = 0, hdrcmplt = 0;
174  	u_char esrc[6], edst[6];
175 	register struct mbuf *m = m0;
176 	register struct rtentry *rt;
177 	register struct ether_header *eh;
178 	int off, len = m->m_pkthdr.len, loop_copy = 0;
179 	int hlen;	/* link layer header lenght */
180 	struct arpcom *ac = IFP2AC(ifp);
181 
182 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
183 		senderr(ENETDOWN);
184 	rt = rt0;
185 	if (rt) {
186 		if ((rt->rt_flags & RTF_UP) == 0) {
187 			rt0 = rt = rtalloc1(dst, 1, 0UL);
188 			if (rt0)
189 				rt->rt_refcnt--;
190 			else
191 				senderr(EHOSTUNREACH);
192 		}
193 		if (rt->rt_flags & RTF_GATEWAY) {
194 			if (rt->rt_gwroute == 0)
195 				goto lookup;
196 			if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
197 				rtfree(rt); rt = rt0;
198 			lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
199 							  0UL);
200 				if ((rt = rt->rt_gwroute) == 0)
201 					senderr(EHOSTUNREACH);
202 			}
203 		}
204 		if (rt->rt_flags & RTF_REJECT)
205 			if (rt->rt_rmx.rmx_expire == 0 ||
206 			    time_second < rt->rt_rmx.rmx_expire)
207 				senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
208 	}
209 	hlen = ETHER_HDR_LEN;
210 	switch (dst->sa_family) {
211 #ifdef INET
212 	case AF_INET:
213 		if (!arpresolve(ac, rt, m, dst, edst, rt0))
214 			return (0);	/* if not yet resolved */
215 		off = m->m_pkthdr.len - m->m_len;
216 		type = htons(ETHERTYPE_IP);
217 		break;
218 #endif
219 #ifdef IPX
220 	case AF_IPX:
221 		type = htons(ETHERTYPE_IPX);
222  		bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
223 		    (caddr_t)edst, sizeof (edst));
224 		break;
225 #endif
226 #ifdef NETATALK
227 	case AF_APPLETALK:
228 	  {
229 	    struct at_ifaddr *aa;
230 
231 	    if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
232 		    goto bad;
233 	    }
234 	    if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
235 		    return (0);
236 	    /*
237 	     * In the phase 2 case, need to prepend an mbuf for the llc header.
238 	     * Since we must preserve the value of m, which is passed to us by
239 	     * value, we m_copy() the first mbuf, and use it for our llc header.
240 	     */
241 	    if ( aa->aa_flags & AFA_PHASE2 ) {
242 		struct llc llc;
243 
244 		M_PREPEND(m, sizeof(struct llc), M_WAIT);
245 		len += sizeof(struct llc);
246 		llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
247 		llc.llc_control = LLC_UI;
248 		bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
249 		llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
250 		bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
251 		type = htons(m->m_pkthdr.len);
252 		hlen = sizeof(struct llc) + ETHER_HDR_LEN;
253 	    } else {
254 		type = htons(ETHERTYPE_AT);
255 	    }
256 	    break;
257 	  }
258 #endif NETATALK
259 #ifdef NS
260 	case AF_NS:
261 		switch(ns_nettype){
262 		default:
263 		case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
264 			type = 0x8137;
265 			break;
266 		case 0x0: /* Novell 802.3 */
267 			type = htons( m->m_pkthdr.len);
268 			break;
269 		case 0xe0e0: /* Novell 802.2 and Token-Ring */
270 			M_PREPEND(m, 3, M_WAIT);
271 			type = htons( m->m_pkthdr.len);
272 			cp = mtod(m, u_char *);
273 			*cp++ = 0xE0;
274 			*cp++ = 0xE0;
275 			*cp++ = 0x03;
276 			break;
277 		}
278  		bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
279 		    (caddr_t)edst, sizeof (edst));
280 		/*
281 		 * XXX if ns_thishost is the same as the node's ethernet
282 		 * address then just the default code will catch this anyhow.
283 		 * So I'm not sure if this next clause should be here at all?
284 		 * [JRE]
285 		 */
286 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
287 			m->m_pkthdr.rcvif = ifp;
288 			schednetisr(NETISR_NS);
289 			inq = &nsintrq;
290 			s = splimp();
291 			if (IF_QFULL(inq)) {
292 				IF_DROP(inq);
293 				m_freem(m);
294 			} else
295 				IF_ENQUEUE(inq, m);
296 			splx(s);
297 			return (error);
298 		}
299 		if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
300 			m->m_flags |= M_BCAST;
301 		}
302 		break;
303 #endif /* NS */
304 #ifdef	ISO
305 	case AF_ISO: {
306 		int	snpalen;
307 		struct	llc *l;
308 		register struct sockaddr_dl *sdl;
309 
310 		if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
311 		    sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
312 			bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
313 		} else if (error =
314 			    iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
315 					    (char *)edst, &snpalen))
316 			goto bad; /* Not Resolved */
317 		/* If broadcasting on a simplex interface, loopback a copy */
318 		if (*edst & 1)
319 			m->m_flags |= (M_BCAST|M_MCAST);
320 		M_PREPEND(m, 3, M_DONTWAIT);
321 		if (m == NULL)
322 			return (0);
323 		type = htons(m->m_pkthdr.len);
324 		l = mtod(m, struct llc *);
325 		l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
326 		l->llc_control = LLC_UI;
327 		len += 3;
328 		IFDEBUG(D_ETHER)
329 			int i;
330 			printf("unoutput: sending pkt to: ");
331 			for (i=0; i<6; i++)
332 				printf("%x ", edst[i] & 0xff);
333 			printf("\n");
334 		ENDDEBUG
335 		} break;
336 #endif /* ISO */
337 #ifdef	LLC
338 /*	case AF_NSAP: */
339 	case AF_CCITT: {
340 		register struct sockaddr_dl *sdl =
341 			(struct sockaddr_dl *) rt -> rt_gateway;
342 
343 		if (sdl && sdl->sdl_family == AF_LINK
344 		    && sdl->sdl_alen > 0) {
345 			bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
346 		} else goto bad; /* Not a link interface ? Funny ... */
347 		if (*edst & 1)
348 			loop_copy = 1;
349 		type = htons(m->m_pkthdr.len);
350 #ifdef LLC_DEBUG
351 		{
352 			int i;
353 			register struct llc *l = mtod(m, struct llc *);
354 
355 			printf("ether_output: sending LLC2 pkt to: ");
356 			for (i=0; i<6; i++)
357 				printf("%x ", edst[i] & 0xff);
358 			printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
359 			       type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
360 			       l->llc_control & 0xff);
361 
362 		}
363 #endif /* LLC_DEBUG */
364 		} break;
365 #endif /* LLC */
366 
367 	case pseudo_AF_HDRCMPLT:
368 		hdrcmplt = 1;
369 		eh = (struct ether_header *)dst->sa_data;
370 		(void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
371 		/* FALLTHROUGH */
372 
373 	case AF_UNSPEC:
374 		loop_copy = -1; /* if this is for us, don't do it */
375 		eh = (struct ether_header *)dst->sa_data;
376  		(void)memcpy(edst, eh->ether_dhost, sizeof (edst));
377 		type = eh->ether_type;
378 		break;
379 
380 	default:
381 		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
382 			dst->sa_family);
383 		senderr(EAFNOSUPPORT);
384 	}
385 
386 	/*
387 	 * Add local net header.  If no space in first mbuf,
388 	 * allocate another.
389 	 */
390 	M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
391 	if (m == 0)
392 		senderr(ENOBUFS);
393 	eh = mtod(m, struct ether_header *);
394 	(void)memcpy(&eh->ether_type, &type,
395 		sizeof(eh->ether_type));
396  	(void)memcpy(eh->ether_dhost, edst, sizeof (edst));
397 	if (hdrcmplt)
398 		(void)memcpy(eh->ether_shost, esrc,
399 			sizeof(eh->ether_shost));
400 	else
401 		(void)memcpy(eh->ether_shost, ac->ac_enaddr,
402 			sizeof(eh->ether_shost));
403 
404 	/*
405 	 * If a simplex interface, and the packet is being sent to our
406 	 * Ethernet address or a broadcast address, loopback a copy.
407 	 * XXX To make a simplex device behave exactly like a duplex
408 	 * device, we should copy in the case of sending to our own
409 	 * ethernet address (thus letting the original actually appear
410 	 * on the wire). However, we don't do that here for security
411 	 * reasons and compatibility with the original behavior.
412 	 */
413 	if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
414 		if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
415 			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
416 
417 			(void) if_simloop(ifp, n, dst, hlen);
418 		} else if (bcmp(eh->ether_dhost,
419 		    eh->ether_shost, ETHER_ADDR_LEN) == 0) {
420 			(void) if_simloop(ifp, m, dst, hlen);
421 			return (0);	/* XXX */
422 		}
423 	}
424 #ifdef BRIDGE
425 	if (do_bridge) {
426 		struct mbuf *m0 = m ;
427 
428 		if (m->m_pkthdr.rcvif)
429 			m->m_pkthdr.rcvif = NULL ;
430 		ifp = bridge_dst_lookup(m);
431 		bdg_forward(&m0, ifp);
432 		if (m0)
433 			m_freem(m0);
434 		return (0);
435 	}
436 #endif
437 	s = splimp();
438 	/*
439 	 * Queue message on interface, and start output if interface
440 	 * not yet active.
441 	 */
442 	if (IF_QFULL(&ifp->if_snd)) {
443 		IF_DROP(&ifp->if_snd);
444 		splx(s);
445 		senderr(ENOBUFS);
446 	}
447 	IF_ENQUEUE(&ifp->if_snd, m);
448 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
449 		(*ifp->if_start)(ifp);
450 	splx(s);
451 	ifp->if_obytes += len + sizeof (struct ether_header);
452 	if (m->m_flags & M_MCAST)
453 		ifp->if_omcasts++;
454 	return (error);
455 
456 bad:
457 	if (m)
458 		m_freem(m);
459 	return (error);
460 }
461 
462 /*
463  * Process a received Ethernet packet;
464  * the packet is in the mbuf chain m without
465  * the ether header, which is provided separately.
466  */
467 void
468 ether_input(ifp, eh, m)
469 	struct ifnet *ifp;
470 	register struct ether_header *eh;
471 	struct mbuf *m;
472 {
473 	register struct ifqueue *inq;
474 	u_short ether_type;
475 	int s;
476 #if defined (ISO) || defined (LLC) || defined(NETATALK)
477 	register struct llc *l;
478 #endif
479 
480 	if ((ifp->if_flags & IFF_UP) == 0) {
481 		m_freem(m);
482 		return;
483 	}
484 	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
485 	if (eh->ether_dhost[0] & 1) {
486 		if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
487 			 sizeof(etherbroadcastaddr)) == 0)
488 			m->m_flags |= M_BCAST;
489 		else
490 			m->m_flags |= M_MCAST;
491 	}
492 	if (m->m_flags & (M_BCAST|M_MCAST))
493 		ifp->if_imcasts++;
494 
495 	ether_type = ntohs(eh->ether_type);
496 
497 #ifdef	NETGRAPH
498 	{
499 		struct arpcom *ac = IFP2AC(ifp);
500 		if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
501 			ngether_send(ac, eh, m);
502 			return;
503 		}
504 	}
505 #endif	/* NETGRAPH */
506 
507 #if NVLAN > 0
508 	if (ether_type == vlan_proto) {
509 		if (vlan_input(eh, m) < 0)
510 			ifp->if_data.ifi_noproto++;
511 		return;
512 	}
513 #endif /* NVLAN > 0 */
514 
515 	switch (ether_type) {
516 #ifdef INET
517 	case ETHERTYPE_IP:
518 		if (ipflow_fastforward(m))
519 			return;
520 		schednetisr(NETISR_IP);
521 		inq = &ipintrq;
522 		break;
523 
524 	case ETHERTYPE_ARP:
525 		schednetisr(NETISR_ARP);
526 		inq = &arpintrq;
527 		break;
528 #endif
529 #ifdef IPX
530 	case ETHERTYPE_IPX:
531 		schednetisr(NETISR_IPX);
532 		inq = &ipxintrq;
533 		break;
534 #endif
535 #ifdef NS
536 	case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
537 		schednetisr(NETISR_NS);
538 		inq = &nsintrq;
539 		break;
540 
541 #endif /* NS */
542 #ifdef NETATALK
543         case ETHERTYPE_AT:
544                 schednetisr(NETISR_ATALK);
545                 inq = &atintrq1;
546                 break;
547         case ETHERTYPE_AARP:
548 		/* probably this should be done with a NETISR as well */
549                 aarpinput(IFP2AC(ifp), m); /* XXX */
550                 return;
551 #endif NETATALK
552 	default:
553 #ifdef NS
554 		checksum = mtod(m, ushort *);
555 		/* Novell 802.3 */
556 		if ((ether_type <= ETHERMTU) &&
557 			((*checksum == 0xffff) || (*checksum == 0xE0E0))){
558 			if(*checksum == 0xE0E0) {
559 				m->m_pkthdr.len -= 3;
560 				m->m_len -= 3;
561 				m->m_data += 3;
562 			}
563 				schednetisr(NETISR_NS);
564 				inq = &nsintrq;
565 				break;
566 		}
567 #endif /* NS */
568 #if defined (ISO) || defined (LLC) || defined(NETATALK)
569 		if (ether_type > ETHERMTU)
570 			goto dropanyway;
571 		l = mtod(m, struct llc *);
572 		switch (l->llc_dsap) {
573 #ifdef NETATALK
574 		case LLC_SNAP_LSAP:
575 		    switch (l->llc_control) {
576 		    case LLC_UI:
577 			if (l->llc_ssap != LLC_SNAP_LSAP)
578 			    goto dropanyway;
579 
580 			if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
581 				   sizeof(at_org_code)) == 0 &&
582 			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
583 			    inq = &atintrq2;
584 			    m_adj( m, sizeof( struct llc ));
585 			    schednetisr(NETISR_ATALK);
586 			    break;
587 			}
588 
589 			if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
590 				   sizeof(aarp_org_code)) == 0 &&
591 			     ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
592 			    m_adj( m, sizeof( struct llc ));
593 			    aarpinput(IFP2AC(ifp), m); /* XXX */
594 			    return;
595 			}
596 
597 		    default:
598 			goto dropanyway;
599 		    }
600 		    break;
601 #endif NETATALK
602 #ifdef	ISO
603 		case LLC_ISO_LSAP:
604 			switch (l->llc_control) {
605 			case LLC_UI:
606 				/* LLC_UI_P forbidden in class 1 service */
607 				if ((l->llc_dsap == LLC_ISO_LSAP) &&
608 				    (l->llc_ssap == LLC_ISO_LSAP)) {
609 					/* LSAP for ISO */
610 					if (m->m_pkthdr.len > ether_type)
611 						m_adj(m, ether_type - m->m_pkthdr.len);
612 					m->m_data += 3;		/* XXX */
613 					m->m_len -= 3;		/* XXX */
614 					m->m_pkthdr.len -= 3;	/* XXX */
615 					M_PREPEND(m, sizeof *eh, M_DONTWAIT);
616 					if (m == 0)
617 						return;
618 					*mtod(m, struct ether_header *) = *eh;
619 					IFDEBUG(D_ETHER)
620 						printf("clnp packet");
621 					ENDDEBUG
622 					schednetisr(NETISR_ISO);
623 					inq = &clnlintrq;
624 					break;
625 				}
626 				goto dropanyway;
627 
628 			case LLC_XID:
629 			case LLC_XID_P:
630 				if(m->m_len < 6)
631 					goto dropanyway;
632 				l->llc_window = 0;
633 				l->llc_fid = 9;
634 				l->llc_class = 1;
635 				l->llc_dsap = l->llc_ssap = 0;
636 				/* Fall through to */
637 			case LLC_TEST:
638 			case LLC_TEST_P:
639 			{
640 				struct sockaddr sa;
641 				register struct ether_header *eh2;
642 				int i;
643 				u_char c = l->llc_dsap;
644 
645 				l->llc_dsap = l->llc_ssap;
646 				l->llc_ssap = c;
647 				if (m->m_flags & (M_BCAST | M_MCAST))
648 					bcopy((caddr_t)ac->ac_enaddr,
649 					      (caddr_t)eh->ether_dhost, 6);
650 				sa.sa_family = AF_UNSPEC;
651 				sa.sa_len = sizeof(sa);
652 				eh2 = (struct ether_header *)sa.sa_data;
653 				for (i = 0; i < 6; i++) {
654 					eh2->ether_shost[i] = c = eh->ether_dhost[i];
655 					eh2->ether_dhost[i] =
656 						eh->ether_dhost[i] = eh->ether_shost[i];
657 					eh->ether_shost[i] = c;
658 				}
659 				ifp->if_output(ifp, m, &sa, NULL);
660 				return;
661 			}
662 			default:
663 				m_freem(m);
664 				return;
665 			}
666 			break;
667 #endif /* ISO */
668 #ifdef LLC
669 		case LLC_X25_LSAP:
670 		{
671 			if (m->m_pkthdr.len > ether_type)
672 				m_adj(m, ether_type - m->m_pkthdr.len);
673 			M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
674 			if (m == 0)
675 				return;
676 			if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
677 					    eh->ether_dhost, LLC_X25_LSAP, 6,
678 					    mtod(m, struct sdl_hdr *)))
679 				panic("ETHER cons addr failure");
680 			mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
681 #ifdef LLC_DEBUG
682 				printf("llc packet\n");
683 #endif /* LLC_DEBUG */
684 			schednetisr(NETISR_CCITT);
685 			inq = &llcintrq;
686 			break;
687 		}
688 #endif /* LLC */
689 		dropanyway:
690 		default:
691 #ifdef	NETGRAPH
692 			ngether_send(IFP2AC(ifp), eh, m);
693 #else	/* NETGRAPH */
694 			m_freem(m);
695 #endif	/* NETGRAPH */
696 			return;
697 		}
698 #else /* ISO || LLC || NETATALK */
699 #ifdef	NETGRAPH
700 	    ngether_send(IFP2AC(ifp), eh, m);
701 #else	/* NETGRAPH */
702 	    m_freem(m);
703 #endif	/* NETGRAPH */
704 	    return;
705 #endif /* ISO || LLC || NETATALK */
706 	}
707 
708 	s = splimp();
709 	if (IF_QFULL(inq)) {
710 		IF_DROP(inq);
711 		m_freem(m);
712 	} else
713 		IF_ENQUEUE(inq, m);
714 	splx(s);
715 }
716 
717 /*
718  * Perform common duties while attaching to interface list
719  */
720 void
721 ether_ifattach(ifp)
722 	register struct ifnet *ifp;
723 {
724 	register struct ifaddr *ifa;
725 	register struct sockaddr_dl *sdl;
726 
727 	ifp->if_type = IFT_ETHER;
728 	ifp->if_addrlen = 6;
729 	ifp->if_hdrlen = 14;
730 	ifp->if_mtu = ETHERMTU;
731 	ifp->if_resolvemulti = ether_resolvemulti;
732 	if (ifp->if_baudrate == 0)
733 	    ifp->if_baudrate = 10000000;
734 	ifa = ifnet_addrs[ifp->if_index - 1];
735 	if (ifa == 0) {
736 		printf("ether_ifattach: no lladdr!\n");
737 		return;
738 	}
739 	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
740 	sdl->sdl_type = IFT_ETHER;
741 	sdl->sdl_alen = ifp->if_addrlen;
742 	bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
743 #ifdef	NETGRAPH
744 	ngether_init(ifp);
745 #endif /* NETGRAPH */
746 }
747 
748 SYSCTL_DECL(_net_link);
749 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
750 
751 int
752 ether_ioctl(ifp, command, data)
753 	struct ifnet *ifp;
754 	int command;
755 	caddr_t data;
756 {
757 	struct ifaddr *ifa = (struct ifaddr *) data;
758 	struct ifreq *ifr = (struct ifreq *) data;
759 	int error = 0;
760 
761 	switch (command) {
762 	case SIOCSIFADDR:
763 		ifp->if_flags |= IFF_UP;
764 
765 		switch (ifa->ifa_addr->sa_family) {
766 #ifdef INET
767 		case AF_INET:
768 			ifp->if_init(ifp->if_softc);	/* before arpwhohas */
769 			arp_ifinit(IFP2AC(ifp), ifa);
770 			break;
771 #endif
772 #ifdef IPX
773 		/*
774 		 * XXX - This code is probably wrong
775 		 */
776 		case AF_IPX:
777 			{
778 			register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
779 			struct arpcom *ac = IFP2AC(ifp);
780 
781 			if (ipx_nullhost(*ina))
782 				ina->x_host =
783 				    *(union ipx_host *)
784 			            ac->ac_enaddr;
785 			else {
786 				bcopy((caddr_t) ina->x_host.c_host,
787 				      (caddr_t) ac->ac_enaddr,
788 				      sizeof(ac->ac_enaddr));
789 			}
790 
791 			/*
792 			 * Set new address
793 			 */
794 			ifp->if_init(ifp->if_softc);
795 			break;
796 			}
797 #endif
798 #ifdef NS
799 		/*
800 		 * XXX - This code is probably wrong
801 		 */
802 		case AF_NS:
803 		{
804 			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
805 			struct arpcom *ac = IFP2AC(ifp);
806 
807 			if (ns_nullhost(*ina))
808 				ina->x_host =
809 				    *(union ns_host *) (ac->ac_enaddr);
810 			else {
811 				bcopy((caddr_t) ina->x_host.c_host,
812 				      (caddr_t) ac->ac_enaddr,
813 				      sizeof(ac->ac_enaddr));
814 			}
815 
816 			/*
817 			 * Set new address
818 			 */
819 			ifp->if_init(ifp->if_softc);
820 			break;
821 		}
822 #endif
823 		default:
824 			ifp->if_init(ifp->if_softc);
825 			break;
826 		}
827 		break;
828 
829 	case SIOCGIFADDR:
830 		{
831 			struct sockaddr *sa;
832 
833 			sa = (struct sockaddr *) & ifr->ifr_data;
834 			bcopy(IFP2AC(ifp)->ac_enaddr,
835 			      (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
836 		}
837 		break;
838 
839 	case SIOCSIFMTU:
840 		/*
841 		 * Set the interface MTU.
842 		 */
843 		if (ifr->ifr_mtu > ETHERMTU) {
844 			error = EINVAL;
845 		} else {
846 			ifp->if_mtu = ifr->ifr_mtu;
847 		}
848 		break;
849 	}
850 	return (error);
851 }
852 
853 int
854 ether_resolvemulti(ifp, llsa, sa)
855 	struct ifnet *ifp;
856 	struct sockaddr **llsa;
857 	struct sockaddr *sa;
858 {
859 	struct sockaddr_dl *sdl;
860 	struct sockaddr_in *sin;
861 	u_char *e_addr;
862 
863 	switch(sa->sa_family) {
864 	case AF_LINK:
865 		/*
866 		 * No mapping needed. Just check that it's a valid MC address.
867 		 */
868 		sdl = (struct sockaddr_dl *)sa;
869 		e_addr = LLADDR(sdl);
870 		if ((e_addr[0] & 1) != 1)
871 			return EADDRNOTAVAIL;
872 		*llsa = 0;
873 		return 0;
874 
875 #ifdef INET
876 	case AF_INET:
877 		sin = (struct sockaddr_in *)sa;
878 		if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
879 			return EADDRNOTAVAIL;
880 		MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
881 		       M_WAITOK);
882 		sdl->sdl_len = sizeof *sdl;
883 		sdl->sdl_family = AF_LINK;
884 		sdl->sdl_index = ifp->if_index;
885 		sdl->sdl_type = IFT_ETHER;
886 		sdl->sdl_nlen = 0;
887 		sdl->sdl_alen = ETHER_ADDR_LEN;
888 		sdl->sdl_slen = 0;
889 		e_addr = LLADDR(sdl);
890 		ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
891 		*llsa = (struct sockaddr *)sdl;
892 		return 0;
893 #endif
894 
895 	default:
896 		/*
897 		 * Well, the text isn't quite right, but it's the name
898 		 * that counts...
899 		 */
900 		return EAFNOSUPPORT;
901 	}
902 }
903 
904 #ifdef	NETGRAPH
905 
906 /***********************************************************************
907  * This section contains the methods for the Netgraph interface
908  ***********************************************************************/
909 /* It's Ascii-art time!
910  * The ifnet is the first part of the arpcom which must be
911  * the first part of the device's softc.. yuk.
912  *
913  *      +--------------------------+-----+---------+
914  *      |   struct ifnet (*ifp)    |     |         |
915  *      |                          |     |         |
916  *      +--------------------------+     |         |
917  *   +--|[ac_ng]     struct arpcom (*ac) |         |
918  *   |  +--------------------------------+         |
919  *   |  |   struct softc (*ifp->if_softc) (device) |
920  *   |  +------------------------------------------+
921  *   |               ^
922  * AC2NG()           |
923  *   |               v
924  *   |       +----------------------+
925  *   |       |   [private] [flags]  |
926  *   +------>| struct ng_node       |
927  *           |    [hooks]           | ** we only allow one hook
928  *           +----------------------+
929  *                   ^
930  *                   |
931  *                   v
932  *           +-------------+
933  *           |    [node]   |
934  *           |    hook     |
935  *           |    [private]|-- *unused*
936  *           +-------------+
937  */
938 
939 /*
940  * called during interface attaching
941  */
942 static void
943 ngether_init(void *ifpvoid)
944 {
945 	struct	ifnet *ifp = ifpvoid;
946 	struct arpcom *ac = IFP2AC(ifp);
947 	static int	ngether_done_init;
948 	char	namebuf[32];
949 	node_p node;
950 
951 	/*
952 	 * we have found a node, make sure our 'type' is availabe.
953 	 */
954 	if (ngether_done_init == 0) {
955 		if (ng_newtype(&typestruct)) {
956 			printf("ngether install failed\n");
957 			return;
958 		}
959 		ngether_done_init = 1;
960 	}
961 	if (ng_make_node_common(&typestruct, &node) != 0)
962 		return;
963 	ac->ac_ng = node;
964 	node->private = ifp;
965 	sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
966 	ng_name_node(AC2NG(ac), namebuf);
967 }
968 
969 /*
970  * It is not possible or allowable to create a node of this type.
971  * If the hardware exists, it will already have created it.
972  */
973 static	int
974 ngether_constructor(node_p *nodep)
975 {
976 	return (EINVAL);
977 }
978 
979 /*
980  * Give our ok for a hook to be added...
981  *
982  * Allow one hook at a time (rawdata).
983  * It can eiteh rdivert everything or only unclaimed packets.
984  */
985 static	int
986 ngether_newhook(node_p node, hook_p hook, const char *name)
987 {
988 
989 	/* check if there is already a hook */
990 	if (LIST_FIRST(&(node->hooks)))
991 		return(EISCONN);
992 	/*
993 	 * Check for which mode hook we want.
994 	 */
995 	if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
996 		if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
997 			return (EINVAL);
998 		}
999 		node->flags |= NGEF_DIVERT;
1000 	} else {
1001 		node->flags &= ~NGEF_DIVERT;
1002 	}
1003 	return (0);
1004 }
1005 
1006 /*
1007  * incoming messages.
1008  * Just respond to the generic TEXT_STATUS message
1009  */
1010 static	int
1011 ngether_rcvmsg(node_p node,
1012 	struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
1013 {
1014 	struct ifnet	*ifp;
1015 	int error = 0;
1016 
1017 	ifp = node->private;
1018 	switch (msg->header.typecookie) {
1019 	    case	NGM_ETHER_COOKIE:
1020 		error = EINVAL;
1021 		break;
1022 	    case	NGM_GENERIC_COOKIE:
1023 		switch(msg->header.cmd) {
1024 		    case NGM_TEXT_STATUS: {
1025 			    char	*arg;
1026 			    int pos = 0;
1027 			    int resplen = sizeof(struct ng_mesg) + 512;
1028 			    MALLOC(*resp, struct ng_mesg *, resplen,
1029 					M_NETGRAPH, M_NOWAIT);
1030 			    if (*resp == NULL) {
1031 				error = ENOMEM;
1032 				break;
1033 			    }
1034 			    bzero(*resp, resplen);
1035 			    arg = (*resp)->data;
1036 
1037 			    /*
1038 			     * Put in the throughput information.
1039 			     */
1040 			    pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
1041 			    ifp->if_ibytes, ifp->if_obytes);
1042 			    pos += sprintf(arg + pos,
1043 				"%ld output errors\n",
1044 			    	ifp->if_oerrors);
1045 			    pos += sprintf(arg + pos,
1046 				"ierrors = %ld\n",
1047 			    	ifp->if_ierrors);
1048 
1049 			    (*resp)->header.version = NG_VERSION;
1050 			    (*resp)->header.arglen = strlen(arg) + 1;
1051 			    (*resp)->header.token = msg->header.token;
1052 			    (*resp)->header.typecookie = NGM_ETHER_COOKIE;
1053 			    (*resp)->header.cmd = msg->header.cmd;
1054 			    strncpy((*resp)->header.cmdstr, "status",
1055 					NG_CMDSTRLEN);
1056 			}
1057 			break;
1058 	    	    default:
1059 		 	error = EINVAL;
1060 		 	break;
1061 		    }
1062 		break;
1063 	    default:
1064 		error = EINVAL;
1065 		break;
1066 	}
1067 	free(msg, M_NETGRAPH);
1068 	return (error);
1069 }
1070 
1071 /*
1072  * Receive a completed ethernet packet.
1073  * Queue it for output.
1074  */
1075 static	int
1076 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1077 {
1078 	struct ifnet *ifp;
1079 	int	error = 0;
1080 	int	s;
1081 	struct ether_header *eh;
1082 
1083 	ifp = hook->node->private;
1084 
1085 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1086 		senderr(ENETDOWN);
1087 	/*
1088 	 * If a simplex interface, and the packet is being sent to our
1089 	 * Ethernet address or a broadcast address, loopback a copy.
1090 	 * XXX To make a simplex device behave exactly like a duplex
1091 	 * device, we should copy in the case of sending to our own
1092 	 * ethernet address (thus letting the original actually appear
1093 	 * on the wire). However, we don't do that here for security
1094 	 * reasons and compatibility with the original behavior.
1095 	 */
1096 	if (ifp->if_flags & IFF_SIMPLEX) {
1097 		eh = mtod(m, struct ether_header *);
1098 		if (m->m_flags & M_BCAST) {
1099 			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
1100 
1101 			ng_queue_data(hook, n, meta);
1102 		} else if (bcmp(eh->ether_dhost,
1103 		    eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1104 			ng_queue_data(hook, m, meta);
1105 			return (0);	/* XXX */
1106 		}
1107 	}
1108 	s = splimp();
1109 	/*
1110 	 * Queue message on interface, and start output if interface
1111 	 * not yet active.
1112 	 * XXX if we lookead at the priority in the meta data we could
1113 	 * queue high priority items at the head.
1114 	 */
1115 	if (IF_QFULL(&ifp->if_snd)) {
1116 		IF_DROP(&ifp->if_snd);
1117 		splx(s);
1118 		senderr(ENOBUFS);
1119 	}
1120 	IF_ENQUEUE(&ifp->if_snd, m);
1121 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
1122 		(*ifp->if_start)(ifp);
1123 	splx(s);
1124 	ifp->if_obytes += m->m_pkthdr.len;
1125 	if (m->m_flags & M_MCAST)
1126 		ifp->if_omcasts++;
1127 	return (error);
1128 
1129 bad:
1130 	NG_FREE_DATA(m, meta);
1131 	return (error);
1132 }
1133 
1134 /*
1135  * pass an mbuf out to the connected hook
1136  */
1137 static void
1138 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
1139 {
1140 	node_p node = AC2NG(ac);
1141 	struct ether_header *eh2;
1142 
1143 	if (node && LIST_FIRST(&(node->hooks))) {
1144 		M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
1145 		if (m == 0)
1146 			return;
1147 		eh2 = mtod(m, struct ether_header *);
1148 		/*
1149 		 * Possibly 'eh' already points
1150 		 * to the right place.
1151 		 */
1152 		if (eh2 != eh)
1153 	 		bcopy(eh, eh2, sizeof(*eh));
1154 		ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
1155 	} else {
1156 		m_freem(m);
1157 	}
1158 }
1159 /*
1160  * do local shutdown processing..
1161  * This node will refuse to go away, unless the hardware says to..
1162  * don't unref the node, or remove our name. just clear our links up.
1163  */
1164 static	int
1165 ngether_rmnode(node_p node)
1166 {
1167 	ng_cutlinks(node);
1168 	node->flags &= ~NG_INVALID; /* bounce back to life */
1169 	return (0);
1170 }
1171 
1172 /* already linked */
1173 static	int
1174 ngether_connect(hook_p hook)
1175 {
1176 	/* be really amiable and just say "YUP that's OK by me! " */
1177 	return (0);
1178 }
1179 
1180 /*
1181  * notify on hook disconnection (destruction)
1182  *
1183  * For this type, removal of the last lins no effect. The interface can run
1184  * independently.
1185  * Since we have no per-hook information, this is rather simple.
1186  */
1187 static	int
1188 ngether_disconnect(hook_p hook)
1189 {
1190 	hook->node->flags &= ~NGEF_DIVERT;
1191 	return (0);
1192 }
1193 #endif /* NETGRAPH */
1194 
1195 /********************************** END *************************************/
1196