16a03354eSMatthew Dillon /* 24408d548SBill Yuan * Copyright (c) 2014 - 2018 The DragonFly Project. All rights reserved. 36a03354eSMatthew Dillon * 46a03354eSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 59187b359SBill Yuan * by Bill Yuan <bycn82@dragonflybsd.org> 66a03354eSMatthew Dillon * 76a03354eSMatthew Dillon * Redistribution and use in source and binary forms, with or without 86a03354eSMatthew Dillon * modification, are permitted provided that the following conditions 96a03354eSMatthew Dillon * are met: 106a03354eSMatthew Dillon * 116a03354eSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 126a03354eSMatthew Dillon * notice, this list of conditions and the following disclaimer. 136a03354eSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 146a03354eSMatthew Dillon * notice, this list of conditions and the following disclaimer in 156a03354eSMatthew Dillon * the documentation and/or other materials provided with the 166a03354eSMatthew Dillon * distribution. 176a03354eSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 186a03354eSMatthew Dillon * contributors may be used to endorse or promote products derived 196a03354eSMatthew Dillon * from this software without specific, prior written permission. 206a03354eSMatthew Dillon * 216a03354eSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 226a03354eSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 236a03354eSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 246a03354eSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 256a03354eSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 266a03354eSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 276a03354eSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 286a03354eSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 296a03354eSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 306a03354eSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 316a03354eSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 326a03354eSMatthew Dillon * SUCH DAMAGE. 336a03354eSMatthew Dillon */ 346a03354eSMatthew Dillon 354408d548SBill Yuan #include "opt_ipfw.h" 364408d548SBill Yuan #include "opt_inet.h" 374408d548SBill Yuan #ifndef INET 384408d548SBill Yuan #error IPFIREWALL3 requires INET. 394408d548SBill Yuan #endif /* INET */ 404408d548SBill Yuan 416a03354eSMatthew Dillon #include <sys/param.h> 426a03354eSMatthew Dillon #include <sys/kernel.h> 436a03354eSMatthew Dillon #include <sys/malloc.h> 446a03354eSMatthew Dillon #include <sys/mbuf.h> 456a03354eSMatthew Dillon #include <sys/socketvar.h> 466a03354eSMatthew Dillon #include <sys/sysctl.h> 476a03354eSMatthew Dillon #include <sys/systimer.h> 486a03354eSMatthew Dillon #include <sys/thread2.h> 496a03354eSMatthew Dillon 506a03354eSMatthew Dillon #include <net/ethernet.h> 516a03354eSMatthew Dillon #include <net/netmsg2.h> 526a03354eSMatthew Dillon #include <net/netisr2.h> 536a03354eSMatthew Dillon #include <net/route.h> 54*bff82488SAaron LI #include <net/if.h> 556a03354eSMatthew Dillon 566a03354eSMatthew Dillon #include <netinet/in_var.h> 576a03354eSMatthew Dillon #include <netinet/ip_var.h> 586a03354eSMatthew Dillon 596a03354eSMatthew Dillon #include <net/ipfw3/ip_fw.h> 604408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_table.h> 616a03354eSMatthew Dillon 626a03354eSMatthew Dillon #include "ip_fw3_layer2.h" 636a03354eSMatthew Dillon 644408d548SBill Yuan extern struct ipfw3_context *fw3_ctx[MAXCPU]; 656a03354eSMatthew Dillon 666a03354eSMatthew Dillon void 676a03354eSMatthew Dillon check_layer2(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 686a03354eSMatthew Dillon struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 696a03354eSMatthew Dillon { 706a03354eSMatthew Dillon *cmd_val = ((*args)->eh != NULL); 716a03354eSMatthew Dillon *cmd_ctl = IP_FW_CTL_NO; 726a03354eSMatthew Dillon } 736a03354eSMatthew Dillon 746a03354eSMatthew Dillon void 756a03354eSMatthew Dillon check_mac(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 766a03354eSMatthew Dillon struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 776a03354eSMatthew Dillon { 786a03354eSMatthew Dillon *cmd_ctl = IP_FW_CTL_NO; 796a03354eSMatthew Dillon if ((*args)->eh != NULL) { 806a03354eSMatthew Dillon uint32_t *want = (uint32_t *)((ipfw_insn_mac *)cmd)->addr; 816a03354eSMatthew Dillon uint32_t *mask = (uint32_t *)((ipfw_insn_mac *)cmd)->mask; 826a03354eSMatthew Dillon uint32_t *hdr = (uint32_t *)(*args)->eh; 836a03354eSMatthew Dillon *cmd_val = 846a03354eSMatthew Dillon (want[0] == (hdr[0] & mask[0]) && 856a03354eSMatthew Dillon want[1] == (hdr[1] & mask[1]) && 866a03354eSMatthew Dillon want[2] == (hdr[2] & mask[2])); 876a03354eSMatthew Dillon } else { 886a03354eSMatthew Dillon *cmd_val = IP_FW_NOT_MATCH; 896a03354eSMatthew Dillon } 906a03354eSMatthew Dillon } 916a03354eSMatthew Dillon 92ab88ebe4SBill Yuan void 93ab88ebe4SBill Yuan check_mac_from(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 94ab88ebe4SBill Yuan struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 95ab88ebe4SBill Yuan { 96ab88ebe4SBill Yuan *cmd_ctl = IP_FW_CTL_NO; 97ab88ebe4SBill Yuan if ((*args)->eh != NULL) { 98ab88ebe4SBill Yuan uint16_t *want = (uint16_t *)((ipfw_insn_mac *)cmd)->addr; 99ab88ebe4SBill Yuan uint16_t *mask = (uint16_t *)((ipfw_insn_mac *)cmd)->mask; 100ab88ebe4SBill Yuan uint16_t *hdr = (uint16_t *)(*args)->eh; 101ab88ebe4SBill Yuan *cmd_val = 102ab88ebe4SBill Yuan (want[3] == (hdr[3] & mask[3]) && 103ab88ebe4SBill Yuan want[4] == (hdr[4] & mask[4]) && 104ab88ebe4SBill Yuan want[5] == (hdr[5] & mask[5])); 105ab88ebe4SBill Yuan } else { 106ab88ebe4SBill Yuan *cmd_val = IP_FW_NOT_MATCH; 107ab88ebe4SBill Yuan } 108ab88ebe4SBill Yuan } 109ab88ebe4SBill Yuan 110ab88ebe4SBill Yuan void 111ab88ebe4SBill Yuan check_mac_from_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 112ab88ebe4SBill Yuan struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 113ab88ebe4SBill Yuan { 1144408d548SBill Yuan struct ipfw3_context *ctx = fw3_ctx[mycpuid]; 1154408d548SBill Yuan struct ipfw3_table_context *table_ctx; 116ab88ebe4SBill Yuan struct radix_node_head *rnh; 117ab88ebe4SBill Yuan struct table_mac_entry *ent = NULL; 118ab88ebe4SBill Yuan 119ab88ebe4SBill Yuan table_ctx = ctx->table_ctx; 120ab88ebe4SBill Yuan table_ctx += cmd->arg1; 121ab88ebe4SBill Yuan rnh = table_ctx->node; 122ab88ebe4SBill Yuan 123ab88ebe4SBill Yuan *cmd_ctl = IP_FW_CTL_NO; 124ab88ebe4SBill Yuan *cmd_val = IP_FW_NOT_MATCH; 125ab88ebe4SBill Yuan if ((*args)->eh != NULL) { 126ab88ebe4SBill Yuan struct sockaddr sa; 127ab88ebe4SBill Yuan sa.sa_len = 8; 128ab88ebe4SBill Yuan strncpy(sa.sa_data, (*args)->eh->ether_shost, 6); 129ab88ebe4SBill Yuan ent = (struct table_mac_entry *)rnh->rnh_lookup((char *)&sa, 130ab88ebe4SBill Yuan NULL, rnh); 131ab88ebe4SBill Yuan if(ent != NULL) 132ab88ebe4SBill Yuan *cmd_val = IP_FW_MATCH; 133ab88ebe4SBill Yuan } 134ab88ebe4SBill Yuan } 135ab88ebe4SBill Yuan 136ab88ebe4SBill Yuan void 137ab88ebe4SBill Yuan check_mac_to(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 138ab88ebe4SBill Yuan struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 139ab88ebe4SBill Yuan { 140ab88ebe4SBill Yuan *cmd_ctl = IP_FW_CTL_NO; 141ab88ebe4SBill Yuan if ((*args)->eh != NULL) { 142ab88ebe4SBill Yuan uint16_t *want = (uint16_t *)((ipfw_insn_mac *)cmd)->addr; 143ab88ebe4SBill Yuan uint16_t *mask = (uint16_t *)((ipfw_insn_mac *)cmd)->mask; 144ab88ebe4SBill Yuan uint16_t *hdr = (uint16_t *)(*args)->eh; 145ab88ebe4SBill Yuan *cmd_val = 146ab88ebe4SBill Yuan (want[0] == (hdr[0] & mask[0]) && 147ab88ebe4SBill Yuan want[1] == (hdr[1] & mask[1]) && 148ab88ebe4SBill Yuan want[2] == (hdr[2] & mask[2])); 149ab88ebe4SBill Yuan } else { 150ab88ebe4SBill Yuan *cmd_val = IP_FW_NOT_MATCH; 151ab88ebe4SBill Yuan } 152ab88ebe4SBill Yuan } 153ab88ebe4SBill Yuan 154ab88ebe4SBill Yuan void 155ab88ebe4SBill Yuan check_mac_to_lookup(int *cmd_ctl, int *cmd_val, struct ip_fw_args **args, 156ab88ebe4SBill Yuan struct ip_fw **f, ipfw_insn *cmd, uint16_t ip_len) 157ab88ebe4SBill Yuan { 1584408d548SBill Yuan struct ipfw3_context *ctx = fw3_ctx[mycpuid]; 1594408d548SBill Yuan struct ipfw3_table_context *table_ctx; 160ab88ebe4SBill Yuan struct radix_node_head *rnh; 161ab88ebe4SBill Yuan struct table_mac_entry *ent = NULL; 162ab88ebe4SBill Yuan 163ab88ebe4SBill Yuan table_ctx = ctx->table_ctx; 164ab88ebe4SBill Yuan table_ctx += cmd->arg1; 165ab88ebe4SBill Yuan rnh = table_ctx->node; 166ab88ebe4SBill Yuan 167ab88ebe4SBill Yuan *cmd_ctl = IP_FW_CTL_NO; 168ab88ebe4SBill Yuan *cmd_val = IP_FW_NOT_MATCH; 169ab88ebe4SBill Yuan if ((*args)->eh != NULL) { 170ab88ebe4SBill Yuan struct sockaddr sa; 171ab88ebe4SBill Yuan sa.sa_len = 8; 172ab88ebe4SBill Yuan strncpy(sa.sa_data, (*args)->eh->ether_dhost, 6); 173ab88ebe4SBill Yuan ent = (struct table_mac_entry *)rnh->rnh_lookup((char *)&sa, 174ab88ebe4SBill Yuan NULL, rnh); 175ab88ebe4SBill Yuan if(ent != NULL) 176ab88ebe4SBill Yuan *cmd_val = IP_FW_MATCH; 177ab88ebe4SBill Yuan } 178ab88ebe4SBill Yuan } 179ab88ebe4SBill Yuan 1806a03354eSMatthew Dillon static int 1814408d548SBill Yuan ip_fw3_layer2_init(void) 1826a03354eSMatthew Dillon { 1834408d548SBill Yuan ip_fw3_register_module(MODULE_LAYER2_ID, MODULE_LAYER2_NAME); 1844408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 1856a03354eSMatthew Dillon O_LAYER2_LAYER2, (filter_func)check_layer2); 1864408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 1876a03354eSMatthew Dillon O_LAYER2_MAC, (filter_func)check_mac); 1884408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 189ab88ebe4SBill Yuan O_LAYER2_MAC_SRC, (filter_func)check_mac_from); 1904408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 191ab88ebe4SBill Yuan O_LAYER2_MAC_DST, (filter_func)check_mac_to); 1924408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 193ab88ebe4SBill Yuan O_LAYER2_MAC_SRC_LOOKUP, 194ab88ebe4SBill Yuan (filter_func)check_mac_from_lookup); 1954408d548SBill Yuan ip_fw3_register_filter_funcs(MODULE_LAYER2_ID, 196ab88ebe4SBill Yuan O_LAYER2_MAC_DST_LOOKUP, 197ab88ebe4SBill Yuan (filter_func)check_mac_to_lookup); 1986a03354eSMatthew Dillon return 0; 1996a03354eSMatthew Dillon } 2006a03354eSMatthew Dillon 2016a03354eSMatthew Dillon static int 2024408d548SBill Yuan ip_fw3_layer2_stop(void) 2036a03354eSMatthew Dillon { 2044408d548SBill Yuan return ip_fw3_unregister_module(MODULE_LAYER2_ID); 2056a03354eSMatthew Dillon } 2066a03354eSMatthew Dillon 2076a03354eSMatthew Dillon static int 2086a03354eSMatthew Dillon ipfw3_layer2_modevent(module_t mod, int type, void *data) 2096a03354eSMatthew Dillon { 2106a03354eSMatthew Dillon switch (type) { 2116a03354eSMatthew Dillon case MOD_LOAD: 2124408d548SBill Yuan return ip_fw3_layer2_init(); 2136a03354eSMatthew Dillon case MOD_UNLOAD: 2144408d548SBill Yuan return ip_fw3_layer2_stop(); 2156a03354eSMatthew Dillon default: 2166a03354eSMatthew Dillon break; 2176a03354eSMatthew Dillon } 2186a03354eSMatthew Dillon return 0; 2196a03354eSMatthew Dillon } 2206a03354eSMatthew Dillon 2216a03354eSMatthew Dillon static moduledata_t ipfw3_layer2_mod = { 2226a03354eSMatthew Dillon "ipfw3_layer2", 2236a03354eSMatthew Dillon ipfw3_layer2_modevent, 2246a03354eSMatthew Dillon NULL 2256a03354eSMatthew Dillon }; 2266a03354eSMatthew Dillon DECLARE_MODULE(ipfw3_layer2, ipfw3_layer2_mod, SI_SUB_PROTO_END, SI_ORDER_ANY); 2276a03354eSMatthew Dillon MODULE_DEPEND(ipfw3_layer2, ipfw3_basic, 1, 1, 1); 2286a03354eSMatthew Dillon MODULE_VERSION(ipfw3_layer2, 1); 229