diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-06-19 14:47:14 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-06-27 07:19:59 -0400 |
commit | 83e96d443b372611adf19e4171d41deb1d8760cf (patch) | |
tree | 47d97976a40831ac75475b0836029120702a2e3b | |
parent | 27fd8d90c996caa480ed6777eaaf21d9e5166cc3 (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.h | 28 | ||||
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 3 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_log_ipv4.c | 385 | ||||
-rw-r--r-- | net/ipv6/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv6/netfilter/Makefile | 3 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_log_ipv6.c | 417 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 6 | ||||
-rw-r--r-- | net/netfilter/Makefile | 3 | ||||
-rw-r--r-- | net/netfilter/nf_log_common.c | 187 | ||||
-rw-r--r-- | net/netfilter/xt_LOG.c | 879 |
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, ...); |
79 | void nf_log_buf_close(struct nf_log_buf *m); | 79 | void nf_log_buf_close(struct nf_log_buf *m); |
80 | 80 | ||
81 | void 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 | |||
88 | void 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 */ | ||
96 | int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb, | ||
97 | u8 proto, int fragment, unsigned int offset); | ||
98 | int 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); | ||
101 | void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk); | ||
102 | void 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 | ||
162 | config 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 |
163 | config NF_NAT_IPV4 | 168 | config 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 |
20 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o | 20 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o |
21 | 21 | ||
22 | # logging | ||
23 | obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o | ||
24 | |||
22 | # NAT helpers (nf_conntrack) | 25 | # NAT helpers (nf_conntrack) |
23 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o | 26 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o |
24 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o | 27 | obj-$(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 | |||
24 | static 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 */ | ||
35 | static 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 | |||
272 | static 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 | |||
295 | fallback: | ||
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 | |||
309 | void 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 | } | ||
337 | EXPORT_SYMBOL_GPL(nf_log_ip_packet); | ||
338 | |||
339 | static 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 | |||
346 | static 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 | |||
352 | static void __net_exit nf_log_ipv4_net_exit(struct net *net) | ||
353 | { | ||
354 | nf_log_unset(net, &nf_ip_logger); | ||
355 | } | ||
356 | |||
357 | static struct pernet_operations nf_log_ipv4_net_ops = { | ||
358 | .init = nf_log_ipv4_net_init, | ||
359 | .exit = nf_log_ipv4_net_exit, | ||
360 | }; | ||
361 | |||
362 | static 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 | |||
374 | static 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 | |||
380 | module_init(nf_log_ipv4_init); | ||
381 | module_exit(nf_log_ipv4_exit); | ||
382 | |||
383 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
384 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | ||
385 | MODULE_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 | ||
230 | config NF_LOG_IPV6 | ||
231 | tristate "IPv6 packet logging" | ||
232 | depends on NETFILTER_ADVANCED | ||
233 | select NF_LOG_COMMON | ||
234 | |||
230 | config NF_NAT_IPV6 | 235 | config 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 | |||
23 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | 23 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o |
24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | 24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o |
25 | 25 | ||
26 | # logging | ||
27 | obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o | ||
28 | |||
26 | # nf_tables | 29 | # nf_tables |
27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 30 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 31 | obj-$(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 | |||
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 | /* One level of recursion won't kill us */ | ||
36 | static 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 | |||
285 | static 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 | |||
308 | fallback: | ||
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 | |||
341 | void 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 | } | ||
369 | EXPORT_SYMBOL_GPL(nf_log_ip6_packet); | ||
370 | |||
371 | static 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 | |||
378 | static 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 | |||
384 | static void __net_exit nf_log_ipv6_net_exit(struct net *net) | ||
385 | { | ||
386 | nf_log_unset(net, &nf_ip6_logger); | ||
387 | } | ||
388 | |||
389 | static struct pernet_operations nf_log_ipv6_net_ops = { | ||
390 | .init = nf_log_ipv6_net_init, | ||
391 | .exit = nf_log_ipv6_net_exit, | ||
392 | }; | ||
393 | |||
394 | static 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 | |||
406 | static 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 | |||
412 | module_init(nf_log_ipv6_init); | ||
413 | module_exit(nf_log_ipv6_exit); | ||
414 | |||
415 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
416 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | ||
417 | MODULE_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 | ||
362 | config NF_LOG_COMMON | ||
363 | tristate | ||
364 | |||
362 | config NF_NAT | 365 | config NF_NAT |
363 | tristate | 366 | tristate |
364 | 367 | ||
@@ -744,6 +747,9 @@ config NETFILTER_XT_TARGET_LED | |||
744 | 747 | ||
745 | config NETFILTER_XT_TARGET_LOG | 748 | config 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 | |||
47 | nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ | 47 | nf_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 | ||
51 | obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o | ||
52 | |||
50 | obj-$(CONFIG_NF_NAT) += nf_nat.o | 53 | obj-$(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 | |||
23 | int 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 | |||
50 | out: | ||
51 | return 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(nf_log_dump_udp_header); | ||
54 | |||
55 | int 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 | } | ||
132 | EXPORT_SYMBOL_GPL(nf_log_dump_tcp_header); | ||
133 | |||
134 | void 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 | } | ||
148 | EXPORT_SYMBOL_GPL(nf_log_dump_sk_uid_gid); | ||
149 | |||
150 | void | ||
151 | nf_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 | } | ||
175 | EXPORT_SYMBOL_GPL(nf_log_dump_packet_common); | ||
176 | |||
177 | static int __init nf_log_common_init(void) | ||
178 | { | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static void __exit nf_log_common_exit(void) {} | ||
183 | |||
184 | module_init(nf_log_common_init); | ||
185 | module_exit(nf_log_common_exit); | ||
186 | |||
187 | MODULE_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 | ||
31 | static 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 | |||
41 | static 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 | |||
68 | out: | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static 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 | |||
150 | static 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 */ | ||
166 | static 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 | |||
404 | static 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 | |||
427 | fallback: | ||
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 | |||
441 | static void | ||
442 | log_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 | |||
471 | static void | ||
472 | ipt_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 */ | ||
504 | static 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 | |||
750 | static 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 | |||
773 | fallback: | ||
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 | |||
806 | static void | ||
807 | ip6t_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 | |||
838 | static unsigned int | 31 | static unsigned int |
839 | log_tg(struct sk_buff *skb, const struct xt_action_param *par) | 32 | log_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 | ||
904 | static 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) | ||
912 | static 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 | |||
920 | static 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 | |||
929 | static 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 | |||
937 | static struct pernet_operations log_net_ops = { | ||
938 | .init = log_net_init, | ||
939 | .exit = log_net_exit, | ||
940 | }; | ||
941 | |||
942 | static int __init log_tg_init(void) | 97 | static 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 | |||
960 | err_target: | ||
961 | unregister_pernet_subsys(&log_net_ops); | ||
962 | err_pernet: | ||
963 | return ret; | ||
964 | } | 100 | } |
965 | 101 | ||
966 | static void __exit log_tg_exit(void) | 102 | static 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 | ||