Blame view

net/netfilter/xt_AUDIT.c 5.08 KB
43f393cae   Thomas Graf   netfilter: audit ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  /*
   * Creates audit record for dropped/accepted packets
   *
   * (C) 2010-2011 Thomas Graf <tgraf@redhat.com>
   * (C) 2010-2011 Red Hat, Inc.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
  */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/audit.h>
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/if_arp.h>
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_AUDIT.h>
400b871ba   Thomas Graf   netfilter ebtable...
22
  #include <linux/netfilter_bridge/ebtables.h>
43f393cae   Thomas Graf   netfilter: audit ...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  #include <net/ipv6.h>
  #include <net/ip.h>
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>");
  MODULE_DESCRIPTION("Xtables: creates audit records for dropped/accepted packets");
  MODULE_ALIAS("ipt_AUDIT");
  MODULE_ALIAS("ip6t_AUDIT");
  MODULE_ALIAS("ebt_AUDIT");
  MODULE_ALIAS("arpt_AUDIT");
  
  static void audit_proto(struct audit_buffer *ab, struct sk_buff *skb,
  			unsigned int proto, unsigned int offset)
  {
  	switch (proto) {
  	case IPPROTO_TCP:
  	case IPPROTO_UDP:
  	case IPPROTO_UDPLITE: {
  		const __be16 *pptr;
  		__be16 _ports[2];
  
  		pptr = skb_header_pointer(skb, offset, sizeof(_ports), _ports);
  		if (pptr == NULL) {
  			audit_log_format(ab, " truncated=1");
  			return;
  		}
  
  		audit_log_format(ab, " sport=%hu dport=%hu",
  				 ntohs(pptr[0]), ntohs(pptr[1]));
  		}
  		break;
  
  	case IPPROTO_ICMP:
  	case IPPROTO_ICMPV6: {
  		const u8 *iptr;
  		u8 _ih[2];
  
  		iptr = skb_header_pointer(skb, offset, sizeof(_ih), &_ih);
  		if (iptr == NULL) {
  			audit_log_format(ab, " truncated=1");
  			return;
  		}
  
  		audit_log_format(ab, " icmptype=%hhu icmpcode=%hhu",
  				 iptr[0], iptr[1]);
  
  		}
  		break;
  	}
  }
  
  static void audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
  {
  	struct iphdr _iph;
  	const struct iphdr *ih;
  
  	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
  	if (!ih) {
  		audit_log_format(ab, " truncated=1");
  		return;
  	}
  
  	audit_log_format(ab, " saddr=%pI4 daddr=%pI4 ipid=%hu proto=%hhu",
  		&ih->saddr, &ih->daddr, ntohs(ih->id), ih->protocol);
  
  	if (ntohs(ih->frag_off) & IP_OFFSET) {
  		audit_log_format(ab, " frag=1");
  		return;
  	}
  
  	audit_proto(ab, skb, ih->protocol, ih->ihl * 4);
  }
  
  static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
  {
  	struct ipv6hdr _ip6h;
  	const struct ipv6hdr *ih;
  	u8 nexthdr;
75f2811c6   Jesse Gross   ipv6: Add fragmen...
101
  	__be16 frag_off;
43f393cae   Thomas Graf   netfilter: audit ...
102
103
104
105
106
107
108
109
110
111
  	int offset;
  
  	ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
  	if (!ih) {
  		audit_log_format(ab, " truncated=1");
  		return;
  	}
  
  	nexthdr = ih->nexthdr;
  	offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h),
75f2811c6   Jesse Gross   ipv6: Add fragmen...
112
  				  &nexthdr, &frag_off);
