aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-14 06:50:43 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-14 06:50:43 -0400
commit334f8b2afd9652e20f67ddee4fec483ed860425b (patch)
tree35d4fb46a9dc145e831fe5da026f2bfd9ee6657c /net/ipv4
parent7477fd2e6b676fcd15861c2a96a7172f71afe0a5 (diff)
parentef1a5a50bbd509b8697dcd4d13017e9e0053867b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6.26
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter.c37
-rw-r--r--net/ipv4/netfilter/Kconfig15
-rw-r--r--net/ipv4/netfilter/Makefile5
-rw-r--r--net/ipv4/netfilter/arp_tables.c66
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c12
-rw-r--r--net/ipv4/netfilter/arptable_filter.c7
-rw-r--r--net/ipv4/netfilter/ip_tables.c35
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c14
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c2
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c9
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c6
-rw-r--r--net/ipv4/netfilter/ipt_recent.c6
-rw-r--r--net/ipv4/netfilter/iptable_filter.c21
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c51
-rw-r--r--net/ipv4/netfilter/iptable_raw.c8
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c70
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c13
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c27
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c61
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c1
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_common.c120
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_dccp.c108
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c45
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c19
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_sctp.c96
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c80
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c77
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udplite.c99
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_unknown.c25
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c25
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c17
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c76
33 files changed, 768 insertions, 487 deletions
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 9a904c6c0dc8..f8edacdf991d 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -182,21 +182,44 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
182 } 182 }
183 return csum; 183 return csum;
184} 184}
185
186EXPORT_SYMBOL(nf_ip_checksum); 185EXPORT_SYMBOL(nf_ip_checksum);
187 186
187static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
188 unsigned int dataoff, unsigned int len,
189 u_int8_t protocol)
190{
191 const struct iphdr *iph = ip_hdr(skb);
192 __sum16 csum = 0;
193
194 switch (skb->ip_summed) {
195 case CHECKSUM_COMPLETE:
196 if (len == skb->len - dataoff)
197 return nf_ip_checksum(skb, hook, dataoff, protocol);
198 /* fall through */
199 case CHECKSUM_NONE:
200 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
201 skb->len - dataoff, 0);
202 skb->ip_summed = CHECKSUM_NONE;
203 csum = __skb_checksum_complete_head(skb, dataoff + len);
204 if (!csum)
205 skb->ip_summed = CHECKSUM_UNNECESSARY;
206 }
207 return csum;
208}
209
188static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) 210static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
189{ 211{
190 return ip_route_output_key(&init_net, (struct rtable **)dst, fl); 212 return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
191} 213}
192 214
193static const struct nf_afinfo nf_ip_afinfo = { 215static const struct nf_afinfo nf_ip_afinfo = {
194 .family = AF_INET, 216 .family = AF_INET,
195 .checksum = nf_ip_checksum, 217 .checksum = nf_ip_checksum,
196 .route = nf_ip_route, 218 .checksum_partial = nf_ip_checksum_partial,
197 .saveroute = nf_ip_saveroute, 219 .route = nf_ip_route,
198 .reroute = nf_ip_reroute, 220 .saveroute = nf_ip_saveroute,
199 .route_key_size = sizeof(struct ip_rt_info), 221 .reroute = nf_ip_reroute,
222 .route_key_size = sizeof(struct ip_rt_info),
200}; 223};
201 224
202static int ipv4_netfilter_init(void) 225static int ipv4_netfilter_init(void)
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 9a077cb24798..0c95cd5872f3 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -241,10 +241,25 @@ config NF_NAT_SNMP_BASIC
241# <expr> '&&' <expr> (6) 241# <expr> '&&' <expr> (6)
242# 242#
243# (6) Returns the result of min(/expr/, /expr/). 243# (6) Returns the result of min(/expr/, /expr/).
244config NF_NAT_PROTO_DCCP
245 tristate
246 depends on NF_NAT && NF_CT_PROTO_DCCP
247 default NF_NAT && NF_CT_PROTO_DCCP
248
244config NF_NAT_PROTO_GRE 249config NF_NAT_PROTO_GRE
245 tristate 250 tristate
246 depends on NF_NAT && NF_CT_PROTO_GRE 251 depends on NF_NAT && NF_CT_PROTO_GRE
247 252
253config NF_NAT_PROTO_UDPLITE
254 tristate
255 depends on NF_NAT && NF_CT_PROTO_UDPLITE
256 default NF_NAT && NF_CT_PROTO_UDPLITE
257
258config NF_NAT_PROTO_SCTP
259 tristate
260 default NF_NAT && NF_CT_PROTO_SCTP
261 depends on NF_NAT && NF_CT_PROTO_SCTP
262
248config NF_NAT_FTP 263config NF_NAT_FTP
249 tristate 264 tristate
250 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT 265 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 0c7dc78a62e9..d9b92fbf5579 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -10,7 +10,7 @@ nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
10endif 10endif
11endif 11endif
12 12
13nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o 13nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_common.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
14iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o 14iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o
15 15
16# connection tracking 16# connection tracking
@@ -29,7 +29,10 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
29obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o 29obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
30 30
31# NAT protocols (nf_nat) 31# NAT protocols (nf_nat)
32obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
32obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 33obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
34obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
35obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
33 36
34# generic IP tables 37# generic IP tables
35obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 38obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 1563f29b5117..03e83a65aec5 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -59,7 +59,7 @@ do { \
59#endif 59#endif
60 60
61static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 61static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
62 char *hdr_addr, int len) 62 const char *hdr_addr, int len)
63{ 63{
64 int i, ret; 64 int i, ret;
65 65
@@ -80,8 +80,8 @@ static inline int arp_packet_match(const struct arphdr *arphdr,
80 const char *outdev, 80 const char *outdev,
81 const struct arpt_arp *arpinfo) 81 const struct arpt_arp *arpinfo)
82{ 82{
83 char *arpptr = (char *)(arphdr + 1); 83 const char *arpptr = (char *)(arphdr + 1);
84 char *src_devaddr, *tgt_devaddr; 84 const char *src_devaddr, *tgt_devaddr;
85 __be32 src_ipaddr, tgt_ipaddr; 85 __be32 src_ipaddr, tgt_ipaddr;
86 int i, ret; 86 int i, ret;
87 87
@@ -222,16 +222,16 @@ unsigned int arpt_do_table(struct sk_buff *skb,
222 unsigned int hook, 222 unsigned int hook,
223 const struct net_device *in, 223 const struct net_device *in,
224 const struct net_device *out, 224 const struct net_device *out,
225 struct arpt_table *table) 225 struct xt_table *table)
226{ 226{
227 static const char nulldevname[IFNAMSIZ]; 227 static const char nulldevname[IFNAMSIZ];
228 unsigned int verdict = NF_DROP; 228 unsigned int verdict = NF_DROP;
229 struct arphdr *arp; 229 const struct arphdr *arp;
230 bool hotdrop = false; 230 bool hotdrop = false;
231 struct arpt_entry *e, *back; 231 struct arpt_entry *e, *back;
232 const char *indev, *outdev; 232 const char *indev, *outdev;
233 void *table_base; 233 void *table_base;
234 struct xt_table_info *private; 234 const struct xt_table_info *private;
235 235
236 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) 236 if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
237 return NF_DROP; 237 return NF_DROP;
@@ -352,7 +352,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
352 e->counters.pcnt = pos; 352 e->counters.pcnt = pos;
353 353
354 for (;;) { 354 for (;;) {
355 struct arpt_standard_target *t 355 const struct arpt_standard_target *t
356 = (void *)arpt_get_target(e); 356 = (void *)arpt_get_target(e);
357 int visited = e->comefrom & (1 << hook); 357 int visited = e->comefrom & (1 << hook);
358 358
@@ -437,7 +437,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
437 437
438static inline int check_entry(struct arpt_entry *e, const char *name) 438static inline int check_entry(struct arpt_entry *e, const char *name)
439{ 439{
440 struct arpt_entry_target *t; 440 const struct arpt_entry_target *t;
441 441
442 if (!arp_checkentry(&e->arp)) { 442 if (!arp_checkentry(&e->arp)) {
443 duprintf("arp_tables: arp check failed %p %s.\n", e, name); 443 duprintf("arp_tables: arp check failed %p %s.\n", e, name);
@@ -457,7 +457,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
457static inline int check_target(struct arpt_entry *e, const char *name) 457static inline int check_target(struct arpt_entry *e, const char *name)
458{ 458{
459 struct arpt_entry_target *t; 459 struct arpt_entry_target *t;
460 struct arpt_target *target; 460 struct xt_target *target;
461 int ret; 461 int ret;
462 462
463 t = arpt_get_target(e); 463 t = arpt_get_target(e);
@@ -480,7 +480,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
480 unsigned int *i) 480 unsigned int *i)
481{ 481{
482 struct arpt_entry_target *t; 482 struct arpt_entry_target *t;
483 struct arpt_target *target; 483 struct xt_target *target;
484 int ret; 484 int ret;
485 485
486 ret = check_entry(e, name); 486 ret = check_entry(e, name);
@@ -706,11 +706,11 @@ static void get_counters(const struct xt_table_info *t,
706 } 706 }
707} 707}
708 708
709static inline struct xt_counters *alloc_counters(struct arpt_table *table) 709static inline struct xt_counters *alloc_counters(struct xt_table *table)
710{ 710{
711 unsigned int countersize; 711 unsigned int countersize;
712 struct xt_counters *counters; 712 struct xt_counters *counters;
713 struct xt_table_info *private = table->private; 713 const struct xt_table_info *private = table->private;
714 714
715 /* We need atomic snapshot of counters: rest doesn't change 715 /* We need atomic snapshot of counters: rest doesn't change
716 * (other than comefrom, which userspace doesn't care 716 * (other than comefrom, which userspace doesn't care
@@ -731,7 +731,7 @@ static inline struct xt_counters *alloc_counters(struct arpt_table *table)
731} 731}
732 732
733static int copy_entries_to_user(unsigned int total_size, 733static int copy_entries_to_user(unsigned int total_size,
734 struct arpt_table *table, 734 struct xt_table *table,
735 void __user *userptr) 735 void __user *userptr)
736{ 736{
737 unsigned int off, num; 737 unsigned int off, num;
@@ -851,7 +851,7 @@ static int compat_table_info(const struct xt_table_info *info,
851static int get_info(struct net *net, void __user *user, int *len, int compat) 851static int get_info(struct net *net, void __user *user, int *len, int compat)
852{ 852{
853 char name[ARPT_TABLE_MAXNAMELEN]; 853 char name[ARPT_TABLE_MAXNAMELEN];
854 struct arpt_table *t; 854 struct xt_table *t;
855 int ret; 855 int ret;
856 856
857 if (*len != sizeof(struct arpt_getinfo)) { 857 if (*len != sizeof(struct arpt_getinfo)) {
@@ -872,7 +872,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
872 "arptable_%s", name); 872 "arptable_%s", name);
873 if (t && !IS_ERR(t)) { 873 if (t && !IS_ERR(t)) {
874 struct arpt_getinfo info; 874 struct arpt_getinfo info;
875 struct xt_table_info *private = t->private; 875 const struct xt_table_info *private = t->private;
876 876
877#ifdef CONFIG_COMPAT 877#ifdef CONFIG_COMPAT
878 if (compat) { 878 if (compat) {
@@ -911,7 +911,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
911{ 911{
912 int ret; 912 int ret;
913 struct arpt_get_entries get; 913 struct arpt_get_entries get;
914 struct arpt_table *t; 914 struct xt_table *t;
915 915
916 if (*len < sizeof(get)) { 916 if (*len < sizeof(get)) {
917 duprintf("get_entries: %u < %Zu\n", *len, sizeof(get)); 917 duprintf("get_entries: %u < %Zu\n", *len, sizeof(get));
@@ -927,7 +927,8 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
927 927
928 t = xt_find_table_lock(net, NF_ARP, get.name); 928 t = xt_find_table_lock(net, NF_ARP, get.name);
929 if (t && !IS_ERR(t)) { 929 if (t && !IS_ERR(t)) {
930 struct xt_table_info *private = t->private; 930 const struct xt_table_info *private = t->private;
931
931 duprintf("t->private->number = %u\n", 932 duprintf("t->private->number = %u\n",
932 private->number); 933 private->number);
933 if (get.size == private->size) 934 if (get.size == private->size)
@@ -936,7 +937,7 @@ static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
936 else { 937 else {
937 duprintf("get_entries: I've got %u not %u!\n", 938 duprintf("get_entries: I've got %u not %u!\n",
938 private->size, get.size); 939 private->size, get.size);
939 ret = -EINVAL; 940 ret = -EAGAIN;
940 } 941 }
941 module_put(t->me); 942 module_put(t->me);
942 xt_table_unlock(t); 943 xt_table_unlock(t);
@@ -953,7 +954,7 @@ static int __do_replace(struct net *net, const char *name,
953 void __user *counters_ptr) 954 void __user *counters_ptr)
954{ 955{
955 int ret; 956 int ret;
956 struct arpt_table *t; 957 struct xt_table *t;
957 struct xt_table_info *oldinfo; 958 struct xt_table_info *oldinfo;
958 struct xt_counters *counters; 959 struct xt_counters *counters;
959 void *loc_cpu_old_entry; 960 void *loc_cpu_old_entry;
@@ -1087,11 +1088,11 @@ static int do_add_counters(struct net *net, void __user *user, unsigned int len,
1087 struct xt_counters_info tmp; 1088 struct xt_counters_info tmp;
1088 struct xt_counters *paddc; 1089 struct xt_counters *paddc;
1089 unsigned int num_counters; 1090 unsigned int num_counters;
1090 char *name; 1091 const char *name;
1091 int size; 1092 int size;
1092 void *ptmp; 1093 void *ptmp;
1093 struct arpt_table *t; 1094 struct xt_table *t;
1094 struct xt_table_info *private; 1095 const struct xt_table_info *private;
1095 int ret = 0; 1096 int ret = 0;
1096 void *loc_cpu_entry; 1097 void *loc_cpu_entry;
1097#ifdef CONFIG_COMPAT 1098#ifdef CONFIG_COMPAT
@@ -1554,11 +1555,11 @@ out:
1554} 1555}
1555 1556
1556static int compat_copy_entries_to_user(unsigned int total_size, 1557static int compat_copy_entries_to_user(unsigned int total_size,
1557 struct arpt_table *table, 1558 struct xt_table *table,
1558 void __user *userptr) 1559 void __user *userptr)
1559{ 1560{
1560 struct xt_counters *counters; 1561 struct xt_counters *counters;
1561 struct xt_table_info *private = table->private; 1562 const struct xt_table_info *private = table->private;
1562 void __user *pos; 1563 void __user *pos;
1563 unsigned int size; 1564 unsigned int size;
1564 int ret = 0; 1565 int ret = 0;
@@ -1592,7 +1593,7 @@ static int compat_get_entries(struct net *net,
1592{ 1593{
1593 int ret; 1594 int ret;
1594 struct compat_arpt_get_entries get; 1595 struct compat_arpt_get_entries get;
1595 struct arpt_table *t; 1596 struct xt_table *t;
1596 1597
1597 if (*len < sizeof(get)) { 1598 if (*len < sizeof(get)) {
1598 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get)); 1599 duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
@@ -1609,7 +1610,7 @@ static int compat_get_entries(struct net *net,
1609 xt_compat_lock(NF_ARP); 1610 xt_compat_lock(NF_ARP);
1610 t = xt_find_table_lock(net, NF_ARP, get.name); 1611 t = xt_find_table_lock(net, NF_ARP, get.name);
1611 if (t && !IS_ERR(t)) { 1612 if (t && !IS_ERR(t)) {
1612 struct xt_table_info *private = t->private; 1613 const struct xt_table_info *private = t->private;
1613 struct xt_table_info info; 1614 struct xt_table_info info;
1614 1615
1615 duprintf("t->private->number = %u\n", private->number); 1616 duprintf("t->private->number = %u\n", private->number);
@@ -1620,7 +1621,7 @@ static int compat_get_entries(struct net *net,
1620 } else if (!ret) { 1621 } else if (!ret) {
1621 duprintf("compat_get_entries: I've got %u not %u!\n", 1622 duprintf("compat_get_entries: I've got %u not %u!\n",
1622 private->size, get.size); 1623 private->size, get.size);
1623 ret = -EINVAL; 1624 ret = -EAGAIN;
1624 } 1625 }
1625 xt_compat_flush_offsets(NF_ARP); 1626 xt_compat_flush_offsets(NF_ARP);
1626 module_put(t->me); 1627 module_put(t->me);
@@ -1722,9 +1723,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
1722 return ret; 1723 return ret;
1723} 1724}
1724 1725
1725struct arpt_table *arpt_register_table(struct net *net, 1726struct xt_table *arpt_register_table(struct net *net, struct xt_table *table,
1726 struct arpt_table *table, 1727 const struct arpt_replace *repl)
1727 const struct arpt_replace *repl)
1728{ 1728{
1729 int ret; 1729 int ret;
1730 struct xt_table_info *newinfo; 1730 struct xt_table_info *newinfo;
@@ -1766,7 +1766,7 @@ out:
1766 return ERR_PTR(ret); 1766 return ERR_PTR(ret);
1767} 1767}
1768 1768
1769void arpt_unregister_table(struct arpt_table *table) 1769void arpt_unregister_table(struct xt_table *table)
1770{ 1770{
1771 struct xt_table_info *private; 1771 struct xt_table_info *private;
1772 void *loc_cpu_entry; 1772 void *loc_cpu_entry;
@@ -1784,7 +1784,7 @@ void arpt_unregister_table(struct arpt_table *table)
1784} 1784}
1785 1785
1786/* The built-in targets: standard (NULL) and error. */ 1786/* The built-in targets: standard (NULL) and error. */
1787static struct arpt_target arpt_standard_target __read_mostly = { 1787static struct xt_target arpt_standard_target __read_mostly = {
1788 .name = ARPT_STANDARD_TARGET, 1788 .name = ARPT_STANDARD_TARGET,
1789 .targetsize = sizeof(int), 1789 .targetsize = sizeof(int),
1790 .family = NF_ARP, 1790 .family = NF_ARP,
@@ -1795,7 +1795,7 @@ static struct arpt_target arpt_standard_target __read_mostly = {
1795#endif 1795#endif
1796}; 1796};
1797 1797
1798static struct arpt_target arpt_error_target __read_mostly = { 1798static struct xt_target arpt_error_target __read_mostly = {
1799 .name = ARPT_ERROR_TARGET, 1799 .name = ARPT_ERROR_TARGET,
1800 .target = arpt_error, 1800 .target = arpt_error,
1801 .targetsize = ARPT_FUNCTION_MAXNAMELEN, 1801 .targetsize = ARPT_FUNCTION_MAXNAMELEN,
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c
index 3f4222b0a803..a385959d2655 100644
--- a/net/ipv4/netfilter/arpt_mangle.c
+++ b/net/ipv4/netfilter/arpt_mangle.c
@@ -15,7 +15,7 @@ target(struct sk_buff *skb,
15 const void *targinfo) 15 const void *targinfo)
16{ 16{
17 const struct arpt_mangle *mangle = targinfo; 17 const struct arpt_mangle *mangle = targinfo;
18 struct arphdr *arp; 18 const struct arphdr *arp;
19 unsigned char *arpptr; 19 unsigned char *arpptr;
20 int pln, hln; 20 int pln, hln;
21 21
@@ -73,8 +73,9 @@ checkentry(const char *tablename, const void *e, const struct xt_target *target,
73 return true; 73 return true;
74} 74}
75 75
76static struct arpt_target arpt_mangle_reg __read_mostly = { 76static struct xt_target arpt_mangle_reg __read_mostly = {
77 .name = "mangle", 77 .name = "mangle",
78 .family = NF_ARP,
78 .target = target, 79 .target = target,
79 .targetsize = sizeof(struct arpt_mangle), 80 .targetsize = sizeof(struct arpt_mangle),
80 .checkentry = checkentry, 81 .checkentry = checkentry,
@@ -83,15 +84,12 @@ static struct arpt_target arpt_mangle_reg __read_mostly = {
83 84
84static int __init arpt_mangle_init(void) 85static int __init arpt_mangle_init(void)
85{ 86{
86 if (arpt_register_target(&arpt_mangle_reg)) 87 return xt_register_target(&arpt_mangle_reg);
87 return -EINVAL;
88
89 return 0;
90} 88}
91 89
92static void __exit arpt_mangle_fini(void) 90static void __exit arpt_mangle_fini(void)
93{ 91{
94 arpt_unregister_target(&arpt_mangle_reg); 92 xt_unregister_target(&arpt_mangle_reg);
95} 93}
96 94
97module_init(arpt_mangle_init); 95module_init(arpt_mangle_init);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 4e9c496a30c2..3be4d07e7ed9 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -45,10 +45,10 @@ static struct
45 .term = ARPT_ERROR_INIT, 45 .term = ARPT_ERROR_INIT,
46}; 46};
47 47
48static struct arpt_table packet_filter = { 48static struct xt_table packet_filter = {
49 .name = "filter", 49 .name = "filter",
50 .valid_hooks = FILTER_VALID_HOOKS, 50 .valid_hooks = FILTER_VALID_HOOKS,
51 .lock = RW_LOCK_UNLOCKED, 51 .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
52 .private = NULL, 52 .private = NULL,
53 .me = THIS_MODULE, 53 .me = THIS_MODULE,
54 .af = NF_ARP, 54 .af = NF_ARP,
@@ -70,18 +70,21 @@ static struct nf_hook_ops arpt_ops[] __read_mostly = {
70 .owner = THIS_MODULE, 70 .owner = THIS_MODULE,
71 .pf = NF_ARP, 71 .pf = NF_ARP,
72 .hooknum = NF_ARP_IN, 72 .hooknum = NF_ARP_IN,
73 .priority = NF_IP_PRI_FILTER,
73 }, 74 },
74 { 75 {
75 .hook = arpt_hook, 76 .hook = arpt_hook,
76 .owner = THIS_MODULE, 77 .owner = THIS_MODULE,
77 .pf = NF_ARP, 78 .pf = NF_ARP,
78 .hooknum = NF_ARP_OUT, 79 .hooknum = NF_ARP_OUT,
80 .priority = NF_IP_PRI_FILTER,
79 }, 81 },
80 { 82 {
81 .hook = arpt_hook, 83 .hook = arpt_hook,
82 .owner = THIS_MODULE, 84 .owner = THIS_MODULE,
83 .pf = NF_ARP, 85 .pf = NF_ARP,
84 .hooknum = NF_ARP_FORWARD, 86 .hooknum = NF_ARP_FORWARD,
87 .priority = NF_IP_PRI_FILTER,
85 }, 88 },
86}; 89};
87 90
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index a819d191e1aa..4e7c719445c2 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -296,7 +296,7 @@ static void trace_packet(struct sk_buff *skb,
296 struct ipt_entry *e) 296 struct ipt_entry *e)
297{ 297{
298 void *table_base; 298 void *table_base;
299 struct ipt_entry *root; 299 const struct ipt_entry *root;
300 char *hookname, *chainname, *comment; 300 char *hookname, *chainname, *comment;
301 unsigned int rulenum = 0; 301 unsigned int rulenum = 0;
302 302
@@ -327,7 +327,7 @@ ipt_do_table(struct sk_buff *skb,
327{ 327{
328 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 328 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
329 u_int16_t offset; 329 u_int16_t offset;
330 struct iphdr *ip; 330 const struct iphdr *ip;
331 u_int16_t datalen; 331 u_int16_t datalen;
332 bool hotdrop = false; 332 bool hotdrop = false;
333 /* Initializing verdict to NF_DROP keeps gcc happy. */ 333 /* Initializing verdict to NF_DROP keeps gcc happy. */
@@ -926,7 +926,7 @@ static struct xt_counters * alloc_counters(struct xt_table *table)
926{ 926{
927 unsigned int countersize; 927 unsigned int countersize;
928 struct xt_counters *counters; 928 struct xt_counters *counters;
929 struct xt_table_info *private = table->private; 929 const struct xt_table_info *private = table->private;
930 930
931 /* We need atomic snapshot of counters: rest doesn't change 931 /* We need atomic snapshot of counters: rest doesn't change
932 (other than comefrom, which userspace doesn't care 932 (other than comefrom, which userspace doesn't care
@@ -953,9 +953,9 @@ copy_entries_to_user(unsigned int total_size,
953 unsigned int off, num; 953 unsigned int off, num;
954 struct ipt_entry *e; 954 struct ipt_entry *e;
955 struct xt_counters *counters; 955 struct xt_counters *counters;
956 struct xt_table_info *private = table->private; 956 const struct xt_table_info *private = table->private;
957 int ret = 0; 957 int ret = 0;
958 void *loc_cpu_entry; 958 const void *loc_cpu_entry;
959 959
960 counters = alloc_counters(table); 960 counters = alloc_counters(table);
961 if (IS_ERR(counters)) 961 if (IS_ERR(counters))
@@ -975,8 +975,8 @@ copy_entries_to_user(unsigned int total_size,
975 /* ... then go back and fix counters and names */ 975 /* ... then go back and fix counters and names */
976 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 976 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
977 unsigned int i; 977 unsigned int i;
978 struct ipt_entry_match *m; 978 const struct ipt_entry_match *m;
979 struct ipt_entry_target *t; 979 const struct ipt_entry_target *t;
980 980
981 e = (struct ipt_entry *)(loc_cpu_entry + off); 981 e = (struct ipt_entry *)(loc_cpu_entry + off);
982 if (copy_to_user(userptr + off 982 if (copy_to_user(userptr + off
@@ -1116,7 +1116,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
1116 "iptable_%s", name); 1116 "iptable_%s", name);
1117 if (t && !IS_ERR(t)) { 1117 if (t && !IS_ERR(t)) {
1118 struct ipt_getinfo info; 1118 struct ipt_getinfo info;
1119 struct xt_table_info *private = t->private; 1119 const struct xt_table_info *private = t->private;
1120 1120
1121#ifdef CONFIG_COMPAT 1121#ifdef CONFIG_COMPAT
1122 if (compat) { 1122 if (compat) {
@@ -1172,7 +1172,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1172 1172
1173 t = xt_find_table_lock(net, AF_INET, get.name); 1173 t = xt_find_table_lock(net, AF_INET, get.name);
1174 if (t && !IS_ERR(t)) { 1174 if (t && !IS_ERR(t)) {
1175 struct xt_table_info *private = t->private; 1175 const struct xt_table_info *private = t->private;
1176 duprintf("t->private->number = %u\n", private->number); 1176 duprintf("t->private->number = %u\n", private->number);
1177 if (get.size == private->size) 1177 if (get.size == private->size)
1178 ret = copy_entries_to_user(private->size, 1178 ret = copy_entries_to_user(private->size,
@@ -1180,7 +1180,7 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len)
1180 else { 1180 else {
1181 duprintf("get_entries: I've got %u not %u!\n", 1181 duprintf("get_entries: I've got %u not %u!\n",
1182 private->size, get.size); 1182 private->size, get.size);
1183 ret = -EINVAL; 1183 ret = -EAGAIN;
1184 } 1184 }
1185 module_put(t->me); 1185 module_put(t->me);
1186 xt_table_unlock(t); 1186 xt_table_unlock(t);
@@ -1337,11 +1337,11 @@ do_add_counters(struct net *net, void __user *user, unsigned int len, int compat
1337 struct xt_counters_info tmp; 1337 struct xt_counters_info tmp;
1338 struct xt_counters *paddc; 1338 struct xt_counters *paddc;
1339 unsigned int num_counters; 1339 unsigned int num_counters;
1340 char *name; 1340 const char *name;
1341 int size; 1341 int size;
1342 void *ptmp; 1342 void *ptmp;
1343 struct xt_table *t; 1343 struct xt_table *t;
1344 struct xt_table_info *private; 1344 const struct xt_table_info *private;
1345 int ret = 0; 1345 int ret = 0;
1346 void *loc_cpu_entry; 1346 void *loc_cpu_entry;
1347#ifdef CONFIG_COMPAT 1347#ifdef CONFIG_COMPAT
@@ -1878,11 +1878,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
1878 void __user *userptr) 1878 void __user *userptr)
1879{ 1879{
1880 struct xt_counters *counters; 1880 struct xt_counters *counters;
1881 struct xt_table_info *private = table->private; 1881 const struct xt_table_info *private = table->private;
1882 void __user *pos; 1882 void __user *pos;
1883 unsigned int size; 1883 unsigned int size;
1884 int ret = 0; 1884 int ret = 0;
1885 void *loc_cpu_entry; 1885 const void *loc_cpu_entry;
1886 unsigned int i = 0; 1886 unsigned int i = 0;
1887 1887
1888 counters = alloc_counters(table); 1888 counters = alloc_counters(table);
@@ -1929,7 +1929,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1929 xt_compat_lock(AF_INET); 1929 xt_compat_lock(AF_INET);
1930 t = xt_find_table_lock(net, AF_INET, get.name); 1930 t = xt_find_table_lock(net, AF_INET, get.name);
1931 if (t && !IS_ERR(t)) { 1931 if (t && !IS_ERR(t)) {
1932 struct xt_table_info *private = t->private; 1932 const struct xt_table_info *private = t->private;
1933 struct xt_table_info info; 1933 struct xt_table_info info;
1934 duprintf("t->private->number = %u\n", private->number); 1934 duprintf("t->private->number = %u\n", private->number);
1935 ret = compat_table_info(private, &info); 1935 ret = compat_table_info(private, &info);
@@ -1939,7 +1939,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
1939 } else if (!ret) { 1939 } else if (!ret) {
1940 duprintf("compat_get_entries: I've got %u not %u!\n", 1940 duprintf("compat_get_entries: I've got %u not %u!\n",
1941 private->size, get.size); 1941 private->size, get.size);
1942 ret = -EINVAL; 1942 ret = -EAGAIN;
1943 } 1943 }
1944 xt_compat_flush_offsets(AF_INET); 1944 xt_compat_flush_offsets(AF_INET);
1945 module_put(t->me); 1945 module_put(t->me);
@@ -2130,7 +2130,8 @@ icmp_match(const struct sk_buff *skb,
2130 unsigned int protoff, 2130 unsigned int protoff,
2131 bool *hotdrop) 2131 bool *hotdrop)
2132{ 2132{
2133 struct icmphdr _icmph, *ic; 2133 const struct icmphdr *ic;
2134 struct icmphdr _icmph;
2134 const struct ipt_icmp *icmpinfo = matchinfo; 2135 const struct ipt_icmp *icmpinfo = matchinfo;
2135 2136
2136 /* Must not be a fragment. */ 2137 /* Must not be a fragment. */
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 380d8daac72b..22d8e7cd9197 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -144,7 +144,7 @@ clusterip_config_init_nodelist(struct clusterip_config *c,
144} 144}
145 145
146static struct clusterip_config * 146static struct clusterip_config *
147clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip, 147clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
148 struct net_device *dev) 148 struct net_device *dev)
149{ 149{
150 struct clusterip_config *c; 150 struct clusterip_config *c;
@@ -333,7 +333,7 @@ clusterip_tg(struct sk_buff *skb, const struct net_device *in,
333 } 333 }
334 334
335#ifdef DEBUG 335#ifdef DEBUG
336 NF_CT_DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 336 nf_ct_dump_tuple_ip(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
337#endif 337#endif
338 pr_debug("hash=%u ct_hash=%u ", hash, ct->mark); 338 pr_debug("hash=%u ct_hash=%u ", hash, ct->mark);
339 if (!clusterip_responsible(cipinfo->config, hash)) { 339 if (!clusterip_responsible(cipinfo->config, hash)) {
@@ -418,7 +418,7 @@ clusterip_tg_check(const char *tablename, const void *e_void,
418/* drop reference count of cluster config when rule is deleted */ 418/* drop reference count of cluster config when rule is deleted */
419static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo) 419static void clusterip_tg_destroy(const struct xt_target *target, void *targinfo)
420{ 420{
421 struct ipt_clusterip_tgt_info *cipinfo = targinfo; 421 const struct ipt_clusterip_tgt_info *cipinfo = targinfo;
422 422
423 /* if no more entries are referencing the config, remove it 423 /* if no more entries are referencing the config, remove it
424 * from the list and destroy the proc entry */ 424 * from the list and destroy the proc entry */
@@ -567,7 +567,7 @@ struct clusterip_seq_position {
567 567
568static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) 568static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
569{ 569{
570 struct proc_dir_entry *pde = s->private; 570 const struct proc_dir_entry *pde = s->private;
571 struct clusterip_config *c = pde->data; 571 struct clusterip_config *c = pde->data;
572 unsigned int weight; 572 unsigned int weight;
573 u_int32_t local_nodes; 573 u_int32_t local_nodes;
@@ -594,7 +594,7 @@ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
594 594
595static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) 595static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos)
596{ 596{
597 struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; 597 struct clusterip_seq_position *idx = v;
598 598
599 *pos = ++idx->pos; 599 *pos = ++idx->pos;
600 if (*pos >= idx->weight) { 600 if (*pos >= idx->weight) {
@@ -613,7 +613,7 @@ static void clusterip_seq_stop(struct seq_file *s, void *v)
613 613
614static int clusterip_seq_show(struct seq_file *s, void *v) 614static int clusterip_seq_show(struct seq_file *s, void *v)
615{ 615{
616 struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; 616 struct clusterip_seq_position *idx = v;
617 617
618 if (idx->pos != 0) 618 if (idx->pos != 0)
619 seq_putc(s, ','); 619 seq_putc(s, ',');
@@ -669,7 +669,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
669{ 669{
670#define PROC_WRITELEN 10 670#define PROC_WRITELEN 10
671 char buffer[PROC_WRITELEN+1]; 671 char buffer[PROC_WRITELEN+1];
672 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); 672 const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
673 struct clusterip_config *c = pde->data; 673 struct clusterip_config *c = pde->data;
674 unsigned long nodenum; 674 unsigned long nodenum;
675 675
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 21395bc2b27f..d60139c134ca 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -100,7 +100,7 @@ ecn_tg_check(const char *tablename, const void *e_void,
100 const struct xt_target *target, void *targinfo, 100 const struct xt_target *target, void *targinfo,
101 unsigned int hook_mask) 101 unsigned int hook_mask)
102{ 102{
103 const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; 103 const struct ipt_ECN_info *einfo = targinfo;
104 const struct ipt_entry *e = e_void; 104 const struct ipt_entry *e = e_void;
105 105
106 if (einfo->operation & IPT_ECN_OP_MASK) { 106 if (einfo->operation & IPT_ECN_OP_MASK) {
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index b38d7850f506..0af14137137b 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -76,7 +76,8 @@ static void dump_packet(const struct nf_loginfo *info,
76 76
77 if ((logflags & IPT_LOG_IPOPT) 77 if ((logflags & IPT_LOG_IPOPT)
78 && ih->ihl * 4 > sizeof(struct iphdr)) { 78 && ih->ihl * 4 > sizeof(struct iphdr)) {
79 unsigned char _opt[4 * 15 - sizeof(struct iphdr)], *op; 79 const unsigned char *op;
80 unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
80 unsigned int i, optsize; 81 unsigned int i, optsize;
81 82
82 optsize = ih->ihl * 4 - sizeof(struct iphdr); 83 optsize = ih->ihl * 4 - sizeof(struct iphdr);
@@ -338,12 +339,16 @@ static void dump_packet(const struct nf_loginfo *info,
338 if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) { 339 if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) {
339 read_lock_bh(&skb->sk->sk_callback_lock); 340 read_lock_bh(&skb->sk->sk_callback_lock);
340 if (skb->sk->sk_socket && skb->sk->sk_socket->file) 341 if (skb->sk->sk_socket && skb->sk->sk_socket->file)
341 printk("UID=%u GID=%u", 342 printk("UID=%u GID=%u ",
342 skb->sk->sk_socket->file->f_uid, 343 skb->sk->sk_socket->file->f_uid,
343 skb->sk->sk_socket->file->f_gid); 344 skb->sk->sk_socket->file->f_gid);
344 read_unlock_bh(&skb->sk->sk_callback_lock); 345 read_unlock_bh(&skb->sk->sk_callback_lock);
345 } 346 }
346 347
348 /* Max length: 16 "MARK=0xFFFFFFFF " */
349 if (!iphoff && skb->mark)
350 printk("MARK=0x%x ", skb->mark);
351
347 /* Proto Max log string length */ 352 /* Proto Max log string length */
348 /* IP: 40+46+6+11+127 = 230 */ 353 /* IP: 40+46+6+11+127 = 230 */
349 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ 354 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 22606e2baa16..2639872849da 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -35,8 +35,10 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv4");
35static void send_reset(struct sk_buff *oldskb, int hook) 35static void send_reset(struct sk_buff *oldskb, int hook)
36{ 36{
37 struct sk_buff *nskb; 37 struct sk_buff *nskb;
38 struct iphdr *oiph, *niph; 38 const struct iphdr *oiph;
39 struct tcphdr _otcph, *oth, *tcph; 39 struct iphdr *niph;
40 const struct tcphdr *oth;
41 struct tcphdr _otcph, *tcph;
40 unsigned int addr_type; 42 unsigned int addr_type;
41 43
42 /* IP header checks: fragment. */ 44 /* IP header checks: fragment. */
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 50e06690eb5b..21cb053f5d7d 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -340,7 +340,7 @@ static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
340static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos) 340static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
341{ 341{
342 struct recent_iter_state *st = seq->private; 342 struct recent_iter_state *st = seq->private;
343 struct recent_table *t = st->table; 343 const struct recent_table *t = st->table;
344 struct recent_entry *e = v; 344 struct recent_entry *e = v;
345 struct list_head *head = e->list.next; 345 struct list_head *head = e->list.next;
346 346
@@ -361,7 +361,7 @@ static void recent_seq_stop(struct seq_file *s, void *v)
361 361
362static int recent_seq_show(struct seq_file *seq, void *v) 362static int recent_seq_show(struct seq_file *seq, void *v)
363{ 363{
364 struct recent_entry *e = v; 364 const struct recent_entry *e = v;
365 unsigned int i; 365 unsigned int i;
366 366
367 i = (e->index - 1) % ip_pkt_list_tot; 367 i = (e->index - 1) % ip_pkt_list_tot;
@@ -396,7 +396,7 @@ static int recent_seq_open(struct inode *inode, struct file *file)
396static ssize_t recent_proc_write(struct file *file, const char __user *input, 396static ssize_t recent_proc_write(struct file *file, const char __user *input,
397 size_t size, loff_t *loff) 397 size_t size, loff_t *loff)
398{ 398{
399 struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); 399 const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
400 struct recent_table *t = pde->data; 400 struct recent_table *t = pde->data;
401 struct recent_entry *e; 401 struct recent_entry *e;
402 char buf[sizeof("+255.255.255.255")], *c = buf; 402 char buf[sizeof("+255.255.255.255")], *c = buf;
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 69f3d7e6e96f..1ea677dcf845 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -56,20 +56,32 @@ static struct
56static struct xt_table packet_filter = { 56static struct xt_table packet_filter = {
57 .name = "filter", 57 .name = "filter",
58 .valid_hooks = FILTER_VALID_HOOKS, 58 .valid_hooks = FILTER_VALID_HOOKS,
59 .lock = RW_LOCK_UNLOCKED, 59 .lock = __RW_LOCK_UNLOCKED(packet_filter.lock),
60 .me = THIS_MODULE, 60 .me = THIS_MODULE,
61 .af = AF_INET, 61 .af = AF_INET,
62}; 62};
63 63
64/* The work comes in here from netfilter.c. */ 64/* The work comes in here from netfilter.c. */
65static unsigned int 65static unsigned int
66ipt_local_in_hook(unsigned int hook,
67 struct sk_buff *skb,
68 const struct net_device *in,
69 const struct net_device *out,
70 int (*okfn)(struct sk_buff *))
71{
72 return ipt_do_table(skb, hook, in, out,
73 nf_local_in_net(in, out)->ipv4.iptable_filter);
74}
75
76static unsigned int
66ipt_hook(unsigned int hook, 77ipt_hook(unsigned int hook,
67 struct sk_buff *skb, 78 struct sk_buff *skb,
68 const struct net_device *in, 79 const struct net_device *in,
69 const struct net_device *out, 80 const struct net_device *out,
70 int (*okfn)(struct sk_buff *)) 81 int (*okfn)(struct sk_buff *))
71{ 82{
72 return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter); 83 return ipt_do_table(skb, hook, in, out,
84 nf_forward_net(in, out)->ipv4.iptable_filter);
73} 85}
74 86
75static unsigned int 87static unsigned int
@@ -88,12 +100,13 @@ ipt_local_out_hook(unsigned int hook,
88 return NF_ACCEPT; 100 return NF_ACCEPT;
89 } 101 }
90 102
91 return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_filter); 103 return ipt_do_table(skb, hook, in, out,
104 nf_local_out_net(in, out)->ipv4.iptable_filter);
92} 105}
93 106
94static struct nf_hook_ops ipt_ops[] __read_mostly = { 107static struct nf_hook_ops ipt_ops[] __read_mostly = {
95 { 108 {
96 .hook = ipt_hook, 109 .hook = ipt_local_in_hook,
97 .owner = THIS_MODULE, 110 .owner = THIS_MODULE,
98 .pf = PF_INET, 111 .pf = PF_INET,
99 .hooknum = NF_INET_LOCAL_IN, 112 .hooknum = NF_INET_LOCAL_IN,
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index c55a210853a7..da59182f2226 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -67,20 +67,54 @@ static struct
67static struct xt_table packet_mangler = { 67static struct xt_table packet_mangler = {
68 .name = "mangle", 68 .name = "mangle",
69 .valid_hooks = MANGLE_VALID_HOOKS, 69 .valid_hooks = MANGLE_VALID_HOOKS,
70 .lock = RW_LOCK_UNLOCKED, 70 .lock = __RW_LOCK_UNLOCKED(packet_mangler.lock),
71 .me = THIS_MODULE, 71 .me = THIS_MODULE,
72 .af = AF_INET, 72 .af = AF_INET,
73}; 73};
74 74
75/* The work comes in here from netfilter.c. */ 75/* The work comes in here from netfilter.c. */
76static unsigned int 76static unsigned int
77ipt_route_hook(unsigned int hook, 77ipt_pre_routing_hook(unsigned int hook,
78 struct sk_buff *skb,
79 const struct net_device *in,
80 const struct net_device *out,
81 int (*okfn)(struct sk_buff *))
82{
83 return ipt_do_table(skb, hook, in, out,
84 nf_pre_routing_net(in, out)->ipv4.iptable_mangle);
85}
86
87static unsigned int
88ipt_post_routing_hook(unsigned int hook,
89 struct sk_buff *skb,
90 const struct net_device *in,
91 const struct net_device *out,
92 int (*okfn)(struct sk_buff *))
93{
94 return ipt_do_table(skb, hook, in, out,
95 nf_post_routing_net(in, out)->ipv4.iptable_mangle);
96}
97
98static unsigned int
99ipt_local_in_hook(unsigned int hook,
100 struct sk_buff *skb,
101 const struct net_device *in,
102 const struct net_device *out,
103 int (*okfn)(struct sk_buff *))
104{
105 return ipt_do_table(skb, hook, in, out,
106 nf_local_in_net(in, out)->ipv4.iptable_mangle);
107}
108
109static unsigned int
110ipt_forward_hook(unsigned int hook,
78 struct sk_buff *skb, 111 struct sk_buff *skb,
79 const struct net_device *in, 112 const struct net_device *in,
80 const struct net_device *out, 113 const struct net_device *out,
81 int (*okfn)(struct sk_buff *)) 114 int (*okfn)(struct sk_buff *))
82{ 115{
83 return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); 116 return ipt_do_table(skb, hook, in, out,
117 nf_forward_net(in, out)->ipv4.iptable_mangle);
84} 118}
85 119
86static unsigned int 120static unsigned int
@@ -112,7 +146,8 @@ ipt_local_hook(unsigned int hook,
112 daddr = iph->daddr; 146 daddr = iph->daddr;
113 tos = iph->tos; 147 tos = iph->tos;
114 148
115 ret = ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_mangle); 149 ret = ipt_do_table(skb, hook, in, out,
150 nf_local_out_net(in, out)->ipv4.iptable_mangle);
116 /* Reroute for ANY change. */ 151 /* Reroute for ANY change. */
117 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { 152 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
118 iph = ip_hdr(skb); 153 iph = ip_hdr(skb);
@@ -130,21 +165,21 @@ ipt_local_hook(unsigned int hook,
130 165
131static struct nf_hook_ops ipt_ops[] __read_mostly = { 166static struct nf_hook_ops ipt_ops[] __read_mostly = {
132 { 167 {
133 .hook = ipt_route_hook, 168 .hook = ipt_pre_routing_hook,
134 .owner = THIS_MODULE, 169 .owner = THIS_MODULE,
135 .pf = PF_INET, 170 .pf = PF_INET,
136 .hooknum = NF_INET_PRE_ROUTING, 171 .hooknum = NF_INET_PRE_ROUTING,
137 .priority = NF_IP_PRI_MANGLE, 172 .priority = NF_IP_PRI_MANGLE,
138 }, 173 },
139 { 174 {
140 .hook = ipt_route_hook, 175 .hook = ipt_local_in_hook,
141 .owner = THIS_MODULE, 176 .owner = THIS_MODULE,
142 .pf = PF_INET, 177 .pf = PF_INET,
143 .hooknum = NF_INET_LOCAL_IN, 178 .hooknum = NF_INET_LOCAL_IN,
144 .priority = NF_IP_PRI_MANGLE, 179 .priority = NF_IP_PRI_MANGLE,
145 }, 180 },
146 { 181 {
147 .hook = ipt_route_hook, 182 .hook = ipt_forward_hook,
148 .owner = THIS_MODULE, 183 .owner = THIS_MODULE,
149 .pf = PF_INET, 184 .pf = PF_INET,
150 .hooknum = NF_INET_FORWARD, 185 .hooknum = NF_INET_FORWARD,
@@ -158,7 +193,7 @@ static struct nf_hook_ops ipt_ops[] __read_mostly = {
158 .priority = NF_IP_PRI_MANGLE, 193 .priority = NF_IP_PRI_MANGLE,
159 }, 194 },
160 { 195 {
161 .hook = ipt_route_hook, 196 .hook = ipt_post_routing_hook,
162 .owner = THIS_MODULE, 197 .owner = THIS_MODULE,
163 .pf = PF_INET, 198 .pf = PF_INET,
164 .hooknum = NF_INET_POST_ROUTING, 199 .hooknum = NF_INET_POST_ROUTING,
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index e41fe8ca4e1c..fddce7754b72 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -39,7 +39,7 @@ static struct
39static struct xt_table packet_raw = { 39static struct xt_table packet_raw = {
40 .name = "raw", 40 .name = "raw",
41 .valid_hooks = RAW_VALID_HOOKS, 41 .valid_hooks = RAW_VALID_HOOKS,
42 .lock = RW_LOCK_UNLOCKED, 42 .lock = __RW_LOCK_UNLOCKED(packet_raw.lock),
43 .me = THIS_MODULE, 43 .me = THIS_MODULE,
44 .af = AF_INET, 44 .af = AF_INET,
45}; 45};
@@ -52,7 +52,8 @@ ipt_hook(unsigned int hook,
52 const struct net_device *out, 52 const struct net_device *out,
53 int (*okfn)(struct sk_buff *)) 53 int (*okfn)(struct sk_buff *))
54{ 54{
55 return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw); 55 return ipt_do_table(skb, hook, in, out,
56 nf_pre_routing_net(in, out)->ipv4.iptable_raw);
56} 57}
57 58
58static unsigned int 59static unsigned int
@@ -70,7 +71,8 @@ ipt_local_hook(unsigned int hook,
70 "packet.\n"); 71 "packet.\n");
71 return NF_ACCEPT; 72 return NF_ACCEPT;
72 } 73 }
73 return ipt_do_table(skb, hook, in, out, init_net.ipv4.iptable_raw); 74 return ipt_do_table(skb, hook, in, out,
75 nf_local_out_net(in, out)->ipv4.iptable_raw);
74} 76}
75 77
76/* 'raw' is the very first table. */ 78/* 'raw' is the very first table. */
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index a65b845c5f15..cacb9cb27dab 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -23,30 +23,36 @@
23#include <net/netfilter/nf_conntrack_l3proto.h> 23#include <net/netfilter/nf_conntrack_l3proto.h>
24#include <net/netfilter/nf_conntrack_core.h> 24#include <net/netfilter/nf_conntrack_core.h>
25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
26#include <net/netfilter/nf_nat_helper.h>
26 27
27static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 28int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
28 struct nf_conntrack_tuple *tuple) 29 struct nf_conn *ct,
30 enum ip_conntrack_info ctinfo);
31EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
32
33static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
34 struct nf_conntrack_tuple *tuple)
29{ 35{
30 const __be32 *ap; 36 const __be32 *ap;
31 __be32 _addrs[2]; 37 __be32 _addrs[2];
32 ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), 38 ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
33 sizeof(u_int32_t) * 2, _addrs); 39 sizeof(u_int32_t) * 2, _addrs);
34 if (ap == NULL) 40 if (ap == NULL)
35 return 0; 41 return false;
36 42
37 tuple->src.u3.ip = ap[0]; 43 tuple->src.u3.ip = ap[0];
38 tuple->dst.u3.ip = ap[1]; 44 tuple->dst.u3.ip = ap[1];
39 45
40 return 1; 46 return true;
41} 47}
42 48
43static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple, 49static bool ipv4_invert_tuple(struct nf_conntrack_tuple *tuple,
44 const struct nf_conntrack_tuple *orig) 50 const struct nf_conntrack_tuple *orig)
45{ 51{
46 tuple->src.u3.ip = orig->dst.u3.ip; 52 tuple->src.u3.ip = orig->dst.u3.ip;
47 tuple->dst.u3.ip = orig->src.u3.ip; 53 tuple->dst.u3.ip = orig->src.u3.ip;
48 54
49 return 1; 55 return true;
50} 56}
51 57
52static int ipv4_print_tuple(struct seq_file *s, 58static int ipv4_print_tuple(struct seq_file *s,
@@ -101,35 +107,41 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
101 const struct net_device *out, 107 const struct net_device *out,
102 int (*okfn)(struct sk_buff *)) 108 int (*okfn)(struct sk_buff *))
103{ 109{
104 /* We've seen it coming out the other side: confirm it */
105 return nf_conntrack_confirm(skb);
106}
107
108static unsigned int ipv4_conntrack_help(unsigned int hooknum,
109 struct sk_buff *skb,
110 const struct net_device *in,
111 const struct net_device *out,
112 int (*okfn)(struct sk_buff *))
113{
114 struct nf_conn *ct; 110 struct nf_conn *ct;
115 enum ip_conntrack_info ctinfo; 111 enum ip_conntrack_info ctinfo;
116 const struct nf_conn_help *help; 112 const struct nf_conn_help *help;
117 const struct nf_conntrack_helper *helper; 113 const struct nf_conntrack_helper *helper;
114 unsigned int ret;
118 115
119 /* This is where we call the helper: as the packet goes out. */ 116 /* This is where we call the helper: as the packet goes out. */
120 ct = nf_ct_get(skb, &ctinfo); 117 ct = nf_ct_get(skb, &ctinfo);
121 if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) 118 if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
122 return NF_ACCEPT; 119 goto out;
123 120
124 help = nfct_help(ct); 121 help = nfct_help(ct);
125 if (!help) 122 if (!help)
126 return NF_ACCEPT; 123 goto out;
124
127 /* rcu_read_lock()ed by nf_hook_slow */ 125 /* rcu_read_lock()ed by nf_hook_slow */
128 helper = rcu_dereference(help->helper); 126 helper = rcu_dereference(help->helper);
129 if (!helper) 127 if (!helper)
130 return NF_ACCEPT; 128 goto out;
131 return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb), 129
132 ct, ctinfo); 130 ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
131 ct, ctinfo);
132 if (ret != NF_ACCEPT)
133 return ret;
134
135 if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
136 typeof(nf_nat_seq_adjust_hook) seq_adjust;
137
138 seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
139 if (!seq_adjust || !seq_adjust(skb, ct, ctinfo))
140 return NF_DROP;
141 }
142out:
143 /* We've seen it coming out the other side: confirm it */
144 return nf_conntrack_confirm(skb);
133} 145}
134 146
135static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 147static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -211,20 +223,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
211 .priority = NF_IP_PRI_CONNTRACK, 223 .priority = NF_IP_PRI_CONNTRACK,
212 }, 224 },
213 { 225 {
214 .hook = ipv4_conntrack_help,
215 .owner = THIS_MODULE,
216 .pf = PF_INET,
217 .hooknum = NF_INET_POST_ROUTING,
218 .priority = NF_IP_PRI_CONNTRACK_HELPER,
219 },
220 {
221 .hook = ipv4_conntrack_help,
222 .owner = THIS_MODULE,
223 .pf = PF_INET,
224 .hooknum = NF_INET_LOCAL_IN,
225 .priority = NF_IP_PRI_CONNTRACK_HELPER,
226 },
227 {
228 .hook = ipv4_confirm, 226 .hook = ipv4_confirm,
229 .owner = THIS_MODULE, 227 .owner = THIS_MODULE,
230 .pf = PF_INET, 228 .pf = PF_INET,
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index e60b885d2dcd..40a46d482490 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -106,21 +106,16 @@ static int ct_seq_show(struct seq_file *s, void *v)
106 /* we only want to print DIR_ORIGINAL */ 106 /* we only want to print DIR_ORIGINAL */
107 if (NF_CT_DIRECTION(hash)) 107 if (NF_CT_DIRECTION(hash))
108 return 0; 108 return 0;
109 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET) 109 if (nf_ct_l3num(ct) != AF_INET)
110 return 0; 110 return 0;
111 111
112 l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] 112 l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
113 .tuple.src.l3num);
114 NF_CT_ASSERT(l3proto); 113 NF_CT_ASSERT(l3proto);
115 l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL] 114 l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
116 .tuple.src.l3num,
117 ct->tuplehash[IP_CT_DIR_ORIGINAL]
118 .tuple.dst.protonum);
119 NF_CT_ASSERT(l4proto); 115 NF_CT_ASSERT(l4proto);
120 116
121 if (seq_printf(s, "%-8s %u %ld ", 117 if (seq_printf(s, "%-8s %u %ld ",
122 l4proto->name, 118 l4proto->name, nf_ct_protonum(ct),
123 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
124 timer_pending(&ct->timeout) 119 timer_pending(&ct->timeout)
125 ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0) 120 ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
126 return -ENOSPC; 121 return -ENOSPC;
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 6873fddb3529..78ab19accace 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -22,22 +22,21 @@
22 22
23static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; 23static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
24 24
25static int icmp_pkt_to_tuple(const struct sk_buff *skb, 25static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
26 unsigned int dataoff, 26 struct nf_conntrack_tuple *tuple)
27 struct nf_conntrack_tuple *tuple)
28{ 27{
29 const struct icmphdr *hp; 28 const struct icmphdr *hp;
30 struct icmphdr _hdr; 29 struct icmphdr _hdr;
31 30
32 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); 31 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
33 if (hp == NULL) 32 if (hp == NULL)
34 return 0; 33 return false;
35 34
36 tuple->dst.u.icmp.type = hp->type; 35 tuple->dst.u.icmp.type = hp->type;
37 tuple->src.u.icmp.id = hp->un.echo.id; 36 tuple->src.u.icmp.id = hp->un.echo.id;
38 tuple->dst.u.icmp.code = hp->code; 37 tuple->dst.u.icmp.code = hp->code;
39 38
40 return 1; 39 return true;
41} 40}
42 41
43/* Add 1; spaces filled with 0. */ 42/* Add 1; spaces filled with 0. */
@@ -52,17 +51,17 @@ static const u_int8_t invmap[] = {
52 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 51 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
53}; 52};
54 53
55static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple, 54static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
56 const struct nf_conntrack_tuple *orig) 55 const struct nf_conntrack_tuple *orig)
57{ 56{
58 if (orig->dst.u.icmp.type >= sizeof(invmap) 57 if (orig->dst.u.icmp.type >= sizeof(invmap)
59 || !invmap[orig->dst.u.icmp.type]) 58 || !invmap[orig->dst.u.icmp.type])
60 return 0; 59 return false;
61 60
62 tuple->src.u.icmp.id = orig->src.u.icmp.id; 61 tuple->src.u.icmp.id = orig->src.u.icmp.id;
63 tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1; 62 tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1;
64 tuple->dst.u.icmp.code = orig->dst.u.icmp.code; 63 tuple->dst.u.icmp.code = orig->dst.u.icmp.code;
65 return 1; 64 return true;
66} 65}
67 66
68/* Print out the per-protocol part of the tuple. */ 67/* Print out the per-protocol part of the tuple. */
@@ -101,8 +100,8 @@ static int icmp_packet(struct nf_conn *ct,
101} 100}
102 101
103/* Called when a new connection for this protocol found. */ 102/* Called when a new connection for this protocol found. */
104static int icmp_new(struct nf_conn *ct, 103static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
105 const struct sk_buff *skb, unsigned int dataoff) 104 unsigned int dataoff)
106{ 105{
107 static const u_int8_t valid_new[] = { 106 static const u_int8_t valid_new[] = {
108 [ICMP_ECHO] = 1, 107 [ICMP_ECHO] = 1,
@@ -116,11 +115,11 @@ static int icmp_new(struct nf_conn *ct,
116 /* Can't create a new ICMP `conn' with this. */ 115 /* Can't create a new ICMP `conn' with this. */
117 pr_debug("icmp: can't create new conn with type %u\n", 116 pr_debug("icmp: can't create new conn with type %u\n",
118 ct->tuplehash[0].tuple.dst.u.icmp.type); 117 ct->tuplehash[0].tuple.dst.u.icmp.type);
119 NF_CT_DUMP_TUPLE(&ct->tuplehash[0].tuple); 118 nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
120 return 0; 119 return false;
121 } 120 }
122 atomic_set(&ct->proto.icmp.count, 0); 121 atomic_set(&ct->proto.icmp.count, 0);
123 return 1; 122 return true;
124} 123}
125 124
126/* Returns conntrack if it dealt with ICMP, and filled in skb fields */ 125/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 36b4e3bb056f..04578593e100 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -150,9 +150,9 @@ find_appropriate_src(const struct nf_conntrack_tuple *tuple,
150 const struct nf_nat_range *range) 150 const struct nf_nat_range *range)
151{ 151{
152 unsigned int h = hash_by_src(tuple); 152 unsigned int h = hash_by_src(tuple);
153 struct nf_conn_nat *nat; 153 const struct nf_conn_nat *nat;
154 struct nf_conn *ct; 154 const struct nf_conn *ct;
155 struct hlist_node *n; 155 const struct hlist_node *n;
156 156
157 rcu_read_lock(); 157 rcu_read_lock();
158 hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) { 158 hlist_for_each_entry_rcu(nat, n, &bysource[h], bysource) {
@@ -349,7 +349,7 @@ nf_nat_setup_info(struct nf_conn *ct,
349EXPORT_SYMBOL(nf_nat_setup_info); 349EXPORT_SYMBOL(nf_nat_setup_info);
350 350
351/* Returns true if succeeded. */ 351/* Returns true if succeeded. */
352static int 352static bool
353manip_pkt(u_int16_t proto, 353manip_pkt(u_int16_t proto,
354 struct sk_buff *skb, 354 struct sk_buff *skb,
355 unsigned int iphdroff, 355 unsigned int iphdroff,
@@ -360,7 +360,7 @@ manip_pkt(u_int16_t proto,
360 const struct nf_nat_protocol *p; 360 const struct nf_nat_protocol *p;
361 361
362 if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) 362 if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
363 return 0; 363 return false;
364 364
365 iph = (void *)skb->data + iphdroff; 365 iph = (void *)skb->data + iphdroff;
366 366
@@ -369,7 +369,7 @@ manip_pkt(u_int16_t proto,
369 /* rcu_read_lock()ed by nf_hook_slow */ 369 /* rcu_read_lock()ed by nf_hook_slow */
370 p = __nf_nat_proto_find(proto); 370 p = __nf_nat_proto_find(proto);
371 if (!p->manip_pkt(skb, iphdroff, target, maniptype)) 371 if (!p->manip_pkt(skb, iphdroff, target, maniptype))
372 return 0; 372 return false;
373 373
374 iph = (void *)skb->data + iphdroff; 374 iph = (void *)skb->data + iphdroff;
375 375
@@ -380,7 +380,7 @@ manip_pkt(u_int16_t proto,
380 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); 380 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
381 iph->daddr = target->dst.u3.ip; 381 iph->daddr = target->dst.u3.ip;
382 } 382 }
383 return 1; 383 return true;
384} 384}
385 385
386/* Do packet manipulations according to nf_nat_setup_info. */ 386/* Do packet manipulations according to nf_nat_setup_info. */
@@ -426,7 +426,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
426 struct icmphdr icmp; 426 struct icmphdr icmp;
427 struct iphdr ip; 427 struct iphdr ip;
428 } *inside; 428 } *inside;
429 struct nf_conntrack_l4proto *l4proto; 429 const struct nf_conntrack_l4proto *l4proto;
430 struct nf_conntrack_tuple inner, target; 430 struct nf_conntrack_tuple inner, target;
431 int hdrlen = ip_hdrlen(skb); 431 int hdrlen = ip_hdrlen(skb);
432 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 432 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@@ -544,46 +544,6 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto)
544} 544}
545EXPORT_SYMBOL(nf_nat_protocol_unregister); 545EXPORT_SYMBOL(nf_nat_protocol_unregister);
546 546
547#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
548int
549nf_nat_port_range_to_nlattr(struct sk_buff *skb,
550 const struct nf_nat_range *range)
551{
552 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.tcp.port);
553 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.tcp.port);
554
555 return 0;
556
557nla_put_failure:
558 return -1;
559}
560EXPORT_SYMBOL_GPL(nf_nat_port_nlattr_to_range);
561
562int
563nf_nat_port_nlattr_to_range(struct nlattr *tb[], struct nf_nat_range *range)
564{
565 int ret = 0;
566
567 /* we have to return whether we actually parsed something or not */
568
569 if (tb[CTA_PROTONAT_PORT_MIN]) {
570 ret = 1;
571 range->min.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
572 }
573
574 if (!tb[CTA_PROTONAT_PORT_MAX]) {
575 if (ret)
576 range->max.tcp.port = range->min.tcp.port;
577 } else {
578 ret = 1;
579 range->max.tcp.port = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
580 }
581
582 return ret;
583}
584EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nlattr);
585#endif
586
587/* Noone using conntrack by the time this called. */ 547/* Noone using conntrack by the time this called. */
588static void nf_nat_cleanup_conntrack(struct nf_conn *ct) 548static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
589{ 549{
@@ -660,6 +620,9 @@ static int __init nf_nat_init(void)
660 nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK; 620 nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
661 621
662 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); 622 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
623
624 BUG_ON(nf_nat_seq_adjust_hook != NULL);
625 rcu_assign_pointer(nf_nat_seq_adjust_hook, nf_nat_seq_adjust);
663 return 0; 626 return 0;
664 627
665 cleanup_extend: 628 cleanup_extend:
@@ -686,6 +649,8 @@ static void __exit nf_nat_cleanup(void)
686 nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size); 649 nf_ct_free_hashtable(bysource, nf_nat_vmalloced, nf_nat_htable_size);
687 nf_ct_l3proto_put(l3proto); 650 nf_ct_l3proto_put(l3proto);
688 nf_ct_extend_unregister(&nat_extend); 651 nf_ct_extend_unregister(&nat_extend);
652 rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
653 synchronize_net();
689} 654}
690 655
691MODULE_LICENSE("GPL"); 656MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 2fca727aa8ba..11976ea29884 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -416,7 +416,6 @@ nf_nat_seq_adjust(struct sk_buff *skb,
416 416
417 return 1; 417 return 1;
418} 418}
419EXPORT_SYMBOL(nf_nat_seq_adjust);
420 419
421/* Setup NAT on this expected conntrack so it follows master. */ 420/* Setup NAT on this expected conntrack so it follows master. */
422/* If we fail to get a free NAT slot, we'll get dropped on confirm */ 421/* If we fail to get a free NAT slot, we'll get dropped on confirm */
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 3a1e6d6afc0a..da3d91a5ef5c 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -72,7 +72,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
72 } 72 }
73 73
74 pr_debug("trying to unexpect other dir: "); 74 pr_debug("trying to unexpect other dir: ");
75 NF_CT_DUMP_TUPLE(&t); 75 nf_ct_dump_tuple_ip(&t);
76 other_exp = nf_ct_expect_find_get(&t); 76 other_exp = nf_ct_expect_find_get(&t);
77 if (other_exp) { 77 if (other_exp) {
78 nf_ct_unexpect_related(other_exp); 78 nf_ct_unexpect_related(other_exp);
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
new file mode 100644
index 000000000000..91537f11273f
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_common.c
@@ -0,0 +1,120 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 * (C) 2008 Patrick McHardy <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/types.h>
11#include <linux/random.h>
12#include <linux/ip.h>
13
14#include <linux/netfilter.h>
15#include <net/netfilter/nf_nat.h>
16#include <net/netfilter/nf_nat_core.h>
17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_nat_protocol.h>
19
20bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
21 enum nf_nat_manip_type maniptype,
22 const union nf_conntrack_man_proto *min,
23 const union nf_conntrack_man_proto *max)
24{
25 __be16 port;
26
27 if (maniptype == IP_NAT_MANIP_SRC)
28 port = tuple->src.u.all;
29 else
30 port = tuple->dst.u.all;
31
32 return ntohs(port) >= ntohs(min->all) &&
33 ntohs(port) <= ntohs(max->all);
34}
35EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
36
37bool nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
38 const struct nf_nat_range *range,
39 enum nf_nat_manip_type maniptype,
40 const struct nf_conn *ct,
41 u_int16_t *rover)
42{
43 unsigned int range_size, min, i;
44 __be16 *portptr;
45 u_int16_t off;
46
47 if (maniptype == IP_NAT_MANIP_SRC)
48 portptr = &tuple->src.u.all;
49 else
50 portptr = &tuple->dst.u.all;
51
52 /* If no range specified... */
53 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
54 /* If it's dst rewrite, can't change port */
55 if (maniptype == IP_NAT_MANIP_DST)
56 return false;
57
58 if (ntohs(*portptr) < 1024) {
59 /* Loose convention: >> 512 is credential passing */
60 if (ntohs(*portptr) < 512) {
61 min = 1;
62 range_size = 511 - min + 1;
63 } else {
64 min = 600;
65 range_size = 1023 - min + 1;
66 }
67 } else {
68 min = 1024;
69 range_size = 65535 - 1024 + 1;
70 }
71 } else {
72 min = ntohs(range->min.all);
73 range_size = ntohs(range->max.all) - min + 1;
74 }
75
76 off = *rover;
77 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
78 off = net_random();
79
80 for (i = 0; i < range_size; i++, off++) {
81 *portptr = htons(min + off % range_size);
82 if (nf_nat_used_tuple(tuple, ct))
83 continue;
84 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
85 *rover = off;
86 return true;
87 }
88 return false;
89}
90EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
91
92#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
93int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
94 const struct nf_nat_range *range)
95{
96 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all);
97 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all);
98 return 0;
99
100nla_put_failure:
101 return -1;
102}
103EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
104
105int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
106 struct nf_nat_range *range)
107{
108 if (tb[CTA_PROTONAT_PORT_MIN]) {
109 range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
110 range->max.all = range->min.tcp.port;
111 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
112 }
113 if (tb[CTA_PROTONAT_PORT_MAX]) {
114 range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
115 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
116 }
117 return 0;
118}
119EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr);
120#endif
diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c
new file mode 100644
index 000000000000..22485ce306d4
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c
@@ -0,0 +1,108 @@
1/*
2 * DCCP NAT protocol helper
3 *
4 * Copyright (c) 2005, 2006. 2008 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/skbuff.h>
16#include <linux/ip.h>
17#include <linux/dccp.h>
18
19#include <net/netfilter/nf_conntrack.h>
20#include <net/netfilter/nf_nat.h>
21#include <net/netfilter/nf_nat_protocol.h>
22
23static u_int16_t dccp_port_rover;
24
25static bool
26dccp_unique_tuple(struct nf_conntrack_tuple *tuple,
27 const struct nf_nat_range *range,
28 enum nf_nat_manip_type maniptype,
29 const struct nf_conn *ct)
30{
31 return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
32 &dccp_port_rover);
33}
34
35static bool
36dccp_manip_pkt(struct sk_buff *skb,
37 unsigned int iphdroff,
38 const struct nf_conntrack_tuple *tuple,
39 enum nf_nat_manip_type maniptype)
40{
41 const struct iphdr *iph = (const void *)(skb->data + iphdroff);
42 struct dccp_hdr *hdr;
43 unsigned int hdroff = iphdroff + iph->ihl * 4;
44 __be32 oldip, newip;
45 __be16 *portptr, oldport, newport;
46 int hdrsize = 8; /* DCCP connection tracking guarantees this much */
47
48 if (skb->len >= hdroff + sizeof(struct dccp_hdr))
49 hdrsize = sizeof(struct dccp_hdr);
50
51 if (!skb_make_writable(skb, hdroff + hdrsize))
52 return false;
53
54 iph = (struct iphdr *)(skb->data + iphdroff);
55 hdr = (struct dccp_hdr *)(skb->data + hdroff);
56
57 if (maniptype == IP_NAT_MANIP_SRC) {
58 oldip = iph->saddr;
59 newip = tuple->src.u3.ip;
60 newport = tuple->src.u.dccp.port;
61 portptr = &hdr->dccph_sport;
62 } else {
63 oldip = iph->daddr;
64 newip = tuple->dst.u3.ip;
65 newport = tuple->dst.u.dccp.port;
66 portptr = &hdr->dccph_dport;
67 }
68
69 oldport = *portptr;
70 *portptr = newport;
71
72 if (hdrsize < sizeof(*hdr))
73 return true;
74
75 inet_proto_csum_replace4(&hdr->dccph_checksum, skb, oldip, newip, 1);
76 inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
77 0);
78 return true;
79}
80
81static const struct nf_nat_protocol nf_nat_protocol_dccp = {
82 .protonum = IPPROTO_DCCP,
83 .me = THIS_MODULE,
84 .manip_pkt = dccp_manip_pkt,
85 .in_range = nf_nat_proto_in_range,
86 .unique_tuple = dccp_unique_tuple,
87#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
88 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
89 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
90#endif
91};
92
93static int __init nf_nat_proto_dccp_init(void)
94{
95 return nf_nat_protocol_register(&nf_nat_protocol_dccp);
96}
97
98static void __exit nf_nat_proto_dccp_fini(void)
99{
100 nf_nat_protocol_unregister(&nf_nat_protocol_dccp);
101}
102
103module_init(nf_nat_proto_dccp_init);
104module_exit(nf_nat_proto_dccp_fini);
105
106MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
107MODULE_DESCRIPTION("DCCP NAT protocol helper");
108MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index a1e4da16da2e..d7e89201351e 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -36,26 +36,8 @@ MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); 36MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
37MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); 37MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
38 38
39/* is key in given range between min and max */
40static int
41gre_in_range(const struct nf_conntrack_tuple *tuple,
42 enum nf_nat_manip_type maniptype,
43 const union nf_conntrack_man_proto *min,
44 const union nf_conntrack_man_proto *max)
45{
46 __be16 key;
47
48 if (maniptype == IP_NAT_MANIP_SRC)
49 key = tuple->src.u.gre.key;
50 else
51 key = tuple->dst.u.gre.key;
52
53 return ntohs(key) >= ntohs(min->gre.key) &&
54 ntohs(key) <= ntohs(max->gre.key);
55}
56
57/* generate unique tuple ... */ 39/* generate unique tuple ... */
58static int 40static bool
59gre_unique_tuple(struct nf_conntrack_tuple *tuple, 41gre_unique_tuple(struct nf_conntrack_tuple *tuple,
60 const struct nf_nat_range *range, 42 const struct nf_nat_range *range,
61 enum nf_nat_manip_type maniptype, 43 enum nf_nat_manip_type maniptype,
@@ -68,7 +50,7 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
68 /* If there is no master conntrack we are not PPTP, 50 /* If there is no master conntrack we are not PPTP,
69 do not change tuples */ 51 do not change tuples */
70 if (!ct->master) 52 if (!ct->master)
71 return 0; 53 return false;
72 54
73 if (maniptype == IP_NAT_MANIP_SRC) 55 if (maniptype == IP_NAT_MANIP_SRC)
74 keyptr = &tuple->src.u.gre.key; 56 keyptr = &tuple->src.u.gre.key;
@@ -89,20 +71,20 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
89 for (i = 0; i < range_size; i++, key++) { 71 for (i = 0; i < range_size; i++, key++) {
90 *keyptr = htons(min + key % range_size); 72 *keyptr = htons(min + key % range_size);
91 if (!nf_nat_used_tuple(tuple, ct)) 73 if (!nf_nat_used_tuple(tuple, ct))
92 return 1; 74 return true;
93 } 75 }
94 76
95 pr_debug("%p: no NAT mapping\n", ct); 77 pr_debug("%p: no NAT mapping\n", ct);
96 return 0; 78 return false;
97} 79}
98 80
99/* manipulate a GRE packet according to maniptype */ 81/* manipulate a GRE packet according to maniptype */
100static int 82static bool
101gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, 83gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
102 const struct nf_conntrack_tuple *tuple, 84 const struct nf_conntrack_tuple *tuple,
103 enum nf_nat_manip_type maniptype) 85 enum nf_nat_manip_type maniptype)
104{ 86{
105 struct gre_hdr *greh; 87 const struct gre_hdr *greh;
106 struct gre_hdr_pptp *pgreh; 88 struct gre_hdr_pptp *pgreh;
107 const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); 89 const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
108 unsigned int hdroff = iphdroff + iph->ihl * 4; 90 unsigned int hdroff = iphdroff + iph->ihl * 4;
@@ -110,7 +92,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
110 /* pgreh includes two optional 32bit fields which are not required 92 /* pgreh includes two optional 32bit fields which are not required
111 * to be there. That's where the magic '8' comes from */ 93 * to be there. That's where the magic '8' comes from */
112 if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8)) 94 if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
113 return 0; 95 return false;
114 96
115 greh = (void *)skb->data + hdroff; 97 greh = (void *)skb->data + hdroff;
116 pgreh = (struct gre_hdr_pptp *)greh; 98 pgreh = (struct gre_hdr_pptp *)greh;
@@ -118,7 +100,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
118 /* we only have destination manip of a packet, since 'source key' 100 /* we only have destination manip of a packet, since 'source key'
119 * is not present in the packet itself */ 101 * is not present in the packet itself */
120 if (maniptype != IP_NAT_MANIP_DST) 102 if (maniptype != IP_NAT_MANIP_DST)
121 return 1; 103 return true;
122 switch (greh->version) { 104 switch (greh->version) {
123 case GRE_VERSION_1701: 105 case GRE_VERSION_1701:
124 /* We do not currently NAT any GREv0 packets. 106 /* We do not currently NAT any GREv0 packets.
@@ -130,21 +112,20 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
130 break; 112 break;
131 default: 113 default:
132 pr_debug("can't nat unknown GRE version\n"); 114 pr_debug("can't nat unknown GRE version\n");
133 return 0; 115 return false;
134 } 116 }
135 return 1; 117 return true;
136} 118}
137 119
138static const struct nf_nat_protocol gre = { 120static const struct nf_nat_protocol gre = {
139 .name = "GRE",
140 .protonum = IPPROTO_GRE, 121 .protonum = IPPROTO_GRE,
141 .me = THIS_MODULE, 122 .me = THIS_MODULE,
142 .manip_pkt = gre_manip_pkt, 123 .manip_pkt = gre_manip_pkt,
143 .in_range = gre_in_range, 124 .in_range = nf_nat_proto_in_range,
144 .unique_tuple = gre_unique_tuple, 125 .unique_tuple = gre_unique_tuple,
145#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 126#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
146 .range_to_nlattr = nf_nat_port_range_to_nlattr, 127 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
147 .nlattr_to_range = nf_nat_port_nlattr_to_range, 128 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
148#endif 129#endif
149}; 130};
150 131
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index 03a02969aa57..19a8b0b07d8e 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -17,7 +17,7 @@
17#include <net/netfilter/nf_nat_rule.h> 17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_nat_protocol.h> 18#include <net/netfilter/nf_nat_protocol.h>
19 19
20static int 20static bool
21icmp_in_range(const struct nf_conntrack_tuple *tuple, 21icmp_in_range(const struct nf_conntrack_tuple *tuple,
22 enum nf_nat_manip_type maniptype, 22 enum nf_nat_manip_type maniptype,
23 const union nf_conntrack_man_proto *min, 23 const union nf_conntrack_man_proto *min,
@@ -27,7 +27,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
27 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id); 27 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
28} 28}
29 29
30static int 30static bool
31icmp_unique_tuple(struct nf_conntrack_tuple *tuple, 31icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
32 const struct nf_nat_range *range, 32 const struct nf_nat_range *range,
33 enum nf_nat_manip_type maniptype, 33 enum nf_nat_manip_type maniptype,
@@ -46,12 +46,12 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
46 tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) + 46 tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
47 (id % range_size)); 47 (id % range_size));
48 if (!nf_nat_used_tuple(tuple, ct)) 48 if (!nf_nat_used_tuple(tuple, ct))
49 return 1; 49 return true;
50 } 50 }
51 return 0; 51 return false;
52} 52}
53 53
54static int 54static bool
55icmp_manip_pkt(struct sk_buff *skb, 55icmp_manip_pkt(struct sk_buff *skb,
56 unsigned int iphdroff, 56 unsigned int iphdroff,
57 const struct nf_conntrack_tuple *tuple, 57 const struct nf_conntrack_tuple *tuple,
@@ -62,24 +62,23 @@ icmp_manip_pkt(struct sk_buff *skb,
62 unsigned int hdroff = iphdroff + iph->ihl*4; 62 unsigned int hdroff = iphdroff + iph->ihl*4;
63 63
64 if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 64 if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
65 return 0; 65 return false;
66 66
67 hdr = (struct icmphdr *)(skb->data + hdroff); 67 hdr = (struct icmphdr *)(skb->data + hdroff);
68 inet_proto_csum_replace2(&hdr->checksum, skb, 68 inet_proto_csum_replace2(&hdr->checksum, skb,
69 hdr->un.echo.id, tuple->src.u.icmp.id, 0); 69 hdr->un.echo.id, tuple->src.u.icmp.id, 0);
70 hdr->un.echo.id = tuple->src.u.icmp.id; 70 hdr->un.echo.id = tuple->src.u.icmp.id;
71 return 1; 71 return true;
72} 72}
73 73
74const struct nf_nat_protocol nf_nat_protocol_icmp = { 74const struct nf_nat_protocol nf_nat_protocol_icmp = {
75 .name = "ICMP",
76 .protonum = IPPROTO_ICMP, 75 .protonum = IPPROTO_ICMP,
77 .me = THIS_MODULE, 76 .me = THIS_MODULE,
78 .manip_pkt = icmp_manip_pkt, 77 .manip_pkt = icmp_manip_pkt,
79 .in_range = icmp_in_range, 78 .in_range = icmp_in_range,
80 .unique_tuple = icmp_unique_tuple, 79 .unique_tuple = icmp_unique_tuple,
81#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 80#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
82 .range_to_nlattr = nf_nat_port_range_to_nlattr, 81 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
83 .nlattr_to_range = nf_nat_port_nlattr_to_range, 82 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
84#endif 83#endif
85}; 84};
diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c
new file mode 100644
index 000000000000..82e4c0e286b8
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/ip.h>
12#include <linux/sctp.h>
13#include <net/sctp/checksum.h>
14
15#include <net/netfilter/nf_nat_protocol.h>
16
17static u_int16_t nf_sctp_port_rover;
18
19static bool
20sctp_unique_tuple(struct nf_conntrack_tuple *tuple,
21 const struct nf_nat_range *range,
22 enum nf_nat_manip_type maniptype,
23 const struct nf_conn *ct)
24{
25 return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
26 &nf_sctp_port_rover);
27}
28
29static bool
30sctp_manip_pkt(struct sk_buff *skb,
31 unsigned int iphdroff,
32 const struct nf_conntrack_tuple *tuple,
33 enum nf_nat_manip_type maniptype)
34{
35 const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
36 sctp_sctphdr_t *hdr;
37 unsigned int hdroff = iphdroff + iph->ihl*4;
38 __be32 oldip, newip;
39 u32 crc32;
40
41 if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
42 return false;
43
44 iph = (struct iphdr *)(skb->data + iphdroff);
45 hdr = (struct sctphdr *)(skb->data + hdroff);
46
47 if (maniptype == IP_NAT_MANIP_SRC) {
48 /* Get rid of src ip and src pt */
49 oldip = iph->saddr;
50 newip = tuple->src.u3.ip;
51 hdr->source = tuple->src.u.sctp.port;
52 } else {
53 /* Get rid of dst ip and dst pt */
54 oldip = iph->daddr;
55 newip = tuple->dst.u3.ip;
56 hdr->dest = tuple->dst.u.sctp.port;
57 }
58
59 crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
60 for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
61 crc32 = sctp_update_cksum((u8 *)skb->data, skb_headlen(skb),
62 crc32);
63 crc32 = sctp_end_cksum(crc32);
64 hdr->checksum = htonl(crc32);
65
66 return true;
67}
68
69static const struct nf_nat_protocol nf_nat_protocol_sctp = {
70 .protonum = IPPROTO_SCTP,
71 .me = THIS_MODULE,
72 .manip_pkt = sctp_manip_pkt,
73 .in_range = nf_nat_proto_in_range,
74 .unique_tuple = sctp_unique_tuple,
75#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
76 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
77 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
78#endif
79};
80
81static int __init nf_nat_proto_sctp_init(void)
82{
83 return nf_nat_protocol_register(&nf_nat_protocol_sctp);
84}
85
86static void __exit nf_nat_proto_sctp_exit(void)
87{
88 nf_nat_protocol_unregister(&nf_nat_protocol_sctp);
89}
90
91module_init(nf_nat_proto_sctp_init);
92module_exit(nf_nat_proto_sctp_exit);
93
94MODULE_LICENSE("GPL");
95MODULE_DESCRIPTION("SCTP NAT protocol helper");
96MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index ffd5d1589eca..399e2cfa263b 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -8,7 +8,6 @@
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/random.h>
12#include <linux/ip.h> 11#include <linux/ip.h>
13#include <linux/tcp.h> 12#include <linux/tcp.h>
14 13
@@ -19,75 +18,19 @@
19#include <net/netfilter/nf_nat_protocol.h> 18#include <net/netfilter/nf_nat_protocol.h>
20#include <net/netfilter/nf_nat_core.h> 19#include <net/netfilter/nf_nat_core.h>
21 20
22static int 21static u_int16_t tcp_port_rover;
23tcp_in_range(const struct nf_conntrack_tuple *tuple,
24 enum nf_nat_manip_type maniptype,
25 const union nf_conntrack_man_proto *min,
26 const union nf_conntrack_man_proto *max)
27{
28 __be16 port;
29
30 if (maniptype == IP_NAT_MANIP_SRC)
31 port = tuple->src.u.tcp.port;
32 else
33 port = tuple->dst.u.tcp.port;
34
35 return ntohs(port) >= ntohs(min->tcp.port) &&
36 ntohs(port) <= ntohs(max->tcp.port);
37}
38 22
39static int 23static bool
40tcp_unique_tuple(struct nf_conntrack_tuple *tuple, 24tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
41 const struct nf_nat_range *range, 25 const struct nf_nat_range *range,
42 enum nf_nat_manip_type maniptype, 26 enum nf_nat_manip_type maniptype,
43 const struct nf_conn *ct) 27 const struct nf_conn *ct)
44{ 28{
45 static u_int16_t port; 29 return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
46 __be16 *portptr; 30 &tcp_port_rover);
47 unsigned int range_size, min, i;
48
49 if (maniptype == IP_NAT_MANIP_SRC)
50 portptr = &tuple->src.u.tcp.port;
51 else
52 portptr = &tuple->dst.u.tcp.port;
53
54 /* If no range specified... */
55 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
56 /* If it's dst rewrite, can't change port */
57 if (maniptype == IP_NAT_MANIP_DST)
58 return 0;
59
60 /* Map privileged onto privileged. */
61 if (ntohs(*portptr) < 1024) {
62 /* Loose convention: >> 512 is credential passing */
63 if (ntohs(*portptr)<512) {
64 min = 1;
65 range_size = 511 - min + 1;
66 } else {
67 min = 600;
68 range_size = 1023 - min + 1;
69 }
70 } else {
71 min = 1024;
72 range_size = 65535 - 1024 + 1;
73 }
74 } else {
75 min = ntohs(range->min.tcp.port);
76 range_size = ntohs(range->max.tcp.port) - min + 1;
77 }
78
79 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
80 port = net_random();
81
82 for (i = 0; i < range_size; i++, port++) {
83 *portptr = htons(min + port % range_size);
84 if (!nf_nat_used_tuple(tuple, ct))
85 return 1;
86 }
87 return 0;
88} 31}
89 32
90static int 33static bool
91tcp_manip_pkt(struct sk_buff *skb, 34tcp_manip_pkt(struct sk_buff *skb,
92 unsigned int iphdroff, 35 unsigned int iphdroff,
93 const struct nf_conntrack_tuple *tuple, 36 const struct nf_conntrack_tuple *tuple,
@@ -107,7 +50,7 @@ tcp_manip_pkt(struct sk_buff *skb,
107 hdrsize = sizeof(struct tcphdr); 50 hdrsize = sizeof(struct tcphdr);
108 51
109 if (!skb_make_writable(skb, hdroff + hdrsize)) 52 if (!skb_make_writable(skb, hdroff + hdrsize))
110 return 0; 53 return false;
111 54
112 iph = (struct iphdr *)(skb->data + iphdroff); 55 iph = (struct iphdr *)(skb->data + iphdroff);
113 hdr = (struct tcphdr *)(skb->data + hdroff); 56 hdr = (struct tcphdr *)(skb->data + hdroff);
@@ -130,22 +73,21 @@ tcp_manip_pkt(struct sk_buff *skb,
130 *portptr = newport; 73 *portptr = newport;
131 74
132 if (hdrsize < sizeof(*hdr)) 75 if (hdrsize < sizeof(*hdr))
133 return 1; 76 return true;
134 77
135 inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); 78 inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
136 inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); 79 inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0);
137 return 1; 80 return true;
138} 81}
139 82
140const struct nf_nat_protocol nf_nat_protocol_tcp = { 83const struct nf_nat_protocol nf_nat_protocol_tcp = {
141 .name = "TCP",
142 .protonum = IPPROTO_TCP, 84 .protonum = IPPROTO_TCP,
143 .me = THIS_MODULE, 85 .me = THIS_MODULE,
144 .manip_pkt = tcp_manip_pkt, 86 .manip_pkt = tcp_manip_pkt,
145 .in_range = tcp_in_range, 87 .in_range = nf_nat_proto_in_range,
146 .unique_tuple = tcp_unique_tuple, 88 .unique_tuple = tcp_unique_tuple,
147#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 89#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
148 .range_to_nlattr = nf_nat_port_range_to_nlattr, 90 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
149 .nlattr_to_range = nf_nat_port_nlattr_to_range, 91 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
150#endif 92#endif
151}; 93};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index 4b8f49910ff2..9e61c79492e4 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -8,7 +8,6 @@
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/random.h>
12#include <linux/ip.h> 11#include <linux/ip.h>
13#include <linux/udp.h> 12#include <linux/udp.h>
14 13
@@ -18,74 +17,19 @@
18#include <net/netfilter/nf_nat_rule.h> 17#include <net/netfilter/nf_nat_rule.h>
19#include <net/netfilter/nf_nat_protocol.h> 18#include <net/netfilter/nf_nat_protocol.h>
20 19
21static int 20static u_int16_t udp_port_rover;
22udp_in_range(const struct nf_conntrack_tuple *tuple,
23 enum nf_nat_manip_type maniptype,
24 const union nf_conntrack_man_proto *min,
25 const union nf_conntrack_man_proto *max)
26{
27 __be16 port;
28
29 if (maniptype == IP_NAT_MANIP_SRC)
30 port = tuple->src.u.udp.port;
31 else
32 port = tuple->dst.u.udp.port;
33
34 return ntohs(port) >= ntohs(min->udp.port) &&
35 ntohs(port) <= ntohs(max->udp.port);
36}
37 21
38static int 22static bool
39udp_unique_tuple(struct nf_conntrack_tuple *tuple, 23udp_unique_tuple(struct nf_conntrack_tuple *tuple,
40 const struct nf_nat_range *range, 24 const struct nf_nat_range *range,
41 enum nf_nat_manip_type maniptype, 25 enum nf_nat_manip_type maniptype,
42 const struct nf_conn *ct) 26 const struct nf_conn *ct)
43{ 27{
44 static u_int16_t port; 28 return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
45 __be16 *portptr; 29 &udp_port_rover);
46 unsigned int range_size, min, i;
47
48 if (maniptype == IP_NAT_MANIP_SRC)
49 portptr = &tuple->src.u.udp.port;
50 else
51 portptr = &tuple->dst.u.udp.port;
52
53 /* If no range specified... */
54 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
55 /* If it's dst rewrite, can't change port */
56 if (maniptype == IP_NAT_MANIP_DST)
57 return 0;
58
59 if (ntohs(*portptr) < 1024) {
60 /* Loose convention: >> 512 is credential passing */
61 if (ntohs(*portptr)<512) {
62 min = 1;
63 range_size = 511 - min + 1;
64 } else {
65 min = 600;
66 range_size = 1023 - min + 1;
67 }
68 } else {
69 min = 1024;
70 range_size = 65535 - 1024 + 1;
71 }
72 } else {
73 min = ntohs(range->min.udp.port);
74 range_size = ntohs(range->max.udp.port) - min + 1;
75 }
76
77 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
78 port = net_random();
79
80 for (i = 0; i < range_size; i++, port++) {
81 *portptr = htons(min + port % range_size);
82 if (!nf_nat_used_tuple(tuple, ct))
83 return 1;
84 }
85 return 0;
86} 30}
87 31
88static int 32static bool
89udp_manip_pkt(struct sk_buff *skb, 33udp_manip_pkt(struct sk_buff *skb,
90 unsigned int iphdroff, 34 unsigned int iphdroff,
91 const struct nf_conntrack_tuple *tuple, 35 const struct nf_conntrack_tuple *tuple,
@@ -98,7 +42,7 @@ udp_manip_pkt(struct sk_buff *skb,
98 __be16 *portptr, newport; 42 __be16 *portptr, newport;
99 43
100 if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) 44 if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
101 return 0; 45 return false;
102 46
103 iph = (struct iphdr *)(skb->data + iphdroff); 47 iph = (struct iphdr *)(skb->data + iphdroff);
104 hdr = (struct udphdr *)(skb->data + hdroff); 48 hdr = (struct udphdr *)(skb->data + hdroff);
@@ -124,18 +68,17 @@ udp_manip_pkt(struct sk_buff *skb,
124 hdr->check = CSUM_MANGLED_0; 68 hdr->check = CSUM_MANGLED_0;
125 } 69 }
126 *portptr = newport; 70 *portptr = newport;
127 return 1; 71 return true;
128} 72}
129 73
130const struct nf_nat_protocol nf_nat_protocol_udp = { 74const struct nf_nat_protocol nf_nat_protocol_udp = {
131 .name = "UDP",
132 .protonum = IPPROTO_UDP, 75 .protonum = IPPROTO_UDP,
133 .me = THIS_MODULE, 76 .me = THIS_MODULE,
134 .manip_pkt = udp_manip_pkt, 77 .manip_pkt = udp_manip_pkt,
135 .in_range = udp_in_range, 78 .in_range = nf_nat_proto_in_range,
136 .unique_tuple = udp_unique_tuple, 79 .unique_tuple = udp_unique_tuple,
137#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 80#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
138 .range_to_nlattr = nf_nat_port_range_to_nlattr, 81 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
139 .nlattr_to_range = nf_nat_port_nlattr_to_range, 82 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
140#endif 83#endif
141}; 84};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/ipv4/netfilter/nf_nat_proto_udplite.c
new file mode 100644
index 000000000000..440a229bbd87
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_udplite.c
@@ -0,0 +1,99 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 * (C) 2008 Patrick McHardy <kaber@trash.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/types.h>
11#include <linux/init.h>
12#include <linux/ip.h>
13#include <linux/udp.h>
14
15#include <linux/netfilter.h>
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nf_nat_protocol.h>
18
19static u_int16_t udplite_port_rover;
20
21static bool
22udplite_unique_tuple(struct nf_conntrack_tuple *tuple,
23 const struct nf_nat_range *range,
24 enum nf_nat_manip_type maniptype,
25 const struct nf_conn *ct)
26{
27 return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct,
28 &udplite_port_rover);
29}
30
31static bool
32udplite_manip_pkt(struct sk_buff *skb,
33 unsigned int iphdroff,
34 const struct nf_conntrack_tuple *tuple,
35 enum nf_nat_manip_type maniptype)
36{
37 const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
38 struct udphdr *hdr;
39 unsigned int hdroff = iphdroff + iph->ihl*4;
40 __be32 oldip, newip;
41 __be16 *portptr, newport;
42
43 if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
44 return false;
45
46 iph = (struct iphdr *)(skb->data + iphdroff);
47 hdr = (struct udphdr *)(skb->data + hdroff);
48
49 if (maniptype == IP_NAT_MANIP_SRC) {
50 /* Get rid of src ip and src pt */
51 oldip = iph->saddr;
52 newip = tuple->src.u3.ip;
53 newport = tuple->src.u.udp.port;
54 portptr = &hdr->source;
55 } else {
56 /* Get rid of dst ip and dst pt */
57 oldip = iph->daddr;
58 newip = tuple->dst.u3.ip;
59 newport = tuple->dst.u.udp.port;
60 portptr = &hdr->dest;
61 }
62
63 inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1);
64 inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 0);
65 if (!hdr->check)
66 hdr->check = CSUM_MANGLED_0;
67
68 *portptr = newport;
69 return true;
70}
71
72static const struct nf_nat_protocol nf_nat_protocol_udplite = {
73 .protonum = IPPROTO_UDPLITE,
74 .me = THIS_MODULE,
75 .manip_pkt = udplite_manip_pkt,
76 .in_range = nf_nat_proto_in_range,
77 .unique_tuple = udplite_unique_tuple,
78#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
79 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
80 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
81#endif
82};
83
84static int __init nf_nat_proto_udplite_init(void)
85{
86 return nf_nat_protocol_register(&nf_nat_protocol_udplite);
87}
88
89static void __exit nf_nat_proto_udplite_fini(void)
90{
91 nf_nat_protocol_unregister(&nf_nat_protocol_udplite);
92}
93
94module_init(nf_nat_proto_udplite_init);
95module_exit(nf_nat_proto_udplite_fini);
96
97MODULE_LICENSE("GPL");
98MODULE_DESCRIPTION("UDP-Lite NAT protocol helper");
99MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
index a26efeb073cb..14381c62acea 100644
--- a/net/ipv4/netfilter/nf_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
@@ -18,35 +18,34 @@
18#include <net/netfilter/nf_nat_rule.h> 18#include <net/netfilter/nf_nat_rule.h>
19#include <net/netfilter/nf_nat_protocol.h> 19#include <net/netfilter/nf_nat_protocol.h>
20 20
21static int unknown_in_range(const struct nf_conntrack_tuple *tuple, 21static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
22 enum nf_nat_manip_type manip_type, 22 enum nf_nat_manip_type manip_type,
23 const union nf_conntrack_man_proto *min, 23 const union nf_conntrack_man_proto *min,
24 const union nf_conntrack_man_proto *max) 24 const union nf_conntrack_man_proto *max)
25{ 25{
26 return 1; 26 return true;
27} 27}
28 28
29static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple, 29static bool unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
30 const struct nf_nat_range *range, 30 const struct nf_nat_range *range,
31 enum nf_nat_manip_type maniptype, 31 enum nf_nat_manip_type maniptype,
32 const struct nf_conn *ct) 32 const struct nf_conn *ct)
33{ 33{
34 /* Sorry: we can't help you; if it's not unique, we can't frob 34 /* Sorry: we can't help you; if it's not unique, we can't frob
35 anything. */ 35 anything. */
36 return 0; 36 return false;
37} 37}
38 38
39static int 39static bool
40unknown_manip_pkt(struct sk_buff *skb, 40unknown_manip_pkt(struct sk_buff *skb,
41 unsigned int iphdroff, 41 unsigned int iphdroff,
42 const struct nf_conntrack_tuple *tuple, 42 const struct nf_conntrack_tuple *tuple,
43 enum nf_nat_manip_type maniptype) 43 enum nf_nat_manip_type maniptype)
44{ 44{
45 return 1; 45 return true;
46} 46}
47 47
48const struct nf_nat_protocol nf_nat_unknown_protocol = { 48const struct nf_nat_protocol nf_nat_unknown_protocol = {
49 .name = "unknown",
50 /* .me isn't set: getting a ref to this cannot fail. */ 49 /* .me isn't set: getting a ref to this cannot fail. */
51 .manip_pkt = unknown_manip_pkt, 50 .manip_pkt = unknown_manip_pkt,
52 .in_range = unknown_in_range, 51 .in_range = unknown_in_range,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index f8fda57ba20b..e8b4d0d4439e 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -61,7 +61,7 @@ static struct
61static struct xt_table __nat_table = { 61static struct xt_table __nat_table = {
62 .name = "nat", 62 .name = "nat",
63 .valid_hooks = NAT_VALID_HOOKS, 63 .valid_hooks = NAT_VALID_HOOKS,
64 .lock = RW_LOCK_UNLOCKED, 64 .lock = __RW_LOCK_UNLOCKED(__nat_table.lock),
65 .me = THIS_MODULE, 65 .me = THIS_MODULE,
66 .af = AF_INET, 66 .af = AF_INET,
67}; 67};
@@ -143,7 +143,7 @@ static bool ipt_snat_checkentry(const char *tablename,
143 void *targinfo, 143 void *targinfo,
144 unsigned int hook_mask) 144 unsigned int hook_mask)
145{ 145{
146 struct nf_nat_multi_range_compat *mr = targinfo; 146 const struct nf_nat_multi_range_compat *mr = targinfo;
147 147
148 /* Must be a valid range */ 148 /* Must be a valid range */
149 if (mr->rangesize != 1) { 149 if (mr->rangesize != 1) {
@@ -159,7 +159,7 @@ static bool ipt_dnat_checkentry(const char *tablename,
159 void *targinfo, 159 void *targinfo,
160 unsigned int hook_mask) 160 unsigned int hook_mask)
161{ 161{
162 struct nf_nat_multi_range_compat *mr = targinfo; 162 const struct nf_nat_multi_range_compat *mr = targinfo;
163 163
164 /* Must be a valid range */ 164 /* Must be a valid range */
165 if (mr->rangesize != 1) { 165 if (mr->rangesize != 1) {
@@ -188,25 +188,6 @@ alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
188 return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); 188 return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
189} 189}
190 190
191unsigned int
192alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
193{
194 __be32 ip
195 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
196 ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
197 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
198 __be16 all
199 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
200 ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
201 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
202 struct nf_nat_range range
203 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
204
205 pr_debug("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
206 ct, NIPQUAD(ip));
207 return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
208}
209
210int nf_nat_rule_find(struct sk_buff *skb, 191int nf_nat_rule_find(struct sk_buff *skb,
211 unsigned int hooknum, 192 unsigned int hooknum,
212 const struct net_device *in, 193 const struct net_device *in,
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 000e080bac5c..5daefad3d193 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -220,7 +220,7 @@ static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
220 if (ch < 0x80) 220 if (ch < 0x80)
221 *len = ch; 221 *len = ch;
222 else { 222 else {
223 cnt = (unsigned char) (ch & 0x7F); 223 cnt = ch & 0x7F;
224 *len = 0; 224 *len = 0;
225 225
226 while (cnt > 0) { 226 while (cnt > 0) {
@@ -618,8 +618,7 @@ struct snmp_cnv
618 int syntax; 618 int syntax;
619}; 619};
620 620
621static struct snmp_cnv snmp_conv [] = 621static const struct snmp_cnv snmp_conv[] = {
622{
623 {ASN1_UNI, ASN1_NUL, SNMP_NULL}, 622 {ASN1_UNI, ASN1_NUL, SNMP_NULL},
624 {ASN1_UNI, ASN1_INT, SNMP_INTEGER}, 623 {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
625 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR}, 624 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
@@ -644,7 +643,7 @@ static unsigned char snmp_tag_cls2syntax(unsigned int tag,
644 unsigned int cls, 643 unsigned int cls,
645 unsigned short *syntax) 644 unsigned short *syntax)
646{ 645{
647 struct snmp_cnv *cnv; 646 const struct snmp_cnv *cnv;
648 647
649 cnv = snmp_conv; 648 cnv = snmp_conv;
650 649
@@ -904,7 +903,7 @@ static inline void mangle_address(unsigned char *begin,
904 u_int32_t old; 903 u_int32_t old;
905 904
906 if (debug) 905 if (debug)
907 memcpy(&old, (unsigned char *)addr, sizeof(old)); 906 memcpy(&old, addr, sizeof(old));
908 907
909 *addr = map->to; 908 *addr = map->to;
910 909
@@ -999,7 +998,7 @@ err_id_free:
999 * 998 *
1000 *****************************************************************************/ 999 *****************************************************************************/
1001 1000
1002static void hex_dump(unsigned char *buf, size_t len) 1001static void hex_dump(const unsigned char *buf, size_t len)
1003{ 1002{
1004 size_t i; 1003 size_t i;
1005 1004
@@ -1080,7 +1079,7 @@ static int snmp_parse_mangle(unsigned char *msg,
1080 if (cls != ASN1_CTX || con != ASN1_CON) 1079 if (cls != ASN1_CTX || con != ASN1_CON)
1081 return 0; 1080 return 0;
1082 if (debug > 1) { 1081 if (debug > 1) {
1083 unsigned char *pdus[] = { 1082 static const unsigned char *const pdus[] = {
1084 [SNMP_PDU_GET] = "get", 1083 [SNMP_PDU_GET] = "get",
1085 [SNMP_PDU_NEXT] = "get-next", 1084 [SNMP_PDU_NEXT] = "get-next",
1086 [SNMP_PDU_RESPONSE] = "response", 1085 [SNMP_PDU_RESPONSE] = "response",
@@ -1232,8 +1231,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
1232{ 1231{
1233 int dir = CTINFO2DIR(ctinfo); 1232 int dir = CTINFO2DIR(ctinfo);
1234 unsigned int ret; 1233 unsigned int ret;
1235 struct iphdr *iph = ip_hdr(skb); 1234 const struct iphdr *iph = ip_hdr(skb);
1236 struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl); 1235 const struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1237 1236
1238 /* SNMP replies and originating SNMP traps get mangled */ 1237 /* SNMP replies and originating SNMP traps get mangled */
1239 if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY) 1238 if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 99b2c788d5a8..b7dd695691a0 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -30,8 +30,8 @@
30#ifdef CONFIG_XFRM 30#ifdef CONFIG_XFRM
31static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) 31static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
32{ 32{
33 struct nf_conn *ct; 33 const struct nf_conn *ct;
34 struct nf_conntrack_tuple *t; 34 const struct nf_conntrack_tuple *t;
35 enum ip_conntrack_info ctinfo; 35 enum ip_conntrack_info ctinfo;
36 enum ip_conntrack_dir dir; 36 enum ip_conntrack_dir dir;
37 unsigned long statusbit; 37 unsigned long statusbit;
@@ -50,7 +50,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
50 if (ct->status & statusbit) { 50 if (ct->status & statusbit) {
51 fl->fl4_dst = t->dst.u3.ip; 51 fl->fl4_dst = t->dst.u3.ip;
52 if (t->dst.protonum == IPPROTO_TCP || 52 if (t->dst.protonum == IPPROTO_TCP ||
53 t->dst.protonum == IPPROTO_UDP) 53 t->dst.protonum == IPPROTO_UDP ||
54 t->dst.protonum == IPPROTO_UDPLITE ||
55 t->dst.protonum == IPPROTO_DCCP ||
56 t->dst.protonum == IPPROTO_SCTP)
54 fl->fl_ip_dport = t->dst.u.tcp.port; 57 fl->fl_ip_dport = t->dst.u.tcp.port;
55 } 58 }
56 59
@@ -59,7 +62,10 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
59 if (ct->status & statusbit) { 62 if (ct->status & statusbit) {
60 fl->fl4_src = t->src.u3.ip; 63 fl->fl4_src = t->src.u3.ip;
61 if (t->dst.protonum == IPPROTO_TCP || 64 if (t->dst.protonum == IPPROTO_TCP ||
62 t->dst.protonum == IPPROTO_UDP) 65 t->dst.protonum == IPPROTO_UDP ||
66 t->dst.protonum == IPPROTO_UDPLITE ||
67 t->dst.protonum == IPPROTO_DCCP ||
68 t->dst.protonum == IPPROTO_SCTP)
63 fl->fl_ip_sport = t->src.u.tcp.port; 69 fl->fl_ip_sport = t->src.u.tcp.port;
64 } 70 }
65} 71}
@@ -87,21 +93,8 @@ nf_nat_fn(unsigned int hooknum,
87 have dropped it. Hence it's the user's responsibilty to 93 have dropped it. Hence it's the user's responsibilty to
88 packet filter it out, or implement conntrack/NAT for that 94 packet filter it out, or implement conntrack/NAT for that
89 protocol. 8) --RR */ 95 protocol. 8) --RR */
90 if (!ct) { 96 if (!ct)
91 /* Exception: ICMP redirect to new connection (not in
92 hash table yet). We must not let this through, in
93 case we're doing NAT to the same network. */
94 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
95 struct icmphdr _hdr, *hp;
96
97 hp = skb_header_pointer(skb, ip_hdrlen(skb),
98 sizeof(_hdr), &_hdr);
99 if (hp != NULL &&
100 hp->type == ICMP_REDIRECT)
101 return NF_DROP;
102 }
103 return NF_ACCEPT; 97 return NF_ACCEPT;
104 }
105 98
106 /* Don't try to NAT if this packet is not conntracked */ 99 /* Don't try to NAT if this packet is not conntracked */
107 if (ct == &nf_conntrack_untracked) 100 if (ct == &nf_conntrack_untracked)
@@ -109,6 +102,9 @@ nf_nat_fn(unsigned int hooknum,
109 102
110 nat = nfct_nat(ct); 103 nat = nfct_nat(ct);
111 if (!nat) { 104 if (!nat) {
105 /* NAT module was loaded late. */
106 if (nf_ct_is_confirmed(ct))
107 return NF_ACCEPT;
112 nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); 108 nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
113 if (nat == NULL) { 109 if (nat == NULL) {
114 pr_debug("failed to add NAT extension\n"); 110 pr_debug("failed to add NAT extension\n");
@@ -134,10 +130,7 @@ nf_nat_fn(unsigned int hooknum,
134 if (!nf_nat_initialized(ct, maniptype)) { 130 if (!nf_nat_initialized(ct, maniptype)) {
135 unsigned int ret; 131 unsigned int ret;
136 132
137 if (unlikely(nf_ct_is_confirmed(ct))) 133 if (hooknum == NF_INET_LOCAL_IN)
138 /* NAT module was loaded late */
139 ret = alloc_null_binding_confirmed(ct, hooknum);
140 else if (hooknum == NF_INET_LOCAL_IN)
141 /* LOCAL_IN hook doesn't have a chain! */ 134 /* LOCAL_IN hook doesn't have a chain! */
142 ret = alloc_null_binding(ct, hooknum); 135 ret = alloc_null_binding(ct, hooknum);
143 else 136 else
@@ -189,7 +182,7 @@ nf_nat_out(unsigned int hooknum,
189 int (*okfn)(struct sk_buff *)) 182 int (*okfn)(struct sk_buff *))
190{ 183{
191#ifdef CONFIG_XFRM 184#ifdef CONFIG_XFRM
192 struct nf_conn *ct; 185 const struct nf_conn *ct;
193 enum ip_conntrack_info ctinfo; 186 enum ip_conntrack_info ctinfo;
194#endif 187#endif
195 unsigned int ret; 188 unsigned int ret;
@@ -223,7 +216,7 @@ nf_nat_local_fn(unsigned int hooknum,
223 const struct net_device *out, 216 const struct net_device *out,
224 int (*okfn)(struct sk_buff *)) 217 int (*okfn)(struct sk_buff *))
225{ 218{
226 struct nf_conn *ct; 219 const struct nf_conn *ct;
227 enum ip_conntrack_info ctinfo; 220 enum ip_conntrack_info ctinfo;
228 unsigned int ret; 221 unsigned int ret;
229 222
@@ -252,25 +245,6 @@ nf_nat_local_fn(unsigned int hooknum,
252 return ret; 245 return ret;
253} 246}
254 247
255static unsigned int
256nf_nat_adjust(unsigned int hooknum,
257 struct sk_buff *skb,
258 const struct net_device *in,
259 const struct net_device *out,
260 int (*okfn)(struct sk_buff *))
261{
262 struct nf_conn *ct;
263 enum ip_conntrack_info ctinfo;
264
265 ct = nf_ct_get(skb, &ctinfo);
266 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
267 pr_debug("nf_nat_standalone: adjusting sequence number\n");
268 if (!nf_nat_seq_adjust(skb, ct, ctinfo))
269 return NF_DROP;
270 }
271 return NF_ACCEPT;
272}
273
274/* We must be after connection tracking and before packet filtering. */ 248/* We must be after connection tracking and before packet filtering. */
275 249
276static struct nf_hook_ops nf_nat_ops[] __read_mostly = { 250static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
@@ -290,14 +264,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
290 .hooknum = NF_INET_POST_ROUTING, 264 .hooknum = NF_INET_POST_ROUTING,
291 .priority = NF_IP_PRI_NAT_SRC, 265 .priority = NF_IP_PRI_NAT_SRC,
292 }, 266 },
293 /* After conntrack, adjust sequence number */
294 {
295 .hook = nf_nat_adjust,
296 .owner = THIS_MODULE,
297 .pf = PF_INET,
298 .hooknum = NF_INET_POST_ROUTING,
299 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
300 },
301 /* Before packet filtering, change destination */ 267 /* Before packet filtering, change destination */
302 { 268 {
303 .hook = nf_nat_local_fn, 269 .hook = nf_nat_local_fn,
@@ -314,14 +280,6 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
314 .hooknum = NF_INET_LOCAL_IN, 280 .hooknum = NF_INET_LOCAL_IN,
315 .priority = NF_IP_PRI_NAT_SRC, 281 .priority = NF_IP_PRI_NAT_SRC,
316 }, 282 },
317 /* After conntrack, adjust sequence number */
318 {
319 .hook = nf_nat_adjust,
320 .owner = THIS_MODULE,
321 .pf = PF_INET,
322 .hooknum = NF_INET_LOCAL_IN,
323 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
324 },
325}; 283};
326 284
327static int __init nf_nat_standalone_init(void) 285static int __init nf_nat_standalone_init(void)