Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: add generic ARP packet logger

This adds the generic plain text packet loggger for ARP packets. It is
based on the ebt_log code. Nevertheless, the output has been modified
to make it consistent with the original xt_LOG output.

This is an example output:

IN=wlan0 OUT= ARP HTYPE=1 PTYPE=0x0800 OPCODE=2 MACSRC=00:ab:12:34:55:63 IPSRC=192.168.10.1 MACDST=80:09:12:70:4f:50 IPDST=192.168.10.150

This patch enables packet logging from ARP chains, eg.

nft add rule arp filter input log prefix "input: "

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+155
+5
net/ipv4/netfilter/Kconfig
··· 159 159 160 160 To compile it as a module, choose M here. If unsure, say N. 161 161 162 + config NF_LOG_ARP 163 + tristate "ARP packet logging" 164 + default m if NETFILTER_ADVANCED=n 165 + select NF_LOG_INET 166 + 162 167 config NF_LOG_IPV4 163 168 tristate "IPv4 packet logging" 164 169 default m if NETFILTER_ADVANCED=n
+1
net/ipv4/netfilter/Makefile
··· 20 20 obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o 21 21 22 22 # logging 23 + obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o 23 24 obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o 24 25 25 26 # NAT helpers (nf_conntrack)
+149
net/ipv4/netfilter/nf_log_arp.c
··· 1 + /* 2 + * (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org> 3 + * 4 + * Based on code from ebt_log from: 5 + * 6 + * Bart De Schuymer <bdschuym@pandora.be> 7 + * Harald Welte <laforge@netfilter.org> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/spinlock.h> 16 + #include <linux/skbuff.h> 17 + #include <linux/if_arp.h> 18 + #include <linux/ip.h> 19 + #include <net/route.h> 20 + 21 + #include <linux/netfilter.h> 22 + #include <linux/netfilter/xt_LOG.h> 23 + #include <net/netfilter/nf_log.h> 24 + 25 + static struct nf_loginfo default_loginfo = { 26 + .type = NF_LOG_TYPE_LOG, 27 + .u = { 28 + .log = { 29 + .level = 5, 30 + .logflags = NF_LOG_MASK, 31 + }, 32 + }, 33 + }; 34 + 35 + struct arppayload { 36 + unsigned char mac_src[ETH_ALEN]; 37 + unsigned char ip_src[4]; 38 + unsigned char mac_dst[ETH_ALEN]; 39 + unsigned char ip_dst[4]; 40 + }; 41 + 42 + static void dump_arp_packet(struct nf_log_buf *m, 43 + const struct nf_loginfo *info, 44 + const struct sk_buff *skb, unsigned int nhoff) 45 + { 46 + const struct arphdr *ah; 47 + struct arphdr _arph; 48 + const struct arppayload *ap; 49 + struct arppayload _arpp; 50 + 51 + ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); 52 + if (ah == NULL) { 53 + nf_log_buf_add(m, "TRUNCATED"); 54 + return; 55 + } 56 + nf_log_buf_add(m, "ARP HTYPE=%d PTYPE=0x%04x OPCODE=%d", 57 + ntohs(ah->ar_hrd), ntohs(ah->ar_pro), ntohs(ah->ar_op)); 58 + 59 + /* If it's for Ethernet and the lengths are OK, then log the ARP 60 + * payload. 61 + */ 62 + if (ah->ar_hrd != htons(1) || 63 + ah->ar_hln != ETH_ALEN || 64 + ah->ar_pln != sizeof(__be32)) 65 + return; 66 + 67 + ap = skb_header_pointer(skb, sizeof(_arph), sizeof(_arpp), &_arpp); 68 + if (ap == NULL) { 69 + nf_log_buf_add(m, " INCOMPLETE [%Zu bytes]", 70 + skb->len - sizeof(_arph)); 71 + return; 72 + } 73 + nf_log_buf_add(m, " MACSRC=%pM IPSRC=%pI4 MACDST=%pM IPDST=%pI4", 74 + ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst); 75 + } 76 + 77 + void nf_log_arp_packet(struct net *net, u_int8_t pf, 78 + unsigned int hooknum, const struct sk_buff *skb, 79 + const struct net_device *in, 80 + const struct net_device *out, 81 + const struct nf_loginfo *loginfo, 82 + const char *prefix) 83 + { 84 + struct nf_log_buf *m; 85 + 86 + /* FIXME: Disabled from containers until syslog ns is supported */ 87 + if (!net_eq(net, &init_net)) 88 + return; 89 + 90 + m = nf_log_buf_open(); 91 + 92 + if (!loginfo) 93 + loginfo = &default_loginfo; 94 + 95 + nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo, 96 + prefix); 97 + dump_arp_packet(m, loginfo, skb, 0); 98 + 99 + nf_log_buf_close(m); 100 + } 101 + 102 + static struct nf_logger nf_arp_logger __read_mostly = { 103 + .name = "nf_log_arp", 104 + .type = NF_LOG_TYPE_LOG, 105 + .logfn = nf_log_arp_packet, 106 + .me = THIS_MODULE, 107 + }; 108 + 109 + static int __net_init nf_log_arp_net_init(struct net *net) 110 + { 111 + nf_log_set(net, NFPROTO_ARP, &nf_arp_logger); 112 + return 0; 113 + } 114 + 115 + static void __net_exit nf_log_arp_net_exit(struct net *net) 116 + { 117 + nf_log_unset(net, &nf_arp_logger); 118 + } 119 + 120 + static struct pernet_operations nf_log_arp_net_ops = { 121 + .init = nf_log_arp_net_init, 122 + .exit = nf_log_arp_net_exit, 123 + }; 124 + 125 + static int __init nf_log_arp_init(void) 126 + { 127 + int ret; 128 + 129 + ret = register_pernet_subsys(&nf_log_arp_net_ops); 130 + if (ret < 0) 131 + return ret; 132 + 133 + nf_log_register(NFPROTO_ARP, &nf_arp_logger); 134 + return 0; 135 + } 136 + 137 + static void __exit nf_log_arp_exit(void) 138 + { 139 + unregister_pernet_subsys(&nf_log_arp_net_ops); 140 + nf_log_unregister(&nf_arp_logger); 141 + } 142 + 143 + module_init(nf_log_arp_init); 144 + module_exit(nf_log_arp_exit); 145 + 146 + MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 147 + MODULE_DESCRIPTION("Netfilter ARP packet logging"); 148 + MODULE_LICENSE("GPL"); 149 + MODULE_ALIAS_NF_LOGGER(3, 0);