aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-06-19 14:47:14 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-06-27 07:19:59 -0400
commit83e96d443b372611adf19e4171d41deb1d8760cf (patch)
tree47d97976a40831ac75475b0836029120702a2e3b
parent27fd8d90c996caa480ed6777eaaf21d9e5166cc3 (diff)
netfilter: log: split family specific code to nf_log_{ip,ip6,common}.c files
The plain text logging is currently embedded into the xt_LOG target. In order to be able to use the plain text logging from nft_log, as a first step, this patch moves the family specific code to the following files and Kconfig symbols: 1) net/ipv4/netfilter/nf_log_ip.c: CONFIG_NF_LOG_IPV4 2) net/ipv6/netfilter/nf_log_ip6.c: CONFIG_NF_LOG_IPV6 3) net/netfilter/nf_log_common.c: CONFIG_NF_LOG_COMMON These new modules will be required by xt_LOG and nft_log. This patch is based on original patch from Arturo Borrero Gonzalez. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/netfilter/nf_log.h28
-rw-r--r--net/ipv4/netfilter/Kconfig5
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/nf_log_ipv4.c385
-rw-r--r--net/ipv6/netfilter/Kconfig5
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/nf_log_ipv6.c417
-rw-r--r--net/netfilter/Kconfig6
-rw-r--r--net/netfilter/Makefile3
-rw-r--r--net/netfilter/nf_log_common.c187
-rw-r--r--net/netfilter/xt_LOG.c879
11 files changed, 1047 insertions, 874 deletions
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h
index aaec845de106..bba354e78f49 100644
--- a/include/net/netfilter/nf_log.h
+++ b/include/net/netfilter/nf_log.h
@@ -78,4 +78,32 @@ struct nf_log_buf *nf_log_buf_open(void);
78__printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...); 78__printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...);
79void nf_log_buf_close(struct nf_log_buf *m); 79void nf_log_buf_close(struct nf_log_buf *m);
80 80
81void nf_log_ip_packet(struct net *net, u_int8_t pf,
82 unsigned int hooknum, const struct sk_buff *skb,
83 const struct net_device *in,
84 const struct net_device *out,
85 const struct nf_loginfo *loginfo,
86 const char *prefix);
87
88void nf_log_ip6_packet(struct net *net, u_int8_t pf,
89 unsigned int hooknum, const struct sk_buff *skb,
90 const struct net_device *in,
91 const struct net_device *out,
92 const struct nf_loginfo *loginfo,
93 const char *prefix);
94
95/* common logging functions */
96int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
97 u8 proto, int fragment, unsigned int offset);
98int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
99 u8 proto, int fragment, unsigned int offset,
100 unsigned int logflags);
101void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk);
102void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
103 unsigned int hooknum, const struct sk_buff *skb,
104 const struct net_device *in,
105 const struct net_device *out,
106 const struct nf_loginfo *loginfo,
107 const char *prefix);
108
81#endif /* _NF_LOG_H */ 109#endif /* _NF_LOG_H */
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 730faacbc5f8..0c980293d225 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -159,6 +159,11 @@ config IP_NF_TARGET_SYNPROXY
159 159
160 To compile it as a module, choose M here. If unsure, say N. 160 To compile it as a module, choose M here. If unsure, say N.
161 161
162config NF_LOG_IPV4
163 tristate "IPv4 packet logging"
164 default m if NETFILTER_ADVANCED=n
165 select NF_LOG_COMMON
166
162# NAT + specific targets: nf_conntrack 167# NAT + specific targets: nf_conntrack
163config NF_NAT_IPV4 168config NF_NAT_IPV4
164 tristate "IPv4 NAT" 169 tristate "IPv4 NAT"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 90b82405331e..730e0c1ead90 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -19,6 +19,9 @@ obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
19# defrag 19# defrag
20obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o 20obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
21 21
22# logging
23obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o
24
22# NAT helpers (nf_conntrack) 25# NAT helpers (nf_conntrack)
23obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 26obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
24obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 27obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c
new file mode 100644
index 000000000000..7e69a401a29e
--- /dev/null
+++ b/net/ipv4/netfilter/nf_log_ipv4.c
@@ -0,0 +1,385 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/spinlock.h>
11#include <linux/skbuff.h>
12#include <linux/if_arp.h>
13#include <linux/ip.h>
14#include <net/ipv6.h>
15#include <net/icmp.h>
16#include <net/udp.h>
17#include <net/tcp.h>
18#include <net/route.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter/xt_LOG.h>
22#include <net/netfilter/nf_log.h>
23
24static struct nf_loginfo default_loginfo = {
25 .type = NF_LOG_TYPE_LOG,
26 .u = {
27 .log = {
28 .level = 5,
29 .logflags = NF_LOG_MASK,
30 },
31 },
32};
33
34/* One level of recursion won't kill us */
35static void dump_ipv4_packet(struct nf_log_buf *m,
36 const struct nf_loginfo *info,
37 const struct sk_buff *skb, unsigned int iphoff)
38{
39 struct iphdr _iph;
40 const struct iphdr *ih;
41 unsigned int logflags;
42
43 if (info->type == NF_LOG_TYPE_LOG)
44 logflags = info->u.log.logflags;
45 else
46 logflags = NF_LOG_MASK;
47
48 ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
49 if (ih == NULL) {
50 nf_log_buf_add(m, "TRUNCATED");
51 return;
52 }
53
54 /* Important fields:
55 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
56 /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
57 nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr);
58
59 /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
60 nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
61 ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
62 ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
63
64 /* Max length: 6 "CE DF MF " */
65 if (ntohs(ih->frag_off) & IP_CE)
66 nf_log_buf_add(m, "CE ");
67 if (ntohs(ih->frag_off) & IP_DF)
68 nf_log_buf_add(m, "DF ");
69 if (ntohs(ih->frag_off) & IP_MF)
70 nf_log_buf_add(m, "MF ");
71
72 /* Max length: 11 "FRAG:65535 " */
73 if (ntohs(ih->frag_off) & IP_OFFSET)
74 nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
75
76 if ((logflags & XT_LOG_IPOPT) &&
77 ih->ihl * 4 > sizeof(struct iphdr)) {
78 const unsigned char *op;
79 unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
80 unsigned int i, optsize;
81
82 optsize = ih->ihl * 4 - sizeof(struct iphdr);
83 op = skb_header_pointer(skb, iphoff+sizeof(_iph),
84 optsize, _opt);
85 if (op == NULL) {
86 nf_log_buf_add(m, "TRUNCATED");
87 return;
88 }
89
90 /* Max length: 127 "OPT (" 15*4*2chars ") " */
91 nf_log_buf_add(m, "OPT (");
92 for (i = 0; i < optsize; i++)
93 nf_log_buf_add(m, "%02X", op[i]);
94 nf_log_buf_add(m, ") ");
95 }
96
97 switch (ih->protocol) {
98 case IPPROTO_TCP:
99 if (nf_log_dump_tcp_header(m, skb, ih->protocol,
100 ntohs(ih->frag_off) & IP_OFFSET,
101 iphoff+ih->ihl*4, logflags))
102 return;
103 break;
104 case IPPROTO_UDP:
105 case IPPROTO_UDPLITE:
106 if (nf_log_dump_udp_header(m, skb, ih->protocol,
107 ntohs(ih->frag_off) & IP_OFFSET,
108 iphoff+ih->ihl*4))
109 return;
110 break;
111 case IPPROTO_ICMP: {
112 struct icmphdr _icmph;
113 const struct icmphdr *ich;
114 static const size_t required_len[NR_ICMP_TYPES+1]
115 = { [ICMP_ECHOREPLY] = 4,
116 [ICMP_DEST_UNREACH]
117 = 8 + sizeof(struct iphdr),
118 [ICMP_SOURCE_QUENCH]
119 = 8 + sizeof(struct iphdr),
120 [ICMP_REDIRECT]
121 = 8 + sizeof(struct iphdr),
122 [ICMP_ECHO] = 4,
123 [ICMP_TIME_EXCEEDED]
124 = 8 + sizeof(struct iphdr),
125 [ICMP_PARAMETERPROB]
126 = 8 + sizeof(struct iphdr),
127 [ICMP_TIMESTAMP] = 20,
128 [ICMP_TIMESTAMPREPLY] = 20,
129 [ICMP_ADDRESS] = 12,
130 [ICMP_ADDRESSREPLY] = 12 };
131
132 /* Max length: 11 "PROTO=ICMP " */
133 nf_log_buf_add(m, "PROTO=ICMP ");
134
135 if (ntohs(ih->frag_off) & IP_OFFSET)
136 break;
137
138 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
139 ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
140 sizeof(_icmph), &_icmph);
141 if (ich == NULL) {
142 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
143 skb->len - iphoff - ih->ihl*4);
144 break;
145 }
146
147 /* Max length: 18 "TYPE=255 CODE=255 " */
148 nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
149
150 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
151 if (ich->type <= NR_ICMP_TYPES &&
152 required_len[ich->type] &&
153 skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
154 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
155 skb->len - iphoff - ih->ihl*4);
156 break;
157 }
158
159 switch (ich->type) {
160 case ICMP_ECHOREPLY:
161 case ICMP_ECHO:
162 /* Max length: 19 "ID=65535 SEQ=65535 " */
163 nf_log_buf_add(m, "ID=%u SEQ=%u ",
164 ntohs(ich->un.echo.id),
165 ntohs(ich->un.echo.sequence));
166 break;
167
168 case ICMP_PARAMETERPROB:
169 /* Max length: 14 "PARAMETER=255 " */
170 nf_log_buf_add(m, "PARAMETER=%u ",
171 ntohl(ich->un.gateway) >> 24);
172 break;
173 case ICMP_REDIRECT:
174 /* Max length: 24 "GATEWAY=255.255.255.255 " */
175 nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
176 /* Fall through */
177 case ICMP_DEST_UNREACH:
178 case ICMP_SOURCE_QUENCH:
179 case ICMP_TIME_EXCEEDED:
180 /* Max length: 3+maxlen */
181 if (!iphoff) { /* Only recurse once. */
182 nf_log_buf_add(m, "[");
183 dump_ipv4_packet(m, info, skb,
184 iphoff + ih->ihl*4+sizeof(_icmph));
185 nf_log_buf_add(m, "] ");
186 }
187
188 /* Max length: 10 "MTU=65535 " */
189 if (ich->type == ICMP_DEST_UNREACH &&
190 ich->code == ICMP_FRAG_NEEDED) {
191 nf_log_buf_add(m, "MTU=%u ",
192 ntohs(ich->un.frag.mtu));
193 }
194 }
195 break;
196 }
197 /* Max Length */
198 case IPPROTO_AH: {
199 struct ip_auth_hdr _ahdr;
200 const struct ip_auth_hdr *ah;
201
202 if (ntohs(ih->frag_off) & IP_OFFSET)
203 break;
204
205 /* Max length: 9 "PROTO=AH " */
206 nf_log_buf_add(m, "PROTO=AH ");
207
208 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
209 ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
210 sizeof(_ahdr), &_ahdr);
211 if (ah == NULL) {
212 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
213 skb->len - iphoff - ih->ihl*4);
214 break;
215 }
216
217 /* Length: 15 "SPI=0xF1234567 " */
218 nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
219 break;
220 }
221 case IPPROTO_ESP: {
222 struct ip_esp_hdr _esph;
223 const struct ip_esp_hdr *eh;
224
225 /* Max length: 10 "PROTO=ESP " */
226 nf_log_buf_add(m, "PROTO=ESP ");
227
228 if (ntohs(ih->frag_off) & IP_OFFSET)
229 break;
230
231 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
232 eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
233 sizeof(_esph), &_esph);
234 if (eh == NULL) {
235 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
236 skb->len - iphoff - ih->ihl*4);
237 break;
238 }
239
240 /* Length: 15 "SPI=0xF1234567 " */
241 nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi));
242 break;
243 }
244 /* Max length: 10 "PROTO 255 " */
245 default:
246 nf_log_buf_add(m, "PROTO=%u ", ih->protocol);
247 }
248
249 /* Max length: 15 "UID=4294967295 " */
250 if ((logflags & XT_LOG_UID) && !iphoff)
251 nf_log_dump_sk_uid_gid(m, skb->sk);
252
253 /* Max length: 16 "MARK=0xFFFFFFFF " */
254 if (!iphoff && skb->mark)
255 nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
256
257 /* Proto Max log string length */
258 /* IP: 40+46+6+11+127 = 230 */
259 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
260 /* UDP: 10+max(25,20) = 35 */
261 /* UDPLITE: 14+max(25,20) = 39 */
262 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
263 /* ESP: 10+max(25)+15 = 50 */
264 /* AH: 9+max(25)+15 = 49 */
265 /* unknown: 10 */
266
267 /* (ICMP allows recursion one level deep) */
268 /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */
269 /* maxlen = 230+ 91 + 230 + 252 = 803 */
270}
271
272static void dump_ipv4_mac_header(struct nf_log_buf *m,
273 const struct nf_loginfo *info,
274 const struct sk_buff *skb)
275{
276 struct net_device *dev = skb->dev;
277 unsigned int logflags = 0;
278
279 if (info->type == NF_LOG_TYPE_LOG)
280 logflags = info->u.log.logflags;
281
282 if (!(logflags & XT_LOG_MACDECODE))
283 goto fallback;
284
285 switch (dev->type) {
286 case ARPHRD_ETHER:
287 nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
288 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
289 ntohs(eth_hdr(skb)->h_proto));
290 return;
291 default:
292 break;
293 }
294
295fallback:
296 nf_log_buf_add(m, "MAC=");
297 if (dev->hard_header_len &&
298 skb->mac_header != skb->network_header) {
299 const unsigned char *p = skb_mac_header(skb);
300 unsigned int i;
301
302 nf_log_buf_add(m, "%02x", *p++);
303 for (i = 1; i < dev->hard_header_len; i++, p++)
304 nf_log_buf_add(m, ":%02x", *p);
305 }
306 nf_log_buf_add(m, " ");
307}
308
309void nf_log_ip_packet(struct net *net, u_int8_t pf,
310 unsigned int hooknum, const struct sk_buff *skb,
311 const struct net_device *in,
312 const struct net_device *out,
313 const struct nf_loginfo *loginfo,
314 const char *prefix)
315{
316 struct nf_log_buf *m;
317
318 /* FIXME: Disabled from containers until syslog ns is supported */
319 if (!net_eq(net, &init_net))
320 return;
321
322 m = nf_log_buf_open();
323
324 if (!loginfo)
325 loginfo = &default_loginfo;
326
327 nf_log_dump_packet_common(m, pf, hooknum, skb, in,
328 out, loginfo, prefix);
329
330 if (in != NULL)
331 dump_ipv4_mac_header(m, loginfo, skb);
332
333 dump_ipv4_packet(m, loginfo, skb, 0);
334
335 nf_log_buf_close(m);
336}
337EXPORT_SYMBOL_GPL(nf_log_ip_packet);
338
339static struct nf_logger nf_ip_logger __read_mostly = {
340 .name = "nf_log_ipv4",
341 .type = NF_LOG_TYPE_LOG,
342 .logfn = nf_log_ip_packet,
343 .me = THIS_MODULE,
344};
345
346static int __net_init nf_log_ipv4_net_init(struct net *net)
347{
348 nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
349 return 0;
350}
351
352static void __net_exit nf_log_ipv4_net_exit(struct net *net)
353{
354 nf_log_unset(net, &nf_ip_logger);
355}
356
357static struct pernet_operations nf_log_ipv4_net_ops = {
358 .init = nf_log_ipv4_net_init,
359 .exit = nf_log_ipv4_net_exit,
360};
361
362static int __init nf_log_ipv4_init(void)
363{
364 int ret;
365
366 ret = register_pernet_subsys(&nf_log_ipv4_net_ops);
367 if (ret < 0)
368 return ret;
369
370 nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
371 return 0;
372}
373
374static void __exit nf_log_ipv4_exit(void)
375{
376 unregister_pernet_subsys(&nf_log_ipv4_net_ops);
377 nf_log_unregister(&nf_ip_logger);
378}
379
380module_init(nf_log_ipv4_init);
381module_exit(nf_log_ipv4_exit);
382
383MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
384MODULE_DESCRIPTION("Netfilter IPv4 packet logging");
385MODULE_LICENSE("GPL");
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4bff1f297e39..1537130e9f5b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -227,6 +227,11 @@ config IP6_NF_SECURITY
227 227
228 If unsure, say N. 228 If unsure, say N.
229 229
230config NF_LOG_IPV6
231 tristate "IPv6 packet logging"
232 depends on NETFILTER_ADVANCED
233 select NF_LOG_COMMON
234
230config NF_NAT_IPV6 235config NF_NAT_IPV6
231 tristate "IPv6 NAT" 236 tristate "IPv6 NAT"
232 depends on NF_CONNTRACK_IPV6 237 depends on NF_CONNTRACK_IPV6
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 70d3dd66f2cd..c0b263104ed2 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -23,6 +23,9 @@ obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
23nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o 23nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
24obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o 24obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
25 25
26# logging
27obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o
28
26# nf_tables 29# nf_tables
27obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o 30obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
28obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o 31obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c
new file mode 100644
index 000000000000..804060946d2b
--- /dev/null
+++ b/net/ipv6/netfilter/nf_log_ipv6.c
@@ -0,0 +1,417 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/spinlock.h>
11#include <linux/skbuff.h>
12#include <linux/if_arp.h>
13#include <linux/ip.h>
14#include <net/ipv6.h>
15#include <net/icmp.h>
16#include <net/udp.h>
17#include <net/tcp.h>
18#include <net/route.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter_ipv6/ip6_tables.h>
22#include <linux/netfilter/xt_LOG.h>
23#include <net/netfilter/nf_log.h>
24
25static 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/* One level of recursion won't kill us */
36static void dump_ipv6_packet(struct nf_log_buf *m,
37 const struct nf_loginfo *info,
38 const struct sk_buff *skb, unsigned int ip6hoff,
39 int recurse)
40{
41 u_int8_t currenthdr;
42 int fragment;
43 struct ipv6hdr _ip6h;
44 const struct ipv6hdr *ih;
45 unsigned int ptr;
46 unsigned int hdrlen = 0;
47 unsigned int logflags;
48
49 if (info->type == NF_LOG_TYPE_LOG)
50 logflags = info->u.log.logflags;
51 else
52 logflags = NF_LOG_MASK;
53
54 ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
55 if (ih == NULL) {
56 nf_log_buf_add(m, "TRUNCATED");
57 return;
58 }
59
60 /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
61 nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
62
63 /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
64 nf_log_buf_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
65 ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
66 (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
67 ih->hop_limit,
68 (ntohl(*(__be32 *)ih) & 0x000fffff));
69
70 fragment = 0;
71 ptr = ip6hoff + sizeof(struct ipv6hdr);
72 currenthdr = ih->nexthdr;
73 while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
74 struct ipv6_opt_hdr _hdr;
75 const struct ipv6_opt_hdr *hp;
76
77 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
78 if (hp == NULL) {
79 nf_log_buf_add(m, "TRUNCATED");
80 return;
81 }
82
83 /* Max length: 48 "OPT (...) " */
84 if (logflags & XT_LOG_IPOPT)
85 nf_log_buf_add(m, "OPT ( ");
86
87 switch (currenthdr) {
88 case IPPROTO_FRAGMENT: {
89 struct frag_hdr _fhdr;
90 const struct frag_hdr *fh;
91
92 nf_log_buf_add(m, "FRAG:");
93 fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
94 &_fhdr);
95 if (fh == NULL) {
96 nf_log_buf_add(m, "TRUNCATED ");
97 return;
98 }
99
100 /* Max length: 6 "65535 " */
101 nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
102
103 /* Max length: 11 "INCOMPLETE " */
104 if (fh->frag_off & htons(0x0001))
105 nf_log_buf_add(m, "INCOMPLETE ");
106
107 nf_log_buf_add(m, "ID:%08x ",
108 ntohl(fh->identification));
109
110 if (ntohs(fh->frag_off) & 0xFFF8)
111 fragment = 1;
112
113 hdrlen = 8;
114
115 break;
116 }
117 case IPPROTO_DSTOPTS:
118 case IPPROTO_ROUTING:
119 case IPPROTO_HOPOPTS:
120 if (fragment) {
121 if (logflags & XT_LOG_IPOPT)
122 nf_log_buf_add(m, ")");
123 return;
124 }
125 hdrlen = ipv6_optlen(hp);
126 break;
127 /* Max Length */
128 case IPPROTO_AH:
129 if (logflags & XT_LOG_IPOPT) {
130 struct ip_auth_hdr _ahdr;
131 const struct ip_auth_hdr *ah;
132
133 /* Max length: 3 "AH " */
134 nf_log_buf_add(m, "AH ");
135
136 if (fragment) {
137 nf_log_buf_add(m, ")");
138 return;
139 }
140
141 ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
142 &_ahdr);
143 if (ah == NULL) {
144 /*
145 * Max length: 26 "INCOMPLETE [65535
146 * bytes] )"
147 */
148 nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
149 skb->len - ptr);
150 return;
151 }
152
153 /* Length: 15 "SPI=0xF1234567 */
154 nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
155
156 }
157
158 hdrlen = (hp->hdrlen+2)<<2;
159 break;
160 case IPPROTO_ESP:
161 if (logflags & XT_LOG_IPOPT) {
162 struct ip_esp_hdr _esph;
163 const struct ip_esp_hdr *eh;
164
165 /* Max length: 4 "ESP " */
166 nf_log_buf_add(m, "ESP ");
167
168 if (fragment) {
169 nf_log_buf_add(m, ")");
170 return;
171 }
172
173 /*
174 * Max length: 26 "INCOMPLETE [65535 bytes] )"
175 */
176 eh = skb_header_pointer(skb, ptr, sizeof(_esph),
177 &_esph);
178 if (eh == NULL) {
179 nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
180 skb->len - ptr);
181 return;
182 }
183
184 /* Length: 16 "SPI=0xF1234567 )" */
185 nf_log_buf_add(m, "SPI=0x%x )",
186 ntohl(eh->spi));
187 }
188 return;
189 default:
190 /* Max length: 20 "Unknown Ext Hdr 255" */
191 nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr);
192 return;
193 }
194 if (logflags & XT_LOG_IPOPT)
195 nf_log_buf_add(m, ") ");
196
197 currenthdr = hp->nexthdr;
198 ptr += hdrlen;
199 }
200
201 switch (currenthdr) {
202 case IPPROTO_TCP:
203 if (nf_log_dump_tcp_header(m, skb, currenthdr, fragment,
204 ptr, logflags))
205 return;
206 break;
207 case IPPROTO_UDP:
208 case IPPROTO_UDPLITE:
209 if (nf_log_dump_udp_header(m, skb, currenthdr, fragment, ptr))
210 return;
211 break;
212 case IPPROTO_ICMPV6: {
213 struct icmp6hdr _icmp6h;
214 const struct icmp6hdr *ic;
215
216 /* Max length: 13 "PROTO=ICMPv6 " */
217 nf_log_buf_add(m, "PROTO=ICMPv6 ");
218
219 if (fragment)
220 break;
221
222 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
223 ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
224 if (ic == NULL) {
225 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
226 skb->len - ptr);
227 return;
228 }
229
230 /* Max length: 18 "TYPE=255 CODE=255 " */
231 nf_log_buf_add(m, "TYPE=%u CODE=%u ",
232 ic->icmp6_type, ic->icmp6_code);
233
234 switch (ic->icmp6_type) {
235 case ICMPV6_ECHO_REQUEST:
236 case ICMPV6_ECHO_REPLY:
237 /* Max length: 19 "ID=65535 SEQ=65535 " */
238 nf_log_buf_add(m, "ID=%u SEQ=%u ",
239 ntohs(ic->icmp6_identifier),
240 ntohs(ic->icmp6_sequence));
241 break;
242 case ICMPV6_MGM_QUERY:
243 case ICMPV6_MGM_REPORT:
244 case ICMPV6_MGM_REDUCTION:
245 break;
246
247 case ICMPV6_PARAMPROB:
248 /* Max length: 17 "POINTER=ffffffff " */
249 nf_log_buf_add(m, "POINTER=%08x ",
250 ntohl(ic->icmp6_pointer));
251 /* Fall through */
252 case ICMPV6_DEST_UNREACH:
253 case ICMPV6_PKT_TOOBIG:
254 case ICMPV6_TIME_EXCEED:
255 /* Max length: 3+maxlen */
256 if (recurse) {
257 nf_log_buf_add(m, "[");
258 dump_ipv6_packet(m, info, skb,
259 ptr + sizeof(_icmp6h), 0);
260 nf_log_buf_add(m, "] ");
261 }
262
263 /* Max length: 10 "MTU=65535 " */
264 if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) {
265 nf_log_buf_add(m, "MTU=%u ",
266 ntohl(ic->icmp6_mtu));
267 }
268 }
269 break;
270 }
271 /* Max length: 10 "PROTO=255 " */
272 default:
273 nf_log_buf_add(m, "PROTO=%u ", currenthdr);
274 }
275
276 /* Max length: 15 "UID=4294967295 " */
277 if ((logflags & XT_LOG_UID) && recurse)
278 nf_log_dump_sk_uid_gid(m, skb->sk);
279
280 /* Max length: 16 "MARK=0xFFFFFFFF " */
281 if (recurse && skb->mark)
282 nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
283}
284
285static void dump_ipv6_mac_header(struct nf_log_buf *m,
286 const struct nf_loginfo *info,
287 const struct sk_buff *skb)
288{
289 struct net_device *dev = skb->dev;
290 unsigned int logflags = 0;
291
292 if (info->type == NF_LOG_TYPE_LOG)
293 logflags = info->u.log.logflags;
294
295 if (!(logflags & XT_LOG_MACDECODE))
296 goto fallback;
297
298 switch (dev->type) {
299 case ARPHRD_ETHER:
300 nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
301 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
302 ntohs(eth_hdr(skb)->h_proto));
303 return;
304 default:
305 break;
306 }
307
308fallback:
309 nf_log_buf_add(m, "MAC=");
310 if (dev->hard_header_len &&
311 skb->mac_header != skb->network_header) {
312 const unsigned char *p = skb_mac_header(skb);
313 unsigned int len = dev->hard_header_len;
314 unsigned int i;
315
316 if (dev->type == ARPHRD_SIT) {
317 p -= ETH_HLEN;
318
319 if (p < skb->head)
320 p = NULL;
321 }
322
323 if (p != NULL) {
324 nf_log_buf_add(m, "%02x", *p++);
325 for (i = 1; i < len; i++)
326 nf_log_buf_add(m, ":%02x", *p++);
327 }
328 nf_log_buf_add(m, " ");
329
330 if (dev->type == ARPHRD_SIT) {
331 const struct iphdr *iph =
332 (struct iphdr *)skb_mac_header(skb);
333 nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr,
334 &iph->daddr);
335 }
336 } else {
337 nf_log_buf_add(m, " ");
338 }
339}
340
341void nf_log_ip6_packet(struct net *net, u_int8_t pf,
342 unsigned int hooknum, const struct sk_buff *skb,
343 const struct net_device *in,
344 const struct net_device *out,
345 const struct nf_loginfo *loginfo,
346 const char *prefix)
347{
348 struct nf_log_buf *m;
349
350 /* FIXME: Disabled from containers until syslog ns is supported */
351 if (!net_eq(net, &init_net))
352 return;
353
354 m = nf_log_buf_open();
355
356 if (!loginfo)
357 loginfo = &default_loginfo;
358
359 nf_log_dump_packet_common(m, pf, hooknum, skb, in, out,
360 loginfo, prefix);
361
362 if (in != NULL)
363 dump_ipv6_mac_header(m, loginfo, skb);
364
365 dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1);
366
367 nf_log_buf_close(m);
368}
369EXPORT_SYMBOL_GPL(nf_log_ip6_packet);
370
371static struct nf_logger nf_ip6_logger __read_mostly = {
372 .name = "nf_log_ipv6",
373 .type = NF_LOG_TYPE_LOG,
374 .logfn = nf_log_ip6_packet,
375 .me = THIS_MODULE,
376};
377
378static int __net_init nf_log_ipv6_net_init(struct net *net)
379{
380 nf_log_set(net, NFPROTO_IPV6, &nf_ip6_logger);
381 return 0;
382}
383
384static void __net_exit nf_log_ipv6_net_exit(struct net *net)
385{
386 nf_log_unset(net, &nf_ip6_logger);
387}
388
389static struct pernet_operations nf_log_ipv6_net_ops = {
390 .init = nf_log_ipv6_net_init,
391 .exit = nf_log_ipv6_net_exit,
392};
393
394static int __init nf_log_ipv6_init(void)
395{
396 int ret;
397
398 ret = register_pernet_subsys(&nf_log_ipv6_net_ops);
399 if (ret < 0)
400 return ret;
401
402 nf_log_register(NFPROTO_IPV6, &nf_ip6_logger);
403 return 0;
404}
405
406static void __exit nf_log_ipv6_exit(void)
407{
408 unregister_pernet_subsys(&nf_log_ipv6_net_ops);
409 nf_log_unregister(&nf_ip6_logger);
410}
411
412module_init(nf_log_ipv6_init);
413module_exit(nf_log_ipv6_exit);
414
415MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
416MODULE_DESCRIPTION("Netfilter IPv4 packet logging");
417MODULE_LICENSE("GPL");
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index e9410d17619d..f17b273c9082 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -359,6 +359,9 @@ config NETFILTER_NETLINK_QUEUE_CT
359 If this option is enabled, NFQUEUE can include Connection Tracking 359 If this option is enabled, NFQUEUE can include Connection Tracking
360 information together with the packet is the enqueued via NFNETLINK. 360 information together with the packet is the enqueued via NFNETLINK.
361 361
362config NF_LOG_COMMON
363 tristate
364
362config NF_NAT 365config NF_NAT
363 tristate 366 tristate
364 367
@@ -744,6 +747,9 @@ config NETFILTER_XT_TARGET_LED
744 747
745config NETFILTER_XT_TARGET_LOG 748config NETFILTER_XT_TARGET_LOG
746 tristate "LOG target support" 749 tristate "LOG target support"
750 select NF_LOG
751 select NF_LOG_IPV4
752 select NF_LOG_IPV6
747 default m if NETFILTER_ADVANCED=n 753 default m if NETFILTER_ADVANCED=n
748 help 754 help
749 This option adds a `LOG' target, which allows you to create rules in 755 This option adds a `LOG' target, which allows you to create rules in
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index bffdad774da7..8308624a406a 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -47,6 +47,9 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
47nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ 47nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \
48 nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o 48 nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o
49 49
50# generic transport layer logging
51obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o
52
50obj-$(CONFIG_NF_NAT) += nf_nat.o 53obj-$(CONFIG_NF_NAT) += nf_nat.o
51 54
52# NAT protocols (nf_nat) 55# NAT protocols (nf_nat)
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c
new file mode 100644
index 000000000000..eeb8ef4ff1a3
--- /dev/null
+++ b/net/netfilter/nf_log_common.c
@@ -0,0 +1,187 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/spinlock.h>
11#include <linux/skbuff.h>
12#include <linux/if_arp.h>
13#include <linux/ip.h>
14#include <net/icmp.h>
15#include <net/udp.h>
16#include <net/tcp.h>
17#include <net/route.h>
18
19#include <linux/netfilter.h>
20#include <linux/netfilter/xt_LOG.h>
21#include <net/netfilter/nf_log.h>
22
23int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
24 u8 proto, int fragment, unsigned int offset)
25{
26 struct udphdr _udph;
27 const struct udphdr *uh;
28
29 if (proto == IPPROTO_UDP)
30 /* Max length: 10 "PROTO=UDP " */
31 nf_log_buf_add(m, "PROTO=UDP ");
32 else /* Max length: 14 "PROTO=UDPLITE " */
33 nf_log_buf_add(m, "PROTO=UDPLITE ");
34
35 if (fragment)
36 goto out;
37
38 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
39 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
40 if (uh == NULL) {
41 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
42
43 return 1;
44 }
45
46 /* Max length: 20 "SPT=65535 DPT=65535 " */
47 nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ",
48 ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len));
49
50out:
51 return 0;
52}
53EXPORT_SYMBOL_GPL(nf_log_dump_udp_header);
54
55int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
56 u8 proto, int fragment, unsigned int offset,
57 unsigned int logflags)
58{
59 struct tcphdr _tcph;
60 const struct tcphdr *th;
61
62 /* Max length: 10 "PROTO=TCP " */
63 nf_log_buf_add(m, "PROTO=TCP ");
64
65 if (fragment)
66 return 0;
67
68 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
69 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
70 if (th == NULL) {
71 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
72 return 1;
73 }
74
75 /* Max length: 20 "SPT=65535 DPT=65535 " */
76 nf_log_buf_add(m, "SPT=%u DPT=%u ",
77 ntohs(th->source), ntohs(th->dest));
78 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
79 if (logflags & XT_LOG_TCPSEQ) {
80 nf_log_buf_add(m, "SEQ=%u ACK=%u ",
81 ntohl(th->seq), ntohl(th->ack_seq));
82 }
83
84 /* Max length: 13 "WINDOW=65535 " */
85 nf_log_buf_add(m, "WINDOW=%u ", ntohs(th->window));
86 /* Max length: 9 "RES=0x3C " */
87 nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
88 TCP_RESERVED_BITS) >> 22));
89 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
90 if (th->cwr)
91 nf_log_buf_add(m, "CWR ");
92 if (th->ece)
93 nf_log_buf_add(m, "ECE ");
94 if (th->urg)
95 nf_log_buf_add(m, "URG ");
96 if (th->ack)
97 nf_log_buf_add(m, "ACK ");
98 if (th->psh)
99 nf_log_buf_add(m, "PSH ");
100 if (th->rst)
101 nf_log_buf_add(m, "RST ");
102 if (th->syn)
103 nf_log_buf_add(m, "SYN ");
104 if (th->fin)
105 nf_log_buf_add(m, "FIN ");
106 /* Max length: 11 "URGP=65535 " */
107 nf_log_buf_add(m, "URGP=%u ", ntohs(th->urg_ptr));
108
109 if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) {
110 u_int8_t _opt[60 - sizeof(struct tcphdr)];
111 const u_int8_t *op;
112 unsigned int i;
113 unsigned int optsize = th->doff*4 - sizeof(struct tcphdr);
114
115 op = skb_header_pointer(skb, offset + sizeof(struct tcphdr),
116 optsize, _opt);
117 if (op == NULL) {
118 nf_log_buf_add(m, "OPT (TRUNCATED)");
119 return 1;
120 }
121
122 /* Max length: 127 "OPT (" 15*4*2chars ") " */
123 nf_log_buf_add(m, "OPT (");
124 for (i = 0; i < optsize; i++)
125 nf_log_buf_add(m, "%02X", op[i]);
126
127 nf_log_buf_add(m, ") ");
128 }
129
130 return 0;
131}
132EXPORT_SYMBOL_GPL(nf_log_dump_tcp_header);
133
134void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk)
135{
136 if (!sk || sk->sk_state == TCP_TIME_WAIT)
137 return;
138
139 read_lock_bh(&sk->sk_callback_lock);
140 if (sk->sk_socket && sk->sk_socket->file) {
141 const struct cred *cred = sk->sk_socket->file->f_cred;
142 nf_log_buf_add(m, "UID=%u GID=%u ",
143 from_kuid_munged(&init_user_ns, cred->fsuid),
144 from_kgid_munged(&init_user_ns, cred->fsgid));
145 }
146 read_unlock_bh(&sk->sk_callback_lock);
147}
148EXPORT_SYMBOL_GPL(nf_log_dump_sk_uid_gid);
149
150void
151nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
152 unsigned int hooknum, const struct sk_buff *skb,
153 const struct net_device *in,
154 const struct net_device *out,
155 const struct nf_loginfo *loginfo, const char *prefix)
156{
157 nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
158 '0' + loginfo->u.log.level, prefix,
159 in ? in->name : "",
160 out ? out->name : "");
161#ifdef CONFIG_BRIDGE_NETFILTER
162 if (skb->nf_bridge) {
163 const struct net_device *physindev;
164 const struct net_device *physoutdev;
165
166 physindev = skb->nf_bridge->physindev;
167 if (physindev && in != physindev)
168 nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
169 physoutdev = skb->nf_bridge->physoutdev;
170 if (physoutdev && out != physoutdev)
171 nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
172 }
173#endif
174}
175EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
176
177static int __init nf_log_common_init(void)
178{
179 return 0;
180}
181
182static void __exit nf_log_common_exit(void) {}
183
184module_init(nf_log_common_init);
185module_exit(nf_log_common_exit);
186
187MODULE_LICENSE("GPL");
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index 649b85fc5463..5a6bd60e20d6 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -28,813 +28,6 @@
28#include <linux/netfilter_ipv6/ip6_tables.h> 28#include <linux/netfilter_ipv6/ip6_tables.h>
29#include <net/netfilter/nf_log.h> 29#include <net/netfilter/nf_log.h>
30 30
31static struct nf_loginfo default_loginfo = {
32 .type = NF_LOG_TYPE_LOG,
33 .u = {
34 .log = {
35 .level = 5,
36 .logflags = NF_LOG_MASK,
37 },
38 },
39};
40
41static int dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
42 u8 proto, int fragment, unsigned int offset)
43{
44 struct udphdr _udph;
45 const struct udphdr *uh;
46
47 if (proto == IPPROTO_UDP)
48 /* Max length: 10 "PROTO=UDP " */
49 nf_log_buf_add(m, "PROTO=UDP ");
50 else /* Max length: 14 "PROTO=UDPLITE " */
51 nf_log_buf_add(m, "PROTO=UDPLITE ");
52
53 if (fragment)
54 goto out;
55
56 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
57 uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
58 if (uh == NULL) {
59 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
60
61 return 1;
62 }
63
64 /* Max length: 20 "SPT=65535 DPT=65535 " */
65 nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ",
66 ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len));
67
68out:
69 return 0;
70}
71
72static int dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
73 u8 proto, int fragment, unsigned int offset,
74 unsigned int logflags)
75{
76 struct tcphdr _tcph;
77 const struct tcphdr *th;
78
79 /* Max length: 10 "PROTO=TCP " */
80 nf_log_buf_add(m, "PROTO=TCP ");
81
82 if (fragment)
83 return 0;
84
85 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
86 th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
87 if (th == NULL) {
88 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
89 return 1;
90 }
91
92 /* Max length: 20 "SPT=65535 DPT=65535 " */
93 nf_log_buf_add(m, "SPT=%u DPT=%u ",
94 ntohs(th->source), ntohs(th->dest));
95 /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
96 if (logflags & XT_LOG_TCPSEQ) {
97 nf_log_buf_add(m, "SEQ=%u ACK=%u ",
98 ntohl(th->seq), ntohl(th->ack_seq));
99 }
100
101 /* Max length: 13 "WINDOW=65535 " */
102 nf_log_buf_add(m, "WINDOW=%u ", ntohs(th->window));
103 /* Max length: 9 "RES=0x3C " */
104 nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
105 TCP_RESERVED_BITS) >> 22));
106 /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
107 if (th->cwr)
108 nf_log_buf_add(m, "CWR ");
109 if (th->ece)
110 nf_log_buf_add(m, "ECE ");
111 if (th->urg)
112 nf_log_buf_add(m, "URG ");
113 if (th->ack)
114 nf_log_buf_add(m, "ACK ");
115 if (th->psh)
116 nf_log_buf_add(m, "PSH ");
117 if (th->rst)
118 nf_log_buf_add(m, "RST ");
119 if (th->syn)
120 nf_log_buf_add(m, "SYN ");
121 if (th->fin)
122 nf_log_buf_add(m, "FIN ");
123 /* Max length: 11 "URGP=65535 " */
124 nf_log_buf_add(m, "URGP=%u ", ntohs(th->urg_ptr));
125
126 if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) {
127 u_int8_t _opt[60 - sizeof(struct tcphdr)];
128 const u_int8_t *op;
129 unsigned int i;
130 unsigned int optsize = th->doff*4 - sizeof(struct tcphdr);
131
132 op = skb_header_pointer(skb, offset + sizeof(struct tcphdr),
133 optsize, _opt);
134 if (op == NULL) {
135 nf_log_buf_add(m, "OPT (TRUNCATED)");
136 return 1;
137 }
138
139 /* Max length: 127 "OPT (" 15*4*2chars ") " */
140 nf_log_buf_add(m, "OPT (");
141 for (i = 0; i < optsize; i++)
142 nf_log_buf_add(m, "%02X", op[i]);
143
144 nf_log_buf_add(m, ") ");
145 }
146
147 return 0;
148}
149
150static void dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk)
151{
152 if (!sk || sk->sk_state == TCP_TIME_WAIT)
153 return;
154
155 read_lock_bh(&sk->sk_callback_lock);
156 if (sk->sk_socket && sk->sk_socket->file) {
157 const struct cred *cred = sk->sk_socket->file->f_cred;
158 nf_log_buf_add(m, "UID=%u GID=%u ",
159 from_kuid_munged(&init_user_ns, cred->fsuid),
160 from_kgid_munged(&init_user_ns, cred->fsgid));
161 }
162 read_unlock_bh(&sk->sk_callback_lock);
163}
164
165/* One level of recursion won't kill us */
166static void dump_ipv4_packet(struct nf_log_buf *m,
167 const struct nf_loginfo *info,
168 const struct sk_buff *skb, unsigned int iphoff)
169{
170 struct iphdr _iph;
171 const struct iphdr *ih;
172 unsigned int logflags;
173
174 if (info->type == NF_LOG_TYPE_LOG)
175 logflags = info->u.log.logflags;
176 else
177 logflags = NF_LOG_MASK;
178
179 ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
180 if (ih == NULL) {
181 nf_log_buf_add(m, "TRUNCATED");
182 return;
183 }
184
185 /* Important fields:
186 * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
187 /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
188 nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ",
189 &ih->saddr, &ih->daddr);
190
191 /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
192 nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
193 ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
194 ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
195
196 /* Max length: 6 "CE DF MF " */
197 if (ntohs(ih->frag_off) & IP_CE)
198 nf_log_buf_add(m, "CE ");
199 if (ntohs(ih->frag_off) & IP_DF)
200 nf_log_buf_add(m, "DF ");
201 if (ntohs(ih->frag_off) & IP_MF)
202 nf_log_buf_add(m, "MF ");
203
204 /* Max length: 11 "FRAG:65535 " */
205 if (ntohs(ih->frag_off) & IP_OFFSET)
206 nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
207
208 if ((logflags & XT_LOG_IPOPT) &&
209 ih->ihl * 4 > sizeof(struct iphdr)) {
210 const unsigned char *op;
211 unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
212 unsigned int i, optsize;
213
214 optsize = ih->ihl * 4 - sizeof(struct iphdr);
215 op = skb_header_pointer(skb, iphoff+sizeof(_iph),
216 optsize, _opt);
217 if (op == NULL) {
218 nf_log_buf_add(m, "TRUNCATED");
219 return;
220 }
221
222 /* Max length: 127 "OPT (" 15*4*2chars ") " */
223 nf_log_buf_add(m, "OPT (");
224 for (i = 0; i < optsize; i++)
225 nf_log_buf_add(m, "%02X", op[i]);
226 nf_log_buf_add(m, ") ");
227 }
228
229 switch (ih->protocol) {
230 case IPPROTO_TCP:
231 if (dump_tcp_header(m, skb, ih->protocol,
232 ntohs(ih->frag_off) & IP_OFFSET,
233 iphoff+ih->ihl*4, logflags))
234 return;
235 break;
236 case IPPROTO_UDP:
237 case IPPROTO_UDPLITE:
238 if (dump_udp_header(m, skb, ih->protocol,
239 ntohs(ih->frag_off) & IP_OFFSET,
240 iphoff+ih->ihl*4))
241 return;
242 break;
243 case IPPROTO_ICMP: {
244 struct icmphdr _icmph;
245 const struct icmphdr *ich;
246 static const size_t required_len[NR_ICMP_TYPES+1]
247 = { [ICMP_ECHOREPLY] = 4,
248 [ICMP_DEST_UNREACH]
249 = 8 + sizeof(struct iphdr),
250 [ICMP_SOURCE_QUENCH]
251 = 8 + sizeof(struct iphdr),
252 [ICMP_REDIRECT]
253 = 8 + sizeof(struct iphdr),
254 [ICMP_ECHO] = 4,
255 [ICMP_TIME_EXCEEDED]
256 = 8 + sizeof(struct iphdr),
257 [ICMP_PARAMETERPROB]
258 = 8 + sizeof(struct iphdr),
259 [ICMP_TIMESTAMP] = 20,
260 [ICMP_TIMESTAMPREPLY] = 20,
261 [ICMP_ADDRESS] = 12,
262 [ICMP_ADDRESSREPLY] = 12 };
263
264 /* Max length: 11 "PROTO=ICMP " */
265 nf_log_buf_add(m, "PROTO=ICMP ");
266
267 if (ntohs(ih->frag_off) & IP_OFFSET)
268 break;
269
270 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
271 ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
272 sizeof(_icmph), &_icmph);
273 if (ich == NULL) {
274 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
275 skb->len - iphoff - ih->ihl*4);
276 break;
277 }
278
279 /* Max length: 18 "TYPE=255 CODE=255 " */
280 nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
281
282 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
283 if (ich->type <= NR_ICMP_TYPES &&
284 required_len[ich->type] &&
285 skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
286 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
287 skb->len - iphoff - ih->ihl*4);
288 break;
289 }
290
291 switch (ich->type) {
292 case ICMP_ECHOREPLY:
293 case ICMP_ECHO:
294 /* Max length: 19 "ID=65535 SEQ=65535 " */
295 nf_log_buf_add(m, "ID=%u SEQ=%u ",
296 ntohs(ich->un.echo.id),
297 ntohs(ich->un.echo.sequence));
298 break;
299
300 case ICMP_PARAMETERPROB:
301 /* Max length: 14 "PARAMETER=255 " */
302 nf_log_buf_add(m, "PARAMETER=%u ",
303 ntohl(ich->un.gateway) >> 24);
304 break;
305 case ICMP_REDIRECT:
306 /* Max length: 24 "GATEWAY=255.255.255.255 " */
307 nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
308 /* Fall through */
309 case ICMP_DEST_UNREACH:
310 case ICMP_SOURCE_QUENCH:
311 case ICMP_TIME_EXCEEDED:
312 /* Max length: 3+maxlen */
313 if (!iphoff) { /* Only recurse once. */
314 nf_log_buf_add(m, "[");
315 dump_ipv4_packet(m, info, skb,
316 iphoff + ih->ihl*4+sizeof(_icmph));
317 nf_log_buf_add(m, "] ");
318 }
319
320 /* Max length: 10 "MTU=65535 " */
321 if (ich->type == ICMP_DEST_UNREACH &&
322 ich->code == ICMP_FRAG_NEEDED) {
323 nf_log_buf_add(m, "MTU=%u ",
324 ntohs(ich->un.frag.mtu));
325 }
326 }
327 break;
328 }
329 /* Max Length */
330 case IPPROTO_AH: {
331 struct ip_auth_hdr _ahdr;
332 const struct ip_auth_hdr *ah;
333
334 if (ntohs(ih->frag_off) & IP_OFFSET)
335 break;
336
337 /* Max length: 9 "PROTO=AH " */
338 nf_log_buf_add(m, "PROTO=AH ");
339
340 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
341 ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
342 sizeof(_ahdr), &_ahdr);
343 if (ah == NULL) {
344 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
345 skb->len - iphoff - ih->ihl*4);
346 break;
347 }
348
349 /* Length: 15 "SPI=0xF1234567 " */
350 nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
351 break;
352 }
353 case IPPROTO_ESP: {
354 struct ip_esp_hdr _esph;
355 const struct ip_esp_hdr *eh;
356
357 /* Max length: 10 "PROTO=ESP " */
358 nf_log_buf_add(m, "PROTO=ESP ");
359
360 if (ntohs(ih->frag_off) & IP_OFFSET)
361 break;
362
363 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
364 eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
365 sizeof(_esph), &_esph);
366 if (eh == NULL) {
367 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
368 skb->len - iphoff - ih->ihl*4);
369 break;
370 }
371
372 /* Length: 15 "SPI=0xF1234567 " */
373 nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi));
374 break;
375 }
376 /* Max length: 10 "PROTO 255 " */
377 default:
378 nf_log_buf_add(m, "PROTO=%u ", ih->protocol);
379 }
380
381 /* Max length: 15 "UID=4294967295 " */
382 if ((logflags & XT_LOG_UID) && !iphoff)
383 dump_sk_uid_gid(m, skb->sk);
384
385 /* Max length: 16 "MARK=0xFFFFFFFF " */
386 if (!iphoff && skb->mark)
387 nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
388
389 /* Proto Max log string length */
390 /* IP: 40+46+6+11+127 = 230 */
391 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
392 /* UDP: 10+max(25,20) = 35 */
393 /* UDPLITE: 14+max(25,20) = 39 */
394 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
395 /* ESP: 10+max(25)+15 = 50 */
396 /* AH: 9+max(25)+15 = 49 */
397 /* unknown: 10 */
398
399 /* (ICMP allows recursion one level deep) */
400 /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */
401 /* maxlen = 230+ 91 + 230 + 252 = 803 */
402}
403
404static void dump_ipv4_mac_header(struct nf_log_buf *m,
405 const struct nf_loginfo *info,
406 const struct sk_buff *skb)
407{
408 struct net_device *dev = skb->dev;
409 unsigned int logflags = 0;
410
411 if (info->type == NF_LOG_TYPE_LOG)
412 logflags = info->u.log.logflags;
413
414 if (!(logflags & XT_LOG_MACDECODE))
415 goto fallback;
416
417 switch (dev->type) {
418 case ARPHRD_ETHER:
419 nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
420 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
421 ntohs(eth_hdr(skb)->h_proto));
422 return;
423 default:
424 break;
425 }
426
427fallback:
428 nf_log_buf_add(m, "MAC=");
429 if (dev->hard_header_len &&
430 skb->mac_header != skb->network_header) {
431 const unsigned char *p = skb_mac_header(skb);
432 unsigned int i;
433
434 nf_log_buf_add(m, "%02x", *p++);
435 for (i = 1; i < dev->hard_header_len; i++, p++)
436 nf_log_buf_add(m, ":%02x", *p);
437 }
438 nf_log_buf_add(m, " ");
439}
440
441static void
442log_packet_common(struct nf_log_buf *m,
443 u_int8_t pf,
444 unsigned int hooknum,
445 const struct sk_buff *skb,
446 const struct net_device *in,
447 const struct net_device *out,
448 const struct nf_loginfo *loginfo,
449 const char *prefix)
450{
451 nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
452 '0' + loginfo->u.log.level, prefix,
453 in ? in->name : "",
454 out ? out->name : "");
455#ifdef CONFIG_BRIDGE_NETFILTER
456 if (skb->nf_bridge) {
457 const struct net_device *physindev;
458 const struct net_device *physoutdev;
459
460 physindev = skb->nf_bridge->physindev;
461 if (physindev && in != physindev)
462 nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
463 physoutdev = skb->nf_bridge->physoutdev;
464 if (physoutdev && out != physoutdev)
465 nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
466 }
467#endif
468}
469
470
471static void
472ipt_log_packet(struct net *net,
473 u_int8_t pf,
474 unsigned int hooknum,
475 const struct sk_buff *skb,
476 const struct net_device *in,
477 const struct net_device *out,
478 const struct nf_loginfo *loginfo,
479 const char *prefix)
480{
481 struct nf_log_buf *m;
482
483 /* FIXME: Disabled from containers until syslog ns is supported */
484 if (!net_eq(net, &init_net))
485 return;
486
487 m = nf_log_buf_open();
488
489 if (!loginfo)
490 loginfo = &default_loginfo;
491
492 log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix);
493
494 if (in != NULL)
495 dump_ipv4_mac_header(m, loginfo, skb);
496
497 dump_ipv4_packet(m, loginfo, skb, 0);
498
499 nf_log_buf_close(m);
500}
501
502#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
503/* One level of recursion won't kill us */
504static void dump_ipv6_packet(struct nf_log_buf *m,
505 const struct nf_loginfo *info,
506 const struct sk_buff *skb, unsigned int ip6hoff,
507 int recurse)
508{
509 u_int8_t currenthdr;
510 int fragment;
511 struct ipv6hdr _ip6h;
512 const struct ipv6hdr *ih;
513 unsigned int ptr;
514 unsigned int hdrlen = 0;
515 unsigned int logflags;
516
517 if (info->type == NF_LOG_TYPE_LOG)
518 logflags = info->u.log.logflags;
519 else
520 logflags = NF_LOG_MASK;
521
522 ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
523 if (ih == NULL) {
524 nf_log_buf_add(m, "TRUNCATED");
525 return;
526 }
527
528 /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
529 nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
530
531 /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
532 nf_log_buf_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
533 ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
534 (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
535 ih->hop_limit, (ntohl(*(__be32 *)ih) & 0x000fffff));
536
537 fragment = 0;
538 ptr = ip6hoff + sizeof(struct ipv6hdr);
539 currenthdr = ih->nexthdr;
540 while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
541 struct ipv6_opt_hdr _hdr;
542 const struct ipv6_opt_hdr *hp;
543
544 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
545 if (hp == NULL) {
546 nf_log_buf_add(m, "TRUNCATED");
547 return;
548 }
549
550 /* Max length: 48 "OPT (...) " */
551 if (logflags & XT_LOG_IPOPT)
552 nf_log_buf_add(m, "OPT ( ");
553
554 switch (currenthdr) {
555 case IPPROTO_FRAGMENT: {
556 struct frag_hdr _fhdr;
557 const struct frag_hdr *fh;
558
559 nf_log_buf_add(m, "FRAG:");
560 fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
561 &_fhdr);
562 if (fh == NULL) {
563 nf_log_buf_add(m, "TRUNCATED ");
564 return;
565 }
566
567 /* Max length: 6 "65535 " */
568 nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
569
570 /* Max length: 11 "INCOMPLETE " */
571 if (fh->frag_off & htons(0x0001))
572 nf_log_buf_add(m, "INCOMPLETE ");
573
574 nf_log_buf_add(m, "ID:%08x ", ntohl(fh->identification));
575
576 if (ntohs(fh->frag_off) & 0xFFF8)
577 fragment = 1;
578
579 hdrlen = 8;
580
581 break;
582 }
583 case IPPROTO_DSTOPTS:
584 case IPPROTO_ROUTING:
585 case IPPROTO_HOPOPTS:
586 if (fragment) {
587 if (logflags & XT_LOG_IPOPT)
588 nf_log_buf_add(m, ")");
589 return;
590 }
591 hdrlen = ipv6_optlen(hp);
592 break;
593 /* Max Length */
594 case IPPROTO_AH:
595 if (logflags & XT_LOG_IPOPT) {
596 struct ip_auth_hdr _ahdr;
597 const struct ip_auth_hdr *ah;
598
599 /* Max length: 3 "AH " */
600 nf_log_buf_add(m, "AH ");
601
602 if (fragment) {
603 nf_log_buf_add(m, ")");
604 return;
605 }
606
607 ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
608 &_ahdr);
609 if (ah == NULL) {
610 /*
611 * Max length: 26 "INCOMPLETE [65535
612 * bytes] )"
613 */
614 nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
615 skb->len - ptr);
616 return;
617 }
618
619 /* Length: 15 "SPI=0xF1234567 */
620 nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
621
622 }
623
624 hdrlen = (hp->hdrlen+2)<<2;
625 break;
626 case IPPROTO_ESP:
627 if (logflags & XT_LOG_IPOPT) {
628 struct ip_esp_hdr _esph;
629 const struct ip_esp_hdr *eh;
630
631 /* Max length: 4 "ESP " */
632 nf_log_buf_add(m, "ESP ");
633
634 if (fragment) {
635 nf_log_buf_add(m, ")");
636 return;
637 }
638
639 /*
640 * Max length: 26 "INCOMPLETE [65535 bytes] )"
641 */
642 eh = skb_header_pointer(skb, ptr, sizeof(_esph),
643 &_esph);
644 if (eh == NULL) {
645 nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
646 skb->len - ptr);
647 return;
648 }
649
650 /* Length: 16 "SPI=0xF1234567 )" */
651 nf_log_buf_add(m, "SPI=0x%x )", ntohl(eh->spi));
652
653 }
654 return;
655 default:
656 /* Max length: 20 "Unknown Ext Hdr 255" */
657 nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr);
658 return;
659 }
660 if (logflags & XT_LOG_IPOPT)
661 nf_log_buf_add(m, ") ");
662
663 currenthdr = hp->nexthdr;
664 ptr += hdrlen;
665 }
666
667 switch (currenthdr) {
668 case IPPROTO_TCP:
669 if (dump_tcp_header(m, skb, currenthdr, fragment, ptr,
670 logflags))
671 return;
672 break;
673 case IPPROTO_UDP:
674 case IPPROTO_UDPLITE:
675 if (dump_udp_header(m, skb, currenthdr, fragment, ptr))
676 return;
677 break;
678 case IPPROTO_ICMPV6: {
679 struct icmp6hdr _icmp6h;
680 const struct icmp6hdr *ic;
681
682 /* Max length: 13 "PROTO=ICMPv6 " */
683 nf_log_buf_add(m, "PROTO=ICMPv6 ");
684
685 if (fragment)
686 break;
687
688 /* Max length: 25 "INCOMPLETE [65535 bytes] " */
689 ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
690 if (ic == NULL) {
691 nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
692 skb->len - ptr);
693 return;
694 }
695
696 /* Max length: 18 "TYPE=255 CODE=255 " */
697 nf_log_buf_add(m, "TYPE=%u CODE=%u ",
698 ic->icmp6_type, ic->icmp6_code);
699
700 switch (ic->icmp6_type) {
701 case ICMPV6_ECHO_REQUEST:
702 case ICMPV6_ECHO_REPLY:
703 /* Max length: 19 "ID=65535 SEQ=65535 " */
704 nf_log_buf_add(m, "ID=%u SEQ=%u ",
705 ntohs(ic->icmp6_identifier),
706 ntohs(ic->icmp6_sequence));
707 break;
708 case ICMPV6_MGM_QUERY:
709 case ICMPV6_MGM_REPORT:
710 case ICMPV6_MGM_REDUCTION:
711 break;
712
713 case ICMPV6_PARAMPROB:
714 /* Max length: 17 "POINTER=ffffffff " */
715 nf_log_buf_add(m, "POINTER=%08x ",
716 ntohl(ic->icmp6_pointer));
717 /* Fall through */
718 case ICMPV6_DEST_UNREACH:
719 case ICMPV6_PKT_TOOBIG:
720 case ICMPV6_TIME_EXCEED:
721 /* Max length: 3+maxlen */
722 if (recurse) {
723 nf_log_buf_add(m, "[");
724 dump_ipv6_packet(m, info, skb,
725 ptr + sizeof(_icmp6h), 0);
726 nf_log_buf_add(m, "] ");
727 }
728
729 /* Max length: 10 "MTU=65535 " */
730 if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
731 nf_log_buf_add(m, "MTU=%u ",
732 ntohl(ic->icmp6_mtu));
733 }
734 break;
735 }
736 /* Max length: 10 "PROTO=255 " */
737 default:
738 nf_log_buf_add(m, "PROTO=%u ", currenthdr);
739 }
740
741 /* Max length: 15 "UID=4294967295 " */
742 if ((logflags & XT_LOG_UID) && recurse)
743 dump_sk_uid_gid(m, skb->sk);
744
745 /* Max length: 16 "MARK=0xFFFFFFFF " */
746 if (recurse && skb->mark)
747 nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
748}
749
750static void dump_ipv6_mac_header(struct nf_log_buf *m,
751 const struct nf_loginfo *info,
752 const struct sk_buff *skb)
753{
754 struct net_device *dev = skb->dev;
755 unsigned int logflags = 0;
756
757 if (info->type == NF_LOG_TYPE_LOG)
758 logflags = info->u.log.logflags;
759
760 if (!(logflags & XT_LOG_MACDECODE))
761 goto fallback;
762
763 switch (dev->type) {
764 case ARPHRD_ETHER:
765 nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ",
766 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
767 ntohs(eth_hdr(skb)->h_proto));
768 return;
769 default:
770 break;
771 }
772
773fallback:
774 nf_log_buf_add(m, "MAC=");
775 if (dev->hard_header_len &&
776 skb->mac_header != skb->network_header) {
777 const unsigned char *p = skb_mac_header(skb);
778 unsigned int len = dev->hard_header_len;
779 unsigned int i;
780
781 if (dev->type == ARPHRD_SIT) {
782 p -= ETH_HLEN;
783
784 if (p < skb->head)
785 p = NULL;
786 }
787
788 if (p != NULL) {
789 nf_log_buf_add(m, "%02x", *p++);
790 for (i = 1; i < len; i++)
791 nf_log_buf_add(m, ":%02x", *p++);
792 }
793 nf_log_buf_add(m, " ");
794
795 if (dev->type == ARPHRD_SIT) {
796 const struct iphdr *iph =
797 (struct iphdr *)skb_mac_header(skb);
798 nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ",
799 &iph->saddr, &iph->daddr);
800 }
801 } else {
802 nf_log_buf_add(m, " ");
803 }
804}
805
806static void
807ip6t_log_packet(struct net *net,
808 u_int8_t pf,
809 unsigned int hooknum,
810 const struct sk_buff *skb,
811 const struct net_device *in,
812 const struct net_device *out,
813 const struct nf_loginfo *loginfo,
814 const char *prefix)
815{
816 struct nf_log_buf *m;
817
818 /* FIXME: Disabled from containers until syslog ns is supported */
819 if (!net_eq(net, &init_net))
820 return;
821
822 m = nf_log_buf_open();
823
824 if (!loginfo)
825 loginfo = &default_loginfo;
826
827 log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix);
828
829 if (in != NULL)
830 dump_ipv6_mac_header(m, loginfo, skb);
831
832 dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1);
833
834 nf_log_buf_close(m);
835}
836#endif
837
838static unsigned int 31static unsigned int
839log_tg(struct sk_buff *skb, const struct xt_action_param *par) 32log_tg(struct sk_buff *skb, const struct xt_action_param *par)
840{ 33{
@@ -847,12 +40,12 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par)
847 li.u.log.logflags = loginfo->logflags; 40 li.u.log.logflags = loginfo->logflags;
848 41
849 if (par->family == NFPROTO_IPV4) 42 if (par->family == NFPROTO_IPV4)
850 ipt_log_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in, 43 nf_log_ip_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in,
851 par->out, &li, loginfo->prefix); 44 par->out, &li, loginfo->prefix);
852#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 45#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
853 else if (par->family == NFPROTO_IPV6) 46 else if (par->family == NFPROTO_IPV6)
854 ip6t_log_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in, 47 nf_log_ip6_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in,
855 par->out, &li, loginfo->prefix); 48 par->out, &li, loginfo->prefix);
856#endif 49#endif
857 else 50 else
858 WARN_ON_ONCE(1); 51 WARN_ON_ONCE(1);
@@ -901,75 +94,13 @@ static struct xt_target log_tg_regs[] __read_mostly = {
901#endif 94#endif
902}; 95};
903 96
904static struct nf_logger ipt_log_logger __read_mostly = {
905 .name = "ipt_LOG",
906 .type = NF_LOG_TYPE_LOG,
907 .logfn = &ipt_log_packet,
908 .me = THIS_MODULE,
909};
910
911#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
912static struct nf_logger ip6t_log_logger __read_mostly = {
913 .name = "ip6t_LOG",
914 .type = NF_LOG_TYPE_LOG,
915 .logfn = &ip6t_log_packet,
916 .me = THIS_MODULE,
917};
918#endif
919
920static int __net_init log_net_init(struct net *net)
921{
922 nf_log_set(net, NFPROTO_IPV4, &ipt_log_logger);
923#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
924 nf_log_set(net, NFPROTO_IPV6, &ip6t_log_logger);
925#endif
926 return 0;
927}
928
929static void __net_exit log_net_exit(struct net *net)
930{
931 nf_log_unset(net, &ipt_log_logger);
932#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
933 nf_log_unset(net, &ip6t_log_logger);
934#endif
935}
936
937static struct pernet_operations log_net_ops = {
938 .init = log_net_init,
939 .exit = log_net_exit,
940};
941
942static int __init log_tg_init(void) 97static int __init log_tg_init(void)
943{ 98{
944 int ret; 99 return xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
945
946 ret = register_pernet_subsys(&log_net_ops);
947 if (ret < 0)
948 goto err_pernet;
949
950 ret = xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
951 if (ret < 0)
952 goto err_target;
953
954 nf_log_register(NFPROTO_IPV4, &ipt_log_logger);
955#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
956 nf_log_register(NFPROTO_IPV6, &ip6t_log_logger);
957#endif
958 return 0;
959
960err_target:
961 unregister_pernet_subsys(&log_net_ops);
962err_pernet:
963 return ret;
964} 100}
965 101
966static void __exit log_tg_exit(void) 102static void __exit log_tg_exit(void)
967{ 103{
968 unregister_pernet_subsys(&log_net_ops);
969 nf_log_unregister(&ipt_log_logger);
970#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
971 nf_log_unregister(&ip6t_log_logger);
972#endif
973 xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); 104 xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs));
974} 105}
975 106