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, 643b3a8eb9SGleb Smirnoff }; 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff /* 673b3a8eb9SGleb Smirnoff * Structure for collecting parameters to dummynet for ip6_output forwarding 683b3a8eb9SGleb Smirnoff */ 693b3a8eb9SGleb Smirnoff struct _ip6dn_args { 703b3a8eb9SGleb Smirnoff struct ip6_pktopts *opt_or; 713b3a8eb9SGleb Smirnoff int flags_or; 723b3a8eb9SGleb Smirnoff struct ip6_moptions *im6o_or; 733b3a8eb9SGleb Smirnoff struct ifnet *origifp_or; 743b3a8eb9SGleb Smirnoff struct ifnet *ifp_or; 753b3a8eb9SGleb Smirnoff struct sockaddr_in6 dst_or; 763b3a8eb9SGleb Smirnoff u_long mtu_or; 773b3a8eb9SGleb Smirnoff }; 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 { 863b3a8eb9SGleb Smirnoff struct mbuf *m; /* the mbuf chain */ 873b3a8eb9SGleb Smirnoff struct ifnet *oif; /* output interface */ 883b3a8eb9SGleb Smirnoff struct sockaddr_in *next_hop; /* forward address */ 893b3a8eb9SGleb Smirnoff struct sockaddr_in6 *next_hop6; /* ipv6 forward address */ 903b3a8eb9SGleb Smirnoff 913b3a8eb9SGleb Smirnoff /* 923b3a8eb9SGleb Smirnoff * On return, it points to the matching rule. 933b3a8eb9SGleb Smirnoff * On entry, rule.slot > 0 means the info is valid and 943b3a8eb9SGleb Smirnoff * contains the starting rule for an ipfw search. 953b3a8eb9SGleb Smirnoff * If chain_id == chain->id && slot >0 then jump to that slot. 963b3a8eb9SGleb Smirnoff * Otherwise, we locate the first rule >= rulenum:rule_id 973b3a8eb9SGleb Smirnoff */ 983b3a8eb9SGleb Smirnoff struct ipfw_rule_ref rule; /* match/restart info */ 993b3a8eb9SGleb Smirnoff 1003b3a8eb9SGleb Smirnoff struct ether_header *eh; /* for bridged packets */ 1013b3a8eb9SGleb Smirnoff 1023b3a8eb9SGleb Smirnoff struct ipfw_flow_id f_id; /* grabbed from IP header */ 1033b3a8eb9SGleb Smirnoff //uint32_t cookie; /* a cookie depending on rule action */ 1043b3a8eb9SGleb Smirnoff struct inpcb *inp; 1053b3a8eb9SGleb Smirnoff 1063b3a8eb9SGleb Smirnoff struct _ip6dn_args dummypar; /* dummynet->ip6_output */ 1072530ed9eSAndrey V. Elsukov union { /* store here if cannot use a pointer */ 1082530ed9eSAndrey V. Elsukov struct sockaddr_in hopstore; 1092530ed9eSAndrey V. Elsukov struct sockaddr_in6 hopstore6; 1102530ed9eSAndrey V. Elsukov }; 1113b3a8eb9SGleb Smirnoff }; 1123b3a8eb9SGleb Smirnoff 1133b3a8eb9SGleb Smirnoff MALLOC_DECLARE(M_IPFW); 1143b3a8eb9SGleb Smirnoff 1153b3a8eb9SGleb Smirnoff /* 1163b3a8eb9SGleb Smirnoff * Hooks sometime need to know the direction of the packet 1173b3a8eb9SGleb Smirnoff * (divert, dummynet, netgraph, ...) 1183b3a8eb9SGleb Smirnoff * We use a generic definition here, with bit0-1 indicating the 1193b3a8eb9SGleb Smirnoff * direction, bit 2 indicating layer2 or 3, bit 3-4 indicating the 1203b3a8eb9SGleb Smirnoff * specific protocol 1213b3a8eb9SGleb Smirnoff * indicating the protocol (if necessary) 1223b3a8eb9SGleb Smirnoff */ 1233b3a8eb9SGleb Smirnoff enum { 1243b3a8eb9SGleb Smirnoff DIR_MASK = 0x3, 1253b3a8eb9SGleb Smirnoff DIR_OUT = 0, 1263b3a8eb9SGleb Smirnoff DIR_IN = 1, 1273b3a8eb9SGleb Smirnoff DIR_FWD = 2, 1283b3a8eb9SGleb Smirnoff DIR_DROP = 3, 1293b3a8eb9SGleb Smirnoff PROTO_LAYER2 = 0x4, /* set for layer 2 */ 1303b3a8eb9SGleb Smirnoff /* PROTO_DEFAULT = 0, */ 1313b3a8eb9SGleb Smirnoff PROTO_IPV4 = 0x08, 1323b3a8eb9SGleb Smirnoff PROTO_IPV6 = 0x10, 1333b3a8eb9SGleb Smirnoff PROTO_IFB = 0x0c, /* layer2 + ifbridge */ 1343b3a8eb9SGleb Smirnoff /* PROTO_OLDBDG = 0x14, unused, old bridge */ 1353b3a8eb9SGleb Smirnoff }; 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 */ 1493b3a8eb9SGleb Smirnoff 1503b3a8eb9SGleb Smirnoff /* attach (arg = 1) or detach (arg = 0) hooks */ 1513b3a8eb9SGleb Smirnoff int ipfw_attach_hooks(int); 1523b3a8eb9SGleb Smirnoff #ifdef NOTYET 1533b3a8eb9SGleb Smirnoff void ipfw_nat_destroy(void); 1543b3a8eb9SGleb Smirnoff #endif 1553b3a8eb9SGleb Smirnoff 1563b3a8eb9SGleb Smirnoff /* In ip_fw_log.c */ 1573b3a8eb9SGleb Smirnoff struct ip; 1580cba2b28SAlexander V. Chernikov struct ip_fw_chain; 15956132dccSAndrey V. Elsukov void ipfw_bpf_init(int); 16056132dccSAndrey V. Elsukov void ipfw_bpf_uninit(int); 16156132dccSAndrey V. Elsukov void ipfw_bpf_mtap2(void *, u_int, struct mbuf *); 1620cba2b28SAlexander V. Chernikov void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 1630cba2b28SAlexander V. Chernikov struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif, 1640cba2b28SAlexander V. Chernikov u_short offset, uint32_t tablearg, struct ip *ip); 1653b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int64_t, norule_counter); 1663b3a8eb9SGleb Smirnoff #define V_norule_counter VNET(norule_counter) 1673b3a8eb9SGleb Smirnoff VNET_DECLARE(int, verbose_limit); 1683b3a8eb9SGleb Smirnoff #define V_verbose_limit VNET(verbose_limit) 1693b3a8eb9SGleb Smirnoff 1703b3a8eb9SGleb Smirnoff /* In ip_fw_dynamic.c */ 1713b3a8eb9SGleb Smirnoff 1723b3a8eb9SGleb Smirnoff enum { /* result for matching dynamic rules */ 1733b3a8eb9SGleb Smirnoff MATCH_REVERSE = 0, 1743b3a8eb9SGleb Smirnoff MATCH_FORWARD, 1753b3a8eb9SGleb Smirnoff MATCH_NONE, 1763b3a8eb9SGleb Smirnoff MATCH_UNKNOWN, 1773b3a8eb9SGleb Smirnoff }; 1783b3a8eb9SGleb Smirnoff 1793b3a8eb9SGleb Smirnoff /* 1803b3a8eb9SGleb Smirnoff * The lock for dynamic rules is only used once outside the file, 1813b3a8eb9SGleb Smirnoff * and only to release the result of lookup_dyn_rule(). 1823b3a8eb9SGleb Smirnoff * Eventually we may implement it with a callback on the function. 1833b3a8eb9SGleb Smirnoff */ 1842e089d5cSAlexander V. Chernikov struct ip_fw_chain; 185563b5ab1SAlexander V. Chernikov struct sockopt_data; 186a73d728dSAlexander V. Chernikov int ipfw_is_dyn_rule(struct ip_fw *rule); 187*b99a6823SAndrey V. Elsukov void ipfw_expire_dyn_states(struct ip_fw_chain *, ipfw_range_tlv *); 1883b3a8eb9SGleb Smirnoff 1893b3a8eb9SGleb Smirnoff struct tcphdr; 1903b3a8eb9SGleb Smirnoff struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *, 1913b3a8eb9SGleb Smirnoff u_int32_t, u_int32_t, int); 192*b99a6823SAndrey V. Elsukov /* 193*b99a6823SAndrey V. Elsukov * Macro to determine that we need to do or redo dynamic state lookup. 194*b99a6823SAndrey V. Elsukov * direction == MATCH_UNKNOWN means that this is first lookup, then we need 195*b99a6823SAndrey V. Elsukov * to do lookup. 196*b99a6823SAndrey V. Elsukov * Otherwise check the state name, if previous lookup was for "any" name, 197*b99a6823SAndrey V. Elsukov * this means there is no state with specific name. Thus no need to do 198*b99a6823SAndrey V. Elsukov * lookup. If previous name was not "any", redo lookup for specific name. 199*b99a6823SAndrey V. Elsukov */ 200*b99a6823SAndrey V. Elsukov #define DYN_LOOKUP_NEEDED(p, cmd) \ 201*b99a6823SAndrey V. Elsukov ((p)->direction == MATCH_UNKNOWN || \ 202*b99a6823SAndrey V. Elsukov ((p)->kidx != 0 && (p)->kidx != (cmd)->arg1)) 203*b99a6823SAndrey V. Elsukov #define DYN_INFO_INIT(p) do { \ 204*b99a6823SAndrey V. Elsukov (p)->direction = MATCH_UNKNOWN; \ 205*b99a6823SAndrey V. Elsukov (p)->kidx = 0; \ 206*b99a6823SAndrey V. Elsukov } while (0) 207*b99a6823SAndrey V. Elsukov struct ipfw_dyn_info { 208*b99a6823SAndrey V. Elsukov uint16_t direction; /* match direction */ 209*b99a6823SAndrey V. Elsukov uint16_t kidx; /* state name kidx */ 210*b99a6823SAndrey V. Elsukov uint32_t hashval; /* hash value */ 211*b99a6823SAndrey V. Elsukov uint32_t version; /* bucket version */ 212*b99a6823SAndrey V. Elsukov uint32_t f_pos; 213*b99a6823SAndrey V. Elsukov }; 2141719df1bSAndrey V. Elsukov int ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule, 215*b99a6823SAndrey V. Elsukov const ipfw_insn_limit *cmd, const struct ip_fw_args *args, 216*b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, struct ipfw_dyn_info *info, 217*b99a6823SAndrey V. Elsukov uint32_t tablearg); 218*b99a6823SAndrey V. Elsukov struct ip_fw *ipfw_dyn_lookup_state(const struct ip_fw_args *args, 219*b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, const ipfw_insn *cmd, 220*b99a6823SAndrey V. Elsukov struct ipfw_dyn_info *info); 221*b99a6823SAndrey V. Elsukov 2222e089d5cSAlexander V. Chernikov void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep); 223563b5ab1SAlexander V. Chernikov int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd); 2243b3a8eb9SGleb Smirnoff 2252e089d5cSAlexander V. Chernikov void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */ 2263b3a8eb9SGleb Smirnoff void ipfw_dyn_uninit(int); /* per-vnet deinitialization */ 2273b3a8eb9SGleb Smirnoff int ipfw_dyn_len(void); 228*b99a6823SAndrey V. Elsukov uint32_t ipfw_dyn_get_count(void); 2293b3a8eb9SGleb Smirnoff 2303b3a8eb9SGleb Smirnoff /* common variables */ 2313b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_one_pass); 2323b3a8eb9SGleb Smirnoff #define V_fw_one_pass VNET(fw_one_pass) 2333b3a8eb9SGleb Smirnoff 2343b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_verbose); 2353b3a8eb9SGleb Smirnoff #define V_fw_verbose VNET(fw_verbose) 2363b3a8eb9SGleb Smirnoff 2373b3a8eb9SGleb Smirnoff VNET_DECLARE(struct ip_fw_chain, layer3_chain); 2383b3a8eb9SGleb Smirnoff #define V_layer3_chain VNET(layer3_chain) 2393b3a8eb9SGleb Smirnoff 24098eff10eSAlexander V. Chernikov VNET_DECLARE(int, ipfw_vnet_ready); 24198eff10eSAlexander V. Chernikov #define V_ipfw_vnet_ready VNET(ipfw_vnet_ready) 24298eff10eSAlexander V. Chernikov 2433b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int32_t, set_disable); 2443b3a8eb9SGleb Smirnoff #define V_set_disable VNET(set_disable) 2453b3a8eb9SGleb Smirnoff 2463b3a8eb9SGleb Smirnoff VNET_DECLARE(int, autoinc_step); 2473b3a8eb9SGleb Smirnoff #define V_autoinc_step VNET(autoinc_step) 2483b3a8eb9SGleb Smirnoff 2493b3a8eb9SGleb Smirnoff VNET_DECLARE(unsigned int, fw_tables_max); 2503b3a8eb9SGleb Smirnoff #define V_fw_tables_max VNET(fw_tables_max) 2513b3a8eb9SGleb Smirnoff 252b074b7bbSAlexander V. Chernikov VNET_DECLARE(unsigned int, fw_tables_sets); 253b074b7bbSAlexander V. Chernikov #define V_fw_tables_sets VNET(fw_tables_sets) 254b074b7bbSAlexander V. Chernikov 255b074b7bbSAlexander V. Chernikov struct tables_config; 256b074b7bbSAlexander V. Chernikov 2577e767c79SAlexander V. Chernikov #ifdef _KERNEL 2587e767c79SAlexander V. Chernikov /* 2597e767c79SAlexander V. Chernikov * Here we have the structure representing an ipfw rule. 2607e767c79SAlexander V. Chernikov * 2617e767c79SAlexander V. Chernikov * It starts with a general area 2627e767c79SAlexander V. Chernikov * followed by an array of one or more instructions, which the code 2637e767c79SAlexander V. Chernikov * accesses as an array of 32-bit values. 2647e767c79SAlexander V. Chernikov * 2657e767c79SAlexander V. Chernikov * Given a rule pointer r: 2667e767c79SAlexander V. Chernikov * 2677e767c79SAlexander V. Chernikov * r->cmd is the start of the first instruction. 2687e767c79SAlexander V. Chernikov * ACTION_PTR(r) is the start of the first action (things to do 2697e767c79SAlexander V. Chernikov * once a rule matched). 2707e767c79SAlexander V. Chernikov */ 2717e767c79SAlexander V. Chernikov 2727e767c79SAlexander V. Chernikov struct ip_fw { 2737e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 2747e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 2757e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 2767e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 2777e767c79SAlexander V. Chernikov uint8_t flags; /* currently unused */ 2787e767c79SAlexander V. Chernikov counter_u64_t cntr; /* Pointer to rule counters */ 2797e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 2807e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 281030b184fSAlexander V. Chernikov uint32_t cached_id; /* used by jump_fast */ 282030b184fSAlexander V. Chernikov uint32_t cached_pos; /* used by jump_fast */ 2837e767c79SAlexander V. Chernikov 2847e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 2857e767c79SAlexander V. Chernikov }; 2867e767c79SAlexander V. Chernikov 2873535eac4SAlexander V. Chernikov #define IPFW_RULE_CNTR_SIZE (2 * sizeof(uint64_t)) 2880d90989bSAlexander V. Chernikov 2897e767c79SAlexander V. Chernikov #endif 2907e767c79SAlexander V. Chernikov 2913b3a8eb9SGleb Smirnoff struct ip_fw_chain { 2923b3a8eb9SGleb Smirnoff struct ip_fw **map; /* array of rule ptrs to ease lookup */ 2935fa3fdd3SAlexander V. Chernikov uint32_t id; /* ruleset id */ 2945fa3fdd3SAlexander V. Chernikov int n_rules; /* number of static rules */ 2959f7d47b0SAlexander V. Chernikov void *tablestate; /* runtime table info */ 2960cba2b28SAlexander V. Chernikov void *valuestate; /* runtime table value info */ 297d5eb80cbSAlexander V. Chernikov int *idxmap; /* skipto array of rules */ 29874b22066SAlexander V. Chernikov void **srvstate; /* runtime service mappings */ 2993b3a8eb9SGleb Smirnoff #if defined( __linux__ ) || defined( _WIN32 ) 3003b3a8eb9SGleb Smirnoff spinlock_t rwmtx; 3015fa3fdd3SAlexander V. Chernikov #endif 3027e767c79SAlexander V. Chernikov int static_len; /* total len of static rules (v0) */ 3035fa3fdd3SAlexander V. Chernikov uint32_t gencnt; /* NAT generation count */ 30474b22066SAlexander V. Chernikov LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */ 3055fa3fdd3SAlexander V. Chernikov struct ip_fw *default_rule; 306b074b7bbSAlexander V. Chernikov struct tables_config *tblcfg; /* tables module data */ 30768394ec8SAlexander V. Chernikov void *ifcfg; /* interface module data */ 308d5eb80cbSAlexander V. Chernikov int *idxmap_back; /* standby skipto array of rules */ 30974b22066SAlexander V. Chernikov struct namedobj_instance *srvmap; /* cfg name->number mappings */ 3105fa3fdd3SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 3115fa3fdd3SAlexander V. Chernikov spinlock_t uh_lock; 3125fa3fdd3SAlexander V. Chernikov #else 3133b3a8eb9SGleb Smirnoff struct rwlock uh_lock; /* lock for upper half */ 3143b3a8eb9SGleb Smirnoff #endif 3153b3a8eb9SGleb Smirnoff }; 3163b3a8eb9SGleb Smirnoff 3170cba2b28SAlexander V. Chernikov /* 64-byte structure representing multi-field table value */ 3180cba2b28SAlexander V. Chernikov struct table_value { 3190cba2b28SAlexander V. Chernikov uint32_t tag; /* O_TAG/O_TAGGED */ 3200cba2b28SAlexander V. Chernikov uint32_t pipe; /* O_PIPE/O_QUEUE */ 3210cba2b28SAlexander V. Chernikov uint16_t divert; /* O_DIVERT/O_TEE */ 3220cba2b28SAlexander V. Chernikov uint16_t skipto; /* skipto, CALLRET */ 3230cba2b28SAlexander V. Chernikov uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */ 3240cba2b28SAlexander V. Chernikov uint32_t fib; /* O_SETFIB */ 3250cba2b28SAlexander V. Chernikov uint32_t nat; /* O_NAT */ 3260cba2b28SAlexander V. Chernikov uint32_t nh4; 3270cba2b28SAlexander V. Chernikov uint8_t dscp; 3282530ed9eSAndrey V. Elsukov uint8_t spare0; 3292530ed9eSAndrey V. Elsukov uint16_t spare1; 3300cba2b28SAlexander V. Chernikov /* -- 32 bytes -- */ 3310cba2b28SAlexander V. Chernikov struct in6_addr nh6; 3320cba2b28SAlexander V. Chernikov uint32_t limit; /* O_LIMIT */ 3332530ed9eSAndrey V. Elsukov uint32_t zoneid; /* scope zone id for nh6 */ 3340cba2b28SAlexander V. Chernikov uint64_t refcnt; /* Number of references */ 3350cba2b28SAlexander V. Chernikov }; 3360cba2b28SAlexander V. Chernikov 33768394ec8SAlexander V. Chernikov 33868394ec8SAlexander V. Chernikov struct named_object { 33968394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nn_next; /* namehash */ 34068394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nv_next; /* valuehash */ 34168394ec8SAlexander V. Chernikov char *name; /* object name */ 3424bd91656SAndrey V. Elsukov uint16_t etlv; /* Export TLV id */ 34374b22066SAlexander V. Chernikov uint8_t subtype;/* object subtype within class */ 3442685841bSAndrey V. Elsukov uint8_t set; /* set object belongs to */ 34568394ec8SAlexander V. Chernikov uint16_t kidx; /* object kernel index */ 3462685841bSAndrey V. Elsukov uint16_t spare; 3472685841bSAndrey V. Elsukov uint32_t ocnt; /* object counter for internal use */ 34868394ec8SAlexander V. Chernikov uint32_t refcnt; /* number of references */ 34968394ec8SAlexander V. Chernikov }; 35068394ec8SAlexander V. Chernikov TAILQ_HEAD(namedobjects_head, named_object); 35168394ec8SAlexander V. Chernikov 3523b3a8eb9SGleb Smirnoff struct sockopt; /* used by tcp_var.h */ 3532d99a349SAlexander V. Chernikov struct sockopt_data { 3542d99a349SAlexander V. Chernikov caddr_t kbuf; /* allocated buffer */ 3552d99a349SAlexander V. Chernikov size_t ksize; /* given buffer size */ 3562d99a349SAlexander V. Chernikov size_t koff; /* data already used */ 3572d99a349SAlexander V. Chernikov size_t kavail; /* number of bytes available */ 3582d99a349SAlexander V. Chernikov size_t ktotal; /* total bytes pushed */ 3592d99a349SAlexander V. Chernikov struct sockopt *sopt; /* socket data */ 360b6ee846eSAlexander V. Chernikov caddr_t sopt_val; /* sopt user buffer */ 3612d99a349SAlexander V. Chernikov size_t valsize; /* original data size */ 3622d99a349SAlexander V. Chernikov }; 3633b3a8eb9SGleb Smirnoff 36468394ec8SAlexander V. Chernikov struct ipfw_ifc; 36568394ec8SAlexander V. Chernikov 36668394ec8SAlexander V. Chernikov typedef void (ipfw_ifc_cb)(struct ip_fw_chain *ch, void *cbdata, 36768394ec8SAlexander V. Chernikov uint16_t ifindex); 36868394ec8SAlexander V. Chernikov 36968394ec8SAlexander V. Chernikov struct ipfw_iface { 37068394ec8SAlexander V. Chernikov struct named_object no; 37168394ec8SAlexander V. Chernikov char ifname[64]; 37268394ec8SAlexander V. Chernikov int resolved; 37368394ec8SAlexander V. Chernikov uint16_t ifindex; 37468394ec8SAlexander V. Chernikov uint16_t spare; 37568394ec8SAlexander V. Chernikov uint64_t gencnt; 37668394ec8SAlexander V. Chernikov TAILQ_HEAD(, ipfw_ifc) consumers; 37768394ec8SAlexander V. Chernikov }; 37868394ec8SAlexander V. Chernikov 37968394ec8SAlexander V. Chernikov struct ipfw_ifc { 38068394ec8SAlexander V. Chernikov TAILQ_ENTRY(ipfw_ifc) next; 38168394ec8SAlexander V. Chernikov struct ipfw_iface *iface; 38268394ec8SAlexander V. Chernikov ipfw_ifc_cb *cb; 38368394ec8SAlexander V. Chernikov void *cbdata; 38468394ec8SAlexander V. Chernikov }; 38568394ec8SAlexander V. Chernikov 386c187c1fbSAlexander V. Chernikov /* Macro for working with various counters */ 3877e767c79SAlexander V. Chernikov #define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \ 3887e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr, 1); \ 3897e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr + 1, _bytes); \ 3907e767c79SAlexander V. Chernikov if ((_cntr)->timestamp != time_uptime) \ 3917e767c79SAlexander V. Chernikov (_cntr)->timestamp = time_uptime; \ 3927e767c79SAlexander V. Chernikov } while (0) 3937e767c79SAlexander V. Chernikov 3947e767c79SAlexander V. Chernikov #define IPFW_INC_DYN_COUNTER(_cntr, _bytes) do { \ 3957e767c79SAlexander V. Chernikov (_cntr)->pcnt++; \ 3967e767c79SAlexander V. Chernikov (_cntr)->bcnt += _bytes; \ 3977e767c79SAlexander V. Chernikov } while (0) 3987e767c79SAlexander V. Chernikov 3997e767c79SAlexander V. Chernikov #define IPFW_ZERO_RULE_COUNTER(_cntr) do { \ 4007e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr); \ 4017e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr + 1); \ 4027e767c79SAlexander V. Chernikov (_cntr)->timestamp = 0; \ 4037e767c79SAlexander V. Chernikov } while (0) 4047e767c79SAlexander V. Chernikov 4057e767c79SAlexander V. Chernikov #define IPFW_ZERO_DYN_COUNTER(_cntr) do { \ 4067e767c79SAlexander V. Chernikov (_cntr)->pcnt = 0; \ 4077e767c79SAlexander V. Chernikov (_cntr)->bcnt = 0; \ 4087e767c79SAlexander V. Chernikov } while (0) 4097e767c79SAlexander V. Chernikov 4100cba2b28SAlexander V. Chernikov #define TARG_VAL(ch, k, f) ((struct table_value *)((ch)->valuestate))[k].f 4110cba2b28SAlexander V. Chernikov #define IP_FW_ARG_TABLEARG(ch, a, f) \ 4120cba2b28SAlexander V. Chernikov (((a) == IP_FW_TARG) ? TARG_VAL(ch, tablearg, f) : (a)) 4133b3a8eb9SGleb Smirnoff /* 4143b3a8eb9SGleb Smirnoff * The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c 4153b3a8eb9SGleb Smirnoff * so the variable and the macros must be here. 4163b3a8eb9SGleb Smirnoff */ 4173b3a8eb9SGleb Smirnoff 418ccba94b8SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 4193b3a8eb9SGleb Smirnoff #define IPFW_LOCK_INIT(_chain) do { \ 4203b3a8eb9SGleb Smirnoff rw_init(&(_chain)->rwmtx, "IPFW static rules"); \ 4213b3a8eb9SGleb Smirnoff rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 4223b3a8eb9SGleb Smirnoff } while (0) 4233b3a8eb9SGleb Smirnoff 4243b3a8eb9SGleb Smirnoff #define IPFW_LOCK_DESTROY(_chain) do { \ 4253b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->rwmtx); \ 4263b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->uh_lock); \ 4273b3a8eb9SGleb Smirnoff } while (0) 4283b3a8eb9SGleb Smirnoff 4295d0cd926SAlexander V. Chernikov #define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED) 4303b3a8eb9SGleb Smirnoff #define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED) 4313b3a8eb9SGleb Smirnoff 432ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER 4333b3a8eb9SGleb Smirnoff #define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx) 4343b3a8eb9SGleb Smirnoff #define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx) 4353b3a8eb9SGleb Smirnoff #define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx) 4363b3a8eb9SGleb Smirnoff #define IPFW_WUNLOCK(p) rw_wunlock(&(p)->rwmtx) 43793bb4f9eSAndrey V. Elsukov #define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) 43893bb4f9eSAndrey V. Elsukov #define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) 439ccba94b8SAlexander V. Chernikov #else /* FreeBSD */ 440ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_INIT(_chain) do { \ 441ccba94b8SAlexander V. Chernikov rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 442ccba94b8SAlexander V. Chernikov } while (0) 443ccba94b8SAlexander V. Chernikov 444ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_DESTROY(_chain) do { \ 445ccba94b8SAlexander V. Chernikov rw_destroy(&(_chain)->uh_lock); \ 446ccba94b8SAlexander V. Chernikov } while (0) 447ccba94b8SAlexander V. Chernikov 44888d950a6SAndrey V. Elsukov #define IPFW_RLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_RLOCKED) 44988d950a6SAndrey V. Elsukov #define IPFW_WLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_WLOCKED) 450ccba94b8SAlexander V. Chernikov 451ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER struct rm_priotracker _tracker 45288d950a6SAndrey V. Elsukov #define IPFW_RLOCK(p) rm_rlock(&V_pfil_lock, &_tracker) 45388d950a6SAndrey V. Elsukov #define IPFW_RUNLOCK(p) rm_runlock(&V_pfil_lock, &_tracker) 45488d950a6SAndrey V. Elsukov #define IPFW_WLOCK(p) rm_wlock(&V_pfil_lock) 45588d950a6SAndrey V. Elsukov #define IPFW_WUNLOCK(p) rm_wunlock(&V_pfil_lock) 45688d950a6SAndrey V. Elsukov #define IPFW_PF_RLOCK(p) 45788d950a6SAndrey V. Elsukov #define IPFW_PF_RUNLOCK(p) 458ccba94b8SAlexander V. Chernikov #endif 4593b3a8eb9SGleb Smirnoff 4602e089d5cSAlexander V. Chernikov #define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED) 4612e089d5cSAlexander V. Chernikov #define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED) 4620caab009SAlexander V. Chernikov #define IPFW_UH_UNLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_UNLOCKED) 4632e089d5cSAlexander V. Chernikov 4643b3a8eb9SGleb Smirnoff #define IPFW_UH_RLOCK(p) rw_rlock(&(p)->uh_lock) 4653b3a8eb9SGleb Smirnoff #define IPFW_UH_RUNLOCK(p) rw_runlock(&(p)->uh_lock) 4663b3a8eb9SGleb Smirnoff #define IPFW_UH_WLOCK(p) rw_wlock(&(p)->uh_lock) 4673b3a8eb9SGleb Smirnoff #define IPFW_UH_WUNLOCK(p) rw_wunlock(&(p)->uh_lock) 4683b3a8eb9SGleb Smirnoff 469b074b7bbSAlexander V. Chernikov struct obj_idx { 470b074b7bbSAlexander V. Chernikov uint16_t uidx; /* internal index supplied by userland */ 471b074b7bbSAlexander V. Chernikov uint16_t kidx; /* kernel object index */ 472b074b7bbSAlexander V. Chernikov uint16_t off; /* tlv offset from rule end in 4-byte words */ 4730468c5baSAlexander V. Chernikov uint8_t spare; 474b074b7bbSAlexander V. Chernikov uint8_t type; /* object type within its category */ 475b074b7bbSAlexander V. Chernikov }; 476b074b7bbSAlexander V. Chernikov 477b074b7bbSAlexander V. Chernikov struct rule_check_info { 4783a845e10SAlexander V. Chernikov uint16_t flags; /* rule-specific check flags */ 47974b22066SAlexander V. Chernikov uint16_t object_opcodes; /* num of opcodes referencing objects */ 4807e767c79SAlexander V. Chernikov uint16_t urule_numoff; /* offset of rulenum in bytes */ 4817e767c79SAlexander V. Chernikov uint8_t version; /* rule version */ 4823a845e10SAlexander V. Chernikov uint8_t spare; 4836c2997ffSAlexander V. Chernikov ipfw_obj_ctlv *ctlv; /* name TLV containter */ 484b074b7bbSAlexander V. Chernikov struct ip_fw *krule; /* resulting rule pointer */ 4857e767c79SAlexander V. Chernikov caddr_t urule; /* original rule pointer */ 486b074b7bbSAlexander V. Chernikov struct obj_idx obuf[8]; /* table references storage */ 487b074b7bbSAlexander V. Chernikov }; 488b074b7bbSAlexander V. Chernikov 4897e767c79SAlexander V. Chernikov /* Legacy interface support */ 4907e767c79SAlexander V. Chernikov /* 4917e767c79SAlexander V. Chernikov * FreeBSD 8 export rule format 4927e767c79SAlexander V. Chernikov */ 4937e767c79SAlexander V. Chernikov struct ip_fw_rule0 { 4947e767c79SAlexander V. Chernikov struct ip_fw *x_next; /* linked list of rules */ 4957e767c79SAlexander V. Chernikov struct ip_fw *next_rule; /* ptr to next [skipto] rule */ 4967e767c79SAlexander V. Chernikov /* 'next_rule' is used to pass up 'set_disable' status */ 4977e767c79SAlexander V. Chernikov 4987e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 4997e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 5007e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 5017e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 5027e767c79SAlexander V. Chernikov uint8_t _pad; /* padding */ 5037e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 5047e767c79SAlexander V. Chernikov 5057e767c79SAlexander V. Chernikov /* These fields are present in all rules. */ 5067e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5077e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5087e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5097e767c79SAlexander V. Chernikov 5107e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 5117e767c79SAlexander V. Chernikov }; 5127e767c79SAlexander V. Chernikov 5137e767c79SAlexander V. Chernikov struct ip_fw_bcounter0 { 5147e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5157e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5167e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5177e767c79SAlexander V. Chernikov }; 5187e767c79SAlexander V. Chernikov 5197e767c79SAlexander V. Chernikov /* Kernel rule length */ 5207e767c79SAlexander V. Chernikov /* 5217e767c79SAlexander V. Chernikov * RULE _K_ SIZE _V_ -> 5227e767c79SAlexander V. Chernikov * get kernel size from userland rool version _V_. 5237e767c79SAlexander V. Chernikov * RULE _U_ SIZE _V_ -> 5247e767c79SAlexander V. Chernikov * get user size version _V_ from kernel rule 5257e767c79SAlexander V. Chernikov * RULESIZE _V_ -> 5267e767c79SAlexander V. Chernikov * get user size rule length 5277e767c79SAlexander V. Chernikov */ 5287e767c79SAlexander V. Chernikov /* FreeBSD8 <> current kernel format */ 5297e767c79SAlexander V. Chernikov #define RULEUSIZE0(r) (sizeof(struct ip_fw_rule0) + (r)->cmd_len * 4 - 4) 5307e767c79SAlexander V. Chernikov #define RULEKSIZE0(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5317e767c79SAlexander V. Chernikov /* FreeBSD11 <> current kernel format */ 5327e767c79SAlexander V. Chernikov #define RULEUSIZE1(r) (roundup2(sizeof(struct ip_fw_rule) + \ 5337e767c79SAlexander V. Chernikov (r)->cmd_len * 4 - 4, 8)) 5347e767c79SAlexander V. Chernikov #define RULEKSIZE1(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5357e767c79SAlexander V. Chernikov 53674b22066SAlexander V. Chernikov /* 53774b22066SAlexander V. Chernikov * Tables/Objects index rewriting code 53874b22066SAlexander V. Chernikov */ 53974b22066SAlexander V. Chernikov 54074b22066SAlexander V. Chernikov /* Default and maximum number of ipfw tables/objects. */ 54174b22066SAlexander V. Chernikov #define IPFW_TABLES_MAX 65536 54274b22066SAlexander V. Chernikov #define IPFW_TABLES_DEFAULT 128 54374b22066SAlexander V. Chernikov #define IPFW_OBJECTS_MAX 65536 5442acdf79fSAndrey V. Elsukov #define IPFW_OBJECTS_DEFAULT 1024 54574b22066SAlexander V. Chernikov 54674b22066SAlexander V. Chernikov #define CHAIN_TO_SRV(ch) ((ch)->srvmap) 5472acdf79fSAndrey V. Elsukov #define SRV_OBJECT(ch, idx) ((ch)->srvstate[(idx)]) 54874b22066SAlexander V. Chernikov 54974b22066SAlexander V. Chernikov struct tid_info { 55074b22066SAlexander V. Chernikov uint32_t set; /* table set */ 55174b22066SAlexander V. Chernikov uint16_t uidx; /* table index */ 55274b22066SAlexander V. Chernikov uint8_t type; /* table type */ 55374b22066SAlexander V. Chernikov uint8_t atype; 55474b22066SAlexander V. Chernikov uint8_t spare; 55574b22066SAlexander V. Chernikov int tlen; /* Total TLV size block */ 55674b22066SAlexander V. Chernikov void *tlvs; /* Pointer to first TLV */ 55774b22066SAlexander V. Chernikov }; 55874b22066SAlexander V. Chernikov 55974b22066SAlexander V. Chernikov /* 56074b22066SAlexander V. Chernikov * Classifier callback. Checks if @cmd opcode contains kernel object reference. 56174b22066SAlexander V. Chernikov * If true, returns its index and type. 56274b22066SAlexander V. Chernikov * Returns 0 if match is found, 1 overwise. 56374b22066SAlexander V. Chernikov */ 56474b22066SAlexander V. Chernikov typedef int (ipfw_obj_rw_cl)(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype); 56574b22066SAlexander V. Chernikov /* 56674b22066SAlexander V. Chernikov * Updater callback. Sets kernel object reference index to @puidx 56774b22066SAlexander V. Chernikov */ 56874b22066SAlexander V. Chernikov typedef void (ipfw_obj_rw_upd)(ipfw_insn *cmd, uint16_t puidx); 56974b22066SAlexander V. Chernikov /* 57074b22066SAlexander V. Chernikov * Finder callback. Tries to find named object by name (specified via @ti). 57174b22066SAlexander V. Chernikov * Stores found named object pointer in @pno. 57274b22066SAlexander V. Chernikov * If object was not found, NULL is stored. 57374b22066SAlexander V. Chernikov * 57474b22066SAlexander V. Chernikov * Return 0 if input data was valid. 57574b22066SAlexander V. Chernikov */ 57674b22066SAlexander V. Chernikov typedef int (ipfw_obj_fname_cb)(struct ip_fw_chain *ch, 57774b22066SAlexander V. Chernikov struct tid_info *ti, struct named_object **pno); 57874b22066SAlexander V. Chernikov /* 57974b22066SAlexander V. Chernikov * Another finder callback. Tries to findex named object by kernel index. 58074b22066SAlexander V. Chernikov * 58174b22066SAlexander V. Chernikov * Returns pointer to named object or NULL. 58274b22066SAlexander V. Chernikov */ 58374b22066SAlexander V. Chernikov typedef struct named_object *(ipfw_obj_fidx_cb)(struct ip_fw_chain *ch, 58474b22066SAlexander V. Chernikov uint16_t kidx); 58574b22066SAlexander V. Chernikov /* 58674b22066SAlexander V. Chernikov * Object creator callback. Tries to create object specified by @ti. 58774b22066SAlexander V. Chernikov * Stores newly-allocated object index in @pkidx. 58874b22066SAlexander V. Chernikov * 58974b22066SAlexander V. Chernikov * Returns 0 on success. 59074b22066SAlexander V. Chernikov */ 59174b22066SAlexander V. Chernikov typedef int (ipfw_obj_create_cb)(struct ip_fw_chain *ch, struct tid_info *ti, 59274b22066SAlexander V. Chernikov uint16_t *pkidx); 5931cf09efeSAndrey V. Elsukov /* 5941cf09efeSAndrey V. Elsukov * Object destroy callback. Intended to free resources allocated by 5951cf09efeSAndrey V. Elsukov * create_object callback. 5961cf09efeSAndrey V. Elsukov */ 5971cf09efeSAndrey V. Elsukov typedef void (ipfw_obj_destroy_cb)(struct ip_fw_chain *ch, 5981cf09efeSAndrey V. Elsukov struct named_object *no); 5992685841bSAndrey V. Elsukov /* 6002685841bSAndrey V. Elsukov * Sets handler callback. Handles moving and swaping set of named object. 6012685841bSAndrey V. Elsukov * SWAP_ALL moves all named objects from set `set' to `new_set' and vise versa; 6022685841bSAndrey V. Elsukov * TEST_ALL checks that there aren't any named object with conflicting names; 6032685841bSAndrey V. Elsukov * MOVE_ALL moves all named objects from set `set' to `new_set'; 6042685841bSAndrey V. Elsukov * COUNT_ONE used to count number of references used by object with kidx `set'; 6052685841bSAndrey V. Elsukov * TEST_ONE checks that named object with kidx `set' can be moved to `new_set`; 6062685841bSAndrey V. Elsukov * MOVE_ONE moves named object with kidx `set' to set `new_set'. 6072685841bSAndrey V. Elsukov */ 6082685841bSAndrey V. Elsukov enum ipfw_sets_cmd { 6092685841bSAndrey V. Elsukov SWAP_ALL = 0, TEST_ALL, MOVE_ALL, COUNT_ONE, TEST_ONE, MOVE_ONE 6102685841bSAndrey V. Elsukov }; 6112685841bSAndrey V. Elsukov typedef int (ipfw_obj_sets_cb)(struct ip_fw_chain *ch, 6122685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 6132685841bSAndrey V. Elsukov 61474b22066SAlexander V. Chernikov 61574b22066SAlexander V. Chernikov struct opcode_obj_rewrite { 61674b22066SAlexander V. Chernikov uint32_t opcode; /* Opcode to act upon */ 61774b22066SAlexander V. Chernikov uint32_t etlv; /* Relevant export TLV id */ 61874b22066SAlexander V. Chernikov ipfw_obj_rw_cl *classifier; /* Check if rewrite is needed */ 61974b22066SAlexander V. Chernikov ipfw_obj_rw_upd *update; /* update cmd with new value */ 62074b22066SAlexander V. Chernikov ipfw_obj_fname_cb *find_byname; /* Find named object by name */ 62174b22066SAlexander V. Chernikov ipfw_obj_fidx_cb *find_bykidx; /* Find named object by kidx */ 62274b22066SAlexander V. Chernikov ipfw_obj_create_cb *create_object; /* Create named object */ 6231cf09efeSAndrey V. Elsukov ipfw_obj_destroy_cb *destroy_object;/* Destroy named object */ 6242685841bSAndrey V. Elsukov ipfw_obj_sets_cb *manage_sets; /* Swap or move sets */ 62574b22066SAlexander V. Chernikov }; 62674b22066SAlexander V. Chernikov 62774b22066SAlexander V. Chernikov #define IPFW_ADD_OBJ_REWRITER(f, c) do { \ 62874b22066SAlexander V. Chernikov if ((f) != 0) \ 62974b22066SAlexander V. Chernikov ipfw_add_obj_rewriter(c, \ 63074b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 63174b22066SAlexander V. Chernikov } while(0) 63274b22066SAlexander V. Chernikov #define IPFW_DEL_OBJ_REWRITER(l, c) do { \ 63374b22066SAlexander V. Chernikov if ((l) != 0) \ 63474b22066SAlexander V. Chernikov ipfw_del_obj_rewriter(c, \ 63574b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 63674b22066SAlexander V. Chernikov } while(0) 6377e767c79SAlexander V. Chernikov 63868394ec8SAlexander V. Chernikov /* In ip_fw_iface.c */ 63968394ec8SAlexander V. Chernikov int ipfw_iface_init(void); 64068394ec8SAlexander V. Chernikov void ipfw_iface_destroy(void); 64168394ec8SAlexander V. Chernikov void vnet_ipfw_iface_destroy(struct ip_fw_chain *ch); 64268394ec8SAlexander V. Chernikov int ipfw_iface_ref(struct ip_fw_chain *ch, char *name, 64368394ec8SAlexander V. Chernikov struct ipfw_ifc *ic); 64468394ec8SAlexander V. Chernikov void ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 64568394ec8SAlexander V. Chernikov void ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 64668394ec8SAlexander V. Chernikov void ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 64768394ec8SAlexander V. Chernikov 6483b3a8eb9SGleb Smirnoff /* In ip_fw_sockopt.c */ 649d5eb80cbSAlexander V. Chernikov void ipfw_init_skipto_cache(struct ip_fw_chain *chain); 650d5eb80cbSAlexander V. Chernikov void ipfw_destroy_skipto_cache(struct ip_fw_chain *chain); 6513b3a8eb9SGleb Smirnoff int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id); 652b429d43cSAlexander V. Chernikov int ipfw_ctl3(struct sockopt *sopt); 6533b3a8eb9SGleb Smirnoff int ipfw_chk(struct ip_fw_args *args); 6547143bb76SAndrey V. Elsukov int ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule, 6557143bb76SAndrey V. Elsukov int locked); 656030b184fSAlexander V. Chernikov void ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head, 657030b184fSAlexander V. Chernikov struct ip_fw *rule); 6583b3a8eb9SGleb Smirnoff void ipfw_reap_rules(struct ip_fw *head); 6597e767c79SAlexander V. Chernikov void ipfw_init_counters(void); 6607e767c79SAlexander V. Chernikov void ipfw_destroy_counters(void); 6617e767c79SAlexander V. Chernikov struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize); 662a73d728dSAlexander V. Chernikov int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt); 6633b3a8eb9SGleb Smirnoff 6646b988f3aSAlexander V. Chernikov typedef int (sopt_handler_f)(struct ip_fw_chain *ch, 6656b988f3aSAlexander V. Chernikov ip_fw3_opheader *op3, struct sockopt_data *sd); 6666b988f3aSAlexander V. Chernikov struct ipfw_sopt_handler { 6676b988f3aSAlexander V. Chernikov uint16_t opcode; 6686b988f3aSAlexander V. Chernikov uint8_t version; 6696b988f3aSAlexander V. Chernikov uint8_t dir; 6706b988f3aSAlexander V. Chernikov sopt_handler_f *handler; 6716b988f3aSAlexander V. Chernikov uint64_t refcnt; 6726b988f3aSAlexander V. Chernikov }; 6736b988f3aSAlexander V. Chernikov #define HDIR_SET 0x01 /* Handler is used to set some data */ 6746b988f3aSAlexander V. Chernikov #define HDIR_GET 0x02 /* Handler is used to retrieve data */ 6756b988f3aSAlexander V. Chernikov #define HDIR_BOTH HDIR_GET|HDIR_SET 6766b988f3aSAlexander V. Chernikov 6776b988f3aSAlexander V. Chernikov void ipfw_init_sopt_handler(void); 6786b988f3aSAlexander V. Chernikov void ipfw_destroy_sopt_handler(void); 6796b988f3aSAlexander V. Chernikov void ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6806b988f3aSAlexander V. Chernikov int ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6812d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed); 6822d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); 6836b988f3aSAlexander V. Chernikov #define IPFW_ADD_SOPT_HANDLER(f, c) do { \ 6846b988f3aSAlexander V. Chernikov if ((f) != 0) \ 6856b988f3aSAlexander V. Chernikov ipfw_add_sopt_handler(c, \ 6866b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 6876b988f3aSAlexander V. Chernikov } while(0) 6886b988f3aSAlexander V. Chernikov #define IPFW_DEL_SOPT_HANDLER(l, c) do { \ 6896b988f3aSAlexander V. Chernikov if ((l) != 0) \ 6906b988f3aSAlexander V. Chernikov ipfw_del_sopt_handler(c, \ 6916b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 6926b988f3aSAlexander V. Chernikov } while(0) 6932d99a349SAlexander V. Chernikov 69474b22066SAlexander V. Chernikov struct namedobj_instance; 695b309f085SAndrey V. Elsukov typedef int (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, 696b074b7bbSAlexander V. Chernikov void *arg); 6972acdf79fSAndrey V. Elsukov typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, 69813263632SAlexander V. Chernikov uint32_t kopt); 6992acdf79fSAndrey V. Elsukov typedef int (objhash_cmp_f)(struct named_object *no, const void *key, 7002acdf79fSAndrey V. Elsukov uint32_t kopt); 701b074b7bbSAlexander V. Chernikov struct namedobj_instance *ipfw_objhash_create(uint32_t items); 702b074b7bbSAlexander V. Chernikov void ipfw_objhash_destroy(struct namedobj_instance *); 703b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks); 7049f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, 7059f7d47b0SAlexander V. Chernikov void **idx, int *blocks); 7069f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, 707b074b7bbSAlexander V. Chernikov void **idx, int *blocks); 708b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_free(void *idx, int blocks); 70913263632SAlexander V. Chernikov void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f); 710b074b7bbSAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni, 711b074b7bbSAlexander V. Chernikov uint32_t set, char *name); 71274b22066SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, 7132acdf79fSAndrey V. Elsukov uint32_t set, uint32_t type, const char *name); 714ac35ff17SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, 715ac35ff17SAlexander V. Chernikov uint16_t idx); 7169490a627SAlexander V. Chernikov int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, 7179490a627SAlexander V. Chernikov struct named_object *b); 718b074b7bbSAlexander V. Chernikov void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); 719b074b7bbSAlexander V. Chernikov void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); 7209f7d47b0SAlexander V. Chernikov uint32_t ipfw_objhash_count(struct namedobj_instance *ni); 7212685841bSAndrey V. Elsukov uint32_t ipfw_objhash_count_type(struct namedobj_instance *ni, uint16_t type); 722b309f085SAndrey V. Elsukov int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, 723b074b7bbSAlexander V. Chernikov void *arg); 7242685841bSAndrey V. Elsukov int ipfw_objhash_foreach_type(struct namedobj_instance *ni, objhash_cb_t *f, 7252685841bSAndrey V. Elsukov void *arg, uint16_t type); 726ac35ff17SAlexander V. Chernikov int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); 727ac35ff17SAlexander V. Chernikov int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); 72813263632SAlexander V. Chernikov void ipfw_objhash_set_funcs(struct namedobj_instance *ni, 72913263632SAlexander V. Chernikov objhash_hash_f *hash_f, objhash_cmp_f *cmp_f); 7302acdf79fSAndrey V. Elsukov int ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, 7312acdf79fSAndrey V. Elsukov uint32_t etlv, struct named_object **pno); 7325dc5a0e0SAndrey V. Elsukov void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); 7332df1a11fSAndrey V. Elsukov ipfw_obj_ntlv *ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, 7342df1a11fSAndrey V. Elsukov uint32_t etlv); 73574b22066SAlexander V. Chernikov void ipfw_init_obj_rewriter(void); 73674b22066SAlexander V. Chernikov void ipfw_destroy_obj_rewriter(void); 73774b22066SAlexander V. Chernikov void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 73874b22066SAlexander V. Chernikov int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 73974b22066SAlexander V. Chernikov 74074b22066SAlexander V. Chernikov int create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, 74174b22066SAlexander V. Chernikov struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti); 74274b22066SAlexander V. Chernikov void update_opcode_kidx(ipfw_insn *cmd, uint16_t idx); 74374b22066SAlexander V. Chernikov int classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx); 74474b22066SAlexander V. Chernikov void ipfw_init_srv(struct ip_fw_chain *ch); 74574b22066SAlexander V. Chernikov void ipfw_destroy_srv(struct ip_fw_chain *ch); 746f81431ccSAndrey V. Elsukov int ipfw_check_object_name_generic(const char *name); 7472685841bSAndrey V. Elsukov int ipfw_obj_manage_sets(struct namedobj_instance *ni, uint16_t type, 7482685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 749b074b7bbSAlexander V. Chernikov 7502acdf79fSAndrey V. Elsukov /* In ip_fw_eaction.c */ 7512acdf79fSAndrey V. Elsukov typedef int (ipfw_eaction_t)(struct ip_fw_chain *ch, struct ip_fw_args *args, 7522acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 7532acdf79fSAndrey V. Elsukov int ipfw_eaction_init(struct ip_fw_chain *ch, int first); 7542acdf79fSAndrey V. Elsukov void ipfw_eaction_uninit(struct ip_fw_chain *ch, int last); 7552acdf79fSAndrey V. Elsukov 7562acdf79fSAndrey V. Elsukov uint16_t ipfw_add_eaction(struct ip_fw_chain *ch, ipfw_eaction_t handler, 7572acdf79fSAndrey V. Elsukov const char *name); 7582acdf79fSAndrey V. Elsukov int ipfw_del_eaction(struct ip_fw_chain *ch, uint16_t eaction_id); 7592acdf79fSAndrey V. Elsukov int ipfw_run_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, 7602acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 7612acdf79fSAndrey V. Elsukov 7623b3a8eb9SGleb Smirnoff /* In ip_fw_table.c */ 7639f7d47b0SAlexander V. Chernikov struct table_info; 7649f7d47b0SAlexander V. Chernikov 7659f7d47b0SAlexander V. Chernikov typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen, 7669f7d47b0SAlexander V. Chernikov uint32_t *val); 7679f7d47b0SAlexander V. Chernikov 76854e5669dSAndrey V. Elsukov int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, 76954e5669dSAndrey V. Elsukov void *paddr, uint32_t *val); 7706951cecfSAndrey V. Elsukov struct named_object *ipfw_objhash_lookup_table_kidx(struct ip_fw_chain *ch, 7716951cecfSAndrey V. Elsukov uint16_t kidx); 7726951cecfSAndrey V. Elsukov int ipfw_ref_table(struct ip_fw_chain *ch, ipfw_obj_ntlv *ntlv, uint16_t *kidx); 7736951cecfSAndrey V. Elsukov void ipfw_unref_table(struct ip_fw_chain *ch, uint16_t kidx); 7746b988f3aSAlexander V. Chernikov int ipfw_init_tables(struct ip_fw_chain *ch, int first); 7753b3a8eb9SGleb Smirnoff int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables); 776a73d728dSAlexander V. Chernikov int ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int nsets); 7776b988f3aSAlexander V. Chernikov void ipfw_destroy_tables(struct ip_fw_chain *ch, int last); 7789f7d47b0SAlexander V. Chernikov 7793b3a8eb9SGleb Smirnoff /* In ip_fw_nat.c -- XXX to be moved to ip_var.h */ 7803b3a8eb9SGleb Smirnoff 7813b3a8eb9SGleb Smirnoff extern struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int); 7823b3a8eb9SGleb Smirnoff 7833b3a8eb9SGleb Smirnoff typedef int ipfw_nat_t(struct ip_fw_args *, struct cfg_nat *, struct mbuf *); 7843b3a8eb9SGleb Smirnoff typedef int ipfw_nat_cfg_t(struct sockopt *); 7853b3a8eb9SGleb Smirnoff 7868856400bSMikolaj Golub VNET_DECLARE(int, ipfw_nat_ready); 7878856400bSMikolaj Golub #define V_ipfw_nat_ready VNET(ipfw_nat_ready) 7888856400bSMikolaj Golub #define IPFW_NAT_LOADED (V_ipfw_nat_ready) 7893b3a8eb9SGleb Smirnoff 7908856400bSMikolaj Golub extern ipfw_nat_t *ipfw_nat_ptr; 7913b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_cfg_ptr; 7923b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_del_ptr; 7933b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr; 7943b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; 7953b3a8eb9SGleb Smirnoff 796af9aa0a8SAndrey V. Elsukov /* Helper functions for IP checksum adjustment */ 797af9aa0a8SAndrey V. Elsukov static __inline uint16_t 798af9aa0a8SAndrey V. Elsukov cksum_add(uint16_t sum, uint16_t a) 799af9aa0a8SAndrey V. Elsukov { 800af9aa0a8SAndrey V. Elsukov uint16_t res; 801af9aa0a8SAndrey V. Elsukov 802af9aa0a8SAndrey V. Elsukov res = sum + a; 803af9aa0a8SAndrey V. Elsukov return (res + (res < a)); 804af9aa0a8SAndrey V. Elsukov } 805af9aa0a8SAndrey V. Elsukov 806af9aa0a8SAndrey V. Elsukov static __inline uint16_t 807af9aa0a8SAndrey V. Elsukov cksum_adjust(uint16_t oldsum, uint16_t old, uint16_t new) 808af9aa0a8SAndrey V. Elsukov { 809af9aa0a8SAndrey V. Elsukov 810af9aa0a8SAndrey V. Elsukov return (~cksum_add(cksum_add(~oldsum, ~old), new)); 811af9aa0a8SAndrey V. Elsukov } 812af9aa0a8SAndrey V. Elsukov 8133b3a8eb9SGleb Smirnoff #endif /* _KERNEL */ 8143b3a8eb9SGleb Smirnoff #endif /* _IPFW2_PRIVATE_H */ 815