13b3a8eb9SGleb Smirnoff /*- 2fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3fe267a55SPedro F. Giffuni * 43b3a8eb9SGleb Smirnoff * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa 53b3a8eb9SGleb Smirnoff * 63b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 73b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 83b3a8eb9SGleb Smirnoff * are met: 93b3a8eb9SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 103b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 113b3a8eb9SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 123b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 133b3a8eb9SGleb Smirnoff * documentation and/or other materials provided with the distribution. 143b3a8eb9SGleb Smirnoff * 153b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 163b3a8eb9SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 173b3a8eb9SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 183b3a8eb9SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 193b3a8eb9SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 203b3a8eb9SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 213b3a8eb9SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 223b3a8eb9SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 233b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 243b3a8eb9SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 253b3a8eb9SGleb Smirnoff * SUCH DAMAGE. 263b3a8eb9SGleb Smirnoff * 273b3a8eb9SGleb Smirnoff * $FreeBSD$ 283b3a8eb9SGleb Smirnoff */ 293b3a8eb9SGleb Smirnoff 303b3a8eb9SGleb Smirnoff #ifndef _IPFW2_PRIVATE_H 313b3a8eb9SGleb Smirnoff #define _IPFW2_PRIVATE_H 323b3a8eb9SGleb Smirnoff 333b3a8eb9SGleb Smirnoff /* 343b3a8eb9SGleb Smirnoff * Internal constants and data structures used by ipfw components 353b3a8eb9SGleb Smirnoff * and not meant to be exported outside the kernel. 363b3a8eb9SGleb Smirnoff */ 373b3a8eb9SGleb Smirnoff 383b3a8eb9SGleb Smirnoff #ifdef _KERNEL 393b3a8eb9SGleb Smirnoff 403b3a8eb9SGleb Smirnoff /* 413b3a8eb9SGleb Smirnoff * For platforms that do not have SYSCTL support, we wrap the 423b3a8eb9SGleb Smirnoff * SYSCTL_* into a function (one per file) to collect the values 433b3a8eb9SGleb Smirnoff * into an array at module initialization. The wrapping macros, 443b3a8eb9SGleb Smirnoff * SYSBEGIN() and SYSEND, are empty in the default case. 453b3a8eb9SGleb Smirnoff */ 463b3a8eb9SGleb Smirnoff #ifndef SYSBEGIN 473b3a8eb9SGleb Smirnoff #define SYSBEGIN(x) 483b3a8eb9SGleb Smirnoff #endif 493b3a8eb9SGleb Smirnoff #ifndef SYSEND 503b3a8eb9SGleb Smirnoff #define SYSEND 513b3a8eb9SGleb Smirnoff #endif 523b3a8eb9SGleb Smirnoff 533b3a8eb9SGleb Smirnoff /* Return values from ipfw_chk() */ 543b3a8eb9SGleb Smirnoff enum { 553b3a8eb9SGleb Smirnoff IP_FW_PASS = 0, 563b3a8eb9SGleb Smirnoff IP_FW_DENY, 573b3a8eb9SGleb Smirnoff IP_FW_DIVERT, 583b3a8eb9SGleb Smirnoff IP_FW_TEE, 593b3a8eb9SGleb Smirnoff IP_FW_DUMMYNET, 603b3a8eb9SGleb Smirnoff IP_FW_NETGRAPH, 613b3a8eb9SGleb Smirnoff IP_FW_NGTEE, 623b3a8eb9SGleb Smirnoff IP_FW_NAT, 633b3a8eb9SGleb Smirnoff IP_FW_REASS, 64ca0f03e8SAndrey V. Elsukov IP_FW_NAT64, 653b3a8eb9SGleb Smirnoff }; 663b3a8eb9SGleb Smirnoff 673b3a8eb9SGleb Smirnoff /* 683b3a8eb9SGleb Smirnoff * Structure for collecting parameters to dummynet for ip6_output forwarding 693b3a8eb9SGleb Smirnoff */ 703b3a8eb9SGleb Smirnoff struct _ip6dn_args { 713b3a8eb9SGleb Smirnoff struct ip6_pktopts *opt_or; 723b3a8eb9SGleb Smirnoff int flags_or; 733b3a8eb9SGleb Smirnoff struct ip6_moptions *im6o_or; 743b3a8eb9SGleb Smirnoff struct ifnet *origifp_or; 753b3a8eb9SGleb Smirnoff struct ifnet *ifp_or; 763b3a8eb9SGleb Smirnoff struct sockaddr_in6 dst_or; 773b3a8eb9SGleb Smirnoff u_long mtu_or; 783b3a8eb9SGleb Smirnoff }; 793b3a8eb9SGleb Smirnoff 803b3a8eb9SGleb Smirnoff /* 813b3a8eb9SGleb Smirnoff * Arguments for calling ipfw_chk() and dummynet_io(). We put them 823b3a8eb9SGleb Smirnoff * all into a structure because this way it is easier and more 833b3a8eb9SGleb Smirnoff * efficient to pass variables around and extend the interface. 843b3a8eb9SGleb Smirnoff */ 853b3a8eb9SGleb Smirnoff struct ip_fw_args { 861cdf23bcSAndrey V. Elsukov uint32_t flags; 87b7795b67SGleb Smirnoff #define IPFW_ARGS_ETHER 0x00010000 /* valid ethernet header */ 88b7795b67SGleb Smirnoff #define IPFW_ARGS_NH4 0x00020000 /* IPv4 next hop in hopstore */ 89b7795b67SGleb Smirnoff #define IPFW_ARGS_NH6 0x00040000 /* IPv6 next hop in hopstore */ 90b7795b67SGleb Smirnoff #define IPFW_ARGS_NH4PTR 0x00080000 /* IPv4 next hop in next_hop */ 91b7795b67SGleb Smirnoff #define IPFW_ARGS_NH6PTR 0x00100000 /* IPv6 next hop in next_hop6 */ 92b7795b67SGleb Smirnoff #define IPFW_ARGS_REF 0x00200000 /* valid ipfw_rule_ref */ 93b7795b67SGleb Smirnoff #define IPFW_ARGS_IN 0x00400000 /* called on input */ 94b7795b67SGleb Smirnoff #define IPFW_ARGS_OUT 0x00800000 /* called on output */ 95b7795b67SGleb Smirnoff #define IPFW_ARGS_IP4 0x01000000 /* belongs to v4 ISR */ 96b7795b67SGleb Smirnoff #define IPFW_ARGS_IP6 0x02000000 /* belongs to v6 ISR */ 97b7795b67SGleb Smirnoff #define IPFW_ARGS_DROP 0x04000000 /* drop it (dummynet) */ 98b7795b67SGleb Smirnoff #define IPFW_ARGS_LENMASK 0x0000ffff /* length of data in *mem */ 99b7795b67SGleb Smirnoff #define IPFW_ARGS_LENGTH(f) ((f) & IPFW_ARGS_LENMASK) 1003b3a8eb9SGleb Smirnoff /* 1013b3a8eb9SGleb Smirnoff * On return, it points to the matching rule. 1023b3a8eb9SGleb Smirnoff * On entry, rule.slot > 0 means the info is valid and 1033b3a8eb9SGleb Smirnoff * contains the starting rule for an ipfw search. 1043b3a8eb9SGleb Smirnoff * If chain_id == chain->id && slot >0 then jump to that slot. 1053b3a8eb9SGleb Smirnoff * Otherwise, we locate the first rule >= rulenum:rule_id 1063b3a8eb9SGleb Smirnoff */ 1073b3a8eb9SGleb Smirnoff struct ipfw_rule_ref rule; /* match/restart info */ 1083b3a8eb9SGleb Smirnoff 109b7795b67SGleb Smirnoff struct ifnet *ifp; /* input/output interface */ 1103b3a8eb9SGleb Smirnoff struct inpcb *inp; 1111cdf23bcSAndrey V. Elsukov union { 1121cdf23bcSAndrey V. Elsukov /* 1131cdf23bcSAndrey V. Elsukov * next_hop[6] pointers can be used to point to next hop 1141cdf23bcSAndrey V. Elsukov * stored in rule's opcode to avoid copying into hopstore. 1151cdf23bcSAndrey V. Elsukov * Also, it is expected that all 0x1-0x10 flags are mutually 1161cdf23bcSAndrey V. Elsukov * exclusive. 1171cdf23bcSAndrey V. Elsukov */ 1181cdf23bcSAndrey V. Elsukov struct sockaddr_in *next_hop; 1191cdf23bcSAndrey V. Elsukov struct sockaddr_in6 *next_hop6; 1201cdf23bcSAndrey V. Elsukov /* ipfw next hop storage */ 1212530ed9eSAndrey V. Elsukov struct sockaddr_in hopstore; 1221cdf23bcSAndrey V. Elsukov struct ip_fw_nh6 { 1231cdf23bcSAndrey V. Elsukov struct in6_addr sin6_addr; 1241cdf23bcSAndrey V. Elsukov uint32_t sin6_scope_id; 1251cdf23bcSAndrey V. Elsukov uint16_t sin6_port; 1261cdf23bcSAndrey V. Elsukov } hopstore6; 1272530ed9eSAndrey V. Elsukov }; 128f355cb3eSGleb Smirnoff union { 1291cdf23bcSAndrey V. Elsukov struct mbuf *m; /* the mbuf chain */ 130f355cb3eSGleb Smirnoff void *mem; /* or memory pointer */ 131f355cb3eSGleb Smirnoff }; 1321cdf23bcSAndrey V. Elsukov struct ipfw_flow_id f_id; /* grabbed from IP header */ 1333b3a8eb9SGleb Smirnoff }; 1343b3a8eb9SGleb Smirnoff 1353b3a8eb9SGleb Smirnoff MALLOC_DECLARE(M_IPFW); 1363b3a8eb9SGleb Smirnoff 1373b3a8eb9SGleb Smirnoff /* wrapper for freeing a packet, in case we need to do more work */ 1383b3a8eb9SGleb Smirnoff #ifndef FREE_PKT 1393b3a8eb9SGleb Smirnoff #if defined(__linux__) || defined(_WIN32) 1403b3a8eb9SGleb Smirnoff #define FREE_PKT(m) netisr_dispatch(-1, m) 1413b3a8eb9SGleb Smirnoff #else 1423b3a8eb9SGleb Smirnoff #define FREE_PKT(m) m_freem(m) 1433b3a8eb9SGleb Smirnoff #endif 1443b3a8eb9SGleb Smirnoff #endif /* !FREE_PKT */ 1453b3a8eb9SGleb Smirnoff 1463b3a8eb9SGleb Smirnoff /* 1473b3a8eb9SGleb Smirnoff * Function definitions. 1483b3a8eb9SGleb Smirnoff */ 149cefe3d67SAndrey V. Elsukov int ipfw_chk(struct ip_fw_args *args); 150cefe3d67SAndrey V. Elsukov struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *, 151cefe3d67SAndrey V. Elsukov u_int32_t, u_int32_t, int); 1523b3a8eb9SGleb Smirnoff 15397245d40SGleb Smirnoff int ipfw_attach_hooks(void); 15497245d40SGleb Smirnoff void ipfw_detach_hooks(void); 1553b3a8eb9SGleb Smirnoff #ifdef NOTYET 1563b3a8eb9SGleb Smirnoff void ipfw_nat_destroy(void); 1573b3a8eb9SGleb Smirnoff #endif 1583b3a8eb9SGleb Smirnoff 1593b3a8eb9SGleb Smirnoff /* In ip_fw_log.c */ 1603b3a8eb9SGleb Smirnoff struct ip; 1610cba2b28SAlexander V. Chernikov struct ip_fw_chain; 162cefe3d67SAndrey V. Elsukov 16356132dccSAndrey V. Elsukov void ipfw_bpf_init(int); 16456132dccSAndrey V. Elsukov void ipfw_bpf_uninit(int); 165f355cb3eSGleb Smirnoff void ipfw_bpf_tap(u_char *, u_int); 166f355cb3eSGleb Smirnoff void ipfw_bpf_mtap(struct mbuf *); 16756132dccSAndrey V. Elsukov void ipfw_bpf_mtap2(void *, u_int, struct mbuf *); 1680cba2b28SAlexander V. Chernikov void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 169f355cb3eSGleb Smirnoff struct ip_fw_args *args, u_short offset, uint32_t tablearg, struct ip *ip); 1703b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int64_t, norule_counter); 1713b3a8eb9SGleb Smirnoff #define V_norule_counter VNET(norule_counter) 1723b3a8eb9SGleb Smirnoff VNET_DECLARE(int, verbose_limit); 1733b3a8eb9SGleb Smirnoff #define V_verbose_limit VNET(verbose_limit) 1743b3a8eb9SGleb Smirnoff 1753b3a8eb9SGleb Smirnoff /* In ip_fw_dynamic.c */ 176cefe3d67SAndrey V. Elsukov struct sockopt_data; 1773b3a8eb9SGleb Smirnoff 1783b3a8eb9SGleb Smirnoff enum { /* result for matching dynamic rules */ 1793b3a8eb9SGleb Smirnoff MATCH_REVERSE = 0, 1803b3a8eb9SGleb Smirnoff MATCH_FORWARD, 1813b3a8eb9SGleb Smirnoff MATCH_NONE, 1823b3a8eb9SGleb Smirnoff MATCH_UNKNOWN, 1833b3a8eb9SGleb Smirnoff }; 1843b3a8eb9SGleb Smirnoff 1853b3a8eb9SGleb Smirnoff /* 186b99a6823SAndrey V. Elsukov * Macro to determine that we need to do or redo dynamic state lookup. 187b99a6823SAndrey V. Elsukov * direction == MATCH_UNKNOWN means that this is first lookup, then we need 188b99a6823SAndrey V. Elsukov * to do lookup. 189b99a6823SAndrey V. Elsukov * Otherwise check the state name, if previous lookup was for "any" name, 190b99a6823SAndrey V. Elsukov * this means there is no state with specific name. Thus no need to do 191b99a6823SAndrey V. Elsukov * lookup. If previous name was not "any", redo lookup for specific name. 192b99a6823SAndrey V. Elsukov */ 193b99a6823SAndrey V. Elsukov #define DYN_LOOKUP_NEEDED(p, cmd) \ 194b99a6823SAndrey V. Elsukov ((p)->direction == MATCH_UNKNOWN || \ 195b99a6823SAndrey V. Elsukov ((p)->kidx != 0 && (p)->kidx != (cmd)->arg1)) 196b99a6823SAndrey V. Elsukov #define DYN_INFO_INIT(p) do { \ 197b99a6823SAndrey V. Elsukov (p)->direction = MATCH_UNKNOWN; \ 198b99a6823SAndrey V. Elsukov (p)->kidx = 0; \ 199b99a6823SAndrey V. Elsukov } while (0) 200b99a6823SAndrey V. Elsukov struct ipfw_dyn_info { 201b99a6823SAndrey V. Elsukov uint16_t direction; /* match direction */ 202b99a6823SAndrey V. Elsukov uint16_t kidx; /* state name kidx */ 203b99a6823SAndrey V. Elsukov uint32_t hashval; /* hash value */ 204b99a6823SAndrey V. Elsukov uint32_t version; /* bucket version */ 205b99a6823SAndrey V. Elsukov uint32_t f_pos; 206b99a6823SAndrey V. Elsukov }; 2071719df1bSAndrey V. Elsukov int ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule, 208b99a6823SAndrey V. Elsukov const ipfw_insn_limit *cmd, const struct ip_fw_args *args, 209b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, struct ipfw_dyn_info *info, 210b99a6823SAndrey V. Elsukov uint32_t tablearg); 211b99a6823SAndrey V. Elsukov struct ip_fw *ipfw_dyn_lookup_state(const struct ip_fw_args *args, 212b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, const ipfw_insn *cmd, 213b99a6823SAndrey V. Elsukov struct ipfw_dyn_info *info); 214b99a6823SAndrey V. Elsukov 215cefe3d67SAndrey V. Elsukov int ipfw_is_dyn_rule(struct ip_fw *rule); 216cefe3d67SAndrey V. Elsukov void ipfw_expire_dyn_states(struct ip_fw_chain *, ipfw_range_tlv *); 2172e089d5cSAlexander V. Chernikov void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep); 218563b5ab1SAlexander V. Chernikov int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd); 2193b3a8eb9SGleb Smirnoff 2202e089d5cSAlexander V. Chernikov void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */ 2213b3a8eb9SGleb Smirnoff void ipfw_dyn_uninit(int); /* per-vnet deinitialization */ 2223b3a8eb9SGleb Smirnoff int ipfw_dyn_len(void); 223cefe3d67SAndrey V. Elsukov uint32_t ipfw_dyn_get_count(uint32_t *, int *); 224cefe3d67SAndrey V. Elsukov void ipfw_dyn_reset_eaction(struct ip_fw_chain *ch, uint16_t eaction_id, 225cefe3d67SAndrey V. Elsukov uint16_t default_id, uint16_t instance_id); 2263b3a8eb9SGleb Smirnoff 2273b3a8eb9SGleb Smirnoff /* common variables */ 2283b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_one_pass); 2293b3a8eb9SGleb Smirnoff #define V_fw_one_pass VNET(fw_one_pass) 2303b3a8eb9SGleb Smirnoff 2313b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_verbose); 2323b3a8eb9SGleb Smirnoff #define V_fw_verbose VNET(fw_verbose) 2333b3a8eb9SGleb Smirnoff 2343b3a8eb9SGleb Smirnoff VNET_DECLARE(struct ip_fw_chain, layer3_chain); 2353b3a8eb9SGleb Smirnoff #define V_layer3_chain VNET(layer3_chain) 2363b3a8eb9SGleb Smirnoff 23798eff10eSAlexander V. Chernikov VNET_DECLARE(int, ipfw_vnet_ready); 23898eff10eSAlexander V. Chernikov #define V_ipfw_vnet_ready VNET(ipfw_vnet_ready) 23998eff10eSAlexander V. Chernikov 2403b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int32_t, set_disable); 2413b3a8eb9SGleb Smirnoff #define V_set_disable VNET(set_disable) 2423b3a8eb9SGleb Smirnoff 2433b3a8eb9SGleb Smirnoff VNET_DECLARE(int, autoinc_step); 2443b3a8eb9SGleb Smirnoff #define V_autoinc_step VNET(autoinc_step) 2453b3a8eb9SGleb Smirnoff 2463b3a8eb9SGleb Smirnoff VNET_DECLARE(unsigned int, fw_tables_max); 2473b3a8eb9SGleb Smirnoff #define V_fw_tables_max VNET(fw_tables_max) 2483b3a8eb9SGleb Smirnoff 249b074b7bbSAlexander V. Chernikov VNET_DECLARE(unsigned int, fw_tables_sets); 250b074b7bbSAlexander V. Chernikov #define V_fw_tables_sets VNET(fw_tables_sets) 251b074b7bbSAlexander V. Chernikov 252b074b7bbSAlexander V. Chernikov struct tables_config; 253b074b7bbSAlexander V. Chernikov 2547e767c79SAlexander V. Chernikov #ifdef _KERNEL 2557e767c79SAlexander V. Chernikov /* 2567e767c79SAlexander V. Chernikov * Here we have the structure representing an ipfw rule. 2577e767c79SAlexander V. Chernikov * 2587e767c79SAlexander V. Chernikov * It starts with a general area 2597e767c79SAlexander V. Chernikov * followed by an array of one or more instructions, which the code 2607e767c79SAlexander V. Chernikov * accesses as an array of 32-bit values. 2617e767c79SAlexander V. Chernikov * 2627e767c79SAlexander V. Chernikov * Given a rule pointer r: 2637e767c79SAlexander V. Chernikov * 2647e767c79SAlexander V. Chernikov * r->cmd is the start of the first instruction. 2657e767c79SAlexander V. Chernikov * ACTION_PTR(r) is the start of the first action (things to do 2667e767c79SAlexander V. Chernikov * once a rule matched). 2677e767c79SAlexander V. Chernikov */ 268322e5efdSAndrey V. Elsukov struct ip_fw_jump_cache { 269322e5efdSAndrey V. Elsukov union { 270322e5efdSAndrey V. Elsukov struct { 271322e5efdSAndrey V. Elsukov uint32_t id; 272322e5efdSAndrey V. Elsukov uint32_t pos; 273322e5efdSAndrey V. Elsukov }; 274322e5efdSAndrey V. Elsukov uint64_t raw_value; 275322e5efdSAndrey V. Elsukov }; 276322e5efdSAndrey V. Elsukov }; 2777e767c79SAlexander V. Chernikov 2787e767c79SAlexander V. Chernikov struct ip_fw { 2797e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 2807e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 2817e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 2827e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 2837e767c79SAlexander V. Chernikov uint8_t flags; /* currently unused */ 2847e767c79SAlexander V. Chernikov counter_u64_t cntr; /* Pointer to rule counters */ 285322e5efdSAndrey V. Elsukov struct ip_fw_jump_cache cache; /* used by jump_fast */ 2867e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 2877e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 288cefe3d67SAndrey V. Elsukov uint32_t refcnt; /* number of references */ 2897e767c79SAlexander V. Chernikov 290cefe3d67SAndrey V. Elsukov struct ip_fw *next; /* linked list of deleted rules */ 2917e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 2927e767c79SAlexander V. Chernikov }; 2937e767c79SAlexander V. Chernikov 2943535eac4SAlexander V. Chernikov #define IPFW_RULE_CNTR_SIZE (2 * sizeof(uint64_t)) 2950d90989bSAlexander V. Chernikov 2967e767c79SAlexander V. Chernikov #endif 2977e767c79SAlexander V. Chernikov 2983b3a8eb9SGleb Smirnoff struct ip_fw_chain { 2993b3a8eb9SGleb Smirnoff struct ip_fw **map; /* array of rule ptrs to ease lookup */ 3005fa3fdd3SAlexander V. Chernikov uint32_t id; /* ruleset id */ 3015fa3fdd3SAlexander V. Chernikov int n_rules; /* number of static rules */ 3029f7d47b0SAlexander V. Chernikov void *tablestate; /* runtime table info */ 3030cba2b28SAlexander V. Chernikov void *valuestate; /* runtime table value info */ 304d5eb80cbSAlexander V. Chernikov int *idxmap; /* skipto array of rules */ 30574b22066SAlexander V. Chernikov void **srvstate; /* runtime service mappings */ 3063b3a8eb9SGleb Smirnoff #if defined( __linux__ ) || defined( _WIN32 ) 3073b3a8eb9SGleb Smirnoff spinlock_t rwmtx; 308f712b161SGleb Smirnoff #else 309f712b161SGleb Smirnoff struct rmlock rwmtx; 3105fa3fdd3SAlexander V. Chernikov #endif 3117e767c79SAlexander V. Chernikov int static_len; /* total len of static rules (v0) */ 3125fa3fdd3SAlexander V. Chernikov uint32_t gencnt; /* NAT generation count */ 31374b22066SAlexander V. Chernikov LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */ 3145fa3fdd3SAlexander V. Chernikov struct ip_fw *default_rule; 315b074b7bbSAlexander V. Chernikov struct tables_config *tblcfg; /* tables module data */ 31668394ec8SAlexander V. Chernikov void *ifcfg; /* interface module data */ 317d5eb80cbSAlexander V. Chernikov int *idxmap_back; /* standby skipto array of rules */ 31874b22066SAlexander V. Chernikov struct namedobj_instance *srvmap; /* cfg name->number mappings */ 3195fa3fdd3SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 3205fa3fdd3SAlexander V. Chernikov spinlock_t uh_lock; 3215fa3fdd3SAlexander V. Chernikov #else 3223b3a8eb9SGleb Smirnoff struct rwlock uh_lock; /* lock for upper half */ 3233b3a8eb9SGleb Smirnoff #endif 3243b3a8eb9SGleb Smirnoff }; 3253b3a8eb9SGleb Smirnoff 3260cba2b28SAlexander V. Chernikov /* 64-byte structure representing multi-field table value */ 3270cba2b28SAlexander V. Chernikov struct table_value { 3280cba2b28SAlexander V. Chernikov uint32_t tag; /* O_TAG/O_TAGGED */ 3290cba2b28SAlexander V. Chernikov uint32_t pipe; /* O_PIPE/O_QUEUE */ 3300cba2b28SAlexander V. Chernikov uint16_t divert; /* O_DIVERT/O_TEE */ 3310cba2b28SAlexander V. Chernikov uint16_t skipto; /* skipto, CALLRET */ 3320cba2b28SAlexander V. Chernikov uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */ 333*fc727ad6SBoris Lytochkin uint16_t fib; /* O_SETFIB */ 334*fc727ad6SBoris Lytochkin uint16_t nat; /* O_NAT */ 335*fc727ad6SBoris Lytochkin uint32_t mark; /* O_SETMARK/O_MARK */ 3360cba2b28SAlexander V. Chernikov uint32_t nh4; 3370cba2b28SAlexander V. Chernikov uint8_t dscp; 3382530ed9eSAndrey V. Elsukov uint8_t spare0; 339*fc727ad6SBoris Lytochkin uint16_t kidx; /* value kernel index */ 3400cba2b28SAlexander V. Chernikov /* -- 32 bytes -- */ 3410cba2b28SAlexander V. Chernikov struct in6_addr nh6; 3420cba2b28SAlexander V. Chernikov uint32_t limit; /* O_LIMIT */ 3432530ed9eSAndrey V. Elsukov uint32_t zoneid; /* scope zone id for nh6 */ 3440cba2b28SAlexander V. Chernikov uint64_t refcnt; /* Number of references */ 3450cba2b28SAlexander V. Chernikov }; 3460cba2b28SAlexander V. Chernikov 34768394ec8SAlexander V. Chernikov struct named_object { 34868394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nn_next; /* namehash */ 34968394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nv_next; /* valuehash */ 35068394ec8SAlexander V. Chernikov char *name; /* object name */ 3514bd91656SAndrey V. Elsukov uint16_t etlv; /* Export TLV id */ 35274b22066SAlexander V. Chernikov uint8_t subtype;/* object subtype within class */ 3532685841bSAndrey V. Elsukov uint8_t set; /* set object belongs to */ 35468394ec8SAlexander V. Chernikov uint16_t kidx; /* object kernel index */ 3552685841bSAndrey V. Elsukov uint16_t spare; 3562685841bSAndrey V. Elsukov uint32_t ocnt; /* object counter for internal use */ 35768394ec8SAlexander V. Chernikov uint32_t refcnt; /* number of references */ 35868394ec8SAlexander V. Chernikov }; 35968394ec8SAlexander V. Chernikov TAILQ_HEAD(namedobjects_head, named_object); 36068394ec8SAlexander V. Chernikov 3613b3a8eb9SGleb Smirnoff struct sockopt; /* used by tcp_var.h */ 3622d99a349SAlexander V. Chernikov struct sockopt_data { 3632d99a349SAlexander V. Chernikov caddr_t kbuf; /* allocated buffer */ 3642d99a349SAlexander V. Chernikov size_t ksize; /* given buffer size */ 3652d99a349SAlexander V. Chernikov size_t koff; /* data already used */ 3662d99a349SAlexander V. Chernikov size_t kavail; /* number of bytes available */ 3672d99a349SAlexander V. Chernikov size_t ktotal; /* total bytes pushed */ 3682d99a349SAlexander V. Chernikov struct sockopt *sopt; /* socket data */ 369b6ee846eSAlexander V. Chernikov caddr_t sopt_val; /* sopt user buffer */ 3702d99a349SAlexander V. Chernikov size_t valsize; /* original data size */ 3712d99a349SAlexander V. Chernikov }; 3723b3a8eb9SGleb Smirnoff 37368394ec8SAlexander V. Chernikov struct ipfw_ifc; 37468394ec8SAlexander V. Chernikov 37568394ec8SAlexander V. Chernikov typedef void (ipfw_ifc_cb)(struct ip_fw_chain *ch, void *cbdata, 37668394ec8SAlexander V. Chernikov uint16_t ifindex); 37768394ec8SAlexander V. Chernikov 37868394ec8SAlexander V. Chernikov struct ipfw_iface { 37968394ec8SAlexander V. Chernikov struct named_object no; 38068394ec8SAlexander V. Chernikov char ifname[64]; 38168394ec8SAlexander V. Chernikov int resolved; 38268394ec8SAlexander V. Chernikov uint16_t ifindex; 38368394ec8SAlexander V. Chernikov uint16_t spare; 38468394ec8SAlexander V. Chernikov uint64_t gencnt; 38568394ec8SAlexander V. Chernikov TAILQ_HEAD(, ipfw_ifc) consumers; 38668394ec8SAlexander V. Chernikov }; 38768394ec8SAlexander V. Chernikov 38868394ec8SAlexander V. Chernikov struct ipfw_ifc { 38968394ec8SAlexander V. Chernikov TAILQ_ENTRY(ipfw_ifc) next; 39068394ec8SAlexander V. Chernikov struct ipfw_iface *iface; 39168394ec8SAlexander V. Chernikov ipfw_ifc_cb *cb; 39268394ec8SAlexander V. Chernikov void *cbdata; 39368394ec8SAlexander V. Chernikov }; 39468394ec8SAlexander V. Chernikov 395c187c1fbSAlexander V. Chernikov /* Macro for working with various counters */ 3967e767c79SAlexander V. Chernikov #define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \ 3977e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr, 1); \ 3987e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr + 1, _bytes); \ 3997e767c79SAlexander V. Chernikov if ((_cntr)->timestamp != time_uptime) \ 4007e767c79SAlexander V. Chernikov (_cntr)->timestamp = time_uptime; \ 4017e767c79SAlexander V. Chernikov } while (0) 4027e767c79SAlexander V. Chernikov 4037e767c79SAlexander V. Chernikov #define IPFW_INC_DYN_COUNTER(_cntr, _bytes) do { \ 4047e767c79SAlexander V. Chernikov (_cntr)->pcnt++; \ 4057e767c79SAlexander V. Chernikov (_cntr)->bcnt += _bytes; \ 4067e767c79SAlexander V. Chernikov } while (0) 4077e767c79SAlexander V. Chernikov 4087e767c79SAlexander V. Chernikov #define IPFW_ZERO_RULE_COUNTER(_cntr) do { \ 4097e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr); \ 4107e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr + 1); \ 4117e767c79SAlexander V. Chernikov (_cntr)->timestamp = 0; \ 4127e767c79SAlexander V. Chernikov } while (0) 4137e767c79SAlexander V. Chernikov 4147e767c79SAlexander V. Chernikov #define IPFW_ZERO_DYN_COUNTER(_cntr) do { \ 4157e767c79SAlexander V. Chernikov (_cntr)->pcnt = 0; \ 4167e767c79SAlexander V. Chernikov (_cntr)->bcnt = 0; \ 4177e767c79SAlexander V. Chernikov } while (0) 4187e767c79SAlexander V. Chernikov 4190cba2b28SAlexander V. Chernikov #define TARG_VAL(ch, k, f) ((struct table_value *)((ch)->valuestate))[k].f 4200cba2b28SAlexander V. Chernikov #define IP_FW_ARG_TABLEARG(ch, a, f) \ 4210cba2b28SAlexander V. Chernikov (((a) == IP_FW_TARG) ? TARG_VAL(ch, tablearg, f) : (a)) 4223b3a8eb9SGleb Smirnoff /* 4233b3a8eb9SGleb Smirnoff * The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c 4243b3a8eb9SGleb Smirnoff * so the variable and the macros must be here. 4253b3a8eb9SGleb Smirnoff */ 4263b3a8eb9SGleb Smirnoff 427ccba94b8SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 4283b3a8eb9SGleb Smirnoff #define IPFW_LOCK_INIT(_chain) do { \ 4293b3a8eb9SGleb Smirnoff rw_init(&(_chain)->rwmtx, "IPFW static rules"); \ 4303b3a8eb9SGleb Smirnoff rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 4313b3a8eb9SGleb Smirnoff } while (0) 4323b3a8eb9SGleb Smirnoff 4333b3a8eb9SGleb Smirnoff #define IPFW_LOCK_DESTROY(_chain) do { \ 4343b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->rwmtx); \ 4353b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->uh_lock); \ 4363b3a8eb9SGleb Smirnoff } while (0) 4373b3a8eb9SGleb Smirnoff 4385d0cd926SAlexander V. Chernikov #define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED) 4393b3a8eb9SGleb Smirnoff #define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED) 4403b3a8eb9SGleb Smirnoff 441ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER 4423b3a8eb9SGleb Smirnoff #define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx) 4433b3a8eb9SGleb Smirnoff #define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx) 4443b3a8eb9SGleb Smirnoff #define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx) 4453b3a8eb9SGleb Smirnoff #define IPFW_WUNLOCK(p) rw_wunlock(&(p)->rwmtx) 44693bb4f9eSAndrey V. Elsukov #define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) 44793bb4f9eSAndrey V. Elsukov #define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) 448ccba94b8SAlexander V. Chernikov #else /* FreeBSD */ 449ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_INIT(_chain) do { \ 450f712b161SGleb Smirnoff rm_init_flags(&(_chain)->rwmtx, "IPFW static rules", RM_RECURSE); \ 451ccba94b8SAlexander V. Chernikov rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 452ccba94b8SAlexander V. Chernikov } while (0) 453ccba94b8SAlexander V. Chernikov 454ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_DESTROY(_chain) do { \ 455f712b161SGleb Smirnoff rm_destroy(&(_chain)->rwmtx); \ 456ccba94b8SAlexander V. Chernikov rw_destroy(&(_chain)->uh_lock); \ 457ccba94b8SAlexander V. Chernikov } while (0) 458ccba94b8SAlexander V. Chernikov 459f712b161SGleb Smirnoff #define IPFW_RLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_RLOCKED) 460f712b161SGleb Smirnoff #define IPFW_WLOCK_ASSERT(_chain) rm_assert(&(_chain)->rwmtx, RA_WLOCKED) 461ccba94b8SAlexander V. Chernikov 462ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER struct rm_priotracker _tracker 463f712b161SGleb Smirnoff #define IPFW_RLOCK(p) rm_rlock(&(p)->rwmtx, &_tracker) 464f712b161SGleb Smirnoff #define IPFW_RUNLOCK(p) rm_runlock(&(p)->rwmtx, &_tracker) 465f712b161SGleb Smirnoff #define IPFW_WLOCK(p) rm_wlock(&(p)->rwmtx) 466f712b161SGleb Smirnoff #define IPFW_WUNLOCK(p) rm_wunlock(&(p)->rwmtx) 467f712b161SGleb Smirnoff #define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) 468f712b161SGleb Smirnoff #define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) 469ccba94b8SAlexander V. Chernikov #endif 4703b3a8eb9SGleb Smirnoff 4712e089d5cSAlexander V. Chernikov #define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED) 4722e089d5cSAlexander V. Chernikov #define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED) 4730caab009SAlexander V. Chernikov #define IPFW_UH_UNLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_UNLOCKED) 4742e089d5cSAlexander V. Chernikov 4753b3a8eb9SGleb Smirnoff #define IPFW_UH_RLOCK(p) rw_rlock(&(p)->uh_lock) 4763b3a8eb9SGleb Smirnoff #define IPFW_UH_RUNLOCK(p) rw_runlock(&(p)->uh_lock) 4773b3a8eb9SGleb Smirnoff #define IPFW_UH_WLOCK(p) rw_wlock(&(p)->uh_lock) 4783b3a8eb9SGleb Smirnoff #define IPFW_UH_WUNLOCK(p) rw_wunlock(&(p)->uh_lock) 4793b3a8eb9SGleb Smirnoff 480b074b7bbSAlexander V. Chernikov struct obj_idx { 481b074b7bbSAlexander V. Chernikov uint16_t uidx; /* internal index supplied by userland */ 482b074b7bbSAlexander V. Chernikov uint16_t kidx; /* kernel object index */ 483b074b7bbSAlexander V. Chernikov uint16_t off; /* tlv offset from rule end in 4-byte words */ 4840468c5baSAlexander V. Chernikov uint8_t spare; 485b074b7bbSAlexander V. Chernikov uint8_t type; /* object type within its category */ 486b074b7bbSAlexander V. Chernikov }; 487b074b7bbSAlexander V. Chernikov 488b074b7bbSAlexander V. Chernikov struct rule_check_info { 4893a845e10SAlexander V. Chernikov uint16_t flags; /* rule-specific check flags */ 49074b22066SAlexander V. Chernikov uint16_t object_opcodes; /* num of opcodes referencing objects */ 4917e767c79SAlexander V. Chernikov uint16_t urule_numoff; /* offset of rulenum in bytes */ 4927e767c79SAlexander V. Chernikov uint8_t version; /* rule version */ 4933a845e10SAlexander V. Chernikov uint8_t spare; 4946c2997ffSAlexander V. Chernikov ipfw_obj_ctlv *ctlv; /* name TLV containter */ 495b074b7bbSAlexander V. Chernikov struct ip_fw *krule; /* resulting rule pointer */ 4967e767c79SAlexander V. Chernikov caddr_t urule; /* original rule pointer */ 497b074b7bbSAlexander V. Chernikov struct obj_idx obuf[8]; /* table references storage */ 498b074b7bbSAlexander V. Chernikov }; 499b074b7bbSAlexander V. Chernikov 5007e767c79SAlexander V. Chernikov /* Legacy interface support */ 5017e767c79SAlexander V. Chernikov /* 5027e767c79SAlexander V. Chernikov * FreeBSD 8 export rule format 5037e767c79SAlexander V. Chernikov */ 5047e767c79SAlexander V. Chernikov struct ip_fw_rule0 { 5057e767c79SAlexander V. Chernikov struct ip_fw *x_next; /* linked list of rules */ 5067e767c79SAlexander V. Chernikov struct ip_fw *next_rule; /* ptr to next [skipto] rule */ 5077e767c79SAlexander V. Chernikov /* 'next_rule' is used to pass up 'set_disable' status */ 5087e767c79SAlexander V. Chernikov 5097e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 5107e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 5117e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 5127e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 5137e767c79SAlexander V. Chernikov uint8_t _pad; /* padding */ 5147e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 5157e767c79SAlexander V. Chernikov 5167e767c79SAlexander V. Chernikov /* These fields are present in all rules. */ 5177e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5187e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5197e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5207e767c79SAlexander V. Chernikov 5217e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 5227e767c79SAlexander V. Chernikov }; 5237e767c79SAlexander V. Chernikov 5247e767c79SAlexander V. Chernikov struct ip_fw_bcounter0 { 5257e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5267e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5277e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5287e767c79SAlexander V. Chernikov }; 5297e767c79SAlexander V. Chernikov 5307e767c79SAlexander V. Chernikov /* Kernel rule length */ 5317e767c79SAlexander V. Chernikov /* 5327e767c79SAlexander V. Chernikov * RULE _K_ SIZE _V_ -> 5337e767c79SAlexander V. Chernikov * get kernel size from userland rool version _V_. 5347e767c79SAlexander V. Chernikov * RULE _U_ SIZE _V_ -> 5357e767c79SAlexander V. Chernikov * get user size version _V_ from kernel rule 5367e767c79SAlexander V. Chernikov * RULESIZE _V_ -> 5377e767c79SAlexander V. Chernikov * get user size rule length 5387e767c79SAlexander V. Chernikov */ 5397e767c79SAlexander V. Chernikov /* FreeBSD8 <> current kernel format */ 5407e767c79SAlexander V. Chernikov #define RULEUSIZE0(r) (sizeof(struct ip_fw_rule0) + (r)->cmd_len * 4 - 4) 5417e767c79SAlexander V. Chernikov #define RULEKSIZE0(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5427e767c79SAlexander V. Chernikov /* FreeBSD11 <> current kernel format */ 5437e767c79SAlexander V. Chernikov #define RULEUSIZE1(r) (roundup2(sizeof(struct ip_fw_rule) + \ 5447e767c79SAlexander V. Chernikov (r)->cmd_len * 4 - 4, 8)) 5457e767c79SAlexander V. Chernikov #define RULEKSIZE1(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5467e767c79SAlexander V. Chernikov 54774b22066SAlexander V. Chernikov /* 54874b22066SAlexander V. Chernikov * Tables/Objects index rewriting code 54974b22066SAlexander V. Chernikov */ 55074b22066SAlexander V. Chernikov 55174b22066SAlexander V. Chernikov /* Default and maximum number of ipfw tables/objects. */ 55274b22066SAlexander V. Chernikov #define IPFW_TABLES_MAX 65536 55374b22066SAlexander V. Chernikov #define IPFW_TABLES_DEFAULT 128 55474b22066SAlexander V. Chernikov #define IPFW_OBJECTS_MAX 65536 5552acdf79fSAndrey V. Elsukov #define IPFW_OBJECTS_DEFAULT 1024 55674b22066SAlexander V. Chernikov 55774b22066SAlexander V. Chernikov #define CHAIN_TO_SRV(ch) ((ch)->srvmap) 5582acdf79fSAndrey V. Elsukov #define SRV_OBJECT(ch, idx) ((ch)->srvstate[(idx)]) 55974b22066SAlexander V. Chernikov 56074b22066SAlexander V. Chernikov struct tid_info { 56174b22066SAlexander V. Chernikov uint32_t set; /* table set */ 56274b22066SAlexander V. Chernikov uint16_t uidx; /* table index */ 56374b22066SAlexander V. Chernikov uint8_t type; /* table type */ 56474b22066SAlexander V. Chernikov uint8_t atype; 56574b22066SAlexander V. Chernikov uint8_t spare; 56674b22066SAlexander V. Chernikov int tlen; /* Total TLV size block */ 56774b22066SAlexander V. Chernikov void *tlvs; /* Pointer to first TLV */ 56874b22066SAlexander V. Chernikov }; 56974b22066SAlexander V. Chernikov 57074b22066SAlexander V. Chernikov /* 57174b22066SAlexander V. Chernikov * Classifier callback. Checks if @cmd opcode contains kernel object reference. 57274b22066SAlexander V. Chernikov * If true, returns its index and type. 57374b22066SAlexander V. Chernikov * Returns 0 if match is found, 1 overwise. 57474b22066SAlexander V. Chernikov */ 57574b22066SAlexander V. Chernikov typedef int (ipfw_obj_rw_cl)(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype); 57674b22066SAlexander V. Chernikov /* 57774b22066SAlexander V. Chernikov * Updater callback. Sets kernel object reference index to @puidx 57874b22066SAlexander V. Chernikov */ 57974b22066SAlexander V. Chernikov typedef void (ipfw_obj_rw_upd)(ipfw_insn *cmd, uint16_t puidx); 58074b22066SAlexander V. Chernikov /* 58174b22066SAlexander V. Chernikov * Finder callback. Tries to find named object by name (specified via @ti). 58274b22066SAlexander V. Chernikov * Stores found named object pointer in @pno. 58374b22066SAlexander V. Chernikov * If object was not found, NULL is stored. 58474b22066SAlexander V. Chernikov * 58574b22066SAlexander V. Chernikov * Return 0 if input data was valid. 58674b22066SAlexander V. Chernikov */ 58774b22066SAlexander V. Chernikov typedef int (ipfw_obj_fname_cb)(struct ip_fw_chain *ch, 58874b22066SAlexander V. Chernikov struct tid_info *ti, struct named_object **pno); 58974b22066SAlexander V. Chernikov /* 59074b22066SAlexander V. Chernikov * Another finder callback. Tries to findex named object by kernel index. 59174b22066SAlexander V. Chernikov * 59274b22066SAlexander V. Chernikov * Returns pointer to named object or NULL. 59374b22066SAlexander V. Chernikov */ 59474b22066SAlexander V. Chernikov typedef struct named_object *(ipfw_obj_fidx_cb)(struct ip_fw_chain *ch, 59574b22066SAlexander V. Chernikov uint16_t kidx); 59674b22066SAlexander V. Chernikov /* 59774b22066SAlexander V. Chernikov * Object creator callback. Tries to create object specified by @ti. 59874b22066SAlexander V. Chernikov * Stores newly-allocated object index in @pkidx. 59974b22066SAlexander V. Chernikov * 60074b22066SAlexander V. Chernikov * Returns 0 on success. 60174b22066SAlexander V. Chernikov */ 60274b22066SAlexander V. Chernikov typedef int (ipfw_obj_create_cb)(struct ip_fw_chain *ch, struct tid_info *ti, 60374b22066SAlexander V. Chernikov uint16_t *pkidx); 6041cf09efeSAndrey V. Elsukov /* 6051cf09efeSAndrey V. Elsukov * Object destroy callback. Intended to free resources allocated by 6061cf09efeSAndrey V. Elsukov * create_object callback. 6071cf09efeSAndrey V. Elsukov */ 6081cf09efeSAndrey V. Elsukov typedef void (ipfw_obj_destroy_cb)(struct ip_fw_chain *ch, 6091cf09efeSAndrey V. Elsukov struct named_object *no); 6102685841bSAndrey V. Elsukov /* 6112685841bSAndrey V. Elsukov * Sets handler callback. Handles moving and swaping set of named object. 6122685841bSAndrey V. Elsukov * SWAP_ALL moves all named objects from set `set' to `new_set' and vise versa; 6132685841bSAndrey V. Elsukov * TEST_ALL checks that there aren't any named object with conflicting names; 6142685841bSAndrey V. Elsukov * MOVE_ALL moves all named objects from set `set' to `new_set'; 6152685841bSAndrey V. Elsukov * COUNT_ONE used to count number of references used by object with kidx `set'; 6162685841bSAndrey V. Elsukov * TEST_ONE checks that named object with kidx `set' can be moved to `new_set`; 6172685841bSAndrey V. Elsukov * MOVE_ONE moves named object with kidx `set' to set `new_set'. 6182685841bSAndrey V. Elsukov */ 6192685841bSAndrey V. Elsukov enum ipfw_sets_cmd { 6202685841bSAndrey V. Elsukov SWAP_ALL = 0, TEST_ALL, MOVE_ALL, COUNT_ONE, TEST_ONE, MOVE_ONE 6212685841bSAndrey V. Elsukov }; 6222685841bSAndrey V. Elsukov typedef int (ipfw_obj_sets_cb)(struct ip_fw_chain *ch, 6232685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 6242685841bSAndrey V. Elsukov 62574b22066SAlexander V. Chernikov struct opcode_obj_rewrite { 62674b22066SAlexander V. Chernikov uint32_t opcode; /* Opcode to act upon */ 62774b22066SAlexander V. Chernikov uint32_t etlv; /* Relevant export TLV id */ 62874b22066SAlexander V. Chernikov ipfw_obj_rw_cl *classifier; /* Check if rewrite is needed */ 62974b22066SAlexander V. Chernikov ipfw_obj_rw_upd *update; /* update cmd with new value */ 63074b22066SAlexander V. Chernikov ipfw_obj_fname_cb *find_byname; /* Find named object by name */ 63174b22066SAlexander V. Chernikov ipfw_obj_fidx_cb *find_bykidx; /* Find named object by kidx */ 63274b22066SAlexander V. Chernikov ipfw_obj_create_cb *create_object; /* Create named object */ 6331cf09efeSAndrey V. Elsukov ipfw_obj_destroy_cb *destroy_object;/* Destroy named object */ 6342685841bSAndrey V. Elsukov ipfw_obj_sets_cb *manage_sets; /* Swap or move sets */ 63574b22066SAlexander V. Chernikov }; 63674b22066SAlexander V. Chernikov 63774b22066SAlexander V. Chernikov #define IPFW_ADD_OBJ_REWRITER(f, c) do { \ 63874b22066SAlexander V. Chernikov if ((f) != 0) \ 63974b22066SAlexander V. Chernikov ipfw_add_obj_rewriter(c, \ 64074b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 64174b22066SAlexander V. Chernikov } while(0) 64274b22066SAlexander V. Chernikov #define IPFW_DEL_OBJ_REWRITER(l, c) do { \ 64374b22066SAlexander V. Chernikov if ((l) != 0) \ 64474b22066SAlexander V. Chernikov ipfw_del_obj_rewriter(c, \ 64574b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 64674b22066SAlexander V. Chernikov } while(0) 6477e767c79SAlexander V. Chernikov 64868394ec8SAlexander V. Chernikov /* In ip_fw_iface.c */ 64968394ec8SAlexander V. Chernikov int ipfw_iface_init(void); 65068394ec8SAlexander V. Chernikov void ipfw_iface_destroy(void); 65168394ec8SAlexander V. Chernikov void vnet_ipfw_iface_destroy(struct ip_fw_chain *ch); 65268394ec8SAlexander V. Chernikov int ipfw_iface_ref(struct ip_fw_chain *ch, char *name, 65368394ec8SAlexander V. Chernikov struct ipfw_ifc *ic); 65468394ec8SAlexander V. Chernikov void ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 65568394ec8SAlexander V. Chernikov void ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 65668394ec8SAlexander V. Chernikov void ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 65768394ec8SAlexander V. Chernikov 6583b3a8eb9SGleb Smirnoff /* In ip_fw_sockopt.c */ 659d5eb80cbSAlexander V. Chernikov void ipfw_init_skipto_cache(struct ip_fw_chain *chain); 660d5eb80cbSAlexander V. Chernikov void ipfw_destroy_skipto_cache(struct ip_fw_chain *chain); 6613b3a8eb9SGleb Smirnoff int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id); 662b429d43cSAlexander V. Chernikov int ipfw_ctl3(struct sockopt *sopt); 6637143bb76SAndrey V. Elsukov int ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule, 6647143bb76SAndrey V. Elsukov int locked); 665030b184fSAlexander V. Chernikov void ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head, 666030b184fSAlexander V. Chernikov struct ip_fw *rule); 6673b3a8eb9SGleb Smirnoff void ipfw_reap_rules(struct ip_fw *head); 6687e767c79SAlexander V. Chernikov void ipfw_init_counters(void); 6697e767c79SAlexander V. Chernikov void ipfw_destroy_counters(void); 6707e767c79SAlexander V. Chernikov struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize); 671cefe3d67SAndrey V. Elsukov void ipfw_free_rule(struct ip_fw *rule); 672a73d728dSAlexander V. Chernikov int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt); 673cefe3d67SAndrey V. Elsukov int ipfw_mark_object_kidx(uint32_t *bmask, uint16_t etlv, uint16_t kidx); 674e758846cSAndrey V. Elsukov ipfw_insn *ipfw_get_action(struct ip_fw *); 6753b3a8eb9SGleb Smirnoff 6766b988f3aSAlexander V. Chernikov typedef int (sopt_handler_f)(struct ip_fw_chain *ch, 6776b988f3aSAlexander V. Chernikov ip_fw3_opheader *op3, struct sockopt_data *sd); 6786b988f3aSAlexander V. Chernikov struct ipfw_sopt_handler { 6796b988f3aSAlexander V. Chernikov uint16_t opcode; 6806b988f3aSAlexander V. Chernikov uint8_t version; 6816b988f3aSAlexander V. Chernikov uint8_t dir; 6826b988f3aSAlexander V. Chernikov sopt_handler_f *handler; 6836b988f3aSAlexander V. Chernikov uint64_t refcnt; 6846b988f3aSAlexander V. Chernikov }; 6856b988f3aSAlexander V. Chernikov #define HDIR_SET 0x01 /* Handler is used to set some data */ 6866b988f3aSAlexander V. Chernikov #define HDIR_GET 0x02 /* Handler is used to retrieve data */ 6876b988f3aSAlexander V. Chernikov #define HDIR_BOTH HDIR_GET|HDIR_SET 6886b988f3aSAlexander V. Chernikov 6896b988f3aSAlexander V. Chernikov void ipfw_init_sopt_handler(void); 6906b988f3aSAlexander V. Chernikov void ipfw_destroy_sopt_handler(void); 6916b988f3aSAlexander V. Chernikov void ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6926b988f3aSAlexander V. Chernikov int ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6932d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed); 6942d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); 6956b988f3aSAlexander V. Chernikov #define IPFW_ADD_SOPT_HANDLER(f, c) do { \ 6966b988f3aSAlexander V. Chernikov if ((f) != 0) \ 6976b988f3aSAlexander V. Chernikov ipfw_add_sopt_handler(c, \ 6986b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 6996b988f3aSAlexander V. Chernikov } while(0) 7006b988f3aSAlexander V. Chernikov #define IPFW_DEL_SOPT_HANDLER(l, c) do { \ 7016b988f3aSAlexander V. Chernikov if ((l) != 0) \ 7026b988f3aSAlexander V. Chernikov ipfw_del_sopt_handler(c, \ 7036b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 7046b988f3aSAlexander V. Chernikov } while(0) 7052d99a349SAlexander V. Chernikov 70674b22066SAlexander V. Chernikov struct namedobj_instance; 707b309f085SAndrey V. Elsukov typedef int (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, 708b074b7bbSAlexander V. Chernikov void *arg); 7092acdf79fSAndrey V. Elsukov typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, 71013263632SAlexander V. Chernikov uint32_t kopt); 7112acdf79fSAndrey V. Elsukov typedef int (objhash_cmp_f)(struct named_object *no, const void *key, 7122acdf79fSAndrey V. Elsukov uint32_t kopt); 713b074b7bbSAlexander V. Chernikov struct namedobj_instance *ipfw_objhash_create(uint32_t items); 714b074b7bbSAlexander V. Chernikov void ipfw_objhash_destroy(struct namedobj_instance *); 715b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks); 7169f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, 7179f7d47b0SAlexander V. Chernikov void **idx, int *blocks); 7189f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, 719b074b7bbSAlexander V. Chernikov void **idx, int *blocks); 720b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_free(void *idx, int blocks); 72113263632SAlexander V. Chernikov void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f); 722b074b7bbSAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni, 723e81fcbecSJustin Hibbits uint32_t set, const char *name); 72474b22066SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, 7252acdf79fSAndrey V. Elsukov uint32_t set, uint32_t type, const char *name); 726ac35ff17SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, 727ac35ff17SAlexander V. Chernikov uint16_t idx); 7289490a627SAlexander V. Chernikov int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, 7299490a627SAlexander V. Chernikov struct named_object *b); 730b074b7bbSAlexander V. Chernikov void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); 731b074b7bbSAlexander V. Chernikov void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); 7329f7d47b0SAlexander V. Chernikov uint32_t ipfw_objhash_count(struct namedobj_instance *ni); 7332685841bSAndrey V. Elsukov uint32_t ipfw_objhash_count_type(struct namedobj_instance *ni, uint16_t type); 734b309f085SAndrey V. Elsukov int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, 735b074b7bbSAlexander V. Chernikov void *arg); 7362685841bSAndrey V. Elsukov int ipfw_objhash_foreach_type(struct namedobj_instance *ni, objhash_cb_t *f, 7372685841bSAndrey V. Elsukov void *arg, uint16_t type); 738ac35ff17SAlexander V. Chernikov int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); 739ac35ff17SAlexander V. Chernikov int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); 74013263632SAlexander V. Chernikov void ipfw_objhash_set_funcs(struct namedobj_instance *ni, 74113263632SAlexander V. Chernikov objhash_hash_f *hash_f, objhash_cmp_f *cmp_f); 7422acdf79fSAndrey V. Elsukov int ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, 7432acdf79fSAndrey V. Elsukov uint32_t etlv, struct named_object **pno); 7445dc5a0e0SAndrey V. Elsukov void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); 7452df1a11fSAndrey V. Elsukov ipfw_obj_ntlv *ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, 7462df1a11fSAndrey V. Elsukov uint32_t etlv); 74774b22066SAlexander V. Chernikov void ipfw_init_obj_rewriter(void); 74874b22066SAlexander V. Chernikov void ipfw_destroy_obj_rewriter(void); 74974b22066SAlexander V. Chernikov void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 75074b22066SAlexander V. Chernikov int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 75174b22066SAlexander V. Chernikov 75274b22066SAlexander V. Chernikov int create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, 75374b22066SAlexander V. Chernikov struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti); 75474b22066SAlexander V. Chernikov void update_opcode_kidx(ipfw_insn *cmd, uint16_t idx); 75574b22066SAlexander V. Chernikov int classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx); 75674b22066SAlexander V. Chernikov void ipfw_init_srv(struct ip_fw_chain *ch); 75774b22066SAlexander V. Chernikov void ipfw_destroy_srv(struct ip_fw_chain *ch); 758f81431ccSAndrey V. Elsukov int ipfw_check_object_name_generic(const char *name); 7592685841bSAndrey V. Elsukov int ipfw_obj_manage_sets(struct namedobj_instance *ni, uint16_t type, 7602685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 761b074b7bbSAlexander V. Chernikov 7622acdf79fSAndrey V. Elsukov /* In ip_fw_eaction.c */ 7632acdf79fSAndrey V. Elsukov typedef int (ipfw_eaction_t)(struct ip_fw_chain *ch, struct ip_fw_args *args, 7642acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 7652acdf79fSAndrey V. Elsukov int ipfw_eaction_init(struct ip_fw_chain *ch, int first); 7662acdf79fSAndrey V. Elsukov void ipfw_eaction_uninit(struct ip_fw_chain *ch, int last); 7672acdf79fSAndrey V. Elsukov 7682acdf79fSAndrey V. Elsukov uint16_t ipfw_add_eaction(struct ip_fw_chain *ch, ipfw_eaction_t handler, 7692acdf79fSAndrey V. Elsukov const char *name); 7702acdf79fSAndrey V. Elsukov int ipfw_del_eaction(struct ip_fw_chain *ch, uint16_t eaction_id); 7712acdf79fSAndrey V. Elsukov int ipfw_run_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, 7722acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 773cefe3d67SAndrey V. Elsukov int ipfw_reset_eaction(struct ip_fw_chain *ch, struct ip_fw *rule, 774cefe3d67SAndrey V. Elsukov uint16_t eaction_id, uint16_t default_id, uint16_t instance_id); 775cefe3d67SAndrey V. Elsukov int ipfw_reset_eaction_instance(struct ip_fw_chain *ch, uint16_t eaction_id, 776cefe3d67SAndrey V. Elsukov uint16_t instance_id); 7772acdf79fSAndrey V. Elsukov 7783b3a8eb9SGleb Smirnoff /* In ip_fw_table.c */ 7799f7d47b0SAlexander V. Chernikov struct table_info; 7809f7d47b0SAlexander V. Chernikov 7819f7d47b0SAlexander V. Chernikov typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen, 7829f7d47b0SAlexander V. Chernikov uint32_t *val); 7839f7d47b0SAlexander V. Chernikov 78454e5669dSAndrey V. Elsukov int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, 78554e5669dSAndrey V. Elsukov void *paddr, uint32_t *val); 7866951cecfSAndrey V. Elsukov struct named_object *ipfw_objhash_lookup_table_kidx(struct ip_fw_chain *ch, 7876951cecfSAndrey V. Elsukov uint16_t kidx); 7886951cecfSAndrey V. Elsukov int ipfw_ref_table(struct ip_fw_chain *ch, ipfw_obj_ntlv *ntlv, uint16_t *kidx); 7896951cecfSAndrey V. Elsukov void ipfw_unref_table(struct ip_fw_chain *ch, uint16_t kidx); 7906b988f3aSAlexander V. Chernikov int ipfw_init_tables(struct ip_fw_chain *ch, int first); 7913b3a8eb9SGleb Smirnoff int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables); 792a73d728dSAlexander V. Chernikov int ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int nsets); 7936b988f3aSAlexander V. Chernikov void ipfw_destroy_tables(struct ip_fw_chain *ch, int last); 7949f7d47b0SAlexander V. Chernikov 7953b3a8eb9SGleb Smirnoff /* In ip_fw_nat.c -- XXX to be moved to ip_var.h */ 7963b3a8eb9SGleb Smirnoff 7973b3a8eb9SGleb Smirnoff extern struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int); 7983b3a8eb9SGleb Smirnoff 7993b3a8eb9SGleb Smirnoff typedef int ipfw_nat_t(struct ip_fw_args *, struct cfg_nat *, struct mbuf *); 8003b3a8eb9SGleb Smirnoff typedef int ipfw_nat_cfg_t(struct sockopt *); 8013b3a8eb9SGleb Smirnoff 8028856400bSMikolaj Golub VNET_DECLARE(int, ipfw_nat_ready); 8038856400bSMikolaj Golub #define V_ipfw_nat_ready VNET(ipfw_nat_ready) 8048856400bSMikolaj Golub #define IPFW_NAT_LOADED (V_ipfw_nat_ready) 8053b3a8eb9SGleb Smirnoff 8068856400bSMikolaj Golub extern ipfw_nat_t *ipfw_nat_ptr; 8073b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_cfg_ptr; 8083b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_del_ptr; 8093b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr; 8103b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; 8113b3a8eb9SGleb Smirnoff 812af9aa0a8SAndrey V. Elsukov /* Helper functions for IP checksum adjustment */ 813af9aa0a8SAndrey V. Elsukov static __inline uint16_t 814af9aa0a8SAndrey V. Elsukov cksum_add(uint16_t sum, uint16_t a) 815af9aa0a8SAndrey V. Elsukov { 816af9aa0a8SAndrey V. Elsukov uint16_t res; 817af9aa0a8SAndrey V. Elsukov 818af9aa0a8SAndrey V. Elsukov res = sum + a; 819af9aa0a8SAndrey V. Elsukov return (res + (res < a)); 820af9aa0a8SAndrey V. Elsukov } 821af9aa0a8SAndrey V. Elsukov 822af9aa0a8SAndrey V. Elsukov static __inline uint16_t 823af9aa0a8SAndrey V. Elsukov cksum_adjust(uint16_t oldsum, uint16_t old, uint16_t new) 824af9aa0a8SAndrey V. Elsukov { 825af9aa0a8SAndrey V. Elsukov 826af9aa0a8SAndrey V. Elsukov return (~cksum_add(cksum_add(~oldsum, ~old), new)); 827af9aa0a8SAndrey V. Elsukov } 828af9aa0a8SAndrey V. Elsukov 8293b3a8eb9SGleb Smirnoff #endif /* _KERNEL */ 8303b3a8eb9SGleb Smirnoff #endif /* _IPFW2_PRIVATE_H */ 831