0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0010
0011 #include <linux/audit.h>
0012 #include <linux/module.h>
0013 #include <linux/skbuff.h>
0014 #include <linux/tcp.h>
0015 #include <linux/udp.h>
0016 #include <linux/if_arp.h>
0017 #include <linux/netfilter/x_tables.h>
0018 #include <linux/netfilter/xt_AUDIT.h>
0019 #include <linux/netfilter_bridge/ebtables.h>
0020 #include <net/ipv6.h>
0021 #include <net/ip.h>
0022
0023 MODULE_LICENSE("GPL");
0024 MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>");
0025 MODULE_DESCRIPTION("Xtables: creates audit records for dropped/accepted packets");
0026 MODULE_ALIAS("ipt_AUDIT");
0027 MODULE_ALIAS("ip6t_AUDIT");
0028 MODULE_ALIAS("ebt_AUDIT");
0029 MODULE_ALIAS("arpt_AUDIT");
0030
0031 static bool audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
0032 {
0033 struct iphdr _iph;
0034 const struct iphdr *ih;
0035
0036 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_iph), &_iph);
0037 if (!ih)
0038 return false;
0039
0040 audit_log_format(ab, " saddr=%pI4 daddr=%pI4 proto=%hhu",
0041 &ih->saddr, &ih->daddr, ih->protocol);
0042
0043 return true;
0044 }
0045
0046 static bool audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
0047 {
0048 struct ipv6hdr _ip6h;
0049 const struct ipv6hdr *ih;
0050 u8 nexthdr;
0051 __be16 frag_off;
0052
0053 ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
0054 if (!ih)
0055 return false;
0056
0057 nexthdr = ih->nexthdr;
0058 ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h), &nexthdr, &frag_off);
0059
0060 audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
0061 &ih->saddr, &ih->daddr, nexthdr);
0062
0063 return true;
0064 }
0065
0066 static unsigned int
0067 audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
0068 {
0069 struct audit_buffer *ab;
0070 int fam = -1;
0071
0072 if (audit_enabled == AUDIT_OFF)
0073 goto errout;
0074 ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
0075 if (ab == NULL)
0076 goto errout;
0077
0078 audit_log_format(ab, "mark=%#x", skb->mark);
0079
0080 switch (xt_family(par)) {
0081 case NFPROTO_BRIDGE:
0082 switch (eth_hdr(skb)->h_proto) {
0083 case htons(ETH_P_IP):
0084 fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
0085 break;
0086 case htons(ETH_P_IPV6):
0087 fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
0088 break;
0089 }
0090 break;
0091 case NFPROTO_IPV4:
0092 fam = audit_ip4(ab, skb) ? NFPROTO_IPV4 : -1;
0093 break;
0094 case NFPROTO_IPV6:
0095 fam = audit_ip6(ab, skb) ? NFPROTO_IPV6 : -1;
0096 break;
0097 }
0098
0099 if (fam == -1)
0100 audit_log_format(ab, " saddr=? daddr=? proto=-1");
0101
0102 audit_log_end(ab);
0103
0104 errout:
0105 return XT_CONTINUE;
0106 }
0107
0108 static unsigned int
0109 audit_tg_ebt(struct sk_buff *skb, const struct xt_action_param *par)
0110 {
0111 audit_tg(skb, par);
0112 return EBT_CONTINUE;
0113 }
0114
0115 static int audit_tg_check(const struct xt_tgchk_param *par)
0116 {
0117 const struct xt_audit_info *info = par->targinfo;
0118
0119 if (info->type > XT_AUDIT_TYPE_MAX) {
0120 pr_info_ratelimited("Audit type out of range (valid range: 0..%u)\n",
0121 XT_AUDIT_TYPE_MAX);
0122 return -ERANGE;
0123 }
0124
0125 return 0;
0126 }
0127
0128 static struct xt_target audit_tg_reg[] __read_mostly = {
0129 {
0130 .name = "AUDIT",
0131 .family = NFPROTO_UNSPEC,
0132 .target = audit_tg,
0133 .targetsize = sizeof(struct xt_audit_info),
0134 .checkentry = audit_tg_check,
0135 .me = THIS_MODULE,
0136 },
0137 {
0138 .name = "AUDIT",
0139 .family = NFPROTO_BRIDGE,
0140 .target = audit_tg_ebt,
0141 .targetsize = sizeof(struct xt_audit_info),
0142 .checkentry = audit_tg_check,
0143 .me = THIS_MODULE,
0144 },
0145 };
0146
0147 static int __init audit_tg_init(void)
0148 {
0149 return xt_register_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
0150 }
0151
0152 static void __exit audit_tg_exit(void)
0153 {
0154 xt_unregister_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
0155 }
0156
0157 module_init(audit_tg_init);
0158 module_exit(audit_tg_exit);