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(ðer_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(ðer_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 --- |