2 * Copyright (c) 1982, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
37 #include "opt_atalk.h"
39 #include "opt_inet6.h"
42 #include "opt_netgraph.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/malloc.h>
49 #include <sys/socket.h>
50 #include <sys/sockio.h>
51 #include <sys/sysctl.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>
60 #if defined(INET) || defined(INET6)
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <netinet/if_ether.h>
66 #include <netinet6/nd6.h>
67 #include <netinet6/in6_ifattach.h>
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 *m,
75 struct sockaddr *dst, short *tp);
80 #include <netns/ns_if.h>
82 int ether_outputdebug = 0;
83 int ether_inputdebug = 0;
87 #include <netiso/argo_debug.h>
88 #include <netiso/iso.h>
89 #include <netiso/iso_var.h>
90 #include <netiso/iso_snpac.h>
94 #include <netccitt/dll.h>
95 #include <netccitt/llc_var.h>
98 #if defined(LLC) && defined(CCITT)
99 extern struct ifqueue pkintrq;
103 #include <netatalk/at.h>
104 #include <netatalk/at_var.h>
105 #include <netatalk/at_extern.h>
107 #define llc_snap_org_code llc_un.type_snap.org_code
108 #define llc_snap_ether_type llc_un.type_snap.ether_type
110 extern u_char at_org_code[3];
111 extern u_char aarp_org_code[3];
112 #endif /* NETATALK */
115 #include <net/bridge.h>
120 #include <net/if_vlan_var.h>
121 #endif /* NVLAN > 0 */
123 static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
125 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
126 #define senderr(e) do { error = (e); goto bad;} while (0)
127 #define IFP2AC(IFP) ((struct arpcom *)IFP)
130 #include <netgraph/ng_ether.h>
131 #include <netgraph/ng_message.h>
132 #include <netgraph/netgraph.h>
134 static void ngether_init(void* ignored);
135 static void ngether_send(struct arpcom *ac,
136 struct ether_header *eh, struct mbuf *m);
137 static ng_constructor_t ngether_constructor;
138 static ng_rcvmsg_t ngether_rcvmsg;
139 static ng_shutdown_t ngether_rmnode;
140 static ng_newhook_t ngether_newhook;
141 static ng_connect_t ngether_connect;
142 static ng_rcvdata_t ngether_rcvdata;
143 static ng_disconnect_t ngether_disconnect;
145 static struct ng_type typestruct = {
161 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
162 #define NGEF_DIVERT NGF_TYPE1 /* all packets sent to netgraph */
163 #endif /* NETGRAPH */
166 * Ethernet output routine.
167 * Encapsulate a packet of type family for the local net.
168 * Use trailer local net encapsulation if enough data in first
169 * packet leaves a multiple of 512 bytes of data in remainder.
170 * Assumes that ifp is actually pointer to arpcom structure.
173 ether_output(ifp, m, dst, rt0)
174 register struct ifnet *ifp;
176 struct sockaddr *dst;
180 int s, error = 0, hdrcmplt = 0;
181 u_char esrc[6], edst[6];
182 register struct rtentry *rt;
183 register struct ether_header *eh;
184 int off, len = m->m_pkthdr.len, loop_copy = 0;
185 int hlen; /* link layer header lenght */
186 struct arpcom *ac = IFP2AC(ifp);
188 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
192 if ((rt->rt_flags & RTF_UP) == 0) {
193 rt0 = rt = rtalloc1(dst, 1, 0UL);
197 senderr(EHOSTUNREACH);
199 if (rt->rt_flags & RTF_GATEWAY) {
200 if (rt->rt_gwroute == 0)
202 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
203 rtfree(rt); rt = rt0;
204 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
206 if ((rt = rt->rt_gwroute) == 0)
207 senderr(EHOSTUNREACH);
210 if (rt->rt_flags & RTF_REJECT)
211 if (rt->rt_rmx.rmx_expire == 0 ||
212 time_second < rt->rt_rmx.rmx_expire)
213 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
215 hlen = ETHER_HDR_LEN;
216 switch (dst->sa_family) {
219 if (!arpresolve(ac, rt, m, dst, edst, rt0))
220 return (0); /* if not yet resolved */
221 off = m->m_pkthdr.len - m->m_len;
222 type = htons(ETHERTYPE_IP);
227 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
228 /* this must be impossible, so we bark */
229 printf("nd6_storelladdr failed\n");
232 off = m->m_pkthdr.len - m->m_len;
233 type = htons(ETHERTYPE_IPV6);
239 error = ef_outputp(ifp, m, dst, &type);
241 senderr(EPFNOSUPPORT);
243 type = htons(ETHERTYPE_IPX);
245 type = htons(ETHERTYPE_IPX);
246 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
247 (caddr_t)edst, sizeof (edst));
253 struct at_ifaddr *aa;
255 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
258 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
261 * In the phase 2 case, need to prepend an mbuf for the llc header.
262 * Since we must preserve the value of m, which is passed to us by
263 * value, we m_copy() the first mbuf, and use it for our llc header.
265 if ( aa->aa_flags & AFA_PHASE2 ) {
268 M_PREPEND(m, sizeof(struct llc), M_WAIT);
269 len += sizeof(struct llc);
270 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
271 llc.llc_control = LLC_UI;
272 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
273 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
274 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
275 type = htons(m->m_pkthdr.len);
276 hlen = sizeof(struct llc) + ETHER_HDR_LEN;
278 type = htons(ETHERTYPE_AT);
287 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
290 case 0x0: /* Novell 802.3 */
291 type = htons( m->m_pkthdr.len);
293 case 0xe0e0: /* Novell 802.2 and Token-Ring */
294 M_PREPEND(m, 3, M_WAIT);
295 type = htons( m->m_pkthdr.len);
296 cp = mtod(m, u_char *);
302 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
303 (caddr_t)edst, sizeof (edst));
305 * XXX if ns_thishost is the same as the node's ethernet
306 * address then just the default code will catch this anyhow.
307 * So I'm not sure if this next clause should be here at all?
310 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
311 m->m_pkthdr.rcvif = ifp;
312 schednetisr(NETISR_NS);
323 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
324 m->m_flags |= M_BCAST;
332 register struct sockaddr_dl *sdl;
334 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
335 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
336 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
338 iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
339 (char *)edst, &snpalen))
340 goto bad; /* Not Resolved */
341 /* If broadcasting on a simplex interface, loopback a copy */
343 m->m_flags |= (M_BCAST|M_MCAST);
344 M_PREPEND(m, 3, M_DONTWAIT);
347 type = htons(m->m_pkthdr.len);
348 l = mtod(m, struct llc *);
349 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
350 l->llc_control = LLC_UI;
354 printf("unoutput: sending pkt to: ");
356 printf("%x ", edst[i] & 0xff);
364 register struct sockaddr_dl *sdl =
365 (struct sockaddr_dl *) rt -> rt_gateway;
367 if (sdl && sdl->sdl_family == AF_LINK
368 && sdl->sdl_alen > 0) {
369 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
370 } else goto bad; /* Not a link interface ? Funny ... */
373 type = htons(m->m_pkthdr.len);
377 register struct llc *l = mtod(m, struct llc *);
379 printf("ether_output: sending LLC2 pkt to: ");
381 printf("%x ", edst[i] & 0xff);
382 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
383 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
384 l->llc_control & 0xff);
387 #endif /* LLC_DEBUG */
391 case pseudo_AF_HDRCMPLT:
393 eh = (struct ether_header *)dst->sa_data;
394 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
398 loop_copy = -1; /* if this is for us, don't do it */
399 eh = (struct ether_header *)dst->sa_data;
400 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
401 type = eh->ether_type;
405 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
407 senderr(EAFNOSUPPORT);
411 * Add local net header. If no space in first mbuf,
414 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
417 eh = mtod(m, struct ether_header *);
418 (void)memcpy(&eh->ether_type, &type,
419 sizeof(eh->ether_type));
420 (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
422 (void)memcpy(eh->ether_shost, esrc,
423 sizeof(eh->ether_shost));
425 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
426 sizeof(eh->ether_shost));
429 * If a simplex interface, and the packet is being sent to our
430 * Ethernet address or a broadcast address, loopback a copy.
431 * XXX To make a simplex device behave exactly like a duplex
432 * device, we should copy in the case of sending to our own
433 * ethernet address (thus letting the original actually appear
434 * on the wire). However, we don't do that here for security
435 * reasons and compatibility with the original behavior.
437 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
438 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
439 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
441 (void) if_simloop(ifp, n, dst, hlen);
442 } else if (bcmp(eh->ether_dhost,
443 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
444 (void) if_simloop(ifp, m, dst, hlen);
445 return (0); /* XXX */
450 struct mbuf *m0 = m ;
452 if (m->m_pkthdr.rcvif)
453 m->m_pkthdr.rcvif = NULL ;
454 ifp = bridge_dst_lookup(m);
455 bdg_forward(&m0, ifp);
463 * Queue message on interface, and start output if interface
466 if (IF_QFULL(&ifp->if_snd)) {
467 IF_DROP(&ifp->if_snd);
471 IF_ENQUEUE(&ifp->if_snd, m);
472 if ((ifp->if_flags & IFF_OACTIVE) == 0)
473 (*ifp->if_start)(ifp);
475 ifp->if_obytes += len + sizeof (struct ether_header);
476 if (m->m_flags & M_MCAST)
487 * Process a received Ethernet packet;
488 * the packet is in the mbuf chain m without
489 * the ether header, which is provided separately.
492 ether_input(ifp, eh, m)
494 register struct ether_header *eh;
497 register struct ifqueue *inq;
500 #if defined (ISO) || defined (LLC) || defined(NETATALK)
501 register struct llc *l;
504 if ((ifp->if_flags & IFF_UP) == 0) {
508 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
509 if (eh->ether_dhost[0] & 1) {
510 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
511 sizeof(etherbroadcastaddr)) == 0)
512 m->m_flags |= M_BCAST;
514 m->m_flags |= M_MCAST;
516 if (m->m_flags & (M_BCAST|M_MCAST))
519 ether_type = ntohs(eh->ether_type);
523 struct arpcom *ac = IFP2AC(ifp);
524 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
525 ngether_send(ac, eh, m);
529 #endif /* NETGRAPH */
532 if (ether_type == vlan_proto) {
533 if (vlan_input(eh, m) < 0)
534 ifp->if_data.ifi_noproto++;
537 #endif /* NVLAN > 0 */
539 switch (ether_type) {
542 if (ipflow_fastforward(m))
544 schednetisr(NETISR_IP);
549 schednetisr(NETISR_ARP);
555 if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
557 schednetisr(NETISR_IPX);
563 schednetisr(NETISR_IPV6);
568 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
569 schednetisr(NETISR_NS);
576 schednetisr(NETISR_ATALK);
580 /* probably this should be done with a NETISR as well */
581 aarpinput(IFP2AC(ifp), m); /* XXX */
586 if (ef_inputp && ef_inputp(ifp, eh, m) == 0)
590 checksum = mtod(m, ushort *);
592 if ((ether_type <= ETHERMTU) &&
593 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
594 if(*checksum == 0xE0E0) {
595 m->m_pkthdr.len -= 3;
599 schednetisr(NETISR_NS);
604 #if defined (ISO) || defined (LLC) || defined(NETATALK)
605 if (ether_type > ETHERMTU)
607 l = mtod(m, struct llc *);
608 switch (l->llc_dsap) {
611 switch (l->llc_control) {
613 if (l->llc_ssap != LLC_SNAP_LSAP)
616 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
617 sizeof(at_org_code)) == 0 &&
618 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
620 m_adj( m, sizeof( struct llc ));
621 schednetisr(NETISR_ATALK);
625 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
626 sizeof(aarp_org_code)) == 0 &&
627 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
628 m_adj( m, sizeof( struct llc ));
629 aarpinput(IFP2AC(ifp), m); /* XXX */
640 switch (l->llc_control) {
642 /* LLC_UI_P forbidden in class 1 service */
643 if ((l->llc_dsap == LLC_ISO_LSAP) &&
644 (l->llc_ssap == LLC_ISO_LSAP)) {
646 if (m->m_pkthdr.len > ether_type)
647 m_adj(m, ether_type - m->m_pkthdr.len);
648 m->m_data += 3; /* XXX */
649 m->m_len -= 3; /* XXX */
650 m->m_pkthdr.len -= 3; /* XXX */
651 M_PREPEND(m, sizeof *eh, M_DONTWAIT);
654 *mtod(m, struct ether_header *) = *eh;
656 printf("clnp packet");
658 schednetisr(NETISR_ISO);
671 l->llc_dsap = l->llc_ssap = 0;
672 /* Fall through to */
677 register struct ether_header *eh2;
679 u_char c = l->llc_dsap;
681 l->llc_dsap = l->llc_ssap;
683 if (m->m_flags & (M_BCAST | M_MCAST))
684 bcopy((caddr_t)ac->ac_enaddr,
685 (caddr_t)eh->ether_dhost, 6);
686 sa.sa_family = AF_UNSPEC;
687 sa.sa_len = sizeof(sa);
688 eh2 = (struct ether_header *)sa.sa_data;
689 for (i = 0; i < 6; i++) {
690 eh2->ether_shost[i] = c = eh->ether_dhost[i];
691 eh2->ether_dhost[i] =
692 eh->ether_dhost[i] = eh->ether_shost[i];
693 eh->ether_shost[i] = c;
695 ifp->if_output(ifp, m, &sa, NULL);
707 if (m->m_pkthdr.len > ether_type)
708 m_adj(m, ether_type - m->m_pkthdr.len);
709 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
712 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
713 eh->ether_dhost, LLC_X25_LSAP, 6,
714 mtod(m, struct sdl_hdr *)))
715 panic("ETHER cons addr failure");
716 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
718 printf("llc packet\n");
719 #endif /* LLC_DEBUG */
720 schednetisr(NETISR_CCITT);
728 ngether_send(IFP2AC(ifp), eh, m);
731 #endif /* NETGRAPH */
734 #else /* ISO || LLC || NETATALK */
736 ngether_send(IFP2AC(ifp), eh, m);
739 #endif /* NETGRAPH */
741 #endif /* ISO || LLC || NETATALK */
754 * Perform common duties while attaching to interface list
758 register struct ifnet *ifp;
760 register struct ifaddr *ifa;
761 register struct sockaddr_dl *sdl;
763 ifp->if_type = IFT_ETHER;
766 ifp->if_mtu = ETHERMTU;
767 ifp->if_resolvemulti = ether_resolvemulti;
768 if (ifp->if_baudrate == 0)
769 ifp->if_baudrate = 10000000;
770 ifa = ifnet_addrs[ifp->if_index - 1];
772 printf("ether_ifattach: no lladdr!\n");
775 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
776 sdl->sdl_type = IFT_ETHER;
777 sdl->sdl_alen = ifp->if_addrlen;
778 bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
781 #endif /* NETGRAPH */
783 in6_ifattach_getifid(ifp);
787 SYSCTL_DECL(_net_link);
788 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
791 ether_ioctl(ifp, command, data)
796 struct ifaddr *ifa = (struct ifaddr *) data;
797 struct ifreq *ifr = (struct ifreq *) data;
802 ifp->if_flags |= IFF_UP;
804 switch (ifa->ifa_addr->sa_family) {
807 ifp->if_init(ifp->if_softc); /* before arpwhohas */
808 arp_ifinit(IFP2AC(ifp), ifa);
813 * XXX - This code is probably wrong
817 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
818 struct arpcom *ac = IFP2AC(ifp);
820 if (ipx_nullhost(*ina))
825 bcopy((caddr_t) ina->x_host.c_host,
826 (caddr_t) ac->ac_enaddr,
827 sizeof(ac->ac_enaddr));
833 ifp->if_init(ifp->if_softc);
839 * XXX - This code is probably wrong
843 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
844 struct arpcom *ac = IFP2AC(ifp);
846 if (ns_nullhost(*ina))
848 *(union ns_host *) (ac->ac_enaddr);
850 bcopy((caddr_t) ina->x_host.c_host,
851 (caddr_t) ac->ac_enaddr,
852 sizeof(ac->ac_enaddr));
858 ifp->if_init(ifp->if_softc);
863 ifp->if_init(ifp->if_softc);
872 sa = (struct sockaddr *) & ifr->ifr_data;
873 bcopy(IFP2AC(ifp)->ac_enaddr,
874 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
880 * Set the interface MTU.
882 if (ifr->ifr_mtu > ETHERMTU) {
885 ifp->if_mtu = ifr->ifr_mtu;
893 ether_resolvemulti(ifp, llsa, sa)
895 struct sockaddr **llsa;
898 struct sockaddr_dl *sdl;
899 struct sockaddr_in *sin;
901 struct sockaddr_in6 *sin6;
905 switch(sa->sa_family) {
908 * No mapping needed. Just check that it's a valid MC address.
910 sdl = (struct sockaddr_dl *)sa;
911 e_addr = LLADDR(sdl);
912 if ((e_addr[0] & 1) != 1)
913 return EADDRNOTAVAIL;
919 sin = (struct sockaddr_in *)sa;
920 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
921 return EADDRNOTAVAIL;
922 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
924 sdl->sdl_len = sizeof *sdl;
925 sdl->sdl_family = AF_LINK;
926 sdl->sdl_index = ifp->if_index;
927 sdl->sdl_type = IFT_ETHER;
929 sdl->sdl_alen = ETHER_ADDR_LEN;
931 e_addr = LLADDR(sdl);
932 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
933 *llsa = (struct sockaddr *)sdl;
938 sin6 = (struct sockaddr_in6 *)sa;
939 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
940 return EADDRNOTAVAIL;
941 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
943 sdl->sdl_len = sizeof *sdl;
944 sdl->sdl_family = AF_LINK;
945 sdl->sdl_index = ifp->if_index;
946 sdl->sdl_type = IFT_ETHER;
948 sdl->sdl_alen = ETHER_ADDR_LEN;
950 e_addr = LLADDR(sdl);
951 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
952 *llsa = (struct sockaddr *)sdl;
958 * Well, the text isn't quite right, but it's the name
967 /***********************************************************************
968 * This section contains the methods for the Netgraph interface
969 ***********************************************************************/
970 /* It's Ascii-art time!
971 * The ifnet is the first part of the arpcom which must be
972 * the first part of the device's softc.. yuk.
974 * +--------------------------+-----+---------+
975 * | struct ifnet (*ifp) | | |
977 * +--------------------------+ | |
978 * +--|[ac_ng] struct arpcom (*ac) | |
979 * | +--------------------------------+ |
980 * | | struct softc (*ifp->if_softc) (device) |
981 * | +------------------------------------------+
985 * | +----------------------+
986 * | | [private] [flags] |
987 * +------>| struct ng_node |
988 * | [hooks] | ** we only allow one hook
989 * +----------------------+
996 * | [private]|-- *unused*
1001 * called during interface attaching
1004 ngether_init(void *ifpvoid)
1006 struct ifnet *ifp = ifpvoid;
1007 struct arpcom *ac = IFP2AC(ifp);
1008 static int ngether_done_init;
1013 * we have found a node, make sure our 'type' is availabe.
1015 if (ngether_done_init == 0) {
1016 if (ng_newtype(&typestruct)) {
1017 printf("ngether install failed\n");
1020 ngether_done_init = 1;
1022 if (ng_make_node_common(&typestruct, &node) != 0)
1025 node->private = ifp;
1026 sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
1027 ng_name_node(AC2NG(ac), namebuf);
1031 * It is not possible or allowable to create a node of this type.
1032 * If the hardware exists, it will already have created it.
1035 ngether_constructor(node_p *nodep)
1041 * Give our ok for a hook to be added...
1043 * Allow one hook at a time (rawdata).
1044 * It can eiteh rdivert everything or only unclaimed packets.
1047 ngether_newhook(node_p node, hook_p hook, const char *name)
1050 /* check if there is already a hook */
1051 if (LIST_FIRST(&(node->hooks)))
1054 * Check for which mode hook we want.
1056 if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
1057 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
1060 node->flags |= NGEF_DIVERT;
1062 node->flags &= ~NGEF_DIVERT;
1068 * incoming messages.
1069 * Just respond to the generic TEXT_STATUS message
1072 ngether_rcvmsg(node_p node,
1073 struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
1078 ifp = node->private;
1079 switch (msg->header.typecookie) {
1080 case NGM_ETHER_COOKIE:
1083 case NGM_GENERIC_COOKIE:
1084 switch(msg->header.cmd) {
1085 case NGM_TEXT_STATUS: {
1088 int resplen = sizeof(struct ng_mesg) + 512;
1089 MALLOC(*resp, struct ng_mesg *, resplen,
1090 M_NETGRAPH, M_NOWAIT);
1091 if (*resp == NULL) {
1095 bzero(*resp, resplen);
1096 arg = (*resp)->data;
1099 * Put in the throughput information.
1101 pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
1102 ifp->if_ibytes, ifp->if_obytes);
1103 pos += sprintf(arg + pos,
1104 "%ld output errors\n",
1106 pos += sprintf(arg + pos,
1110 (*resp)->header.version = NG_VERSION;
1111 (*resp)->header.arglen = strlen(arg) + 1;
1112 (*resp)->header.token = msg->header.token;
1113 (*resp)->header.typecookie = NGM_ETHER_COOKIE;
1114 (*resp)->header.cmd = msg->header.cmd;
1115 strncpy((*resp)->header.cmdstr, "status",
1128 free(msg, M_NETGRAPH);
1133 * Receive a completed ethernet packet.
1134 * Queue it for output.
1137 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1142 struct ether_header *eh;
1144 ifp = hook->node->private;
1146 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1148 /* drop in the MAC address */
1149 eh = mtod(m, struct ether_header *);
1150 bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6);
1152 * If a simplex interface, and the packet is being sent to our
1153 * Ethernet address or a broadcast address, loopback a copy.
1154 * XXX To make a simplex device behave exactly like a duplex
1155 * device, we should copy in the case of sending to our own
1156 * ethernet address (thus letting the original actually appear
1157 * on the wire). However, we don't do that here for security
1158 * reasons and compatibility with the original behavior.
1160 if (ifp->if_flags & IFF_SIMPLEX) {
1161 if (m->m_flags & M_BCAST) {
1162 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
1164 ng_queue_data(hook, n, meta);
1165 } else if (bcmp(eh->ether_dhost,
1166 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1167 ng_queue_data(hook, m, meta);
1168 return (0); /* XXX */
1173 * Queue message on interface, and start output if interface
1175 * XXX if we lookead at the priority in the meta data we could
1176 * queue high priority items at the head.
1178 if (IF_QFULL(&ifp->if_snd)) {
1179 IF_DROP(&ifp->if_snd);
1183 IF_ENQUEUE(&ifp->if_snd, m);
1184 if ((ifp->if_flags & IFF_OACTIVE) == 0)
1185 (*ifp->if_start)(ifp);
1187 ifp->if_obytes += m->m_pkthdr.len;
1188 if (m->m_flags & M_MCAST)
1193 NG_FREE_DATA(m, meta);
1198 * pass an mbuf out to the connected hook
1199 * More complicated than just an m_prepend, as it tries to save later nodes
1200 * from needing to do lots of m_pullups.
1203 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
1206 node_p node = AC2NG(ac);
1207 struct ether_header *eh2;
1209 if (node && LIST_FIRST(&(node->hooks))) {
1211 * Possibly the header is already on the front,
1213 eh2 = mtod(m, struct ether_header *) - 1;
1216 * This is the case so just move the markers back to
1217 * re-include it. We lucked out.
1218 * This allows us to avoid a yucky m_pullup
1219 * in later nodes if it works.
1221 m->m_len += sizeof(*eh);
1222 m->m_data -= sizeof(*eh);
1223 m->m_pkthdr.len += sizeof(*eh);
1226 * Alternatively there may be room even though
1227 * it is stored somewhere else. If so, copy it in.
1228 * This only safe because we KNOW that this packet has
1229 * just been generated by an ethernet card, so there
1230 * are no aliases to the buffer. (unlike in outgoing
1232 * Nearly all ethernet cards will end up producing mbufs
1233 * that fall into these cases. So we are not optimising
1237 if (m->m_flags & M_EXT) {
1238 room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
1239 if (room > m->m_ext.ext_size) /* garbage */
1240 room = 0; /* fail immediatly */
1242 room = (mtod(m, caddr_t) - m->m_pktdat);
1244 if (room > sizeof (*eh)) {
1245 /* we have room, just copy it and adjust */
1246 m->m_len += sizeof(*eh);
1247 m->m_data -= sizeof(*eh);
1248 m->m_pkthdr.len += sizeof(*eh);
1251 * Doing anything more is likely to get more
1252 * expensive than it's worth..
1253 * it's probable that everything else is in one
1254 * big lump. The next node will do an m_pullup()
1255 * for exactly the amount of data it needs and
1256 * hopefully everything after that will not
1257 * need one. So let's just use M_PREPEND.
1259 M_PREPEND(m, sizeof (*eh), M_DONTWAIT);
1263 bcopy ((caddr_t)eh, mtod(m, struct ether_header *),
1266 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
1273 * do local shutdown processing..
1274 * This node will refuse to go away, unless the hardware says to..
1275 * don't unref the node, or remove our name. just clear our links up.
1278 ngether_rmnode(node_p node)
1281 node->flags &= ~NG_INVALID; /* bounce back to life */
1285 /* already linked */
1287 ngether_connect(hook_p hook)
1289 /* be really amiable and just say "YUP that's OK by me! " */
1294 * notify on hook disconnection (destruction)
1296 * For this type, removal of the last lins no effect. The interface can run
1298 * Since we have no per-hook information, this is rather simple.
1301 ngether_disconnect(hook_p hook)
1303 hook->node->flags &= ~NGEF_DIVERT;
1306 #endif /* NETGRAPH */
1308 /********************************** END *************************************/