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