diff options
author | David S. Miller <davem@davemloft.net> | 2012-03-08 01:27:56 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-03-08 01:27:56 -0500 |
commit | c75a312d8b2c97943014261d71c6ef2622b6d0d9 (patch) | |
tree | 374a25ac277d787485dc9acf87710e28f50d52bb /net/ipv4 | |
parent | b4fb05ea402cb6930b40d3152d8acabc391b23e2 (diff) | |
parent | ace30d73ef09fd5f95b24c5c1c5aa11963981494 (diff) |
Merge branch 'master' of git://1984.lsi.us.es/net-next
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 9 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_LOG.c | 516 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_proto_icmp.c | 60 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 8 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_h323.c | 14 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_sip.c | 7 |
7 files changed, 86 insertions, 529 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 74dfc9e5211f..fcc543cd987a 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -123,15 +123,6 @@ config IP_NF_TARGET_REJECT | |||
123 | 123 | ||
124 | To compile it as a module, choose M here. If unsure, say N. | 124 | To compile it as a module, choose M here. If unsure, say N. |
125 | 125 | ||
126 | config IP_NF_TARGET_LOG | ||
127 | tristate "LOG target support" | ||
128 | default m if NETFILTER_ADVANCED=n | ||
129 | help | ||
130 | This option adds a `LOG' target, which allows you to create rules in | ||
131 | any iptables table which records the packet header to the syslog. | ||
132 | |||
133 | To compile it as a module, choose M here. If unsure, say N. | ||
134 | |||
135 | config IP_NF_TARGET_ULOG | 126 | config IP_NF_TARGET_ULOG |
136 | tristate "ULOG target support" | 127 | tristate "ULOG target support" |
137 | default m if NETFILTER_ADVANCED=n | 128 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 213a462b739b..240b68469a7a 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -54,7 +54,6 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o | |||
54 | # targets | 54 | # targets |
55 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 55 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o |
56 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o | 56 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o |
57 | obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o | ||
58 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o | 57 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o |
59 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o | 58 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o |
60 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o | 59 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c deleted file mode 100644 index d76d6c9ed946..000000000000 --- a/net/ipv4/netfilter/ipt_LOG.c +++ /dev/null | |||
@@ -1,516 +0,0 @@ | |||
1 | /* | ||
2 | * This is a module which is used for logging packets. | ||
3 | */ | ||
4 | |||
5 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
6 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/if_arp.h> | ||
17 | #include <linux/ip.h> | ||
18 | #include <net/icmp.h> | ||
19 | #include <net/udp.h> | ||
20 | #include <net/tcp.h> | ||
21 | #include <net/route.h> | ||
22 | |||
23 | #include <linux/netfilter.h> | ||
24 | #include <linux/netfilter/x_tables.h> | ||
25 | #include <linux/netfilter_ipv4/ipt_LOG.h> | ||
26 | #include <net/netfilter/nf_log.h> | ||
27 | #include <net/netfilter/xt_log.h> | ||
28 | |||
29 | MODULE_LICENSE("GPL"); | ||
30 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
31 | MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog"); | ||
32 | |||
33 | /* One level of recursion won't kill us */ | ||
34 | static void dump_packet(struct sbuff *m, | ||
35 | const struct nf_loginfo *info, | ||
36 | const struct sk_buff *skb, | ||
37 | 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 | sb_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 | sb_add(m, "SRC=%pI4 DST=%pI4 ", | ||
58 | &ih->saddr, &ih->daddr); | ||
59 | |||
60 | /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ | ||
61 | sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", | ||
62 | ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, | ||
63 | ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); | ||
64 | |||
65 | /* Max length: 6 "CE DF MF " */ | ||
66 | if (ntohs(ih->frag_off) & IP_CE) | ||
67 | sb_add(m, "CE "); | ||
68 | if (ntohs(ih->frag_off) & IP_DF) | ||
69 | sb_add(m, "DF "); | ||
70 | if (ntohs(ih->frag_off) & IP_MF) | ||
71 | sb_add(m, "MF "); | ||
72 | |||
73 | /* Max length: 11 "FRAG:65535 " */ | ||
74 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
75 | sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); | ||
76 | |||
77 | if ((logflags & IPT_LOG_IPOPT) && | ||
78 | ih->ihl * 4 > sizeof(struct iphdr)) { | ||
79 | const unsigned char *op; | ||
80 | unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; | ||
81 | unsigned int i, optsize; | ||
82 | |||
83 | optsize = ih->ihl * 4 - sizeof(struct iphdr); | ||
84 | op = skb_header_pointer(skb, iphoff+sizeof(_iph), | ||
85 | optsize, _opt); | ||
86 | if (op == NULL) { | ||
87 | sb_add(m, "TRUNCATED"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
92 | sb_add(m, "OPT ("); | ||
93 | for (i = 0; i < optsize; i++) | ||
94 | sb_add(m, "%02X", op[i]); | ||
95 | sb_add(m, ") "); | ||
96 | } | ||
97 | |||
98 | switch (ih->protocol) { | ||
99 | case IPPROTO_TCP: { | ||
100 | struct tcphdr _tcph; | ||
101 | const struct tcphdr *th; | ||
102 | |||
103 | /* Max length: 10 "PROTO=TCP " */ | ||
104 | sb_add(m, "PROTO=TCP "); | ||
105 | |||
106 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
107 | break; | ||
108 | |||
109 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
110 | th = skb_header_pointer(skb, iphoff + ih->ihl * 4, | ||
111 | sizeof(_tcph), &_tcph); | ||
112 | if (th == NULL) { | ||
113 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
114 | skb->len - iphoff - ih->ihl*4); | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
119 | sb_add(m, "SPT=%u DPT=%u ", | ||
120 | ntohs(th->source), ntohs(th->dest)); | ||
121 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | ||
122 | if (logflags & IPT_LOG_TCPSEQ) | ||
123 | sb_add(m, "SEQ=%u ACK=%u ", | ||
124 | ntohl(th->seq), ntohl(th->ack_seq)); | ||
125 | /* Max length: 13 "WINDOW=65535 " */ | ||
126 | sb_add(m, "WINDOW=%u ", ntohs(th->window)); | ||
127 | /* Max length: 9 "RES=0x3F " */ | ||
128 | sb_add(m, "RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); | ||
129 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | ||
130 | if (th->cwr) | ||
131 | sb_add(m, "CWR "); | ||
132 | if (th->ece) | ||
133 | sb_add(m, "ECE "); | ||
134 | if (th->urg) | ||
135 | sb_add(m, "URG "); | ||
136 | if (th->ack) | ||
137 | sb_add(m, "ACK "); | ||
138 | if (th->psh) | ||
139 | sb_add(m, "PSH "); | ||
140 | if (th->rst) | ||
141 | sb_add(m, "RST "); | ||
142 | if (th->syn) | ||
143 | sb_add(m, "SYN "); | ||
144 | if (th->fin) | ||
145 | sb_add(m, "FIN "); | ||
146 | /* Max length: 11 "URGP=65535 " */ | ||
147 | sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); | ||
148 | |||
149 | if ((logflags & IPT_LOG_TCPOPT) && | ||
150 | th->doff * 4 > sizeof(struct tcphdr)) { | ||
151 | unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; | ||
152 | const unsigned char *op; | ||
153 | unsigned int i, optsize; | ||
154 | |||
155 | optsize = th->doff * 4 - sizeof(struct tcphdr); | ||
156 | op = skb_header_pointer(skb, | ||
157 | iphoff+ih->ihl*4+sizeof(_tcph), | ||
158 | optsize, _opt); | ||
159 | if (op == NULL) { | ||
160 | sb_add(m, "TRUNCATED"); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
165 | sb_add(m, "OPT ("); | ||
166 | for (i = 0; i < optsize; i++) | ||
167 | sb_add(m, "%02X", op[i]); | ||
168 | sb_add(m, ") "); | ||
169 | } | ||
170 | break; | ||
171 | } | ||
172 | case IPPROTO_UDP: | ||
173 | case IPPROTO_UDPLITE: { | ||
174 | struct udphdr _udph; | ||
175 | const struct udphdr *uh; | ||
176 | |||
177 | if (ih->protocol == IPPROTO_UDP) | ||
178 | /* Max length: 10 "PROTO=UDP " */ | ||
179 | sb_add(m, "PROTO=UDP " ); | ||
180 | else /* Max length: 14 "PROTO=UDPLITE " */ | ||
181 | sb_add(m, "PROTO=UDPLITE "); | ||
182 | |||
183 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
184 | break; | ||
185 | |||
186 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
187 | uh = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
188 | sizeof(_udph), &_udph); | ||
189 | if (uh == NULL) { | ||
190 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
191 | skb->len - iphoff - ih->ihl*4); | ||
192 | break; | ||
193 | } | ||
194 | |||
195 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
196 | sb_add(m, "SPT=%u DPT=%u LEN=%u ", | ||
197 | ntohs(uh->source), ntohs(uh->dest), | ||
198 | ntohs(uh->len)); | ||
199 | break; | ||
200 | } | ||
201 | case IPPROTO_ICMP: { | ||
202 | struct icmphdr _icmph; | ||
203 | const struct icmphdr *ich; | ||
204 | static const size_t required_len[NR_ICMP_TYPES+1] | ||
205 | = { [ICMP_ECHOREPLY] = 4, | ||
206 | [ICMP_DEST_UNREACH] | ||
207 | = 8 + sizeof(struct iphdr), | ||
208 | [ICMP_SOURCE_QUENCH] | ||
209 | = 8 + sizeof(struct iphdr), | ||
210 | [ICMP_REDIRECT] | ||
211 | = 8 + sizeof(struct iphdr), | ||
212 | [ICMP_ECHO] = 4, | ||
213 | [ICMP_TIME_EXCEEDED] | ||
214 | = 8 + sizeof(struct iphdr), | ||
215 | [ICMP_PARAMETERPROB] | ||
216 | = 8 + sizeof(struct iphdr), | ||
217 | [ICMP_TIMESTAMP] = 20, | ||
218 | [ICMP_TIMESTAMPREPLY] = 20, | ||
219 | [ICMP_ADDRESS] = 12, | ||
220 | [ICMP_ADDRESSREPLY] = 12 }; | ||
221 | |||
222 | /* Max length: 11 "PROTO=ICMP " */ | ||
223 | sb_add(m, "PROTO=ICMP "); | ||
224 | |||
225 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
226 | break; | ||
227 | |||
228 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
229 | ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, | ||
230 | sizeof(_icmph), &_icmph); | ||
231 | if (ich == NULL) { | ||
232 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
233 | skb->len - iphoff - ih->ihl*4); | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
238 | sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); | ||
239 | |||
240 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
241 | if (ich->type <= NR_ICMP_TYPES && | ||
242 | required_len[ich->type] && | ||
243 | skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { | ||
244 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
245 | skb->len - iphoff - ih->ihl*4); | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | switch (ich->type) { | ||
250 | case ICMP_ECHOREPLY: | ||
251 | case ICMP_ECHO: | ||
252 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
253 | sb_add(m, "ID=%u SEQ=%u ", | ||
254 | ntohs(ich->un.echo.id), | ||
255 | ntohs(ich->un.echo.sequence)); | ||
256 | break; | ||
257 | |||
258 | case ICMP_PARAMETERPROB: | ||
259 | /* Max length: 14 "PARAMETER=255 " */ | ||
260 | sb_add(m, "PARAMETER=%u ", | ||
261 | ntohl(ich->un.gateway) >> 24); | ||
262 | break; | ||
263 | case ICMP_REDIRECT: | ||
264 | /* Max length: 24 "GATEWAY=255.255.255.255 " */ | ||
265 | sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway); | ||
266 | /* Fall through */ | ||
267 | case ICMP_DEST_UNREACH: | ||
268 | case ICMP_SOURCE_QUENCH: | ||
269 | case ICMP_TIME_EXCEEDED: | ||
270 | /* Max length: 3+maxlen */ | ||
271 | if (!iphoff) { /* Only recurse once. */ | ||
272 | sb_add(m, "["); | ||
273 | dump_packet(m, info, skb, | ||
274 | iphoff + ih->ihl*4+sizeof(_icmph)); | ||
275 | sb_add(m, "] "); | ||
276 | } | ||
277 | |||
278 | /* Max length: 10 "MTU=65535 " */ | ||
279 | if (ich->type == ICMP_DEST_UNREACH && | ||
280 | ich->code == ICMP_FRAG_NEEDED) | ||
281 | sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu)); | ||
282 | } | ||
283 | break; | ||
284 | } | ||
285 | /* Max Length */ | ||
286 | case IPPROTO_AH: { | ||
287 | struct ip_auth_hdr _ahdr; | ||
288 | const struct ip_auth_hdr *ah; | ||
289 | |||
290 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
291 | break; | ||
292 | |||
293 | /* Max length: 9 "PROTO=AH " */ | ||
294 | sb_add(m, "PROTO=AH "); | ||
295 | |||
296 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
297 | ah = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
298 | sizeof(_ahdr), &_ahdr); | ||
299 | if (ah == NULL) { | ||
300 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
301 | skb->len - iphoff - ih->ihl*4); | ||
302 | break; | ||
303 | } | ||
304 | |||
305 | /* Length: 15 "SPI=0xF1234567 " */ | ||
306 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
307 | break; | ||
308 | } | ||
309 | case IPPROTO_ESP: { | ||
310 | struct ip_esp_hdr _esph; | ||
311 | const struct ip_esp_hdr *eh; | ||
312 | |||
313 | /* Max length: 10 "PROTO=ESP " */ | ||
314 | sb_add(m, "PROTO=ESP "); | ||
315 | |||
316 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
317 | break; | ||
318 | |||
319 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
320 | eh = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
321 | sizeof(_esph), &_esph); | ||
322 | if (eh == NULL) { | ||
323 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
324 | skb->len - iphoff - ih->ihl*4); | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | /* Length: 15 "SPI=0xF1234567 " */ | ||
329 | sb_add(m, "SPI=0x%x ", ntohl(eh->spi)); | ||
330 | break; | ||
331 | } | ||
332 | /* Max length: 10 "PROTO 255 " */ | ||
333 | default: | ||
334 | sb_add(m, "PROTO=%u ", ih->protocol); | ||
335 | } | ||
336 | |||
337 | /* Max length: 15 "UID=4294967295 " */ | ||
338 | if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) { | ||
339 | read_lock_bh(&skb->sk->sk_callback_lock); | ||
340 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | ||
341 | sb_add(m, "UID=%u GID=%u ", | ||
342 | skb->sk->sk_socket->file->f_cred->fsuid, | ||
343 | skb->sk->sk_socket->file->f_cred->fsgid); | ||
344 | read_unlock_bh(&skb->sk->sk_callback_lock); | ||
345 | } | ||
346 | |||
347 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
348 | if (!iphoff && skb->mark) | ||
349 | sb_add(m, "MARK=0x%x ", skb->mark); | ||
350 | |||
351 | /* Proto Max log string length */ | ||
352 | /* IP: 40+46+6+11+127 = 230 */ | ||
353 | /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ | ||
354 | /* UDP: 10+max(25,20) = 35 */ | ||
355 | /* UDPLITE: 14+max(25,20) = 39 */ | ||
356 | /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ | ||
357 | /* ESP: 10+max(25)+15 = 50 */ | ||
358 | /* AH: 9+max(25)+15 = 49 */ | ||
359 | /* unknown: 10 */ | ||
360 | |||
361 | /* (ICMP allows recursion one level deep) */ | ||
362 | /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ | ||
363 | /* maxlen = 230+ 91 + 230 + 252 = 803 */ | ||
364 | } | ||
365 | |||
366 | static void dump_mac_header(struct sbuff *m, | ||
367 | const struct nf_loginfo *info, | ||
368 | const struct sk_buff *skb) | ||
369 | { | ||
370 | struct net_device *dev = skb->dev; | ||
371 | unsigned int logflags = 0; | ||
372 | |||
373 | if (info->type == NF_LOG_TYPE_LOG) | ||
374 | logflags = info->u.log.logflags; | ||
375 | |||
376 | if (!(logflags & IPT_LOG_MACDECODE)) | ||
377 | goto fallback; | ||
378 | |||
379 | switch (dev->type) { | ||
380 | case ARPHRD_ETHER: | ||
381 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
382 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
383 | ntohs(eth_hdr(skb)->h_proto)); | ||
384 | return; | ||
385 | default: | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | fallback: | ||
390 | sb_add(m, "MAC="); | ||
391 | if (dev->hard_header_len && | ||
392 | skb->mac_header != skb->network_header) { | ||
393 | const unsigned char *p = skb_mac_header(skb); | ||
394 | unsigned int i; | ||
395 | |||
396 | sb_add(m, "%02x", *p++); | ||
397 | for (i = 1; i < dev->hard_header_len; i++, p++) | ||
398 | sb_add(m, ":%02x", *p); | ||
399 | } | ||
400 | sb_add(m, " "); | ||
401 | } | ||
402 | |||
403 | static struct nf_loginfo default_loginfo = { | ||
404 | .type = NF_LOG_TYPE_LOG, | ||
405 | .u = { | ||
406 | .log = { | ||
407 | .level = 5, | ||
408 | .logflags = NF_LOG_MASK, | ||
409 | }, | ||
410 | }, | ||
411 | }; | ||
412 | |||
413 | static void | ||
414 | ipt_log_packet(u_int8_t pf, | ||
415 | unsigned int hooknum, | ||
416 | const struct sk_buff *skb, | ||
417 | const struct net_device *in, | ||
418 | const struct net_device *out, | ||
419 | const struct nf_loginfo *loginfo, | ||
420 | const char *prefix) | ||
421 | { | ||
422 | struct sbuff *m = sb_open(); | ||
423 | |||
424 | if (!loginfo) | ||
425 | loginfo = &default_loginfo; | ||
426 | |||
427 | sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, | ||
428 | prefix, | ||
429 | in ? in->name : "", | ||
430 | out ? out->name : ""); | ||
431 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
432 | if (skb->nf_bridge) { | ||
433 | const struct net_device *physindev; | ||
434 | const struct net_device *physoutdev; | ||
435 | |||
436 | physindev = skb->nf_bridge->physindev; | ||
437 | if (physindev && in != physindev) | ||
438 | sb_add(m, "PHYSIN=%s ", physindev->name); | ||
439 | physoutdev = skb->nf_bridge->physoutdev; | ||
440 | if (physoutdev && out != physoutdev) | ||
441 | sb_add(m, "PHYSOUT=%s ", physoutdev->name); | ||
442 | } | ||
443 | #endif | ||
444 | |||
445 | if (in != NULL) | ||
446 | dump_mac_header(m, loginfo, skb); | ||
447 | |||
448 | dump_packet(m, loginfo, skb, 0); | ||
449 | |||
450 | sb_close(m); | ||
451 | } | ||
452 | |||
453 | static unsigned int | ||
454 | log_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
455 | { | ||
456 | const struct ipt_log_info *loginfo = par->targinfo; | ||
457 | struct nf_loginfo li; | ||
458 | |||
459 | li.type = NF_LOG_TYPE_LOG; | ||
460 | li.u.log.level = loginfo->level; | ||
461 | li.u.log.logflags = loginfo->logflags; | ||
462 | |||
463 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, par->out, &li, | ||
464 | loginfo->prefix); | ||
465 | return XT_CONTINUE; | ||
466 | } | ||
467 | |||
468 | static int log_tg_check(const struct xt_tgchk_param *par) | ||
469 | { | ||
470 | const struct ipt_log_info *loginfo = par->targinfo; | ||
471 | |||
472 | if (loginfo->level >= 8) { | ||
473 | pr_debug("level %u >= 8\n", loginfo->level); | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | if (loginfo->prefix[sizeof(loginfo->prefix)-1] != '\0') { | ||
477 | pr_debug("prefix is not null-terminated\n"); | ||
478 | return -EINVAL; | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static struct xt_target log_tg_reg __read_mostly = { | ||
484 | .name = "LOG", | ||
485 | .family = NFPROTO_IPV4, | ||
486 | .target = log_tg, | ||
487 | .targetsize = sizeof(struct ipt_log_info), | ||
488 | .checkentry = log_tg_check, | ||
489 | .me = THIS_MODULE, | ||
490 | }; | ||
491 | |||
492 | static struct nf_logger ipt_log_logger __read_mostly = { | ||
493 | .name = "ipt_LOG", | ||
494 | .logfn = &ipt_log_packet, | ||
495 | .me = THIS_MODULE, | ||
496 | }; | ||
497 | |||
498 | static int __init log_tg_init(void) | ||
499 | { | ||
500 | int ret; | ||
501 | |||
502 | ret = xt_register_target(&log_tg_reg); | ||
503 | if (ret < 0) | ||
504 | return ret; | ||
505 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static void __exit log_tg_exit(void) | ||
510 | { | ||
511 | nf_log_unregister(&ipt_log_logger); | ||
512 | xt_unregister_target(&log_tg_reg); | ||
513 | } | ||
514 | |||
515 | module_init(log_tg_init); | ||
516 | module_exit(log_tg_exit); | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index ab5b27a2916f..7cbe9cb261c2 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -75,25 +75,31 @@ static int icmp_print_tuple(struct seq_file *s, | |||
75 | ntohs(tuple->src.u.icmp.id)); | 75 | ntohs(tuple->src.u.icmp.id)); |
76 | } | 76 | } |
77 | 77 | ||
78 | static unsigned int *icmp_get_timeouts(struct net *net) | ||
79 | { | ||
80 | return &nf_ct_icmp_timeout; | ||
81 | } | ||
82 | |||
78 | /* Returns verdict for packet, or -1 for invalid. */ | 83 | /* Returns verdict for packet, or -1 for invalid. */ |
79 | static int icmp_packet(struct nf_conn *ct, | 84 | static int icmp_packet(struct nf_conn *ct, |
80 | const struct sk_buff *skb, | 85 | const struct sk_buff *skb, |
81 | unsigned int dataoff, | 86 | unsigned int dataoff, |
82 | enum ip_conntrack_info ctinfo, | 87 | enum ip_conntrack_info ctinfo, |
83 | u_int8_t pf, | 88 | u_int8_t pf, |
84 | unsigned int hooknum) | 89 | unsigned int hooknum, |
90 | unsigned int *timeout) | ||
85 | { | 91 | { |
86 | /* Do not immediately delete the connection after the first | 92 | /* Do not immediately delete the connection after the first |
87 | successful reply to avoid excessive conntrackd traffic | 93 | successful reply to avoid excessive conntrackd traffic |
88 | and also to handle correctly ICMP echo reply duplicates. */ | 94 | and also to handle correctly ICMP echo reply duplicates. */ |
89 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); | 95 | nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); |
90 | 96 | ||
91 | return NF_ACCEPT; | 97 | return NF_ACCEPT; |
92 | } | 98 | } |
93 | 99 | ||
94 | /* Called when a new connection for this protocol found. */ | 100 | /* Called when a new connection for this protocol found. */ |
95 | static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, | 101 | static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, |
96 | unsigned int dataoff) | 102 | unsigned int dataoff, unsigned int *timeouts) |
97 | { | 103 | { |
98 | static const u_int8_t valid_new[] = { | 104 | static const u_int8_t valid_new[] = { |
99 | [ICMP_ECHO] = 1, | 105 | [ICMP_ECHO] = 1, |
@@ -263,6 +269,44 @@ static int icmp_nlattr_tuple_size(void) | |||
263 | } | 269 | } |
264 | #endif | 270 | #endif |
265 | 271 | ||
272 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) | ||
273 | |||
274 | #include <linux/netfilter/nfnetlink.h> | ||
275 | #include <linux/netfilter/nfnetlink_cttimeout.h> | ||
276 | |||
277 | static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], void *data) | ||
278 | { | ||
279 | unsigned int *timeout = data; | ||
280 | |||
281 | if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { | ||
282 | *timeout = | ||
283 | ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ; | ||
284 | } else { | ||
285 | /* Set default ICMP timeout. */ | ||
286 | *timeout = nf_ct_icmp_timeout; | ||
287 | } | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static int | ||
292 | icmp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) | ||
293 | { | ||
294 | const unsigned int *timeout = data; | ||
295 | |||
296 | NLA_PUT_BE32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ)); | ||
297 | |||
298 | return 0; | ||
299 | |||
300 | nla_put_failure: | ||
301 | return -ENOSPC; | ||
302 | } | ||
303 | |||
304 | static const struct nla_policy | ||
305 | icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = { | ||
306 | [CTA_TIMEOUT_ICMP_TIMEOUT] = { .type = NLA_U32 }, | ||
307 | }; | ||
308 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | ||
309 | |||
266 | #ifdef CONFIG_SYSCTL | 310 | #ifdef CONFIG_SYSCTL |
267 | static struct ctl_table_header *icmp_sysctl_header; | 311 | static struct ctl_table_header *icmp_sysctl_header; |
268 | static struct ctl_table icmp_sysctl_table[] = { | 312 | static struct ctl_table icmp_sysctl_table[] = { |
@@ -298,6 +342,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
298 | .invert_tuple = icmp_invert_tuple, | 342 | .invert_tuple = icmp_invert_tuple, |
299 | .print_tuple = icmp_print_tuple, | 343 | .print_tuple = icmp_print_tuple, |
300 | .packet = icmp_packet, | 344 | .packet = icmp_packet, |
345 | .get_timeouts = icmp_get_timeouts, | ||
301 | .new = icmp_new, | 346 | .new = icmp_new, |
302 | .error = icmp_error, | 347 | .error = icmp_error, |
303 | .destroy = NULL, | 348 | .destroy = NULL, |
@@ -308,6 +353,15 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
308 | .nlattr_to_tuple = icmp_nlattr_to_tuple, | 353 | .nlattr_to_tuple = icmp_nlattr_to_tuple, |
309 | .nla_policy = icmp_nla_policy, | 354 | .nla_policy = icmp_nla_policy, |
310 | #endif | 355 | #endif |
356 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) | ||
357 | .ctnl_timeout = { | ||
358 | .nlattr_to_obj = icmp_timeout_nlattr_to_obj, | ||
359 | .obj_to_nlattr = icmp_timeout_obj_to_nlattr, | ||
360 | .nlattr_max = CTA_TIMEOUT_ICMP_MAX, | ||
361 | .obj_size = sizeof(unsigned int), | ||
362 | .nla_policy = icmp_timeout_nla_policy, | ||
363 | }, | ||
364 | #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */ | ||
311 | #ifdef CONFIG_SYSCTL | 365 | #ifdef CONFIG_SYSCTL |
312 | .ctl_table_header = &icmp_sysctl_header, | 366 | .ctl_table_header = &icmp_sysctl_header, |
313 | .ctl_table = icmp_sysctl_table, | 367 | .ctl_table = icmp_sysctl_table, |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index a708933dc230..abb52adf5acd 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -686,6 +686,11 @@ static struct pernet_operations nf_nat_net_ops = { | |||
686 | .exit = nf_nat_net_exit, | 686 | .exit = nf_nat_net_exit, |
687 | }; | 687 | }; |
688 | 688 | ||
689 | static struct nf_ct_helper_expectfn follow_master_nat = { | ||
690 | .name = "nat-follow-master", | ||
691 | .expectfn = nf_nat_follow_master, | ||
692 | }; | ||
693 | |||
689 | static int __init nf_nat_init(void) | 694 | static int __init nf_nat_init(void) |
690 | { | 695 | { |
691 | size_t i; | 696 | size_t i; |
@@ -717,6 +722,8 @@ static int __init nf_nat_init(void) | |||
717 | 722 | ||
718 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); | 723 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); |
719 | 724 | ||
725 | nf_ct_helper_expectfn_register(&follow_master_nat); | ||
726 | |||
720 | BUG_ON(nf_nat_seq_adjust_hook != NULL); | 727 | BUG_ON(nf_nat_seq_adjust_hook != NULL); |
721 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); | 728 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); |
722 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); | 729 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
@@ -736,6 +743,7 @@ static void __exit nf_nat_cleanup(void) | |||
736 | unregister_pernet_subsys(&nf_nat_net_ops); | 743 | unregister_pernet_subsys(&nf_nat_net_ops); |
737 | nf_ct_l3proto_put(l3proto); | 744 | nf_ct_l3proto_put(l3proto); |
738 | nf_ct_extend_unregister(&nat_extend); | 745 | nf_ct_extend_unregister(&nat_extend); |
746 | nf_ct_helper_expectfn_unregister(&follow_master_nat); | ||
739 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); | 747 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); |
740 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); | 748 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); |
741 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); | 749 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index dc1dd912baf4..82536701e3a3 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -568,6 +568,16 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | |||
568 | return 0; | 568 | return 0; |
569 | } | 569 | } |
570 | 570 | ||
571 | static struct nf_ct_helper_expectfn q931_nat = { | ||
572 | .name = "Q.931", | ||
573 | .expectfn = ip_nat_q931_expect, | ||
574 | }; | ||
575 | |||
576 | static struct nf_ct_helper_expectfn callforwarding_nat = { | ||
577 | .name = "callforwarding", | ||
578 | .expectfn = ip_nat_callforwarding_expect, | ||
579 | }; | ||
580 | |||
571 | /****************************************************************************/ | 581 | /****************************************************************************/ |
572 | static int __init init(void) | 582 | static int __init init(void) |
573 | { | 583 | { |
@@ -590,6 +600,8 @@ static int __init init(void) | |||
590 | RCU_INIT_POINTER(nat_h245_hook, nat_h245); | 600 | RCU_INIT_POINTER(nat_h245_hook, nat_h245); |
591 | RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding); | 601 | RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding); |
592 | RCU_INIT_POINTER(nat_q931_hook, nat_q931); | 602 | RCU_INIT_POINTER(nat_q931_hook, nat_q931); |
603 | nf_ct_helper_expectfn_register(&q931_nat); | ||
604 | nf_ct_helper_expectfn_register(&callforwarding_nat); | ||
593 | return 0; | 605 | return 0; |
594 | } | 606 | } |
595 | 607 | ||
@@ -605,6 +617,8 @@ static void __exit fini(void) | |||
605 | RCU_INIT_POINTER(nat_h245_hook, NULL); | 617 | RCU_INIT_POINTER(nat_h245_hook, NULL); |
606 | RCU_INIT_POINTER(nat_callforwarding_hook, NULL); | 618 | RCU_INIT_POINTER(nat_callforwarding_hook, NULL); |
607 | RCU_INIT_POINTER(nat_q931_hook, NULL); | 619 | RCU_INIT_POINTER(nat_q931_hook, NULL); |
620 | nf_ct_helper_expectfn_unregister(&q931_nat); | ||
621 | nf_ct_helper_expectfn_unregister(&callforwarding_nat); | ||
608 | synchronize_rcu(); | 622 | synchronize_rcu(); |
609 | } | 623 | } |
610 | 624 | ||
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index d0319f96269f..57932c43960e 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
@@ -526,6 +526,11 @@ err1: | |||
526 | return NF_DROP; | 526 | return NF_DROP; |
527 | } | 527 | } |
528 | 528 | ||
529 | static struct nf_ct_helper_expectfn sip_nat = { | ||
530 | .name = "sip", | ||
531 | .expectfn = ip_nat_sip_expected, | ||
532 | }; | ||
533 | |||
529 | static void __exit nf_nat_sip_fini(void) | 534 | static void __exit nf_nat_sip_fini(void) |
530 | { | 535 | { |
531 | RCU_INIT_POINTER(nf_nat_sip_hook, NULL); | 536 | RCU_INIT_POINTER(nf_nat_sip_hook, NULL); |
@@ -535,6 +540,7 @@ static void __exit nf_nat_sip_fini(void) | |||
535 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL); | 540 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, NULL); |
536 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL); | 541 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, NULL); |
537 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL); | 542 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, NULL); |
543 | nf_ct_helper_expectfn_unregister(&sip_nat); | ||
538 | synchronize_rcu(); | 544 | synchronize_rcu(); |
539 | } | 545 | } |
540 | 546 | ||
@@ -554,6 +560,7 @@ static int __init nf_nat_sip_init(void) | |||
554 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port); | 560 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port); |
555 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session); | 561 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session); |
556 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media); | 562 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media); |
563 | nf_ct_helper_expectfn_register(&sip_nat); | ||
557 | return 0; | 564 | return 0; |
558 | } | 565 | } |
559 | 566 | ||