Deleted Added
full compact
if_ethersubr.c (234946) if_ethersubr.c (240099)
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

--- 13 unchanged lines hidden (view full) ---

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
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

--- 13 unchanged lines hidden (view full) ---

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93
30 * $FreeBSD: head/sys/net/if_ethersubr.c 234946 2012-05-03 08:56:43Z melifaro $
30 * $FreeBSD: head/sys/net/if_ethersubr.c 240099 2012-09-04 19:43:26Z melifaro $
31 */
32
33#include "opt_atalk.h"
34#include "opt_inet.h"
35#include "opt_inet6.h"
36#include "opt_ipx.h"
37#include "opt_netgraph.h"
38#include "opt_mbuf_profiling.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/malloc.h>
45#include <sys/module.h>
46#include <sys/mbuf.h>
47#include <sys/random.h>
31 */
32
33#include "opt_atalk.h"
34#include "opt_inet.h"
35#include "opt_inet6.h"
36#include "opt_ipx.h"
37#include "opt_netgraph.h"
38#include "opt_mbuf_profiling.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/lock.h>
44#include <sys/malloc.h>
45#include <sys/module.h>
46#include <sys/mbuf.h>
47#include <sys/random.h>
48#include <sys/rwlock.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/if_arp.h>
55#include <net/netisr.h>
56#include <net/route.h>
57#include <net/if_llc.h>
58#include <net/if_dl.h>
59#include <net/if_types.h>
60#include <net/bpf.h>
61#include <net/ethernet.h>
62#include <net/if_bridgevar.h>
63#include <net/if_vlan_var.h>
64#include <net/if_llatbl.h>
65#include <net/pf_mtag.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/if_arp.h>
54#include <net/netisr.h>
55#include <net/route.h>
56#include <net/if_llc.h>
57#include <net/if_dl.h>
58#include <net/if_types.h>
59#include <net/bpf.h>
60#include <net/ethernet.h>
61#include <net/if_bridgevar.h>
62#include <net/if_vlan_var.h>
63#include <net/if_llatbl.h>
64#include <net/pf_mtag.h>
65#include <net/pfil.h>
66#include <net/vnet.h>
67
68#if defined(INET) || defined(INET6)
69#include <netinet/in.h>
70#include <netinet/in_var.h>
71#include <netinet/if_ether.h>
72#include <netinet/ip_carp.h>
73#include <netinet/ip_var.h>
66#include <net/vnet.h>
67
68#if defined(INET) || defined(INET6)
69#include <netinet/in.h>
70#include <netinet/in_var.h>
71#include <netinet/if_ether.h>
72#include <netinet/ip_carp.h>
73#include <netinet/ip_var.h>
74#include <netinet/ip_fw.h>
75#include <netinet/ipfw/ip_fw_private.h>
76#endif
77#ifdef INET6
78#include <netinet6/nd6.h>
79#endif
80
81#ifdef IPX
82#include <netipx/ipx.h>
83#include <netipx/ipx_if.h>

--- 17 unchanged lines hidden (view full) ---

101
102#include <security/mac/mac_framework.h>
103
104#ifdef CTASSERT
105CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2);
106CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN);
107#endif
108
74#endif
75#ifdef INET6
76#include <netinet6/nd6.h>
77#endif
78
79#ifdef IPX
80#include <netipx/ipx.h>
81#include <netipx/ipx_if.h>

--- 17 unchanged lines hidden (view full) ---

