aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-03-08 01:27:56 -0500
committerDavid S. Miller <davem@davemloft.net>2012-03-08 01:27:56 -0500
commitc75a312d8b2c97943014261d71c6ef2622b6d0d9 (patch)
tree374a25ac277d787485dc9acf87710e28f50d52bb /net/ipv4
parentb4fb05ea402cb6930b40d3152d8acabc391b23e2 (diff)
parentace30d73ef09fd5f95b24c5c1c5aa11963981494 (diff)
Merge branch 'master' of git://1984.lsi.us.es/net-next
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/Kconfig9
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c516
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c60
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c14
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c7
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
126config 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
135config IP_NF_TARGET_ULOG 126config 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
55obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 55obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
56obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 56obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
57obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
58obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 57obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
59obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 58obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
60obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 59obj-$(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
29MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
31MODULE_DESCRIPTION("Xtables: IPv4 packet logging to syslog");
32
33/* One level of recursion won't kill us */
34static 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
366static 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
389fallback:
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
403static 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
413static void
414ipt_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
453static unsigned int
454log_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
468static 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
483static 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
492static struct nf_logger ipt_log_logger __read_mostly = {
493 .name = "ipt_LOG",
494 .logfn = &ipt_log_packet,
495 .me = THIS_MODULE,
496};
497
498static 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
509static void __exit log_tg_exit(void)
510{
511 nf_log_unregister(&ipt_log_logger);
512 xt_unregister_target(&log_tg_reg);
513}
514
515module_init(log_tg_init);
516module_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
78static 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. */
79static int icmp_packet(struct nf_conn *ct, 84static 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. */
95static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, 101static 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
277static 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
291static int
292icmp_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
300nla_put_failure:
301 return -ENOSPC;
302}
303
304static const struct nla_policy
305icmp_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
267static struct ctl_table_header *icmp_sysctl_header; 311static struct ctl_table_header *icmp_sysctl_header;
268static struct ctl_table icmp_sysctl_table[] = { 312static 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
689static struct nf_ct_helper_expectfn follow_master_nat = {
690 .name = "nat-follow-master",
691 .expectfn = nf_nat_follow_master,
692};
693
689static int __init nf_nat_init(void) 694static 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
571static struct nf_ct_helper_expectfn q931_nat = {
572 .name = "Q.931",
573 .expectfn = ip_nat_q931_expect,
574};
575
576static struct nf_ct_helper_expectfn callforwarding_nat = {
577 .name = "callforwarding",
578 .expectfn = ip_nat_callforwarding_expect,
579};
580
571/****************************************************************************/ 581/****************************************************************************/
572static int __init init(void) 582static 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
529static struct nf_ct_helper_expectfn sip_nat = {
530 .name = "sip",
531 .expectfn = ip_nat_sip_expected,
532};
533
529static void __exit nf_nat_sip_fini(void) 534static 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