13b3a8eb9SGleb Smirnoff /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 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 283b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 293b3a8eb9SGleb Smirnoff /* 303b3a8eb9SGleb Smirnoff * Logging support for ipfw 313b3a8eb9SGleb Smirnoff */ 323b3a8eb9SGleb Smirnoff 333b3a8eb9SGleb Smirnoff #include "opt_ipfw.h" 343b3a8eb9SGleb Smirnoff #include "opt_inet.h" 353b3a8eb9SGleb Smirnoff #ifndef INET 363b3a8eb9SGleb Smirnoff #error IPFIREWALL requires INET. 373b3a8eb9SGleb Smirnoff #endif /* INET */ 383b3a8eb9SGleb Smirnoff #include "opt_inet6.h" 393b3a8eb9SGleb Smirnoff 403b3a8eb9SGleb Smirnoff #include <sys/param.h> 413b3a8eb9SGleb Smirnoff #include <sys/systm.h> 423b3a8eb9SGleb Smirnoff #include <sys/kernel.h> 438ec07310SGleb Smirnoff #include <sys/mbuf.h> 443b3a8eb9SGleb Smirnoff #include <sys/socket.h> 453b3a8eb9SGleb Smirnoff #include <sys/sysctl.h> 463b3a8eb9SGleb Smirnoff #include <sys/syslog.h> 473b3a8eb9SGleb Smirnoff #include <net/ethernet.h> /* for ETHERTYPE_IP */ 483b3a8eb9SGleb Smirnoff #include <net/if.h> 49*4a77657cSAndrey V. Elsukov #include <net/if_dl.h> 5076039bc8SGleb Smirnoff #include <net/if_var.h> 513d0d5b21SJustin Hibbits #include <net/if_private.h> 523b3a8eb9SGleb Smirnoff #include <net/vnet.h> 53*4a77657cSAndrey V. Elsukov #include <net/route.h> 54*4a77657cSAndrey V. Elsukov #include <net/route/route_var.h> 553b3a8eb9SGleb Smirnoff 563b3a8eb9SGleb Smirnoff #include <netinet/in.h> 573b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 583b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 593b3a8eb9SGleb Smirnoff #include <netinet/ip_var.h> 603b3a8eb9SGleb Smirnoff #include <netinet/ip_fw.h> 613b3a8eb9SGleb Smirnoff #include <netinet/udp.h> 620dff875fSGleb Smirnoff #include <netinet/tcp.h> 633b3a8eb9SGleb Smirnoff 643b3a8eb9SGleb Smirnoff #include <netinet/ip6.h> 653b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 663b3a8eb9SGleb Smirnoff #ifdef INET6 673b3a8eb9SGleb Smirnoff #include <netinet6/in6_var.h> /* ip6_sprintf() */ 683b3a8eb9SGleb Smirnoff #endif 693b3a8eb9SGleb Smirnoff 703b3a8eb9SGleb Smirnoff #include <netpfil/ipfw/ip_fw_private.h> 713b3a8eb9SGleb Smirnoff 723b3a8eb9SGleb Smirnoff #ifdef MAC 733b3a8eb9SGleb Smirnoff #include <security/mac/mac_framework.h> 743b3a8eb9SGleb Smirnoff #endif 753b3a8eb9SGleb Smirnoff 763b3a8eb9SGleb Smirnoff /* 773b3a8eb9SGleb Smirnoff * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T 783b3a8eb9SGleb Smirnoff * Other macros just cast void * into the appropriate type 793b3a8eb9SGleb Smirnoff */ 803b3a8eb9SGleb Smirnoff #define L3HDR(T, ip) ((T *)((u_int32_t *)(ip) + (ip)->ip_hl)) 813b3a8eb9SGleb Smirnoff #define TCP(p) ((struct tcphdr *)(p)) 823b3a8eb9SGleb Smirnoff #define SCTP(p) ((struct sctphdr *)(p)) 833b3a8eb9SGleb Smirnoff #define UDP(p) ((struct udphdr *)(p)) 843b3a8eb9SGleb Smirnoff #define ICMP(p) ((struct icmphdr *)(p)) 853b3a8eb9SGleb Smirnoff #define ICMP6(p) ((struct icmp6_hdr *)(p)) 863b3a8eb9SGleb Smirnoff 87d0f65d47SLuigi Rizzo #ifdef __APPLE__ 88d0f65d47SLuigi Rizzo #undef snprintf 89d0f65d47SLuigi Rizzo #define snprintf sprintf 90d0f65d47SLuigi Rizzo #define SNPARGS(buf, len) buf + len 91d0f65d47SLuigi Rizzo #define SNP(buf) buf 92d0f65d47SLuigi Rizzo #else /* !__APPLE__ */ 933b3a8eb9SGleb Smirnoff #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 943b3a8eb9SGleb Smirnoff #define SNP(buf) buf, sizeof(buf) 95d0f65d47SLuigi Rizzo #endif /* !__APPLE__ */ 963b3a8eb9SGleb Smirnoff 970cba2b28SAlexander V. Chernikov #define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f) 983b3a8eb9SGleb Smirnoff 99*4a77657cSAndrey V. Elsukov static void 100*4a77657cSAndrey V. Elsukov ipfw_log_ipfw0(struct ip_fw_args *args, struct ip *ip) 101*4a77657cSAndrey V. Elsukov { 102f355cb3eSGleb Smirnoff if (args->flags & IPFW_ARGS_LENMASK) 103f355cb3eSGleb Smirnoff ipfw_bpf_tap(args->mem, IPFW_ARGS_LENGTH(args->flags)); 104f355cb3eSGleb Smirnoff else if (args->flags & IPFW_ARGS_ETHER) 105f355cb3eSGleb Smirnoff /* layer2, use orig hdr */ 106f355cb3eSGleb Smirnoff ipfw_bpf_mtap(args->m); 107b49bf73fSPhilip Paeps else { 1083b3a8eb9SGleb Smirnoff /* Add fake header. Later we will store 1093b3a8eb9SGleb Smirnoff * more info in the header. 1103b3a8eb9SGleb Smirnoff */ 111b49bf73fSPhilip Paeps if (ip->ip_v == 4) 11256132dccSAndrey V. Elsukov ipfw_bpf_mtap2("DDDDDDSSSSSS\x08\x00", 113f355cb3eSGleb Smirnoff ETHER_HDR_LEN, args->m); 114b49bf73fSPhilip Paeps else if (ip->ip_v == 6) 11556132dccSAndrey V. Elsukov ipfw_bpf_mtap2("DDDDDDSSSSSS\x86\xdd", 116f355cb3eSGleb Smirnoff ETHER_HDR_LEN, args->m); 117b49bf73fSPhilip Paeps else 118b49bf73fSPhilip Paeps /* Obviously bogus EtherType. */ 11956132dccSAndrey V. Elsukov ipfw_bpf_mtap2("DDDDDDSSSSSS\xff\xff", 120f355cb3eSGleb Smirnoff ETHER_HDR_LEN, args->m); 121b49bf73fSPhilip Paeps } 1223b3a8eb9SGleb Smirnoff } 123*4a77657cSAndrey V. Elsukov 124*4a77657cSAndrey V. Elsukov /* 125*4a77657cSAndrey V. Elsukov * XXX this function alone takes about 2Kbytes of code! 126*4a77657cSAndrey V. Elsukov */ 127*4a77657cSAndrey V. Elsukov static void 128*4a77657cSAndrey V. Elsukov ipfw_log_syslog(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 129*4a77657cSAndrey V. Elsukov struct ip_fw_args *args, u_short offset, uint32_t tablearg, struct ip *ip) 130*4a77657cSAndrey V. Elsukov { 131*4a77657cSAndrey V. Elsukov char *action; 132*4a77657cSAndrey V. Elsukov int limit_reached = 0; 133*4a77657cSAndrey V. Elsukov char action2[92], proto[128], fragment[32], mark_str[24]; 134*4a77657cSAndrey V. Elsukov 1353b3a8eb9SGleb Smirnoff fragment[0] = '\0'; 1363b3a8eb9SGleb Smirnoff proto[0] = '\0'; 1373b3a8eb9SGleb Smirnoff 1383b3a8eb9SGleb Smirnoff if (f == NULL) { /* bogus pkt */ 1393b3a8eb9SGleb Smirnoff if (V_verbose_limit != 0 && V_norule_counter >= V_verbose_limit) 1403b3a8eb9SGleb Smirnoff return; 1413b3a8eb9SGleb Smirnoff V_norule_counter++; 1423b3a8eb9SGleb Smirnoff if (V_norule_counter == V_verbose_limit) 1433b3a8eb9SGleb Smirnoff limit_reached = V_verbose_limit; 1443b3a8eb9SGleb Smirnoff action = "Refuse"; 1453b3a8eb9SGleb Smirnoff } else { /* O_LOG is the first action, find the real one */ 1463b3a8eb9SGleb Smirnoff ipfw_insn *cmd = ACTION_PTR(f); 1473b3a8eb9SGleb Smirnoff ipfw_insn_log *l = (ipfw_insn_log *)cmd; 1483b3a8eb9SGleb Smirnoff 1493b3a8eb9SGleb Smirnoff if (l->max_log != 0 && l->log_left == 0) 1503b3a8eb9SGleb Smirnoff return; 1513b3a8eb9SGleb Smirnoff l->log_left--; 1523b3a8eb9SGleb Smirnoff if (l->log_left == 0) 1533b3a8eb9SGleb Smirnoff limit_reached = l->max_log; 1543b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); /* point to first action */ 1553b3a8eb9SGleb Smirnoff if (cmd->opcode == O_ALTQ) { 1563b3a8eb9SGleb Smirnoff ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd; 1573b3a8eb9SGleb Smirnoff 1583b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Altq %d", 1593b3a8eb9SGleb Smirnoff altq->qid); 1603b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); 1613b3a8eb9SGleb Smirnoff } 1624763c0aaSAndrey V. Elsukov if (cmd->opcode == O_PROB || cmd->opcode == O_TAG) 1633b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); 1643b3a8eb9SGleb Smirnoff 1653b3a8eb9SGleb Smirnoff action = action2; 1663b3a8eb9SGleb Smirnoff switch (cmd->opcode) { 1673b3a8eb9SGleb Smirnoff case O_DENY: 1683b3a8eb9SGleb Smirnoff action = "Deny"; 1693b3a8eb9SGleb Smirnoff break; 1703b3a8eb9SGleb Smirnoff 1713b3a8eb9SGleb Smirnoff case O_REJECT: 1723b3a8eb9SGleb Smirnoff if (cmd->arg1==ICMP_REJECT_RST) 1733b3a8eb9SGleb Smirnoff action = "Reset"; 174665c8a2eSMichael Tuexen else if (cmd->arg1==ICMP_REJECT_ABORT) 175665c8a2eSMichael Tuexen action = "Abort"; 1763b3a8eb9SGleb Smirnoff else if (cmd->arg1==ICMP_UNREACH_HOST) 1773b3a8eb9SGleb Smirnoff action = "Reject"; 1783b3a8eb9SGleb Smirnoff else 1793b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Unreach %d", 1803b3a8eb9SGleb Smirnoff cmd->arg1); 1813b3a8eb9SGleb Smirnoff break; 1823b3a8eb9SGleb Smirnoff 1833b3a8eb9SGleb Smirnoff case O_UNREACH6: 1843b3a8eb9SGleb Smirnoff if (cmd->arg1==ICMP6_UNREACH_RST) 1853b3a8eb9SGleb Smirnoff action = "Reset"; 186665c8a2eSMichael Tuexen else if (cmd->arg1==ICMP6_UNREACH_ABORT) 187665c8a2eSMichael Tuexen action = "Abort"; 1883b3a8eb9SGleb Smirnoff else 1893b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Unreach %d", 1903b3a8eb9SGleb Smirnoff cmd->arg1); 1913b3a8eb9SGleb Smirnoff break; 1923b3a8eb9SGleb Smirnoff 1933b3a8eb9SGleb Smirnoff case O_ACCEPT: 1943b3a8eb9SGleb Smirnoff action = "Accept"; 1953b3a8eb9SGleb Smirnoff break; 1963b3a8eb9SGleb Smirnoff case O_COUNT: 1973b3a8eb9SGleb Smirnoff action = "Count"; 1983b3a8eb9SGleb Smirnoff break; 1993b3a8eb9SGleb Smirnoff case O_DIVERT: 2003b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Divert %d", 2010cba2b28SAlexander V. Chernikov TARG(cmd->arg1, divert)); 2023b3a8eb9SGleb Smirnoff break; 2033b3a8eb9SGleb Smirnoff case O_TEE: 2043b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Tee %d", 2050cba2b28SAlexander V. Chernikov TARG(cmd->arg1, divert)); 2063b3a8eb9SGleb Smirnoff break; 2074763c0aaSAndrey V. Elsukov case O_SETDSCP: 2084763c0aaSAndrey V. Elsukov snprintf(SNPARGS(action2, 0), "SetDscp %d", 2094763c0aaSAndrey V. Elsukov TARG(cmd->arg1, dscp) & 0x3F); 2104763c0aaSAndrey V. Elsukov break; 2113b3a8eb9SGleb Smirnoff case O_SETFIB: 2123b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "SetFib %d", 21391e93dafSAlexander V. Chernikov TARG(cmd->arg1, fib) & 0x7FFF); 2143b3a8eb9SGleb Smirnoff break; 2153b3a8eb9SGleb Smirnoff case O_SKIPTO: 2163b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "SkipTo %d", 217*4a77657cSAndrey V. Elsukov TARG(insntod(cmd, u32)->d[0], skipto)); 2183b3a8eb9SGleb Smirnoff break; 2193b3a8eb9SGleb Smirnoff case O_PIPE: 2203b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Pipe %d", 2210cba2b28SAlexander V. Chernikov TARG(cmd->arg1, pipe)); 2223b3a8eb9SGleb Smirnoff break; 2233b3a8eb9SGleb Smirnoff case O_QUEUE: 2243b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Queue %d", 2250cba2b28SAlexander V. Chernikov TARG(cmd->arg1, pipe)); 2263b3a8eb9SGleb Smirnoff break; 2273b3a8eb9SGleb Smirnoff case O_FORWARD_IP: { 2288144690aSEric van Gyzen char buf[INET_ADDRSTRLEN]; 2293b3a8eb9SGleb Smirnoff ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd; 2303b3a8eb9SGleb Smirnoff int len; 2313b3a8eb9SGleb Smirnoff struct in_addr dummyaddr; 2323b3a8eb9SGleb Smirnoff if (sa->sa.sin_addr.s_addr == INADDR_ANY) 2333b3a8eb9SGleb Smirnoff dummyaddr.s_addr = htonl(tablearg); 2343b3a8eb9SGleb Smirnoff else 2353b3a8eb9SGleb Smirnoff dummyaddr.s_addr = sa->sa.sin_addr.s_addr; 2363b3a8eb9SGleb Smirnoff 2373b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(action2, 0), "Forward to %s", 2388144690aSEric van Gyzen inet_ntoa_r(dummyaddr, buf)); 2393b3a8eb9SGleb Smirnoff 2403b3a8eb9SGleb Smirnoff if (sa->sa.sin_port) 2413b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, len), ":%d", 2423b3a8eb9SGleb Smirnoff sa->sa.sin_port); 2433b3a8eb9SGleb Smirnoff } 2443b3a8eb9SGleb Smirnoff break; 2453b3a8eb9SGleb Smirnoff #ifdef INET6 2463b3a8eb9SGleb Smirnoff case O_FORWARD_IP6: { 2473b3a8eb9SGleb Smirnoff char buf[INET6_ADDRSTRLEN]; 2483b3a8eb9SGleb Smirnoff ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd; 2493b3a8eb9SGleb Smirnoff int len; 2503b3a8eb9SGleb Smirnoff 2513b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(action2, 0), "Forward to [%s]", 2523b3a8eb9SGleb Smirnoff ip6_sprintf(buf, &sa->sa.sin6_addr)); 2533b3a8eb9SGleb Smirnoff 2543b3a8eb9SGleb Smirnoff if (sa->sa.sin6_port) 2553b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, len), ":%u", 2563b3a8eb9SGleb Smirnoff sa->sa.sin6_port); 2573b3a8eb9SGleb Smirnoff } 2583b3a8eb9SGleb Smirnoff break; 2593b3a8eb9SGleb Smirnoff #endif 2603b3a8eb9SGleb Smirnoff case O_NETGRAPH: 2613b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Netgraph %d", 2623b3a8eb9SGleb Smirnoff cmd->arg1); 2633b3a8eb9SGleb Smirnoff break; 2643b3a8eb9SGleb Smirnoff case O_NGTEE: 2653b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Ngtee %d", 2663b3a8eb9SGleb Smirnoff cmd->arg1); 2673b3a8eb9SGleb Smirnoff break; 2683b3a8eb9SGleb Smirnoff case O_NAT: 2693b3a8eb9SGleb Smirnoff action = "Nat"; 2703b3a8eb9SGleb Smirnoff break; 2713b3a8eb9SGleb Smirnoff case O_REASS: 2723b3a8eb9SGleb Smirnoff action = "Reass"; 2733b3a8eb9SGleb Smirnoff break; 2743b3a8eb9SGleb Smirnoff case O_CALLRETURN: 2753b3a8eb9SGleb Smirnoff if (cmd->len & F_NOT) 276*4a77657cSAndrey V. Elsukov snprintf(SNPARGS(action2, 0), "Return %s", 277*4a77657cSAndrey V. Elsukov cmd->arg1 == RETURN_NEXT_RULENUM ? 278*4a77657cSAndrey V. Elsukov "next-rulenum": "next-rule"); 2793b3a8eb9SGleb Smirnoff else 2803b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Call %d", 281*4a77657cSAndrey V. Elsukov TARG(insntod(cmd, u32)->d[0], skipto)); 2823b3a8eb9SGleb Smirnoff break; 283fc727ad6SBoris Lytochkin case O_SETMARK: 284fc727ad6SBoris Lytochkin if (cmd->arg1 == IP_FW_TARG) 285*4a77657cSAndrey V. Elsukov snprintf(SNPARGS(action2, 0), "SetMark %#010x", 286fc727ad6SBoris Lytochkin TARG(cmd->arg1, mark)); 287fc727ad6SBoris Lytochkin else 288*4a77657cSAndrey V. Elsukov snprintf(SNPARGS(action2, 0), "SetMark %#010x", 289*4a77657cSAndrey V. Elsukov insntoc(cmd, u32)->d[0]); 290fc727ad6SBoris Lytochkin break; 291399ad578SAndrey V. Elsukov case O_EXTERNAL_ACTION: 292399ad578SAndrey V. Elsukov snprintf(SNPARGS(action2, 0), "Eaction %s", 293399ad578SAndrey V. Elsukov ((struct named_object *)SRV_OBJECT(chain, 294*4a77657cSAndrey V. Elsukov insntod(cmd, kidx)->kidx))->name); 295399ad578SAndrey V. Elsukov break; 2963b3a8eb9SGleb Smirnoff default: 2973b3a8eb9SGleb Smirnoff action = "UNKNOWN"; 2983b3a8eb9SGleb Smirnoff break; 2993b3a8eb9SGleb Smirnoff } 3003b3a8eb9SGleb Smirnoff } 3013b3a8eb9SGleb Smirnoff 3023b3a8eb9SGleb Smirnoff if (hlen == 0) { /* non-ip */ 3033b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, 0), "MAC"); 3043b3a8eb9SGleb Smirnoff 3053b3a8eb9SGleb Smirnoff } else { 3063b3a8eb9SGleb Smirnoff int len; 3073b3a8eb9SGleb Smirnoff #ifdef INET6 3083b3a8eb9SGleb Smirnoff char src[INET6_ADDRSTRLEN + 2], dst[INET6_ADDRSTRLEN + 2]; 3093b3a8eb9SGleb Smirnoff #else 3103b3a8eb9SGleb Smirnoff char src[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN]; 3113b3a8eb9SGleb Smirnoff #endif 3123b3a8eb9SGleb Smirnoff struct icmphdr *icmp; 3133b3a8eb9SGleb Smirnoff struct tcphdr *tcp; 3143b3a8eb9SGleb Smirnoff struct udphdr *udp; 3153b3a8eb9SGleb Smirnoff #ifdef INET6 3163b3a8eb9SGleb Smirnoff struct ip6_hdr *ip6 = NULL; 3173b3a8eb9SGleb Smirnoff struct icmp6_hdr *icmp6; 3183b3a8eb9SGleb Smirnoff u_short ip6f_mf; 3193b3a8eb9SGleb Smirnoff #endif 3203b3a8eb9SGleb Smirnoff src[0] = '\0'; 3213b3a8eb9SGleb Smirnoff dst[0] = '\0'; 3223b3a8eb9SGleb Smirnoff #ifdef INET6 3233b3a8eb9SGleb Smirnoff ip6f_mf = offset & IP6F_MORE_FRAG; 3243b3a8eb9SGleb Smirnoff offset &= IP6F_OFF_MASK; 3253b3a8eb9SGleb Smirnoff 3263b3a8eb9SGleb Smirnoff if (IS_IP6_FLOW_ID(&(args->f_id))) { 3273b3a8eb9SGleb Smirnoff char ip6buf[INET6_ADDRSTRLEN]; 3283b3a8eb9SGleb Smirnoff snprintf(src, sizeof(src), "[%s]", 3293b3a8eb9SGleb Smirnoff ip6_sprintf(ip6buf, &args->f_id.src_ip6)); 3303b3a8eb9SGleb Smirnoff snprintf(dst, sizeof(dst), "[%s]", 3313b3a8eb9SGleb Smirnoff ip6_sprintf(ip6buf, &args->f_id.dst_ip6)); 3323b3a8eb9SGleb Smirnoff 3333b3a8eb9SGleb Smirnoff ip6 = (struct ip6_hdr *)ip; 3343b3a8eb9SGleb Smirnoff tcp = (struct tcphdr *)(((char *)ip) + hlen); 3353b3a8eb9SGleb Smirnoff udp = (struct udphdr *)(((char *)ip) + hlen); 3363b3a8eb9SGleb Smirnoff } else 3373b3a8eb9SGleb Smirnoff #endif 3383b3a8eb9SGleb Smirnoff { 3393b3a8eb9SGleb Smirnoff tcp = L3HDR(struct tcphdr, ip); 3403b3a8eb9SGleb Smirnoff udp = L3HDR(struct udphdr, ip); 3413b3a8eb9SGleb Smirnoff 3423b3a8eb9SGleb Smirnoff inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); 3433b3a8eb9SGleb Smirnoff inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); 3443b3a8eb9SGleb Smirnoff } 3453b3a8eb9SGleb Smirnoff 3463b3a8eb9SGleb Smirnoff switch (args->f_id.proto) { 3473b3a8eb9SGleb Smirnoff case IPPROTO_TCP: 3483b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "TCP %s", src); 3493b3a8eb9SGleb Smirnoff if (offset == 0) 3503b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), ":%d %s:%d", 3513b3a8eb9SGleb Smirnoff ntohs(tcp->th_sport), 3523b3a8eb9SGleb Smirnoff dst, 3533b3a8eb9SGleb Smirnoff ntohs(tcp->th_dport)); 3543b3a8eb9SGleb Smirnoff else 3553b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 3563b3a8eb9SGleb Smirnoff break; 3573b3a8eb9SGleb Smirnoff 3583b3a8eb9SGleb Smirnoff case IPPROTO_UDP: 359d3834420SAndrey V. Elsukov case IPPROTO_UDPLITE: 360d3834420SAndrey V. Elsukov len = snprintf(SNPARGS(proto, 0), "UDP%s%s", 361d3834420SAndrey V. Elsukov args->f_id.proto == IPPROTO_UDP ? " ": "Lite ", 362d3834420SAndrey V. Elsukov src); 3633b3a8eb9SGleb Smirnoff if (offset == 0) 3643b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), ":%d %s:%d", 3653b3a8eb9SGleb Smirnoff ntohs(udp->uh_sport), 3663b3a8eb9SGleb Smirnoff dst, 3673b3a8eb9SGleb Smirnoff ntohs(udp->uh_dport)); 3683b3a8eb9SGleb Smirnoff else 3693b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 3703b3a8eb9SGleb Smirnoff break; 3713b3a8eb9SGleb Smirnoff 3723b3a8eb9SGleb Smirnoff case IPPROTO_ICMP: 3733b3a8eb9SGleb Smirnoff icmp = L3HDR(struct icmphdr, ip); 3743b3a8eb9SGleb Smirnoff if (offset == 0) 3753b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), 3763b3a8eb9SGleb Smirnoff "ICMP:%u.%u ", 3773b3a8eb9SGleb Smirnoff icmp->icmp_type, icmp->icmp_code); 3783b3a8eb9SGleb Smirnoff else 3793b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "ICMP "); 3803b3a8eb9SGleb Smirnoff len += snprintf(SNPARGS(proto, len), "%s", src); 3813b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 3823b3a8eb9SGleb Smirnoff break; 3833b3a8eb9SGleb Smirnoff #ifdef INET6 3843b3a8eb9SGleb Smirnoff case IPPROTO_ICMPV6: 3853b3a8eb9SGleb Smirnoff icmp6 = (struct icmp6_hdr *)(((char *)ip) + hlen); 3863b3a8eb9SGleb Smirnoff if (offset == 0) 3873b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), 3883b3a8eb9SGleb Smirnoff "ICMPv6:%u.%u ", 3893b3a8eb9SGleb Smirnoff icmp6->icmp6_type, icmp6->icmp6_code); 3903b3a8eb9SGleb Smirnoff else 3913b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "ICMPv6 "); 3923b3a8eb9SGleb Smirnoff len += snprintf(SNPARGS(proto, len), "%s", src); 3933b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 3943b3a8eb9SGleb Smirnoff break; 3953b3a8eb9SGleb Smirnoff #endif 3963b3a8eb9SGleb Smirnoff default: 3973b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "P:%d %s", 3983b3a8eb9SGleb Smirnoff args->f_id.proto, src); 3993b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 4003b3a8eb9SGleb Smirnoff break; 4013b3a8eb9SGleb Smirnoff } 4023b3a8eb9SGleb Smirnoff 4033b3a8eb9SGleb Smirnoff #ifdef INET6 4043b3a8eb9SGleb Smirnoff if (IS_IP6_FLOW_ID(&(args->f_id))) { 405bf55a003SAndrey V. Elsukov if (offset || ip6f_mf) 4063b3a8eb9SGleb Smirnoff snprintf(SNPARGS(fragment, 0), 4073b3a8eb9SGleb Smirnoff " (frag %08x:%d@%d%s)", 4083b3a8eb9SGleb Smirnoff args->f_id.extra, 4093b3a8eb9SGleb Smirnoff ntohs(ip6->ip6_plen) - hlen, 4103b3a8eb9SGleb Smirnoff ntohs(offset) << 3, ip6f_mf ? "+" : ""); 4113b3a8eb9SGleb Smirnoff } else 4123b3a8eb9SGleb Smirnoff #endif 4133b3a8eb9SGleb Smirnoff { 4143b3a8eb9SGleb Smirnoff int ipoff, iplen; 4153b3a8eb9SGleb Smirnoff ipoff = ntohs(ip->ip_off); 4163b3a8eb9SGleb Smirnoff iplen = ntohs(ip->ip_len); 4173b3a8eb9SGleb Smirnoff if (ipoff & (IP_MF | IP_OFFMASK)) 4183b3a8eb9SGleb Smirnoff snprintf(SNPARGS(fragment, 0), 4193b3a8eb9SGleb Smirnoff " (frag %d:%d@%d%s)", 4203b3a8eb9SGleb Smirnoff ntohs(ip->ip_id), iplen - (ip->ip_hl << 2), 4213b3a8eb9SGleb Smirnoff offset << 3, 4223b3a8eb9SGleb Smirnoff (ipoff & IP_MF) ? "+" : ""); 4233b3a8eb9SGleb Smirnoff } 4243b3a8eb9SGleb Smirnoff } 425fc727ad6SBoris Lytochkin 426fc727ad6SBoris Lytochkin /* [fw]mark */ 427fc727ad6SBoris Lytochkin if (args->rule.pkt_mark) 428fc727ad6SBoris Lytochkin snprintf(SNPARGS(mark_str, 0), " mark:%#x", 429fc727ad6SBoris Lytochkin args->rule.pkt_mark); 430fc727ad6SBoris Lytochkin else 431fc727ad6SBoris Lytochkin mark_str[0] = '\0'; 432fc727ad6SBoris Lytochkin 4333b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 434fc727ad6SBoris Lytochkin log(LOG_SECURITY | LOG_INFO, "ipfw: %d %s %s%s %s via %s%s\n", 435fc727ad6SBoris Lytochkin f ? f->rulenum : -1, action, proto, mark_str, 436b7795b67SGleb Smirnoff args->flags & IPFW_ARGS_OUT ? "out" : "in", args->ifp->if_xname, 4373b3a8eb9SGleb Smirnoff fragment); 438b7795b67SGleb Smirnoff #else 439fc727ad6SBoris Lytochkin log(LOG_SECURITY | LOG_INFO, "ipfw: %d %s %s%s [no if info]%s\n", 440fc727ad6SBoris Lytochkin f ? f->rulenum : -1, action, proto, mark_str, fragment); 4413b3a8eb9SGleb Smirnoff #endif 4423b3a8eb9SGleb Smirnoff if (limit_reached) 4433b3a8eb9SGleb Smirnoff log(LOG_SECURITY | LOG_NOTICE, 4443b3a8eb9SGleb Smirnoff "ipfw: limit %d reached on entry %d\n", 4453b3a8eb9SGleb Smirnoff limit_reached, f ? f->rulenum : -1); 4463b3a8eb9SGleb Smirnoff } 447*4a77657cSAndrey V. Elsukov 448*4a77657cSAndrey V. Elsukov static void 449*4a77657cSAndrey V. Elsukov ipfw_rtsocklog_fill_l3(struct ip_fw_args *args, 450*4a77657cSAndrey V. Elsukov char **buf, struct sockaddr **src, struct sockaddr **dst) 451*4a77657cSAndrey V. Elsukov { 452*4a77657cSAndrey V. Elsukov struct sockaddr_in *v4src, *v4dst; 453*4a77657cSAndrey V. Elsukov #ifdef INET6 454*4a77657cSAndrey V. Elsukov struct sockaddr_in6 *v6src, *v6dst; 455*4a77657cSAndrey V. Elsukov 456*4a77657cSAndrey V. Elsukov if (IS_IP6_FLOW_ID(&(args->f_id))) { 457*4a77657cSAndrey V. Elsukov v6src = (struct sockaddr_in6 *)*buf; 458*4a77657cSAndrey V. Elsukov *buf += sizeof(*v6src); 459*4a77657cSAndrey V. Elsukov v6dst = (struct sockaddr_in6 *)*buf; 460*4a77657cSAndrey V. Elsukov *buf += sizeof(*v6dst); 461*4a77657cSAndrey V. Elsukov v6src->sin6_len = v6dst->sin6_len = sizeof(*v6src); 462*4a77657cSAndrey V. Elsukov v6src->sin6_family = v6dst->sin6_family = AF_INET6; 463*4a77657cSAndrey V. Elsukov v6src->sin6_addr = args->f_id.src_ip6; 464*4a77657cSAndrey V. Elsukov v6dst->sin6_addr = args->f_id.dst_ip6; 465*4a77657cSAndrey V. Elsukov 466*4a77657cSAndrey V. Elsukov *src = (struct sockaddr *)v6src; 467*4a77657cSAndrey V. Elsukov *dst = (struct sockaddr *)v6dst; 468*4a77657cSAndrey V. Elsukov } else 469*4a77657cSAndrey V. Elsukov #endif 470*4a77657cSAndrey V. Elsukov { 471*4a77657cSAndrey V. Elsukov v4src = (struct sockaddr_in *)*buf; 472*4a77657cSAndrey V. Elsukov *buf += sizeof(*v4src); 473*4a77657cSAndrey V. Elsukov v4dst = (struct sockaddr_in *)*buf; 474*4a77657cSAndrey V. Elsukov *buf += sizeof(*v4dst); 475*4a77657cSAndrey V. Elsukov v4src->sin_len = v4dst->sin_len = sizeof(*v4src); 476*4a77657cSAndrey V. Elsukov v4src->sin_family = v4dst->sin_family = AF_INET; 477*4a77657cSAndrey V. Elsukov v4src->sin_addr.s_addr = htonl(args->f_id.src_ip); 478*4a77657cSAndrey V. Elsukov v4dst->sin_addr.s_addr = htonl(args->f_id.dst_ip); 479*4a77657cSAndrey V. Elsukov 480*4a77657cSAndrey V. Elsukov *src = (struct sockaddr *)v4src; 481*4a77657cSAndrey V. Elsukov *dst = (struct sockaddr *)v4dst; 482*4a77657cSAndrey V. Elsukov } 483*4a77657cSAndrey V. Elsukov } 484*4a77657cSAndrey V. Elsukov 485*4a77657cSAndrey V. Elsukov static struct sockaddr * 486*4a77657cSAndrey V. Elsukov ipfw_rtsocklog_handle_tablearg(struct ip_fw_chain *chain, ipfw_insn *cmd, 487*4a77657cSAndrey V. Elsukov uint32_t tablearg, uint32_t *targ_value, char **buf) 488*4a77657cSAndrey V. Elsukov { 489*4a77657cSAndrey V. Elsukov struct sockaddr_in *v4nh = NULL; 490*4a77657cSAndrey V. Elsukov 491*4a77657cSAndrey V. Elsukov /* handle tablearg now */ 492*4a77657cSAndrey V. Elsukov switch (cmd->opcode) { 493*4a77657cSAndrey V. Elsukov case O_DIVERT: 494*4a77657cSAndrey V. Elsukov case O_TEE: 495*4a77657cSAndrey V. Elsukov *targ_value = TARG(cmd->arg1, divert); 496*4a77657cSAndrey V. Elsukov break; 497*4a77657cSAndrey V. Elsukov case O_NETGRAPH: 498*4a77657cSAndrey V. Elsukov case O_NGTEE: 499*4a77657cSAndrey V. Elsukov *targ_value = TARG(cmd->arg1, netgraph); 500*4a77657cSAndrey V. Elsukov break; 501*4a77657cSAndrey V. Elsukov case O_SETDSCP: 502*4a77657cSAndrey V. Elsukov *targ_value = (TARG(cmd->arg1, dscp) & 0x3F); 503*4a77657cSAndrey V. Elsukov break; 504*4a77657cSAndrey V. Elsukov case O_SETFIB: 505*4a77657cSAndrey V. Elsukov *targ_value = (TARG(cmd->arg1, fib) & 0x7FFF); 506*4a77657cSAndrey V. Elsukov break; 507*4a77657cSAndrey V. Elsukov case O_SKIPTO: 508*4a77657cSAndrey V. Elsukov case O_CALLRETURN: 509*4a77657cSAndrey V. Elsukov if (cmd->opcode == O_CALLRETURN && (cmd->len & F_NOT)) 510*4a77657cSAndrey V. Elsukov break; 511*4a77657cSAndrey V. Elsukov *targ_value = (TARG(insntod(cmd, u32)->d[0], skipto)); 512*4a77657cSAndrey V. Elsukov break; 513*4a77657cSAndrey V. Elsukov case O_PIPE: 514*4a77657cSAndrey V. Elsukov case O_QUEUE: 515*4a77657cSAndrey V. Elsukov *targ_value = TARG(cmd->arg1, pipe); 516*4a77657cSAndrey V. Elsukov break; 517*4a77657cSAndrey V. Elsukov case O_MARK: 518*4a77657cSAndrey V. Elsukov *targ_value = TARG(cmd->arg1, mark); 519*4a77657cSAndrey V. Elsukov break; 520*4a77657cSAndrey V. Elsukov case O_FORWARD_IP: 521*4a77657cSAndrey V. Elsukov v4nh = (struct sockaddr_in *)buf; 522*4a77657cSAndrey V. Elsukov buf += sizeof(*v4nh); 523*4a77657cSAndrey V. Elsukov *v4nh = ((ipfw_insn_sa *)cmd)->sa; 524*4a77657cSAndrey V. Elsukov if (v4nh->sin_addr.s_addr == INADDR_ANY) 525*4a77657cSAndrey V. Elsukov v4nh->sin_addr.s_addr = htonl(tablearg); 526*4a77657cSAndrey V. Elsukov 527*4a77657cSAndrey V. Elsukov return (struct sockaddr *)v4nh; 528*4a77657cSAndrey V. Elsukov #ifdef INET6 529*4a77657cSAndrey V. Elsukov case O_FORWARD_IP6: 530*4a77657cSAndrey V. Elsukov return (struct sockaddr *)&(((ipfw_insn_sa6 *)cmd)->sa); 531*4a77657cSAndrey V. Elsukov #endif 532*4a77657cSAndrey V. Elsukov default: 533*4a77657cSAndrey V. Elsukov break; 534*4a77657cSAndrey V. Elsukov } 535*4a77657cSAndrey V. Elsukov 536*4a77657cSAndrey V. Elsukov return (NULL); 537*4a77657cSAndrey V. Elsukov } 538*4a77657cSAndrey V. Elsukov 539*4a77657cSAndrey V. Elsukov #define MAX_COMMENT_LEN 80 540*4a77657cSAndrey V. Elsukov 541*4a77657cSAndrey V. Elsukov static size_t 542*4a77657cSAndrey V. Elsukov ipfw_copy_rule_comment(struct ip_fw *f, char *dst) 543*4a77657cSAndrey V. Elsukov { 544*4a77657cSAndrey V. Elsukov ipfw_insn *cmd; 545*4a77657cSAndrey V. Elsukov size_t rcomment_len = 0; 546*4a77657cSAndrey V. Elsukov int l, cmdlen; 547*4a77657cSAndrey V. Elsukov 548*4a77657cSAndrey V. Elsukov for (l = f->cmd_len, cmd = f->cmd; l > 0; l -= cmdlen, cmd += cmdlen) { 549*4a77657cSAndrey V. Elsukov cmdlen = F_LEN(cmd); 550*4a77657cSAndrey V. Elsukov if (cmd->opcode != O_NOP) { 551*4a77657cSAndrey V. Elsukov continue; 552*4a77657cSAndrey V. Elsukov } else if (cmd->len == 1) { 553*4a77657cSAndrey V. Elsukov return (0); 554*4a77657cSAndrey V. Elsukov } 555*4a77657cSAndrey V. Elsukov break; 556*4a77657cSAndrey V. Elsukov } 557*4a77657cSAndrey V. Elsukov if (l <= 0) { 558*4a77657cSAndrey V. Elsukov return (0); 559*4a77657cSAndrey V. Elsukov } 560*4a77657cSAndrey V. Elsukov rcomment_len = strnlen((char *)(cmd + 1), MAX_COMMENT_LEN - 1) + 1; 561*4a77657cSAndrey V. Elsukov strlcpy(dst, (char *)(cmd + 1), rcomment_len); 562*4a77657cSAndrey V. Elsukov return (rcomment_len); 563*4a77657cSAndrey V. Elsukov } 564*4a77657cSAndrey V. Elsukov 565*4a77657cSAndrey V. Elsukov static void 566*4a77657cSAndrey V. Elsukov ipfw_log_rtsock(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 567*4a77657cSAndrey V. Elsukov struct ip_fw_args *args, u_short offset, uint32_t tablearg, 568*4a77657cSAndrey V. Elsukov void *_eh) 569*4a77657cSAndrey V. Elsukov { 570*4a77657cSAndrey V. Elsukov struct sockaddr_dl *sdl_ipfwcmd; 571*4a77657cSAndrey V. Elsukov struct ether_header *eh = _eh; 572*4a77657cSAndrey V. Elsukov struct rt_addrinfo *info; 573*4a77657cSAndrey V. Elsukov uint32_t *targ_value; 574*4a77657cSAndrey V. Elsukov ipfwlog_rtsock_hdr_v2 *hdr; 575*4a77657cSAndrey V. Elsukov ipfw_insn *cmd; 576*4a77657cSAndrey V. Elsukov ipfw_insn_log *l; 577*4a77657cSAndrey V. Elsukov char *buf, *orig_buf; 578*4a77657cSAndrey V. Elsukov /* at least 4 x sizeof(struct sockaddr_dl) + rule comment (80) */ 579*4a77657cSAndrey V. Elsukov size_t buflen = 512; 580*4a77657cSAndrey V. Elsukov 581*4a77657cSAndrey V. Elsukov /* Should we log? O_LOG is the first one */ 582*4a77657cSAndrey V. Elsukov cmd = ACTION_PTR(f); 583*4a77657cSAndrey V. Elsukov l = (ipfw_insn_log *)cmd; 584*4a77657cSAndrey V. Elsukov 585*4a77657cSAndrey V. Elsukov if (l->max_log != 0 && l->log_left == 0) 586*4a77657cSAndrey V. Elsukov return; 587*4a77657cSAndrey V. Elsukov 588*4a77657cSAndrey V. Elsukov l->log_left--; 589*4a77657cSAndrey V. Elsukov if (V_fw_verbose != 0 && l->log_left == 0) { 590*4a77657cSAndrey V. Elsukov log(LOG_SECURITY | LOG_NOTICE, 591*4a77657cSAndrey V. Elsukov "ipfw: limit %d reached on entry %d\n", 592*4a77657cSAndrey V. Elsukov l->max_log, f ? f->rulenum : -1); 593*4a77657cSAndrey V. Elsukov } 594*4a77657cSAndrey V. Elsukov 595*4a77657cSAndrey V. Elsukov buf = orig_buf = malloc(buflen, M_TEMP, M_NOWAIT | M_ZERO); 596*4a77657cSAndrey V. Elsukov if (buf == NULL) 597*4a77657cSAndrey V. Elsukov return; 598*4a77657cSAndrey V. Elsukov 599*4a77657cSAndrey V. Elsukov info = (struct rt_addrinfo *)buf; 600*4a77657cSAndrey V. Elsukov buf += sizeof (*info); 601*4a77657cSAndrey V. Elsukov 602*4a77657cSAndrey V. Elsukov cmd = ipfw_get_action(f); 603*4a77657cSAndrey V. Elsukov sdl_ipfwcmd = (struct sockaddr_dl *)buf; 604*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_family = AF_IPFWLOG; 605*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_index = f->set; 606*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_type = 2; /* version */ 607*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_alen = sizeof(*hdr); 608*4a77657cSAndrey V. Elsukov hdr = (ipfwlog_rtsock_hdr_v2 *)(sdl_ipfwcmd->sdl_data); 609*4a77657cSAndrey V. Elsukov /* fill rule comment in if any */ 610*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_nlen = ipfw_copy_rule_comment(f, hdr->comment); 611*4a77657cSAndrey V. Elsukov targ_value = &hdr->tablearg; 612*4a77657cSAndrey V. Elsukov hdr->rulenum = f->rulenum; 613*4a77657cSAndrey V. Elsukov hdr->mark = args->rule.pkt_mark; 614*4a77657cSAndrey V. Elsukov hdr->cmd = *cmd; 615*4a77657cSAndrey V. Elsukov 616*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_len = sizeof(*sdl_ipfwcmd); 617*4a77657cSAndrey V. Elsukov if (sizeof(*hdr) + sdl_ipfwcmd->sdl_nlen > sizeof(sdl_ipfwcmd->sdl_data)) { 618*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_len += sizeof(*hdr) + sdl_ipfwcmd->sdl_nlen - 619*4a77657cSAndrey V. Elsukov sizeof(sdl_ipfwcmd->sdl_data); 620*4a77657cSAndrey V. Elsukov } 621*4a77657cSAndrey V. Elsukov buf += sdl_ipfwcmd->sdl_len; 622*4a77657cSAndrey V. Elsukov 623*4a77657cSAndrey V. Elsukov /* fill L2 in if present */ 624*4a77657cSAndrey V. Elsukov if (args->flags & IPFW_ARGS_ETHER && eh != NULL) { 625*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_slen = sizeof(eh->ether_shost); 626*4a77657cSAndrey V. Elsukov memcpy(hdr->ether_shost, eh->ether_shost, 627*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_slen); 628*4a77657cSAndrey V. Elsukov memcpy(hdr->ether_dhost, eh->ether_dhost, 629*4a77657cSAndrey V. Elsukov sdl_ipfwcmd->sdl_slen); 630*4a77657cSAndrey V. Elsukov } 631*4a77657cSAndrey V. Elsukov 632*4a77657cSAndrey V. Elsukov info->rti_info[RTAX_DST] = (struct sockaddr *)sdl_ipfwcmd; 633*4a77657cSAndrey V. Elsukov 634*4a77657cSAndrey V. Elsukov /* Warn if we're about to stop sending messages */ 635*4a77657cSAndrey V. Elsukov if (l->max_log != 0 && l->log_left < (l->max_log >> 1)) { 636*4a77657cSAndrey V. Elsukov info->rti_flags |= RTF_PROTO1; 637*4a77657cSAndrey V. Elsukov } 638*4a77657cSAndrey V. Elsukov 639*4a77657cSAndrey V. Elsukov /* handle tablearg */ 640*4a77657cSAndrey V. Elsukov info->rti_info[RTAX_GENMASK] = ipfw_rtsocklog_handle_tablearg( 641*4a77657cSAndrey V. Elsukov chain, cmd, tablearg, targ_value, &buf); 642*4a77657cSAndrey V. Elsukov 643*4a77657cSAndrey V. Elsukov /* L3 */ 644*4a77657cSAndrey V. Elsukov ipfw_rtsocklog_fill_l3(args, &buf, 645*4a77657cSAndrey V. Elsukov &info->rti_info[RTAX_GATEWAY], 646*4a77657cSAndrey V. Elsukov &info->rti_info[RTAX_NETMASK]); 647*4a77657cSAndrey V. Elsukov 648*4a77657cSAndrey V. Elsukov info->rti_ifp = args->ifp; 649*4a77657cSAndrey V. Elsukov rtsock_routemsg_info(RTM_IPFWLOG, info, RT_ALL_FIBS); 650*4a77657cSAndrey V. Elsukov 651*4a77657cSAndrey V. Elsukov free(orig_buf, M_TEMP); 652*4a77657cSAndrey V. Elsukov } 653*4a77657cSAndrey V. Elsukov 654*4a77657cSAndrey V. Elsukov /* 655*4a77657cSAndrey V. Elsukov * We enter here when we have a rule with O_LOG. 656*4a77657cSAndrey V. Elsukov */ 657*4a77657cSAndrey V. Elsukov void 658*4a77657cSAndrey V. Elsukov ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 659*4a77657cSAndrey V. Elsukov struct ip_fw_args *args, u_short offset, uint32_t tablearg, 660*4a77657cSAndrey V. Elsukov struct ip *ip, void *eh) 661*4a77657cSAndrey V. Elsukov { 662*4a77657cSAndrey V. Elsukov ipfw_insn *cmd; 663*4a77657cSAndrey V. Elsukov 664*4a77657cSAndrey V. Elsukov if (f == NULL || hlen == 0) 665*4a77657cSAndrey V. Elsukov return; 666*4a77657cSAndrey V. Elsukov 667*4a77657cSAndrey V. Elsukov /* O_LOG is the first action */ 668*4a77657cSAndrey V. Elsukov cmd = ACTION_PTR(f); 669*4a77657cSAndrey V. Elsukov 670*4a77657cSAndrey V. Elsukov if (cmd->arg1 == IPFW_LOG_DEFAULT) { 671*4a77657cSAndrey V. Elsukov if (V_fw_verbose == 0) { 672*4a77657cSAndrey V. Elsukov ipfw_log_ipfw0(args, ip); 673*4a77657cSAndrey V. Elsukov return; 674*4a77657cSAndrey V. Elsukov } 675*4a77657cSAndrey V. Elsukov ipfw_log_syslog(chain, f, hlen, args, offset, tablearg, ip); 676*4a77657cSAndrey V. Elsukov return; 677*4a77657cSAndrey V. Elsukov } 678*4a77657cSAndrey V. Elsukov 679*4a77657cSAndrey V. Elsukov if (cmd->arg1 & IPFW_LOG_SYSLOG) 680*4a77657cSAndrey V. Elsukov ipfw_log_syslog(chain, f, hlen, args, offset, tablearg, ip); 681*4a77657cSAndrey V. Elsukov 682*4a77657cSAndrey V. Elsukov if (cmd->arg1 & IPFW_LOG_RTSOCK) 683*4a77657cSAndrey V. Elsukov ipfw_log_rtsock(chain, f, hlen, args, offset, tablearg, eh); 684*4a77657cSAndrey V. Elsukov 685*4a77657cSAndrey V. Elsukov if (cmd->arg1 & IPFW_LOG_IPFW0) 686*4a77657cSAndrey V. Elsukov ipfw_log_ipfw0(args, ip); 687*4a77657cSAndrey V. Elsukov } 6883b3a8eb9SGleb Smirnoff /* end of file */ 689