1 /* 2 * Creates audit record for dropped/accepted packets 3 * 4 * (C) 2010-2011 Thomas Graf <tgraf@redhat.com> 5 * (C) 2010-2011 Red Hat, Inc. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14 #include <linux/audit.h> 15 #include <linux/module.h> 16 #include <linux/skbuff.h> 17 #include <linux/tcp.h> 18 #include <linux/udp.h> 19 #include <linux/if_arp.h> 20 #include <linux/netfilter/x_tables.h> 21 #include <linux/netfilter/xt_AUDIT.h> 22 #include <linux/netfilter_bridge/ebtables.h> 23 #include <net/ipv6.h> 24 #include <net/ip.h> 25 26 MODULE_LICENSE("GPL"); 27 MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>"); 28 MODULE_DESCRIPTION("Xtables: creates audit records for dropped/accepted packets"); 29 MODULE_ALIAS("ipt_AUDIT"); 30 MODULE_ALIAS("ip6t_AUDIT"); 31 MODULE_ALIAS("ebt_AUDIT"); 32 MODULE_ALIAS("arpt_AUDIT"); 33 34 static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb) 35 { 36 struct iphdr _iph; 37 const struct iphdr *ih; 38 39 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph); 40 if (!ih) 41 return false; 42 43 audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu", 44 &ih->saddr, &ih->daddr, ih->protocol); 45 46 return true; 47 } 48 49 static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb) 50 { 51 struct ipv6hdr _ip6h; 52 const struct ipv6hdr *ih; 53 u8 nexthdr; 54 __be16 frag_off; 55 56 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h); 57 if (!ih) 58 return false; 59 60 nexthdr = ih->nexthdr; 61 ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off); 62 63 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu", 64 &ih->saddr, &ih->daddr, nexthdr); 65 66 return true; 67 } 68 69 static unsigned int 70 audit_tg(struct sk_buff *skb, const struct xt_action_param *par) 71 { 72 struct audit_buffer *ab; 73 int fam = -1; 74 75 if (audit_enabled == 0) 76 goto errout; 77 ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); 78 if (ab == NULL) 79 goto errout; 80 81 audit_log_format(ab, "mark=%#x", skb->mark); 82 83 switch (xt_family(par)) { 84 case NFPROTO_BRIDGE: 85 switch (eth_hdr(skb)->h_proto) { 86 case htons(ETH_P_IP): 87 fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; 88 break; 89 case htons(ETH_P_IPV6): 90 fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; 91 break; 92 } 93 break; 94 case NFPROTO_IPV4: 95 fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1; 96 break; 97 case NFPROTO_IPV6: 98 fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1; 99 break; 100 } 101 102 if (fam == -1) 103 audit_log_format(ab, " saddr=? daddr=? proto=-1"); 104 105 audit_log_end(ab); 106 107 errout: 108 return XT_CONTINUE; 109 } 110 111 static unsigned int 112 audit_tg_ebt(struct sk_buff *skb, const struct xt_action_param *par) 113 { 114 audit_tg(skb, par); 115 return EBT_CONTINUE; 116 } 117 118 static int audit_tg_check(const struct xt_tgchk_param *par) 119 { 120 const struct xt_audit_info *info = par->targinfo; 121 122 if (info->type > XT_AUDIT_TYPE_MAX) { 123 pr_info_ratelimited("Audit type out of range (valid range: 0..%hhu)\n", 124 XT_AUDIT_TYPE_MAX); 125 return -ERANGE; 126 } 127 128 return 0; 129 } 130 131 static struct xt_target audit_tg_reg[] __read_mostly = { 132 { 133 .name = "AUDIT", 134 .family = NFPROTO_UNSPEC, 135 .target = audit_tg, 136 .targetsize = sizeof(struct xt_audit_info), 137 .checkentry = audit_tg_check, 138 .me = THIS_MODULE, 139 }, 140 { 141 .name = "AUDIT", 142 .family = NFPROTO_BRIDGE, 143 .target = audit_tg_ebt, 144 .targetsize = sizeof(struct xt_audit_info), 145 .checkentry = audit_tg_check, 146 .me = THIS_MODULE, 147 }, 148 }; 149 150 static int __init audit_tg_init(void) 151 { 152 return xt_register_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg)); 153 } 154 155 static void __exit audit_tg_exit(void) 156 { 157 xt_unregister_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg)); 158 } 159 160 module_init(audit_tg_init); 161 module_exit(audit_tg_exit); 162