99
100#include <security/mac/mac_framework.h>
101
102#ifdef CTASSERT
103CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2);
104CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN);
105#endif
106
107VNET_DEFINE(struct pfil_head, link_pfil_hook); /* Packet filter hooks */
108
109/* netgraph node hooks for ng_ether(4) */
110void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
111void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
112int (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
113void (*ng_ether_attach_p)(struct ifnet *ifp);
114void (*ng_ether_detach_p)(struct ifnet *ifp);
115
116void (*vlan_input_p)(struct ifnet *, struct mbuf *);

--- 19 unchanged lines hidden (view full) ---

136/* XXX: should be in an arp support file, not here */
137static MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
138
139#define ETHER_IS_BROADCAST(addr) \
140 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
141
142#define senderr(e) do { error = (e); goto bad;} while (0)
143
109/* netgraph node hooks for ng_ether(4) */
110void (*ng_ether_input_p)(struct ifnet *ifp, struct mbuf **mp);
111void (*ng_ether_input_orphan_p)(struct ifnet *ifp, struct mbuf *m);
112int (*ng_ether_output_p)(struct ifnet *ifp, struct mbuf **mp);
113void (*ng_ether_attach_p)(struct ifnet *ifp);
114void (*ng_ether_detach_p)(struct ifnet *ifp);
115
116void (*vlan_input_p)(struct ifnet *, struct mbuf *);

--- 19 unchanged lines hidden (view full) ---

136/* XXX: should be in an arp support file, not here */
137static MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
138
139#define ETHER_IS_BROADCAST(addr) \
140 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0)
141
142#define senderr(e) do { error = (e); goto bad;} while (0)
143
144#if defined(INET) || defined(INET6)
145int
146ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared);
147static VNET_DEFINE(int, ether_ipfw);
148#define V_ether_ipfw VNET(ether_ipfw)
149#endif
150
151
152/*
153 * Ethernet output routine.
154 * Encapsulate a packet of type family for the local net.
155 * Use trailer local net encapsulation if enough data in first
156 * packet leaves a multiple of 512 bytes of data in remainder.
157 */
158int
159ether_output(struct ifnet *ifp, struct mbuf *m,

--- 262 unchanged lines hidden (view full) ---

422 * Ethernet link layer output routine to send a raw frame to the device.
423 *
424 * This assumes that the 14 byte Ethernet header is present and contiguous
425 * in the first mbuf (if BRIDGE'ing).
426 */
427int
428ether_output_frame(struct ifnet *ifp, struct mbuf *m)
429{
144/*
145 * Ethernet output routine.
146 * Encapsulate a packet of type family for the local net.
147 * Use trailer local net encapsulation if enough data in first
148 * packet leaves a multiple of 512 bytes of data in remainder.
149 */
150int
151ether_output(struct ifnet *ifp, struct mbuf *m,

--- 262 unchanged lines hidden (view full) ---

414 * Ethernet link layer output routine to send a raw frame to the device.
415 *
416 * This assumes that the 14 byte Ethernet header is present and contiguous
417 * in the first mbuf (if BRIDGE'ing).
418 */
419int
420ether_output_frame(struct ifnet *ifp, struct mbuf *m)
421{
430#if defined(INET) || defined(INET6)
422 int i;
431
423
432 if (V_ip_fw_chk_ptr && V_ether_ipfw != 0) {
433 if (ether_ipfw_chk(&m, ifp, 0) == 0) {
434 if (m) {
435 m_freem(m);
436 return EACCES; /* pkt dropped */
437 } else
438 return 0; /* consumed e.g. in a pipe */
439 }
424 if (PFIL_HOOKED(&V_link_pfil_hook)) {
425 i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_OUT, NULL);
426
427 if (i != 0)
428 return (EACCES);
429
430 if (m == NULL)
431 return (0);
440 }
432 }
441#endif
442
443 /*
444 * Queue message on interface, update output statistics if
445 * successful, and start output if interface not yet active.
446 */
447 return ((ifp->if_transmit)(ifp, m));
448}
449
450#if defined(INET) || defined(INET6)
433
434 /*
435 * Queue message on interface, update output statistics if
436 * successful, and start output if interface not yet active.
437 */
438 return ((ifp->if_transmit)(ifp, m));
439}
440
441#if defined(INET) || defined(INET6)
451/*
452 * ipfw processing for ethernet packets (in and out).
453 * The second parameter is NULL from ether_demux, and ifp from
454 * ether_output_frame.
455 */
456int
457ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared)
458{
459 struct ether_header *eh;
460 struct ether_header save_eh;
461 struct mbuf *m;
462 int i;
463 struct ip_fw_args args;
464 struct m_tag *mtag;
465
466 /* fetch start point from rule, if any */
467 mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
468 if (mtag == NULL) {
469 args.rule.slot = 0;
470 } else {
471 /* dummynet packet, already partially processed */
472 struct ipfw_rule_ref *r;
473
474 /* XXX can we free it after use ? */
475 mtag->m_tag_id = PACKET_TAG_NONE;
476 r = (struct ipfw_rule_ref *)(mtag + 1);
477 if (r->info & IPFW_ONEPASS)
478 return (1);
479 args.rule = *r;
480 }
481
482 /*
483 * I need some amt of data to be contiguous, and in case others need
484 * the packet (shared==1) also better be in the first mbuf.
485 */
486 m = *m0;
487 i = min( m->m_pkthdr.len, max_protohdr);
488 if ( shared || m->m_len < i) {
489 m = m_pullup(m, i);
490 if (m == NULL) {
491 *m0 = m;
492 return 0;
493 }
494 }
495 eh = mtod(m, struct ether_header *);
496 save_eh = *eh; /* save copy for restore below */
497 m_adj(m, ETHER_HDR_LEN); /* strip ethernet header */
498
499 args.m = m; /* the packet we are looking at */
500 args.oif = dst; /* destination, if any */
501 args.next_hop = NULL; /* we do not support forward yet */
502 args.next_hop6 = NULL; /* we do not support forward yet */
503 args.eh = &save_eh; /* MAC header for bridged/MAC packets */
504 args.inp = NULL; /* used by ipfw uid/gid/jail rules */
505 i = V_ip_fw_chk_ptr(&args);
506 m = args.m;
507 if (m != NULL) {
508 /*
509 * Restore Ethernet header, as needed, in case the
510 * mbuf chain was replaced by ipfw.
511 */
512 M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT);
513 if (m == NULL) {
514 *m0 = m;
515 return 0;
516 }
517 if (eh != mtod(m, struct ether_header *))
518 bcopy(&save_eh, mtod(m, struct ether_header *),
519 ETHER_HDR_LEN);
520 }
521 *m0 = m;
522
523 if (i == IP_FW_DENY) /* drop */
524 return 0;
525
526 KASSERT(m != NULL, ("ether_ipfw_chk: m is NULL"));
527
528 if (i == IP_FW_PASS) /* a PASS rule. */
529 return 1;
530
531 if (ip_dn_io_ptr && (i == IP_FW_DUMMYNET)) {
532 int dir;
533 /*
534 * Pass the pkt to dummynet, which consumes it.
535 * If shared, make a copy and keep the original.
536 */
537 if (shared) {
538 m = m_copypacket(m, M_DONTWAIT);
539 if (m == NULL)
540 return 0;
541 } else {
542 /*
543 * Pass the original to dummynet and
544 * nothing back to the caller
545 */
546 *m0 = NULL ;
547 }
548 dir = PROTO_LAYER2 | (dst ? DIR_OUT : DIR_IN);
549 ip_dn_io_ptr(&m, dir, &args);
550 return 0;
551 }
552 /*
553 * XXX at some point add support for divert/forward actions.
554 * If none of the above matches, we have to drop the pkt.
555 */
556 return 0;
557}
558#endif
559
560/*
561 * Process a received Ethernet packet; the packet is in the
562 * mbuf chain m with the ethernet header at the front.
563 */
564static void
565ether_input_internal(struct ifnet *ifp, struct mbuf *m)

--- 217 unchanged lines hidden (view full) ---

783ether_init(__unused void *arg)
784{
785
786 netisr_register(&ether_nh);
787}
788SYSINIT(ether, SI_SUB_INIT_IF, SI_ORDER_ANY, ether_init, NULL);
789
790static void
442#endif
443
444/*
445 * Process a received Ethernet packet; the packet is in the
446 * mbuf chain m with the ethernet header at the front.
447 */
448static void
449ether_input_internal(struct ifnet *ifp, struct mbuf *m)

--- 217 unchanged lines hidden (view full) ---

667ether_init(__unused void *arg)
668{
669
670 netisr_register(&ether_nh);
671}
672SYSINIT(ether, SI_SUB_INIT_IF, SI_ORDER_ANY, ether_init, NULL);
673
674static void
675vnet_ether_init(__unused void *arg)
676{
677 int i;
678
679 /* Initialize packet filter hooks. */
680 V_link_pfil_hook.ph_type = PFIL_TYPE_AF;
681 V_link_pfil_hook.ph_af = AF_LINK;
682 if ((i = pfil_head_register(&V_link_pfil_hook)) != 0)
683 printf("%s: WARNING: unable to register pfil link hook, "
684 "error %d\n", __func__, i);
685}
686VNET_SYSINIT(vnet_ether_init, SI_SUB_PROTO_IF, SI_ORDER_ANY,
687 vnet_ether_init, NULL);
688
689static void
690vnet_ether_destroy(__unused void *arg)
691{
692 int i;
693
694 if ((i = pfil_head_unregister(&V_link_pfil_hook)) != 0)
695 printf("%s: WARNING: unable to unregister pfil link hook, "
696 "error %d\n", __func__, i);
697}
698VNET_SYSUNINIT(vnet_ether_uninit, SI_SUB_PROTO_IF, SI_ORDER_ANY,
699 vnet_ether_destroy, NULL);
700
701
702
703static void
791ether_input(struct ifnet *ifp, struct mbuf *m)
792{
793
794 /*
795 * We will rely on rcvif being set properly in the deferred context,
796 * so assert it is correct here.
797 */
798 KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch", __func__));
799
800 netisr_dispatch(NETISR_ETHER, m);
801}
802
803/*
804 * Upper layer processing for a received Ethernet packet.
805 */
806void
807ether_demux(struct ifnet *ifp, struct mbuf *m)
808{
809 struct ether_header *eh;
704ether_input(struct ifnet *ifp, struct mbuf *m)
705{
706
707 /*
708 * We will rely on rcvif being set properly in the deferred context,
709 * so assert it is correct here.
710 */
711 KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch", __func__));
712
713 netisr_dispatch(NETISR_ETHER, m);
714}
715
716/*
717 * Upper layer processing for a received Ethernet packet.
718 */
719void
720ether_demux(struct ifnet *ifp, struct mbuf *m)
721{
722 struct ether_header *eh;
810 int isr;
723 int i, isr;
811 u_short ether_type;
812#if defined(NETATALK)
813 struct llc *l;
814#endif
815
816 KASSERT(ifp != NULL, ("%s: NULL interface pointer", __func__));
817
724 u_short ether_type;
725#if defined(NETATALK)
726 struct llc *l;
727#endif
728
729 KASSERT(ifp != NULL, ("%s: NULL interface pointer", __func__));
730
818#if defined(INET) || defined(INET6)
819 /*
820 * Allow dummynet and/or ipfw to claim the frame.
821 * Do not do this for PROMISC frames in case we are re-entered.
822 */
823 if (V_ip_fw_chk_ptr && V_ether_ipfw != 0 && !(m->m_flags & M_PROMISC)) {
824 if (ether_ipfw_chk(&m, NULL, 0) == 0) {
825 if (m)
826 m_freem(m); /* dropped; free mbuf chain */
827 return; /* consumed */
828 }
731 /* Do not grab PROMISC frames in case we are re-entered. */
732 if (PFIL_HOOKED(&V_link_pfil_hook) && !(m->m_flags & M_PROMISC)) {
733 i = pfil_run_hooks(&V_link_pfil_hook, &m, ifp, PFIL_IN, NULL);
734
735 if (i != 0 || m == NULL)
736 return;
829 }
737 }
830#endif
738
831 eh = mtod(m, struct ether_header *);
832 ether_type = ntohs(eh->ether_type);
833
834 /*
835 * If this frame has a VLAN tag other than 0, call vlan_input()
836 * if its module is loaded. Otherwise, drop.
837 */
838 if ((m->m_flags & M_VLANTAG) &&

--- 212 unchanged lines hidden (view full) ---

1051 (*ng_ether_attach_p)(ifp);
1052 CURVNET_RESTORE();
1053 }
1054}
1055#endif
1056
1057SYSCTL_DECL(_net_link);
1058SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
739 eh = mtod(m, struct ether_header *);
740 ether_type = ntohs(eh->ether_type);
741
742 /*
743 * If this frame has a VLAN tag other than 0, call vlan_input()
744 * if its module is loaded. Otherwise, drop.
745 */
746 if ((m->m_flags & M_VLANTAG) &&

--- 212 unchanged lines hidden (view full) ---

959 (*ng_ether_attach_p)(ifp);
960 CURVNET_RESTORE();
961 }
962}
963#endif
964
965SYSCTL_DECL(_net_link);
966SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
1059#if defined(INET) || defined(INET6)
1060SYSCTL_VNET_INT(_net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW,
1061 &VNET_NAME(ether_ipfw), 0, "Pass ether pkts through firewall");
1062#endif
1063
1064#if 0
1065/*
1066 * This is for reference. We have a table-driven version
1067 * of the little-endian crc32 generator, which is faster
1068 * than the double-loop.
1069 */
1070uint32_t

--- 338 unchanged lines hidden ---
967
968#if 0
969/*
970 * This is for reference. We have a table-driven version
971 * of the little-endian crc32 generator, which is faster
972 * than the double-loop.
973 */
974uint32_t

--- 338 unchanged lines hidden ---