aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ip_output.c30
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c5
-rw-r--r--net/ipv4/ipvs/ip_vs_est.c1
-rw-r--r--net/ipv4/ipvs/ip_vs_sched.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c10
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c36
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c47
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c26
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c17
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c10
-rw-r--r--net/ipv4/netfilter/ipt_recent.c20
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c74
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c97
17 files changed, 206 insertions, 176 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 2a830de3a699..71da31818cfc 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -202,13 +202,11 @@ static inline int ip_finish_output2(struct sk_buff *skb)
202 202
203static inline int ip_finish_output(struct sk_buff *skb) 203static inline int ip_finish_output(struct sk_buff *skb)
204{ 204{
205 struct net_device *dev = skb->dst->dev; 205 if (skb->len > dst_mtu(skb->dst) &&
206 206 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
207 skb->dev = dev; 207 return ip_fragment(skb, ip_finish_output2);
208 skb->protocol = htons(ETH_P_IP); 208 else
209 209 return ip_finish_output2(skb);
210 return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
211 ip_finish_output2);
212} 210}
213 211
214int ip_mc_output(struct sk_buff *skb) 212int ip_mc_output(struct sk_buff *skb)
@@ -265,21 +263,21 @@ int ip_mc_output(struct sk_buff *skb)
265 newskb->dev, ip_dev_loopback_xmit); 263 newskb->dev, ip_dev_loopback_xmit);
266 } 264 }
267 265
268 if (skb->len > dst_mtu(&rt->u.dst)) 266 return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,
269 return ip_fragment(skb, ip_finish_output); 267 ip_finish_output);
270 else
271 return ip_finish_output(skb);
272} 268}
273 269
274int ip_output(struct sk_buff *skb) 270int ip_output(struct sk_buff *skb)
275{ 271{
272 struct net_device *dev = skb->dst->dev;
273
276 IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS); 274 IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
277 275
278 if (skb->len > dst_mtu(skb->dst) && 276 skb->dev = dev;
279 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) 277 skb->protocol = htons(ETH_P_IP);
280 return ip_fragment(skb, ip_finish_output); 278
281 else 279 return NF_HOOK(PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,
282 return ip_finish_output(skb); 280 ip_finish_output);
283} 281}
284 282
285int ip_queue_xmit(struct sk_buff *skb, int ipfragok) 283int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 1aca94a9fd8b..3f47ad8e1cad 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -532,11 +532,8 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum,
532{ 532{
533 if (!((*pskb)->ipvs_property)) 533 if (!((*pskb)->ipvs_property))
534 return NF_ACCEPT; 534 return NF_ACCEPT;
535
536 /* The packet was sent from IPVS, exit this chain */ 535 /* The packet was sent from IPVS, exit this chain */
537 (*okfn)(*pskb); 536 return NF_STOP;
538
539 return NF_STOLEN;
540} 537}
541 538
542u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) 539u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
diff --git a/net/ipv4/ipvs/ip_vs_est.c b/net/ipv4/ipvs/ip_vs_est.c
index e7004741ac73..c453e1e57f4b 100644
--- a/net/ipv4/ipvs/ip_vs_est.c
+++ b/net/ipv4/ipvs/ip_vs_est.c
@@ -18,6 +18,7 @@
18#include <linux/jiffies.h> 18#include <linux/jiffies.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/interrupt.h>
21 22
22#include <net/ip_vs.h> 23#include <net/ip_vs.h>
23 24
diff --git a/net/ipv4/ipvs/ip_vs_sched.c b/net/ipv4/ipvs/ip_vs_sched.c
index 0f7c56a225bd..8bc42b76223d 100644
--- a/net/ipv4/ipvs/ip_vs_sched.c
+++ b/net/ipv4/ipvs/ip_vs_sched.c
@@ -22,6 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/spinlock.h> 24#include <linux/spinlock.h>
25#include <linux/interrupt.h>
25#include <asm/string.h> 26#include <asm/string.h>
26#include <linux/kmod.h> 27#include <linux/kmod.h>
27 28
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 0366eedb4d70..84e4f79b7ffa 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -36,7 +36,7 @@ static unsigned int master_timeout = 300;
36MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); 36MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
37MODULE_DESCRIPTION("Amanda connection tracking module"); 37MODULE_DESCRIPTION("Amanda connection tracking module");
38MODULE_LICENSE("GPL"); 38MODULE_LICENSE("GPL");
39module_param(master_timeout, int, 0600); 39module_param(master_timeout, uint, 0600);
40MODULE_PARM_DESC(master_timeout, "timeout for the master connection"); 40MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
41 41
42static const char *conns[] = { "DATA ", "MESG ", "INDEX " }; 42static const char *conns[] = { "DATA ", "MESG ", "INDEX " };
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 68b173bcda60..e627e5856172 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -34,7 +34,7 @@ static int ports_c;
34module_param_array(ports, ushort, &ports_c, 0400); 34module_param_array(ports, ushort, &ports_c, 0400);
35 35
36static int loose; 36static int loose;
37module_param(loose, int, 0600); 37module_param(loose, bool, 0600);
38 38
39unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb, 39unsigned int (*ip_nat_ftp_hook)(struct sk_buff **pskb,
40 enum ip_conntrack_info ctinfo, 40 enum ip_conntrack_info ctinfo,
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index d7c40421d0d1..c51a2cf71b4b 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -36,7 +36,7 @@
36#define MAX_PORTS 8 36#define MAX_PORTS 8
37static unsigned short ports[MAX_PORTS]; 37static unsigned short ports[MAX_PORTS];
38static int ports_c; 38static int ports_c;
39static int max_dcc_channels = 8; 39static unsigned int max_dcc_channels = 8;
40static unsigned int dcc_timeout = 300; 40static unsigned int dcc_timeout = 300;
41/* This is slow, but it's simple. --RR */ 41/* This is slow, but it's simple. --RR */
42static char *irc_buffer; 42static char *irc_buffer;
@@ -54,9 +54,9 @@ MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
54MODULE_LICENSE("GPL"); 54MODULE_LICENSE("GPL");
55module_param_array(ports, ushort, &ports_c, 0400); 55module_param_array(ports, ushort, &ports_c, 0400);
56MODULE_PARM_DESC(ports, "port numbers of IRC servers"); 56MODULE_PARM_DESC(ports, "port numbers of IRC servers");
57module_param(max_dcc_channels, int, 0400); 57module_param(max_dcc_channels, uint, 0400);
58MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); 58MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session");
59module_param(dcc_timeout, int, 0400); 59module_param(dcc_timeout, uint, 0400);
60MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); 60MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
61 61
62static const char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " }; 62static const char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
@@ -254,10 +254,6 @@ static int __init init(void)
254 printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n"); 254 printk("ip_conntrack_irc: max_dcc_channels must be a positive integer\n");
255 return -EBUSY; 255 return -EBUSY;
256 } 256 }
257 if (dcc_timeout < 0) {
258 printk("ip_conntrack_irc: dcc_timeout must be a positive integer\n");
259 return -EBUSY;
260 }
261 257
262 irc_buffer = kmalloc(65536, GFP_KERNEL); 258 irc_buffer = kmalloc(65536, GFP_KERNEL);
263 if (!irc_buffer) 259 if (!irc_buffer)
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 186646eb249f..4e68e16a2612 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -37,7 +37,7 @@ MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper");
37MODULE_LICENSE("GPL"); 37MODULE_LICENSE("GPL");
38 38
39static unsigned int timeout = 3; 39static unsigned int timeout = 3;
40module_param(timeout, int, 0600); 40module_param(timeout, uint, 0400);
41MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); 41MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
42 42
43static int help(struct sk_buff **pskb, 43static int help(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 91fe8f2e38ff..c9ebbe0d2d9c 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -79,6 +79,7 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
79 const struct ip_conntrack_tuple *tuple) 79 const struct ip_conntrack_tuple *tuple)
80{ 80{
81 struct nfattr *nest_parms; 81 struct nfattr *nest_parms;
82 int ret;
82 83
83 nest_parms = NFA_NEST(skb, CTA_TUPLE_IP); 84 nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
84 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip); 85 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
@@ -86,10 +87,10 @@ ctnetlink_dump_tuples(struct sk_buff *skb,
86 NFA_NEST_END(skb, nest_parms); 87 NFA_NEST_END(skb, nest_parms);
87 88
88 nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); 89 nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
89 ctnetlink_dump_tuples_proto(skb, tuple); 90 ret = ctnetlink_dump_tuples_proto(skb, tuple);
90 NFA_NEST_END(skb, nest_parms); 91 NFA_NEST_END(skb, nest_parms);
91 92
92 return 0; 93 return ret;
93 94
94nfattr_failure: 95nfattr_failure:
95 return -1; 96 return -1;
@@ -160,7 +161,7 @@ ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
160 return 0; 161 return 0;
161 162
162 nest_helper = NFA_NEST(skb, CTA_HELP); 163 nest_helper = NFA_NEST(skb, CTA_HELP);
163 NFA_PUT(skb, CTA_HELP_NAME, CTA_HELP_MAXNAMESIZE, &ct->helper->name); 164 NFA_PUT(skb, CTA_HELP_NAME, strlen(ct->helper->name), ct->helper->name);
164 165
165 if (ct->helper->to_nfattr) 166 if (ct->helper->to_nfattr)
166 ct->helper->to_nfattr(skb, ct); 167 ct->helper->to_nfattr(skb, ct);
@@ -229,7 +230,7 @@ nfattr_failure:
229static inline int 230static inline int
230ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct) 231ctnetlink_dump_use(struct sk_buff *skb, const struct ip_conntrack *ct)
231{ 232{
232 unsigned int use = htonl(atomic_read(&ct->ct_general.use)); 233 u_int32_t use = htonl(atomic_read(&ct->ct_general.use));
233 234
234 NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use); 235 NFA_PUT(skb, CTA_USE, sizeof(u_int32_t), &use);
235 return 0; 236 return 0;
@@ -311,29 +312,22 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
311 if (events & IPCT_DESTROY) { 312 if (events & IPCT_DESTROY) {
312 type = IPCTNL_MSG_CT_DELETE; 313 type = IPCTNL_MSG_CT_DELETE;
313 group = NFNLGRP_CONNTRACK_DESTROY; 314 group = NFNLGRP_CONNTRACK_DESTROY;
314 goto alloc_skb; 315 } else if (events & (IPCT_NEW | IPCT_RELATED)) {
315 }
316 if (events & (IPCT_NEW | IPCT_RELATED)) {
317 type = IPCTNL_MSG_CT_NEW; 316 type = IPCTNL_MSG_CT_NEW;
318 flags = NLM_F_CREATE|NLM_F_EXCL; 317 flags = NLM_F_CREATE|NLM_F_EXCL;
319 /* dump everything */ 318 /* dump everything */
320 events = ~0UL; 319 events = ~0UL;
321 group = NFNLGRP_CONNTRACK_NEW; 320 group = NFNLGRP_CONNTRACK_NEW;
322 goto alloc_skb; 321 } else if (events & (IPCT_STATUS |
323 }
324 if (events & (IPCT_STATUS |
325 IPCT_PROTOINFO | 322 IPCT_PROTOINFO |
326 IPCT_HELPER | 323 IPCT_HELPER |
327 IPCT_HELPINFO | 324 IPCT_HELPINFO |
328 IPCT_NATINFO)) { 325 IPCT_NATINFO)) {
329 type = IPCTNL_MSG_CT_NEW; 326 type = IPCTNL_MSG_CT_NEW;
330 group = NFNLGRP_CONNTRACK_UPDATE; 327 group = NFNLGRP_CONNTRACK_UPDATE;
331 goto alloc_skb; 328 } else
332 } 329 return NOTIFY_DONE;
333 330
334 return NOTIFY_DONE;
335
336alloc_skb:
337 /* FIXME: Check if there are any listeners before, don't hurt performance */ 331 /* FIXME: Check if there are any listeners before, don't hurt performance */
338 332
339 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); 333 skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
@@ -1037,6 +1031,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
1037 return err; 1031 return err;
1038 } 1032 }
1039 1033
1034#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
1035 if (cda[CTA_MARK-1])
1036 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1037#endif
1038
1040 ct->helper = ip_conntrack_helper_find_get(rtuple); 1039 ct->helper = ip_conntrack_helper_find_get(rtuple);
1041 1040
1042 add_timer(&ct->timeout); 1041 add_timer(&ct->timeout);
@@ -1045,11 +1044,6 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
1045 if (ct->helper) 1044 if (ct->helper)
1046 ip_conntrack_helper_put(ct->helper); 1045 ip_conntrack_helper_put(ct->helper);
1047 1046
1048#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
1049 if (cda[CTA_MARK-1])
1050 ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
1051#endif
1052
1053 DEBUGP("conntrack with id %u inserted\n", ct->id); 1047 DEBUGP("conntrack with id %u inserted\n", ct->id);
1054 return 0; 1048 return 0;
1055 1049
@@ -1209,7 +1203,6 @@ static int ctnetlink_expect_event(struct notifier_block *this,
1209 unsigned int type; 1203 unsigned int type;
1210 unsigned char *b; 1204 unsigned char *b;
1211 int flags = 0; 1205 int flags = 0;
1212 u16 proto;
1213 1206
1214 if (events & IPEXP_NEW) { 1207 if (events & IPEXP_NEW) {
1215 type = IPCTNL_MSG_EXP_NEW; 1208 type = IPCTNL_MSG_EXP_NEW;
@@ -1236,7 +1229,6 @@ static int ctnetlink_expect_event(struct notifier_block *this,
1236 goto nfattr_failure; 1229 goto nfattr_failure;
1237 1230
1238 nlh->nlmsg_len = skb->tail - b; 1231 nlh->nlmsg_len = skb->tail - b;
1239 proto = exp->tuple.dst.protonum;
1240 nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0); 1232 nfnetlink_send(skb, 0, NFNLGRP_CONNTRACK_EXP_NEW, 0);
1241 return NOTIFY_DONE; 1233 return NOTIFY_DONE;
1242 1234
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index 5f9925db608e..30fc21d6165a 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -47,20 +47,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
47 return 1; 47 return 1;
48} 48}
49 49
50/* Add 1; spaces filled with 0. */
51static const u_int8_t invmap[] = {
52 [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
53 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
54 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
55 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
56 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
57 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
58 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
59 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
60};
61
50static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple, 62static int icmp_invert_tuple(struct ip_conntrack_tuple *tuple,
51 const struct ip_conntrack_tuple *orig) 63 const struct ip_conntrack_tuple *orig)
52{ 64{
53 /* Add 1; spaces filled with 0. */
54 static const u_int8_t invmap[]
55 = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
56 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
57 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
58 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
59 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
60 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
61 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
62 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
63
64 if (orig->dst.u.icmp.type >= sizeof(invmap) 65 if (orig->dst.u.icmp.type >= sizeof(invmap)
65 || !invmap[orig->dst.u.icmp.type]) 66 || !invmap[orig->dst.u.icmp.type])
66 return 0; 67 return 0;
@@ -110,17 +111,17 @@ static int icmp_packet(struct ip_conntrack *ct,
110 return NF_ACCEPT; 111 return NF_ACCEPT;
111} 112}
112 113
113static const u_int8_t valid_new[] = {
114 [ICMP_ECHO] = 1,
115 [ICMP_TIMESTAMP] = 1,
116 [ICMP_INFO_REQUEST] = 1,
117 [ICMP_ADDRESS] = 1
118};
119
120/* Called when a new connection for this protocol found. */ 114/* Called when a new connection for this protocol found. */
121static int icmp_new(struct ip_conntrack *conntrack, 115static int icmp_new(struct ip_conntrack *conntrack,
122 const struct sk_buff *skb) 116 const struct sk_buff *skb)
123{ 117{
118 static const u_int8_t valid_new[] = {
119 [ICMP_ECHO] = 1,
120 [ICMP_TIMESTAMP] = 1,
121 [ICMP_INFO_REQUEST] = 1,
122 [ICMP_ADDRESS] = 1
123 };
124
124 if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) 125 if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
125 || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { 126 || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
126 /* Can't create a new ICMP `conn' with this. */ 127 /* Can't create a new ICMP `conn' with this. */
@@ -279,10 +280,6 @@ static int icmp_tuple_to_nfattr(struct sk_buff *skb,
279 NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t), 280 NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
280 &t->dst.u.icmp.code); 281 &t->dst.u.icmp.code);
281 282
282 if (t->dst.u.icmp.type >= sizeof(valid_new)
283 || !valid_new[t->dst.u.icmp.type])
284 return -EINVAL;
285
286 return 0; 283 return 0;
287 284
288nfattr_failure: 285nfattr_failure:
@@ -295,7 +292,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
295 if (!tb[CTA_PROTO_ICMP_TYPE-1] 292 if (!tb[CTA_PROTO_ICMP_TYPE-1]
296 || !tb[CTA_PROTO_ICMP_CODE-1] 293 || !tb[CTA_PROTO_ICMP_CODE-1]
297 || !tb[CTA_PROTO_ICMP_ID-1]) 294 || !tb[CTA_PROTO_ICMP_ID-1])
298 return -1; 295 return -EINVAL;
299 296
300 tuple->dst.u.icmp.type = 297 tuple->dst.u.icmp.type =
301 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]); 298 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
@@ -304,6 +301,10 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
304 tuple->src.u.icmp.id = 301 tuple->src.u.icmp.id =
305 *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); 302 *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
306 303
304 if (tuple->dst.u.icmp.type >= sizeof(invmap)
305 || !invmap[tuple->dst.u.icmp.type])
306 return -EINVAL;
307
307 return 0; 308 return 0;
308} 309}
309#endif 310#endif
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index a88bcc551244..7ba97783e741 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -451,30 +451,6 @@ static unsigned int ip_conntrack_defrag(unsigned int hooknum,
451 return NF_ACCEPT; 451 return NF_ACCEPT;
452} 452}
453 453
454static unsigned int ip_refrag(unsigned int hooknum,
455 struct sk_buff **pskb,
456 const struct net_device *in,
457 const struct net_device *out,
458 int (*okfn)(struct sk_buff *))
459{
460 struct rtable *rt = (struct rtable *)(*pskb)->dst;
461
462 /* We've seen it coming out the other side: confirm */
463 if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
464 return NF_DROP;
465
466 /* Local packets are never produced too large for their
467 interface. We degfragment them at LOCAL_OUT, however,
468 so we have to refragment them here. */
469 if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
470 !skb_shinfo(*pskb)->tso_size) {
471 /* No hook can be after us, so this should be OK. */
472 ip_fragment(*pskb, okfn);
473 return NF_STOLEN;
474 }
475 return NF_ACCEPT;
476}
477
478static unsigned int ip_conntrack_local(unsigned int hooknum, 454static unsigned int ip_conntrack_local(unsigned int hooknum,
479 struct sk_buff **pskb, 455 struct sk_buff **pskb,
480 const struct net_device *in, 456 const struct net_device *in,
@@ -544,7 +520,7 @@ static struct nf_hook_ops ip_conntrack_helper_in_ops = {
544 520
545/* Refragmenter; last chance. */ 521/* Refragmenter; last chance. */
546static struct nf_hook_ops ip_conntrack_out_ops = { 522static struct nf_hook_ops ip_conntrack_out_ops = {
547 .hook = ip_refrag, 523 .hook = ip_confirm,
548 .owner = THIS_MODULE, 524 .owner = THIS_MODULE,
549 .pf = PF_INET, 525 .pf = PF_INET,
550 .hooknum = NF_IP_POST_ROUTING, 526 .hooknum = NF_IP_POST_ROUTING,
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 30cd4e18c129..f04111f74e09 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -190,23 +190,6 @@ ip_nat_out(unsigned int hooknum,
190 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) 190 || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
191 return NF_ACCEPT; 191 return NF_ACCEPT;
192 192
193 /* We can hit fragment here; forwarded packets get
194 defragmented by connection tracking coming in, then
195 fragmented (grr) by the forward code.
196
197 In future: If we have nfct != NULL, AND we have NAT
198 initialized, AND there is no helper, then we can do full
199 NAPT on the head, and IP-address-only NAT on the rest.
200
201 I'm starting to have nightmares about fragments. */
202
203 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
204 *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT);
205
206 if (!*pskb)
207 return NF_STOLEN;
208 }
209
210 return ip_nat_fn(hooknum, pskb, in, out, okfn); 193 return ip_nat_fn(hooknum, pskb, in, out, okfn);
211} 194}
212 195
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index f057025a719e..6693526ae128 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -203,7 +203,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
203 sizeof(struct tcphdr), 0)); 203 sizeof(struct tcphdr), 0));
204 204
205 /* Adjust IP TTL, DF */ 205 /* Adjust IP TTL, DF */
206 nskb->nh.iph->ttl = MAXTTL; 206 nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
207 /* Set DF, id = 0 */ 207 /* Set DF, id = 0 */
208 nskb->nh.iph->frag_off = htons(IP_DF); 208 nskb->nh.iph->frag_off = htons(IP_DF);
209 nskb->nh.iph->id = 0; 209 nskb->nh.iph->id = 0;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 2883ccd8a91d..38641cd06123 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -77,15 +77,15 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG);
77#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0) 77#define PRINTR(format, args...) do { if (net_ratelimit()) printk(format , ## args); } while (0)
78 78
79static unsigned int nlbufsiz = 4096; 79static unsigned int nlbufsiz = 4096;
80module_param(nlbufsiz, uint, 0600); /* FIXME: Check size < 128k --RR */ 80module_param(nlbufsiz, uint, 0400);
81MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); 81MODULE_PARM_DESC(nlbufsiz, "netlink buffer size");
82 82
83static unsigned int flushtimeout = 10; 83static unsigned int flushtimeout = 10;
84module_param(flushtimeout, int, 0600); 84module_param(flushtimeout, uint, 0600);
85MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)"); 85MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)");
86 86
87static unsigned int nflog = 1; 87static int nflog = 1;
88module_param(nflog, int, 0400); 88module_param(nflog, bool, 0400);
89MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); 89MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
90 90
91/* global data structures */ 91/* global data structures */
@@ -376,7 +376,7 @@ static int __init init(void)
376 376
377 DEBUGP("ipt_ULOG: init module\n"); 377 DEBUGP("ipt_ULOG: init module\n");
378 378
379 if (nlbufsiz >= 128*1024) { 379 if (nlbufsiz > 128*1024) {
380 printk("Netlink buffer has to be <= 128kB\n"); 380 printk("Netlink buffer has to be <= 128kB\n");
381 return -EINVAL; 381 return -EINVAL;
382 } 382 }
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 261cbb4d4c49..5ddccb18c65e 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -24,10 +24,10 @@
24#define HASH_LOG 9 24#define HASH_LOG 9
25 25
26/* Defaults, these can be overridden on the module command-line. */ 26/* Defaults, these can be overridden on the module command-line. */
27static int ip_list_tot = 100; 27static unsigned int ip_list_tot = 100;
28static int ip_pkt_list_tot = 20; 28static unsigned int ip_pkt_list_tot = 20;
29static int ip_list_hash_size = 0; 29static unsigned int ip_list_hash_size = 0;
30static int ip_list_perms = 0644; 30static unsigned int ip_list_perms = 0644;
31#ifdef DEBUG 31#ifdef DEBUG
32static int debug = 1; 32static int debug = 1;
33#endif 33#endif
@@ -38,13 +38,13 @@ KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. htt
38MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>"); 38MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
39MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER); 39MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41module_param(ip_list_tot, int, 0400); 41module_param(ip_list_tot, uint, 0400);
42module_param(ip_pkt_list_tot, int, 0400); 42module_param(ip_pkt_list_tot, uint, 0400);
43module_param(ip_list_hash_size, int, 0400); 43module_param(ip_list_hash_size, uint, 0400);
44module_param(ip_list_perms, int, 0400); 44module_param(ip_list_perms, uint, 0400);
45#ifdef DEBUG 45#ifdef DEBUG
46module_param(debug, int, 0600); 46module_param(debug, bool, 0600);
47MODULE_PARM_DESC(debug,"debugging level, defaults to 1"); 47MODULE_PARM_DESC(debug,"enable debugging output");
48#endif 48#endif
49MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list"); 49MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
50MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember"); 50MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 8202c1c0afad..9bdbb7793971 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -22,6 +22,7 @@
22#include <linux/skbuff.h> 22#include <linux/skbuff.h>
23#include <linux/icmp.h> 23#include <linux/icmp.h>
24#include <linux/sysctl.h> 24#include <linux/sysctl.h>
25#include <net/route.h>
25#include <net/ip.h> 26#include <net/ip.h>
26 27
27#include <linux/netfilter_ipv4.h> 28#include <linux/netfilter_ipv4.h>
@@ -180,30 +181,6 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
180 return NF_ACCEPT; 181 return NF_ACCEPT;
181} 182}
182 183
183static unsigned int ipv4_refrag(unsigned int hooknum,
184 struct sk_buff **pskb,
185 const struct net_device *in,
186 const struct net_device *out,
187 int (*okfn)(struct sk_buff *))
188{
189 struct rtable *rt = (struct rtable *)(*pskb)->dst;
190
191 /* We've seen it coming out the other side: confirm */
192 if (ipv4_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
193 return NF_DROP;
194
195 /* Local packets are never produced too large for their
196 interface. We degfragment them at LOCAL_OUT, however,
197 so we have to refragment them here. */
198 if ((*pskb)->len > dst_mtu(&rt->u.dst) &&
199 !skb_shinfo(*pskb)->tso_size) {
200 /* No hook can be after us, so this should be OK. */
201 ip_fragment(*pskb, okfn);
202 return NF_STOLEN;
203 }
204 return NF_ACCEPT;
205}
206
207static unsigned int ipv4_conntrack_in(unsigned int hooknum, 184static unsigned int ipv4_conntrack_in(unsigned int hooknum,
208 struct sk_buff **pskb, 185 struct sk_buff **pskb,
209 const struct net_device *in, 186 const struct net_device *in,
@@ -283,7 +260,7 @@ static struct nf_hook_ops ipv4_conntrack_helper_in_ops = {
283 260
284/* Refragmenter; last chance. */ 261/* Refragmenter; last chance. */
285static struct nf_hook_ops ipv4_conntrack_out_ops = { 262static struct nf_hook_ops ipv4_conntrack_out_ops = {
286 .hook = ipv4_refrag, 263 .hook = ipv4_confirm,
287 .owner = THIS_MODULE, 264 .owner = THIS_MODULE,
288 .pf = PF_INET, 265 .pf = PF_INET,
289 .hooknum = NF_IP_POST_ROUTING, 266 .hooknum = NF_IP_POST_ROUTING,
@@ -392,6 +369,48 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
392 return -ENOENT; 369 return -ENOENT;
393} 370}
394 371
372#if defined(CONFIG_NF_CT_NETLINK) || \
373 defined(CONFIG_NF_CT_NETLINK_MODULE)
374
375#include <linux/netfilter/nfnetlink.h>
376#include <linux/netfilter/nfnetlink_conntrack.h>
377
378static int ipv4_tuple_to_nfattr(struct sk_buff *skb,
379 const struct nf_conntrack_tuple *tuple)
380{
381 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t),
382 &tuple->src.u3.ip);
383 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t),
384 &tuple->dst.u3.ip);
385 return 0;
386
387nfattr_failure:
388 return -1;
389}
390
391static const size_t cta_min_ip[CTA_IP_MAX] = {
392 [CTA_IP_V4_SRC-1] = sizeof(u_int32_t),
393 [CTA_IP_V4_DST-1] = sizeof(u_int32_t),
394};
395
396static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
397 struct nf_conntrack_tuple *t)
398{
399 if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1])
400 return -EINVAL;
401
402 if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
403 return -EINVAL;
404
405 t->src.u3.ip =
406 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
407 t->dst.u3.ip =
408 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
409
410 return 0;
411}
412#endif
413
395static struct nf_sockopt_ops so_getorigdst = { 414static struct nf_sockopt_ops so_getorigdst = {
396 .pf = PF_INET, 415 .pf = PF_INET,
397 .get_optmin = SO_ORIGINAL_DST, 416 .get_optmin = SO_ORIGINAL_DST,
@@ -408,6 +427,11 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
408 .print_conntrack = ipv4_print_conntrack, 427 .print_conntrack = ipv4_print_conntrack,
409 .prepare = ipv4_prepare, 428 .prepare = ipv4_prepare,
410 .get_features = ipv4_get_features, 429 .get_features = ipv4_get_features,
430#if defined(CONFIG_NF_CT_NETLINK) || \
431 defined(CONFIG_NF_CT_NETLINK_MODULE)
432 .tuple_to_nfattr = ipv4_tuple_to_nfattr,
433 .nfattr_to_tuple = ipv4_nfattr_to_tuple,
434#endif
411 .me = THIS_MODULE, 435 .me = THIS_MODULE,
412}; 436};
413 437
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 7ddb5c08f7b8..52dc175be39a 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -50,20 +50,21 @@ static int icmp_pkt_to_tuple(const struct sk_buff *skb,
50 return 1; 50 return 1;
51} 51}
52 52
53/* Add 1; spaces filled with 0. */
54static const u_int8_t invmap[] = {
55 [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
56 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
57 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
58 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
59 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
60 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
61 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
62 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
63};
64
53static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple, 65static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
54 const struct nf_conntrack_tuple *orig) 66 const struct nf_conntrack_tuple *orig)
55{ 67{
56 /* Add 1; spaces filled with 0. */
57 static u_int8_t invmap[]
58 = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
59 [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
60 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
61 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
62 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
63 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
64 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
65 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1};
66
67 if (orig->dst.u.icmp.type >= sizeof(invmap) 68 if (orig->dst.u.icmp.type >= sizeof(invmap)
68 || !invmap[orig->dst.u.icmp.type]) 69 || !invmap[orig->dst.u.icmp.type])
69 return 0; 70 return 0;
@@ -120,11 +121,12 @@ static int icmp_packet(struct nf_conn *ct,
120static int icmp_new(struct nf_conn *conntrack, 121static int icmp_new(struct nf_conn *conntrack,
121 const struct sk_buff *skb, unsigned int dataoff) 122 const struct sk_buff *skb, unsigned int dataoff)
122{ 123{
123 static u_int8_t valid_new[] 124 static const u_int8_t valid_new[] = {
124 = { [ICMP_ECHO] = 1, 125 [ICMP_ECHO] = 1,
125 [ICMP_TIMESTAMP] = 1, 126 [ICMP_TIMESTAMP] = 1,
126 [ICMP_INFO_REQUEST] = 1, 127 [ICMP_INFO_REQUEST] = 1,
127 [ICMP_ADDRESS] = 1 }; 128 [ICMP_ADDRESS] = 1
129 };
128 130
129 if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) 131 if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
130 || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { 132 || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
@@ -168,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
168 return -NF_ACCEPT; 170 return -NF_ACCEPT;
169 } 171 }
170 172
171 innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol); 173 innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol);
172 dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp); 174 dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
173 /* Are they talking about one of our connections? */ 175 /* Are they talking about one of our connections? */
174 if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, 176 if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -281,6 +283,60 @@ checksum_skipped:
281 return icmp_error_message(skb, ctinfo, hooknum); 283 return icmp_error_message(skb, ctinfo, hooknum);
282} 284}
283 285
286#if defined(CONFIG_NF_CT_NETLINK) || \
287 defined(CONFIG_NF_CT_NETLINK_MODULE)
288
289#include <linux/netfilter/nfnetlink.h>
290#include <linux/netfilter/nfnetlink_conntrack.h>
291
292static int icmp_tuple_to_nfattr(struct sk_buff *skb,
293 const struct nf_conntrack_tuple *t)
294{
295 NFA_PUT(skb, CTA_PROTO_ICMP_ID, sizeof(u_int16_t),
296 &t->src.u.icmp.id);
297 NFA_PUT(skb, CTA_PROTO_ICMP_TYPE, sizeof(u_int8_t),
298 &t->dst.u.icmp.type);
299 NFA_PUT(skb, CTA_PROTO_ICMP_CODE, sizeof(u_int8_t),
300 &t->dst.u.icmp.code);
301
302 return 0;
303
304nfattr_failure:
305 return -1;
306}
307
308static const size_t cta_min_proto[CTA_PROTO_MAX] = {
309 [CTA_PROTO_ICMP_TYPE-1] = sizeof(u_int8_t),
310 [CTA_PROTO_ICMP_CODE-1] = sizeof(u_int8_t),
311 [CTA_PROTO_ICMP_ID-1] = sizeof(u_int16_t)
312};
313
314static int icmp_nfattr_to_tuple(struct nfattr *tb[],
315 struct nf_conntrack_tuple *tuple)
316{
317 if (!tb[CTA_PROTO_ICMP_TYPE-1]
318 || !tb[CTA_PROTO_ICMP_CODE-1]
319 || !tb[CTA_PROTO_ICMP_ID-1])
320 return -EINVAL;
321
322 if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
323 return -EINVAL;
324
325 tuple->dst.u.icmp.type =
326 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
327 tuple->dst.u.icmp.code =
328 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
329 tuple->src.u.icmp.id =
330 *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
331
332 if (tuple->dst.u.icmp.type >= sizeof(invmap)
333 || !invmap[tuple->dst.u.icmp.type])
334 return -EINVAL;
335
336 return 0;
337}
338#endif
339
284struct nf_conntrack_protocol nf_conntrack_protocol_icmp = 340struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
285{ 341{
286 .list = { NULL, NULL }, 342 .list = { NULL, NULL },
@@ -295,7 +351,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
295 .new = icmp_new, 351 .new = icmp_new,
296 .error = icmp_error, 352 .error = icmp_error,
297 .destroy = NULL, 353 .destroy = NULL,
298 .me = NULL 354 .me = NULL,
355#if defined(CONFIG_NF_CT_NETLINK) || \
356 defined(CONFIG_NF_CT_NETLINK_MODULE)
357 .tuple_to_nfattr = icmp_tuple_to_nfattr,
358 .nfattr_to_tuple = icmp_nfattr_to_tuple,
359#endif
299}; 360};
300 361
301EXPORT_SYMBOL(nf_conntrack_protocol_icmp); 362EXPORT_SYMBOL(nf_conntrack_protocol_icmp);