17ec2f6bcSAndrey V. Elsukov /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 37ec2f6bcSAndrey V. Elsukov * 47ec2f6bcSAndrey V. Elsukov * Copyright (c) 2020 Yandex LLC 57ec2f6bcSAndrey V. Elsukov * Copyright (c) 2020 Andrey V. Elsukov <ae@FreeBSD.org> 67ec2f6bcSAndrey V. Elsukov * 77ec2f6bcSAndrey V. Elsukov * Redistribution and use in source and binary forms, with or without 87ec2f6bcSAndrey V. Elsukov * modification, are permitted provided that the following conditions 97ec2f6bcSAndrey V. Elsukov * are met: 107ec2f6bcSAndrey V. Elsukov * 1. Redistributions of source code must retain the above copyright 117ec2f6bcSAndrey V. Elsukov * notice, this list of conditions and the following disclaimer. 127ec2f6bcSAndrey V. Elsukov * 2. Redistributions in binary form must reproduce the above copyright 137ec2f6bcSAndrey V. Elsukov * notice, this list of conditions and the following disclaimer in the 147ec2f6bcSAndrey V. Elsukov * documentation and/or other materials provided with the distribution. 157ec2f6bcSAndrey V. Elsukov * 167ec2f6bcSAndrey V. Elsukov * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 177ec2f6bcSAndrey V. Elsukov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187ec2f6bcSAndrey V. Elsukov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197ec2f6bcSAndrey V. Elsukov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 207ec2f6bcSAndrey V. Elsukov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217ec2f6bcSAndrey V. Elsukov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227ec2f6bcSAndrey V. Elsukov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237ec2f6bcSAndrey V. Elsukov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247ec2f6bcSAndrey V. Elsukov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257ec2f6bcSAndrey V. Elsukov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267ec2f6bcSAndrey V. Elsukov * SUCH DAMAGE. 277ec2f6bcSAndrey V. Elsukov */ 287ec2f6bcSAndrey V. Elsukov 297ec2f6bcSAndrey V. Elsukov #pragma D depends_on provider ipfw 307ec2f6bcSAndrey V. Elsukov 317ec2f6bcSAndrey V. Elsukov /* ipfw_chk() return values */ 327ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_PASS 337ec2f6bcSAndrey V. Elsukov inline int IP_FW_PASS = 0; 347ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_DENY 357ec2f6bcSAndrey V. Elsukov inline int IP_FW_DENY = 1; 367ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_DIVERT 377ec2f6bcSAndrey V. Elsukov inline int IP_FW_DIVERT = 2; 387ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_TEE 397ec2f6bcSAndrey V. Elsukov inline int IP_FW_TEE = 3; 407ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_DUMMYNET 417ec2f6bcSAndrey V. Elsukov inline int IP_FW_DUMMYNET = 4; 427ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_NETGRAPH 437ec2f6bcSAndrey V. Elsukov inline int IP_FW_NETGRAPH = 5; 447ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_NGTEE 457ec2f6bcSAndrey V. Elsukov inline int IP_FW_NGTEE = 6; 467ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_NAT 477ec2f6bcSAndrey V. Elsukov inline int IP_FW_NAT = 7; 487ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_REASS 497ec2f6bcSAndrey V. Elsukov inline int IP_FW_REASS = 8; 507ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IP_FW_NAT64 517ec2f6bcSAndrey V. Elsukov inline int IP_FW_NAT64 = 9; 527ec2f6bcSAndrey V. Elsukov 537ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" ipfw_retcodes 547ec2f6bcSAndrey V. Elsukov inline string ipfw_retcodes[int ret] = 557ec2f6bcSAndrey V. Elsukov ret == IP_FW_PASS ? "PASS" : 567ec2f6bcSAndrey V. Elsukov ret == IP_FW_DENY ? "DENY" : 577ec2f6bcSAndrey V. Elsukov ret == IP_FW_DIVERT ? "DIVERT" : 587ec2f6bcSAndrey V. Elsukov ret == IP_FW_TEE ? "TEE" : 597ec2f6bcSAndrey V. Elsukov ret == IP_FW_DUMMYNET ? "DUMMYNET" : 607ec2f6bcSAndrey V. Elsukov ret == IP_FW_NETGRAPH ? "NETGRAPH" : 617ec2f6bcSAndrey V. Elsukov ret == IP_FW_NGTEE ? "NGTEE" : 627ec2f6bcSAndrey V. Elsukov ret == IP_FW_NAT ? "NAT" : 637ec2f6bcSAndrey V. Elsukov ret == IP_FW_REASS ? "REASS" : 647ec2f6bcSAndrey V. Elsukov ret == IP_FW_NAT64 ? "NAT64" : 657ec2f6bcSAndrey V. Elsukov "<unknown>"; 667ec2f6bcSAndrey V. Elsukov 677ec2f6bcSAndrey V. Elsukov /* ip_fw_args flags */ 687ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_ETHER 697ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_ETHER = 0x00010000; /* valid ethernet header */ 707ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_NH4 717ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_NH4 = 0x00020000; /* IPv4 next hop in hopstore */ 727ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_NH6 737ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_NH6 = 0x00040000; /* IPv6 next hop in hopstore */ 747ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_NH4PTR 757ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_NH4PTR = 0x00080000; /* IPv4 next hop in next_hop */ 767ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_NH6PTR 777ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_NH6PTR = 0x00100000; /* IPv6 next hop in next_hop6 */ 787ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_REF 797ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_REF = 0x00200000; /* valid ipfw_rule_ref */ 807ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_IN 817ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_IN = 0x00400000; /* called on input */ 827ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_OUT 837ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_OUT = 0x00800000; /* called on output */ 847ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_IP4 857ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_IP4 = 0x01000000; /* belongs to v4 ISR */ 867ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_IP6 877ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_IP6 = 0x02000000; /* belongs to v6 ISR */ 887ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_DROP 897ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_DROP = 0x04000000; /* drop it (dummynet) */ 907ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ARGS_LENMASK 917ec2f6bcSAndrey V. Elsukov inline int IPFW_ARGS_LENMASK = 0x0000ffff; /* length of data in *mem */ 927ec2f6bcSAndrey V. Elsukov 937ec2f6bcSAndrey V. Elsukov /* ipfw_rule_ref.info */ 947ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_INFO_MASK 957ec2f6bcSAndrey V. Elsukov inline int IPFW_INFO_MASK = 0x0000ffff; 967ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_INFO_OUT 977ec2f6bcSAndrey V. Elsukov inline int IPFW_INFO_OUT = 0x00000000; 987ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_INFO_IN 997ec2f6bcSAndrey V. Elsukov inline int IPFW_INFO_IN = 0x80000000; 1007ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_ONEPASS 1017ec2f6bcSAndrey V. Elsukov inline int IPFW_ONEPASS = 0x40000000; 1027ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_IS_MASK 1037ec2f6bcSAndrey V. Elsukov inline int IPFW_IS_MASK = 0x30000000; 1047ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_IS_DIVERT 1057ec2f6bcSAndrey V. Elsukov inline int IPFW_IS_DIVERT = 0x20000000; 1067ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_IS_DUMMYNET 1077ec2f6bcSAndrey V. Elsukov inline int IPFW_IS_DUMMYNET = 0x10000000; 1087ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" IPFW_IS_PIPE 1097ec2f6bcSAndrey V. Elsukov inline int IPFW_IS_PIPE = 0x08000000; 1107ec2f6bcSAndrey V. Elsukov 1117ec2f6bcSAndrey V. Elsukov typedef struct ipfw_match_info { 1127ec2f6bcSAndrey V. Elsukov uint32_t flags; 1137ec2f6bcSAndrey V. Elsukov 1147ec2f6bcSAndrey V. Elsukov struct mbuf *m; 1157ec2f6bcSAndrey V. Elsukov void *mem; 1167ec2f6bcSAndrey V. Elsukov struct inpcb *inp; 1177ec2f6bcSAndrey V. Elsukov struct ifnet *ifp; 1187ec2f6bcSAndrey V. Elsukov struct ip *ipp; 1197ec2f6bcSAndrey V. Elsukov struct ip6_hdr *ip6p; 1207ec2f6bcSAndrey V. Elsukov 1217ec2f6bcSAndrey V. Elsukov /* flow id */ 1227ec2f6bcSAndrey V. Elsukov uint8_t addr_type; 1237ec2f6bcSAndrey V. Elsukov uint8_t proto; 1247ec2f6bcSAndrey V. Elsukov uint8_t proto_flags; 1257ec2f6bcSAndrey V. Elsukov uint16_t fib; /* XXX */ 1267ec2f6bcSAndrey V. Elsukov in_addr_t dst_ip; /* in network byte order */ 1277ec2f6bcSAndrey V. Elsukov in_addr_t src_ip; /* in network byte order */ 1287ec2f6bcSAndrey V. Elsukov struct in6_addr dst_ip6; 1297ec2f6bcSAndrey V. Elsukov struct in6_addr src_ip6; 1307ec2f6bcSAndrey V. Elsukov 1317ec2f6bcSAndrey V. Elsukov uint16_t dst_port; /* in host byte order */ 1327ec2f6bcSAndrey V. Elsukov uint16_t src_port; /* in host byte order */ 1337ec2f6bcSAndrey V. Elsukov 1347ec2f6bcSAndrey V. Elsukov uint32_t flowid; /* IPv6 flowid */ 1357ec2f6bcSAndrey V. Elsukov uint32_t extra; 1367ec2f6bcSAndrey V. Elsukov 1377ec2f6bcSAndrey V. Elsukov /* ipfw_rule_ref */ 1387ec2f6bcSAndrey V. Elsukov uint32_t slot; 1397ec2f6bcSAndrey V. Elsukov uint32_t rulenum; 1407ec2f6bcSAndrey V. Elsukov uint32_t rule_id; 1417ec2f6bcSAndrey V. Elsukov uint32_t chain_id; 1427ec2f6bcSAndrey V. Elsukov uint32_t match_info; 1437ec2f6bcSAndrey V. Elsukov } ipfw_match_info_t; 1447ec2f6bcSAndrey V. Elsukov 1457ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" translator 1467ec2f6bcSAndrey V. Elsukov translator ipfw_match_info_t < struct ip_fw_args *p > { 1477ec2f6bcSAndrey V. Elsukov flags = p->flags; 1487ec2f6bcSAndrey V. Elsukov m = (p->flags & IPFW_ARGS_LENMASK) ? NULL : p->m; 1497ec2f6bcSAndrey V. Elsukov mem = (p->flags & IPFW_ARGS_LENMASK) ? p->mem : NULL; 1507ec2f6bcSAndrey V. Elsukov inp = p->inp; 1517ec2f6bcSAndrey V. Elsukov ifp = p->ifp; 1527ec2f6bcSAndrey V. Elsukov /* Initialize IP pointer corresponding to addr_type */ 1537ec2f6bcSAndrey V. Elsukov ipp = (p->flags & IPFW_ARGS_IP4) ? 1547ec2f6bcSAndrey V. Elsukov (p->flags & IPFW_ARGS_LENMASK) ? (struct ip *)p->mem : 1557ec2f6bcSAndrey V. Elsukov (p->m != NULL) ? (struct ip *)p->m->m_data : NULL : NULL; 1567ec2f6bcSAndrey V. Elsukov ip6p = (p->flags & IPFW_ARGS_IP6) ? 1577ec2f6bcSAndrey V. Elsukov (p->flags & IPFW_ARGS_LENMASK) ? (struct ip6_hdr *)p->mem : 1587ec2f6bcSAndrey V. Elsukov (p->m != NULL) ? (struct ip6_hdr *)p->m->m_data : NULL : NULL; 1597ec2f6bcSAndrey V. Elsukov 1607ec2f6bcSAndrey V. Elsukov /* fill f_id fields */ 1617ec2f6bcSAndrey V. Elsukov addr_type = p->f_id.addr_type; 1627ec2f6bcSAndrey V. Elsukov proto = p->f_id.proto; 1637ec2f6bcSAndrey V. Elsukov proto_flags = p->f_id._flags; 1647ec2f6bcSAndrey V. Elsukov 1657ec2f6bcSAndrey V. Elsukov /* f_id.fib keeps truncated fibnum, use mbuf's fibnum if possible */ 1667ec2f6bcSAndrey V. Elsukov fib = p->m != NULL ? p->m->m_pkthdr.fibnum : p->f_id.fib; 1677ec2f6bcSAndrey V. Elsukov 1687ec2f6bcSAndrey V. Elsukov /* 1697ec2f6bcSAndrey V. Elsukov * ipfw_chk() keeps IPv4 addresses in host byte order. But for 1707ec2f6bcSAndrey V. Elsukov * dtrace script it is useful to have them in network byte order, 1717ec2f6bcSAndrey V. Elsukov * because inet_ntoa() uses address in network byte order. 1727ec2f6bcSAndrey V. Elsukov */ 1737ec2f6bcSAndrey V. Elsukov dst_ip = htonl(p->f_id.dst_ip); 1747ec2f6bcSAndrey V. Elsukov src_ip = htonl(p->f_id.src_ip); 1757ec2f6bcSAndrey V. Elsukov 1767ec2f6bcSAndrey V. Elsukov dst_ip6 = p->f_id.dst_ip6; 1777ec2f6bcSAndrey V. Elsukov src_ip6 = p->f_id.src_ip6; 1787ec2f6bcSAndrey V. Elsukov 1797ec2f6bcSAndrey V. Elsukov dst_port = p->f_id.dst_port; 1807ec2f6bcSAndrey V. Elsukov src_port = p->f_id.src_port; 1817ec2f6bcSAndrey V. Elsukov 1827ec2f6bcSAndrey V. Elsukov flowid = p->f_id.flow_id6; 1837ec2f6bcSAndrey V. Elsukov extra = p->f_id.extra; 1847ec2f6bcSAndrey V. Elsukov 1857ec2f6bcSAndrey V. Elsukov /* ipfw_rule_ref */ 1867ec2f6bcSAndrey V. Elsukov slot = (p->flags & IPFW_ARGS_REF) ? p->rule.slot : 0; 1877ec2f6bcSAndrey V. Elsukov rulenum = (p->flags & IPFW_ARGS_REF) ? p->rule.rulenum : 0; 1887ec2f6bcSAndrey V. Elsukov rule_id = (p->flags & IPFW_ARGS_REF) ? p->rule.rule_id : 0; 1897ec2f6bcSAndrey V. Elsukov chain_id = (p->flags & IPFW_ARGS_REF) ? p->rule.chain_id : 0; 1907ec2f6bcSAndrey V. Elsukov match_info = (p->flags & IPFW_ARGS_REF) ? p->rule.info : 0; 1917ec2f6bcSAndrey V. Elsukov }; 1927ec2f6bcSAndrey V. Elsukov 1937ec2f6bcSAndrey V. Elsukov typedef struct ipfw_rule_info { 1947ec2f6bcSAndrey V. Elsukov uint16_t act_ofs; 1957ec2f6bcSAndrey V. Elsukov uint16_t cmd_len; 1967ec2f6bcSAndrey V. Elsukov uint32_t rulenum; 1977ec2f6bcSAndrey V. Elsukov uint8_t flags; 1987ec2f6bcSAndrey V. Elsukov uint8_t set; 1997ec2f6bcSAndrey V. Elsukov uint32_t rule_id; 2007ec2f6bcSAndrey V. Elsukov uint32_t cached_id; 2017ec2f6bcSAndrey V. Elsukov uint32_t cached_pos; 2027ec2f6bcSAndrey V. Elsukov uint32_t refcnt; 2037ec2f6bcSAndrey V. Elsukov } ipfw_rule_info_t; 2047ec2f6bcSAndrey V. Elsukov 2057ec2f6bcSAndrey V. Elsukov #pragma D binding "1.0" translator 2067ec2f6bcSAndrey V. Elsukov translator ipfw_rule_info_t < struct ip_fw *r > { 2077ec2f6bcSAndrey V. Elsukov act_ofs = r->act_ofs; 2087ec2f6bcSAndrey V. Elsukov cmd_len = r->cmd_len; 2097ec2f6bcSAndrey V. Elsukov rulenum = r->rulenum; 2107ec2f6bcSAndrey V. Elsukov flags = r->flags; 2117ec2f6bcSAndrey V. Elsukov set = r->set; 2127ec2f6bcSAndrey V. Elsukov rule_id = r->id; 2135c8e8e82SAndrey V. Elsukov cached_id = r->cache.id; 2145c8e8e82SAndrey V. Elsukov cached_pos = r->cache.pos; 2157ec2f6bcSAndrey V. Elsukov refcnt = r->refcnt; 2167ec2f6bcSAndrey V. Elsukov }; 2177ec2f6bcSAndrey V. Elsukov 218