aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/datagram.c2
-rw-r--r--net/ipv4/devinet.c14
-rw-r--r--net/ipv4/fib_semantics.c14
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/inet_diag.c19
-rw-r--r--net/ipv4/inet_hashtables.c2
-rw-r--r--net/ipv4/inet_timewait_sock.c4
-rw-r--r--net/ipv4/ip_gre.c3
-rw-r--r--net/ipv4/ipip.c3
-rw-r--r--net/ipv4/netfilter/Kconfig26
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c40
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c12
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c32
-rw-r--r--net/ipv4/netfilter/ip_tables.c40
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c15
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c13
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c16
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c9
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c8
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c8
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c12
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c8
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c207
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c11
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c11
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c18
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c9
-rw-r--r--net/ipv4/netfilter/ipt_ah.c10
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c10
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c10
-rw-r--r--net/ipv4/netfilter/ipt_owner.c9
-rw-r--r--net/ipv4/netfilter/ipt_recent.c12
-rw-r--r--net/ipv4/netfilter/ipt_tos.c10
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c11
-rw-r--r--net/ipv4/netfilter/iptable_filter.c2
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c2
-rw-r--r--net/ipv4/netfilter/iptable_raw.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c12
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c6
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c5
-rw-r--r--net/ipv4/tcp.c7
-rw-r--r--net/ipv4/tcp_input.c105
-rw-r--r--net/ipv4/tcp_ipv4.c18
-rw-r--r--net/ipv4/tcp_output.c3
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c57
-rw-r--r--net/ipv4/xfrm4_policy.c51
-rw-r--r--net/ipv4/xfrm4_state.c1
58 files changed, 426 insertions, 512 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 864009643675..5750a2b2a0d6 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1007,7 +1007,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
1007 RT_CONN_FLAGS(sk), 1007 RT_CONN_FLAGS(sk),
1008 sk->sk_bound_dev_if, 1008 sk->sk_bound_dev_if,
1009 sk->sk_protocol, 1009 sk->sk_protocol,
1010 inet->sport, inet->dport, sk); 1010 inet->sport, inet->dport, sk, 0);
1011 if (err) 1011 if (err)
1012 return err; 1012 return err;
1013 1013
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 7b068a891953..0072d79f0c2a 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -49,7 +49,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
49 err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr, 49 err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
50 RT_CONN_FLAGS(sk), oif, 50 RT_CONN_FLAGS(sk), oif,
51 sk->sk_protocol, 51 sk->sk_protocol,
52 inet->sport, usin->sin_port, sk); 52 inet->sport, usin->sin_port, sk, 1);
53 if (err) 53 if (err)
54 return err; 54 return err;
55 if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { 55 if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 480ace9819f6..c40203640966 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1140,7 +1140,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1140 1140
1141 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); 1141 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
1142 if (nlh == NULL) 1142 if (nlh == NULL)
1143 return -ENOBUFS; 1143 return -EMSGSIZE;
1144 1144
1145 ifm = nlmsg_data(nlh); 1145 ifm = nlmsg_data(nlh);
1146 ifm->ifa_family = AF_INET; 1146 ifm->ifa_family = AF_INET;
@@ -1167,7 +1167,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1167 return nlmsg_end(skb, nlh); 1167 return nlmsg_end(skb, nlh);
1168 1168
1169nla_put_failure: 1169nla_put_failure:
1170 return nlmsg_cancel(skb, nlh); 1170 nlmsg_cancel(skb, nlh);
1171 return -EMSGSIZE;
1171} 1172}
1172 1173
1173static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 1174static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1225,9 +1226,12 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
1225 goto errout; 1226 goto errout;
1226 1227
1227 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); 1228 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1228 /* failure implies BUG in inet_nlmsg_size() */ 1229 if (err < 0) {
1229 BUG_ON(err < 0); 1230 /* -EMSGSIZE implies BUG in inet_nlmsg_size() */
1230 1231 WARN_ON(err == -EMSGSIZE);
1232 kfree_skb(skb);
1233 goto errout;
1234 }
1231 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1235 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1232errout: 1236errout:
1233 if (err < 0) 1237 if (err < 0)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e63b8a98fb4d..be1028c9933e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -314,9 +314,12 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
314 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 314 err = fib_dump_info(skb, info->pid, seq, event, tb_id,
315 fa->fa_type, fa->fa_scope, key, dst_len, 315 fa->fa_type, fa->fa_scope, key, dst_len,
316 fa->fa_tos, fa->fa_info, 0); 316 fa->fa_tos, fa->fa_info, 0);
317 /* failure implies BUG in fib_nlmsg_size() */ 317 if (err < 0) {
318 BUG_ON(err < 0); 318 /* -EMSGSIZE implies BUG in fib_nlmsg_size() */
319 319 WARN_ON(err == -EMSGSIZE);
320 kfree_skb(skb);
321 goto errout;
322 }
320 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, 323 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
321 info->nlh, GFP_KERNEL); 324 info->nlh, GFP_KERNEL);
322errout: 325errout:
@@ -960,7 +963,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
960 963
961 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags); 964 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
962 if (nlh == NULL) 965 if (nlh == NULL)
963 return -ENOBUFS; 966 return -EMSGSIZE;
964 967
965 rtm = nlmsg_data(nlh); 968 rtm = nlmsg_data(nlh);
966 rtm->rtm_family = AF_INET; 969 rtm->rtm_family = AF_INET;
@@ -1031,7 +1034,8 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
1031 return nlmsg_end(skb, nlh); 1034 return nlmsg_end(skb, nlh);
1032 1035
1033nla_put_failure: 1036nla_put_failure:
1034 return nlmsg_cancel(skb, nlh); 1037 nlmsg_cancel(skb, nlh);
1038 return -EMSGSIZE;
1035} 1039}
1036 1040
1037/* 1041/*
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 0017ccb01d6d..024ae56cab25 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -455,6 +455,8 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
455 skb = add_grhead(skb, pmc, type, &pgr); 455 skb = add_grhead(skb, pmc, type, &pgr);
456 first = 0; 456 first = 0;
457 } 457 }
458 if (!skb)
459 return NULL;
458 psrc = (__be32 *)skb_put(skb, sizeof(__be32)); 460 psrc = (__be32 *)skb_put(skb, sizeof(__be32));
459 *psrc = psf->sf_inaddr; 461 *psrc = psf->sf_inaddr;
460 scount++; stotal++; 462 scount++; stotal++;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 77761ac4f7bb..8aa7d51e6881 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -153,7 +153,7 @@ static int inet_csk_diag_fill(struct sock *sk,
153rtattr_failure: 153rtattr_failure:
154nlmsg_failure: 154nlmsg_failure:
155 skb_trim(skb, b - skb->data); 155 skb_trim(skb, b - skb->data);
156 return -1; 156 return -EMSGSIZE;
157} 157}
158 158
159static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, 159static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -209,7 +209,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
209 return skb->len; 209 return skb->len;
210nlmsg_failure: 210nlmsg_failure:
211 skb_trim(skb, previous_tail - skb->data); 211 skb_trim(skb, previous_tail - skb->data);
212 return -1; 212 return -EMSGSIZE;
213} 213}
214 214
215static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, 215static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -274,11 +274,14 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,
274 if (!rep) 274 if (!rep)
275 goto out; 275 goto out;
276 276
277 if (sk_diag_fill(sk, rep, req->idiag_ext, 277 err = sk_diag_fill(sk, rep, req->idiag_ext,
278 NETLINK_CB(in_skb).pid, 278 NETLINK_CB(in_skb).pid,
279 nlh->nlmsg_seq, 0, nlh) <= 0) 279 nlh->nlmsg_seq, 0, nlh);
280 BUG(); 280 if (err < 0) {
281 281 WARN_ON(err == -EMSGSIZE);
282 kfree_skb(rep);
283 goto out;
284 }
282 err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid, 285 err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
283 MSG_DONTWAIT); 286 MSG_DONTWAIT);
284 if (err > 0) 287 if (err > 0)
@@ -775,7 +778,7 @@ next_normal:
775 struct inet_timewait_sock *tw; 778 struct inet_timewait_sock *tw;
776 779
777 inet_twsk_for_each(tw, node, 780 inet_twsk_for_each(tw, node,
778 &hashinfo->ehash[i + hashinfo->ehash_size].chain) { 781 &head->twchain) {
779 782
780 if (num < s_num) 783 if (num < s_num)
781 goto next_dying; 784 goto next_dying;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 8c79c8a4ea5c..150ace18dc75 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -212,7 +212,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
212 write_lock(&head->lock); 212 write_lock(&head->lock);
213 213
214 /* Check TIME-WAIT sockets first. */ 214 /* Check TIME-WAIT sockets first. */
215 sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) { 215 sk_for_each(sk2, node, &head->twchain) {
216 tw = inet_twsk(sk2); 216 tw = inet_twsk(sk2);
217 217
218 if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) { 218 if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 9f414e35c488..a73cf93cee36 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -78,8 +78,8 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
78 if (__sk_del_node_init(sk)) 78 if (__sk_del_node_init(sk))
79 sock_prot_dec_use(sk->sk_prot); 79 sock_prot_dec_use(sk->sk_prot);
80 80
81 /* Step 3: Hash TW into TIMEWAIT half of established hash table. */ 81 /* Step 3: Hash TW into TIMEWAIT chain. */
82 inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain); 82 inet_twsk_add_node(tw, &ehead->twchain);
83 atomic_inc(&tw->tw_refcnt); 83 atomic_inc(&tw->tw_refcnt);
84 84
85 write_unlock(&ehead->lock); 85 write_unlock(&ehead->lock);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 476cb6084c75..51c83500790f 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1008,7 +1008,8 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
1008 goto done; 1008 goto done;
1009 dev = t->dev; 1009 dev = t->dev;
1010 } 1010 }
1011 err = unregister_netdevice(dev); 1011 unregister_netdevice(dev);
1012 err = 0;
1012 break; 1013 break;
1013 1014
1014 default: 1015 default:
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 9d719d664e5b..da8bbd20c7ed 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -754,7 +754,8 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
754 goto done; 754 goto done;
755 dev = t->dev; 755 dev = t->dev;
756 } 756 }
757 err = unregister_netdevice(dev); 757 unregister_netdevice(dev);
758 err = 0;
758 break; 759 break;
759 760
760 default: 761 default:
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 47bd3ad18b71..9b08e7ad71bc 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -361,32 +361,6 @@ config IP_NF_TARGET_ULOG
361 361
362 To compile it as a module, choose M here. If unsure, say N. 362 To compile it as a module, choose M here. If unsure, say N.
363 363
364config IP_NF_TARGET_TCPMSS
365 tristate "TCPMSS target support"
366 depends on IP_NF_IPTABLES
367 ---help---
368 This option adds a `TCPMSS' target, which allows you to alter the
369 MSS value of TCP SYN packets, to control the maximum size for that
370 connection (usually limiting it to your outgoing interface's MTU
371 minus 40).
372
373 This is used to overcome criminally braindead ISPs or servers which
374 block ICMP Fragmentation Needed packets. The symptoms of this
375 problem are that everything works fine from your Linux
376 firewall/router, but machines behind it can never exchange large
377 packets:
378 1) Web browsers connect, then hang with no data received.
379 2) Small mail works fine, but large emails hang.
380 3) ssh works fine, but scp hangs after initial handshaking.
381
382 Workaround: activate this option and add a rule to your firewall
383 configuration like:
384
385 iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
386 -j TCPMSS --clamp-mss-to-pmtu
387
388 To compile it as a module, choose M here. If unsure, say N.
389
390# NAT + specific targets: ip_conntrack 364# NAT + specific targets: ip_conntrack
391config IP_NF_NAT 365config IP_NF_NAT
392 tristate "Full NAT" 366 tristate "Full NAT"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 16d177b71bf8..6625ec68180c 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -103,7 +103,6 @@ obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
103obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o 103obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
104obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 104obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
105obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 105obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
106obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
107obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 106obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
108obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o 107obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
109 108
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 06e4e8a6dd9f..c34f48fe5478 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -50,12 +50,9 @@ static DEFINE_RWLOCK(tcp_lock);
50 If it's non-zero, we mark only out of window RST segments as INVALID. */ 50 If it's non-zero, we mark only out of window RST segments as INVALID. */
51int ip_ct_tcp_be_liberal __read_mostly = 0; 51int ip_ct_tcp_be_liberal __read_mostly = 0;
52 52
53/* When connection is picked up from the middle, how many packets are required 53/* If it is set to zero, we disable picking up already established
54 to pass in each direction when we assume we are in sync - if any side uses
55 window scaling, we lost the game.
56 If it is set to zero, we disable picking up already established
57 connections. */ 54 connections. */
58int ip_ct_tcp_loose __read_mostly = 3; 55int ip_ct_tcp_loose __read_mostly = 1;
59 56
60/* Max number of the retransmitted packets without receiving an (acceptable) 57/* Max number of the retransmitted packets without receiving an (acceptable)
61 ACK from the destination. If this number is reached, a shorter timer 58 ACK from the destination. If this number is reached, a shorter timer
@@ -694,11 +691,10 @@ static int tcp_in_window(struct ip_ct_tcp *state,
694 before(sack, receiver->td_end + 1), 691 before(sack, receiver->td_end + 1),
695 after(ack, receiver->td_end - MAXACKWINDOW(sender))); 692 after(ack, receiver->td_end - MAXACKWINDOW(sender)));
696 693
697 if (sender->loose || receiver->loose || 694 if (before(seq, sender->td_maxend + 1) &&
698 (before(seq, sender->td_maxend + 1) && 695 after(end, sender->td_end - receiver->td_maxwin - 1) &&
699 after(end, sender->td_end - receiver->td_maxwin - 1) && 696 before(sack, receiver->td_end + 1) &&
700 before(sack, receiver->td_end + 1) && 697 after(ack, receiver->td_end - MAXACKWINDOW(sender))) {
701 after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
702 /* 698 /*
703 * Take into account window scaling (RFC 1323). 699 * Take into account window scaling (RFC 1323).
704 */ 700 */
@@ -743,15 +739,13 @@ static int tcp_in_window(struct ip_ct_tcp *state,
743 state->retrans = 0; 739 state->retrans = 0;
744 } 740 }
745 } 741 }
746 /*
747 * Close the window of disabled window tracking :-)
748 */
749 if (sender->loose)
750 sender->loose--;
751
752 res = 1; 742 res = 1;
753 } else { 743 } else {
754 if (LOG_INVALID(IPPROTO_TCP)) 744 res = 0;
745 if (sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL ||
746 ip_ct_tcp_be_liberal)
747 res = 1;
748 if (!res && LOG_INVALID(IPPROTO_TCP))
755 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, 749 nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
756 "ip_ct_tcp: %s ", 750 "ip_ct_tcp: %s ",
757 before(seq, sender->td_maxend + 1) ? 751 before(seq, sender->td_maxend + 1) ?
@@ -762,8 +756,6 @@ static int tcp_in_window(struct ip_ct_tcp *state,
762 : "ACK is over the upper bound (ACKed data not seen yet)" 756 : "ACK is over the upper bound (ACKed data not seen yet)"
763 : "SEQ is under the lower bound (already ACKed data retransmitted)" 757 : "SEQ is under the lower bound (already ACKed data retransmitted)"
764 : "SEQ is over the upper bound (over the window of the receiver)"); 758 : "SEQ is over the upper bound (over the window of the receiver)");
765
766 res = ip_ct_tcp_be_liberal;
767 } 759 }
768 760
769 DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u " 761 DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
@@ -1105,8 +1097,6 @@ static int tcp_new(struct ip_conntrack *conntrack,
1105 1097
1106 tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]); 1098 tcp_options(skb, iph, th, &conntrack->proto.tcp.seen[0]);
1107 conntrack->proto.tcp.seen[1].flags = 0; 1099 conntrack->proto.tcp.seen[1].flags = 0;
1108 conntrack->proto.tcp.seen[0].loose =
1109 conntrack->proto.tcp.seen[1].loose = 0;
1110 } else if (ip_ct_tcp_loose == 0) { 1100 } else if (ip_ct_tcp_loose == 0) {
1111 /* Don't try to pick up connections. */ 1101 /* Don't try to pick up connections. */
1112 return 0; 1102 return 0;
@@ -1127,11 +1117,11 @@ static int tcp_new(struct ip_conntrack *conntrack,
1127 conntrack->proto.tcp.seen[0].td_maxwin; 1117 conntrack->proto.tcp.seen[0].td_maxwin;
1128 conntrack->proto.tcp.seen[0].td_scale = 0; 1118 conntrack->proto.tcp.seen[0].td_scale = 0;
1129 1119
1130 /* We assume SACK. Should we assume window scaling too? */ 1120 /* We assume SACK and liberal window checking to handle
1121 * window scaling */
1131 conntrack->proto.tcp.seen[0].flags = 1122 conntrack->proto.tcp.seen[0].flags =
1132 conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM; 1123 conntrack->proto.tcp.seen[1].flags = IP_CT_TCP_FLAG_SACK_PERM |
1133 conntrack->proto.tcp.seen[0].loose = 1124 IP_CT_TCP_FLAG_BE_LIBERAL;
1134 conntrack->proto.tcp.seen[1].loose = ip_ct_tcp_loose;
1135 } 1125 }
1136 1126
1137 conntrack->proto.tcp.seen[1].td_end = 0; 1127 conntrack->proto.tcp.seen[1].td_end = 0;
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 9d1a5175dcd4..5e08c2bf887d 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -246,8 +246,9 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
246 if (maniptype == IP_NAT_MANIP_SRC) { 246 if (maniptype == IP_NAT_MANIP_SRC) {
247 if (find_appropriate_src(orig_tuple, tuple, range)) { 247 if (find_appropriate_src(orig_tuple, tuple, range)) {
248 DEBUGP("get_unique_tuple: Found current src map\n"); 248 DEBUGP("get_unique_tuple: Found current src map\n");
249 if (!ip_nat_used_tuple(tuple, conntrack)) 249 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
250 return; 250 if (!ip_nat_used_tuple(tuple, conntrack))
251 return;
251 } 252 }
252 } 253 }
253 254
@@ -261,6 +262,13 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
261 262
262 proto = ip_nat_proto_find_get(orig_tuple->dst.protonum); 263 proto = ip_nat_proto_find_get(orig_tuple->dst.protonum);
263 264
265 /* Change protocol info to have some randomization */
266 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
267 proto->unique_tuple(tuple, range, maniptype, conntrack);
268 ip_nat_proto_put(proto);
269 return;
270 }
271
264 /* Only bother mapping if it's not already in range and unique */ 272 /* Only bother mapping if it's not already in range and unique */
265 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) 273 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)
266 || proto->in_range(tuple, maniptype, &range->min, &range->max)) 274 || proto->in_range(tuple, maniptype, &range->min, &range->max))
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index ee80feb4b2a9..2e5c4bc52a60 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -183,7 +183,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
183 datalen = (*pskb)->len - iph->ihl*4; 183 datalen = (*pskb)->len - iph->ihl*4;
184 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { 184 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
185 tcph->check = 0; 185 tcph->check = 0;
186 tcph->check = tcp_v4_check(tcph, datalen, 186 tcph->check = tcp_v4_check(datalen,
187 iph->saddr, iph->daddr, 187 iph->saddr, iph->daddr,
188 csum_partial((char *)tcph, 188 csum_partial((char *)tcph,
189 datalen, 0)); 189 datalen, 0));
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index b586d18b3fb3..14ff24f53a7a 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -8,6 +8,7 @@
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>
11#include <linux/netfilter.h> 12#include <linux/netfilter.h>
12#include <linux/ip.h> 13#include <linux/ip.h>
13#include <linux/tcp.h> 14#include <linux/tcp.h>
@@ -75,6 +76,10 @@ tcp_unique_tuple(struct ip_conntrack_tuple *tuple,
75 range_size = ntohs(range->max.tcp.port) - min + 1; 76 range_size = ntohs(range->max.tcp.port) - min + 1;
76 } 77 }
77 78
79 /* Start from random port to avoid prediction */
80 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
81 port = net_random();
82
78 for (i = 0; i < range_size; i++, port++) { 83 for (i = 0; i < range_size; i++, port++) {
79 *portptr = htons(min + port % range_size); 84 *portptr = htons(min + port % range_size);
80 if (!ip_nat_used_tuple(tuple, conntrack)) { 85 if (!ip_nat_used_tuple(tuple, conntrack)) {
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 5ced0877b32f..dfd521672891 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -8,6 +8,7 @@
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>
11#include <linux/netfilter.h> 12#include <linux/netfilter.h>
12#include <linux/ip.h> 13#include <linux/ip.h>
13#include <linux/udp.h> 14#include <linux/udp.h>
@@ -74,6 +75,10 @@ udp_unique_tuple(struct ip_conntrack_tuple *tuple,
74 range_size = ntohs(range->max.udp.port) - min + 1; 75 range_size = ntohs(range->max.udp.port) - min + 1;
75 } 76 }
76 77
78 /* Start from random port to avoid prediction */
79 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
80 port = net_random();
81
77 for (i = 0; i < range_size; i++, port++) { 82 for (i = 0; i < range_size; i++, port++) {
78 *portptr = htons(min + port % range_size); 83 *portptr = htons(min + port % range_size);
79 if (!ip_nat_used_tuple(tuple, conntrack)) 84 if (!ip_nat_used_tuple(tuple, conntrack))
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index a176aa3031e0..e1c8a05f3dc6 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -86,7 +86,7 @@ static struct
86 } 86 }
87}; 87};
88 88
89static struct ipt_table nat_table = { 89static struct xt_table nat_table = {
90 .name = "nat", 90 .name = "nat",
91 .valid_hooks = NAT_VALID_HOOKS, 91 .valid_hooks = NAT_VALID_HOOKS,
92 .lock = RW_LOCK_UNLOCKED, 92 .lock = RW_LOCK_UNLOCKED,
@@ -99,7 +99,7 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb,
99 const struct net_device *in, 99 const struct net_device *in,
100 const struct net_device *out, 100 const struct net_device *out,
101 unsigned int hooknum, 101 unsigned int hooknum,
102 const struct ipt_target *target, 102 const struct xt_target *target,
103 const void *targinfo) 103 const void *targinfo)
104{ 104{
105 struct ip_conntrack *ct; 105 struct ip_conntrack *ct;
@@ -141,7 +141,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
141 const struct net_device *in, 141 const struct net_device *in,
142 const struct net_device *out, 142 const struct net_device *out,
143 unsigned int hooknum, 143 unsigned int hooknum,
144 const struct ipt_target *target, 144 const struct xt_target *target,
145 const void *targinfo) 145 const void *targinfo)
146{ 146{
147 struct ip_conntrack *ct; 147 struct ip_conntrack *ct;
@@ -166,7 +166,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb,
166 166
167static int ipt_snat_checkentry(const char *tablename, 167static int ipt_snat_checkentry(const char *tablename,
168 const void *entry, 168 const void *entry,
169 const struct ipt_target *target, 169 const struct xt_target *target,
170 void *targinfo, 170 void *targinfo,
171 unsigned int hook_mask) 171 unsigned int hook_mask)
172{ 172{
@@ -182,7 +182,7 @@ static int ipt_snat_checkentry(const char *tablename,
182 182
183static int ipt_dnat_checkentry(const char *tablename, 183static int ipt_dnat_checkentry(const char *tablename,
184 const void *entry, 184 const void *entry,
185 const struct ipt_target *target, 185 const struct xt_target *target,
186 void *targinfo, 186 void *targinfo,
187 unsigned int hook_mask) 187 unsigned int hook_mask)
188{ 188{
@@ -193,6 +193,10 @@ static int ipt_dnat_checkentry(const char *tablename,
193 printk("DNAT: multiple ranges no longer supported\n"); 193 printk("DNAT: multiple ranges no longer supported\n");
194 return 0; 194 return 0;
195 } 195 }
196 if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
197 printk("DNAT: port randomization not supported\n");
198 return 0;
199 }
196 return 1; 200 return 1;
197} 201}
198 202
@@ -257,8 +261,9 @@ int ip_nat_rule_find(struct sk_buff **pskb,
257 return ret; 261 return ret;
258} 262}
259 263
260static struct ipt_target ipt_snat_reg = { 264static struct xt_target ipt_snat_reg = {
261 .name = "SNAT", 265 .name = "SNAT",
266 .family = AF_INET,
262 .target = ipt_snat_target, 267 .target = ipt_snat_target,
263 .targetsize = sizeof(struct ip_nat_multi_range_compat), 268 .targetsize = sizeof(struct ip_nat_multi_range_compat),
264 .table = "nat", 269 .table = "nat",
@@ -266,8 +271,9 @@ static struct ipt_target ipt_snat_reg = {
266 .checkentry = ipt_snat_checkentry, 271 .checkentry = ipt_snat_checkentry,
267}; 272};
268 273
269static struct ipt_target ipt_dnat_reg = { 274static struct xt_target ipt_dnat_reg = {
270 .name = "DNAT", 275 .name = "DNAT",
276 .family = AF_INET,
271 .target = ipt_dnat_target, 277 .target = ipt_dnat_target,
272 .targetsize = sizeof(struct ip_nat_multi_range_compat), 278 .targetsize = sizeof(struct ip_nat_multi_range_compat),
273 .table = "nat", 279 .table = "nat",
@@ -282,27 +288,27 @@ int __init ip_nat_rule_init(void)
282 ret = ipt_register_table(&nat_table, &nat_initial_table.repl); 288 ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
283 if (ret != 0) 289 if (ret != 0)
284 return ret; 290 return ret;
285 ret = ipt_register_target(&ipt_snat_reg); 291 ret = xt_register_target(&ipt_snat_reg);
286 if (ret != 0) 292 if (ret != 0)
287 goto unregister_table; 293 goto unregister_table;
288 294
289 ret = ipt_register_target(&ipt_dnat_reg); 295 ret = xt_register_target(&ipt_dnat_reg);
290 if (ret != 0) 296 if (ret != 0)
291 goto unregister_snat; 297 goto unregister_snat;
292 298
293 return ret; 299 return ret;
294 300
295 unregister_snat: 301 unregister_snat:
296 ipt_unregister_target(&ipt_snat_reg); 302 xt_unregister_target(&ipt_snat_reg);
297 unregister_table: 303 unregister_table:
298 ipt_unregister_table(&nat_table); 304 xt_unregister_table(&nat_table);
299 305
300 return ret; 306 return ret;
301} 307}
302 308
303void ip_nat_rule_cleanup(void) 309void ip_nat_rule_cleanup(void)
304{ 310{
305 ipt_unregister_target(&ipt_dnat_reg); 311 xt_unregister_target(&ipt_dnat_reg);
306 ipt_unregister_target(&ipt_snat_reg); 312 xt_unregister_target(&ipt_snat_reg);
307 ipt_unregister_table(&nat_table); 313 ipt_unregister_table(&nat_table);
308} 314}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index fc1f153c86ba..5a7b3a341389 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -216,7 +216,7 @@ ipt_do_table(struct sk_buff **pskb,
216 unsigned int hook, 216 unsigned int hook,
217 const struct net_device *in, 217 const struct net_device *in,
218 const struct net_device *out, 218 const struct net_device *out,
219 struct ipt_table *table) 219 struct xt_table *table)
220{ 220{
221 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); 221 static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
222 u_int16_t offset; 222 u_int16_t offset;
@@ -507,7 +507,7 @@ check_entry(struct ipt_entry *e, const char *name)
507static inline int check_match(struct ipt_entry_match *m, const char *name, 507static inline int check_match(struct ipt_entry_match *m, const char *name,
508 const struct ipt_ip *ip, unsigned int hookmask) 508 const struct ipt_ip *ip, unsigned int hookmask)
509{ 509{
510 struct ipt_match *match; 510 struct xt_match *match;
511 int ret; 511 int ret;
512 512
513 match = m->u.kernel.match; 513 match = m->u.kernel.match;
@@ -531,7 +531,7 @@ find_check_match(struct ipt_entry_match *m,
531 unsigned int hookmask, 531 unsigned int hookmask,
532 unsigned int *i) 532 unsigned int *i)
533{ 533{
534 struct ipt_match *match; 534 struct xt_match *match;
535 int ret; 535 int ret;
536 536
537 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, 537 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
@@ -557,7 +557,7 @@ err:
557static inline int check_target(struct ipt_entry *e, const char *name) 557static inline int check_target(struct ipt_entry *e, const char *name)
558{ 558{
559 struct ipt_entry_target *t; 559 struct ipt_entry_target *t;
560 struct ipt_target *target; 560 struct xt_target *target;
561 int ret; 561 int ret;
562 562
563 t = ipt_get_target(e); 563 t = ipt_get_target(e);
@@ -580,7 +580,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
580 unsigned int *i) 580 unsigned int *i)
581{ 581{
582 struct ipt_entry_target *t; 582 struct ipt_entry_target *t;
583 struct ipt_target *target; 583 struct xt_target *target;
584 int ret; 584 int ret;
585 unsigned int j; 585 unsigned int j;
586 586
@@ -818,7 +818,7 @@ get_counters(const struct xt_table_info *t,
818 } 818 }
819} 819}
820 820
821static inline struct xt_counters * alloc_counters(struct ipt_table *table) 821static inline struct xt_counters * alloc_counters(struct xt_table *table)
822{ 822{
823 unsigned int countersize; 823 unsigned int countersize;
824 struct xt_counters *counters; 824 struct xt_counters *counters;
@@ -843,7 +843,7 @@ static inline struct xt_counters * alloc_counters(struct ipt_table *table)
843 843
844static int 844static int
845copy_entries_to_user(unsigned int total_size, 845copy_entries_to_user(unsigned int total_size,
846 struct ipt_table *table, 846 struct xt_table *table,
847 void __user *userptr) 847 void __user *userptr)
848{ 848{
849 unsigned int off, num; 849 unsigned int off, num;
@@ -1046,7 +1046,7 @@ static int compat_table_info(struct xt_table_info *info,
1046static int get_info(void __user *user, int *len, int compat) 1046static int get_info(void __user *user, int *len, int compat)
1047{ 1047{
1048 char name[IPT_TABLE_MAXNAMELEN]; 1048 char name[IPT_TABLE_MAXNAMELEN];
1049 struct ipt_table *t; 1049 struct xt_table *t;
1050 int ret; 1050 int ret;
1051 1051
1052 if (*len != sizeof(struct ipt_getinfo)) { 1052 if (*len != sizeof(struct ipt_getinfo)) {
@@ -1107,7 +1107,7 @@ get_entries(struct ipt_get_entries __user *uptr, int *len)
1107{ 1107{
1108 int ret; 1108 int ret;
1109 struct ipt_get_entries get; 1109 struct ipt_get_entries get;
1110 struct ipt_table *t; 1110 struct xt_table *t;
1111 1111
1112 if (*len < sizeof(get)) { 1112 if (*len < sizeof(get)) {
1113 duprintf("get_entries: %u < %d\n", *len, 1113 duprintf("get_entries: %u < %d\n", *len,
@@ -1151,7 +1151,7 @@ __do_replace(const char *name, unsigned int valid_hooks,
1151 void __user *counters_ptr) 1151 void __user *counters_ptr)
1152{ 1152{
1153 int ret; 1153 int ret;
1154 struct ipt_table *t; 1154 struct xt_table *t;
1155 struct xt_table_info *oldinfo; 1155 struct xt_table_info *oldinfo;
1156 struct xt_counters *counters; 1156 struct xt_counters *counters;
1157 void *loc_cpu_old_entry; 1157 void *loc_cpu_old_entry;
@@ -1302,7 +1302,7 @@ do_add_counters(void __user *user, unsigned int len, int compat)
1302 char *name; 1302 char *name;
1303 int size; 1303 int size;
1304 void *ptmp; 1304 void *ptmp;
1305 struct ipt_table *t; 1305 struct xt_table *t;
1306 struct xt_table_info *private; 1306 struct xt_table_info *private;
1307 int ret = 0; 1307 int ret = 0;
1308 void *loc_cpu_entry; 1308 void *loc_cpu_entry;
@@ -1437,7 +1437,7 @@ compat_check_calc_match(struct ipt_entry_match *m,
1437 unsigned int hookmask, 1437 unsigned int hookmask,
1438 int *size, int *i) 1438 int *size, int *i)
1439{ 1439{
1440 struct ipt_match *match; 1440 struct xt_match *match;
1441 1441
1442 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, 1442 match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name,
1443 m->u.user.revision), 1443 m->u.user.revision),
@@ -1466,7 +1466,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e,
1466 const char *name) 1466 const char *name)
1467{ 1467{
1468 struct ipt_entry_target *t; 1468 struct ipt_entry_target *t;
1469 struct ipt_target *target; 1469 struct xt_target *target;
1470 unsigned int entry_offset; 1470 unsigned int entry_offset;
1471 int ret, off, h, j; 1471 int ret, off, h, j;
1472 1472
@@ -1550,7 +1550,7 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr,
1550 struct xt_table_info *newinfo, unsigned char *base) 1550 struct xt_table_info *newinfo, unsigned char *base)
1551{ 1551{
1552 struct ipt_entry_target *t; 1552 struct ipt_entry_target *t;
1553 struct ipt_target *target; 1553 struct xt_target *target;
1554 struct ipt_entry *de; 1554 struct ipt_entry *de;
1555 unsigned int origsize; 1555 unsigned int origsize;
1556 int ret, h; 1556 int ret, h;
@@ -1795,7 +1795,7 @@ struct compat_ipt_get_entries
1795}; 1795};
1796 1796
1797static int compat_copy_entries_to_user(unsigned int total_size, 1797static int compat_copy_entries_to_user(unsigned int total_size,
1798 struct ipt_table *table, void __user *userptr) 1798 struct xt_table *table, void __user *userptr)
1799{ 1799{
1800 unsigned int off, num; 1800 unsigned int off, num;
1801 struct compat_ipt_entry e; 1801 struct compat_ipt_entry e;
@@ -1869,7 +1869,7 @@ compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len)
1869{ 1869{
1870 int ret; 1870 int ret;
1871 struct compat_ipt_get_entries get; 1871 struct compat_ipt_get_entries get;
1872 struct ipt_table *t; 1872 struct xt_table *t;
1873 1873
1874 1874
1875 if (*len < sizeof(get)) { 1875 if (*len < sizeof(get)) {
@@ -2052,7 +2052,7 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
2052 return 0; 2052 return 0;
2053} 2053}
2054 2054
2055void ipt_unregister_table(struct ipt_table *table) 2055void ipt_unregister_table(struct xt_table *table)
2056{ 2056{
2057 struct xt_table_info *private; 2057 struct xt_table_info *private;
2058 void *loc_cpu_entry; 2058 void *loc_cpu_entry;
@@ -2124,7 +2124,7 @@ icmp_checkentry(const char *tablename,
2124} 2124}
2125 2125
2126/* The built-in targets: standard (NULL) and error. */ 2126/* The built-in targets: standard (NULL) and error. */
2127static struct ipt_target ipt_standard_target = { 2127static struct xt_target ipt_standard_target = {
2128 .name = IPT_STANDARD_TARGET, 2128 .name = IPT_STANDARD_TARGET,
2129 .targetsize = sizeof(int), 2129 .targetsize = sizeof(int),
2130 .family = AF_INET, 2130 .family = AF_INET,
@@ -2135,7 +2135,7 @@ static struct ipt_target ipt_standard_target = {
2135#endif 2135#endif
2136}; 2136};
2137 2137
2138static struct ipt_target ipt_error_target = { 2138static struct xt_target ipt_error_target = {
2139 .name = IPT_ERROR_TARGET, 2139 .name = IPT_ERROR_TARGET,
2140 .target = ipt_error, 2140 .target = ipt_error,
2141 .targetsize = IPT_FUNCTION_MAXNAMELEN, 2141 .targetsize = IPT_FUNCTION_MAXNAMELEN,
@@ -2158,7 +2158,7 @@ static struct nf_sockopt_ops ipt_sockopts = {
2158#endif 2158#endif
2159}; 2159};
2160 2160
2161static struct ipt_match icmp_matchstruct = { 2161static struct xt_match icmp_matchstruct = {
2162 .name = "icmp", 2162 .name = "icmp",
2163 .match = icmp_match, 2163 .match = icmp_match,
2164 .matchsize = sizeof(struct ipt_icmp), 2164 .matchsize = sizeof(struct ipt_icmp),
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index b1c11160b9de..343c2abdc1a0 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -26,6 +26,7 @@
26 26
27#include <linux/netfilter_arp.h> 27#include <linux/netfilter_arp.h>
28 28
29#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_ipv4/ip_tables.h> 30#include <linux/netfilter_ipv4/ip_tables.h>
30#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> 31#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
31#include <net/netfilter/nf_conntrack_compat.h> 32#include <net/netfilter/nf_conntrack_compat.h>
@@ -247,6 +248,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
247 switch (iph->protocol) { 248 switch (iph->protocol) {
248 case IPPROTO_TCP: 249 case IPPROTO_TCP:
249 case IPPROTO_UDP: 250 case IPPROTO_UDP:
251 case IPPROTO_UDPLITE:
250 case IPPROTO_SCTP: 252 case IPPROTO_SCTP:
251 case IPPROTO_DCCP: 253 case IPPROTO_DCCP:
252 case IPPROTO_ICMP: 254 case IPPROTO_ICMP:
@@ -329,7 +331,7 @@ target(struct sk_buff **pskb,
329 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 331 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
330 && (ctinfo == IP_CT_RELATED 332 && (ctinfo == IP_CT_RELATED
331 || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY)) 333 || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
332 return IPT_CONTINUE; 334 return XT_CONTINUE;
333 335
334 /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, 336 /* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
335 * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here 337 * TIMESTAMP, INFO_REQUEST or ADDRESS type icmp packets from here
@@ -367,7 +369,7 @@ target(struct sk_buff **pskb,
367 * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */ 369 * actually a unicast IP packet. TCP doesn't like PACKET_MULTICAST */
368 (*pskb)->pkt_type = PACKET_HOST; 370 (*pskb)->pkt_type = PACKET_HOST;
369 371
370 return IPT_CONTINUE; 372 return XT_CONTINUE;
371} 373}
372 374
373static int 375static int
@@ -470,8 +472,9 @@ static void destroy(const struct xt_target *target, void *targinfo)
470 nf_ct_l3proto_module_put(target->family); 472 nf_ct_l3proto_module_put(target->family);
471} 473}
472 474
473static struct ipt_target clusterip_tgt = { 475static struct xt_target clusterip_tgt = {
474 .name = "CLUSTERIP", 476 .name = "CLUSTERIP",
477 .family = AF_INET,
475 .target = target, 478 .target = target,
476 .targetsize = sizeof(struct ipt_clusterip_tgt_info), 479 .targetsize = sizeof(struct ipt_clusterip_tgt_info),
477 .checkentry = checkentry, 480 .checkentry = checkentry,
@@ -727,7 +730,7 @@ static int __init ipt_clusterip_init(void)
727{ 730{
728 int ret; 731 int ret;
729 732
730 ret = ipt_register_target(&clusterip_tgt); 733 ret = xt_register_target(&clusterip_tgt);
731 if (ret < 0) 734 if (ret < 0)
732 return ret; 735 return ret;
733 736
@@ -753,7 +756,7 @@ cleanup_hook:
753 nf_unregister_hook(&cip_arp_ops); 756 nf_unregister_hook(&cip_arp_ops);
754#endif /* CONFIG_PROC_FS */ 757#endif /* CONFIG_PROC_FS */
755cleanup_target: 758cleanup_target:
756 ipt_unregister_target(&clusterip_tgt); 759 xt_unregister_target(&clusterip_tgt);
757 return ret; 760 return ret;
758} 761}
759 762
@@ -765,7 +768,7 @@ static void __exit ipt_clusterip_fini(void)
765 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent); 768 remove_proc_entry(clusterip_procdir->name, clusterip_procdir->parent);
766#endif 769#endif
767 nf_unregister_hook(&cip_arp_ops); 770 nf_unregister_hook(&cip_arp_ops);
768 ipt_unregister_target(&clusterip_tgt); 771 xt_unregister_target(&clusterip_tgt);
769} 772}
770 773
771module_init(ipt_clusterip_init); 774module_init(ipt_clusterip_init);
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index b55d670a24df..b5ca5938d1fe 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -9,12 +9,14 @@
9 * ipt_ECN.c,v 1.5 2002/08/18 19:36:51 laforge Exp 9 * ipt_ECN.c,v 1.5 2002/08/18 19:36:51 laforge Exp
10*/ 10*/
11 11
12#include <linux/in.h>
12#include <linux/module.h> 13#include <linux/module.h>
13#include <linux/skbuff.h> 14#include <linux/skbuff.h>
14#include <linux/ip.h> 15#include <linux/ip.h>
15#include <linux/tcp.h> 16#include <linux/tcp.h>
16#include <net/checksum.h> 17#include <net/checksum.h>
17 18
19#include <linux/netfilter/x_tables.h>
18#include <linux/netfilter_ipv4/ip_tables.h> 20#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv4/ipt_ECN.h> 21#include <linux/netfilter_ipv4/ipt_ECN.h>
20 22
@@ -95,7 +97,7 @@ target(struct sk_buff **pskb,
95 if (!set_ect_tcp(pskb, einfo)) 97 if (!set_ect_tcp(pskb, einfo))
96 return NF_DROP; 98 return NF_DROP;
97 99
98 return IPT_CONTINUE; 100 return XT_CONTINUE;
99} 101}
100 102
101static int 103static int
@@ -119,7 +121,7 @@ checkentry(const char *tablename,
119 return 0; 121 return 0;
120 } 122 }
121 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR)) 123 if ((einfo->operation & (IPT_ECN_OP_SET_ECE|IPT_ECN_OP_SET_CWR))
122 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO))) { 124 && (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & XT_INV_PROTO))) {
123 printk(KERN_WARNING "ECN: cannot use TCP operations on a " 125 printk(KERN_WARNING "ECN: cannot use TCP operations on a "
124 "non-tcp rule\n"); 126 "non-tcp rule\n");
125 return 0; 127 return 0;
@@ -127,8 +129,9 @@ checkentry(const char *tablename,
127 return 1; 129 return 1;
128} 130}
129 131
130static struct ipt_target ipt_ecn_reg = { 132static struct xt_target ipt_ecn_reg = {
131 .name = "ECN", 133 .name = "ECN",
134 .family = AF_INET,
132 .target = target, 135 .target = target,
133 .targetsize = sizeof(struct ipt_ECN_info), 136 .targetsize = sizeof(struct ipt_ECN_info),
134 .table = "mangle", 137 .table = "mangle",
@@ -138,12 +141,12 @@ static struct ipt_target ipt_ecn_reg = {
138 141
139static int __init ipt_ecn_init(void) 142static int __init ipt_ecn_init(void)
140{ 143{
141 return ipt_register_target(&ipt_ecn_reg); 144 return xt_register_target(&ipt_ecn_reg);
142} 145}
143 146
144static void __exit ipt_ecn_fini(void) 147static void __exit ipt_ecn_fini(void)
145{ 148{
146 ipt_unregister_target(&ipt_ecn_reg); 149 xt_unregister_target(&ipt_ecn_reg);
147} 150}
148 151
149module_init(ipt_ecn_init); 152module_init(ipt_ecn_init);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index c96de16fefae..f68370ffb43f 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -20,7 +20,7 @@
20#include <net/route.h> 20#include <net/route.h>
21 21
22#include <linux/netfilter.h> 22#include <linux/netfilter.h>
23#include <linux/netfilter_ipv4/ip_tables.h> 23#include <linux/netfilter/x_tables.h>
24#include <linux/netfilter_ipv4/ipt_LOG.h> 24#include <linux/netfilter_ipv4/ipt_LOG.h>
25 25
26MODULE_LICENSE("GPL"); 26MODULE_LICENSE("GPL");
@@ -432,7 +432,7 @@ ipt_log_target(struct sk_buff **pskb,
432 432
433 ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li, 433 ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
434 loginfo->prefix); 434 loginfo->prefix);
435 return IPT_CONTINUE; 435 return XT_CONTINUE;
436} 436}
437 437
438static int ipt_log_checkentry(const char *tablename, 438static int ipt_log_checkentry(const char *tablename,
@@ -455,8 +455,9 @@ static int ipt_log_checkentry(const char *tablename,
455 return 1; 455 return 1;
456} 456}
457 457
458static struct ipt_target ipt_log_reg = { 458static struct xt_target ipt_log_reg = {
459 .name = "LOG", 459 .name = "LOG",
460 .family = AF_INET,
460 .target = ipt_log_target, 461 .target = ipt_log_target,
461 .targetsize = sizeof(struct ipt_log_info), 462 .targetsize = sizeof(struct ipt_log_info),
462 .checkentry = ipt_log_checkentry, 463 .checkentry = ipt_log_checkentry,
@@ -471,8 +472,11 @@ static struct nf_logger ipt_log_logger ={
471 472
472static int __init ipt_log_init(void) 473static int __init ipt_log_init(void)
473{ 474{
474 if (ipt_register_target(&ipt_log_reg)) 475 int ret;
475 return -EINVAL; 476
477 ret = xt_register_target(&ipt_log_reg);
478 if (ret < 0)
479 return ret;
476 if (nf_log_register(PF_INET, &ipt_log_logger) < 0) { 480 if (nf_log_register(PF_INET, &ipt_log_logger) < 0) {
477 printk(KERN_WARNING "ipt_LOG: not logging via system console " 481 printk(KERN_WARNING "ipt_LOG: not logging via system console "
478 "since somebody else already registered for PF_INET\n"); 482 "since somebody else already registered for PF_INET\n");
@@ -486,7 +490,7 @@ static int __init ipt_log_init(void)
486static void __exit ipt_log_fini(void) 490static void __exit ipt_log_fini(void)
487{ 491{
488 nf_log_unregister_logger(&ipt_log_logger); 492 nf_log_unregister_logger(&ipt_log_logger);
489 ipt_unregister_target(&ipt_log_reg); 493 xt_unregister_target(&ipt_log_reg);
490} 494}
491 495
492module_init(ipt_log_init); 496module_init(ipt_log_init);
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index d669685afd04..91c42efcd533 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -25,7 +25,7 @@
25#else 25#else
26#include <linux/netfilter_ipv4/ip_nat_rule.h> 26#include <linux/netfilter_ipv4/ip_nat_rule.h>
27#endif 27#endif
28#include <linux/netfilter_ipv4/ip_tables.h> 28#include <linux/netfilter/x_tables.h>
29 29
30MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 31MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -190,8 +190,9 @@ static struct notifier_block masq_inet_notifier = {
190 .notifier_call = masq_inet_event, 190 .notifier_call = masq_inet_event,
191}; 191};
192 192
193static struct ipt_target masquerade = { 193static struct xt_target masquerade = {
194 .name = "MASQUERADE", 194 .name = "MASQUERADE",
195 .family = AF_INET,
195 .target = masquerade_target, 196 .target = masquerade_target,
196 .targetsize = sizeof(struct ip_nat_multi_range_compat), 197 .targetsize = sizeof(struct ip_nat_multi_range_compat),
197 .table = "nat", 198 .table = "nat",
@@ -204,7 +205,7 @@ static int __init ipt_masquerade_init(void)
204{ 205{
205 int ret; 206 int ret;
206 207
207 ret = ipt_register_target(&masquerade); 208 ret = xt_register_target(&masquerade);
208 209
209 if (ret == 0) { 210 if (ret == 0) {
210 /* Register for device down reports */ 211 /* Register for device down reports */
@@ -218,7 +219,7 @@ static int __init ipt_masquerade_init(void)
218 219
219static void __exit ipt_masquerade_fini(void) 220static void __exit ipt_masquerade_fini(void)
220{ 221{
221 ipt_unregister_target(&masquerade); 222 xt_unregister_target(&masquerade);
222 unregister_netdevice_notifier(&masq_dev_notifier); 223 unregister_netdevice_notifier(&masq_dev_notifier);
223 unregister_inetaddr_notifier(&masq_inet_notifier); 224 unregister_inetaddr_notifier(&masq_inet_notifier);
224} 225}
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 9390e90f2b25..b4acc241d898 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -15,6 +15,7 @@
15#include <linux/netdevice.h> 15#include <linux/netdevice.h>
16#include <linux/netfilter.h> 16#include <linux/netfilter.h>
17#include <linux/netfilter_ipv4.h> 17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter/x_tables.h>
18#ifdef CONFIG_NF_NAT_NEEDED 19#ifdef CONFIG_NF_NAT_NEEDED
19#include <net/netfilter/nf_nat_rule.h> 20#include <net/netfilter/nf_nat_rule.h>
20#else 21#else
@@ -88,8 +89,9 @@ target(struct sk_buff **pskb,
88 return ip_nat_setup_info(ct, &newrange, hooknum); 89 return ip_nat_setup_info(ct, &newrange, hooknum);
89} 90}
90 91
91static struct ipt_target target_module = { 92static struct xt_target target_module = {
92 .name = MODULENAME, 93 .name = MODULENAME,
94 .family = AF_INET,
93 .target = target, 95 .target = target,
94 .targetsize = sizeof(struct ip_nat_multi_range_compat), 96 .targetsize = sizeof(struct ip_nat_multi_range_compat),
95 .table = "nat", 97 .table = "nat",
@@ -101,12 +103,12 @@ static struct ipt_target target_module = {
101 103
102static int __init ipt_netmap_init(void) 104static int __init ipt_netmap_init(void)
103{ 105{
104 return ipt_register_target(&target_module); 106 return xt_register_target(&target_module);
105} 107}
106 108
107static void __exit ipt_netmap_fini(void) 109static void __exit ipt_netmap_fini(void)
108{ 110{
109 ipt_unregister_target(&target_module); 111 xt_unregister_target(&target_module);
110} 112}
111 113
112module_init(ipt_netmap_init); 114module_init(ipt_netmap_init);
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 462eceb3a1b1..54cd021aa5a8 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -18,6 +18,7 @@
18#include <net/protocol.h> 18#include <net/protocol.h>
19#include <net/checksum.h> 19#include <net/checksum.h>
20#include <linux/netfilter_ipv4.h> 20#include <linux/netfilter_ipv4.h>
21#include <linux/netfilter/x_tables.h>
21#ifdef CONFIG_NF_NAT_NEEDED 22#ifdef CONFIG_NF_NAT_NEEDED
22#include <net/netfilter/nf_nat_rule.h> 23#include <net/netfilter/nf_nat_rule.h>
23#else 24#else
@@ -104,8 +105,9 @@ redirect_target(struct sk_buff **pskb,
104 return ip_nat_setup_info(ct, &newrange, hooknum); 105 return ip_nat_setup_info(ct, &newrange, hooknum);
105} 106}
106 107
107static struct ipt_target redirect_reg = { 108static struct xt_target redirect_reg = {
108 .name = "REDIRECT", 109 .name = "REDIRECT",
110 .family = AF_INET,
109 .target = redirect_target, 111 .target = redirect_target,
110 .targetsize = sizeof(struct ip_nat_multi_range_compat), 112 .targetsize = sizeof(struct ip_nat_multi_range_compat),
111 .table = "nat", 113 .table = "nat",
@@ -116,12 +118,12 @@ static struct ipt_target redirect_reg = {
116 118
117static int __init ipt_redirect_init(void) 119static int __init ipt_redirect_init(void)
118{ 120{
119 return ipt_register_target(&redirect_reg); 121 return xt_register_target(&redirect_reg);
120} 122}
121 123
122static void __exit ipt_redirect_fini(void) 124static void __exit ipt_redirect_fini(void)
123{ 125{
124 ipt_unregister_target(&redirect_reg); 126 xt_unregister_target(&redirect_reg);
125} 127}
126 128
127module_init(ipt_redirect_init); 129module_init(ipt_redirect_init);
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index f0319e5ee437..e4a1ddb386a7 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -22,6 +22,7 @@
22#include <net/tcp.h> 22#include <net/tcp.h>
23#include <net/route.h> 23#include <net/route.h>
24#include <net/dst.h> 24#include <net/dst.h>
25#include <linux/netfilter/x_tables.h>
25#include <linux/netfilter_ipv4/ip_tables.h> 26#include <linux/netfilter_ipv4/ip_tables.h>
26#include <linux/netfilter_ipv4/ipt_REJECT.h> 27#include <linux/netfilter_ipv4/ipt_REJECT.h>
27#ifdef CONFIG_BRIDGE_NETFILTER 28#ifdef CONFIG_BRIDGE_NETFILTER
@@ -116,7 +117,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
116 117
117 /* Adjust TCP checksum */ 118 /* Adjust TCP checksum */
118 tcph->check = 0; 119 tcph->check = 0;
119 tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), 120 tcph->check = tcp_v4_check(sizeof(struct tcphdr),
120 nskb->nh.iph->saddr, 121 nskb->nh.iph->saddr,
121 nskb->nh.iph->daddr, 122 nskb->nh.iph->daddr,
122 csum_partial((char *)tcph, 123 csum_partial((char *)tcph,
@@ -230,7 +231,7 @@ static int check(const char *tablename,
230 } else if (rejinfo->with == IPT_TCP_RESET) { 231 } else if (rejinfo->with == IPT_TCP_RESET) {
231 /* Must specify that it's a TCP packet */ 232 /* Must specify that it's a TCP packet */
232 if (e->ip.proto != IPPROTO_TCP 233 if (e->ip.proto != IPPROTO_TCP
233 || (e->ip.invflags & IPT_INV_PROTO)) { 234 || (e->ip.invflags & XT_INV_PROTO)) {
234 DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n"); 235 DEBUGP("REJECT: TCP_RESET invalid for non-tcp\n");
235 return 0; 236 return 0;
236 } 237 }
@@ -238,8 +239,9 @@ static int check(const char *tablename,
238 return 1; 239 return 1;
239} 240}
240 241
241static struct ipt_target ipt_reject_reg = { 242static struct xt_target ipt_reject_reg = {
242 .name = "REJECT", 243 .name = "REJECT",
244 .family = AF_INET,
243 .target = reject, 245 .target = reject,
244 .targetsize = sizeof(struct ipt_reject_info), 246 .targetsize = sizeof(struct ipt_reject_info),
245 .table = "filter", 247 .table = "filter",
@@ -251,12 +253,12 @@ static struct ipt_target ipt_reject_reg = {
251 253
252static int __init ipt_reject_init(void) 254static int __init ipt_reject_init(void)
253{ 255{
254 return ipt_register_target(&ipt_reject_reg); 256 return xt_register_target(&ipt_reject_reg);
255} 257}
256 258
257static void __exit ipt_reject_fini(void) 259static void __exit ipt_reject_fini(void)
258{ 260{
259 ipt_unregister_target(&ipt_reject_reg); 261 xt_unregister_target(&ipt_reject_reg);
260} 262}
261 263
262module_init(ipt_reject_init); 264module_init(ipt_reject_init);
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index 3dcf29411337..a1cdd1262de2 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -34,6 +34,7 @@
34#include <net/protocol.h> 34#include <net/protocol.h>
35#include <net/checksum.h> 35#include <net/checksum.h>
36#include <linux/netfilter_ipv4.h> 36#include <linux/netfilter_ipv4.h>
37#include <linux/netfilter/x_tables.h>
37#ifdef CONFIG_NF_NAT_NEEDED 38#ifdef CONFIG_NF_NAT_NEEDED
38#include <net/netfilter/nf_nat_rule.h> 39#include <net/netfilter/nf_nat_rule.h>
39#else 40#else
@@ -186,8 +187,9 @@ same_target(struct sk_buff **pskb,
186 return ip_nat_setup_info(ct, &newrange, hooknum); 187 return ip_nat_setup_info(ct, &newrange, hooknum);
187} 188}
188 189
189static struct ipt_target same_reg = { 190static struct xt_target same_reg = {
190 .name = "SAME", 191 .name = "SAME",
192 .family = AF_INET,
191 .target = same_target, 193 .target = same_target,
192 .targetsize = sizeof(struct ipt_same_info), 194 .targetsize = sizeof(struct ipt_same_info),
193 .table = "nat", 195 .table = "nat",
@@ -199,12 +201,12 @@ static struct ipt_target same_reg = {
199 201
200static int __init ipt_same_init(void) 202static int __init ipt_same_init(void)
201{ 203{
202 return ipt_register_target(&same_reg); 204 return xt_register_target(&same_reg);
203} 205}
204 206
205static void __exit ipt_same_fini(void) 207static void __exit ipt_same_fini(void)
206{ 208{
207 ipt_unregister_target(&same_reg); 209 xt_unregister_target(&same_reg);
208} 210}
209 211
210module_init(ipt_same_init); 212module_init(ipt_same_init);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
deleted file mode 100644
index 93eb5c3c1884..000000000000
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ /dev/null
@@ -1,207 +0,0 @@
1/*
2 * This is a module which is used for setting the MSS option in TCP packets.
3 *
4 * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
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#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/ip.h>
15#include <net/tcp.h>
16
17#include <linux/netfilter_ipv4/ip_tables.h>
18#include <linux/netfilter_ipv4/ipt_TCPMSS.h>
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
22MODULE_DESCRIPTION("iptables TCP MSS modification module");
23
24static inline unsigned int
25optlen(const u_int8_t *opt, unsigned int offset)
26{
27 /* Beware zero-length options: make finite progress */
28 if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0)
29 return 1;
30 else
31 return opt[offset+1];
32}
33
34static unsigned int
35ipt_tcpmss_target(struct sk_buff **pskb,
36 const struct net_device *in,
37 const struct net_device *out,
38 unsigned int hooknum,
39 const struct xt_target *target,
40 const void *targinfo)
41{
42 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
43 struct tcphdr *tcph;
44 struct iphdr *iph;
45 u_int16_t tcplen, newmss;
46 __be16 newtotlen, oldval;
47 unsigned int i;
48 u_int8_t *opt;
49
50 if (!skb_make_writable(pskb, (*pskb)->len))
51 return NF_DROP;
52
53 iph = (*pskb)->nh.iph;
54 tcplen = (*pskb)->len - iph->ihl*4;
55 tcph = (void *)iph + iph->ihl*4;
56
57 /* Since it passed flags test in tcp match, we know it is is
58 not a fragment, and has data >= tcp header length. SYN
59 packets should not contain data: if they did, then we risk
60 running over MTU, sending Frag Needed and breaking things
61 badly. --RR */
62 if (tcplen != tcph->doff*4) {
63 if (net_ratelimit())
64 printk(KERN_ERR
65 "ipt_tcpmss_target: bad length (%d bytes)\n",
66 (*pskb)->len);
67 return NF_DROP;
68 }
69
70 if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) {
71 if (dst_mtu((*pskb)->dst) <= sizeof(struct iphdr) +
72 sizeof(struct tcphdr)) {
73 if (net_ratelimit())
74 printk(KERN_ERR "ipt_tcpmss_target: "
75 "unknown or invalid path-MTU (%d)\n",
76 dst_mtu((*pskb)->dst));
77 return NF_DROP; /* or IPT_CONTINUE ?? */
78 }
79
80 newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) -
81 sizeof(struct tcphdr);
82 } else
83 newmss = tcpmssinfo->mss;
84
85 opt = (u_int8_t *)tcph;
86 for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
87 if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
88 opt[i+1] == TCPOLEN_MSS) {
89 u_int16_t oldmss;
90
91 oldmss = (opt[i+2] << 8) | opt[i+3];
92
93 if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU &&
94 oldmss <= newmss)
95 return IPT_CONTINUE;
96
97 opt[i+2] = (newmss & 0xff00) >> 8;
98 opt[i+3] = (newmss & 0x00ff);
99
100 nf_proto_csum_replace2(&tcph->check, *pskb,
101 htons(oldmss), htons(newmss), 0);
102 return IPT_CONTINUE;
103 }
104 }
105
106 /*
107 * MSS Option not found ?! add it..
108 */
109 if (skb_tailroom((*pskb)) < TCPOLEN_MSS) {
110 struct sk_buff *newskb;
111
112 newskb = skb_copy_expand(*pskb, skb_headroom(*pskb),
113 TCPOLEN_MSS, GFP_ATOMIC);
114 if (!newskb)
115 return NF_DROP;
116 kfree_skb(*pskb);
117 *pskb = newskb;
118 iph = (*pskb)->nh.iph;
119 tcph = (void *)iph + iph->ihl*4;
120 }
121
122 skb_put((*pskb), TCPOLEN_MSS);
123
124 opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
125 memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
126
127 nf_proto_csum_replace2(&tcph->check, *pskb,
128 htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
129 opt[0] = TCPOPT_MSS;
130 opt[1] = TCPOLEN_MSS;
131 opt[2] = (newmss & 0xff00) >> 8;
132 opt[3] = (newmss & 0x00ff);
133
134 nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
135
136 oldval = ((__be16 *)tcph)[6];
137 tcph->doff += TCPOLEN_MSS/4;
138 nf_proto_csum_replace2(&tcph->check, *pskb,
139 oldval, ((__be16 *)tcph)[6], 0);
140
141 newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
142 nf_csum_replace2(&iph->check, iph->tot_len, newtotlen);
143 iph->tot_len = newtotlen;
144 return IPT_CONTINUE;
145}
146
147#define TH_SYN 0x02
148
149static inline int find_syn_match(const struct ipt_entry_match *m)
150{
151 const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data;
152
153 if (strcmp(m->u.kernel.match->name, "tcp") == 0 &&
154 tcpinfo->flg_cmp & TH_SYN &&
155 !(tcpinfo->invflags & IPT_TCP_INV_FLAGS))
156 return 1;
157
158 return 0;
159}
160
161/* Must specify -p tcp --syn/--tcp-flags SYN */
162static int
163ipt_tcpmss_checkentry(const char *tablename,
164 const void *e_void,
165 const struct xt_target *target,
166 void *targinfo,
167 unsigned int hook_mask)
168{
169 const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
170 const struct ipt_entry *e = e_void;
171
172 if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU &&
173 (hook_mask & ~((1 << NF_IP_FORWARD) |
174 (1 << NF_IP_LOCAL_OUT) |
175 (1 << NF_IP_POST_ROUTING))) != 0) {
176 printk("TCPMSS: path-MTU clamping only supported in "
177 "FORWARD, OUTPUT and POSTROUTING hooks\n");
178 return 0;
179 }
180
181 if (IPT_MATCH_ITERATE(e, find_syn_match))
182 return 1;
183 printk("TCPMSS: Only works on TCP SYN packets\n");
184 return 0;
185}
186
187static struct ipt_target ipt_tcpmss_reg = {
188 .name = "TCPMSS",
189 .target = ipt_tcpmss_target,
190 .targetsize = sizeof(struct ipt_tcpmss_info),
191 .proto = IPPROTO_TCP,
192 .checkentry = ipt_tcpmss_checkentry,
193 .me = THIS_MODULE,
194};
195
196static int __init ipt_tcpmss_init(void)
197{
198 return ipt_register_target(&ipt_tcpmss_reg);
199}
200
201static void __exit ipt_tcpmss_fini(void)
202{
203 ipt_unregister_target(&ipt_tcpmss_reg);
204}
205
206module_init(ipt_tcpmss_init);
207module_exit(ipt_tcpmss_fini);
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 18e74ac4d425..29b05a6bd108 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -13,7 +13,7 @@
13#include <linux/ip.h> 13#include <linux/ip.h>
14#include <net/checksum.h> 14#include <net/checksum.h>
15 15
16#include <linux/netfilter_ipv4/ip_tables.h> 16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter_ipv4/ipt_TOS.h> 17#include <linux/netfilter_ipv4/ipt_TOS.h>
18 18
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
@@ -40,7 +40,7 @@ target(struct sk_buff **pskb,
40 iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; 40 iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
41 nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos)); 41 nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
42 } 42 }
43 return IPT_CONTINUE; 43 return XT_CONTINUE;
44} 44}
45 45
46static int 46static int
@@ -63,8 +63,9 @@ checkentry(const char *tablename,
63 return 1; 63 return 1;
64} 64}
65 65
66static struct ipt_target ipt_tos_reg = { 66static struct xt_target ipt_tos_reg = {
67 .name = "TOS", 67 .name = "TOS",
68 .family = AF_INET,
68 .target = target, 69 .target = target,
69 .targetsize = sizeof(struct ipt_tos_target_info), 70 .targetsize = sizeof(struct ipt_tos_target_info),
70 .table = "mangle", 71 .table = "mangle",
@@ -74,12 +75,12 @@ static struct ipt_target ipt_tos_reg = {
74 75
75static int __init ipt_tos_init(void) 76static int __init ipt_tos_init(void)
76{ 77{
77 return ipt_register_target(&ipt_tos_reg); 78 return xt_register_target(&ipt_tos_reg);
78} 79}
79 80
80static void __exit ipt_tos_fini(void) 81static void __exit ipt_tos_fini(void)
81{ 82{
82 ipt_unregister_target(&ipt_tos_reg); 83 xt_unregister_target(&ipt_tos_reg);
83} 84}
84 85
85module_init(ipt_tos_init); 86module_init(ipt_tos_init);
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index fffe5ca82e91..d2b6fa3f9dcd 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -12,7 +12,7 @@
12#include <linux/ip.h> 12#include <linux/ip.h>
13#include <net/checksum.h> 13#include <net/checksum.h>
14 14
15#include <linux/netfilter_ipv4/ip_tables.h> 15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter_ipv4/ipt_TTL.h> 16#include <linux/netfilter_ipv4/ipt_TTL.h>
17 17
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -59,7 +59,7 @@ ipt_ttl_target(struct sk_buff **pskb,
59 iph->ttl = new_ttl; 59 iph->ttl = new_ttl;
60 } 60 }
61 61
62 return IPT_CONTINUE; 62 return XT_CONTINUE;
63} 63}
64 64
65static int ipt_ttl_checkentry(const char *tablename, 65static int ipt_ttl_checkentry(const char *tablename,
@@ -80,8 +80,9 @@ static int ipt_ttl_checkentry(const char *tablename,
80 return 1; 80 return 1;
81} 81}
82 82
83static struct ipt_target ipt_TTL = { 83static struct xt_target ipt_TTL = {
84 .name = "TTL", 84 .name = "TTL",
85 .family = AF_INET,
85 .target = ipt_ttl_target, 86 .target = ipt_ttl_target,
86 .targetsize = sizeof(struct ipt_TTL_info), 87 .targetsize = sizeof(struct ipt_TTL_info),
87 .table = "mangle", 88 .table = "mangle",
@@ -91,12 +92,12 @@ static struct ipt_target ipt_TTL = {
91 92
92static int __init ipt_ttl_init(void) 93static int __init ipt_ttl_init(void)
93{ 94{
94 return ipt_register_target(&ipt_TTL); 95 return xt_register_target(&ipt_TTL);
95} 96}
96 97
97static void __exit ipt_ttl_fini(void) 98static void __exit ipt_ttl_fini(void)
98{ 99{
99 ipt_unregister_target(&ipt_TTL); 100 xt_unregister_target(&ipt_TTL);
100} 101}
101 102
102module_init(ipt_ttl_init); 103module_init(ipt_ttl_init);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index dbd34783a64d..7af57a3a1f36 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -57,7 +57,7 @@
57#include <linux/mm.h> 57#include <linux/mm.h>
58#include <linux/moduleparam.h> 58#include <linux/moduleparam.h>
59#include <linux/netfilter.h> 59#include <linux/netfilter.h>
60#include <linux/netfilter_ipv4/ip_tables.h> 60#include <linux/netfilter/x_tables.h>
61#include <linux/netfilter_ipv4/ipt_ULOG.h> 61#include <linux/netfilter_ipv4/ipt_ULOG.h>
62#include <net/sock.h> 62#include <net/sock.h>
63#include <linux/bitops.h> 63#include <linux/bitops.h>
@@ -132,7 +132,6 @@ static void ulog_send(unsigned int nlgroupnum)
132 ub->qlen = 0; 132 ub->qlen = 0;
133 ub->skb = NULL; 133 ub->skb = NULL;
134 ub->lastnlh = NULL; 134 ub->lastnlh = NULL;
135
136} 135}
137 136
138 137
@@ -314,7 +313,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
314 313
315 ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL); 314 ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
316 315
317 return IPT_CONTINUE; 316 return XT_CONTINUE;
318} 317}
319 318
320static void ipt_logfn(unsigned int pf, 319static void ipt_logfn(unsigned int pf,
@@ -363,8 +362,9 @@ static int ipt_ulog_checkentry(const char *tablename,
363 return 1; 362 return 1;
364} 363}
365 364
366static struct ipt_target ipt_ulog_reg = { 365static struct xt_target ipt_ulog_reg = {
367 .name = "ULOG", 366 .name = "ULOG",
367 .family = AF_INET,
368 .target = ipt_ulog_target, 368 .target = ipt_ulog_target,
369 .targetsize = sizeof(struct ipt_ulog_info), 369 .targetsize = sizeof(struct ipt_ulog_info),
370 .checkentry = ipt_ulog_checkentry, 370 .checkentry = ipt_ulog_checkentry,
@@ -379,7 +379,7 @@ static struct nf_logger ipt_ulog_logger = {
379 379
380static int __init ipt_ulog_init(void) 380static int __init ipt_ulog_init(void)
381{ 381{
382 int i; 382 int ret, i;
383 383
384 DEBUGP("ipt_ULOG: init module\n"); 384 DEBUGP("ipt_ULOG: init module\n");
385 385
@@ -400,9 +400,10 @@ static int __init ipt_ulog_init(void)
400 if (!nflognl) 400 if (!nflognl)
401 return -ENOMEM; 401 return -ENOMEM;
402 402
403 if (ipt_register_target(&ipt_ulog_reg) != 0) { 403 ret = xt_register_target(&ipt_ulog_reg);
404 if (ret < 0) {
404 sock_release(nflognl->sk_socket); 405 sock_release(nflognl->sk_socket);
405 return -EINVAL; 406 return ret;
406 } 407 }
407 if (nflog) 408 if (nflog)
408 nf_log_register(PF_INET, &ipt_ulog_logger); 409 nf_log_register(PF_INET, &ipt_ulog_logger);
@@ -419,7 +420,7 @@ static void __exit ipt_ulog_fini(void)
419 420
420 if (nflog) 421 if (nflog)
421 nf_log_unregister_logger(&ipt_ulog_logger); 422 nf_log_unregister_logger(&ipt_ulog_logger);
422 ipt_unregister_target(&ipt_ulog_reg); 423 xt_unregister_target(&ipt_ulog_reg);
423 sock_release(nflognl->sk_socket); 424 sock_release(nflognl->sk_socket);
424 425
425 /* remove pending timers and free allocated skb's */ 426 /* remove pending timers and free allocated skb's */
@@ -435,7 +436,6 @@ static void __exit ipt_ulog_fini(void)
435 ub->skb = NULL; 436 ub->skb = NULL;
436 } 437 }
437 } 438 }
438
439} 439}
440 440
441module_init(ipt_ulog_init); 441module_init(ipt_ulog_init);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
index 7b60eb74788b..648f555c4d16 100644
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ b/net/ipv4/netfilter/ipt_addrtype.c
@@ -16,7 +16,7 @@
16#include <net/route.h> 16#include <net/route.h>
17 17
18#include <linux/netfilter_ipv4/ipt_addrtype.h> 18#include <linux/netfilter_ipv4/ipt_addrtype.h>
19#include <linux/netfilter_ipv4/ip_tables.h> 19#include <linux/netfilter/x_tables.h>
20 20
21MODULE_LICENSE("GPL"); 21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 22MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
@@ -44,8 +44,9 @@ static int match(const struct sk_buff *skb,
44 return ret; 44 return ret;
45} 45}
46 46
47static struct ipt_match addrtype_match = { 47static struct xt_match addrtype_match = {
48 .name = "addrtype", 48 .name = "addrtype",
49 .family = AF_INET,
49 .match = match, 50 .match = match,
50 .matchsize = sizeof(struct ipt_addrtype_info), 51 .matchsize = sizeof(struct ipt_addrtype_info),
51 .me = THIS_MODULE 52 .me = THIS_MODULE
@@ -53,12 +54,12 @@ static struct ipt_match addrtype_match = {
53 54
54static int __init ipt_addrtype_init(void) 55static int __init ipt_addrtype_init(void)
55{ 56{
56 return ipt_register_match(&addrtype_match); 57 return xt_register_match(&addrtype_match);
57} 58}
58 59
59static void __exit ipt_addrtype_fini(void) 60static void __exit ipt_addrtype_fini(void)
60{ 61{
61 ipt_unregister_match(&addrtype_match); 62 xt_unregister_match(&addrtype_match);
62} 63}
63 64
64module_init(ipt_addrtype_init); 65module_init(ipt_addrtype_init);
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c
index 1798f86bc534..42f41224a43a 100644
--- a/net/ipv4/netfilter/ipt_ah.c
+++ b/net/ipv4/netfilter/ipt_ah.c
@@ -6,12 +6,13 @@
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include <linux/in.h>
9#include <linux/module.h> 10#include <linux/module.h>
10#include <linux/skbuff.h> 11#include <linux/skbuff.h>
11#include <linux/ip.h> 12#include <linux/ip.h>
12 13
13#include <linux/netfilter_ipv4/ipt_ah.h> 14#include <linux/netfilter_ipv4/ipt_ah.h>
14#include <linux/netfilter_ipv4/ip_tables.h> 15#include <linux/netfilter/x_tables.h>
15 16
16MODULE_LICENSE("GPL"); 17MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>"); 18MODULE_AUTHOR("Yon Uriarte <yon@astaro.de>");
@@ -86,8 +87,9 @@ checkentry(const char *tablename,
86 return 1; 87 return 1;
87} 88}
88 89
89static struct ipt_match ah_match = { 90static struct xt_match ah_match = {
90 .name = "ah", 91 .name = "ah",
92 .family = AF_INET,
91 .match = match, 93 .match = match,
92 .matchsize = sizeof(struct ipt_ah), 94 .matchsize = sizeof(struct ipt_ah),
93 .proto = IPPROTO_AH, 95 .proto = IPPROTO_AH,
@@ -97,12 +99,12 @@ static struct ipt_match ah_match = {
97 99
98static int __init ipt_ah_init(void) 100static int __init ipt_ah_init(void)
99{ 101{
100 return ipt_register_match(&ah_match); 102 return xt_register_match(&ah_match);
101} 103}
102 104
103static void __exit ipt_ah_fini(void) 105static void __exit ipt_ah_fini(void)
104{ 106{
105 ipt_unregister_match(&ah_match); 107 xt_unregister_match(&ah_match);
106} 108}
107 109
108module_init(ipt_ah_init); 110module_init(ipt_ah_init);
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c
index dafbdec0efc0..37508b2cfea6 100644
--- a/net/ipv4/netfilter/ipt_ecn.c
+++ b/net/ipv4/netfilter/ipt_ecn.c
@@ -9,10 +9,13 @@
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12#include <linux/in.h>
13#include <linux/ip.h>
12#include <linux/module.h> 14#include <linux/module.h>
13#include <linux/skbuff.h> 15#include <linux/skbuff.h>
14#include <linux/tcp.h> 16#include <linux/tcp.h>
15 17
18#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter_ipv4/ip_tables.h> 19#include <linux/netfilter_ipv4/ip_tables.h>
17#include <linux/netfilter_ipv4/ipt_ecn.h> 20#include <linux/netfilter_ipv4/ipt_ecn.h>
18 21
@@ -109,8 +112,9 @@ static int checkentry(const char *tablename, const void *ip_void,
109 return 1; 112 return 1;
110} 113}
111 114
112static struct ipt_match ecn_match = { 115static struct xt_match ecn_match = {
113 .name = "ecn", 116 .name = "ecn",
117 .family = AF_INET,
114 .match = match, 118 .match = match,
115 .matchsize = sizeof(struct ipt_ecn_info), 119 .matchsize = sizeof(struct ipt_ecn_info),
116 .checkentry = checkentry, 120 .checkentry = checkentry,
@@ -119,12 +123,12 @@ static struct ipt_match ecn_match = {
119 123
120static int __init ipt_ecn_init(void) 124static int __init ipt_ecn_init(void)
121{ 125{
122 return ipt_register_match(&ecn_match); 126 return xt_register_match(&ecn_match);
123} 127}
124 128
125static void __exit ipt_ecn_fini(void) 129static void __exit ipt_ecn_fini(void)
126{ 130{
127 ipt_unregister_match(&ecn_match); 131 xt_unregister_match(&ecn_match);
128} 132}
129 133
130module_init(ipt_ecn_init); 134module_init(ipt_ecn_init);
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c
index 5202edd8d333..05de593be94c 100644
--- a/net/ipv4/netfilter/ipt_iprange.c
+++ b/net/ipv4/netfilter/ipt_iprange.c
@@ -10,7 +10,7 @@
10#include <linux/module.h> 10#include <linux/module.h>
11#include <linux/skbuff.h> 11#include <linux/skbuff.h>
12#include <linux/ip.h> 12#include <linux/ip.h>
13#include <linux/netfilter_ipv4/ip_tables.h> 13#include <linux/netfilter/x_tables.h>
14#include <linux/netfilter_ipv4/ipt_iprange.h> 14#include <linux/netfilter_ipv4/ipt_iprange.h>
15 15
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
@@ -63,22 +63,22 @@ match(const struct sk_buff *skb,
63 return 1; 63 return 1;
64} 64}
65 65
66static struct ipt_match iprange_match = { 66static struct xt_match iprange_match = {
67 .name = "iprange", 67 .name = "iprange",
68 .family = AF_INET,
68 .match = match, 69 .match = match,
69 .matchsize = sizeof(struct ipt_iprange_info), 70 .matchsize = sizeof(struct ipt_iprange_info),
70 .destroy = NULL,
71 .me = THIS_MODULE 71 .me = THIS_MODULE
72}; 72};
73 73
74static int __init ipt_iprange_init(void) 74static int __init ipt_iprange_init(void)
75{ 75{
76 return ipt_register_match(&iprange_match); 76 return xt_register_match(&iprange_match);
77} 77}
78 78
79static void __exit ipt_iprange_fini(void) 79static void __exit ipt_iprange_fini(void)
80{ 80{
81 ipt_unregister_match(&iprange_match); 81 xt_unregister_match(&iprange_match);
82} 82}
83 83
84module_init(ipt_iprange_init); 84module_init(ipt_iprange_init);
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c
index 78c336f12a9e..9f496ac834b5 100644
--- a/net/ipv4/netfilter/ipt_owner.c
+++ b/net/ipv4/netfilter/ipt_owner.c
@@ -15,7 +15,7 @@
15#include <net/sock.h> 15#include <net/sock.h>
16 16
17#include <linux/netfilter_ipv4/ipt_owner.h> 17#include <linux/netfilter_ipv4/ipt_owner.h>
18#include <linux/netfilter_ipv4/ip_tables.h> 18#include <linux/netfilter/x_tables.h>
19 19
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 21MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
@@ -68,8 +68,9 @@ checkentry(const char *tablename,
68 return 1; 68 return 1;
69} 69}
70 70
71static struct ipt_match owner_match = { 71static struct xt_match owner_match = {
72 .name = "owner", 72 .name = "owner",
73 .family = AF_INET,
73 .match = match, 74 .match = match,
74 .matchsize = sizeof(struct ipt_owner_info), 75 .matchsize = sizeof(struct ipt_owner_info),
75 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING), 76 .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING),
@@ -79,12 +80,12 @@ static struct ipt_match owner_match = {
79 80
80static int __init ipt_owner_init(void) 81static int __init ipt_owner_init(void)
81{ 82{
82 return ipt_register_match(&owner_match); 83 return xt_register_match(&owner_match);
83} 84}
84 85
85static void __exit ipt_owner_fini(void) 86static void __exit ipt_owner_fini(void)
86{ 87{
87 ipt_unregister_match(&owner_match); 88 xt_unregister_match(&owner_match);
88} 89}
89 90
90module_init(ipt_owner_init); 91module_init(ipt_owner_init);
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 4db0e73c56f1..6b97b6796173 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -12,6 +12,7 @@
12 * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org 12 * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
13 */ 13 */
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/ip.h>
15#include <linux/moduleparam.h> 16#include <linux/moduleparam.h>
16#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
17#include <linux/seq_file.h> 18#include <linux/seq_file.h>
@@ -24,7 +25,7 @@
24#include <linux/skbuff.h> 25#include <linux/skbuff.h>
25#include <linux/inet.h> 26#include <linux/inet.h>
26 27
27#include <linux/netfilter_ipv4/ip_tables.h> 28#include <linux/netfilter/x_tables.h>
28#include <linux/netfilter_ipv4/ipt_recent.h> 29#include <linux/netfilter_ipv4/ipt_recent.h>
29 30
30MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 31MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
@@ -462,8 +463,9 @@ static struct file_operations recent_fops = {
462}; 463};
463#endif /* CONFIG_PROC_FS */ 464#endif /* CONFIG_PROC_FS */
464 465
465static struct ipt_match recent_match = { 466static struct xt_match recent_match = {
466 .name = "recent", 467 .name = "recent",
468 .family = AF_INET,
467 .match = ipt_recent_match, 469 .match = ipt_recent_match,
468 .matchsize = sizeof(struct ipt_recent_info), 470 .matchsize = sizeof(struct ipt_recent_info),
469 .checkentry = ipt_recent_checkentry, 471 .checkentry = ipt_recent_checkentry,
@@ -479,13 +481,13 @@ static int __init ipt_recent_init(void)
479 return -EINVAL; 481 return -EINVAL;
480 ip_list_hash_size = 1 << fls(ip_list_tot); 482 ip_list_hash_size = 1 << fls(ip_list_tot);
481 483
482 err = ipt_register_match(&recent_match); 484 err = xt_register_match(&recent_match);
483#ifdef CONFIG_PROC_FS 485#ifdef CONFIG_PROC_FS
484 if (err) 486 if (err)
485 return err; 487 return err;
486 proc_dir = proc_mkdir("ipt_recent", proc_net); 488 proc_dir = proc_mkdir("ipt_recent", proc_net);
487 if (proc_dir == NULL) { 489 if (proc_dir == NULL) {
488 ipt_unregister_match(&recent_match); 490 xt_unregister_match(&recent_match);
489 err = -ENOMEM; 491 err = -ENOMEM;
490 } 492 }
491#endif 493#endif
@@ -495,7 +497,7 @@ static int __init ipt_recent_init(void)
495static void __exit ipt_recent_exit(void) 497static void __exit ipt_recent_exit(void)
496{ 498{
497 BUG_ON(!list_empty(&tables)); 499 BUG_ON(!list_empty(&tables));
498 ipt_unregister_match(&recent_match); 500 xt_unregister_match(&recent_match);
499#ifdef CONFIG_PROC_FS 501#ifdef CONFIG_PROC_FS
500 remove_proc_entry("ipt_recent", proc_net); 502 remove_proc_entry("ipt_recent", proc_net);
501#endif 503#endif
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c
index 5549c39c7851..5d33b51d49d8 100644
--- a/net/ipv4/netfilter/ipt_tos.c
+++ b/net/ipv4/netfilter/ipt_tos.c
@@ -8,11 +8,12 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/ip.h>
11#include <linux/module.h> 12#include <linux/module.h>
12#include <linux/skbuff.h> 13#include <linux/skbuff.h>
13 14
14#include <linux/netfilter_ipv4/ipt_tos.h> 15#include <linux/netfilter_ipv4/ipt_tos.h>
15#include <linux/netfilter_ipv4/ip_tables.h> 16#include <linux/netfilter/x_tables.h>
16 17
17MODULE_LICENSE("GPL"); 18MODULE_LICENSE("GPL");
18MODULE_DESCRIPTION("iptables TOS match module"); 19MODULE_DESCRIPTION("iptables TOS match module");
@@ -32,8 +33,9 @@ match(const struct sk_buff *skb,
32 return (skb->nh.iph->tos == info->tos) ^ info->invert; 33 return (skb->nh.iph->tos == info->tos) ^ info->invert;
33} 34}
34 35
35static struct ipt_match tos_match = { 36static struct xt_match tos_match = {
36 .name = "tos", 37 .name = "tos",
38 .family = AF_INET,
37 .match = match, 39 .match = match,
38 .matchsize = sizeof(struct ipt_tos_info), 40 .matchsize = sizeof(struct ipt_tos_info),
39 .me = THIS_MODULE, 41 .me = THIS_MODULE,
@@ -41,12 +43,12 @@ static struct ipt_match tos_match = {
41 43
42static int __init ipt_multiport_init(void) 44static int __init ipt_multiport_init(void)
43{ 45{
44 return ipt_register_match(&tos_match); 46 return xt_register_match(&tos_match);
45} 47}
46 48
47static void __exit ipt_multiport_fini(void) 49static void __exit ipt_multiport_fini(void)
48{ 50{
49 ipt_unregister_match(&tos_match); 51 xt_unregister_match(&tos_match);
50} 52}
51 53
52module_init(ipt_multiport_init); 54module_init(ipt_multiport_init);
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c
index a5243bdb87d7..d5cd984e5ed2 100644
--- a/net/ipv4/netfilter/ipt_ttl.c
+++ b/net/ipv4/netfilter/ipt_ttl.c
@@ -9,11 +9,12 @@
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12#include <linux/ip.h>
12#include <linux/module.h> 13#include <linux/module.h>
13#include <linux/skbuff.h> 14#include <linux/skbuff.h>
14 15
15#include <linux/netfilter_ipv4/ipt_ttl.h> 16#include <linux/netfilter_ipv4/ipt_ttl.h>
16#include <linux/netfilter_ipv4/ip_tables.h> 17#include <linux/netfilter/x_tables.h>
17 18
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("IP tables TTL matching module"); 20MODULE_DESCRIPTION("IP tables TTL matching module");
@@ -48,8 +49,9 @@ static int match(const struct sk_buff *skb,
48 return 0; 49 return 0;
49} 50}
50 51
51static struct ipt_match ttl_match = { 52static struct xt_match ttl_match = {
52 .name = "ttl", 53 .name = "ttl",
54 .family = AF_INET,
53 .match = match, 55 .match = match,
54 .matchsize = sizeof(struct ipt_ttl_info), 56 .matchsize = sizeof(struct ipt_ttl_info),
55 .me = THIS_MODULE, 57 .me = THIS_MODULE,
@@ -57,13 +59,12 @@ static struct ipt_match ttl_match = {
57 59
58static int __init ipt_ttl_init(void) 60static int __init ipt_ttl_init(void)
59{ 61{
60 return ipt_register_match(&ttl_match); 62 return xt_register_match(&ttl_match);
61} 63}
62 64
63static void __exit ipt_ttl_fini(void) 65static void __exit ipt_ttl_fini(void)
64{ 66{
65 ipt_unregister_match(&ttl_match); 67 xt_unregister_match(&ttl_match);
66
67} 68}
68 69
69module_init(ipt_ttl_init); 70module_init(ipt_ttl_init);
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index e2e7dd8d7903..51053cb42f43 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -74,7 +74,7 @@ static struct
74 } 74 }
75}; 75};
76 76
77static struct ipt_table packet_filter = { 77static struct xt_table packet_filter = {
78 .name = "filter", 78 .name = "filter",
79 .valid_hooks = FILTER_VALID_HOOKS, 79 .valid_hooks = FILTER_VALID_HOOKS,
80 .lock = RW_LOCK_UNLOCKED, 80 .lock = RW_LOCK_UNLOCKED,
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index af2939889444..a532e4d84332 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -103,7 +103,7 @@ static struct
103 } 103 }
104}; 104};
105 105
106static struct ipt_table packet_mangler = { 106static struct xt_table packet_mangler = {
107 .name = "mangle", 107 .name = "mangle",
108 .valid_hooks = MANGLE_VALID_HOOKS, 108 .valid_hooks = MANGLE_VALID_HOOKS,
109 .lock = RW_LOCK_UNLOCKED, 109 .lock = RW_LOCK_UNLOCKED,
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index bcbeb4aeacd9..5277550fa6b5 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -79,7 +79,7 @@ static struct
79 } 79 }
80}; 80};
81 81
82static struct ipt_table packet_raw = { 82static struct xt_table packet_raw = {
83 .name = "raw", 83 .name = "raw",
84 .valid_hooks = RAW_VALID_HOOKS, 84 .valid_hooks = RAW_VALID_HOOKS,
85 .lock = RW_LOCK_UNLOCKED, 85 .lock = RW_LOCK_UNLOCKED,
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 86a92272b053..998b2557692c 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -254,8 +254,9 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
254 if (maniptype == IP_NAT_MANIP_SRC) { 254 if (maniptype == IP_NAT_MANIP_SRC) {
255 if (find_appropriate_src(orig_tuple, tuple, range)) { 255 if (find_appropriate_src(orig_tuple, tuple, range)) {
256 DEBUGP("get_unique_tuple: Found current src map\n"); 256 DEBUGP("get_unique_tuple: Found current src map\n");
257 if (!nf_nat_used_tuple(tuple, ct)) 257 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM))
258 return; 258 if (!nf_nat_used_tuple(tuple, ct))
259 return;
259 } 260 }
260 } 261 }
261 262
@@ -269,6 +270,13 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
269 270
270 proto = nf_nat_proto_find_get(orig_tuple->dst.protonum); 271 proto = nf_nat_proto_find_get(orig_tuple->dst.protonum);
271 272
273 /* Change protocol info to have some randomization */
274 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) {
275 proto->unique_tuple(tuple, range, maniptype, ct);
276 nf_nat_proto_put(proto);
277 return;
278 }
279
272 /* Only bother mapping if it's not already in range and unique */ 280 /* Only bother mapping if it's not already in range and unique */
273 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || 281 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
274 proto->in_range(tuple, maniptype, &range->min, &range->max)) && 282 proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 98fbfc84d183..dc6738bdfab7 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -176,7 +176,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
176 datalen = (*pskb)->len - iph->ihl*4; 176 datalen = (*pskb)->len - iph->ihl*4;
177 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { 177 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
178 tcph->check = 0; 178 tcph->check = 0;
179 tcph->check = tcp_v4_check(tcph, datalen, 179 tcph->check = tcp_v4_check(datalen,
180 iph->saddr, iph->daddr, 180 iph->saddr, iph->daddr,
181 csum_partial((char *)tcph, 181 csum_partial((char *)tcph,
182 datalen, 0)); 182 datalen, 0));
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index 7e26a7e9bee1..439164c7a626 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -8,6 +8,7 @@
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>
11#include <linux/ip.h> 12#include <linux/ip.h>
12#include <linux/tcp.h> 13#include <linux/tcp.h>
13 14
@@ -75,6 +76,9 @@ tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
75 range_size = ntohs(range->max.tcp.port) - min + 1; 76 range_size = ntohs(range->max.tcp.port) - min + 1;
76 } 77 }
77 78
79 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
80 port = net_random();
81
78 for (i = 0; i < range_size; i++, port++) { 82 for (i = 0; i < range_size; i++, port++) {
79 *portptr = htons(min + port % range_size); 83 *portptr = htons(min + port % range_size);
80 if (!nf_nat_used_tuple(tuple, ct)) 84 if (!nf_nat_used_tuple(tuple, ct))
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index ab0ce4c8699f..8cae6e063bb6 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -8,6 +8,7 @@
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>
11#include <linux/ip.h> 12#include <linux/ip.h>
12#include <linux/udp.h> 13#include <linux/udp.h>
13 14
@@ -73,6 +74,9 @@ udp_unique_tuple(struct nf_conntrack_tuple *tuple,
73 range_size = ntohs(range->max.udp.port) - min + 1; 74 range_size = ntohs(range->max.udp.port) - min + 1;
74 } 75 }
75 76
77 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM)
78 port = net_random();
79
76 for (i = 0; i < range_size; i++, port++) { 80 for (i = 0; i < range_size; i++, port++) {
77 *portptr = htons(min + port % range_size); 81 *portptr = htons(min + port % range_size);
78 if (!nf_nat_used_tuple(tuple, ct)) 82 if (!nf_nat_used_tuple(tuple, ct))
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index b868ee0195d4..7f95b4e2eb31 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -119,7 +119,7 @@ static struct
119 } 119 }
120}; 120};
121 121
122static struct ipt_table nat_table = { 122static struct xt_table nat_table = {
123 .name = "nat", 123 .name = "nat",
124 .valid_hooks = NAT_VALID_HOOKS, 124 .valid_hooks = NAT_VALID_HOOKS,
125 .lock = RW_LOCK_UNLOCKED, 125 .lock = RW_LOCK_UNLOCKED,
@@ -226,6 +226,10 @@ static int ipt_dnat_checkentry(const char *tablename,
226 printk("DNAT: multiple ranges no longer supported\n"); 226 printk("DNAT: multiple ranges no longer supported\n");
227 return 0; 227 return 0;
228 } 228 }
229 if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM) {
230 printk("DNAT: port randomization not supported\n");
231 return 0;
232 }
229 return 1; 233 return 1;
230} 234}
231 235
@@ -290,7 +294,7 @@ int nf_nat_rule_find(struct sk_buff **pskb,
290 return ret; 294 return ret;
291} 295}
292 296
293static struct ipt_target ipt_snat_reg = { 297static struct xt_target ipt_snat_reg = {
294 .name = "SNAT", 298 .name = "SNAT",
295 .target = ipt_snat_target, 299 .target = ipt_snat_target,
296 .targetsize = sizeof(struct nf_nat_multi_range_compat), 300 .targetsize = sizeof(struct nf_nat_multi_range_compat),
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 00d6dea9f7f3..5a964a167c13 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -32,12 +32,6 @@
32#define DEBUGP(format, args...) 32#define DEBUGP(format, args...)
33#endif 33#endif
34 34
35#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \
36 : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
37 : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \
38 : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
39 : "*ERROR*")))
40
41#ifdef CONFIG_XFRM 35#ifdef CONFIG_XFRM
42static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) 36static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
43{ 37{
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index a6c63bbd9ddb..fed6a1e7af9e 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -489,7 +489,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
489 } 489 }
490 490
491 security_sk_classify_flow(sk, &fl); 491 security_sk_classify_flow(sk, &fl);
492 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 492 err = ip_route_output_flow(&rt, &fl, sk, 1);
493 } 493 }
494 if (err) 494 if (err)
495 goto done; 495 goto done;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2daa0dc19d33..baee304a3cb7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2635,7 +2635,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2635 2635
2636 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); 2636 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
2637 if (nlh == NULL) 2637 if (nlh == NULL)
2638 return -ENOBUFS; 2638 return -EMSGSIZE;
2639 2639
2640 r = nlmsg_data(nlh); 2640 r = nlmsg_data(nlh);
2641 r->rtm_family = AF_INET; 2641 r->rtm_family = AF_INET;
@@ -2718,7 +2718,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2718 return nlmsg_end(skb, nlh); 2718 return nlmsg_end(skb, nlh);
2719 2719
2720nla_put_failure: 2720nla_put_failure:
2721 return nlmsg_cancel(skb, nlh); 2721 nlmsg_cancel(skb, nlh);
2722 return -EMSGSIZE;
2722} 2723}
2723 2724
2724int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) 2725int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b67e0dd743be..5bd43d7294fd 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2415,10 +2415,11 @@ void __init tcp_init(void)
2415 &tcp_hashinfo.ehash_size, 2415 &tcp_hashinfo.ehash_size,
2416 NULL, 2416 NULL,
2417 0); 2417 0);
2418 tcp_hashinfo.ehash_size = (1 << tcp_hashinfo.ehash_size) >> 1; 2418 tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size;
2419 for (i = 0; i < (tcp_hashinfo.ehash_size << 1); i++) { 2419 for (i = 0; i < tcp_hashinfo.ehash_size; i++) {
2420 rwlock_init(&tcp_hashinfo.ehash[i].lock); 2420 rwlock_init(&tcp_hashinfo.ehash[i].lock);
2421 INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain); 2421 INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain);
2422 INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain);
2422 } 2423 }
2423 2424
2424 tcp_hashinfo.bhash = 2425 tcp_hashinfo.bhash =
@@ -2475,7 +2476,7 @@ void __init tcp_init(void)
2475 2476
2476 printk(KERN_INFO "TCP: Hash tables configured " 2477 printk(KERN_INFO "TCP: Hash tables configured "
2477 "(established %d bind %d)\n", 2478 "(established %d bind %d)\n",
2478 tcp_hashinfo.ehash_size << 1, tcp_hashinfo.bhash_size); 2479 tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
2479 2480
2480 tcp_register_congestion_control(&tcp_reno); 2481 tcp_register_congestion_control(&tcp_reno);
2481} 2482}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c26076fb890e..c6109895bb5e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -936,28 +936,58 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
936 struct tcp_sock *tp = tcp_sk(sk); 936 struct tcp_sock *tp = tcp_sk(sk);
937 unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked; 937 unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked;
938 struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2); 938 struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2);
939 struct sk_buff *cached_skb;
939 int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; 940 int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
940 int reord = tp->packets_out; 941 int reord = tp->packets_out;
941 int prior_fackets; 942 int prior_fackets;
942 u32 lost_retrans = 0; 943 u32 lost_retrans = 0;
943 int flag = 0; 944 int flag = 0;
944 int dup_sack = 0; 945 int dup_sack = 0;
946 int cached_fack_count;
945 int i; 947 int i;
948 int first_sack_index;
946 949
947 if (!tp->sacked_out) 950 if (!tp->sacked_out)
948 tp->fackets_out = 0; 951 tp->fackets_out = 0;
949 prior_fackets = tp->fackets_out; 952 prior_fackets = tp->fackets_out;
950 953
954 /* Check for D-SACK. */
955 if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
956 dup_sack = 1;
957 tp->rx_opt.sack_ok |= 4;
958 NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
959 } else if (num_sacks > 1 &&
960 !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
961 !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
962 dup_sack = 1;
963 tp->rx_opt.sack_ok |= 4;
964 NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
965 }
966
967 /* D-SACK for already forgotten data...
968 * Do dumb counting. */
969 if (dup_sack &&
970 !after(ntohl(sp[0].end_seq), prior_snd_una) &&
971 after(ntohl(sp[0].end_seq), tp->undo_marker))
972 tp->undo_retrans--;
973
974 /* Eliminate too old ACKs, but take into
975 * account more or less fresh ones, they can
976 * contain valid SACK info.
977 */
978 if (before(TCP_SKB_CB(ack_skb)->ack_seq, prior_snd_una - tp->max_window))
979 return 0;
980
951 /* SACK fastpath: 981 /* SACK fastpath:
952 * if the only SACK change is the increase of the end_seq of 982 * if the only SACK change is the increase of the end_seq of
953 * the first block then only apply that SACK block 983 * the first block then only apply that SACK block
954 * and use retrans queue hinting otherwise slowpath */ 984 * and use retrans queue hinting otherwise slowpath */
955 flag = 1; 985 flag = 1;
956 for (i = 0; i< num_sacks; i++) { 986 for (i = 0; i < num_sacks; i++) {
957 __u32 start_seq = ntohl(sp[i].start_seq); 987 __be32 start_seq = sp[i].start_seq;
958 __u32 end_seq = ntohl(sp[i].end_seq); 988 __be32 end_seq = sp[i].end_seq;
959 989
960 if (i == 0){ 990 if (i == 0) {
961 if (tp->recv_sack_cache[i].start_seq != start_seq) 991 if (tp->recv_sack_cache[i].start_seq != start_seq)
962 flag = 0; 992 flag = 0;
963 } else { 993 } else {
@@ -967,39 +997,14 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
967 } 997 }
968 tp->recv_sack_cache[i].start_seq = start_seq; 998 tp->recv_sack_cache[i].start_seq = start_seq;
969 tp->recv_sack_cache[i].end_seq = end_seq; 999 tp->recv_sack_cache[i].end_seq = end_seq;
970 1000 }
971 /* Check for D-SACK. */ 1001 /* Clear the rest of the cache sack blocks so they won't match mistakenly. */
972 if (i == 0) { 1002 for (; i < ARRAY_SIZE(tp->recv_sack_cache); i++) {
973 u32 ack = TCP_SKB_CB(ack_skb)->ack_seq; 1003 tp->recv_sack_cache[i].start_seq = 0;
974 1004 tp->recv_sack_cache[i].end_seq = 0;
975 if (before(start_seq, ack)) {
976 dup_sack = 1;
977 tp->rx_opt.sack_ok |= 4;
978 NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
979 } else if (num_sacks > 1 &&
980 !after(end_seq, ntohl(sp[1].end_seq)) &&
981 !before(start_seq, ntohl(sp[1].start_seq))) {
982 dup_sack = 1;
983 tp->rx_opt.sack_ok |= 4;
984 NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
985 }
986
987 /* D-SACK for already forgotten data...
988 * Do dumb counting. */
989 if (dup_sack &&
990 !after(end_seq, prior_snd_una) &&
991 after(end_seq, tp->undo_marker))
992 tp->undo_retrans--;
993
994 /* Eliminate too old ACKs, but take into
995 * account more or less fresh ones, they can
996 * contain valid SACK info.
997 */
998 if (before(ack, prior_snd_una - tp->max_window))
999 return 0;
1000 }
1001 } 1005 }
1002 1006
1007 first_sack_index = 0;
1003 if (flag) 1008 if (flag)
1004 num_sacks = 1; 1009 num_sacks = 1;
1005 else { 1010 else {
@@ -1016,6 +1021,10 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1016 tmp = sp[j]; 1021 tmp = sp[j];
1017 sp[j] = sp[j+1]; 1022 sp[j] = sp[j+1];
1018 sp[j+1] = tmp; 1023 sp[j+1] = tmp;
1024
1025 /* Track where the first SACK block goes to */
1026 if (j == first_sack_index)
1027 first_sack_index = j+1;
1019 } 1028 }
1020 1029
1021 } 1030 }
@@ -1025,20 +1034,22 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1025 /* clear flag as used for different purpose in following code */ 1034 /* clear flag as used for different purpose in following code */
1026 flag = 0; 1035 flag = 0;
1027 1036
1037 /* Use SACK fastpath hint if valid */
1038 cached_skb = tp->fastpath_skb_hint;
1039 cached_fack_count = tp->fastpath_cnt_hint;
1040 if (!cached_skb) {
1041 cached_skb = sk->sk_write_queue.next;
1042 cached_fack_count = 0;
1043 }
1044
1028 for (i=0; i<num_sacks; i++, sp++) { 1045 for (i=0; i<num_sacks; i++, sp++) {
1029 struct sk_buff *skb; 1046 struct sk_buff *skb;
1030 __u32 start_seq = ntohl(sp->start_seq); 1047 __u32 start_seq = ntohl(sp->start_seq);
1031 __u32 end_seq = ntohl(sp->end_seq); 1048 __u32 end_seq = ntohl(sp->end_seq);
1032 int fack_count; 1049 int fack_count;
1033 1050
1034 /* Use SACK fastpath hint if valid */ 1051 skb = cached_skb;
1035 if (tp->fastpath_skb_hint) { 1052 fack_count = cached_fack_count;
1036 skb = tp->fastpath_skb_hint;
1037 fack_count = tp->fastpath_cnt_hint;
1038 } else {
1039 skb = sk->sk_write_queue.next;
1040 fack_count = 0;
1041 }
1042 1053
1043 /* Event "B" in the comment above. */ 1054 /* Event "B" in the comment above. */
1044 if (after(end_seq, tp->high_seq)) 1055 if (after(end_seq, tp->high_seq))
@@ -1048,8 +1059,12 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1048 int in_sack, pcount; 1059 int in_sack, pcount;
1049 u8 sacked; 1060 u8 sacked;
1050 1061
1051 tp->fastpath_skb_hint = skb; 1062 cached_skb = skb;
1052 tp->fastpath_cnt_hint = fack_count; 1063 cached_fack_count = fack_count;
1064 if (i == first_sack_index) {
1065 tp->fastpath_skb_hint = skb;
1066 tp->fastpath_cnt_hint = fack_count;
1067 }
1053 1068
1054 /* The retransmission queue is always in order, so 1069 /* The retransmission queue is always in order, so
1055 * we can short-circuit the walk early. 1070 * we can short-circuit the walk early.
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 12de90a5047c..f51d6404c61c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -191,7 +191,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
191 tmp = ip_route_connect(&rt, nexthop, inet->saddr, 191 tmp = ip_route_connect(&rt, nexthop, inet->saddr,
192 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, 192 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
193 IPPROTO_TCP, 193 IPPROTO_TCP,
194 inet->sport, usin->sin_port, sk); 194 inet->sport, usin->sin_port, sk, 1);
195 if (tmp < 0) 195 if (tmp < 0)
196 return tmp; 196 return tmp;
197 197
@@ -502,11 +502,11 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
502 struct tcphdr *th = skb->h.th; 502 struct tcphdr *th = skb->h.th;
503 503
504 if (skb->ip_summed == CHECKSUM_PARTIAL) { 504 if (skb->ip_summed == CHECKSUM_PARTIAL) {
505 th->check = ~tcp_v4_check(th, len, 505 th->check = ~tcp_v4_check(len, inet->saddr,
506 inet->saddr, inet->daddr, 0); 506 inet->daddr, 0);
507 skb->csum_offset = offsetof(struct tcphdr, check); 507 skb->csum_offset = offsetof(struct tcphdr, check);
508 } else { 508 } else {
509 th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, 509 th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
510 csum_partial((char *)th, 510 csum_partial((char *)th,
511 th->doff << 2, 511 th->doff << 2,
512 skb->csum)); 512 skb->csum));
@@ -525,7 +525,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
525 th = skb->h.th; 525 th = skb->h.th;
526 526
527 th->check = 0; 527 th->check = 0;
528 th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); 528 th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
529 skb->csum_offset = offsetof(struct tcphdr, check); 529 skb->csum_offset = offsetof(struct tcphdr, check);
530 skb->ip_summed = CHECKSUM_PARTIAL; 530 skb->ip_summed = CHECKSUM_PARTIAL;
531 return 0; 531 return 0;
@@ -747,7 +747,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
747 if (skb) { 747 if (skb) {
748 struct tcphdr *th = skb->h.th; 748 struct tcphdr *th = skb->h.th;
749 749
750 th->check = tcp_v4_check(th, skb->len, 750 th->check = tcp_v4_check(skb->len,
751 ireq->loc_addr, 751 ireq->loc_addr,
752 ireq->rmt_addr, 752 ireq->rmt_addr,
753 csum_partial((char *)th, skb->len, 753 csum_partial((char *)th, skb->len,
@@ -1514,7 +1514,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
1514static __sum16 tcp_v4_checksum_init(struct sk_buff *skb) 1514static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
1515{ 1515{
1516 if (skb->ip_summed == CHECKSUM_COMPLETE) { 1516 if (skb->ip_summed == CHECKSUM_COMPLETE) {
1517 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, 1517 if (!tcp_v4_check(skb->len, skb->nh.iph->saddr,
1518 skb->nh.iph->daddr, skb->csum)) { 1518 skb->nh.iph->daddr, skb->csum)) {
1519 skb->ip_summed = CHECKSUM_UNNECESSARY; 1519 skb->ip_summed = CHECKSUM_UNNECESSARY;
1520 return 0; 1520 return 0;
@@ -2051,7 +2051,7 @@ static void *established_get_first(struct seq_file *seq)
2051 } 2051 }
2052 st->state = TCP_SEQ_STATE_TIME_WAIT; 2052 st->state = TCP_SEQ_STATE_TIME_WAIT;
2053 inet_twsk_for_each(tw, node, 2053 inet_twsk_for_each(tw, node,
2054 &tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain) { 2054 &tcp_hashinfo.ehash[st->bucket].twchain) {
2055 if (tw->tw_family != st->family) { 2055 if (tw->tw_family != st->family) {
2056 continue; 2056 continue;
2057 } 2057 }
@@ -2107,7 +2107,7 @@ get_tw:
2107 } 2107 }
2108 2108
2109 st->state = TCP_SEQ_STATE_TIME_WAIT; 2109 st->state = TCP_SEQ_STATE_TIME_WAIT;
2110 tw = tw_head(&tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain); 2110 tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
2111 goto get_tw; 2111 goto get_tw;
2112found: 2112found:
2113 cur = sk; 2113 cur = sk;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 975f4472af29..58b7111523f4 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -965,7 +965,8 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk
965 u32 in_flight, cwnd; 965 u32 in_flight, cwnd;
966 966
967 /* Don't be strict about the congestion window for the final FIN. */ 967 /* Don't be strict about the congestion window for the final FIN. */
968 if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) 968 if ((TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
969 tcp_skb_pcount(skb) == 1)
969 return 1; 970 return 1;
970 971
971 in_flight = tcp_packets_in_flight(tp); 972 in_flight = tcp_packets_in_flight(tp);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index cfff930f2baf..8b54c68a0d12 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -629,7 +629,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
629 { .sport = inet->sport, 629 { .sport = inet->sport,
630 .dport = dport } } }; 630 .dport = dport } } };
631 security_sk_classify_flow(sk, &fl); 631 security_sk_classify_flow(sk, &fl);
632 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 632 err = ip_route_output_flow(&rt, &fl, sk, 1);
633 if (err) 633 if (err)
634 goto out; 634 goto out;
635 635
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index e23c21d31a53..e54c5494c88f 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -23,6 +23,12 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
23 IP_ECN_set_ce(inner_iph); 23 IP_ECN_set_ce(inner_iph);
24} 24}
25 25
26static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
27{
28 if (INET_ECN_is_ce(iph->tos))
29 IP6_ECN_set_ce(skb->nh.ipv6h);
30}
31
26/* Add encapsulation header. 32/* Add encapsulation header.
27 * 33 *
28 * The top IP header will be constructed per RFC 2401. The following fields 34 * The top IP header will be constructed per RFC 2401. The following fields
@@ -36,6 +42,7 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
36static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 42static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
37{ 43{
38 struct dst_entry *dst = skb->dst; 44 struct dst_entry *dst = skb->dst;
45 struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
39 struct iphdr *iph, *top_iph; 46 struct iphdr *iph, *top_iph;
40 int flags; 47 int flags;
41 48
@@ -48,15 +55,27 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
48 top_iph->ihl = 5; 55 top_iph->ihl = 5;
49 top_iph->version = 4; 56 top_iph->version = 4;
50 57
58 flags = x->props.flags;
59
51 /* DS disclosed */ 60 /* DS disclosed */
52 top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); 61 if (xdst->route->ops->family == AF_INET) {
62 top_iph->protocol = IPPROTO_IPIP;
63 top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
64 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
65 0 : (iph->frag_off & htons(IP_DF));
66 }
67#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
68 else {
69 struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
70 top_iph->protocol = IPPROTO_IPV6;
71 top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
72 top_iph->frag_off = 0;
73 }
74#endif
53 75
54 flags = x->props.flags;
55 if (flags & XFRM_STATE_NOECN) 76 if (flags & XFRM_STATE_NOECN)
56 IP_ECN_clear(top_iph); 77 IP_ECN_clear(top_iph);
57 78
58 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
59 0 : (iph->frag_off & htons(IP_DF));
60 if (!top_iph->frag_off) 79 if (!top_iph->frag_off)
61 __ip_select_ident(top_iph, dst->child, 0); 80 __ip_select_ident(top_iph, dst->child, 0);
62 81
@@ -64,7 +83,6 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
64 83
65 top_iph->saddr = x->props.saddr.a4; 84 top_iph->saddr = x->props.saddr.a4;
66 top_iph->daddr = x->id.daddr.a4; 85 top_iph->daddr = x->id.daddr.a4;
67 top_iph->protocol = IPPROTO_IPIP;
68 86
69 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); 87 memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
70 return 0; 88 return 0;
@@ -75,8 +93,16 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
75 struct iphdr *iph = skb->nh.iph; 93 struct iphdr *iph = skb->nh.iph;
76 int err = -EINVAL; 94 int err = -EINVAL;
77 95
78 if (iph->protocol != IPPROTO_IPIP) 96 switch(iph->protocol){
79 goto out; 97 case IPPROTO_IPIP:
98#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
99 case IPPROTO_IPV6:
100 break;
101#endif
102 default:
103 goto out;
104 }
105
80 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 106 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
81 goto out; 107 goto out;
82 108
@@ -84,10 +110,19 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
84 (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) 110 (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
85 goto out; 111 goto out;
86 112
87 if (x->props.flags & XFRM_STATE_DECAP_DSCP) 113 if (iph->protocol == IPPROTO_IPIP) {
88 ipv4_copy_dscp(iph, skb->h.ipiph); 114 if (x->props.flags & XFRM_STATE_DECAP_DSCP)
89 if (!(x->props.flags & XFRM_STATE_NOECN)) 115 ipv4_copy_dscp(iph, skb->h.ipiph);
90 ipip_ecn_decapsulate(skb); 116 if (!(x->props.flags & XFRM_STATE_NOECN))
117 ipip_ecn_decapsulate(skb);
118 }
119#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
120 else {
121 if (!(x->props.flags & XFRM_STATE_NOECN))
122 ipip6_ecn_decapsulate(iph, skb);
123 skb->protocol = htons(ETH_P_IPV6);
124 }
125#endif
91 skb->mac.raw = memmove(skb->data - skb->mac_len, 126 skb->mac.raw = memmove(skb->data - skb->mac_len,
92 skb->mac.raw, skb->mac_len); 127 skb->mac.raw, skb->mac_len);
93 skb->nh.raw = skb->data; 128 skb->nh.raw = skb->data;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index fb9f69c616f5..699f27ce62ad 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -72,13 +72,11 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
72 struct dst_entry *dst, *dst_prev; 72 struct dst_entry *dst, *dst_prev;
73 struct rtable *rt0 = (struct rtable*)(*dst_p); 73 struct rtable *rt0 = (struct rtable*)(*dst_p);
74 struct rtable *rt = rt0; 74 struct rtable *rt = rt0;
75 __be32 remote = fl->fl4_dst;
76 __be32 local = fl->fl4_src;
77 struct flowi fl_tunnel = { 75 struct flowi fl_tunnel = {
78 .nl_u = { 76 .nl_u = {
79 .ip4_u = { 77 .ip4_u = {
80 .saddr = local, 78 .saddr = fl->fl4_src,
81 .daddr = remote, 79 .daddr = fl->fl4_dst,
82 .tos = fl->fl4_tos 80 .tos = fl->fl4_tos
83 } 81 }
84 } 82 }
@@ -94,7 +92,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
94 for (i = 0; i < nx; i++) { 92 for (i = 0; i < nx; i++) {
95 struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops); 93 struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
96 struct xfrm_dst *xdst; 94 struct xfrm_dst *xdst;
97 int tunnel = 0;
98 95
99 if (unlikely(dst1 == NULL)) { 96 if (unlikely(dst1 == NULL)) {
100 err = -ENOBUFS; 97 err = -ENOBUFS;
@@ -116,19 +113,28 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
116 113
117 dst1->next = dst_prev; 114 dst1->next = dst_prev;
118 dst_prev = dst1; 115 dst_prev = dst1;
119 if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { 116
120 remote = xfrm[i]->id.daddr.a4;
121 local = xfrm[i]->props.saddr.a4;
122 tunnel = 1;
123 }
124 header_len += xfrm[i]->props.header_len; 117 header_len += xfrm[i]->props.header_len;
125 trailer_len += xfrm[i]->props.trailer_len; 118 trailer_len += xfrm[i]->props.trailer_len;
126 119
127 if (tunnel) { 120 if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
128 fl_tunnel.fl4_src = local; 121 unsigned short encap_family = xfrm[i]->props.family;
129 fl_tunnel.fl4_dst = remote; 122 switch(encap_family) {
123 case AF_INET:
124 fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
125 fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
126 break;
127#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
128 case AF_INET6:
129 ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
130 ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
131 break;
132#endif
133 default:
134 BUG_ON(1);
135 }
130 err = xfrm_dst_lookup((struct xfrm_dst **)&rt, 136 err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
131 &fl_tunnel, AF_INET); 137 &fl_tunnel, encap_family);
132 if (err) 138 if (err)
133 goto error; 139 goto error;
134 } else 140 } else
@@ -145,6 +151,7 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
145 i = 0; 151 i = 0;
146 for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { 152 for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
147 struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; 153 struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
154 struct xfrm_state_afinfo *afinfo;
148 x->u.rt.fl = *fl; 155 x->u.rt.fl = *fl;
149 156
150 dst_prev->xfrm = xfrm[i++]; 157 dst_prev->xfrm = xfrm[i++];
@@ -162,8 +169,18 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
162 /* Copy neighbout for reachability confirmation */ 169 /* Copy neighbout for reachability confirmation */
163 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); 170 dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
164 dst_prev->input = rt->u.dst.input; 171 dst_prev->input = rt->u.dst.input;
165 dst_prev->output = xfrm4_output; 172 /* XXX: When IPv6 module can be unloaded, we should manage reference
166 if (rt->peer) 173 * to xfrm6_output in afinfo->output. Miyazawa
174 * */
175 afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
176 if (!afinfo) {
177 dst = *dst_p;
178 err = -EAFNOSUPPORT;
179 goto error;
180 }
181 dst_prev->output = afinfo->output;
182 xfrm_state_put_afinfo(afinfo);
183 if (dst_prev->xfrm->props.family == AF_INET && rt->peer)
167 atomic_inc(&rt->peer->refcnt); 184 atomic_inc(&rt->peer->refcnt);
168 x->u.rt.peer = rt->peer; 185 x->u.rt.peer = rt->peer;
169 /* Sheit... I remember I did this right. Apparently, 186 /* Sheit... I remember I did this right. Apparently,
@@ -274,7 +291,7 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
274 291
275 if (likely(xdst->u.rt.idev)) 292 if (likely(xdst->u.rt.idev))
276 in_dev_put(xdst->u.rt.idev); 293 in_dev_put(xdst->u.rt.idev);
277 if (likely(xdst->u.rt.peer)) 294 if (dst->xfrm->props.family == AF_INET && likely(xdst->u.rt.peer))
278 inet_putpeer(xdst->u.rt.peer); 295 inet_putpeer(xdst->u.rt.peer);
279 xfrm_dst_destroy(xdst); 296 xfrm_dst_destroy(xdst);
280} 297}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 3cc3df0c6ece..93e2c061cdda 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -51,6 +51,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
51 .family = AF_INET, 51 .family = AF_INET,
52 .init_flags = xfrm4_init_flags, 52 .init_flags = xfrm4_init_flags,
53 .init_tempsel = __xfrm4_init_tempsel, 53 .init_tempsel = __xfrm4_init_tempsel,
54 .output = xfrm4_output,
54}; 55};
55 56
56void __init xfrm4_state_init(void) 57void __init xfrm4_state_init(void)