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 { 86*1cdf23bcSAndrey V. Elsukov uint32_t flags; 87*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_ETHER 0x0001 /* has valid ethernet header */ 88*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_NH4 0x0002 /* has IPv4 next hop in hopstore */ 89*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_NH6 0x0004 /* has IPv6 next hop in hopstore */ 90*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_NH4PTR 0x0008 /* has IPv4 next hop in next_hop */ 91*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_NH6PTR 0x0010 /* has IPv6 next hop in next_hop6 */ 92*1cdf23bcSAndrey V. Elsukov #define IPFW_ARGS_REF 0x0020 /* has valid ipfw_rule_ref */ 933b3a8eb9SGleb Smirnoff /* 943b3a8eb9SGleb Smirnoff * On return, it points to the matching rule. 953b3a8eb9SGleb Smirnoff * On entry, rule.slot > 0 means the info is valid and 963b3a8eb9SGleb Smirnoff * contains the starting rule for an ipfw search. 973b3a8eb9SGleb Smirnoff * If chain_id == chain->id && slot >0 then jump to that slot. 983b3a8eb9SGleb Smirnoff * Otherwise, we locate the first rule >= rulenum:rule_id 993b3a8eb9SGleb Smirnoff */ 1003b3a8eb9SGleb Smirnoff struct ipfw_rule_ref rule; /* match/restart info */ 1013b3a8eb9SGleb Smirnoff 102*1cdf23bcSAndrey V. Elsukov struct ifnet *oif; /* output interface */ 1033b3a8eb9SGleb Smirnoff struct inpcb *inp; 104*1cdf23bcSAndrey V. Elsukov union { 105*1cdf23bcSAndrey V. Elsukov /* 106*1cdf23bcSAndrey V. Elsukov * We don't support forwarding on layer2, thus we can 107*1cdf23bcSAndrey V. Elsukov * keep eh pointer in this union. 108*1cdf23bcSAndrey V. Elsukov * next_hop[6] pointers can be used to point to next hop 109*1cdf23bcSAndrey V. Elsukov * stored in rule's opcode to avoid copying into hopstore. 110*1cdf23bcSAndrey V. Elsukov * Also, it is expected that all 0x1-0x10 flags are mutually 111*1cdf23bcSAndrey V. Elsukov * exclusive. 112*1cdf23bcSAndrey V. Elsukov */ 113*1cdf23bcSAndrey V. Elsukov struct ether_header *eh; /* for bridged packets */ 114*1cdf23bcSAndrey V. Elsukov struct sockaddr_in *next_hop; 115*1cdf23bcSAndrey V. Elsukov struct sockaddr_in6 *next_hop6; 116*1cdf23bcSAndrey V. Elsukov /* ipfw next hop storage */ 1172530ed9eSAndrey V. Elsukov struct sockaddr_in hopstore; 118*1cdf23bcSAndrey V. Elsukov struct ip_fw_nh6 { 119*1cdf23bcSAndrey V. Elsukov struct in6_addr sin6_addr; 120*1cdf23bcSAndrey V. Elsukov uint32_t sin6_scope_id; 121*1cdf23bcSAndrey V. Elsukov uint16_t sin6_port; 122*1cdf23bcSAndrey V. Elsukov } hopstore6; 1232530ed9eSAndrey V. Elsukov }; 124*1cdf23bcSAndrey V. Elsukov 125*1cdf23bcSAndrey V. Elsukov struct mbuf *m; /* the mbuf chain */ 126*1cdf23bcSAndrey V. Elsukov struct ipfw_flow_id f_id; /* grabbed from IP header */ 1273b3a8eb9SGleb Smirnoff }; 1283b3a8eb9SGleb Smirnoff 1293b3a8eb9SGleb Smirnoff MALLOC_DECLARE(M_IPFW); 1303b3a8eb9SGleb Smirnoff 1313b3a8eb9SGleb Smirnoff /* 1323b3a8eb9SGleb Smirnoff * Hooks sometime need to know the direction of the packet 1333b3a8eb9SGleb Smirnoff * (divert, dummynet, netgraph, ...) 1343b3a8eb9SGleb Smirnoff * We use a generic definition here, with bit0-1 indicating the 1353b3a8eb9SGleb Smirnoff * direction, bit 2 indicating layer2 or 3, bit 3-4 indicating the 1363b3a8eb9SGleb Smirnoff * specific protocol 1373b3a8eb9SGleb Smirnoff * indicating the protocol (if necessary) 1383b3a8eb9SGleb Smirnoff */ 1393b3a8eb9SGleb Smirnoff enum { 1403b3a8eb9SGleb Smirnoff DIR_MASK = 0x3, 1413b3a8eb9SGleb Smirnoff DIR_OUT = 0, 1423b3a8eb9SGleb Smirnoff DIR_IN = 1, 1433b3a8eb9SGleb Smirnoff DIR_FWD = 2, 1443b3a8eb9SGleb Smirnoff DIR_DROP = 3, 1453b3a8eb9SGleb Smirnoff PROTO_LAYER2 = 0x4, /* set for layer 2 */ 1463b3a8eb9SGleb Smirnoff /* PROTO_DEFAULT = 0, */ 1473b3a8eb9SGleb Smirnoff PROTO_IPV4 = 0x08, 1483b3a8eb9SGleb Smirnoff PROTO_IPV6 = 0x10, 1493b3a8eb9SGleb Smirnoff PROTO_IFB = 0x0c, /* layer2 + ifbridge */ 1503b3a8eb9SGleb Smirnoff /* PROTO_OLDBDG = 0x14, unused, old bridge */ 1513b3a8eb9SGleb Smirnoff }; 1523b3a8eb9SGleb Smirnoff 1533b3a8eb9SGleb Smirnoff /* wrapper for freeing a packet, in case we need to do more work */ 1543b3a8eb9SGleb Smirnoff #ifndef FREE_PKT 1553b3a8eb9SGleb Smirnoff #if defined(__linux__) || defined(_WIN32) 1563b3a8eb9SGleb Smirnoff #define FREE_PKT(m) netisr_dispatch(-1, m) 1573b3a8eb9SGleb Smirnoff #else 1583b3a8eb9SGleb Smirnoff #define FREE_PKT(m) m_freem(m) 1593b3a8eb9SGleb Smirnoff #endif 1603b3a8eb9SGleb Smirnoff #endif /* !FREE_PKT */ 1613b3a8eb9SGleb Smirnoff 1623b3a8eb9SGleb Smirnoff /* 1633b3a8eb9SGleb Smirnoff * Function definitions. 1643b3a8eb9SGleb Smirnoff */ 165cefe3d67SAndrey V. Elsukov int ipfw_chk(struct ip_fw_args *args); 166cefe3d67SAndrey V. Elsukov struct mbuf *ipfw_send_pkt(struct mbuf *, struct ipfw_flow_id *, 167cefe3d67SAndrey V. Elsukov u_int32_t, u_int32_t, int); 1683b3a8eb9SGleb Smirnoff 1693b3a8eb9SGleb Smirnoff /* attach (arg = 1) or detach (arg = 0) hooks */ 1703b3a8eb9SGleb Smirnoff int ipfw_attach_hooks(int); 1713b3a8eb9SGleb Smirnoff #ifdef NOTYET 1723b3a8eb9SGleb Smirnoff void ipfw_nat_destroy(void); 1733b3a8eb9SGleb Smirnoff #endif 1743b3a8eb9SGleb Smirnoff 1753b3a8eb9SGleb Smirnoff /* In ip_fw_log.c */ 1763b3a8eb9SGleb Smirnoff struct ip; 1770cba2b28SAlexander V. Chernikov struct ip_fw_chain; 178cefe3d67SAndrey V. Elsukov 17956132dccSAndrey V. Elsukov void ipfw_bpf_init(int); 18056132dccSAndrey V. Elsukov void ipfw_bpf_uninit(int); 18156132dccSAndrey V. Elsukov void ipfw_bpf_mtap2(void *, u_int, struct mbuf *); 1820cba2b28SAlexander V. Chernikov void ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 1830cba2b28SAlexander V. Chernikov struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif, 1840cba2b28SAlexander V. Chernikov u_short offset, uint32_t tablearg, struct ip *ip); 1853b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int64_t, norule_counter); 1863b3a8eb9SGleb Smirnoff #define V_norule_counter VNET(norule_counter) 1873b3a8eb9SGleb Smirnoff VNET_DECLARE(int, verbose_limit); 1883b3a8eb9SGleb Smirnoff #define V_verbose_limit VNET(verbose_limit) 1893b3a8eb9SGleb Smirnoff 1903b3a8eb9SGleb Smirnoff /* In ip_fw_dynamic.c */ 191cefe3d67SAndrey V. Elsukov struct sockopt_data; 1923b3a8eb9SGleb Smirnoff 1933b3a8eb9SGleb Smirnoff enum { /* result for matching dynamic rules */ 1943b3a8eb9SGleb Smirnoff MATCH_REVERSE = 0, 1953b3a8eb9SGleb Smirnoff MATCH_FORWARD, 1963b3a8eb9SGleb Smirnoff MATCH_NONE, 1973b3a8eb9SGleb Smirnoff MATCH_UNKNOWN, 1983b3a8eb9SGleb Smirnoff }; 1993b3a8eb9SGleb Smirnoff 2003b3a8eb9SGleb Smirnoff /* 201b99a6823SAndrey V. Elsukov * Macro to determine that we need to do or redo dynamic state lookup. 202b99a6823SAndrey V. Elsukov * direction == MATCH_UNKNOWN means that this is first lookup, then we need 203b99a6823SAndrey V. Elsukov * to do lookup. 204b99a6823SAndrey V. Elsukov * Otherwise check the state name, if previous lookup was for "any" name, 205b99a6823SAndrey V. Elsukov * this means there is no state with specific name. Thus no need to do 206b99a6823SAndrey V. Elsukov * lookup. If previous name was not "any", redo lookup for specific name. 207b99a6823SAndrey V. Elsukov */ 208b99a6823SAndrey V. Elsukov #define DYN_LOOKUP_NEEDED(p, cmd) \ 209b99a6823SAndrey V. Elsukov ((p)->direction == MATCH_UNKNOWN || \ 210b99a6823SAndrey V. Elsukov ((p)->kidx != 0 && (p)->kidx != (cmd)->arg1)) 211b99a6823SAndrey V. Elsukov #define DYN_INFO_INIT(p) do { \ 212b99a6823SAndrey V. Elsukov (p)->direction = MATCH_UNKNOWN; \ 213b99a6823SAndrey V. Elsukov (p)->kidx = 0; \ 214b99a6823SAndrey V. Elsukov } while (0) 215b99a6823SAndrey V. Elsukov struct ipfw_dyn_info { 216b99a6823SAndrey V. Elsukov uint16_t direction; /* match direction */ 217b99a6823SAndrey V. Elsukov uint16_t kidx; /* state name kidx */ 218b99a6823SAndrey V. Elsukov uint32_t hashval; /* hash value */ 219b99a6823SAndrey V. Elsukov uint32_t version; /* bucket version */ 220b99a6823SAndrey V. Elsukov uint32_t f_pos; 221b99a6823SAndrey V. Elsukov }; 2221719df1bSAndrey V. Elsukov int ipfw_dyn_install_state(struct ip_fw_chain *chain, struct ip_fw *rule, 223b99a6823SAndrey V. Elsukov const ipfw_insn_limit *cmd, const struct ip_fw_args *args, 224b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, struct ipfw_dyn_info *info, 225b99a6823SAndrey V. Elsukov uint32_t tablearg); 226b99a6823SAndrey V. Elsukov struct ip_fw *ipfw_dyn_lookup_state(const struct ip_fw_args *args, 227b99a6823SAndrey V. Elsukov const void *ulp, int pktlen, const ipfw_insn *cmd, 228b99a6823SAndrey V. Elsukov struct ipfw_dyn_info *info); 229b99a6823SAndrey V. Elsukov 230cefe3d67SAndrey V. Elsukov int ipfw_is_dyn_rule(struct ip_fw *rule); 231cefe3d67SAndrey V. Elsukov void ipfw_expire_dyn_states(struct ip_fw_chain *, ipfw_range_tlv *); 2322e089d5cSAlexander V. Chernikov void ipfw_get_dynamic(struct ip_fw_chain *chain, char **bp, const char *ep); 233563b5ab1SAlexander V. Chernikov int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd); 2343b3a8eb9SGleb Smirnoff 2352e089d5cSAlexander V. Chernikov void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */ 2363b3a8eb9SGleb Smirnoff void ipfw_dyn_uninit(int); /* per-vnet deinitialization */ 2373b3a8eb9SGleb Smirnoff int ipfw_dyn_len(void); 238cefe3d67SAndrey V. Elsukov uint32_t ipfw_dyn_get_count(uint32_t *, int *); 239cefe3d67SAndrey V. Elsukov void ipfw_dyn_reset_eaction(struct ip_fw_chain *ch, uint16_t eaction_id, 240cefe3d67SAndrey V. Elsukov uint16_t default_id, uint16_t instance_id); 2413b3a8eb9SGleb Smirnoff 2423b3a8eb9SGleb Smirnoff /* common variables */ 2433b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_one_pass); 2443b3a8eb9SGleb Smirnoff #define V_fw_one_pass VNET(fw_one_pass) 2453b3a8eb9SGleb Smirnoff 2463b3a8eb9SGleb Smirnoff VNET_DECLARE(int, fw_verbose); 2473b3a8eb9SGleb Smirnoff #define V_fw_verbose VNET(fw_verbose) 2483b3a8eb9SGleb Smirnoff 2493b3a8eb9SGleb Smirnoff VNET_DECLARE(struct ip_fw_chain, layer3_chain); 2503b3a8eb9SGleb Smirnoff #define V_layer3_chain VNET(layer3_chain) 2513b3a8eb9SGleb Smirnoff 25298eff10eSAlexander V. Chernikov VNET_DECLARE(int, ipfw_vnet_ready); 25398eff10eSAlexander V. Chernikov #define V_ipfw_vnet_ready VNET(ipfw_vnet_ready) 25498eff10eSAlexander V. Chernikov 2553b3a8eb9SGleb Smirnoff VNET_DECLARE(u_int32_t, set_disable); 2563b3a8eb9SGleb Smirnoff #define V_set_disable VNET(set_disable) 2573b3a8eb9SGleb Smirnoff 2583b3a8eb9SGleb Smirnoff VNET_DECLARE(int, autoinc_step); 2593b3a8eb9SGleb Smirnoff #define V_autoinc_step VNET(autoinc_step) 2603b3a8eb9SGleb Smirnoff 2613b3a8eb9SGleb Smirnoff VNET_DECLARE(unsigned int, fw_tables_max); 2623b3a8eb9SGleb Smirnoff #define V_fw_tables_max VNET(fw_tables_max) 2633b3a8eb9SGleb Smirnoff 264b074b7bbSAlexander V. Chernikov VNET_DECLARE(unsigned int, fw_tables_sets); 265b074b7bbSAlexander V. Chernikov #define V_fw_tables_sets VNET(fw_tables_sets) 266b074b7bbSAlexander V. Chernikov 267b074b7bbSAlexander V. Chernikov struct tables_config; 268b074b7bbSAlexander V. Chernikov 2697e767c79SAlexander V. Chernikov #ifdef _KERNEL 2707e767c79SAlexander V. Chernikov /* 2717e767c79SAlexander V. Chernikov * Here we have the structure representing an ipfw rule. 2727e767c79SAlexander V. Chernikov * 2737e767c79SAlexander V. Chernikov * It starts with a general area 2747e767c79SAlexander V. Chernikov * followed by an array of one or more instructions, which the code 2757e767c79SAlexander V. Chernikov * accesses as an array of 32-bit values. 2767e767c79SAlexander V. Chernikov * 2777e767c79SAlexander V. Chernikov * Given a rule pointer r: 2787e767c79SAlexander V. Chernikov * 2797e767c79SAlexander V. Chernikov * r->cmd is the start of the first instruction. 2807e767c79SAlexander V. Chernikov * ACTION_PTR(r) is the start of the first action (things to do 2817e767c79SAlexander V. Chernikov * once a rule matched). 2827e767c79SAlexander V. Chernikov */ 2837e767c79SAlexander V. Chernikov 2847e767c79SAlexander V. Chernikov struct ip_fw { 2857e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 2867e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 2877e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 2887e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 2897e767c79SAlexander V. Chernikov uint8_t flags; /* currently unused */ 2907e767c79SAlexander V. Chernikov counter_u64_t cntr; /* Pointer to rule counters */ 2917e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 2927e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 293030b184fSAlexander V. Chernikov uint32_t cached_id; /* used by jump_fast */ 294030b184fSAlexander V. Chernikov uint32_t cached_pos; /* used by jump_fast */ 295cefe3d67SAndrey V. Elsukov uint32_t refcnt; /* number of references */ 2967e767c79SAlexander V. Chernikov 297cefe3d67SAndrey V. Elsukov struct ip_fw *next; /* linked list of deleted rules */ 2987e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 2997e767c79SAlexander V. Chernikov }; 3007e767c79SAlexander V. Chernikov 3013535eac4SAlexander V. Chernikov #define IPFW_RULE_CNTR_SIZE (2 * sizeof(uint64_t)) 3020d90989bSAlexander V. Chernikov 3037e767c79SAlexander V. Chernikov #endif 3047e767c79SAlexander V. Chernikov 3053b3a8eb9SGleb Smirnoff struct ip_fw_chain { 3063b3a8eb9SGleb Smirnoff struct ip_fw **map; /* array of rule ptrs to ease lookup */ 3075fa3fdd3SAlexander V. Chernikov uint32_t id; /* ruleset id */ 3085fa3fdd3SAlexander V. Chernikov int n_rules; /* number of static rules */ 3099f7d47b0SAlexander V. Chernikov void *tablestate; /* runtime table info */ 3100cba2b28SAlexander V. Chernikov void *valuestate; /* runtime table value info */ 311d5eb80cbSAlexander V. Chernikov int *idxmap; /* skipto array of rules */ 31274b22066SAlexander V. Chernikov void **srvstate; /* runtime service mappings */ 3133b3a8eb9SGleb Smirnoff #if defined( __linux__ ) || defined( _WIN32 ) 3143b3a8eb9SGleb Smirnoff spinlock_t rwmtx; 3155fa3fdd3SAlexander V. Chernikov #endif 3167e767c79SAlexander V. Chernikov int static_len; /* total len of static rules (v0) */ 3175fa3fdd3SAlexander V. Chernikov uint32_t gencnt; /* NAT generation count */ 31874b22066SAlexander V. Chernikov LIST_HEAD(nat_list, cfg_nat) nat; /* list of nat entries */ 3195fa3fdd3SAlexander V. Chernikov struct ip_fw *default_rule; 320b074b7bbSAlexander V. Chernikov struct tables_config *tblcfg; /* tables module data */ 32168394ec8SAlexander V. Chernikov void *ifcfg; /* interface module data */ 322d5eb80cbSAlexander V. Chernikov int *idxmap_back; /* standby skipto array of rules */ 32374b22066SAlexander V. Chernikov struct namedobj_instance *srvmap; /* cfg name->number mappings */ 3245fa3fdd3SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 3255fa3fdd3SAlexander V. Chernikov spinlock_t uh_lock; 3265fa3fdd3SAlexander V. Chernikov #else 3273b3a8eb9SGleb Smirnoff struct rwlock uh_lock; /* lock for upper half */ 3283b3a8eb9SGleb Smirnoff #endif 3293b3a8eb9SGleb Smirnoff }; 3303b3a8eb9SGleb Smirnoff 3310cba2b28SAlexander V. Chernikov /* 64-byte structure representing multi-field table value */ 3320cba2b28SAlexander V. Chernikov struct table_value { 3330cba2b28SAlexander V. Chernikov uint32_t tag; /* O_TAG/O_TAGGED */ 3340cba2b28SAlexander V. Chernikov uint32_t pipe; /* O_PIPE/O_QUEUE */ 3350cba2b28SAlexander V. Chernikov uint16_t divert; /* O_DIVERT/O_TEE */ 3360cba2b28SAlexander V. Chernikov uint16_t skipto; /* skipto, CALLRET */ 3370cba2b28SAlexander V. Chernikov uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */ 3380cba2b28SAlexander V. Chernikov uint32_t fib; /* O_SETFIB */ 3390cba2b28SAlexander V. Chernikov uint32_t nat; /* O_NAT */ 3400cba2b28SAlexander V. Chernikov uint32_t nh4; 3410cba2b28SAlexander V. Chernikov uint8_t dscp; 3422530ed9eSAndrey V. Elsukov uint8_t spare0; 3432530ed9eSAndrey V. Elsukov uint16_t spare1; 3440cba2b28SAlexander V. Chernikov /* -- 32 bytes -- */ 3450cba2b28SAlexander V. Chernikov struct in6_addr nh6; 3460cba2b28SAlexander V. Chernikov uint32_t limit; /* O_LIMIT */ 3472530ed9eSAndrey V. Elsukov uint32_t zoneid; /* scope zone id for nh6 */ 3480cba2b28SAlexander V. Chernikov uint64_t refcnt; /* Number of references */ 3490cba2b28SAlexander V. Chernikov }; 3500cba2b28SAlexander V. Chernikov 35168394ec8SAlexander V. Chernikov 35268394ec8SAlexander V. Chernikov struct named_object { 35368394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nn_next; /* namehash */ 35468394ec8SAlexander V. Chernikov TAILQ_ENTRY(named_object) nv_next; /* valuehash */ 35568394ec8SAlexander V. Chernikov char *name; /* object name */ 3564bd91656SAndrey V. Elsukov uint16_t etlv; /* Export TLV id */ 35774b22066SAlexander V. Chernikov uint8_t subtype;/* object subtype within class */ 3582685841bSAndrey V. Elsukov uint8_t set; /* set object belongs to */ 35968394ec8SAlexander V. Chernikov uint16_t kidx; /* object kernel index */ 3602685841bSAndrey V. Elsukov uint16_t spare; 3612685841bSAndrey V. Elsukov uint32_t ocnt; /* object counter for internal use */ 36268394ec8SAlexander V. Chernikov uint32_t refcnt; /* number of references */ 36368394ec8SAlexander V. Chernikov }; 36468394ec8SAlexander V. Chernikov TAILQ_HEAD(namedobjects_head, named_object); 36568394ec8SAlexander V. Chernikov 3663b3a8eb9SGleb Smirnoff struct sockopt; /* used by tcp_var.h */ 3672d99a349SAlexander V. Chernikov struct sockopt_data { 3682d99a349SAlexander V. Chernikov caddr_t kbuf; /* allocated buffer */ 3692d99a349SAlexander V. Chernikov size_t ksize; /* given buffer size */ 3702d99a349SAlexander V. Chernikov size_t koff; /* data already used */ 3712d99a349SAlexander V. Chernikov size_t kavail; /* number of bytes available */ 3722d99a349SAlexander V. Chernikov size_t ktotal; /* total bytes pushed */ 3732d99a349SAlexander V. Chernikov struct sockopt *sopt; /* socket data */ 374b6ee846eSAlexander V. Chernikov caddr_t sopt_val; /* sopt user buffer */ 3752d99a349SAlexander V. Chernikov size_t valsize; /* original data size */ 3762d99a349SAlexander V. Chernikov }; 3773b3a8eb9SGleb Smirnoff 37868394ec8SAlexander V. Chernikov struct ipfw_ifc; 37968394ec8SAlexander V. Chernikov 38068394ec8SAlexander V. Chernikov typedef void (ipfw_ifc_cb)(struct ip_fw_chain *ch, void *cbdata, 38168394ec8SAlexander V. Chernikov uint16_t ifindex); 38268394ec8SAlexander V. Chernikov 38368394ec8SAlexander V. Chernikov struct ipfw_iface { 38468394ec8SAlexander V. Chernikov struct named_object no; 38568394ec8SAlexander V. Chernikov char ifname[64]; 38668394ec8SAlexander V. Chernikov int resolved; 38768394ec8SAlexander V. Chernikov uint16_t ifindex; 38868394ec8SAlexander V. Chernikov uint16_t spare; 38968394ec8SAlexander V. Chernikov uint64_t gencnt; 39068394ec8SAlexander V. Chernikov TAILQ_HEAD(, ipfw_ifc) consumers; 39168394ec8SAlexander V. Chernikov }; 39268394ec8SAlexander V. Chernikov 39368394ec8SAlexander V. Chernikov struct ipfw_ifc { 39468394ec8SAlexander V. Chernikov TAILQ_ENTRY(ipfw_ifc) next; 39568394ec8SAlexander V. Chernikov struct ipfw_iface *iface; 39668394ec8SAlexander V. Chernikov ipfw_ifc_cb *cb; 39768394ec8SAlexander V. Chernikov void *cbdata; 39868394ec8SAlexander V. Chernikov }; 39968394ec8SAlexander V. Chernikov 400c187c1fbSAlexander V. Chernikov /* Macro for working with various counters */ 4017e767c79SAlexander V. Chernikov #define IPFW_INC_RULE_COUNTER(_cntr, _bytes) do { \ 4027e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr, 1); \ 4037e767c79SAlexander V. Chernikov counter_u64_add((_cntr)->cntr + 1, _bytes); \ 4047e767c79SAlexander V. Chernikov if ((_cntr)->timestamp != time_uptime) \ 4057e767c79SAlexander V. Chernikov (_cntr)->timestamp = time_uptime; \ 4067e767c79SAlexander V. Chernikov } while (0) 4077e767c79SAlexander V. Chernikov 4087e767c79SAlexander V. Chernikov #define IPFW_INC_DYN_COUNTER(_cntr, _bytes) do { \ 4097e767c79SAlexander V. Chernikov (_cntr)->pcnt++; \ 4107e767c79SAlexander V. Chernikov (_cntr)->bcnt += _bytes; \ 4117e767c79SAlexander V. Chernikov } while (0) 4127e767c79SAlexander V. Chernikov 4137e767c79SAlexander V. Chernikov #define IPFW_ZERO_RULE_COUNTER(_cntr) do { \ 4147e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr); \ 4157e767c79SAlexander V. Chernikov counter_u64_zero((_cntr)->cntr + 1); \ 4167e767c79SAlexander V. Chernikov (_cntr)->timestamp = 0; \ 4177e767c79SAlexander V. Chernikov } while (0) 4187e767c79SAlexander V. Chernikov 4197e767c79SAlexander V. Chernikov #define IPFW_ZERO_DYN_COUNTER(_cntr) do { \ 4207e767c79SAlexander V. Chernikov (_cntr)->pcnt = 0; \ 4217e767c79SAlexander V. Chernikov (_cntr)->bcnt = 0; \ 4227e767c79SAlexander V. Chernikov } while (0) 4237e767c79SAlexander V. Chernikov 4240cba2b28SAlexander V. Chernikov #define TARG_VAL(ch, k, f) ((struct table_value *)((ch)->valuestate))[k].f 4250cba2b28SAlexander V. Chernikov #define IP_FW_ARG_TABLEARG(ch, a, f) \ 4260cba2b28SAlexander V. Chernikov (((a) == IP_FW_TARG) ? TARG_VAL(ch, tablearg, f) : (a)) 4273b3a8eb9SGleb Smirnoff /* 4283b3a8eb9SGleb Smirnoff * The lock is heavily used by ip_fw2.c (the main file) and ip_fw_nat.c 4293b3a8eb9SGleb Smirnoff * so the variable and the macros must be here. 4303b3a8eb9SGleb Smirnoff */ 4313b3a8eb9SGleb Smirnoff 432ccba94b8SAlexander V. Chernikov #if defined( __linux__ ) || defined( _WIN32 ) 4333b3a8eb9SGleb Smirnoff #define IPFW_LOCK_INIT(_chain) do { \ 4343b3a8eb9SGleb Smirnoff rw_init(&(_chain)->rwmtx, "IPFW static rules"); \ 4353b3a8eb9SGleb Smirnoff rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 4363b3a8eb9SGleb Smirnoff } while (0) 4373b3a8eb9SGleb Smirnoff 4383b3a8eb9SGleb Smirnoff #define IPFW_LOCK_DESTROY(_chain) do { \ 4393b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->rwmtx); \ 4403b3a8eb9SGleb Smirnoff rw_destroy(&(_chain)->uh_lock); \ 4413b3a8eb9SGleb Smirnoff } while (0) 4423b3a8eb9SGleb Smirnoff 4435d0cd926SAlexander V. Chernikov #define IPFW_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_RLOCKED) 4443b3a8eb9SGleb Smirnoff #define IPFW_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->rwmtx, RA_WLOCKED) 4453b3a8eb9SGleb Smirnoff 446ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER 4473b3a8eb9SGleb Smirnoff #define IPFW_RLOCK(p) rw_rlock(&(p)->rwmtx) 4483b3a8eb9SGleb Smirnoff #define IPFW_RUNLOCK(p) rw_runlock(&(p)->rwmtx) 4493b3a8eb9SGleb Smirnoff #define IPFW_WLOCK(p) rw_wlock(&(p)->rwmtx) 4503b3a8eb9SGleb Smirnoff #define IPFW_WUNLOCK(p) rw_wunlock(&(p)->rwmtx) 45193bb4f9eSAndrey V. Elsukov #define IPFW_PF_RLOCK(p) IPFW_RLOCK(p) 45293bb4f9eSAndrey V. Elsukov #define IPFW_PF_RUNLOCK(p) IPFW_RUNLOCK(p) 453ccba94b8SAlexander V. Chernikov #else /* FreeBSD */ 454ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_INIT(_chain) do { \ 455ccba94b8SAlexander V. Chernikov rw_init(&(_chain)->uh_lock, "IPFW UH lock"); \ 456ccba94b8SAlexander V. Chernikov } while (0) 457ccba94b8SAlexander V. Chernikov 458ccba94b8SAlexander V. Chernikov #define IPFW_LOCK_DESTROY(_chain) do { \ 459ccba94b8SAlexander V. Chernikov rw_destroy(&(_chain)->uh_lock); \ 460ccba94b8SAlexander V. Chernikov } while (0) 461ccba94b8SAlexander V. Chernikov 46288d950a6SAndrey V. Elsukov #define IPFW_RLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_RLOCKED) 46388d950a6SAndrey V. Elsukov #define IPFW_WLOCK_ASSERT(_chain) rm_assert(&V_pfil_lock, RA_WLOCKED) 464ccba94b8SAlexander V. Chernikov 465ccba94b8SAlexander V. Chernikov #define IPFW_RLOCK_TRACKER struct rm_priotracker _tracker 46688d950a6SAndrey V. Elsukov #define IPFW_RLOCK(p) rm_rlock(&V_pfil_lock, &_tracker) 46788d950a6SAndrey V. Elsukov #define IPFW_RUNLOCK(p) rm_runlock(&V_pfil_lock, &_tracker) 46888d950a6SAndrey V. Elsukov #define IPFW_WLOCK(p) rm_wlock(&V_pfil_lock) 46988d950a6SAndrey V. Elsukov #define IPFW_WUNLOCK(p) rm_wunlock(&V_pfil_lock) 47088d950a6SAndrey V. Elsukov #define IPFW_PF_RLOCK(p) 47188d950a6SAndrey V. Elsukov #define IPFW_PF_RUNLOCK(p) 472ccba94b8SAlexander V. Chernikov #endif 4733b3a8eb9SGleb Smirnoff 4742e089d5cSAlexander V. Chernikov #define IPFW_UH_RLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_RLOCKED) 4752e089d5cSAlexander V. Chernikov #define IPFW_UH_WLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_WLOCKED) 4760caab009SAlexander V. Chernikov #define IPFW_UH_UNLOCK_ASSERT(_chain) rw_assert(&(_chain)->uh_lock, RA_UNLOCKED) 4772e089d5cSAlexander V. Chernikov 4783b3a8eb9SGleb Smirnoff #define IPFW_UH_RLOCK(p) rw_rlock(&(p)->uh_lock) 4793b3a8eb9SGleb Smirnoff #define IPFW_UH_RUNLOCK(p) rw_runlock(&(p)->uh_lock) 4803b3a8eb9SGleb Smirnoff #define IPFW_UH_WLOCK(p) rw_wlock(&(p)->uh_lock) 4813b3a8eb9SGleb Smirnoff #define IPFW_UH_WUNLOCK(p) rw_wunlock(&(p)->uh_lock) 4823b3a8eb9SGleb Smirnoff 483b074b7bbSAlexander V. Chernikov struct obj_idx { 484b074b7bbSAlexander V. Chernikov uint16_t uidx; /* internal index supplied by userland */ 485b074b7bbSAlexander V. Chernikov uint16_t kidx; /* kernel object index */ 486b074b7bbSAlexander V. Chernikov uint16_t off; /* tlv offset from rule end in 4-byte words */ 4870468c5baSAlexander V. Chernikov uint8_t spare; 488b074b7bbSAlexander V. Chernikov uint8_t type; /* object type within its category */ 489b074b7bbSAlexander V. Chernikov }; 490b074b7bbSAlexander V. Chernikov 491b074b7bbSAlexander V. Chernikov struct rule_check_info { 4923a845e10SAlexander V. Chernikov uint16_t flags; /* rule-specific check flags */ 49374b22066SAlexander V. Chernikov uint16_t object_opcodes; /* num of opcodes referencing objects */ 4947e767c79SAlexander V. Chernikov uint16_t urule_numoff; /* offset of rulenum in bytes */ 4957e767c79SAlexander V. Chernikov uint8_t version; /* rule version */ 4963a845e10SAlexander V. Chernikov uint8_t spare; 4976c2997ffSAlexander V. Chernikov ipfw_obj_ctlv *ctlv; /* name TLV containter */ 498b074b7bbSAlexander V. Chernikov struct ip_fw *krule; /* resulting rule pointer */ 4997e767c79SAlexander V. Chernikov caddr_t urule; /* original rule pointer */ 500b074b7bbSAlexander V. Chernikov struct obj_idx obuf[8]; /* table references storage */ 501b074b7bbSAlexander V. Chernikov }; 502b074b7bbSAlexander V. Chernikov 5037e767c79SAlexander V. Chernikov /* Legacy interface support */ 5047e767c79SAlexander V. Chernikov /* 5057e767c79SAlexander V. Chernikov * FreeBSD 8 export rule format 5067e767c79SAlexander V. Chernikov */ 5077e767c79SAlexander V. Chernikov struct ip_fw_rule0 { 5087e767c79SAlexander V. Chernikov struct ip_fw *x_next; /* linked list of rules */ 5097e767c79SAlexander V. Chernikov struct ip_fw *next_rule; /* ptr to next [skipto] rule */ 5107e767c79SAlexander V. Chernikov /* 'next_rule' is used to pass up 'set_disable' status */ 5117e767c79SAlexander V. Chernikov 5127e767c79SAlexander V. Chernikov uint16_t act_ofs; /* offset of action in 32-bit units */ 5137e767c79SAlexander V. Chernikov uint16_t cmd_len; /* # of 32-bit words in cmd */ 5147e767c79SAlexander V. Chernikov uint16_t rulenum; /* rule number */ 5157e767c79SAlexander V. Chernikov uint8_t set; /* rule set (0..31) */ 5167e767c79SAlexander V. Chernikov uint8_t _pad; /* padding */ 5177e767c79SAlexander V. Chernikov uint32_t id; /* rule id */ 5187e767c79SAlexander V. Chernikov 5197e767c79SAlexander V. Chernikov /* These fields are present in all rules. */ 5207e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5217e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5227e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5237e767c79SAlexander V. Chernikov 5247e767c79SAlexander V. Chernikov ipfw_insn cmd[1]; /* storage for commands */ 5257e767c79SAlexander V. Chernikov }; 5267e767c79SAlexander V. Chernikov 5277e767c79SAlexander V. Chernikov struct ip_fw_bcounter0 { 5287e767c79SAlexander V. Chernikov uint64_t pcnt; /* Packet counter */ 5297e767c79SAlexander V. Chernikov uint64_t bcnt; /* Byte counter */ 5307e767c79SAlexander V. Chernikov uint32_t timestamp; /* tv_sec of last match */ 5317e767c79SAlexander V. Chernikov }; 5327e767c79SAlexander V. Chernikov 5337e767c79SAlexander V. Chernikov /* Kernel rule length */ 5347e767c79SAlexander V. Chernikov /* 5357e767c79SAlexander V. Chernikov * RULE _K_ SIZE _V_ -> 5367e767c79SAlexander V. Chernikov * get kernel size from userland rool version _V_. 5377e767c79SAlexander V. Chernikov * RULE _U_ SIZE _V_ -> 5387e767c79SAlexander V. Chernikov * get user size version _V_ from kernel rule 5397e767c79SAlexander V. Chernikov * RULESIZE _V_ -> 5407e767c79SAlexander V. Chernikov * get user size rule length 5417e767c79SAlexander V. Chernikov */ 5427e767c79SAlexander V. Chernikov /* FreeBSD8 <> current kernel format */ 5437e767c79SAlexander V. Chernikov #define RULEUSIZE0(r) (sizeof(struct ip_fw_rule0) + (r)->cmd_len * 4 - 4) 5447e767c79SAlexander V. Chernikov #define RULEKSIZE0(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5457e767c79SAlexander V. Chernikov /* FreeBSD11 <> current kernel format */ 5467e767c79SAlexander V. Chernikov #define RULEUSIZE1(r) (roundup2(sizeof(struct ip_fw_rule) + \ 5477e767c79SAlexander V. Chernikov (r)->cmd_len * 4 - 4, 8)) 5487e767c79SAlexander V. Chernikov #define RULEKSIZE1(r) roundup2((sizeof(struct ip_fw) + (r)->cmd_len*4 - 4), 8) 5497e767c79SAlexander V. Chernikov 55074b22066SAlexander V. Chernikov /* 55174b22066SAlexander V. Chernikov * Tables/Objects index rewriting code 55274b22066SAlexander V. Chernikov */ 55374b22066SAlexander V. Chernikov 55474b22066SAlexander V. Chernikov /* Default and maximum number of ipfw tables/objects. */ 55574b22066SAlexander V. Chernikov #define IPFW_TABLES_MAX 65536 55674b22066SAlexander V. Chernikov #define IPFW_TABLES_DEFAULT 128 55774b22066SAlexander V. Chernikov #define IPFW_OBJECTS_MAX 65536 5582acdf79fSAndrey V. Elsukov #define IPFW_OBJECTS_DEFAULT 1024 55974b22066SAlexander V. Chernikov 56074b22066SAlexander V. Chernikov #define CHAIN_TO_SRV(ch) ((ch)->srvmap) 5612acdf79fSAndrey V. Elsukov #define SRV_OBJECT(ch, idx) ((ch)->srvstate[(idx)]) 56274b22066SAlexander V. Chernikov 56374b22066SAlexander V. Chernikov struct tid_info { 56474b22066SAlexander V. Chernikov uint32_t set; /* table set */ 56574b22066SAlexander V. Chernikov uint16_t uidx; /* table index */ 56674b22066SAlexander V. Chernikov uint8_t type; /* table type */ 56774b22066SAlexander V. Chernikov uint8_t atype; 56874b22066SAlexander V. Chernikov uint8_t spare; 56974b22066SAlexander V. Chernikov int tlen; /* Total TLV size block */ 57074b22066SAlexander V. Chernikov void *tlvs; /* Pointer to first TLV */ 57174b22066SAlexander V. Chernikov }; 57274b22066SAlexander V. Chernikov 57374b22066SAlexander V. Chernikov /* 57474b22066SAlexander V. Chernikov * Classifier callback. Checks if @cmd opcode contains kernel object reference. 57574b22066SAlexander V. Chernikov * If true, returns its index and type. 57674b22066SAlexander V. Chernikov * Returns 0 if match is found, 1 overwise. 57774b22066SAlexander V. Chernikov */ 57874b22066SAlexander V. Chernikov typedef int (ipfw_obj_rw_cl)(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype); 57974b22066SAlexander V. Chernikov /* 58074b22066SAlexander V. Chernikov * Updater callback. Sets kernel object reference index to @puidx 58174b22066SAlexander V. Chernikov */ 58274b22066SAlexander V. Chernikov typedef void (ipfw_obj_rw_upd)(ipfw_insn *cmd, uint16_t puidx); 58374b22066SAlexander V. Chernikov /* 58474b22066SAlexander V. Chernikov * Finder callback. Tries to find named object by name (specified via @ti). 58574b22066SAlexander V. Chernikov * Stores found named object pointer in @pno. 58674b22066SAlexander V. Chernikov * If object was not found, NULL is stored. 58774b22066SAlexander V. Chernikov * 58874b22066SAlexander V. Chernikov * Return 0 if input data was valid. 58974b22066SAlexander V. Chernikov */ 59074b22066SAlexander V. Chernikov typedef int (ipfw_obj_fname_cb)(struct ip_fw_chain *ch, 59174b22066SAlexander V. Chernikov struct tid_info *ti, struct named_object **pno); 59274b22066SAlexander V. Chernikov /* 59374b22066SAlexander V. Chernikov * Another finder callback. Tries to findex named object by kernel index. 59474b22066SAlexander V. Chernikov * 59574b22066SAlexander V. Chernikov * Returns pointer to named object or NULL. 59674b22066SAlexander V. Chernikov */ 59774b22066SAlexander V. Chernikov typedef struct named_object *(ipfw_obj_fidx_cb)(struct ip_fw_chain *ch, 59874b22066SAlexander V. Chernikov uint16_t kidx); 59974b22066SAlexander V. Chernikov /* 60074b22066SAlexander V. Chernikov * Object creator callback. Tries to create object specified by @ti. 60174b22066SAlexander V. Chernikov * Stores newly-allocated object index in @pkidx. 60274b22066SAlexander V. Chernikov * 60374b22066SAlexander V. Chernikov * Returns 0 on success. 60474b22066SAlexander V. Chernikov */ 60574b22066SAlexander V. Chernikov typedef int (ipfw_obj_create_cb)(struct ip_fw_chain *ch, struct tid_info *ti, 60674b22066SAlexander V. Chernikov uint16_t *pkidx); 6071cf09efeSAndrey V. Elsukov /* 6081cf09efeSAndrey V. Elsukov * Object destroy callback. Intended to free resources allocated by 6091cf09efeSAndrey V. Elsukov * create_object callback. 6101cf09efeSAndrey V. Elsukov */ 6111cf09efeSAndrey V. Elsukov typedef void (ipfw_obj_destroy_cb)(struct ip_fw_chain *ch, 6121cf09efeSAndrey V. Elsukov struct named_object *no); 6132685841bSAndrey V. Elsukov /* 6142685841bSAndrey V. Elsukov * Sets handler callback. Handles moving and swaping set of named object. 6152685841bSAndrey V. Elsukov * SWAP_ALL moves all named objects from set `set' to `new_set' and vise versa; 6162685841bSAndrey V. Elsukov * TEST_ALL checks that there aren't any named object with conflicting names; 6172685841bSAndrey V. Elsukov * MOVE_ALL moves all named objects from set `set' to `new_set'; 6182685841bSAndrey V. Elsukov * COUNT_ONE used to count number of references used by object with kidx `set'; 6192685841bSAndrey V. Elsukov * TEST_ONE checks that named object with kidx `set' can be moved to `new_set`; 6202685841bSAndrey V. Elsukov * MOVE_ONE moves named object with kidx `set' to set `new_set'. 6212685841bSAndrey V. Elsukov */ 6222685841bSAndrey V. Elsukov enum ipfw_sets_cmd { 6232685841bSAndrey V. Elsukov SWAP_ALL = 0, TEST_ALL, MOVE_ALL, COUNT_ONE, TEST_ONE, MOVE_ONE 6242685841bSAndrey V. Elsukov }; 6252685841bSAndrey V. Elsukov typedef int (ipfw_obj_sets_cb)(struct ip_fw_chain *ch, 6262685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 6272685841bSAndrey V. Elsukov 62874b22066SAlexander V. Chernikov 62974b22066SAlexander V. Chernikov struct opcode_obj_rewrite { 63074b22066SAlexander V. Chernikov uint32_t opcode; /* Opcode to act upon */ 63174b22066SAlexander V. Chernikov uint32_t etlv; /* Relevant export TLV id */ 63274b22066SAlexander V. Chernikov ipfw_obj_rw_cl *classifier; /* Check if rewrite is needed */ 63374b22066SAlexander V. Chernikov ipfw_obj_rw_upd *update; /* update cmd with new value */ 63474b22066SAlexander V. Chernikov ipfw_obj_fname_cb *find_byname; /* Find named object by name */ 63574b22066SAlexander V. Chernikov ipfw_obj_fidx_cb *find_bykidx; /* Find named object by kidx */ 63674b22066SAlexander V. Chernikov ipfw_obj_create_cb *create_object; /* Create named object */ 6371cf09efeSAndrey V. Elsukov ipfw_obj_destroy_cb *destroy_object;/* Destroy named object */ 6382685841bSAndrey V. Elsukov ipfw_obj_sets_cb *manage_sets; /* Swap or move sets */ 63974b22066SAlexander V. Chernikov }; 64074b22066SAlexander V. Chernikov 64174b22066SAlexander V. Chernikov #define IPFW_ADD_OBJ_REWRITER(f, c) do { \ 64274b22066SAlexander V. Chernikov if ((f) != 0) \ 64374b22066SAlexander V. Chernikov ipfw_add_obj_rewriter(c, \ 64474b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 64574b22066SAlexander V. Chernikov } while(0) 64674b22066SAlexander V. Chernikov #define IPFW_DEL_OBJ_REWRITER(l, c) do { \ 64774b22066SAlexander V. Chernikov if ((l) != 0) \ 64874b22066SAlexander V. Chernikov ipfw_del_obj_rewriter(c, \ 64974b22066SAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 65074b22066SAlexander V. Chernikov } while(0) 6517e767c79SAlexander V. Chernikov 65268394ec8SAlexander V. Chernikov /* In ip_fw_iface.c */ 65368394ec8SAlexander V. Chernikov int ipfw_iface_init(void); 65468394ec8SAlexander V. Chernikov void ipfw_iface_destroy(void); 65568394ec8SAlexander V. Chernikov void vnet_ipfw_iface_destroy(struct ip_fw_chain *ch); 65668394ec8SAlexander V. Chernikov int ipfw_iface_ref(struct ip_fw_chain *ch, char *name, 65768394ec8SAlexander V. Chernikov struct ipfw_ifc *ic); 65868394ec8SAlexander V. Chernikov void ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 65968394ec8SAlexander V. Chernikov void ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 66068394ec8SAlexander V. Chernikov void ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic); 66168394ec8SAlexander V. Chernikov 6623b3a8eb9SGleb Smirnoff /* In ip_fw_sockopt.c */ 663d5eb80cbSAlexander V. Chernikov void ipfw_init_skipto_cache(struct ip_fw_chain *chain); 664d5eb80cbSAlexander V. Chernikov void ipfw_destroy_skipto_cache(struct ip_fw_chain *chain); 6653b3a8eb9SGleb Smirnoff int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id); 666b429d43cSAlexander V. Chernikov int ipfw_ctl3(struct sockopt *sopt); 6677143bb76SAndrey V. Elsukov int ipfw_add_protected_rule(struct ip_fw_chain *chain, struct ip_fw *rule, 6687143bb76SAndrey V. Elsukov int locked); 669030b184fSAlexander V. Chernikov void ipfw_reap_add(struct ip_fw_chain *chain, struct ip_fw **head, 670030b184fSAlexander V. Chernikov struct ip_fw *rule); 6713b3a8eb9SGleb Smirnoff void ipfw_reap_rules(struct ip_fw *head); 6727e767c79SAlexander V. Chernikov void ipfw_init_counters(void); 6737e767c79SAlexander V. Chernikov void ipfw_destroy_counters(void); 6747e767c79SAlexander V. Chernikov struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize); 675cefe3d67SAndrey V. Elsukov void ipfw_free_rule(struct ip_fw *rule); 676a73d728dSAlexander V. Chernikov int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt); 677cefe3d67SAndrey V. Elsukov int ipfw_mark_object_kidx(uint32_t *bmask, uint16_t etlv, uint16_t kidx); 6783b3a8eb9SGleb Smirnoff 6796b988f3aSAlexander V. Chernikov typedef int (sopt_handler_f)(struct ip_fw_chain *ch, 6806b988f3aSAlexander V. Chernikov ip_fw3_opheader *op3, struct sockopt_data *sd); 6816b988f3aSAlexander V. Chernikov struct ipfw_sopt_handler { 6826b988f3aSAlexander V. Chernikov uint16_t opcode; 6836b988f3aSAlexander V. Chernikov uint8_t version; 6846b988f3aSAlexander V. Chernikov uint8_t dir; 6856b988f3aSAlexander V. Chernikov sopt_handler_f *handler; 6866b988f3aSAlexander V. Chernikov uint64_t refcnt; 6876b988f3aSAlexander V. Chernikov }; 6886b988f3aSAlexander V. Chernikov #define HDIR_SET 0x01 /* Handler is used to set some data */ 6896b988f3aSAlexander V. Chernikov #define HDIR_GET 0x02 /* Handler is used to retrieve data */ 6906b988f3aSAlexander V. Chernikov #define HDIR_BOTH HDIR_GET|HDIR_SET 6916b988f3aSAlexander V. Chernikov 6926b988f3aSAlexander V. Chernikov void ipfw_init_sopt_handler(void); 6936b988f3aSAlexander V. Chernikov void ipfw_destroy_sopt_handler(void); 6946b988f3aSAlexander V. Chernikov void ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6956b988f3aSAlexander V. Chernikov int ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count); 6962d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed); 6972d99a349SAlexander V. Chernikov caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed); 6986b988f3aSAlexander V. Chernikov #define IPFW_ADD_SOPT_HANDLER(f, c) do { \ 6996b988f3aSAlexander V. Chernikov if ((f) != 0) \ 7006b988f3aSAlexander V. Chernikov ipfw_add_sopt_handler(c, \ 7016b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 7026b988f3aSAlexander V. Chernikov } while(0) 7036b988f3aSAlexander V. Chernikov #define IPFW_DEL_SOPT_HANDLER(l, c) do { \ 7046b988f3aSAlexander V. Chernikov if ((l) != 0) \ 7056b988f3aSAlexander V. Chernikov ipfw_del_sopt_handler(c, \ 7066b988f3aSAlexander V. Chernikov sizeof(c) / sizeof(c[0])); \ 7076b988f3aSAlexander V. Chernikov } while(0) 7082d99a349SAlexander V. Chernikov 70974b22066SAlexander V. Chernikov struct namedobj_instance; 710b309f085SAndrey V. Elsukov typedef int (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *, 711b074b7bbSAlexander V. Chernikov void *arg); 7122acdf79fSAndrey V. Elsukov typedef uint32_t (objhash_hash_f)(struct namedobj_instance *ni, const void *key, 71313263632SAlexander V. Chernikov uint32_t kopt); 7142acdf79fSAndrey V. Elsukov typedef int (objhash_cmp_f)(struct named_object *no, const void *key, 7152acdf79fSAndrey V. Elsukov uint32_t kopt); 716b074b7bbSAlexander V. Chernikov struct namedobj_instance *ipfw_objhash_create(uint32_t items); 717b074b7bbSAlexander V. Chernikov void ipfw_objhash_destroy(struct namedobj_instance *); 718b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_alloc(uint32_t items, void **idx, int *pblocks); 7199f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_merge(struct namedobj_instance *ni, 7209f7d47b0SAlexander V. Chernikov void **idx, int *blocks); 7219f7d47b0SAlexander V. Chernikov void ipfw_objhash_bitmap_swap(struct namedobj_instance *ni, 722b074b7bbSAlexander V. Chernikov void **idx, int *blocks); 723b074b7bbSAlexander V. Chernikov void ipfw_objhash_bitmap_free(void *idx, int blocks); 72413263632SAlexander V. Chernikov void ipfw_objhash_set_hashf(struct namedobj_instance *ni, objhash_hash_f *f); 725b074b7bbSAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name(struct namedobj_instance *ni, 726b074b7bbSAlexander V. Chernikov uint32_t set, char *name); 72774b22066SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_name_type(struct namedobj_instance *ni, 7282acdf79fSAndrey V. Elsukov uint32_t set, uint32_t type, const char *name); 729ac35ff17SAlexander V. Chernikov struct named_object *ipfw_objhash_lookup_kidx(struct namedobj_instance *ni, 730ac35ff17SAlexander V. Chernikov uint16_t idx); 7319490a627SAlexander V. Chernikov int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, 7329490a627SAlexander V. Chernikov struct named_object *b); 733b074b7bbSAlexander V. Chernikov void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); 734b074b7bbSAlexander V. Chernikov void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); 7359f7d47b0SAlexander V. Chernikov uint32_t ipfw_objhash_count(struct namedobj_instance *ni); 7362685841bSAndrey V. Elsukov uint32_t ipfw_objhash_count_type(struct namedobj_instance *ni, uint16_t type); 737b309f085SAndrey V. Elsukov int ipfw_objhash_foreach(struct namedobj_instance *ni, objhash_cb_t *f, 738b074b7bbSAlexander V. Chernikov void *arg); 7392685841bSAndrey V. Elsukov int ipfw_objhash_foreach_type(struct namedobj_instance *ni, objhash_cb_t *f, 7402685841bSAndrey V. Elsukov void *arg, uint16_t type); 741ac35ff17SAlexander V. Chernikov int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); 742ac35ff17SAlexander V. Chernikov int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); 74313263632SAlexander V. Chernikov void ipfw_objhash_set_funcs(struct namedobj_instance *ni, 74413263632SAlexander V. Chernikov objhash_hash_f *hash_f, objhash_cmp_f *cmp_f); 7452acdf79fSAndrey V. Elsukov int ipfw_objhash_find_type(struct namedobj_instance *ni, struct tid_info *ti, 7462acdf79fSAndrey V. Elsukov uint32_t etlv, struct named_object **pno); 7475dc5a0e0SAndrey V. Elsukov void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); 7482df1a11fSAndrey V. Elsukov ipfw_obj_ntlv *ipfw_find_name_tlv_type(void *tlvs, int len, uint16_t uidx, 7492df1a11fSAndrey V. Elsukov uint32_t etlv); 75074b22066SAlexander V. Chernikov void ipfw_init_obj_rewriter(void); 75174b22066SAlexander V. Chernikov void ipfw_destroy_obj_rewriter(void); 75274b22066SAlexander V. Chernikov void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 75374b22066SAlexander V. Chernikov int ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); 75474b22066SAlexander V. Chernikov 75574b22066SAlexander V. Chernikov int create_objects_compat(struct ip_fw_chain *ch, ipfw_insn *cmd, 75674b22066SAlexander V. Chernikov struct obj_idx *oib, struct obj_idx *pidx, struct tid_info *ti); 75774b22066SAlexander V. Chernikov void update_opcode_kidx(ipfw_insn *cmd, uint16_t idx); 75874b22066SAlexander V. Chernikov int classify_opcode_kidx(ipfw_insn *cmd, uint16_t *puidx); 75974b22066SAlexander V. Chernikov void ipfw_init_srv(struct ip_fw_chain *ch); 76074b22066SAlexander V. Chernikov void ipfw_destroy_srv(struct ip_fw_chain *ch); 761f81431ccSAndrey V. Elsukov int ipfw_check_object_name_generic(const char *name); 7622685841bSAndrey V. Elsukov int ipfw_obj_manage_sets(struct namedobj_instance *ni, uint16_t type, 7632685841bSAndrey V. Elsukov uint16_t set, uint8_t new_set, enum ipfw_sets_cmd cmd); 764b074b7bbSAlexander V. Chernikov 7652acdf79fSAndrey V. Elsukov /* In ip_fw_eaction.c */ 7662acdf79fSAndrey V. Elsukov typedef int (ipfw_eaction_t)(struct ip_fw_chain *ch, struct ip_fw_args *args, 7672acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 7682acdf79fSAndrey V. Elsukov int ipfw_eaction_init(struct ip_fw_chain *ch, int first); 7692acdf79fSAndrey V. Elsukov void ipfw_eaction_uninit(struct ip_fw_chain *ch, int last); 7702acdf79fSAndrey V. Elsukov 7712acdf79fSAndrey V. Elsukov uint16_t ipfw_add_eaction(struct ip_fw_chain *ch, ipfw_eaction_t handler, 7722acdf79fSAndrey V. Elsukov const char *name); 7732acdf79fSAndrey V. Elsukov int ipfw_del_eaction(struct ip_fw_chain *ch, uint16_t eaction_id); 7742acdf79fSAndrey V. Elsukov int ipfw_run_eaction(struct ip_fw_chain *ch, struct ip_fw_args *args, 7752acdf79fSAndrey V. Elsukov ipfw_insn *cmd, int *done); 776cefe3d67SAndrey V. Elsukov int ipfw_reset_eaction(struct ip_fw_chain *ch, struct ip_fw *rule, 777cefe3d67SAndrey V. Elsukov uint16_t eaction_id, uint16_t default_id, uint16_t instance_id); 778cefe3d67SAndrey V. Elsukov int ipfw_reset_eaction_instance(struct ip_fw_chain *ch, uint16_t eaction_id, 779cefe3d67SAndrey V. Elsukov uint16_t instance_id); 7802acdf79fSAndrey V. Elsukov 7813b3a8eb9SGleb Smirnoff /* In ip_fw_table.c */ 7829f7d47b0SAlexander V. Chernikov struct table_info; 7839f7d47b0SAlexander V. Chernikov 7849f7d47b0SAlexander V. Chernikov typedef int (table_lookup_t)(struct table_info *ti, void *key, uint32_t keylen, 7859f7d47b0SAlexander V. Chernikov uint32_t *val); 7869f7d47b0SAlexander V. Chernikov 78754e5669dSAndrey V. Elsukov int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen, 78854e5669dSAndrey V. Elsukov void *paddr, uint32_t *val); 7896951cecfSAndrey V. Elsukov struct named_object *ipfw_objhash_lookup_table_kidx(struct ip_fw_chain *ch, 7906951cecfSAndrey V. Elsukov uint16_t kidx); 7916951cecfSAndrey V. Elsukov int ipfw_ref_table(struct ip_fw_chain *ch, ipfw_obj_ntlv *ntlv, uint16_t *kidx); 7926951cecfSAndrey V. Elsukov void ipfw_unref_table(struct ip_fw_chain *ch, uint16_t kidx); 7936b988f3aSAlexander V. Chernikov int ipfw_init_tables(struct ip_fw_chain *ch, int first); 7943b3a8eb9SGleb Smirnoff int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables); 795a73d728dSAlexander V. Chernikov int ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int nsets); 7966b988f3aSAlexander V. Chernikov void ipfw_destroy_tables(struct ip_fw_chain *ch, int last); 7979f7d47b0SAlexander V. Chernikov 7983b3a8eb9SGleb Smirnoff /* In ip_fw_nat.c -- XXX to be moved to ip_var.h */ 7993b3a8eb9SGleb Smirnoff 8003b3a8eb9SGleb Smirnoff extern struct cfg_nat *(*lookup_nat_ptr)(struct nat_list *, int); 8013b3a8eb9SGleb Smirnoff 8023b3a8eb9SGleb Smirnoff typedef int ipfw_nat_t(struct ip_fw_args *, struct cfg_nat *, struct mbuf *); 8033b3a8eb9SGleb Smirnoff typedef int ipfw_nat_cfg_t(struct sockopt *); 8043b3a8eb9SGleb Smirnoff 8058856400bSMikolaj Golub VNET_DECLARE(int, ipfw_nat_ready); 8068856400bSMikolaj Golub #define V_ipfw_nat_ready VNET(ipfw_nat_ready) 8078856400bSMikolaj Golub #define IPFW_NAT_LOADED (V_ipfw_nat_ready) 8083b3a8eb9SGleb Smirnoff 8098856400bSMikolaj Golub extern ipfw_nat_t *ipfw_nat_ptr; 8103b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_cfg_ptr; 8113b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_del_ptr; 8123b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_cfg_ptr; 8133b3a8eb9SGleb Smirnoff extern ipfw_nat_cfg_t *ipfw_nat_get_log_ptr; 8143b3a8eb9SGleb Smirnoff 815af9aa0a8SAndrey V. Elsukov /* Helper functions for IP checksum adjustment */ 816af9aa0a8SAndrey V. Elsukov static __inline uint16_t 817af9aa0a8SAndrey V. Elsukov cksum_add(uint16_t sum, uint16_t a) 818af9aa0a8SAndrey V. Elsukov { 819af9aa0a8SAndrey V. Elsukov uint16_t res; 820af9aa0a8SAndrey V. Elsukov 821af9aa0a8SAndrey V. Elsukov res = sum + a; 822af9aa0a8SAndrey V. Elsukov return (res + (res < a)); 823af9aa0a8SAndrey V. Elsukov } 824af9aa0a8SAndrey V. Elsukov 825af9aa0a8SAndrey V. Elsukov static __inline uint16_t 826af9aa0a8SAndrey V. Elsukov cksum_adjust(uint16_t oldsum, uint16_t old, uint16_t new) 827af9aa0a8SAndrey V. Elsukov { 828af9aa0a8SAndrey V. Elsukov 829af9aa0a8SAndrey V. Elsukov return (~cksum_add(cksum_add(~oldsum, ~old), new)); 830af9aa0a8SAndrey V. Elsukov } 831af9aa0a8SAndrey V. Elsukov 8323b3a8eb9SGleb Smirnoff #endif /* _KERNEL */ 8333b3a8eb9SGleb Smirnoff #endif /* _IPFW2_PRIVATE_H */ 834