13b3a8eb9SGleb Smirnoff /*- 23b3a8eb9SGleb Smirnoff * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa 33b3a8eb9SGleb Smirnoff * 43b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 53b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 63b3a8eb9SGleb Smirnoff * are met: 73b3a8eb9SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 83b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 93b3a8eb9SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 103b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 113b3a8eb9SGleb Smirnoff * documentation and/or other materials provided with the distribution. 123b3a8eb9SGleb Smirnoff * 133b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 143b3a8eb9SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 153b3a8eb9SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 163b3a8eb9SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 173b3a8eb9SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 183b3a8eb9SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 193b3a8eb9SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 203b3a8eb9SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 213b3a8eb9SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 223b3a8eb9SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 233b3a8eb9SGleb Smirnoff * SUCH DAMAGE. 243b3a8eb9SGleb Smirnoff */ 253b3a8eb9SGleb Smirnoff 263b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 273b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 283b3a8eb9SGleb Smirnoff 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> 43*8ec07310SGleb Smirnoff #include <sys/malloc.h> 44*8ec07310SGleb Smirnoff #include <sys/mbuf.h> 453b3a8eb9SGleb Smirnoff #include <sys/socket.h> 463b3a8eb9SGleb Smirnoff #include <sys/sysctl.h> 473b3a8eb9SGleb Smirnoff #include <sys/syslog.h> 483b3a8eb9SGleb Smirnoff #include <sys/lock.h> 493b3a8eb9SGleb Smirnoff #include <sys/rwlock.h> 503b3a8eb9SGleb Smirnoff #include <net/ethernet.h> /* for ETHERTYPE_IP */ 513b3a8eb9SGleb Smirnoff #include <net/if.h> 5276039bc8SGleb Smirnoff #include <net/if_var.h> 533b3a8eb9SGleb Smirnoff #include <net/if_clone.h> 543b3a8eb9SGleb Smirnoff #include <net/vnet.h> 553b3a8eb9SGleb Smirnoff #include <net/if_types.h> /* for IFT_PFLOG */ 563b3a8eb9SGleb Smirnoff #include <net/bpf.h> /* for BPF */ 573b3a8eb9SGleb Smirnoff 583b3a8eb9SGleb Smirnoff #include <netinet/in.h> 593b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 603b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 613b3a8eb9SGleb Smirnoff #include <netinet/ip_var.h> 623b3a8eb9SGleb Smirnoff #include <netinet/ip_fw.h> 633b3a8eb9SGleb Smirnoff #include <netinet/tcp_var.h> 643b3a8eb9SGleb Smirnoff #include <netinet/udp.h> 653b3a8eb9SGleb Smirnoff 663b3a8eb9SGleb Smirnoff #include <netinet/ip6.h> 673b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 683b3a8eb9SGleb Smirnoff #ifdef INET6 693b3a8eb9SGleb Smirnoff #include <netinet6/in6_var.h> /* ip6_sprintf() */ 703b3a8eb9SGleb Smirnoff #endif 713b3a8eb9SGleb Smirnoff 723b3a8eb9SGleb Smirnoff #include <netpfil/ipfw/ip_fw_private.h> 733b3a8eb9SGleb Smirnoff 743b3a8eb9SGleb Smirnoff #ifdef MAC 753b3a8eb9SGleb Smirnoff #include <security/mac/mac_framework.h> 763b3a8eb9SGleb Smirnoff #endif 773b3a8eb9SGleb Smirnoff 783b3a8eb9SGleb Smirnoff /* 793b3a8eb9SGleb Smirnoff * L3HDR maps an ipv4 pointer into a layer3 header pointer of type T 803b3a8eb9SGleb Smirnoff * Other macros just cast void * into the appropriate type 813b3a8eb9SGleb Smirnoff */ 823b3a8eb9SGleb Smirnoff #define L3HDR(T, ip) ((T *)((u_int32_t *)(ip) + (ip)->ip_hl)) 833b3a8eb9SGleb Smirnoff #define TCP(p) ((struct tcphdr *)(p)) 843b3a8eb9SGleb Smirnoff #define SCTP(p) ((struct sctphdr *)(p)) 853b3a8eb9SGleb Smirnoff #define UDP(p) ((struct udphdr *)(p)) 863b3a8eb9SGleb Smirnoff #define ICMP(p) ((struct icmphdr *)(p)) 873b3a8eb9SGleb Smirnoff #define ICMP6(p) ((struct icmp6_hdr *)(p)) 883b3a8eb9SGleb Smirnoff 89d0f65d47SLuigi Rizzo #ifdef __APPLE__ 90d0f65d47SLuigi Rizzo #undef snprintf 91d0f65d47SLuigi Rizzo #define snprintf sprintf 92d0f65d47SLuigi Rizzo #define SNPARGS(buf, len) buf + len 93d0f65d47SLuigi Rizzo #define SNP(buf) buf 94d0f65d47SLuigi Rizzo #else /* !__APPLE__ */ 953b3a8eb9SGleb Smirnoff #define SNPARGS(buf, len) buf + len, sizeof(buf) > len ? sizeof(buf) - len : 0 963b3a8eb9SGleb Smirnoff #define SNP(buf) buf, sizeof(buf) 97d0f65d47SLuigi Rizzo #endif /* !__APPLE__ */ 983b3a8eb9SGleb Smirnoff 993b3a8eb9SGleb Smirnoff #ifdef WITHOUT_BPF 1003b3a8eb9SGleb Smirnoff void 1013b3a8eb9SGleb Smirnoff ipfw_log_bpf(int onoff) 1023b3a8eb9SGleb Smirnoff { 1033b3a8eb9SGleb Smirnoff } 1043b3a8eb9SGleb Smirnoff #else /* !WITHOUT_BPF */ 1053b3a8eb9SGleb Smirnoff static struct ifnet *log_if; /* hook to attach to bpf */ 1063b3a8eb9SGleb Smirnoff static struct rwlock log_if_lock; 1073b3a8eb9SGleb Smirnoff #define LOGIF_LOCK_INIT(x) rw_init(&log_if_lock, "ipfw log_if lock") 1083b3a8eb9SGleb Smirnoff #define LOGIF_LOCK_DESTROY(x) rw_destroy(&log_if_lock) 1093b3a8eb9SGleb Smirnoff #define LOGIF_RLOCK(x) rw_rlock(&log_if_lock) 1103b3a8eb9SGleb Smirnoff #define LOGIF_RUNLOCK(x) rw_runlock(&log_if_lock) 1113b3a8eb9SGleb Smirnoff #define LOGIF_WLOCK(x) rw_wlock(&log_if_lock) 1123b3a8eb9SGleb Smirnoff #define LOGIF_WUNLOCK(x) rw_wunlock(&log_if_lock) 1133b3a8eb9SGleb Smirnoff 11442a58907SGleb Smirnoff static const char ipfwname[] = "ipfw"; 1153b3a8eb9SGleb Smirnoff 1163b3a8eb9SGleb Smirnoff /* we use this dummy function for all ifnet callbacks */ 1173b3a8eb9SGleb Smirnoff static int 1183b3a8eb9SGleb Smirnoff log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr) 1193b3a8eb9SGleb Smirnoff { 1203b3a8eb9SGleb Smirnoff return EINVAL; 1213b3a8eb9SGleb Smirnoff } 1223b3a8eb9SGleb Smirnoff 1233b3a8eb9SGleb Smirnoff static int 1243b3a8eb9SGleb Smirnoff ipfw_log_output(struct ifnet *ifp, struct mbuf *m, 12547e8d432SGleb Smirnoff const struct sockaddr *dst, struct route *ro) 1263b3a8eb9SGleb Smirnoff { 1273b3a8eb9SGleb Smirnoff if (m != NULL) 1283b3a8eb9SGleb Smirnoff FREE_PKT(m); 1293b3a8eb9SGleb Smirnoff return EINVAL; 1303b3a8eb9SGleb Smirnoff } 1313b3a8eb9SGleb Smirnoff 1323b3a8eb9SGleb Smirnoff static void 1333b3a8eb9SGleb Smirnoff ipfw_log_start(struct ifnet* ifp) 1343b3a8eb9SGleb Smirnoff { 1353b3a8eb9SGleb Smirnoff panic("ipfw_log_start() must not be called"); 1363b3a8eb9SGleb Smirnoff } 1373b3a8eb9SGleb Smirnoff 1383b3a8eb9SGleb Smirnoff static const u_char ipfwbroadcastaddr[6] = 1393b3a8eb9SGleb Smirnoff { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 1403b3a8eb9SGleb Smirnoff 1413b3a8eb9SGleb Smirnoff static int 1423b3a8eb9SGleb Smirnoff ipfw_log_clone_match(struct if_clone *ifc, const char *name) 1433b3a8eb9SGleb Smirnoff { 1443b3a8eb9SGleb Smirnoff 14542a58907SGleb Smirnoff return (strncmp(name, ipfwname, sizeof(ipfwname) - 1) == 0); 1463b3a8eb9SGleb Smirnoff } 1473b3a8eb9SGleb Smirnoff 1483b3a8eb9SGleb Smirnoff static int 1493b3a8eb9SGleb Smirnoff ipfw_log_clone_create(struct if_clone *ifc, char *name, size_t len, 1503b3a8eb9SGleb Smirnoff caddr_t params) 1513b3a8eb9SGleb Smirnoff { 1523b3a8eb9SGleb Smirnoff int error; 1533b3a8eb9SGleb Smirnoff int unit; 1543b3a8eb9SGleb Smirnoff struct ifnet *ifp; 1553b3a8eb9SGleb Smirnoff 1563b3a8eb9SGleb Smirnoff error = ifc_name2unit(name, &unit); 1573b3a8eb9SGleb Smirnoff if (error) 1583b3a8eb9SGleb Smirnoff return (error); 1593b3a8eb9SGleb Smirnoff 1603b3a8eb9SGleb Smirnoff error = ifc_alloc_unit(ifc, &unit); 1613b3a8eb9SGleb Smirnoff if (error) 1623b3a8eb9SGleb Smirnoff return (error); 1633b3a8eb9SGleb Smirnoff 1643b3a8eb9SGleb Smirnoff ifp = if_alloc(IFT_PFLOG); 1653b3a8eb9SGleb Smirnoff if (ifp == NULL) { 1663b3a8eb9SGleb Smirnoff ifc_free_unit(ifc, unit); 1673b3a8eb9SGleb Smirnoff return (ENOSPC); 1683b3a8eb9SGleb Smirnoff } 16942a58907SGleb Smirnoff ifp->if_dname = ipfwname; 1703b3a8eb9SGleb Smirnoff ifp->if_dunit = unit; 17142a58907SGleb Smirnoff snprintf(ifp->if_xname, IFNAMSIZ, "%s%d", ipfwname, unit); 1723b3a8eb9SGleb Smirnoff strlcpy(name, ifp->if_xname, len); 1733b3a8eb9SGleb Smirnoff ifp->if_mtu = 65536; 1743b3a8eb9SGleb Smirnoff ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST; 1753b3a8eb9SGleb Smirnoff ifp->if_init = (void *)log_dummy; 1763b3a8eb9SGleb Smirnoff ifp->if_ioctl = log_dummy; 1773b3a8eb9SGleb Smirnoff ifp->if_start = ipfw_log_start; 1783b3a8eb9SGleb Smirnoff ifp->if_output = ipfw_log_output; 1793b3a8eb9SGleb Smirnoff ifp->if_addrlen = 6; 1803b3a8eb9SGleb Smirnoff ifp->if_hdrlen = 14; 1813b3a8eb9SGleb Smirnoff ifp->if_broadcastaddr = ipfwbroadcastaddr; 1823b3a8eb9SGleb Smirnoff ifp->if_baudrate = IF_Mbps(10); 1833b3a8eb9SGleb Smirnoff 1843b3a8eb9SGleb Smirnoff LOGIF_WLOCK(); 1853b3a8eb9SGleb Smirnoff if (log_if == NULL) 1863b3a8eb9SGleb Smirnoff log_if = ifp; 1873b3a8eb9SGleb Smirnoff else { 1883b3a8eb9SGleb Smirnoff LOGIF_WUNLOCK(); 1893b3a8eb9SGleb Smirnoff if_free(ifp); 1903b3a8eb9SGleb Smirnoff ifc_free_unit(ifc, unit); 1913b3a8eb9SGleb Smirnoff return (EEXIST); 1923b3a8eb9SGleb Smirnoff } 1933b3a8eb9SGleb Smirnoff LOGIF_WUNLOCK(); 1943b3a8eb9SGleb Smirnoff if_attach(ifp); 1953b3a8eb9SGleb Smirnoff bpfattach(ifp, DLT_EN10MB, 14); 1963b3a8eb9SGleb Smirnoff 1973b3a8eb9SGleb Smirnoff return (0); 1983b3a8eb9SGleb Smirnoff } 1993b3a8eb9SGleb Smirnoff 2003b3a8eb9SGleb Smirnoff static int 2013b3a8eb9SGleb Smirnoff ipfw_log_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) 2023b3a8eb9SGleb Smirnoff { 2033b3a8eb9SGleb Smirnoff int unit; 2043b3a8eb9SGleb Smirnoff 2053b3a8eb9SGleb Smirnoff if (ifp == NULL) 2063b3a8eb9SGleb Smirnoff return (0); 2073b3a8eb9SGleb Smirnoff 2083b3a8eb9SGleb Smirnoff LOGIF_WLOCK(); 2093b3a8eb9SGleb Smirnoff if (log_if != NULL && ifp == log_if) 2103b3a8eb9SGleb Smirnoff log_if = NULL; 2113b3a8eb9SGleb Smirnoff else { 2123b3a8eb9SGleb Smirnoff LOGIF_WUNLOCK(); 2133b3a8eb9SGleb Smirnoff return (EINVAL); 2143b3a8eb9SGleb Smirnoff } 2153b3a8eb9SGleb Smirnoff LOGIF_WUNLOCK(); 2163b3a8eb9SGleb Smirnoff 2173b3a8eb9SGleb Smirnoff unit = ifp->if_dunit; 2183b3a8eb9SGleb Smirnoff bpfdetach(ifp); 2193b3a8eb9SGleb Smirnoff if_detach(ifp); 2203b3a8eb9SGleb Smirnoff if_free(ifp); 2213b3a8eb9SGleb Smirnoff ifc_free_unit(ifc, unit); 2223b3a8eb9SGleb Smirnoff 2233b3a8eb9SGleb Smirnoff return (0); 2243b3a8eb9SGleb Smirnoff } 2253b3a8eb9SGleb Smirnoff 22642a58907SGleb Smirnoff static struct if_clone *ipfw_log_cloner; 2273b3a8eb9SGleb Smirnoff 2283b3a8eb9SGleb Smirnoff void 2293b3a8eb9SGleb Smirnoff ipfw_log_bpf(int onoff) 2303b3a8eb9SGleb Smirnoff { 2313b3a8eb9SGleb Smirnoff 2323b3a8eb9SGleb Smirnoff if (onoff) { 2333b3a8eb9SGleb Smirnoff LOGIF_LOCK_INIT(); 23442a58907SGleb Smirnoff ipfw_log_cloner = if_clone_advanced(ipfwname, 0, 23542a58907SGleb Smirnoff ipfw_log_clone_match, ipfw_log_clone_create, 23642a58907SGleb Smirnoff ipfw_log_clone_destroy); 2373b3a8eb9SGleb Smirnoff } else { 23842a58907SGleb Smirnoff if_clone_detach(ipfw_log_cloner); 2393b3a8eb9SGleb Smirnoff LOGIF_LOCK_DESTROY(); 2403b3a8eb9SGleb Smirnoff } 2413b3a8eb9SGleb Smirnoff } 2423b3a8eb9SGleb Smirnoff #endif /* !WITHOUT_BPF */ 2433b3a8eb9SGleb Smirnoff 2440cba2b28SAlexander V. Chernikov #define TARG(k, f) IP_FW_ARG_TABLEARG(chain, k, f) 2453b3a8eb9SGleb Smirnoff /* 2463b3a8eb9SGleb Smirnoff * We enter here when we have a rule with O_LOG. 2473b3a8eb9SGleb Smirnoff * XXX this function alone takes about 2Kbytes of code! 2483b3a8eb9SGleb Smirnoff */ 2493b3a8eb9SGleb Smirnoff void 2500cba2b28SAlexander V. Chernikov ipfw_log(struct ip_fw_chain *chain, struct ip_fw *f, u_int hlen, 2510cba2b28SAlexander V. Chernikov struct ip_fw_args *args, struct mbuf *m, struct ifnet *oif, 2520cba2b28SAlexander V. Chernikov u_short offset, uint32_t tablearg, struct ip *ip) 2533b3a8eb9SGleb Smirnoff { 2543b3a8eb9SGleb Smirnoff char *action; 2553b3a8eb9SGleb Smirnoff int limit_reached = 0; 2563b3a8eb9SGleb Smirnoff char action2[92], proto[128], fragment[32]; 2573b3a8eb9SGleb Smirnoff 2583b3a8eb9SGleb Smirnoff if (V_fw_verbose == 0) { 2593b3a8eb9SGleb Smirnoff #ifndef WITHOUT_BPF 2603b3a8eb9SGleb Smirnoff LOGIF_RLOCK(); 2613b3a8eb9SGleb Smirnoff if (log_if == NULL || log_if->if_bpf == NULL) { 2623b3a8eb9SGleb Smirnoff LOGIF_RUNLOCK(); 2633b3a8eb9SGleb Smirnoff return; 2643b3a8eb9SGleb Smirnoff } 2653b3a8eb9SGleb Smirnoff 2663b3a8eb9SGleb Smirnoff if (args->eh) /* layer2, use orig hdr */ 2673b3a8eb9SGleb Smirnoff BPF_MTAP2(log_if, args->eh, ETHER_HDR_LEN, m); 268b49bf73fSPhilip Paeps else { 2693b3a8eb9SGleb Smirnoff /* Add fake header. Later we will store 2703b3a8eb9SGleb Smirnoff * more info in the header. 2713b3a8eb9SGleb Smirnoff */ 272b49bf73fSPhilip Paeps if (ip->ip_v == 4) 2733b3a8eb9SGleb Smirnoff BPF_MTAP2(log_if, "DDDDDDSSSSSS\x08\x00", ETHER_HDR_LEN, m); 274b49bf73fSPhilip Paeps else if (ip->ip_v == 6) 275b49bf73fSPhilip Paeps BPF_MTAP2(log_if, "DDDDDDSSSSSS\x86\xdd", ETHER_HDR_LEN, m); 276b49bf73fSPhilip Paeps else 277b49bf73fSPhilip Paeps /* Obviously bogus EtherType. */ 278b49bf73fSPhilip Paeps BPF_MTAP2(log_if, "DDDDDDSSSSSS\xff\xff", ETHER_HDR_LEN, m); 279b49bf73fSPhilip Paeps } 2803b3a8eb9SGleb Smirnoff LOGIF_RUNLOCK(); 2813b3a8eb9SGleb Smirnoff #endif /* !WITHOUT_BPF */ 2823b3a8eb9SGleb Smirnoff return; 2833b3a8eb9SGleb Smirnoff } 2843b3a8eb9SGleb Smirnoff /* the old 'log' function */ 2853b3a8eb9SGleb Smirnoff fragment[0] = '\0'; 2863b3a8eb9SGleb Smirnoff proto[0] = '\0'; 2873b3a8eb9SGleb Smirnoff 2883b3a8eb9SGleb Smirnoff if (f == NULL) { /* bogus pkt */ 2893b3a8eb9SGleb Smirnoff if (V_verbose_limit != 0 && V_norule_counter >= V_verbose_limit) 2903b3a8eb9SGleb Smirnoff return; 2913b3a8eb9SGleb Smirnoff V_norule_counter++; 2923b3a8eb9SGleb Smirnoff if (V_norule_counter == V_verbose_limit) 2933b3a8eb9SGleb Smirnoff limit_reached = V_verbose_limit; 2943b3a8eb9SGleb Smirnoff action = "Refuse"; 2953b3a8eb9SGleb Smirnoff } else { /* O_LOG is the first action, find the real one */ 2963b3a8eb9SGleb Smirnoff ipfw_insn *cmd = ACTION_PTR(f); 2973b3a8eb9SGleb Smirnoff ipfw_insn_log *l = (ipfw_insn_log *)cmd; 2983b3a8eb9SGleb Smirnoff 2993b3a8eb9SGleb Smirnoff if (l->max_log != 0 && l->log_left == 0) 3003b3a8eb9SGleb Smirnoff return; 3013b3a8eb9SGleb Smirnoff l->log_left--; 3023b3a8eb9SGleb Smirnoff if (l->log_left == 0) 3033b3a8eb9SGleb Smirnoff limit_reached = l->max_log; 3043b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); /* point to first action */ 3053b3a8eb9SGleb Smirnoff if (cmd->opcode == O_ALTQ) { 3063b3a8eb9SGleb Smirnoff ipfw_insn_altq *altq = (ipfw_insn_altq *)cmd; 3073b3a8eb9SGleb Smirnoff 3083b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Altq %d", 3093b3a8eb9SGleb Smirnoff altq->qid); 3103b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); 3113b3a8eb9SGleb Smirnoff } 312ae01d73cSAlexander V. Chernikov if (cmd->opcode == O_PROB || cmd->opcode == O_TAG || 313ae01d73cSAlexander V. Chernikov cmd->opcode == O_SETDSCP) 3143b3a8eb9SGleb Smirnoff cmd += F_LEN(cmd); 3153b3a8eb9SGleb Smirnoff 3163b3a8eb9SGleb Smirnoff action = action2; 3173b3a8eb9SGleb Smirnoff switch (cmd->opcode) { 3183b3a8eb9SGleb Smirnoff case O_DENY: 3193b3a8eb9SGleb Smirnoff action = "Deny"; 3203b3a8eb9SGleb Smirnoff break; 3213b3a8eb9SGleb Smirnoff 3223b3a8eb9SGleb Smirnoff case O_REJECT: 3233b3a8eb9SGleb Smirnoff if (cmd->arg1==ICMP_REJECT_RST) 3243b3a8eb9SGleb Smirnoff action = "Reset"; 3253b3a8eb9SGleb Smirnoff else if (cmd->arg1==ICMP_UNREACH_HOST) 3263b3a8eb9SGleb Smirnoff action = "Reject"; 3273b3a8eb9SGleb Smirnoff else 3283b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Unreach %d", 3293b3a8eb9SGleb Smirnoff cmd->arg1); 3303b3a8eb9SGleb Smirnoff break; 3313b3a8eb9SGleb Smirnoff 3323b3a8eb9SGleb Smirnoff case O_UNREACH6: 3333b3a8eb9SGleb Smirnoff if (cmd->arg1==ICMP6_UNREACH_RST) 3343b3a8eb9SGleb Smirnoff action = "Reset"; 3353b3a8eb9SGleb Smirnoff else 3363b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Unreach %d", 3373b3a8eb9SGleb Smirnoff cmd->arg1); 3383b3a8eb9SGleb Smirnoff break; 3393b3a8eb9SGleb Smirnoff 3403b3a8eb9SGleb Smirnoff case O_ACCEPT: 3413b3a8eb9SGleb Smirnoff action = "Accept"; 3423b3a8eb9SGleb Smirnoff break; 3433b3a8eb9SGleb Smirnoff case O_COUNT: 3443b3a8eb9SGleb Smirnoff action = "Count"; 3453b3a8eb9SGleb Smirnoff break; 3463b3a8eb9SGleb Smirnoff case O_DIVERT: 3473b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Divert %d", 3480cba2b28SAlexander V. Chernikov TARG(cmd->arg1, divert)); 3493b3a8eb9SGleb Smirnoff break; 3503b3a8eb9SGleb Smirnoff case O_TEE: 3513b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Tee %d", 3520cba2b28SAlexander V. Chernikov TARG(cmd->arg1, divert)); 3533b3a8eb9SGleb Smirnoff break; 3543b3a8eb9SGleb Smirnoff case O_SETFIB: 3553b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "SetFib %d", 35691e93dafSAlexander V. Chernikov TARG(cmd->arg1, fib) & 0x7FFF); 3573b3a8eb9SGleb Smirnoff break; 3583b3a8eb9SGleb Smirnoff case O_SKIPTO: 3593b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "SkipTo %d", 3600cba2b28SAlexander V. Chernikov TARG(cmd->arg1, skipto)); 3613b3a8eb9SGleb Smirnoff break; 3623b3a8eb9SGleb Smirnoff case O_PIPE: 3633b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Pipe %d", 3640cba2b28SAlexander V. Chernikov TARG(cmd->arg1, pipe)); 3653b3a8eb9SGleb Smirnoff break; 3663b3a8eb9SGleb Smirnoff case O_QUEUE: 3673b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Queue %d", 3680cba2b28SAlexander V. Chernikov TARG(cmd->arg1, pipe)); 3693b3a8eb9SGleb Smirnoff break; 3703b3a8eb9SGleb Smirnoff case O_FORWARD_IP: { 3713b3a8eb9SGleb Smirnoff ipfw_insn_sa *sa = (ipfw_insn_sa *)cmd; 3723b3a8eb9SGleb Smirnoff int len; 3733b3a8eb9SGleb Smirnoff struct in_addr dummyaddr; 3743b3a8eb9SGleb Smirnoff if (sa->sa.sin_addr.s_addr == INADDR_ANY) 3753b3a8eb9SGleb Smirnoff dummyaddr.s_addr = htonl(tablearg); 3763b3a8eb9SGleb Smirnoff else 3773b3a8eb9SGleb Smirnoff dummyaddr.s_addr = sa->sa.sin_addr.s_addr; 3783b3a8eb9SGleb Smirnoff 3793b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(action2, 0), "Forward to %s", 3803b3a8eb9SGleb Smirnoff inet_ntoa(dummyaddr)); 3813b3a8eb9SGleb Smirnoff 3823b3a8eb9SGleb Smirnoff if (sa->sa.sin_port) 3833b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, len), ":%d", 3843b3a8eb9SGleb Smirnoff sa->sa.sin_port); 3853b3a8eb9SGleb Smirnoff } 3863b3a8eb9SGleb Smirnoff break; 3873b3a8eb9SGleb Smirnoff #ifdef INET6 3883b3a8eb9SGleb Smirnoff case O_FORWARD_IP6: { 3893b3a8eb9SGleb Smirnoff char buf[INET6_ADDRSTRLEN]; 3903b3a8eb9SGleb Smirnoff ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd; 3913b3a8eb9SGleb Smirnoff int len; 3923b3a8eb9SGleb Smirnoff 3933b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(action2, 0), "Forward to [%s]", 3943b3a8eb9SGleb Smirnoff ip6_sprintf(buf, &sa->sa.sin6_addr)); 3953b3a8eb9SGleb Smirnoff 3963b3a8eb9SGleb Smirnoff if (sa->sa.sin6_port) 3973b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, len), ":%u", 3983b3a8eb9SGleb Smirnoff sa->sa.sin6_port); 3993b3a8eb9SGleb Smirnoff } 4003b3a8eb9SGleb Smirnoff break; 4013b3a8eb9SGleb Smirnoff #endif 4023b3a8eb9SGleb Smirnoff case O_NETGRAPH: 4033b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Netgraph %d", 4043b3a8eb9SGleb Smirnoff cmd->arg1); 4053b3a8eb9SGleb Smirnoff break; 4063b3a8eb9SGleb Smirnoff case O_NGTEE: 4073b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Ngtee %d", 4083b3a8eb9SGleb Smirnoff cmd->arg1); 4093b3a8eb9SGleb Smirnoff break; 4103b3a8eb9SGleb Smirnoff case O_NAT: 4113b3a8eb9SGleb Smirnoff action = "Nat"; 4123b3a8eb9SGleb Smirnoff break; 4133b3a8eb9SGleb Smirnoff case O_REASS: 4143b3a8eb9SGleb Smirnoff action = "Reass"; 4153b3a8eb9SGleb Smirnoff break; 4163b3a8eb9SGleb Smirnoff case O_CALLRETURN: 4173b3a8eb9SGleb Smirnoff if (cmd->len & F_NOT) 4183b3a8eb9SGleb Smirnoff action = "Return"; 4193b3a8eb9SGleb Smirnoff else 4203b3a8eb9SGleb Smirnoff snprintf(SNPARGS(action2, 0), "Call %d", 4213b3a8eb9SGleb Smirnoff cmd->arg1); 4223b3a8eb9SGleb Smirnoff break; 4233b3a8eb9SGleb Smirnoff default: 4243b3a8eb9SGleb Smirnoff action = "UNKNOWN"; 4253b3a8eb9SGleb Smirnoff break; 4263b3a8eb9SGleb Smirnoff } 4273b3a8eb9SGleb Smirnoff } 4283b3a8eb9SGleb Smirnoff 4293b3a8eb9SGleb Smirnoff if (hlen == 0) { /* non-ip */ 4303b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, 0), "MAC"); 4313b3a8eb9SGleb Smirnoff 4323b3a8eb9SGleb Smirnoff } else { 4333b3a8eb9SGleb Smirnoff int len; 4343b3a8eb9SGleb Smirnoff #ifdef INET6 4353b3a8eb9SGleb Smirnoff char src[INET6_ADDRSTRLEN + 2], dst[INET6_ADDRSTRLEN + 2]; 4363b3a8eb9SGleb Smirnoff #else 4373b3a8eb9SGleb Smirnoff char src[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN]; 4383b3a8eb9SGleb Smirnoff #endif 4393b3a8eb9SGleb Smirnoff struct icmphdr *icmp; 4403b3a8eb9SGleb Smirnoff struct tcphdr *tcp; 4413b3a8eb9SGleb Smirnoff struct udphdr *udp; 4423b3a8eb9SGleb Smirnoff #ifdef INET6 4433b3a8eb9SGleb Smirnoff struct ip6_hdr *ip6 = NULL; 4443b3a8eb9SGleb Smirnoff struct icmp6_hdr *icmp6; 4453b3a8eb9SGleb Smirnoff u_short ip6f_mf; 4463b3a8eb9SGleb Smirnoff #endif 4473b3a8eb9SGleb Smirnoff src[0] = '\0'; 4483b3a8eb9SGleb Smirnoff dst[0] = '\0'; 4493b3a8eb9SGleb Smirnoff #ifdef INET6 4503b3a8eb9SGleb Smirnoff ip6f_mf = offset & IP6F_MORE_FRAG; 4513b3a8eb9SGleb Smirnoff offset &= IP6F_OFF_MASK; 4523b3a8eb9SGleb Smirnoff 4533b3a8eb9SGleb Smirnoff if (IS_IP6_FLOW_ID(&(args->f_id))) { 4543b3a8eb9SGleb Smirnoff char ip6buf[INET6_ADDRSTRLEN]; 4553b3a8eb9SGleb Smirnoff snprintf(src, sizeof(src), "[%s]", 4563b3a8eb9SGleb Smirnoff ip6_sprintf(ip6buf, &args->f_id.src_ip6)); 4573b3a8eb9SGleb Smirnoff snprintf(dst, sizeof(dst), "[%s]", 4583b3a8eb9SGleb Smirnoff ip6_sprintf(ip6buf, &args->f_id.dst_ip6)); 4593b3a8eb9SGleb Smirnoff 4603b3a8eb9SGleb Smirnoff ip6 = (struct ip6_hdr *)ip; 4613b3a8eb9SGleb Smirnoff tcp = (struct tcphdr *)(((char *)ip) + hlen); 4623b3a8eb9SGleb Smirnoff udp = (struct udphdr *)(((char *)ip) + hlen); 4633b3a8eb9SGleb Smirnoff } else 4643b3a8eb9SGleb Smirnoff #endif 4653b3a8eb9SGleb Smirnoff { 4663b3a8eb9SGleb Smirnoff tcp = L3HDR(struct tcphdr, ip); 4673b3a8eb9SGleb Smirnoff udp = L3HDR(struct udphdr, ip); 4683b3a8eb9SGleb Smirnoff 4693b3a8eb9SGleb Smirnoff inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); 4703b3a8eb9SGleb Smirnoff inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); 4713b3a8eb9SGleb Smirnoff } 4723b3a8eb9SGleb Smirnoff 4733b3a8eb9SGleb Smirnoff switch (args->f_id.proto) { 4743b3a8eb9SGleb Smirnoff case IPPROTO_TCP: 4753b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "TCP %s", src); 4763b3a8eb9SGleb Smirnoff if (offset == 0) 4773b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), ":%d %s:%d", 4783b3a8eb9SGleb Smirnoff ntohs(tcp->th_sport), 4793b3a8eb9SGleb Smirnoff dst, 4803b3a8eb9SGleb Smirnoff ntohs(tcp->th_dport)); 4813b3a8eb9SGleb Smirnoff else 4823b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 4833b3a8eb9SGleb Smirnoff break; 4843b3a8eb9SGleb Smirnoff 4853b3a8eb9SGleb Smirnoff case IPPROTO_UDP: 4863b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "UDP %s", src); 4873b3a8eb9SGleb Smirnoff if (offset == 0) 4883b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), ":%d %s:%d", 4893b3a8eb9SGleb Smirnoff ntohs(udp->uh_sport), 4903b3a8eb9SGleb Smirnoff dst, 4913b3a8eb9SGleb Smirnoff ntohs(udp->uh_dport)); 4923b3a8eb9SGleb Smirnoff else 4933b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 4943b3a8eb9SGleb Smirnoff break; 4953b3a8eb9SGleb Smirnoff 4963b3a8eb9SGleb Smirnoff case IPPROTO_ICMP: 4973b3a8eb9SGleb Smirnoff icmp = L3HDR(struct icmphdr, ip); 4983b3a8eb9SGleb Smirnoff if (offset == 0) 4993b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), 5003b3a8eb9SGleb Smirnoff "ICMP:%u.%u ", 5013b3a8eb9SGleb Smirnoff icmp->icmp_type, icmp->icmp_code); 5023b3a8eb9SGleb Smirnoff else 5033b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "ICMP "); 5043b3a8eb9SGleb Smirnoff len += snprintf(SNPARGS(proto, len), "%s", src); 5053b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 5063b3a8eb9SGleb Smirnoff break; 5073b3a8eb9SGleb Smirnoff #ifdef INET6 5083b3a8eb9SGleb Smirnoff case IPPROTO_ICMPV6: 5093b3a8eb9SGleb Smirnoff icmp6 = (struct icmp6_hdr *)(((char *)ip) + hlen); 5103b3a8eb9SGleb Smirnoff if (offset == 0) 5113b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), 5123b3a8eb9SGleb Smirnoff "ICMPv6:%u.%u ", 5133b3a8eb9SGleb Smirnoff icmp6->icmp6_type, icmp6->icmp6_code); 5143b3a8eb9SGleb Smirnoff else 5153b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "ICMPv6 "); 5163b3a8eb9SGleb Smirnoff len += snprintf(SNPARGS(proto, len), "%s", src); 5173b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 5183b3a8eb9SGleb Smirnoff break; 5193b3a8eb9SGleb Smirnoff #endif 5203b3a8eb9SGleb Smirnoff default: 5213b3a8eb9SGleb Smirnoff len = snprintf(SNPARGS(proto, 0), "P:%d %s", 5223b3a8eb9SGleb Smirnoff args->f_id.proto, src); 5233b3a8eb9SGleb Smirnoff snprintf(SNPARGS(proto, len), " %s", dst); 5243b3a8eb9SGleb Smirnoff break; 5253b3a8eb9SGleb Smirnoff } 5263b3a8eb9SGleb Smirnoff 5273b3a8eb9SGleb Smirnoff #ifdef INET6 5283b3a8eb9SGleb Smirnoff if (IS_IP6_FLOW_ID(&(args->f_id))) { 529bf55a003SAndrey V. Elsukov if (offset || ip6f_mf) 5303b3a8eb9SGleb Smirnoff snprintf(SNPARGS(fragment, 0), 5313b3a8eb9SGleb Smirnoff " (frag %08x:%d@%d%s)", 5323b3a8eb9SGleb Smirnoff args->f_id.extra, 5333b3a8eb9SGleb Smirnoff ntohs(ip6->ip6_plen) - hlen, 5343b3a8eb9SGleb Smirnoff ntohs(offset) << 3, ip6f_mf ? "+" : ""); 5353b3a8eb9SGleb Smirnoff } else 5363b3a8eb9SGleb Smirnoff #endif 5373b3a8eb9SGleb Smirnoff { 5383b3a8eb9SGleb Smirnoff int ipoff, iplen; 5393b3a8eb9SGleb Smirnoff ipoff = ntohs(ip->ip_off); 5403b3a8eb9SGleb Smirnoff iplen = ntohs(ip->ip_len); 5413b3a8eb9SGleb Smirnoff if (ipoff & (IP_MF | IP_OFFMASK)) 5423b3a8eb9SGleb Smirnoff snprintf(SNPARGS(fragment, 0), 5433b3a8eb9SGleb Smirnoff " (frag %d:%d@%d%s)", 5443b3a8eb9SGleb Smirnoff ntohs(ip->ip_id), iplen - (ip->ip_hl << 2), 5453b3a8eb9SGleb Smirnoff offset << 3, 5463b3a8eb9SGleb Smirnoff (ipoff & IP_MF) ? "+" : ""); 5473b3a8eb9SGleb Smirnoff } 5483b3a8eb9SGleb Smirnoff } 5493b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 5503b3a8eb9SGleb Smirnoff if (oif || m->m_pkthdr.rcvif) 5513b3a8eb9SGleb Smirnoff log(LOG_SECURITY | LOG_INFO, 5523b3a8eb9SGleb Smirnoff "ipfw: %d %s %s %s via %s%s\n", 5533b3a8eb9SGleb Smirnoff f ? f->rulenum : -1, 5543b3a8eb9SGleb Smirnoff action, proto, oif ? "out" : "in", 5553b3a8eb9SGleb Smirnoff oif ? oif->if_xname : m->m_pkthdr.rcvif->if_xname, 5563b3a8eb9SGleb Smirnoff fragment); 5573b3a8eb9SGleb Smirnoff else 5583b3a8eb9SGleb Smirnoff #endif 5593b3a8eb9SGleb Smirnoff log(LOG_SECURITY | LOG_INFO, 5603b3a8eb9SGleb Smirnoff "ipfw: %d %s %s [no if info]%s\n", 5613b3a8eb9SGleb Smirnoff f ? f->rulenum : -1, 5623b3a8eb9SGleb Smirnoff action, proto, fragment); 5633b3a8eb9SGleb Smirnoff if (limit_reached) 5643b3a8eb9SGleb Smirnoff log(LOG_SECURITY | LOG_NOTICE, 5653b3a8eb9SGleb Smirnoff "ipfw: limit %d reached on entry %d\n", 5663b3a8eb9SGleb Smirnoff limit_reached, f ? f->rulenum : -1); 5673b3a8eb9SGleb Smirnoff } 5683b3a8eb9SGleb Smirnoff /* end of file */ 569