43f393cae   Thomas Graf   netfilter: audit ...
113
114
115
116
117
118
119
120
121
122
123
124
125
  
  	audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
  			 &ih->saddr, &ih->daddr, nexthdr);
  
  	if (offset)
  		audit_proto(ab, skb, nexthdr, offset);
  }
  
  static unsigned int
  audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
  {
  	const struct xt_audit_info *info = par->targinfo;
  	struct audit_buffer *ab;
ed018fa4d   Gao feng   netfilter: xt_AUD...
126
127
  	if (audit_enabled == 0)
  		goto errout;
43f393cae   Thomas Graf   netfilter: audit ...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
  	if (ab == NULL)
  		goto errout;
  
  	audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s",
  			 info->type, par->hooknum, skb->len,
  			 par->in ? par->in->name : "?",
  			 par->out ? par->out->name : "?");
  
  	if (skb->mark)
  		audit_log_format(ab, " mark=%#x", skb->mark);
  
  	if (skb->dev && skb->dev->type == ARPHRD_ETHER) {
  		audit_log_format(ab, " smac=%pM dmac=%pM macproto=0x%04x",
  				 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
  				 ntohs(eth_hdr(skb)->h_proto));
  
  		if (par->family == NFPROTO_BRIDGE) {
  			switch (eth_hdr(skb)->h_proto) {
b80edf0b5   Joe Perches   netfilter: Conver...
147
  			case htons(ETH_P_IP):
43f393cae   Thomas Graf   netfilter: audit ...
148
149
  				audit_ip4(ab, skb);
  				break;
b80edf0b5   Joe Perches   netfilter: Conver...
150
  			case htons(ETH_P_IPV6):
43f393cae   Thomas Graf   netfilter: audit ...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  				audit_ip6(ab, skb);
  				break;
  			}
  		}
  	}
  
  	switch (par->family) {
  	case NFPROTO_IPV4:
  		audit_ip4(ab, skb);
  		break;
  
  	case NFPROTO_IPV6:
  		audit_ip6(ab, skb);
  		break;
  	}
131ad62d8   Mr Dash Four   netfilter: add SE...
166
167
168
169
  #ifdef CONFIG_NETWORK_SECMARK
  	if (skb->secmark)
  		audit_log_secctx(ab, skb->secmark);
  #endif
43f393cae   Thomas Graf   netfilter: audit ...
170
171
172
173
174
  	audit_log_end(ab);
  
  errout:
  	return XT_CONTINUE;
  }
400b871ba   Thomas Graf   netfilter ebtable...
175
176
177
178
179
180
  static unsigned int
  audit_tg_ebt(struct sk_buff *skb, const struct xt_action_param *par)
  {
  	audit_tg(skb, par);
  	return EBT_CONTINUE;
  }
43f393cae   Thomas Graf   netfilter: audit ...
181
182
183
184
185
186
187
188
189
190
191
192
193
  static int audit_tg_check(const struct xt_tgchk_param *par)
  {
  	const struct xt_audit_info *info = par->targinfo;
  
  	if (info->type > XT_AUDIT_TYPE_MAX) {
  		pr_info("Audit type out of range (valid range: 0..%hhu)
  ",
  			XT_AUDIT_TYPE_MAX);
  		return -ERANGE;
  	}
  
  	return 0;
  }
400b871ba   Thomas Graf   netfilter ebtable...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  static struct xt_target audit_tg_reg[] __read_mostly = {
  	{
  		.name		= "AUDIT",
  		.family		= NFPROTO_UNSPEC,
  		.target		= audit_tg,
  		.targetsize	= sizeof(struct xt_audit_info),
  		.checkentry	= audit_tg_check,
  		.me		= THIS_MODULE,
  	},
  	{
  		.name		= "AUDIT",
  		.family		= NFPROTO_BRIDGE,
  		.target		= audit_tg_ebt,
  		.targetsize	= sizeof(struct xt_audit_info),
  		.checkentry	= audit_tg_check,
  		.me		= THIS_MODULE,
  	},
43f393cae   Thomas Graf   netfilter: audit ...
211
212
213
214
  };
  
  static int __init audit_tg_init(void)
  {
400b871ba   Thomas Graf   netfilter ebtable...
215
  	return xt_register_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
43f393cae   Thomas Graf   netfilter: audit ...
216
217
218
219
  }
  
  static void __exit audit_tg_exit(void)
  {
400b871ba   Thomas Graf   netfilter ebtable...
220
  	xt_unregister_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
43f393cae   Thomas Graf   netfilter: audit ...
221
222
223
224
  }
  
  module_init(audit_tg_init);
  module_exit(audit_tg_exit);