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"
41 #include "opt_netgraph.h"
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
48 #include <sys/socket.h>
49 #include <sys/sockio.h>
50 #include <sys/sysctl.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>
59 #if defined(INET) || defined(INET6)
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/if_ether.h>
65 #include <netinet6/nd6.h>
66 #include <netinet6/in6_ifattach.h>
70 #include <netipx/ipx.h>
71 #include <netipx/ipx_if.h>
76 #include <netns/ns_if.h>
78 int ether_outputdebug = 0;
79 int ether_inputdebug = 0;
83 #include <netiso/argo_debug.h>
84 #include <netiso/iso.h>
85 #include <netiso/iso_var.h>
86 #include <netiso/iso_snpac.h>
90 #include <netccitt/dll.h>
91 #include <netccitt/llc_var.h>
94 #if defined(LLC) && defined(CCITT)
95 extern struct ifqueue pkintrq;
99 #include <netatalk/at.h>
100 #include <netatalk/at_var.h>
101 #include <netatalk/at_extern.h>
103 #define llc_snap_org_code llc_un.type_snap.org_code
104 #define llc_snap_ether_type llc_un.type_snap.ether_type
106 extern u_char at_org_code[3];
107 extern u_char aarp_org_code[3];
108 #endif /* NETATALK */
111 #include <net/bridge.h>
116 #include <net/if_vlan_var.h>
117 #endif /* NVLAN > 0 */
119 static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
121 u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
122 #define senderr(e) do { error = (e); goto bad;} while (0)
123 #define IFP2AC(IFP) ((struct arpcom *)IFP)
126 #include <netgraph/ng_ether.h>
127 #include <netgraph/ng_message.h>
128 #include <netgraph/netgraph.h>
130 static void ngether_init(void* ignored);
131 static void ngether_send(struct arpcom *ac,
132 struct ether_header *eh, struct mbuf *m);
133 static ng_constructor_t ngether_constructor;
134 static ng_rcvmsg_t ngether_rcvmsg;
135 static ng_shutdown_t ngether_rmnode;
136 static ng_newhook_t ngether_newhook;
137 static ng_connect_t ngether_connect;
138 static ng_rcvdata_t ngether_rcvdata;
139 static ng_disconnect_t ngether_disconnect;
141 static struct ng_type typestruct = {
156 #define AC2NG(AC) ((node_p)((AC)->ac_ng))
157 #define NGEF_DIVERT NGF_TYPE1 /* all packets sent to netgraph */
158 #endif /* NETGRAPH */
161 * Ethernet output routine.
162 * Encapsulate a packet of type family for the local net.
163 * Use trailer local net encapsulation if enough data in first
164 * packet leaves a multiple of 512 bytes of data in remainder.
165 * Assumes that ifp is actually pointer to arpcom structure.
168 ether_output(ifp, m0, dst, rt0)
169 register struct ifnet *ifp;
171 struct sockaddr *dst;
175 int s, error = 0, hdrcmplt = 0;
176 u_char esrc[6], edst[6];
177 register struct mbuf *m = m0;
178 register struct rtentry *rt;
179 register struct ether_header *eh;
180 int off, len = m->m_pkthdr.len, loop_copy = 0;
181 int hlen; /* link layer header lenght */
182 struct arpcom *ac = IFP2AC(ifp);
184 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
188 if ((rt->rt_flags & RTF_UP) == 0) {
189 rt0 = rt = rtalloc1(dst, 1, 0UL);
193 senderr(EHOSTUNREACH);
195 if (rt->rt_flags & RTF_GATEWAY) {
196 if (rt->rt_gwroute == 0)
198 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
199 rtfree(rt); rt = rt0;
200 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
202 if ((rt = rt->rt_gwroute) == 0)
203 senderr(EHOSTUNREACH);
206 if (rt->rt_flags & RTF_REJECT)
207 if (rt->rt_rmx.rmx_expire == 0 ||
208 time_second < rt->rt_rmx.rmx_expire)
209 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
211 hlen = ETHER_HDR_LEN;
212 switch (dst->sa_family) {
215 if (!arpresolve(ac, rt, m, dst, edst, rt0))
216 return (0); /* if not yet resolved */
217 off = m->m_pkthdr.len - m->m_len;
218 type = htons(ETHERTYPE_IP);
223 if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
224 /* this must be impossible, so we bark */
225 printf("nd6_storelladdr failed\n");
228 off = m->m_pkthdr.len - m->m_len;
229 type = htons(ETHERTYPE_IPV6);
234 type = htons(ETHERTYPE_IPX);
235 bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
236 (caddr_t)edst, sizeof (edst));
242 struct at_ifaddr *aa;
244 if ((aa = at_ifawithnet((struct sockaddr_at *)dst)) == NULL) {
247 if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst))
250 * In the phase 2 case, need to prepend an mbuf for the llc header.
251 * Since we must preserve the value of m, which is passed to us by
252 * value, we m_copy() the first mbuf, and use it for our llc header.
254 if ( aa->aa_flags & AFA_PHASE2 ) {
257 M_PREPEND(m, sizeof(struct llc), M_WAIT);
258 len += sizeof(struct llc);
259 llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
260 llc.llc_control = LLC_UI;
261 bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
262 llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
263 bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
264 type = htons(m->m_pkthdr.len);
265 hlen = sizeof(struct llc) + ETHER_HDR_LEN;
267 type = htons(ETHERTYPE_AT);
276 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
279 case 0x0: /* Novell 802.3 */
280 type = htons( m->m_pkthdr.len);
282 case 0xe0e0: /* Novell 802.2 and Token-Ring */
283 M_PREPEND(m, 3, M_WAIT);
284 type = htons( m->m_pkthdr.len);
285 cp = mtod(m, u_char *);
291 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
292 (caddr_t)edst, sizeof (edst));
294 * XXX if ns_thishost is the same as the node's ethernet
295 * address then just the default code will catch this anyhow.
296 * So I'm not sure if this next clause should be here at all?
299 if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
300 m->m_pkthdr.rcvif = ifp;
301 schednetisr(NETISR_NS);
312 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
313 m->m_flags |= M_BCAST;
321 register struct sockaddr_dl *sdl;
323 if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
324 sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
325 bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
327 iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
328 (char *)edst, &snpalen))
329 goto bad; /* Not Resolved */
330 /* If broadcasting on a simplex interface, loopback a copy */
332 m->m_flags |= (M_BCAST|M_MCAST);
333 M_PREPEND(m, 3, M_DONTWAIT);
336 type = htons(m->m_pkthdr.len);
337 l = mtod(m, struct llc *);
338 l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
339 l->llc_control = LLC_UI;
343 printf("unoutput: sending pkt to: ");
345 printf("%x ", edst[i] & 0xff);
353 register struct sockaddr_dl *sdl =
354 (struct sockaddr_dl *) rt -> rt_gateway;
356 if (sdl && sdl->sdl_family == AF_LINK
357 && sdl->sdl_alen > 0) {
358 bcopy(LLADDR(sdl), (char *)edst, sizeof(edst));
359 } else goto bad; /* Not a link interface ? Funny ... */
362 type = htons(m->m_pkthdr.len);
366 register struct llc *l = mtod(m, struct llc *);
368 printf("ether_output: sending LLC2 pkt to: ");
370 printf("%x ", edst[i] & 0xff);
371 printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
372 type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
373 l->llc_control & 0xff);
376 #endif /* LLC_DEBUG */
380 case pseudo_AF_HDRCMPLT:
382 eh = (struct ether_header *)dst->sa_data;
383 (void)memcpy(esrc, eh->ether_shost, sizeof (esrc));
387 loop_copy = -1; /* if this is for us, don't do it */
388 eh = (struct ether_header *)dst->sa_data;
389 (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
390 type = eh->ether_type;
394 printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
396 senderr(EAFNOSUPPORT);
400 * Add local net header. If no space in first mbuf,
403 M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
406 eh = mtod(m, struct ether_header *);
407 (void)memcpy(&eh->ether_type, &type,
408 sizeof(eh->ether_type));
409 (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
411 (void)memcpy(eh->ether_shost, esrc,
412 sizeof(eh->ether_shost));
414 (void)memcpy(eh->ether_shost, ac->ac_enaddr,
415 sizeof(eh->ether_shost));
418 * If a simplex interface, and the packet is being sent to our
419 * Ethernet address or a broadcast address, loopback a copy.
420 * XXX To make a simplex device behave exactly like a duplex
421 * device, we should copy in the case of sending to our own
422 * ethernet address (thus letting the original actually appear
423 * on the wire). However, we don't do that here for security
424 * reasons and compatibility with the original behavior.
426 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
427 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
428 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
430 (void) if_simloop(ifp, n, dst, hlen);
431 } else if (bcmp(eh->ether_dhost,
432 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
433 (void) if_simloop(ifp, m, dst, hlen);
434 return (0); /* XXX */
439 struct mbuf *m0 = m ;
441 if (m->m_pkthdr.rcvif)
442 m->m_pkthdr.rcvif = NULL ;
443 ifp = bridge_dst_lookup(m);
444 bdg_forward(&m0, ifp);
452 * Queue message on interface, and start output if interface
455 if (IF_QFULL(&ifp->if_snd)) {
456 IF_DROP(&ifp->if_snd);
460 IF_ENQUEUE(&ifp->if_snd, m);
461 if ((ifp->if_flags & IFF_OACTIVE) == 0)
462 (*ifp->if_start)(ifp);
464 ifp->if_obytes += len + sizeof (struct ether_header);
465 if (m->m_flags & M_MCAST)
476 * Process a received Ethernet packet;
477 * the packet is in the mbuf chain m without
478 * the ether header, which is provided separately.
481 ether_input(ifp, eh, m)
483 register struct ether_header *eh;
486 register struct ifqueue *inq;
489 #if defined (ISO) || defined (LLC) || defined(NETATALK)
490 register struct llc *l;
493 if ((ifp->if_flags & IFF_UP) == 0) {
497 ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
498 if (eh->ether_dhost[0] & 1) {
499 if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
500 sizeof(etherbroadcastaddr)) == 0)
501 m->m_flags |= M_BCAST;
503 m->m_flags |= M_MCAST;
505 if (m->m_flags & (M_BCAST|M_MCAST))
508 ether_type = ntohs(eh->ether_type);
512 struct arpcom *ac = IFP2AC(ifp);
513 if (AC2NG(ac) && (AC2NG(ac)->flags & NGEF_DIVERT)) {
514 ngether_send(ac, eh, m);
518 #endif /* NETGRAPH */
521 if (ether_type == vlan_proto) {
522 if (vlan_input(eh, m) < 0)
523 ifp->if_data.ifi_noproto++;
526 #endif /* NVLAN > 0 */
528 switch (ether_type) {
531 if (ipflow_fastforward(m))
533 schednetisr(NETISR_IP);
538 schednetisr(NETISR_ARP);
544 schednetisr(NETISR_IPX);
550 schednetisr(NETISR_IPV6);
555 case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
556 schednetisr(NETISR_NS);
563 schednetisr(NETISR_ATALK);
567 /* probably this should be done with a NETISR as well */
568 aarpinput(IFP2AC(ifp), m); /* XXX */
573 checksum = mtod(m, ushort *);
575 if ((ether_type <= ETHERMTU) &&
576 ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
577 if(*checksum == 0xE0E0) {
578 m->m_pkthdr.len -= 3;
582 schednetisr(NETISR_NS);
587 #if defined (ISO) || defined (LLC) || defined(NETATALK)
588 if (ether_type > ETHERMTU)
590 l = mtod(m, struct llc *);
591 switch (l->llc_dsap) {
594 switch (l->llc_control) {
596 if (l->llc_ssap != LLC_SNAP_LSAP)
599 if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
600 sizeof(at_org_code)) == 0 &&
601 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
603 m_adj( m, sizeof( struct llc ));
604 schednetisr(NETISR_ATALK);
608 if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
609 sizeof(aarp_org_code)) == 0 &&
610 ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
611 m_adj( m, sizeof( struct llc ));
612 aarpinput(IFP2AC(ifp), m); /* XXX */
623 switch (l->llc_control) {
625 /* LLC_UI_P forbidden in class 1 service */
626 if ((l->llc_dsap == LLC_ISO_LSAP) &&
627 (l->llc_ssap == LLC_ISO_LSAP)) {
629 if (m->m_pkthdr.len > ether_type)
630 m_adj(m, ether_type - m->m_pkthdr.len);
631 m->m_data += 3; /* XXX */
632 m->m_len -= 3; /* XXX */
633 m->m_pkthdr.len -= 3; /* XXX */
634 M_PREPEND(m, sizeof *eh, M_DONTWAIT);
637 *mtod(m, struct ether_header *) = *eh;
639 printf("clnp packet");
641 schednetisr(NETISR_ISO);
654 l->llc_dsap = l->llc_ssap = 0;
655 /* Fall through to */
660 register struct ether_header *eh2;
662 u_char c = l->llc_dsap;
664 l->llc_dsap = l->llc_ssap;
666 if (m->m_flags & (M_BCAST | M_MCAST))
667 bcopy((caddr_t)ac->ac_enaddr,
668 (caddr_t)eh->ether_dhost, 6);
669 sa.sa_family = AF_UNSPEC;
670 sa.sa_len = sizeof(sa);
671 eh2 = (struct ether_header *)sa.sa_data;
672 for (i = 0; i < 6; i++) {
673 eh2->ether_shost[i] = c = eh->ether_dhost[i];
674 eh2->ether_dhost[i] =
675 eh->ether_dhost[i] = eh->ether_shost[i];
676 eh->ether_shost[i] = c;
678 ifp->if_output(ifp, m, &sa, NULL);
690 if (m->m_pkthdr.len > ether_type)
691 m_adj(m, ether_type - m->m_pkthdr.len);
692 M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
695 if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
696 eh->ether_dhost, LLC_X25_LSAP, 6,
697 mtod(m, struct sdl_hdr *)))
698 panic("ETHER cons addr failure");
699 mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
701 printf("llc packet\n");
702 #endif /* LLC_DEBUG */
703 schednetisr(NETISR_CCITT);
711 ngether_send(IFP2AC(ifp), eh, m);
714 #endif /* NETGRAPH */
717 #else /* ISO || LLC || NETATALK */
719 ngether_send(IFP2AC(ifp), eh, m);
722 #endif /* NETGRAPH */
724 #endif /* ISO || LLC || NETATALK */
737 * Perform common duties while attaching to interface list
741 register struct ifnet *ifp;
743 register struct ifaddr *ifa;
744 register struct sockaddr_dl *sdl;
746 ifp->if_type = IFT_ETHER;
749 ifp->if_mtu = ETHERMTU;
750 ifp->if_resolvemulti = ether_resolvemulti;
751 if (ifp->if_baudrate == 0)
752 ifp->if_baudrate = 10000000;
753 ifa = ifnet_addrs[ifp->if_index - 1];
755 printf("ether_ifattach: no lladdr!\n");
758 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
759 sdl->sdl_type = IFT_ETHER;
760 sdl->sdl_alen = ifp->if_addrlen;
761 bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
764 #endif /* NETGRAPH */
766 in6_ifattach_getifid(ifp);
770 SYSCTL_DECL(_net_link);
771 SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
774 ether_ioctl(ifp, command, data)
779 struct ifaddr *ifa = (struct ifaddr *) data;
780 struct ifreq *ifr = (struct ifreq *) data;
785 ifp->if_flags |= IFF_UP;
787 switch (ifa->ifa_addr->sa_family) {
790 ifp->if_init(ifp->if_softc); /* before arpwhohas */
791 arp_ifinit(IFP2AC(ifp), ifa);
796 * XXX - This code is probably wrong
800 register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
801 struct arpcom *ac = IFP2AC(ifp);
803 if (ipx_nullhost(*ina))
808 bcopy((caddr_t) ina->x_host.c_host,
809 (caddr_t) ac->ac_enaddr,
810 sizeof(ac->ac_enaddr));
816 ifp->if_init(ifp->if_softc);
822 * XXX - This code is probably wrong
826 register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
827 struct arpcom *ac = IFP2AC(ifp);
829 if (ns_nullhost(*ina))
831 *(union ns_host *) (ac->ac_enaddr);
833 bcopy((caddr_t) ina->x_host.c_host,
834 (caddr_t) ac->ac_enaddr,
835 sizeof(ac->ac_enaddr));
841 ifp->if_init(ifp->if_softc);
846 ifp->if_init(ifp->if_softc);
855 sa = (struct sockaddr *) & ifr->ifr_data;
856 bcopy(IFP2AC(ifp)->ac_enaddr,
857 (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
863 * Set the interface MTU.
865 if (ifr->ifr_mtu > ETHERMTU) {
868 ifp->if_mtu = ifr->ifr_mtu;
876 ether_resolvemulti(ifp, llsa, sa)
878 struct sockaddr **llsa;
881 struct sockaddr_dl *sdl;
882 struct sockaddr_in *sin;
884 struct sockaddr_in6 *sin6;
888 switch(sa->sa_family) {
891 * No mapping needed. Just check that it's a valid MC address.
893 sdl = (struct sockaddr_dl *)sa;
894 e_addr = LLADDR(sdl);
895 if ((e_addr[0] & 1) != 1)
896 return EADDRNOTAVAIL;
902 sin = (struct sockaddr_in *)sa;
903 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
904 return EADDRNOTAVAIL;
905 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
907 sdl->sdl_len = sizeof *sdl;
908 sdl->sdl_family = AF_LINK;
909 sdl->sdl_index = ifp->if_index;
910 sdl->sdl_type = IFT_ETHER;
912 sdl->sdl_alen = ETHER_ADDR_LEN;
914 e_addr = LLADDR(sdl);
915 ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr);
916 *llsa = (struct sockaddr *)sdl;
921 sin6 = (struct sockaddr_in6 *)sa;
922 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
923 return EADDRNOTAVAIL;
924 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
926 sdl->sdl_len = sizeof *sdl;
927 sdl->sdl_family = AF_LINK;
928 sdl->sdl_index = ifp->if_index;
929 sdl->sdl_type = IFT_ETHER;
931 sdl->sdl_alen = ETHER_ADDR_LEN;
933 e_addr = LLADDR(sdl);
934 ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
935 *llsa = (struct sockaddr *)sdl;
941 * Well, the text isn't quite right, but it's the name
950 /***********************************************************************
951 * This section contains the methods for the Netgraph interface
952 ***********************************************************************/
953 /* It's Ascii-art time!
954 * The ifnet is the first part of the arpcom which must be
955 * the first part of the device's softc.. yuk.
957 * +--------------------------+-----+---------+
958 * | struct ifnet (*ifp) | | |
960 * +--------------------------+ | |
961 * +--|[ac_ng] struct arpcom (*ac) | |
962 * | +--------------------------------+ |
963 * | | struct softc (*ifp->if_softc) (device) |
964 * | +------------------------------------------+
968 * | +----------------------+
969 * | | [private] [flags] |
970 * +------>| struct ng_node |
971 * | [hooks] | ** we only allow one hook
972 * +----------------------+
979 * | [private]|-- *unused*
984 * called during interface attaching
987 ngether_init(void *ifpvoid)
989 struct ifnet *ifp = ifpvoid;
990 struct arpcom *ac = IFP2AC(ifp);
991 static int ngether_done_init;
996 * we have found a node, make sure our 'type' is availabe.
998 if (ngether_done_init == 0) {
999 if (ng_newtype(&typestruct)) {
1000 printf("ngether install failed\n");
1003 ngether_done_init = 1;
1005 if (ng_make_node_common(&typestruct, &node) != 0)
1008 node->private = ifp;
1009 sprintf(namebuf, "%s%d", ifp->if_name, ifp->if_unit);
1010 ng_name_node(AC2NG(ac), namebuf);
1014 * It is not possible or allowable to create a node of this type.
1015 * If the hardware exists, it will already have created it.
1018 ngether_constructor(node_p *nodep)
1024 * Give our ok for a hook to be added...
1026 * Allow one hook at a time (rawdata).
1027 * It can eiteh rdivert everything or only unclaimed packets.
1030 ngether_newhook(node_p node, hook_p hook, const char *name)
1033 /* check if there is already a hook */
1034 if (LIST_FIRST(&(node->hooks)))
1037 * Check for which mode hook we want.
1039 if (strcmp(name, NG_ETHER_HOOK_ORPHAN) != 0) {
1040 if (strcmp(name, NG_ETHER_HOOK_DIVERT) != 0) {
1043 node->flags |= NGEF_DIVERT;
1045 node->flags &= ~NGEF_DIVERT;
1051 * incoming messages.
1052 * Just respond to the generic TEXT_STATUS message
1055 ngether_rcvmsg(node_p node,
1056 struct ng_mesg *msg, const char *retaddr, struct ng_mesg **resp)
1061 ifp = node->private;
1062 switch (msg->header.typecookie) {
1063 case NGM_ETHER_COOKIE:
1066 case NGM_GENERIC_COOKIE:
1067 switch(msg->header.cmd) {
1068 case NGM_TEXT_STATUS: {
1071 int resplen = sizeof(struct ng_mesg) + 512;
1072 MALLOC(*resp, struct ng_mesg *, resplen,
1073 M_NETGRAPH, M_NOWAIT);
1074 if (*resp == NULL) {
1078 bzero(*resp, resplen);
1079 arg = (*resp)->data;
1082 * Put in the throughput information.
1084 pos = sprintf(arg, "%ld bytes in, %ld bytes out\n",
1085 ifp->if_ibytes, ifp->if_obytes);
1086 pos += sprintf(arg + pos,
1087 "%ld output errors\n",
1089 pos += sprintf(arg + pos,
1093 (*resp)->header.version = NG_VERSION;
1094 (*resp)->header.arglen = strlen(arg) + 1;
1095 (*resp)->header.token = msg->header.token;
1096 (*resp)->header.typecookie = NGM_ETHER_COOKIE;
1097 (*resp)->header.cmd = msg->header.cmd;
1098 strncpy((*resp)->header.cmdstr, "status",
1111 free(msg, M_NETGRAPH);
1116 * Receive a completed ethernet packet.
1117 * Queue it for output.
1120 ngether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
1125 struct ether_header *eh;
1127 ifp = hook->node->private;
1129 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
1131 /* drop in the MAC address */
1132 eh = mtod(m, struct ether_header *);
1133 bcopy(IFP2AC(ifp)->ac_enaddr, eh->ether_shost, 6);
1135 * If a simplex interface, and the packet is being sent to our
1136 * Ethernet address or a broadcast address, loopback a copy.
1137 * XXX To make a simplex device behave exactly like a duplex
1138 * device, we should copy in the case of sending to our own
1139 * ethernet address (thus letting the original actually appear
1140 * on the wire). However, we don't do that here for security
1141 * reasons and compatibility with the original behavior.
1143 if (ifp->if_flags & IFF_SIMPLEX) {
1144 if (m->m_flags & M_BCAST) {
1145 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
1147 ng_queue_data(hook, n, meta);
1148 } else if (bcmp(eh->ether_dhost,
1149 eh->ether_shost, ETHER_ADDR_LEN) == 0) {
1150 ng_queue_data(hook, m, meta);
1151 return (0); /* XXX */
1156 * Queue message on interface, and start output if interface
1158 * XXX if we lookead at the priority in the meta data we could
1159 * queue high priority items at the head.
1161 if (IF_QFULL(&ifp->if_snd)) {
1162 IF_DROP(&ifp->if_snd);
1166 IF_ENQUEUE(&ifp->if_snd, m);
1167 if ((ifp->if_flags & IFF_OACTIVE) == 0)
1168 (*ifp->if_start)(ifp);
1170 ifp->if_obytes += m->m_pkthdr.len;
1171 if (m->m_flags & M_MCAST)
1176 NG_FREE_DATA(m, meta);
1181 * pass an mbuf out to the connected hook
1182 * More complicated than just an m_prepend, as it tries to save later nodes
1183 * from needing to do lots of m_pullups.
1186 ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
1189 node_p node = AC2NG(ac);
1190 struct ether_header *eh2;
1192 if (node && LIST_FIRST(&(node->hooks))) {
1194 * Possibly the header is already on the front,
1196 eh2 = mtod(m, struct ether_header *) - 1;
1199 * This is the case so just move the markers back to
1200 * re-include it. We lucked out.
1201 * This allows us to avoid a yucky m_pullup
1202 * in later nodes if it works.
1204 m->m_len += sizeof(*eh);
1205 m->m_data -= sizeof(*eh);
1206 m->m_pkthdr.len += sizeof(*eh);
1209 * Alternatively there may be room even though
1210 * it is stored somewhere else. If so, copy it in.
1211 * This only safe because we KNOW that this packet has
1212 * just been generated by an ethernet card, so there
1213 * are no aliases to the buffer. (unlike in outgoing
1215 * Nearly all ethernet cards will end up producing mbufs
1216 * that fall into these cases. So we are not optimising
1220 if (m->m_flags & M_EXT) {
1221 room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
1222 if (room > m->m_ext.ext_size) /* garbage */
1223 room = 0; /* fail immediatly */
1225 room = (mtod(m, caddr_t) - m->m_pktdat);
1227 if (room > sizeof (*eh)) {
1228 /* we have room, just copy it and adjust */
1229 m->m_len += sizeof(*eh);
1230 m->m_data -= sizeof(*eh);
1231 m->m_pkthdr.len += sizeof(*eh);
1234 * Doing anything more is likely to get more
1235 * expensive than it's worth..
1236 * it's probable that everything else is in one
1237 * big lump. The next node will do an m_pullup()
1238 * for exactly the amount of data it needs and
1239 * hopefully everything after that will not
1240 * need one. So let's just use M_PREPEND.
1242 M_PREPEND(m, sizeof (*eh), M_DONTWAIT);
1246 bcopy ((caddr_t)eh, mtod(m, struct ether_header *),
1249 ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL);
1256 * do local shutdown processing..
1257 * This node will refuse to go away, unless the hardware says to..
1258 * don't unref the node, or remove our name. just clear our links up.
1261 ngether_rmnode(node_p node)
1264 node->flags &= ~NG_INVALID; /* bounce back to life */
1268 /* already linked */
1270 ngether_connect(hook_p hook)
1272 /* be really amiable and just say "YUP that's OK by me! " */
1277 * notify on hook disconnection (destruction)
1279 * For this type, removal of the last lins no effect. The interface can run
1281 * Since we have no per-hook information, this is rather simple.
1284 ngether_disconnect(hook_p hook)
1286 hook->node->flags &= ~NGEF_DIVERT;
1289 #endif /* NETGRAPH */
1291 /********************************** END *************************************/