aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-12-05 09:37:56 -0500
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-12-05 09:37:56 -0500
commit4c1ac1b49122b805adfa4efc620592f68dccf5db (patch)
tree87557f4bc2fd4fe65b7570489c2f610c45c0adcd /net/ipv4
parentc4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff)
parentd916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/infiniband/core/iwcm.c drivers/net/chelsio/cxgb2.c drivers/net/wireless/bcm43xx/bcm43xx_main.c drivers/net/wireless/prism54/islpci_eth.c drivers/usb/core/hub.h drivers/usb/input/hid-core.c net/core/netpoll.c Fix up merge failures with Linus's head and fix new compilation failures. Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/Kconfig19
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/af_inet.c16
-rw-r--r--net/ipv4/ah4.c4
-rw-r--r--net/ipv4/arp.c2
-rw-r--r--net/ipv4/cipso_ipv4.c813
-rw-r--r--net/ipv4/devinet.c32
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv4/fib_frontend.c5
-rw-r--r--net/ipv4/fib_rules.c53
-rw-r--r--net/ipv4/fib_semantics.c36
-rw-r--r--net/ipv4/icmp.c6
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/inet_connection_sock.c2
-rw-r--r--net/ipv4/ip_gre.c56
-rw-r--r--net/ipv4/ip_output.c19
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipconfig.c105
-rw-r--r--net/ipv4/ipip.c16
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/ipvs/ip_vs_app.c3
-rw-r--r--net/ipv4/ipvs/ip_vs_core.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_proto.c8
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_tcp.c16
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_udp.c22
-rw-r--r--net/ipv4/netfilter.c10
-rw-r--r--net/ipv4/netfilter/Kconfig138
-rw-r--r--net/ipv4/netfilter/Makefile30
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c11
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c14
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c8
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c172
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c874
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.c1926
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c33
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c12
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c66
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c118
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_tftp.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_amanda.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_ftp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c32
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c58
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c29
-rw-r--r--net/ipv4/netfilter/ip_nat_irc.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c8
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_icmp.c10
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_tcp.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_udp.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c199
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c85
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_tftp.c9
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c25
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c11
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c20
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c29
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c4
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c6
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c18
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c12
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c24
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c5
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c5
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c733
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c8
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c137
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c412
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c57
-rw-r--r--net/ipv4/netfilter/nf_nat_amanda.c78
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c647
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c179
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c596
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c433
-rw-r--r--net/ipv4/netfilter/nf_nat_irc.c101
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c315
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c179
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c86
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c148
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c138
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_unknown.c54
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c343
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c283
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c1332
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c406
-rw-r--r--net/ipv4/netfilter/nf_nat_tftp.c52
-rw-r--r--net/ipv4/proc.c13
-rw-r--r--net/ipv4/raw.c4
-rw-r--r--net/ipv4/route.c66
-rw-r--r--net/ipv4/syncookies.c18
-rw-r--r--net/ipv4/sysctl_net_ipv4.c76
-rw-r--r--net/ipv4/tcp.c156
-rw-r--r--net/ipv4/tcp_cong.c91
-rw-r--r--net/ipv4/tcp_htcp.c4
-rw-r--r--net/ipv4/tcp_input.c14
-rw-r--r--net/ipv4/tcp_ipv4.c713
-rw-r--r--net/ipv4/tcp_minisocks.c69
-rw-r--r--net/ipv4/tcp_output.c122
-rw-r--r--net/ipv4/tcp_probe.c2
-rw-r--r--net/ipv4/tcp_timer.c2
-rw-r--r--net/ipv4/tcp_vegas.c4
-rw-r--r--net/ipv4/udp.c558
-rw-r--r--net/ipv4/udp_impl.h38
-rw-r--r--net/ipv4/udplite.c119
-rw-r--r--net/ipv4/xfrm4_policy.c7
110 files changed, 9193 insertions, 4922 deletions
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 5572071af735..503e7059e312 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -104,13 +104,6 @@ config IP_MULTIPLE_TABLES
104 104
105 If unsure, say N. 105 If unsure, say N.
106 106
107config IP_ROUTE_FWMARK
108 bool "IP: use netfilter MARK value as routing key"
109 depends on IP_MULTIPLE_TABLES && NETFILTER
110 help
111 If you say Y here, you will be able to specify different routes for
112 packets with different mark values (see iptables(8), MARK target).
113
114config IP_ROUTE_MULTIPATH 107config IP_ROUTE_MULTIPATH
115 bool "IP: equal cost multipath" 108 bool "IP: equal cost multipath"
116 depends on IP_ADVANCED_ROUTER 109 depends on IP_ADVANCED_ROUTER
@@ -625,5 +618,17 @@ config DEFAULT_TCP_CONG
625 default "reno" if DEFAULT_RENO 618 default "reno" if DEFAULT_RENO
626 default "cubic" 619 default "cubic"
627 620
621config TCP_MD5SIG
622 bool "TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)"
623 depends on EXPERIMENTAL
624 select CRYPTO
625 select CRYPTO_MD5
626 ---help---
627 RFC2385 specifices a method of giving MD5 protection to TCP sessions.
628 Its main (only?) use is to protect BGP sessions between core routers
629 on the Internet.
630
631 If unsure, say N.
632
628source "net/ipv4/ipvs/Kconfig" 633source "net/ipv4/ipvs/Kconfig"
629 634
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 15645c51520c..7a068626feea 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -8,7 +8,8 @@ obj-y := route.o inetpeer.o protocol.o \
8 inet_timewait_sock.o inet_connection_sock.o \ 8 inet_timewait_sock.o inet_connection_sock.o \
9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \ 9 tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
10 tcp_minisocks.o tcp_cong.o \ 10 tcp_minisocks.o tcp_cong.o \
11 datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ 11 datagram.o raw.o udp.o udplite.o \
12 arp.o icmp.o devinet.o af_inet.o igmp.o \
12 sysctl_net_ipv4.o fib_frontend.o fib_semantics.o 13 sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
13 14
14obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o 15obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index edcf0932ac6d..1144900d37f6 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -104,6 +104,7 @@
104#include <net/inet_connection_sock.h> 104#include <net/inet_connection_sock.h>
105#include <net/tcp.h> 105#include <net/tcp.h>
106#include <net/udp.h> 106#include <net/udp.h>
107#include <net/udplite.h>
107#include <linux/skbuff.h> 108#include <linux/skbuff.h>
108#include <net/sock.h> 109#include <net/sock.h>
109#include <net/raw.h> 110#include <net/raw.h>
@@ -204,7 +205,7 @@ int inet_listen(struct socket *sock, int backlog)
204 * we can only allow the backlog to be adjusted. 205 * we can only allow the backlog to be adjusted.
205 */ 206 */
206 if (old_state != TCP_LISTEN) { 207 if (old_state != TCP_LISTEN) {
207 err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); 208 err = inet_csk_listen_start(sk, backlog);
208 if (err) 209 if (err)
209 goto out; 210 goto out;
210 } 211 }
@@ -643,7 +644,7 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
643 sin->sin_port = inet->dport; 644 sin->sin_port = inet->dport;
644 sin->sin_addr.s_addr = inet->daddr; 645 sin->sin_addr.s_addr = inet->daddr;
645 } else { 646 } else {
646 __u32 addr = inet->rcv_saddr; 647 __be32 addr = inet->rcv_saddr;
647 if (!addr) 648 if (!addr)
648 addr = inet->saddr; 649 addr = inet->saddr;
649 sin->sin_port = inet->sport; 650 sin->sin_port = inet->sport;
@@ -994,8 +995,8 @@ static int inet_sk_reselect_saddr(struct sock *sk)
994 struct inet_sock *inet = inet_sk(sk); 995 struct inet_sock *inet = inet_sk(sk);
995 int err; 996 int err;
996 struct rtable *rt; 997 struct rtable *rt;
997 __u32 old_saddr = inet->saddr; 998 __be32 old_saddr = inet->saddr;
998 __u32 new_saddr; 999 __be32 new_saddr;
999 __be32 daddr = inet->daddr; 1000 __be32 daddr = inet->daddr;
1000 1001
1001 if (inet->opt && inet->opt->srr) 1002 if (inet->opt && inet->opt->srr)
@@ -1223,10 +1224,13 @@ static int __init init_ipv4_mibs(void)
1223 tcp_statistics[1] = alloc_percpu(struct tcp_mib); 1224 tcp_statistics[1] = alloc_percpu(struct tcp_mib);
1224 udp_statistics[0] = alloc_percpu(struct udp_mib); 1225 udp_statistics[0] = alloc_percpu(struct udp_mib);
1225 udp_statistics[1] = alloc_percpu(struct udp_mib); 1226 udp_statistics[1] = alloc_percpu(struct udp_mib);
1227 udplite_statistics[0] = alloc_percpu(struct udp_mib);
1228 udplite_statistics[1] = alloc_percpu(struct udp_mib);
1226 if (! 1229 if (!
1227 (net_statistics[0] && net_statistics[1] && ip_statistics[0] 1230 (net_statistics[0] && net_statistics[1] && ip_statistics[0]
1228 && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1] 1231 && ip_statistics[1] && tcp_statistics[0] && tcp_statistics[1]
1229 && udp_statistics[0] && udp_statistics[1])) 1232 && udp_statistics[0] && udp_statistics[1]
1233 && udplite_statistics[0] && udplite_statistics[1] ) )
1230 return -ENOMEM; 1234 return -ENOMEM;
1231 1235
1232 (void) tcp_mib_init(); 1236 (void) tcp_mib_init();
@@ -1313,6 +1317,8 @@ static int __init inet_init(void)
1313 /* Setup TCP slab cache for open requests. */ 1317 /* Setup TCP slab cache for open requests. */
1314 tcp_init(); 1318 tcp_init();
1315 1319
1320 /* Add UDP-Lite (RFC 3828) */
1321 udplite4_register();
1316 1322
1317 /* 1323 /*
1318 * Set the ICMP layer up 1324 * Set the ICMP layer up
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 99542977e47e..67a5509e26fc 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -14,7 +14,7 @@
14 * into IP header for icv calculation. Options are already checked 14 * into IP header for icv calculation. Options are already checked
15 * for validity, so paranoia is not required. */ 15 * for validity, so paranoia is not required. */
16 16
17static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) 17static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr)
18{ 18{
19 unsigned char * optptr = (unsigned char*)(iph+1); 19 unsigned char * optptr = (unsigned char*)(iph+1);
20 int l = iph->ihl*4 - sizeof(struct iphdr); 20 int l = iph->ihl*4 - sizeof(struct iphdr);
@@ -162,7 +162,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
162 iph->frag_off = 0; 162 iph->frag_off = 0;
163 iph->check = 0; 163 iph->check = 0;
164 if (ihl > sizeof(*iph)) { 164 if (ihl > sizeof(*iph)) {
165 u32 dummy; 165 __be32 dummy;
166 if (ip_clear_mutable_options(iph, &dummy)) 166 if (ip_clear_mutable_options(iph, &dummy))
167 goto out; 167 goto out;
168 } 168 }
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index cfb5d3de9c84..3981e8be9ab8 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -203,7 +203,7 @@ struct neigh_table arp_tbl = {
203 .gc_thresh3 = 1024, 203 .gc_thresh3 = 1024,
204}; 204};
205 205
206int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir) 206int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
207{ 207{
208 switch (dev->type) { 208 switch (dev->type) {
209 case ARPHRD_ETHER: 209 case ARPHRD_ETHER:
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 6460233407c7..60aafb4a8adf 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -319,6 +319,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
319 entry->activity += 1; 319 entry->activity += 1;
320 atomic_inc(&entry->lsm_data->refcount); 320 atomic_inc(&entry->lsm_data->refcount);
321 secattr->cache = entry->lsm_data; 321 secattr->cache = entry->lsm_data;
322 secattr->flags |= NETLBL_SECATTR_CACHE;
322 if (prev_entry == NULL) { 323 if (prev_entry == NULL) {
323 spin_unlock_bh(&cipso_v4_cache[bkt].lock); 324 spin_unlock_bh(&cipso_v4_cache[bkt].lock);
324 return 0; 325 return 0;
@@ -377,12 +378,11 @@ int cipso_v4_cache_add(const struct sk_buff *skb,
377 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 378 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
378 if (entry == NULL) 379 if (entry == NULL)
379 return -ENOMEM; 380 return -ENOMEM;
380 entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC); 381 entry->key = kmemdup(cipso_ptr, cipso_ptr_len, GFP_ATOMIC);
381 if (entry->key == NULL) { 382 if (entry->key == NULL) {
382 ret_val = -ENOMEM; 383 ret_val = -ENOMEM;
383 goto cache_add_failure; 384 goto cache_add_failure;
384 } 385 }
385 memcpy(entry->key, cipso_ptr, cipso_ptr_len);
386 entry->key_len = cipso_ptr_len; 386 entry->key_len = cipso_ptr_len;
387 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); 387 entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
388 atomic_inc(&secattr->cache->refcount); 388 atomic_inc(&secattr->cache->refcount);
@@ -447,8 +447,30 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
447 */ 447 */
448int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) 448int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
449{ 449{
450 u32 iter;
451
450 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) 452 if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
451 return -EINVAL; 453 return -EINVAL;
454 for (iter = 0; iter < CIPSO_V4_TAG_MAXCNT; iter++) {
455 switch (doi_def->tags[iter]) {
456 case CIPSO_V4_TAG_RBITMAP:
457 break;
458 case CIPSO_V4_TAG_RANGE:
459 if (doi_def->type != CIPSO_V4_MAP_PASS)
460 return -EINVAL;
461 break;
462 case CIPSO_V4_TAG_INVALID:
463 if (iter == 0)
464 return -EINVAL;
465 break;
466 case CIPSO_V4_TAG_ENUM:
467 if (doi_def->type != CIPSO_V4_MAP_PASS)
468 return -EINVAL;
469 break;
470 default:
471 return -EINVAL;
472 }
473 }
452 474
453 doi_def->valid = 1; 475 doi_def->valid = 1;
454 INIT_RCU_HEAD(&doi_def->rcu); 476 INIT_RCU_HEAD(&doi_def->rcu);
@@ -805,8 +827,7 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
805/** 827/**
806 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network 828 * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
807 * @doi_def: the DOI definition 829 * @doi_def: the DOI definition
808 * @host_cat: the category bitmap in host format 830 * @secattr: the security attributes
809 * @host_cat_len: the length of the host's category bitmap in bytes
810 * @net_cat: the zero'd out category bitmap in network/CIPSO format 831 * @net_cat: the zero'd out category bitmap in network/CIPSO format
811 * @net_cat_len: the length of the CIPSO bitmap in bytes 832 * @net_cat_len: the length of the CIPSO bitmap in bytes
812 * 833 *
@@ -817,59 +838,51 @@ static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
817 * 838 *
818 */ 839 */
819static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, 840static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
820 const unsigned char *host_cat, 841 const struct netlbl_lsm_secattr *secattr,
821 u32 host_cat_len,
822 unsigned char *net_cat, 842 unsigned char *net_cat,
823 u32 net_cat_len) 843 u32 net_cat_len)
824{ 844{
825 int host_spot = -1; 845 int host_spot = -1;
826 u32 net_spot; 846 u32 net_spot = CIPSO_V4_INV_CAT;
827 u32 net_spot_max = 0; 847 u32 net_spot_max = 0;
828 u32 host_clen_bits = host_cat_len * 8;
829 u32 net_clen_bits = net_cat_len * 8; 848 u32 net_clen_bits = net_cat_len * 8;
830 u32 host_cat_size; 849 u32 host_cat_size = 0;
831 u32 *host_cat_array; 850 u32 *host_cat_array = NULL;
832 851
833 switch (doi_def->type) { 852 if (doi_def->type == CIPSO_V4_MAP_STD) {
834 case CIPSO_V4_MAP_PASS:
835 net_spot_max = host_cat_len;
836 while (net_spot_max > 0 && host_cat[net_spot_max - 1] == 0)
837 net_spot_max--;
838 if (net_spot_max > net_cat_len)
839 return -EINVAL;
840 memcpy(net_cat, host_cat, net_spot_max);
841 return net_spot_max;
842 case CIPSO_V4_MAP_STD:
843 host_cat_size = doi_def->map.std->cat.local_size; 853 host_cat_size = doi_def->map.std->cat.local_size;
844 host_cat_array = doi_def->map.std->cat.local; 854 host_cat_array = doi_def->map.std->cat.local;
845 for (;;) { 855 }
846 host_spot = cipso_v4_bitmap_walk(host_cat, 856
847 host_clen_bits, 857 for (;;) {
848 host_spot + 1, 858 host_spot = netlbl_secattr_catmap_walk(secattr->mls_cat,
849 1); 859 host_spot + 1);
850 if (host_spot < 0) 860 if (host_spot < 0)
851 break; 861 break;
862
863 switch (doi_def->type) {
864 case CIPSO_V4_MAP_PASS:
865 net_spot = host_spot;
866 break;
867 case CIPSO_V4_MAP_STD:
852 if (host_spot >= host_cat_size) 868 if (host_spot >= host_cat_size)
853 return -EPERM; 869 return -EPERM;
854
855 net_spot = host_cat_array[host_spot]; 870 net_spot = host_cat_array[host_spot];
856 if (net_spot >= net_clen_bits) 871 if (net_spot >= CIPSO_V4_INV_CAT)
857 return -ENOSPC; 872 return -EPERM;
858 cipso_v4_bitmap_setbit(net_cat, net_spot, 1); 873 break;
859
860 if (net_spot > net_spot_max)
861 net_spot_max = net_spot;
862 } 874 }
875 if (net_spot >= net_clen_bits)
876 return -ENOSPC;
877 cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
863 878
864 if (host_spot == -2) 879 if (net_spot > net_spot_max)
865 return -EFAULT; 880 net_spot_max = net_spot;
866
867 if (++net_spot_max % 8)
868 return net_spot_max / 8 + 1;
869 return net_spot_max / 8;
870 } 881 }
871 882
872 return -EINVAL; 883 if (++net_spot_max % 8)
884 return net_spot_max / 8 + 1;
885 return net_spot_max / 8;
873} 886}
874 887
875/** 888/**
@@ -877,102 +890,333 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
877 * @doi_def: the DOI definition 890 * @doi_def: the DOI definition
878 * @net_cat: the category bitmap in network/CIPSO format 891 * @net_cat: the category bitmap in network/CIPSO format
879 * @net_cat_len: the length of the CIPSO bitmap in bytes 892 * @net_cat_len: the length of the CIPSO bitmap in bytes
880 * @host_cat: the zero'd out category bitmap in host format 893 * @secattr: the security attributes
881 * @host_cat_len: the length of the host's category bitmap in bytes
882 * 894 *
883 * Description: 895 * Description:
884 * Perform a label mapping to translate a CIPSO bitmap to the correct local 896 * Perform a label mapping to translate a CIPSO bitmap to the correct local
885 * MLS category bitmap using the given DOI definition. Returns the minimum 897 * MLS category bitmap using the given DOI definition. Returns zero on
886 * size in bytes of the host bitmap on success, negative values otherwise. 898 * success, negative values on failure.
887 * 899 *
888 */ 900 */
889static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, 901static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
890 const unsigned char *net_cat, 902 const unsigned char *net_cat,
891 u32 net_cat_len, 903 u32 net_cat_len,
892 unsigned char *host_cat, 904 struct netlbl_lsm_secattr *secattr)
893 u32 host_cat_len)
894{ 905{
895 u32 host_spot; 906 int ret_val;
896 u32 host_spot_max = 0;
897 int net_spot = -1; 907 int net_spot = -1;
908 u32 host_spot = CIPSO_V4_INV_CAT;
898 u32 net_clen_bits = net_cat_len * 8; 909 u32 net_clen_bits = net_cat_len * 8;
899 u32 host_clen_bits = host_cat_len * 8; 910 u32 net_cat_size = 0;
900 u32 net_cat_size; 911 u32 *net_cat_array = NULL;
901 u32 *net_cat_array;
902 912
903 switch (doi_def->type) { 913 if (doi_def->type == CIPSO_V4_MAP_STD) {
904 case CIPSO_V4_MAP_PASS:
905 if (net_cat_len > host_cat_len)
906 return -EINVAL;
907 memcpy(host_cat, net_cat, net_cat_len);
908 return net_cat_len;
909 case CIPSO_V4_MAP_STD:
910 net_cat_size = doi_def->map.std->cat.cipso_size; 914 net_cat_size = doi_def->map.std->cat.cipso_size;
911 net_cat_array = doi_def->map.std->cat.cipso; 915 net_cat_array = doi_def->map.std->cat.cipso;
912 for (;;) { 916 }
913 net_spot = cipso_v4_bitmap_walk(net_cat,
914 net_clen_bits,
915 net_spot + 1,
916 1);
917 if (net_spot < 0)
918 break;
919 if (net_spot >= net_cat_size ||
920 net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
921 return -EPERM;
922 917
923 host_spot = net_cat_array[net_spot]; 918 for (;;) {
924 if (host_spot >= host_clen_bits) 919 net_spot = cipso_v4_bitmap_walk(net_cat,
925 return -ENOSPC; 920 net_clen_bits,
926 cipso_v4_bitmap_setbit(host_cat, host_spot, 1); 921 net_spot + 1,
922 1);
923 if (net_spot < 0) {
924 if (net_spot == -2)
925 return -EFAULT;
926 return 0;
927 }
927 928
928 if (host_spot > host_spot_max) 929 switch (doi_def->type) {
929 host_spot_max = host_spot; 930 case CIPSO_V4_MAP_PASS:
931 host_spot = net_spot;
932 break;
933 case CIPSO_V4_MAP_STD:
934 if (net_spot >= net_cat_size)
935 return -EPERM;
936 host_spot = net_cat_array[net_spot];
937 if (host_spot >= CIPSO_V4_INV_CAT)
938 return -EPERM;
939 break;
930 } 940 }
941 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
942 host_spot,
943 GFP_ATOMIC);
944 if (ret_val != 0)
945 return ret_val;
946 }
947
948 return -EINVAL;
949}
950
951/**
952 * cipso_v4_map_cat_enum_valid - Checks to see if the categories are valid
953 * @doi_def: the DOI definition
954 * @enumcat: category list
955 * @enumcat_len: length of the category list in bytes
956 *
957 * Description:
958 * Checks the given categories against the given DOI definition and returns a
959 * negative value if any of the categories do not have a valid mapping and a
960 * zero value if all of the categories are valid.
961 *
962 */
963static int cipso_v4_map_cat_enum_valid(const struct cipso_v4_doi *doi_def,
964 const unsigned char *enumcat,
965 u32 enumcat_len)
966{
967 u16 cat;
968 int cat_prev = -1;
969 u32 iter;
970
971 if (doi_def->type != CIPSO_V4_MAP_PASS || enumcat_len & 0x01)
972 return -EFAULT;
973
974 for (iter = 0; iter < enumcat_len; iter += 2) {
975 cat = ntohs(*((__be16 *)&enumcat[iter]));
976 if (cat <= cat_prev)
977 return -EFAULT;
978 cat_prev = cat;
979 }
980
981 return 0;
982}
983
984/**
985 * cipso_v4_map_cat_enum_hton - Perform a category mapping from host to network
986 * @doi_def: the DOI definition
987 * @secattr: the security attributes
988 * @net_cat: the zero'd out category list in network/CIPSO format
989 * @net_cat_len: the length of the CIPSO category list in bytes
990 *
991 * Description:
992 * Perform a label mapping to translate a local MLS category bitmap to the
993 * correct CIPSO category list using the given DOI definition. Returns the
994 * size in bytes of the network category bitmap on success, negative values
995 * otherwise.
996 *
997 */
998static int cipso_v4_map_cat_enum_hton(const struct cipso_v4_doi *doi_def,
999 const struct netlbl_lsm_secattr *secattr,
1000 unsigned char *net_cat,
1001 u32 net_cat_len)
1002{
1003 int cat = -1;
1004 u32 cat_iter = 0;
1005
1006 for (;;) {
1007 cat = netlbl_secattr_catmap_walk(secattr->mls_cat, cat + 1);
1008 if (cat < 0)
1009 break;
1010 if ((cat_iter + 2) > net_cat_len)
1011 return -ENOSPC;
1012
1013 *((__be16 *)&net_cat[cat_iter]) = htons(cat);
1014 cat_iter += 2;
1015 }
1016
1017 return cat_iter;
1018}
1019
1020/**
1021 * cipso_v4_map_cat_enum_ntoh - Perform a category mapping from network to host
1022 * @doi_def: the DOI definition
1023 * @net_cat: the category list in network/CIPSO format
1024 * @net_cat_len: the length of the CIPSO bitmap in bytes
1025 * @secattr: the security attributes
1026 *
1027 * Description:
1028 * Perform a label mapping to translate a CIPSO category list to the correct
1029 * local MLS category bitmap using the given DOI definition. Returns zero on
1030 * success, negative values on failure.
1031 *
1032 */
1033static int cipso_v4_map_cat_enum_ntoh(const struct cipso_v4_doi *doi_def,
1034 const unsigned char *net_cat,
1035 u32 net_cat_len,
1036 struct netlbl_lsm_secattr *secattr)
1037{
1038 int ret_val;
1039 u32 iter;
1040
1041 for (iter = 0; iter < net_cat_len; iter += 2) {
1042 ret_val = netlbl_secattr_catmap_setbit(secattr->mls_cat,
1043 ntohs(*((__be16 *)&net_cat[iter])),
1044 GFP_ATOMIC);
1045 if (ret_val != 0)
1046 return ret_val;
1047 }
1048
1049 return 0;
1050}
1051
1052/**
1053 * cipso_v4_map_cat_rng_valid - Checks to see if the categories are valid
1054 * @doi_def: the DOI definition
1055 * @rngcat: category list
1056 * @rngcat_len: length of the category list in bytes
1057 *
1058 * Description:
1059 * Checks the given categories against the given DOI definition and returns a
1060 * negative value if any of the categories do not have a valid mapping and a
1061 * zero value if all of the categories are valid.
1062 *
1063 */
1064static int cipso_v4_map_cat_rng_valid(const struct cipso_v4_doi *doi_def,
1065 const unsigned char *rngcat,
1066 u32 rngcat_len)
1067{
1068 u16 cat_high;
1069 u16 cat_low;
1070 u32 cat_prev = CIPSO_V4_MAX_REM_CATS + 1;
1071 u32 iter;
931 1072
932 if (net_spot == -2) 1073 if (doi_def->type != CIPSO_V4_MAP_PASS || rngcat_len & 0x01)
1074 return -EFAULT;
1075
1076 for (iter = 0; iter < rngcat_len; iter += 4) {
1077 cat_high = ntohs(*((__be16 *)&rngcat[iter]));
1078 if ((iter + 4) <= rngcat_len)
1079 cat_low = ntohs(*((__be16 *)&rngcat[iter + 2]));
1080 else
1081 cat_low = 0;
1082
1083 if (cat_high > cat_prev)
933 return -EFAULT; 1084 return -EFAULT;
934 1085
935 if (++host_spot_max % 8) 1086 cat_prev = cat_low;
936 return host_spot_max / 8 + 1;
937 return host_spot_max / 8;
938 } 1087 }
939 1088
940 return -EINVAL; 1089 return 0;
1090}
1091
1092/**
1093 * cipso_v4_map_cat_rng_hton - Perform a category mapping from host to network
1094 * @doi_def: the DOI definition
1095 * @secattr: the security attributes
1096 * @net_cat: the zero'd out category list in network/CIPSO format
1097 * @net_cat_len: the length of the CIPSO category list in bytes
1098 *
1099 * Description:
1100 * Perform a label mapping to translate a local MLS category bitmap to the
1101 * correct CIPSO category list using the given DOI definition. Returns the
1102 * size in bytes of the network category bitmap on success, negative values
1103 * otherwise.
1104 *
1105 */
1106static int cipso_v4_map_cat_rng_hton(const struct cipso_v4_doi *doi_def,
1107 const struct netlbl_lsm_secattr *secattr,
1108 unsigned char *net_cat,
1109 u32 net_cat_len)
1110{
1111 /* The constant '16' is not random, it is the maximum number of
1112 * high/low category range pairs as permitted by the CIPSO draft based
1113 * on a maximum IPv4 header length of 60 bytes - the BUG_ON() assertion
1114 * does a sanity check to make sure we don't overflow the array. */
1115 int iter = -1;
1116 u16 array[16];
1117 u32 array_cnt = 0;
1118 u32 cat_size = 0;
1119
1120 BUG_ON(net_cat_len > 30);
1121
1122 for (;;) {
1123 iter = netlbl_secattr_catmap_walk(secattr->mls_cat, iter + 1);
1124 if (iter < 0)
1125 break;
1126 cat_size += (iter == 0 ? 0 : sizeof(u16));
1127 if (cat_size > net_cat_len)
1128 return -ENOSPC;
1129 array[array_cnt++] = iter;
1130
1131 iter = netlbl_secattr_catmap_walk_rng(secattr->mls_cat, iter);
1132 if (iter < 0)
1133 return -EFAULT;
1134 cat_size += sizeof(u16);
1135 if (cat_size > net_cat_len)
1136 return -ENOSPC;
1137 array[array_cnt++] = iter;
1138 }
1139
1140 for (iter = 0; array_cnt > 0;) {
1141 *((__be16 *)&net_cat[iter]) = htons(array[--array_cnt]);
1142 iter += 2;
1143 array_cnt--;
1144 if (array[array_cnt] != 0) {
1145 *((__be16 *)&net_cat[iter]) = htons(array[array_cnt]);
1146 iter += 2;
1147 }
1148 }
1149
1150 return cat_size;
1151}
1152
1153/**
1154 * cipso_v4_map_cat_rng_ntoh - Perform a category mapping from network to host
1155 * @doi_def: the DOI definition
1156 * @net_cat: the category list in network/CIPSO format
1157 * @net_cat_len: the length of the CIPSO bitmap in bytes
1158 * @secattr: the security attributes
1159 *
1160 * Description:
1161 * Perform a label mapping to translate a CIPSO category list to the correct
1162 * local MLS category bitmap using the given DOI definition. Returns zero on
1163 * success, negative values on failure.
1164 *
1165 */
1166static int cipso_v4_map_cat_rng_ntoh(const struct cipso_v4_doi *doi_def,
1167 const unsigned char *net_cat,
1168 u32 net_cat_len,
1169 struct netlbl_lsm_secattr *secattr)
1170{
1171 int ret_val;
1172 u32 net_iter;
1173 u16 cat_low;
1174 u16 cat_high;
1175
1176 for(net_iter = 0; net_iter < net_cat_len; net_iter += 4) {
1177 cat_high = ntohs(*((__be16 *)&net_cat[net_iter]));
1178 if ((net_iter + 4) <= net_cat_len)
1179 cat_low = ntohs(*((__be16 *)&net_cat[net_iter + 2]));
1180 else
1181 cat_low = 0;
1182
1183 ret_val = netlbl_secattr_catmap_setrng(secattr->mls_cat,
1184 cat_low,
1185 cat_high,
1186 GFP_ATOMIC);
1187 if (ret_val != 0)
1188 return ret_val;
1189 }
1190
1191 return 0;
941} 1192}
942 1193
943/* 1194/*
944 * Protocol Handling Functions 1195 * Protocol Handling Functions
945 */ 1196 */
946 1197
1198#define CIPSO_V4_OPT_LEN_MAX 40
947#define CIPSO_V4_HDR_LEN 6 1199#define CIPSO_V4_HDR_LEN 6
948 1200
949/** 1201/**
950 * cipso_v4_gentag_hdr - Generate a CIPSO option header 1202 * cipso_v4_gentag_hdr - Generate a CIPSO option header
951 * @doi_def: the DOI definition 1203 * @doi_def: the DOI definition
952 * @len: the total tag length in bytes 1204 * @len: the total tag length in bytes, not including this header
953 * @buf: the CIPSO option buffer 1205 * @buf: the CIPSO option buffer
954 * 1206 *
955 * Description: 1207 * Description:
956 * Write a CIPSO header into the beginning of @buffer. Return zero on success, 1208 * Write a CIPSO header into the beginning of @buffer.
957 * negative values on failure.
958 * 1209 *
959 */ 1210 */
960static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, 1211static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
961 u32 len, 1212 unsigned char *buf,
962 unsigned char *buf) 1213 u32 len)
963{ 1214{
964 if (CIPSO_V4_HDR_LEN + len > 40)
965 return -ENOSPC;
966
967 buf[0] = IPOPT_CIPSO; 1215 buf[0] = IPOPT_CIPSO;
968 buf[1] = CIPSO_V4_HDR_LEN + len; 1216 buf[1] = CIPSO_V4_HDR_LEN + len;
969 *(u32 *)&buf[2] = htonl(doi_def->doi); 1217 *(__be32 *)&buf[2] = htonl(doi_def->doi);
970
971 return 0;
972} 1218}
973 1219
974#define CIPSO_V4_TAG1_CAT_LEN 30
975
976/** 1220/**
977 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) 1221 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
978 * @doi_def: the DOI definition 1222 * @doi_def: the DOI definition
@@ -983,83 +1227,249 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
983 * Description: 1227 * Description:
984 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The 1228 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
985 * actual buffer length may be larger than the indicated size due to 1229 * actual buffer length may be larger than the indicated size due to
986 * translation between host and network category bitmaps. Returns zero on 1230 * translation between host and network category bitmaps. Returns the size of
987 * success, negative values on failure. 1231 * the tag on success, negative values on failure.
988 * 1232 *
989 */ 1233 */
990static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, 1234static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
991 const struct netlbl_lsm_secattr *secattr, 1235 const struct netlbl_lsm_secattr *secattr,
992 unsigned char **buffer, 1236 unsigned char *buffer,
993 u32 *buffer_len) 1237 u32 buffer_len)
994{ 1238{
995 int ret_val = -EPERM; 1239 int ret_val;
996 unsigned char *buf = NULL; 1240 u32 tag_len;
997 u32 buf_len;
998 u32 level; 1241 u32 level;
999 1242
1000 if (secattr->mls_cat) { 1243 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
1001 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, 1244 return -EPERM;
1002 GFP_ATOMIC); 1245
1003 if (buf == NULL) 1246 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1004 return -ENOMEM; 1247 if (ret_val != 0)
1248 return ret_val;
1005 1249
1250 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1006 ret_val = cipso_v4_map_cat_rbm_hton(doi_def, 1251 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1007 secattr->mls_cat, 1252 secattr,
1008 secattr->mls_cat_len, 1253 &buffer[4],
1009 &buf[CIPSO_V4_HDR_LEN + 4], 1254 buffer_len - 4);
1010 CIPSO_V4_TAG1_CAT_LEN);
1011 if (ret_val < 0) 1255 if (ret_val < 0)
1012 goto gentag_failure; 1256 return ret_val;
1013 1257
1014 /* This will send packets using the "optimized" format when 1258 /* This will send packets using the "optimized" format when
1015 * possibile as specified in section 3.4.2.6 of the 1259 * possibile as specified in section 3.4.2.6 of the
1016 * CIPSO draft. */ 1260 * CIPSO draft. */
1017 if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) 1261 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1018 ret_val = 10; 1262 tag_len = 14;
1263 else
1264 tag_len = 4 + ret_val;
1265 } else
1266 tag_len = 4;
1267
1268 buffer[0] = 0x01;
1269 buffer[1] = tag_len;
1270 buffer[3] = level;
1271
1272 return tag_len;
1273}
1019 1274
1020 buf_len = 4 + ret_val; 1275/**
1021 } else { 1276 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
1022 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); 1277 * @doi_def: the DOI definition
1023 if (buf == NULL) 1278 * @tag: the CIPSO tag
1279 * @secattr: the security attributes
1280 *
1281 * Description:
1282 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
1283 * attributes in @secattr. Return zero on success, negatives values on
1284 * failure.
1285 *
1286 */
1287static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1288 const unsigned char *tag,
1289 struct netlbl_lsm_secattr *secattr)
1290{
1291 int ret_val;
1292 u8 tag_len = tag[1];
1293 u32 level;
1294
1295 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1296 if (ret_val != 0)
1297 return ret_val;
1298 secattr->mls_lvl = level;
1299 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1300
1301 if (tag_len > 4) {
1302 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1303 if (secattr->mls_cat == NULL)
1024 return -ENOMEM; 1304 return -ENOMEM;
1025 buf_len = 4; 1305
1306 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
1307 &tag[4],
1308 tag_len - 4,
1309 secattr);
1310 if (ret_val != 0) {
1311 netlbl_secattr_catmap_free(secattr->mls_cat);
1312 return ret_val;
1313 }
1314
1315 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1026 } 1316 }
1027 1317
1318 return 0;
1319}
1320
1321/**
1322 * cipso_v4_gentag_enum - Generate a CIPSO enumerated tag (type #2)
1323 * @doi_def: the DOI definition
1324 * @secattr: the security attributes
1325 * @buffer: the option buffer
1326 * @buffer_len: length of buffer in bytes
1327 *
1328 * Description:
1329 * Generate a CIPSO option using the enumerated tag, tag type #2. Returns the
1330 * size of the tag on success, negative values on failure.
1331 *
1332 */
1333static int cipso_v4_gentag_enum(const struct cipso_v4_doi *doi_def,
1334 const struct netlbl_lsm_secattr *secattr,
1335 unsigned char *buffer,
1336 u32 buffer_len)
1337{
1338 int ret_val;
1339 u32 tag_len;
1340 u32 level;
1341
1342 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1343 return -EPERM;
1344
1028 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); 1345 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1029 if (ret_val != 0) 1346 if (ret_val != 0)
1030 goto gentag_failure; 1347 return ret_val;
1348
1349 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1350 ret_val = cipso_v4_map_cat_enum_hton(doi_def,
1351 secattr,
1352 &buffer[4],
1353 buffer_len - 4);
1354 if (ret_val < 0)
1355 return ret_val;
1356
1357 tag_len = 4 + ret_val;
1358 } else
1359 tag_len = 4;
1360
1361 buffer[0] = 0x02;
1362 buffer[1] = tag_len;
1363 buffer[3] = level;
1031 1364
1032 ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); 1365 return tag_len;
1366}
1367
1368/**
1369 * cipso_v4_parsetag_enum - Parse a CIPSO enumerated tag
1370 * @doi_def: the DOI definition
1371 * @tag: the CIPSO tag
1372 * @secattr: the security attributes
1373 *
1374 * Description:
1375 * Parse a CIPSO enumerated tag (tag type #2) and return the security
1376 * attributes in @secattr. Return zero on success, negatives values on
1377 * failure.
1378 *
1379 */
1380static int cipso_v4_parsetag_enum(const struct cipso_v4_doi *doi_def,
1381 const unsigned char *tag,
1382 struct netlbl_lsm_secattr *secattr)
1383{
1384 int ret_val;
1385 u8 tag_len = tag[1];
1386 u32 level;
1387
1388 ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
1033 if (ret_val != 0) 1389 if (ret_val != 0)
1034 goto gentag_failure; 1390 return ret_val;
1391 secattr->mls_lvl = level;
1392 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1393
1394 if (tag_len > 4) {
1395 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1396 if (secattr->mls_cat == NULL)
1397 return -ENOMEM;
1035 1398
1036 buf[CIPSO_V4_HDR_LEN] = 0x01; 1399 ret_val = cipso_v4_map_cat_enum_ntoh(doi_def,
1037 buf[CIPSO_V4_HDR_LEN + 1] = buf_len; 1400 &tag[4],
1038 buf[CIPSO_V4_HDR_LEN + 3] = level; 1401 tag_len - 4,
1402 secattr);
1403 if (ret_val != 0) {
1404 netlbl_secattr_catmap_free(secattr->mls_cat);
1405 return ret_val;
1406 }
1039 1407
1040 *buffer = buf; 1408 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1041 *buffer_len = CIPSO_V4_HDR_LEN + buf_len; 1409 }
1042 1410
1043 return 0; 1411 return 0;
1412}
1044 1413
1045gentag_failure: 1414/**
1046 kfree(buf); 1415 * cipso_v4_gentag_rng - Generate a CIPSO ranged tag (type #5)
1047 return ret_val; 1416 * @doi_def: the DOI definition
1417 * @secattr: the security attributes
1418 * @buffer: the option buffer
1419 * @buffer_len: length of buffer in bytes
1420 *
1421 * Description:
1422 * Generate a CIPSO option using the ranged tag, tag type #5. Returns the
1423 * size of the tag on success, negative values on failure.
1424 *
1425 */
1426static int cipso_v4_gentag_rng(const struct cipso_v4_doi *doi_def,
1427 const struct netlbl_lsm_secattr *secattr,
1428 unsigned char *buffer,
1429 u32 buffer_len)
1430{
1431 int ret_val;
1432 u32 tag_len;
1433 u32 level;
1434
1435 if (!(secattr->flags & NETLBL_SECATTR_MLS_LVL))
1436 return -EPERM;
1437
1438 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1439 if (ret_val != 0)
1440 return ret_val;
1441
1442 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1443 ret_val = cipso_v4_map_cat_rng_hton(doi_def,
1444 secattr,
1445 &buffer[4],
1446 buffer_len - 4);
1447 if (ret_val < 0)
1448 return ret_val;
1449
1450 tag_len = 4 + ret_val;
1451 } else
1452 tag_len = 4;
1453
1454 buffer[0] = 0x05;
1455 buffer[1] = tag_len;
1456 buffer[3] = level;
1457
1458 return tag_len;
1048} 1459}
1049 1460
1050/** 1461/**
1051 * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag 1462 * cipso_v4_parsetag_rng - Parse a CIPSO ranged tag
1052 * @doi_def: the DOI definition 1463 * @doi_def: the DOI definition
1053 * @tag: the CIPSO tag 1464 * @tag: the CIPSO tag
1054 * @secattr: the security attributes 1465 * @secattr: the security attributes
1055 * 1466 *
1056 * Description: 1467 * Description:
1057 * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security 1468 * Parse a CIPSO ranged tag (tag type #5) and return the security attributes
1058 * attributes in @secattr. Return zero on success, negatives values on 1469 * in @secattr. Return zero on success, negatives values on failure.
1059 * failure.
1060 * 1470 *
1061 */ 1471 */
1062static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, 1472static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def,
1063 const unsigned char *tag, 1473 const unsigned char *tag,
1064 struct netlbl_lsm_secattr *secattr) 1474 struct netlbl_lsm_secattr *secattr)
1065{ 1475{
@@ -1071,32 +1481,23 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
1071 if (ret_val != 0) 1481 if (ret_val != 0)
1072 return ret_val; 1482 return ret_val;
1073 secattr->mls_lvl = level; 1483 secattr->mls_lvl = level;
1074 secattr->mls_lvl_vld = 1; 1484 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
1075 1485
1076 if (tag_len > 4) { 1486 if (tag_len > 4) {
1077 switch (doi_def->type) { 1487 secattr->mls_cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
1078 case CIPSO_V4_MAP_PASS:
1079 secattr->mls_cat_len = tag_len - 4;
1080 break;
1081 case CIPSO_V4_MAP_STD:
1082 secattr->mls_cat_len =
1083 doi_def->map.std->cat.local_size;
1084 break;
1085 }
1086 secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
1087 if (secattr->mls_cat == NULL) 1488 if (secattr->mls_cat == NULL)
1088 return -ENOMEM; 1489 return -ENOMEM;
1089 1490
1090 ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, 1491 ret_val = cipso_v4_map_cat_rng_ntoh(doi_def,
1091 &tag[4], 1492 &tag[4],
1092 tag_len - 4, 1493 tag_len - 4,
1093 secattr->mls_cat, 1494 secattr);
1094 secattr->mls_cat_len); 1495 if (ret_val != 0) {
1095 if (ret_val < 0) { 1496 netlbl_secattr_catmap_free(secattr->mls_cat);
1096 kfree(secattr->mls_cat);
1097 return ret_val; 1497 return ret_val;
1098 } 1498 }
1099 secattr->mls_cat_len = ret_val; 1499
1500 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
1100 } 1501 }
1101 1502
1102 return 0; 1503 return 0;
@@ -1140,7 +1541,7 @@ int cipso_v4_validate(unsigned char **option)
1140 } 1541 }
1141 1542
1142 rcu_read_lock(); 1543 rcu_read_lock();
1143 doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2]))); 1544 doi_def = cipso_v4_doi_search(ntohl(*((__be32 *)&opt[2])));
1144 if (doi_def == NULL) { 1545 if (doi_def == NULL) {
1145 err_offset = 2; 1546 err_offset = 2;
1146 goto validate_return_locked; 1547 goto validate_return_locked;
@@ -1191,6 +1592,44 @@ int cipso_v4_validate(unsigned char **option)
1191 } 1592 }
1192 } 1593 }
1193 break; 1594 break;
1595 case CIPSO_V4_TAG_ENUM:
1596 if (tag_len < 4) {
1597 err_offset = opt_iter + 1;
1598 goto validate_return_locked;
1599 }
1600
1601 if (cipso_v4_map_lvl_valid(doi_def,
1602 tag[3]) < 0) {
1603 err_offset = opt_iter + 3;
1604 goto validate_return_locked;
1605 }
1606 if (tag_len > 4 &&
1607 cipso_v4_map_cat_enum_valid(doi_def,
1608 &tag[4],
1609 tag_len - 4) < 0) {
1610 err_offset = opt_iter + 4;
1611 goto validate_return_locked;
1612 }
1613 break;
1614 case CIPSO_V4_TAG_RANGE:
1615 if (tag_len < 4) {
1616 err_offset = opt_iter + 1;
1617 goto validate_return_locked;
1618 }
1619
1620 if (cipso_v4_map_lvl_valid(doi_def,
1621 tag[3]) < 0) {
1622 err_offset = opt_iter + 3;
1623 goto validate_return_locked;
1624 }
1625 if (tag_len > 4 &&
1626 cipso_v4_map_cat_rng_valid(doi_def,
1627 &tag[4],
1628 tag_len - 4) < 0) {
1629 err_offset = opt_iter + 4;
1630 goto validate_return_locked;
1631 }
1632 break;
1194 default: 1633 default:
1195 err_offset = opt_iter; 1634 err_offset = opt_iter;
1196 goto validate_return_locked; 1635 goto validate_return_locked;
@@ -1265,7 +1704,7 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1265{ 1704{
1266 int ret_val = -EPERM; 1705 int ret_val = -EPERM;
1267 u32 iter; 1706 u32 iter;
1268 unsigned char *buf = NULL; 1707 unsigned char *buf;
1269 u32 buf_len = 0; 1708 u32 buf_len = 0;
1270 u32 opt_len; 1709 u32 opt_len;
1271 struct ip_options *opt = NULL; 1710 struct ip_options *opt = NULL;
@@ -1281,17 +1720,40 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1281 if (sk == NULL) 1720 if (sk == NULL)
1282 return 0; 1721 return 0;
1283 1722
1723 /* We allocate the maximum CIPSO option size here so we are probably
1724 * being a little wasteful, but it makes our life _much_ easier later
1725 * on and after all we are only talking about 40 bytes. */
1726 buf_len = CIPSO_V4_OPT_LEN_MAX;
1727 buf = kmalloc(buf_len, GFP_ATOMIC);
1728 if (buf == NULL) {
1729 ret_val = -ENOMEM;
1730 goto socket_setattr_failure;
1731 }
1732
1284 /* XXX - This code assumes only one tag per CIPSO option which isn't 1733 /* XXX - This code assumes only one tag per CIPSO option which isn't
1285 * really a good assumption to make but since we only support the MAC 1734 * really a good assumption to make but since we only support the MAC
1286 * tags right now it is a safe assumption. */ 1735 * tags right now it is a safe assumption. */
1287 iter = 0; 1736 iter = 0;
1288 do { 1737 do {
1738 memset(buf, 0, buf_len);
1289 switch (doi_def->tags[iter]) { 1739 switch (doi_def->tags[iter]) {
1290 case CIPSO_V4_TAG_RBITMAP: 1740 case CIPSO_V4_TAG_RBITMAP:
1291 ret_val = cipso_v4_gentag_rbm(doi_def, 1741 ret_val = cipso_v4_gentag_rbm(doi_def,
1292 secattr, 1742 secattr,
1293 &buf, 1743 &buf[CIPSO_V4_HDR_LEN],
1294 &buf_len); 1744 buf_len - CIPSO_V4_HDR_LEN);
1745 break;
1746 case CIPSO_V4_TAG_ENUM:
1747 ret_val = cipso_v4_gentag_enum(doi_def,
1748 secattr,
1749 &buf[CIPSO_V4_HDR_LEN],
1750 buf_len - CIPSO_V4_HDR_LEN);
1751 break;
1752 case CIPSO_V4_TAG_RANGE:
1753 ret_val = cipso_v4_gentag_rng(doi_def,
1754 secattr,
1755 &buf[CIPSO_V4_HDR_LEN],
1756 buf_len - CIPSO_V4_HDR_LEN);
1295 break; 1757 break;
1296 default: 1758 default:
1297 ret_val = -EPERM; 1759 ret_val = -EPERM;
@@ -1299,11 +1761,13 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1299 } 1761 }
1300 1762
1301 iter++; 1763 iter++;
1302 } while (ret_val != 0 && 1764 } while (ret_val < 0 &&
1303 iter < CIPSO_V4_TAG_MAXCNT && 1765 iter < CIPSO_V4_TAG_MAXCNT &&
1304 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1766 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1305 if (ret_val != 0) 1767 if (ret_val < 0)
1306 goto socket_setattr_failure; 1768 goto socket_setattr_failure;
1769 cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1770 buf_len = CIPSO_V4_HDR_LEN + ret_val;
1307 1771
1308 /* We can't use ip_options_get() directly because it makes a call to 1772 /* We can't use ip_options_get() directly because it makes a call to
1309 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1773 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1370,19 +1834,33 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1370 if (ret_val == 0) 1834 if (ret_val == 0)
1371 return ret_val; 1835 return ret_val;
1372 1836
1373 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1837 doi = ntohl(*(__be32 *)&cipso_ptr[2]);
1374 rcu_read_lock(); 1838 rcu_read_lock();
1375 doi_def = cipso_v4_doi_getdef(doi); 1839 doi_def = cipso_v4_doi_search(doi);
1376 if (doi_def == NULL) { 1840 if (doi_def == NULL) {
1377 rcu_read_unlock(); 1841 rcu_read_unlock();
1378 return -ENOMSG; 1842 return -ENOMSG;
1379 } 1843 }
1844
1845 /* XXX - This code assumes only one tag per CIPSO option which isn't
1846 * really a good assumption to make but since we only support the MAC
1847 * tags right now it is a safe assumption. */
1380 switch (cipso_ptr[6]) { 1848 switch (cipso_ptr[6]) {
1381 case CIPSO_V4_TAG_RBITMAP: 1849 case CIPSO_V4_TAG_RBITMAP:
1382 ret_val = cipso_v4_parsetag_rbm(doi_def, 1850 ret_val = cipso_v4_parsetag_rbm(doi_def,
1383 &cipso_ptr[6], 1851 &cipso_ptr[6],
1384 secattr); 1852 secattr);
1385 break; 1853 break;
1854 case CIPSO_V4_TAG_ENUM:
1855 ret_val = cipso_v4_parsetag_enum(doi_def,
1856 &cipso_ptr[6],
1857 secattr);
1858 break;
1859 case CIPSO_V4_TAG_RANGE:
1860 ret_val = cipso_v4_parsetag_rng(doi_def,
1861 &cipso_ptr[6],
1862 secattr);
1863 break;
1386 } 1864 }
1387 rcu_read_unlock(); 1865 rcu_read_unlock();
1388 1866
@@ -1430,23 +1908,30 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1430 u32 doi; 1908 u32 doi;
1431 struct cipso_v4_doi *doi_def; 1909 struct cipso_v4_doi *doi_def;
1432 1910
1433 if (!CIPSO_V4_OPTEXIST(skb))
1434 return -ENOMSG;
1435 cipso_ptr = CIPSO_V4_OPTPTR(skb); 1911 cipso_ptr = CIPSO_V4_OPTPTR(skb);
1436 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) 1912 if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
1437 return 0; 1913 return 0;
1438 1914
1439 doi = ntohl(*(u32 *)&cipso_ptr[2]); 1915 doi = ntohl(*(__be32 *)&cipso_ptr[2]);
1440 rcu_read_lock(); 1916 rcu_read_lock();
1441 doi_def = cipso_v4_doi_getdef(doi); 1917 doi_def = cipso_v4_doi_search(doi);
1442 if (doi_def == NULL) 1918 if (doi_def == NULL)
1443 goto skbuff_getattr_return; 1919 goto skbuff_getattr_return;
1920
1921 /* XXX - This code assumes only one tag per CIPSO option which isn't
1922 * really a good assumption to make but since we only support the MAC
1923 * tags right now it is a safe assumption. */
1444 switch (cipso_ptr[6]) { 1924 switch (cipso_ptr[6]) {
1445 case CIPSO_V4_TAG_RBITMAP: 1925 case CIPSO_V4_TAG_RBITMAP:
1446 ret_val = cipso_v4_parsetag_rbm(doi_def, 1926 ret_val = cipso_v4_parsetag_rbm(doi_def,
1447 &cipso_ptr[6], 1927 &cipso_ptr[6],
1448 secattr); 1928 secattr);
1449 break; 1929 break;
1930 case CIPSO_V4_TAG_ENUM:
1931 ret_val = cipso_v4_parsetag_enum(doi_def,
1932 &cipso_ptr[6],
1933 secattr);
1934 break;
1450 } 1935 }
1451 1936
1452skbuff_getattr_return: 1937skbuff_getattr_return:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7602c79a389b..2fd899160f85 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -577,20 +577,20 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
577 * Determine a default network mask, based on the IP address. 577 * Determine a default network mask, based on the IP address.
578 */ 578 */
579 579
580static __inline__ int inet_abc_len(u32 addr) 580static __inline__ int inet_abc_len(__be32 addr)
581{ 581{
582 int rc = -1; /* Something else, probably a multicast. */ 582 int rc = -1; /* Something else, probably a multicast. */
583 583
584 if (ZERONET(addr)) 584 if (ZERONET(addr))
585 rc = 0; 585 rc = 0;
586 else { 586 else {
587 addr = ntohl(addr); 587 __u32 haddr = ntohl(addr);
588 588
589 if (IN_CLASSA(addr)) 589 if (IN_CLASSA(haddr))
590 rc = 8; 590 rc = 8;
591 else if (IN_CLASSB(addr)) 591 else if (IN_CLASSB(haddr))
592 rc = 16; 592 rc = 16;
593 else if (IN_CLASSC(addr)) 593 else if (IN_CLASSC(haddr))
594 rc = 24; 594 rc = 24;
595 } 595 }
596 596
@@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = {
1120 .notifier_call =inetdev_event, 1120 .notifier_call =inetdev_event,
1121}; 1121};
1122 1122
1123static inline size_t inet_nlmsg_size(void)
1124{
1125 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
1126 + nla_total_size(4) /* IFA_ADDRESS */
1127 + nla_total_size(4) /* IFA_LOCAL */
1128 + nla_total_size(4) /* IFA_BROADCAST */
1129 + nla_total_size(4) /* IFA_ANYCAST */
1130 + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
1131}
1132
1123static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, 1133static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1124 u32 pid, u32 seq, int event, unsigned int flags) 1134 u32 pid, u32 seq, int event, unsigned int flags)
1125{ 1135{
@@ -1208,15 +1218,13 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
1208 u32 seq = nlh ? nlh->nlmsg_seq : 0; 1218 u32 seq = nlh ? nlh->nlmsg_seq : 0;
1209 int err = -ENOBUFS; 1219 int err = -ENOBUFS;
1210 1220
1211 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1221 skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
1212 if (skb == NULL) 1222 if (skb == NULL)
1213 goto errout; 1223 goto errout;
1214 1224
1215 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); 1225 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1216 if (err < 0) { 1226 /* failure implies BUG in inet_nlmsg_size() */
1217 kfree_skb(skb); 1227 BUG_ON(err < 0);
1218 goto errout;
1219 }
1220 1228
1221 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1229 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1222errout: 1230errout:
@@ -1556,12 +1564,12 @@ static void devinet_sysctl_register(struct in_device *in_dev,
1556{ 1564{
1557 int i; 1565 int i;
1558 struct net_device *dev = in_dev ? in_dev->dev : NULL; 1566 struct net_device *dev = in_dev ? in_dev->dev : NULL;
1559 struct devinet_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL); 1567 struct devinet_sysctl_table *t = kmemdup(&devinet_sysctl, sizeof(*t),
1568 GFP_KERNEL);
1560 char *dev_name = NULL; 1569 char *dev_name = NULL;
1561 1570
1562 if (!t) 1571 if (!t)
1563 return; 1572 return;
1564 memcpy(t, &devinet_sysctl, sizeof(*t));
1565 for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) { 1573 for (i = 0; i < ARRAY_SIZE(t->devinet_vars) - 1; i++) {
1566 t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf; 1574 t->devinet_vars[i].data += (char *)p - (char *)&ipv4_devconf;
1567 t->devinet_vars[i].de = NULL; 1575 t->devinet_vars[i].de = NULL;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index b5c205b57669..f2c6776ea0e6 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -67,7 +67,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
67 if (x->encap) { 67 if (x->encap) {
68 struct xfrm_encap_tmpl *encap = x->encap; 68 struct xfrm_encap_tmpl *encap = x->encap;
69 struct udphdr *uh; 69 struct udphdr *uh;
70 u32 *udpdata32; 70 __be32 *udpdata32;
71 71
72 uh = (struct udphdr *)esph; 72 uh = (struct udphdr *)esph;
73 uh->source = encap->encap_sport; 73 uh->source = encap->encap_sport;
@@ -81,7 +81,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
81 esph = (struct ip_esp_hdr *)(uh + 1); 81 esph = (struct ip_esp_hdr *)(uh + 1);
82 break; 82 break;
83 case UDP_ENCAP_ESPINUDP_NON_IKE: 83 case UDP_ENCAP_ESPINUDP_NON_IKE:
84 udpdata32 = (u32 *)(uh + 1); 84 udpdata32 = (__be32 *)(uh + 1);
85 udpdata32[0] = udpdata32[1] = 0; 85 udpdata32[0] = udpdata32[1] = 0;
86 esph = (struct ip_esp_hdr *)(udpdata32 + 2); 86 esph = (struct ip_esp_hdr *)(udpdata32 + 2);
87 break; 87 break;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index af0190d8b6c0..d47b72af89ed 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -768,8 +768,8 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
768{ 768{
769 769
770 struct fib_result res; 770 struct fib_result res;
771 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 771 struct flowi fl = { .mark = frn->fl_mark,
772 .fwmark = frn->fl_fwmark, 772 .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
773 .tos = frn->fl_tos, 773 .tos = frn->fl_tos,
774 .scope = frn->fl_scope } } }; 774 .scope = frn->fl_scope } } };
775 if (tb) { 775 if (tb) {
@@ -811,7 +811,6 @@ static void nl_fib_input(struct sock *sk, int len)
811 811
812 pid = nlh->nlmsg_pid; /*pid of sending process */ 812 pid = nlh->nlmsg_pid; /*pid of sending process */
813 NETLINK_CB(skb).pid = 0; /* from kernel */ 813 NETLINK_CB(skb).pid = 0; /* from kernel */
814 NETLINK_CB(skb).dst_pid = pid;
815 NETLINK_CB(skb).dst_group = 0; /* unicast */ 814 NETLINK_CB(skb).dst_group = 0; /* unicast */
816 netlink_unicast(sk, skb, pid, MSG_DONTWAIT); 815 netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
817} 816}
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 0852b9cd065a..b837c33e0404 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -44,10 +44,6 @@ struct fib4_rule
44 __be32 srcmask; 44 __be32 srcmask;
45 __be32 dst; 45 __be32 dst;
46 __be32 dstmask; 46 __be32 dstmask;
47#ifdef CONFIG_IP_ROUTE_FWMARK
48 u32 fwmark;
49 u32 fwmask;
50#endif
51#ifdef CONFIG_NET_CLS_ROUTE 47#ifdef CONFIG_NET_CLS_ROUTE
52 u32 tclassid; 48 u32 tclassid;
53#endif 49#endif
@@ -160,11 +156,6 @@ static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
160 if (r->tos && (r->tos != fl->fl4_tos)) 156 if (r->tos && (r->tos != fl->fl4_tos))
161 return 0; 157 return 0;
162 158
163#ifdef CONFIG_IP_ROUTE_FWMARK
164 if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask)
165 return 0;
166#endif
167
168 return 1; 159 return 1;
169} 160}
170 161
@@ -179,14 +170,10 @@ static struct fib_table *fib_empty_table(void)
179} 170}
180 171
181static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { 172static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
182 [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, 173 FRA_GENERIC_POLICY,
183 [FRA_PRIORITY] = { .type = NLA_U32 },
184 [FRA_SRC] = { .type = NLA_U32 }, 174 [FRA_SRC] = { .type = NLA_U32 },
185 [FRA_DST] = { .type = NLA_U32 }, 175 [FRA_DST] = { .type = NLA_U32 },
186 [FRA_FWMARK] = { .type = NLA_U32 },
187 [FRA_FWMASK] = { .type = NLA_U32 },
188 [FRA_FLOW] = { .type = NLA_U32 }, 176 [FRA_FLOW] = { .type = NLA_U32 },
189 [FRA_TABLE] = { .type = NLA_U32 },
190}; 177};
191 178
192static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 179static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
@@ -220,20 +207,6 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
220 if (tb[FRA_DST]) 207 if (tb[FRA_DST])
221 rule4->dst = nla_get_be32(tb[FRA_DST]); 208 rule4->dst = nla_get_be32(tb[FRA_DST]);
222 209
223#ifdef CONFIG_IP_ROUTE_FWMARK
224 if (tb[FRA_FWMARK]) {
225 rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]);
226 if (rule4->fwmark)
227 /* compatibility: if the mark value is non-zero all bits
228 * are compared unless a mask is explicitly specified.
229 */
230 rule4->fwmask = 0xFFFFFFFF;
231 }
232
233 if (tb[FRA_FWMASK])
234 rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]);
235#endif
236
237#ifdef CONFIG_NET_CLS_ROUTE 210#ifdef CONFIG_NET_CLS_ROUTE
238 if (tb[FRA_FLOW]) 211 if (tb[FRA_FLOW])
239 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); 212 rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
@@ -264,14 +237,6 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
264 if (frh->tos && (rule4->tos != frh->tos)) 237 if (frh->tos && (rule4->tos != frh->tos))
265 return 0; 238 return 0;
266 239
267#ifdef CONFIG_IP_ROUTE_FWMARK
268 if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK])))
269 return 0;
270
271 if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK])))
272 return 0;
273#endif
274
275#ifdef CONFIG_NET_CLS_ROUTE 240#ifdef CONFIG_NET_CLS_ROUTE
276 if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW]))) 241 if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
277 return 0; 242 return 0;
@@ -296,14 +261,6 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
296 frh->src_len = rule4->src_len; 261 frh->src_len = rule4->src_len;
297 frh->tos = rule4->tos; 262 frh->tos = rule4->tos;
298 263
299#ifdef CONFIG_IP_ROUTE_FWMARK
300 if (rule4->fwmark)
301 NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark);
302
303 if (rule4->fwmask || rule4->fwmark)
304 NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask);
305#endif
306
307 if (rule4->dst_len) 264 if (rule4->dst_len)
308 NLA_PUT_BE32(skb, FRA_DST, rule4->dst); 265 NLA_PUT_BE32(skb, FRA_DST, rule4->dst);
309 266
@@ -342,6 +299,13 @@ static u32 fib4_rule_default_pref(void)
342 return 0; 299 return 0;
343} 300}
344 301
302static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
303{
304 return nla_total_size(4) /* dst */
305 + nla_total_size(4) /* src */
306 + nla_total_size(4); /* flow */
307}
308
345static struct fib_rules_ops fib4_rules_ops = { 309static struct fib_rules_ops fib4_rules_ops = {
346 .family = AF_INET, 310 .family = AF_INET,
347 .rule_size = sizeof(struct fib4_rule), 311 .rule_size = sizeof(struct fib4_rule),
@@ -351,6 +315,7 @@ static struct fib_rules_ops fib4_rules_ops = {
351 .compare = fib4_rule_compare, 315 .compare = fib4_rule_compare,
352 .fill = fib4_rule_fill, 316 .fill = fib4_rule_fill,
353 .default_pref = fib4_rule_default_pref, 317 .default_pref = fib4_rule_default_pref,
318 .nlmsg_payload = fib4_rule_nlmsg_payload,
354 .nlgroup = RTNLGRP_IPV4_RULE, 319 .nlgroup = RTNLGRP_IPV4_RULE,
355 .policy = fib4_rule_policy, 320 .policy = fib4_rule_policy,
356 .rules_list = &fib4_rules, 321 .rules_list = &fib4_rules,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 884d176e0082..e63b8a98fb4d 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev)
273 return -1; 273 return -1;
274} 274}
275 275
276static inline size_t fib_nlmsg_size(struct fib_info *fi)
277{
278 size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
279 + nla_total_size(4) /* RTA_TABLE */
280 + nla_total_size(4) /* RTA_DST */
281 + nla_total_size(4) /* RTA_PRIORITY */
282 + nla_total_size(4); /* RTA_PREFSRC */
283
284 /* space for nested metrics */
285 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
286
287 if (fi->fib_nhs) {
288 /* Also handles the special case fib_nhs == 1 */
289
290 /* each nexthop is packed in an attribute */
291 size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
292
293 /* may contain flow and gateway attribute */
294 nhsize += 2 * nla_total_size(4);
295
296 /* all nexthops are packed in a nested attribute */
297 payload += nla_total_size(fi->fib_nhs * nhsize);
298 }
299
300 return payload;
301}
302
276void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, 303void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
277 int dst_len, u32 tb_id, struct nl_info *info) 304 int dst_len, u32 tb_id, struct nl_info *info)
278{ 305{
279 struct sk_buff *skb; 306 struct sk_buff *skb;
280 int payload = sizeof(struct rtmsg) + 256;
281 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; 307 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
282 int err = -ENOBUFS; 308 int err = -ENOBUFS;
283 309
284 skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); 310 skb = nlmsg_new(fib_nlmsg_size(fa->fa_info), GFP_KERNEL);
285 if (skb == NULL) 311 if (skb == NULL)
286 goto errout; 312 goto errout;
287 313
288 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 314 err = fib_dump_info(skb, info->pid, seq, event, tb_id,
289 fa->fa_type, fa->fa_scope, key, dst_len, 315 fa->fa_type, fa->fa_scope, key, dst_len,
290 fa->fa_tos, fa->fa_info, 0); 316 fa->fa_tos, fa->fa_info, 0);
291 if (err < 0) { 317 /* failure implies BUG in fib_nlmsg_size() */
292 kfree_skb(skb); 318 BUG_ON(err < 0);
293 goto errout;
294 }
295 319
296 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, 320 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
297 info->nlh, GFP_KERNEL); 321 info->nlh, GFP_KERNEL);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index b39a37a47545..40cf0d0e1b83 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -332,7 +332,7 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd,
332 struct sk_buff *skb) 332 struct sk_buff *skb)
333{ 333{
334 struct icmp_bxm *icmp_param = (struct icmp_bxm *)from; 334 struct icmp_bxm *icmp_param = (struct icmp_bxm *)from;
335 unsigned int csum; 335 __wsum csum;
336 336
337 csum = skb_copy_and_csum_bits(icmp_param->skb, 337 csum = skb_copy_and_csum_bits(icmp_param->skb,
338 icmp_param->offset + offset, 338 icmp_param->offset + offset,
@@ -356,7 +356,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
356 ip_flush_pending_frames(icmp_socket->sk); 356 ip_flush_pending_frames(icmp_socket->sk);
357 else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { 357 else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) {
358 struct icmphdr *icmph = skb->h.icmph; 358 struct icmphdr *icmph = skb->h.icmph;
359 unsigned int csum = 0; 359 __wsum csum = 0;
360 struct sk_buff *skb1; 360 struct sk_buff *skb1;
361 361
362 skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) { 362 skb_queue_walk(&icmp_socket->sk->sk_write_queue, skb1) {
@@ -931,7 +931,7 @@ int icmp_rcv(struct sk_buff *skb)
931 931
932 switch (skb->ip_summed) { 932 switch (skb->ip_summed) {
933 case CHECKSUM_COMPLETE: 933 case CHECKSUM_COMPLETE:
934 if (!(u16)csum_fold(skb->csum)) 934 if (!csum_fold(skb->csum))
935 break; 935 break;
936 /* fall through */ 936 /* fall through */
937 case CHECKSUM_NONE: 937 case CHECKSUM_NONE:
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 6eee71647b7c..0017ccb01d6d 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -932,7 +932,7 @@ int igmp_rcv(struct sk_buff *skb)
932 932
933 switch (skb->ip_summed) { 933 switch (skb->ip_summed) {
934 case CHECKSUM_COMPLETE: 934 case CHECKSUM_COMPLETE:
935 if (!(u16)csum_fold(skb->csum)) 935 if (!csum_fold(skb->csum))
936 break; 936 break;
937 /* fall through */ 937 /* fall through */
938 case CHECKSUM_NONE: 938 case CHECKSUM_NONE:
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 96bbe2a0aa1b..9d68837888d3 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -343,7 +343,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
343EXPORT_SYMBOL_GPL(inet_csk_route_req); 343EXPORT_SYMBOL_GPL(inet_csk_route_req);
344 344
345static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, 345static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport,
346 const u32 rnd, const u16 synq_hsize) 346 const u32 rnd, const u32 synq_hsize)
347{ 347{
348 return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); 348 return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1);
349} 349}
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index d5b5dec075b8..476cb6084c75 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -144,7 +144,7 @@ static struct net_device *ipgre_fb_tunnel_dev;
144 */ 144 */
145 145
146#define HASH_SIZE 16 146#define HASH_SIZE 16
147#define HASH(addr) ((addr^(addr>>4))&0xF) 147#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
148 148
149static struct ip_tunnel *tunnels[4][HASH_SIZE]; 149static struct ip_tunnel *tunnels[4][HASH_SIZE];
150 150
@@ -157,7 +157,7 @@ static DEFINE_RWLOCK(ipgre_lock);
157 157
158/* Given src, dst and key, find appropriate for input tunnel. */ 158/* Given src, dst and key, find appropriate for input tunnel. */
159 159
160static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) 160static struct ip_tunnel * ipgre_tunnel_lookup(__be32 remote, __be32 local, __be32 key)
161{ 161{
162 unsigned h0 = HASH(remote); 162 unsigned h0 = HASH(remote);
163 unsigned h1 = HASH(key); 163 unsigned h1 = HASH(key);
@@ -194,9 +194,9 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key)
194 194
195static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t) 195static struct ip_tunnel **ipgre_bucket(struct ip_tunnel *t)
196{ 196{
197 u32 remote = t->parms.iph.daddr; 197 __be32 remote = t->parms.iph.daddr;
198 u32 local = t->parms.iph.saddr; 198 __be32 local = t->parms.iph.saddr;
199 u32 key = t->parms.i_key; 199 __be32 key = t->parms.i_key;
200 unsigned h = HASH(key); 200 unsigned h = HASH(key);
201 int prio = 0; 201 int prio = 0;
202 202
@@ -236,9 +236,9 @@ static void ipgre_tunnel_unlink(struct ip_tunnel *t)
236 236
237static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create) 237static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int create)
238{ 238{
239 u32 remote = parms->iph.daddr; 239 __be32 remote = parms->iph.daddr;
240 u32 local = parms->iph.saddr; 240 __be32 local = parms->iph.saddr;
241 u32 key = parms->i_key; 241 __be32 key = parms->i_key;
242 struct ip_tunnel *t, **tp, *nt; 242 struct ip_tunnel *t, **tp, *nt;
243 struct net_device *dev; 243 struct net_device *dev;
244 unsigned h = HASH(key); 244 unsigned h = HASH(key);
@@ -319,12 +319,12 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
319 */ 319 */
320 320
321 struct iphdr *iph = (struct iphdr*)skb->data; 321 struct iphdr *iph = (struct iphdr*)skb->data;
322 u16 *p = (u16*)(skb->data+(iph->ihl<<2)); 322 __be16 *p = (__be16*)(skb->data+(iph->ihl<<2));
323 int grehlen = (iph->ihl<<2) + 4; 323 int grehlen = (iph->ihl<<2) + 4;
324 int type = skb->h.icmph->type; 324 int type = skb->h.icmph->type;
325 int code = skb->h.icmph->code; 325 int code = skb->h.icmph->code;
326 struct ip_tunnel *t; 326 struct ip_tunnel *t;
327 u16 flags; 327 __be16 flags;
328 328
329 flags = p[0]; 329 flags = p[0];
330 if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { 330 if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
@@ -370,7 +370,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
370 } 370 }
371 371
372 read_lock(&ipgre_lock); 372 read_lock(&ipgre_lock);
373 t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((u32*)p) + (grehlen>>2) - 1) : 0); 373 t = ipgre_tunnel_lookup(iph->daddr, iph->saddr, (flags&GRE_KEY) ? *(((__be32*)p) + (grehlen>>2) - 1) : 0);
374 if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr)) 374 if (t == NULL || t->parms.iph.daddr == 0 || MULTICAST(t->parms.iph.daddr))
375 goto out; 375 goto out;
376 376
@@ -388,14 +388,14 @@ out:
388#else 388#else
389 struct iphdr *iph = (struct iphdr*)dp; 389 struct iphdr *iph = (struct iphdr*)dp;
390 struct iphdr *eiph; 390 struct iphdr *eiph;
391 u16 *p = (u16*)(dp+(iph->ihl<<2)); 391 __be16 *p = (__be16*)(dp+(iph->ihl<<2));
392 int type = skb->h.icmph->type; 392 int type = skb->h.icmph->type;
393 int code = skb->h.icmph->code; 393 int code = skb->h.icmph->code;
394 int rel_type = 0; 394 int rel_type = 0;
395 int rel_code = 0; 395 int rel_code = 0;
396 __be32 rel_info = 0; 396 __be32 rel_info = 0;
397 __u32 n = 0; 397 __u32 n = 0;
398 u16 flags; 398 __be16 flags;
399 int grehlen = (iph->ihl<<2) + 4; 399 int grehlen = (iph->ihl<<2) + 4;
400 struct sk_buff *skb2; 400 struct sk_buff *skb2;
401 struct flowi fl; 401 struct flowi fl;
@@ -556,9 +556,9 @@ static int ipgre_rcv(struct sk_buff *skb)
556{ 556{
557 struct iphdr *iph; 557 struct iphdr *iph;
558 u8 *h; 558 u8 *h;
559 u16 flags; 559 __be16 flags;
560 u16 csum = 0; 560 __sum16 csum = 0;
561 u32 key = 0; 561 __be32 key = 0;
562 u32 seqno = 0; 562 u32 seqno = 0;
563 struct ip_tunnel *tunnel; 563 struct ip_tunnel *tunnel;
564 int offset = 4; 564 int offset = 4;
@@ -568,7 +568,7 @@ static int ipgre_rcv(struct sk_buff *skb)
568 568
569 iph = skb->nh.iph; 569 iph = skb->nh.iph;
570 h = skb->data; 570 h = skb->data;
571 flags = *(u16*)h; 571 flags = *(__be16*)h;
572 572
573 if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { 573 if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
574 /* - Version must be 0. 574 /* - Version must be 0.
@@ -580,7 +580,7 @@ static int ipgre_rcv(struct sk_buff *skb)
580 if (flags&GRE_CSUM) { 580 if (flags&GRE_CSUM) {
581 switch (skb->ip_summed) { 581 switch (skb->ip_summed) {
582 case CHECKSUM_COMPLETE: 582 case CHECKSUM_COMPLETE:
583 csum = (u16)csum_fold(skb->csum); 583 csum = csum_fold(skb->csum);
584 if (!csum) 584 if (!csum)
585 break; 585 break;
586 /* fall through */ 586 /* fall through */
@@ -592,11 +592,11 @@ static int ipgre_rcv(struct sk_buff *skb)
592 offset += 4; 592 offset += 4;
593 } 593 }
594 if (flags&GRE_KEY) { 594 if (flags&GRE_KEY) {
595 key = *(u32*)(h + offset); 595 key = *(__be32*)(h + offset);
596 offset += 4; 596 offset += 4;
597 } 597 }
598 if (flags&GRE_SEQ) { 598 if (flags&GRE_SEQ) {
599 seqno = ntohl(*(u32*)(h + offset)); 599 seqno = ntohl(*(__be32*)(h + offset));
600 offset += 4; 600 offset += 4;
601 } 601 }
602 } 602 }
@@ -605,7 +605,7 @@ static int ipgre_rcv(struct sk_buff *skb)
605 if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) { 605 if ((tunnel = ipgre_tunnel_lookup(iph->saddr, iph->daddr, key)) != NULL) {
606 secpath_reset(skb); 606 secpath_reset(skb);
607 607
608 skb->protocol = *(u16*)(h + 2); 608 skb->protocol = *(__be16*)(h + 2);
609 /* WCCP version 1 and 2 protocol decoding. 609 /* WCCP version 1 and 2 protocol decoding.
610 * - Change protocol to IP 610 * - Change protocol to IP
611 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header 611 * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
@@ -673,13 +673,13 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
673 struct iphdr *old_iph = skb->nh.iph; 673 struct iphdr *old_iph = skb->nh.iph;
674 struct iphdr *tiph; 674 struct iphdr *tiph;
675 u8 tos; 675 u8 tos;
676 u16 df; 676 __be16 df;
677 struct rtable *rt; /* Route to the other host */ 677 struct rtable *rt; /* Route to the other host */
678 struct net_device *tdev; /* Device to other host */ 678 struct net_device *tdev; /* Device to other host */
679 struct iphdr *iph; /* Our new IP header */ 679 struct iphdr *iph; /* Our new IP header */
680 int max_headroom; /* The extra header space needed */ 680 int max_headroom; /* The extra header space needed */
681 int gre_hlen; 681 int gre_hlen;
682 u32 dst; 682 __be32 dst;
683 int mtu; 683 int mtu;
684 684
685 if (tunnel->recursion++) { 685 if (tunnel->recursion++) {
@@ -860,11 +860,11 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
860 iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); 860 iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT);
861 } 861 }
862 862
863 ((u16*)(iph+1))[0] = tunnel->parms.o_flags; 863 ((__be16*)(iph+1))[0] = tunnel->parms.o_flags;
864 ((u16*)(iph+1))[1] = skb->protocol; 864 ((__be16*)(iph+1))[1] = skb->protocol;
865 865
866 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { 866 if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) {
867 u32 *ptr = (u32*)(((u8*)iph) + tunnel->hlen - 4); 867 __be32 *ptr = (__be32*)(((u8*)iph) + tunnel->hlen - 4);
868 868
869 if (tunnel->parms.o_flags&GRE_SEQ) { 869 if (tunnel->parms.o_flags&GRE_SEQ) {
870 ++tunnel->o_seqno; 870 ++tunnel->o_seqno;
@@ -877,7 +877,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
877 } 877 }
878 if (tunnel->parms.o_flags&GRE_CSUM) { 878 if (tunnel->parms.o_flags&GRE_CSUM) {
879 *ptr = 0; 879 *ptr = 0;
880 *(__u16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr)); 880 *(__sum16*)ptr = ip_compute_csum((void*)(iph+1), skb->len - sizeof(struct iphdr));
881 } 881 }
882 } 882 }
883 883
@@ -1068,7 +1068,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh
1068{ 1068{
1069 struct ip_tunnel *t = netdev_priv(dev); 1069 struct ip_tunnel *t = netdev_priv(dev);
1070 struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); 1070 struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
1071 u16 *p = (u16*)(iph+1); 1071 __be16 *p = (__be16*)(iph+1);
1072 1072
1073 memcpy(iph, &t->parms.iph, sizeof(struct iphdr)); 1073 memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
1074 p[0] = t->parms.o_flags; 1074 p[0] = t->parms.o_flags;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index fc195a44fc2e..1da3d32f8289 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -288,9 +288,8 @@ int ip_output(struct sk_buff *skb)
288 !(IPCB(skb)->flags & IPSKB_REROUTED)); 288 !(IPCB(skb)->flags & IPSKB_REROUTED));
289} 289}
290 290
291int ip_queue_xmit(struct sk_buff *skb, int ipfragok) 291int ip_queue_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok)
292{ 292{
293 struct sock *sk = skb->sk;
294 struct inet_sock *inet = inet_sk(sk); 293 struct inet_sock *inet = inet_sk(sk);
295 struct ip_options *opt = inet->opt; 294 struct ip_options *opt = inet->opt;
296 struct rtable *rt; 295 struct rtable *rt;
@@ -342,7 +341,7 @@ packet_routed:
342 341
343 /* OK, we know where to send it, allocate and build IP header. */ 342 /* OK, we know where to send it, allocate and build IP header. */
344 iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); 343 iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));
345 *((__u16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); 344 *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));
346 iph->tot_len = htons(skb->len); 345 iph->tot_len = htons(skb->len);
347 if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok) 346 if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)
348 iph->frag_off = htons(IP_DF); 347 iph->frag_off = htons(IP_DF);
@@ -386,6 +385,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
386 dst_release(to->dst); 385 dst_release(to->dst);
387 to->dst = dst_clone(from->dst); 386 to->dst = dst_clone(from->dst);
388 to->dev = from->dev; 387 to->dev = from->dev;
388 to->mark = from->mark;
389 389
390 /* Copy the flags to each fragment. */ 390 /* Copy the flags to each fragment. */
391 IPCB(to)->flags = IPCB(from)->flags; 391 IPCB(to)->flags = IPCB(from)->flags;
@@ -394,7 +394,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
394 to->tc_index = from->tc_index; 394 to->tc_index = from->tc_index;
395#endif 395#endif
396#ifdef CONFIG_NETFILTER 396#ifdef CONFIG_NETFILTER
397 to->nfmark = from->nfmark;
398 /* Connection association is same as pre-frag packet */ 397 /* Connection association is same as pre-frag packet */
399 nf_conntrack_put(to->nfct); 398 nf_conntrack_put(to->nfct);
400 to->nfct = from->nfct; 399 to->nfct = from->nfct;
@@ -683,7 +682,7 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
683 if (memcpy_fromiovecend(to, iov, offset, len) < 0) 682 if (memcpy_fromiovecend(to, iov, offset, len) < 0)
684 return -EFAULT; 683 return -EFAULT;
685 } else { 684 } else {
686 unsigned int csum = 0; 685 __wsum csum = 0;
687 if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0) 686 if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
688 return -EFAULT; 687 return -EFAULT;
689 skb->csum = csum_block_add(skb->csum, csum, odd); 688 skb->csum = csum_block_add(skb->csum, csum, odd);
@@ -691,11 +690,11 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk
691 return 0; 690 return 0;
692} 691}
693 692
694static inline unsigned int 693static inline __wsum
695csum_page(struct page *page, int offset, int copy) 694csum_page(struct page *page, int offset, int copy)
696{ 695{
697 char *kaddr; 696 char *kaddr;
698 unsigned int csum; 697 __wsum csum;
699 kaddr = kmap(page); 698 kaddr = kmap(page);
700 csum = csum_partial(kaddr + offset, copy, 0); 699 csum = csum_partial(kaddr + offset, copy, 0);
701 kunmap(page); 700 kunmap(page);
@@ -1167,7 +1166,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page,
1167 } 1166 }
1168 1167
1169 if (skb->ip_summed == CHECKSUM_NONE) { 1168 if (skb->ip_summed == CHECKSUM_NONE) {
1170 unsigned int csum; 1169 __wsum csum;
1171 csum = csum_page(page, offset, len); 1170 csum = csum_page(page, offset, len);
1172 skb->csum = csum_block_add(skb->csum, csum, skb->len); 1171 skb->csum = csum_block_add(skb->csum, csum, skb->len);
1173 } 1172 }
@@ -1315,7 +1314,7 @@ void ip_flush_pending_frames(struct sock *sk)
1315static int ip_reply_glue_bits(void *dptr, char *to, int offset, 1314static int ip_reply_glue_bits(void *dptr, char *to, int offset,
1316 int len, int odd, struct sk_buff *skb) 1315 int len, int odd, struct sk_buff *skb)
1317{ 1316{
1318 unsigned int csum; 1317 __wsum csum;
1319 1318
1320 csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0); 1319 csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);
1321 skb->csum = csum_block_add(skb->csum, csum, odd); 1320 skb->csum = csum_block_add(skb->csum, csum, odd);
@@ -1385,7 +1384,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
1385 &ipc, rt, MSG_DONTWAIT); 1384 &ipc, rt, MSG_DONTWAIT);
1386 if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { 1385 if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {
1387 if (arg->csumoffset >= 0) 1386 if (arg->csumoffset >= 0)
1388 *((u16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum)); 1387 *((__sum16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum));
1389 skb->ip_summed = CHECKSUM_NONE; 1388 skb->ip_summed = CHECKSUM_NONE;
1390 ip_push_pending_frames(sk); 1389 ip_push_pending_frames(sk);
1391 } 1390 }
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 4b132953bcc2..57d4bae6f080 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -355,7 +355,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
355 sin = (struct sockaddr_in *)msg->msg_name; 355 sin = (struct sockaddr_in *)msg->msg_name;
356 if (sin) { 356 if (sin) {
357 sin->sin_family = AF_INET; 357 sin->sin_family = AF_INET;
358 sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset); 358 sin->sin_addr.s_addr = *(__be32*)(skb->nh.raw + serr->addr_offset);
359 sin->sin_port = serr->port; 359 sin->sin_port = serr->port;
360 memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); 360 memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
361 } 361 }
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 955a07abb91d..afa60b9a003f 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -101,6 +101,7 @@
101#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers 101#define CONF_NAMESERVERS_MAX 3 /* Maximum number of nameservers
102 - '3' from resolv.h */ 102 - '3' from resolv.h */
103 103
104#define NONE __constant_htonl(INADDR_NONE)
104 105
105/* 106/*
106 * Public IP configuration 107 * Public IP configuration
@@ -129,19 +130,19 @@ int ic_proto_enabled __initdata = 0
129 130
130static int ic_host_name_set __initdata = 0; /* Host name set by us? */ 131static int ic_host_name_set __initdata = 0; /* Host name set by us? */
131 132
132u32 ic_myaddr = INADDR_NONE; /* My IP address */ 133__be32 ic_myaddr = NONE; /* My IP address */
133static u32 ic_netmask = INADDR_NONE; /* Netmask for local subnet */ 134static __be32 ic_netmask = NONE; /* Netmask for local subnet */
134u32 ic_gateway = INADDR_NONE; /* Gateway IP address */ 135__be32 ic_gateway = NONE; /* Gateway IP address */
135 136
136u32 ic_servaddr = INADDR_NONE; /* Boot server IP address */ 137__be32 ic_servaddr = NONE; /* Boot server IP address */
137 138
138u32 root_server_addr = INADDR_NONE; /* Address of NFS server */ 139__be32 root_server_addr = NONE; /* Address of NFS server */
139u8 root_server_path[256] = { 0, }; /* Path to mount as root */ 140u8 root_server_path[256] = { 0, }; /* Path to mount as root */
140 141
141/* Persistent data: */ 142/* Persistent data: */
142 143
143static int ic_proto_used; /* Protocol used, if any */ 144static int ic_proto_used; /* Protocol used, if any */
144static u32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ 145static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */
145static u8 ic_domain[64]; /* DNS (not NIS) domain name */ 146static u8 ic_domain[64]; /* DNS (not NIS) domain name */
146 147
147/* 148/*
@@ -172,7 +173,7 @@ struct ic_device {
172 struct net_device *dev; 173 struct net_device *dev;
173 unsigned short flags; 174 unsigned short flags;
174 short able; 175 short able;
175 u32 xid; 176 __be32 xid;
176}; 177};
177 178
178static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ 179static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
@@ -223,7 +224,7 @@ static int __init ic_open_devs(void)
223 d->flags = oflags; 224 d->flags = oflags;
224 d->able = able; 225 d->able = able;
225 if (able & IC_BOOTP) 226 if (able & IC_BOOTP)
226 get_random_bytes(&d->xid, sizeof(u32)); 227 get_random_bytes(&d->xid, sizeof(__be32));
227 else 228 else
228 d->xid = 0; 229 d->xid = 0;
229 ic_proto_have_if |= able; 230 ic_proto_have_if |= able;
@@ -269,7 +270,7 @@ static void __init ic_close_devs(void)
269 */ 270 */
270 271
271static inline void 272static inline void
272set_sockaddr(struct sockaddr_in *sin, u32 addr, u16 port) 273set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
273{ 274{
274 sin->sin_family = AF_INET; 275 sin->sin_family = AF_INET;
275 sin->sin_addr.s_addr = addr; 276 sin->sin_addr.s_addr = addr;
@@ -332,7 +333,7 @@ static int __init ic_setup_routes(void)
332{ 333{
333 /* No need to setup device routes, only the default route... */ 334 /* No need to setup device routes, only the default route... */
334 335
335 if (ic_gateway != INADDR_NONE) { 336 if (ic_gateway != NONE) {
336 struct rtentry rm; 337 struct rtentry rm;
337 int err; 338 int err;
338 339
@@ -368,10 +369,10 @@ static int __init ic_defaults(void)
368 if (!ic_host_name_set) 369 if (!ic_host_name_set)
369 sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr)); 370 sprintf(init_utsname()->nodename, "%u.%u.%u.%u", NIPQUAD(ic_myaddr));
370 371
371 if (root_server_addr == INADDR_NONE) 372 if (root_server_addr == NONE)
372 root_server_addr = ic_servaddr; 373 root_server_addr = ic_servaddr;
373 374
374 if (ic_netmask == INADDR_NONE) { 375 if (ic_netmask == NONE) {
375 if (IN_CLASSA(ntohl(ic_myaddr))) 376 if (IN_CLASSA(ntohl(ic_myaddr)))
376 ic_netmask = htonl(IN_CLASSA_NET); 377 ic_netmask = htonl(IN_CLASSA_NET);
377 else if (IN_CLASSB(ntohl(ic_myaddr))) 378 else if (IN_CLASSB(ntohl(ic_myaddr)))
@@ -420,7 +421,7 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
420{ 421{
421 struct arphdr *rarp; 422 struct arphdr *rarp;
422 unsigned char *rarp_ptr; 423 unsigned char *rarp_ptr;
423 u32 sip, tip; 424 __be32 sip, tip;
424 unsigned char *sha, *tha; /* s for "source", t for "target" */ 425 unsigned char *sha, *tha; /* s for "source", t for "target" */
425 struct ic_device *d; 426 struct ic_device *d;
426 427
@@ -485,12 +486,12 @@ ic_rarp_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
485 goto drop_unlock; 486 goto drop_unlock;
486 487
487 /* Discard packets which are not from specified server. */ 488 /* Discard packets which are not from specified server. */
488 if (ic_servaddr != INADDR_NONE && ic_servaddr != sip) 489 if (ic_servaddr != NONE && ic_servaddr != sip)
489 goto drop_unlock; 490 goto drop_unlock;
490 491
491 /* We have a winner! */ 492 /* We have a winner! */
492 ic_dev = dev; 493 ic_dev = dev;
493 if (ic_myaddr == INADDR_NONE) 494 if (ic_myaddr == NONE)
494 ic_myaddr = tip; 495 ic_myaddr = tip;
495 ic_servaddr = sip; 496 ic_servaddr = sip;
496 ic_got_reply = IC_RARP; 497 ic_got_reply = IC_RARP;
@@ -530,13 +531,13 @@ struct bootp_pkt { /* BOOTP packet format */
530 u8 htype; /* HW address type */ 531 u8 htype; /* HW address type */
531 u8 hlen; /* HW address length */ 532 u8 hlen; /* HW address length */
532 u8 hops; /* Used only by gateways */ 533 u8 hops; /* Used only by gateways */
533 u32 xid; /* Transaction ID */ 534 __be32 xid; /* Transaction ID */
534 u16 secs; /* Seconds since we started */ 535 __be16 secs; /* Seconds since we started */
535 u16 flags; /* Just what it says */ 536 __be16 flags; /* Just what it says */
536 u32 client_ip; /* Client's IP address if known */ 537 __be32 client_ip; /* Client's IP address if known */
537 u32 your_ip; /* Assigned IP address */ 538 __be32 your_ip; /* Assigned IP address */
538 u32 server_ip; /* (Next, e.g. NFS) Server's IP address */ 539 __be32 server_ip; /* (Next, e.g. NFS) Server's IP address */
539 u32 relay_ip; /* IP address of BOOTP relay */ 540 __be32 relay_ip; /* IP address of BOOTP relay */
540 u8 hw_addr[16]; /* Client's HW address */ 541 u8 hw_addr[16]; /* Client's HW address */
541 u8 serv_name[64]; /* Server host name */ 542 u8 serv_name[64]; /* Server host name */
542 u8 boot_file[128]; /* Name of boot file */ 543 u8 boot_file[128]; /* Name of boot file */
@@ -576,7 +577,7 @@ static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 };
576static void __init 577static void __init
577ic_dhcp_init_options(u8 *options) 578ic_dhcp_init_options(u8 *options)
578{ 579{
579 u8 mt = ((ic_servaddr == INADDR_NONE) 580 u8 mt = ((ic_servaddr == NONE)
580 ? DHCPDISCOVER : DHCPREQUEST); 581 ? DHCPDISCOVER : DHCPREQUEST);
581 u8 *e = options; 582 u8 *e = options;
582 583
@@ -666,7 +667,7 @@ static inline void ic_bootp_init(void)
666 int i; 667 int i;
667 668
668 for (i = 0; i < CONF_NAMESERVERS_MAX; i++) 669 for (i = 0; i < CONF_NAMESERVERS_MAX; i++)
669 ic_nameservers[i] = INADDR_NONE; 670 ic_nameservers[i] = NONE;
670 671
671 dev_add_pack(&bootp_packet_type); 672 dev_add_pack(&bootp_packet_type);
672} 673}
@@ -708,7 +709,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
708 h->frag_off = htons(IP_DF); 709 h->frag_off = htons(IP_DF);
709 h->ttl = 64; 710 h->ttl = 64;
710 h->protocol = IPPROTO_UDP; 711 h->protocol = IPPROTO_UDP;
711 h->daddr = INADDR_BROADCAST; 712 h->daddr = htonl(INADDR_BROADCAST);
712 h->check = ip_fast_csum((unsigned char *) h, h->ihl); 713 h->check = ip_fast_csum((unsigned char *) h, h->ihl);
713 714
714 /* Construct UDP header */ 715 /* Construct UDP header */
@@ -730,8 +731,8 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
730 b->htype = dev->type; /* can cause undefined behavior */ 731 b->htype = dev->type; /* can cause undefined behavior */
731 } 732 }
732 b->hlen = dev->addr_len; 733 b->hlen = dev->addr_len;
733 b->your_ip = INADDR_NONE; 734 b->your_ip = NONE;
734 b->server_ip = INADDR_NONE; 735 b->server_ip = NONE;
735 memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); 736 memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
736 b->secs = htons(jiffies_diff / HZ); 737 b->secs = htons(jiffies_diff / HZ);
737 b->xid = d->xid; 738 b->xid = d->xid;
@@ -788,11 +789,11 @@ static void __init ic_do_bootp_ext(u8 *ext)
788 789
789 switch (*ext++) { 790 switch (*ext++) {
790 case 1: /* Subnet mask */ 791 case 1: /* Subnet mask */
791 if (ic_netmask == INADDR_NONE) 792 if (ic_netmask == NONE)
792 memcpy(&ic_netmask, ext+1, 4); 793 memcpy(&ic_netmask, ext+1, 4);
793 break; 794 break;
794 case 3: /* Default gateway */ 795 case 3: /* Default gateway */
795 if (ic_gateway == INADDR_NONE) 796 if (ic_gateway == NONE)
796 memcpy(&ic_gateway, ext+1, 4); 797 memcpy(&ic_gateway, ext+1, 4);
797 break; 798 break;
798 case 6: /* DNS server */ 799 case 6: /* DNS server */
@@ -800,7 +801,7 @@ static void __init ic_do_bootp_ext(u8 *ext)
800 if (servers > CONF_NAMESERVERS_MAX) 801 if (servers > CONF_NAMESERVERS_MAX)
801 servers = CONF_NAMESERVERS_MAX; 802 servers = CONF_NAMESERVERS_MAX;
802 for (i = 0; i < servers; i++) { 803 for (i = 0; i < servers; i++) {
803 if (ic_nameservers[i] == INADDR_NONE) 804 if (ic_nameservers[i] == NONE)
804 memcpy(&ic_nameservers[i], ext+1+4*i, 4); 805 memcpy(&ic_nameservers[i], ext+1+4*i, 4);
805 } 806 }
806 break; 807 break;
@@ -917,7 +918,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
917 918
918#ifdef IPCONFIG_DHCP 919#ifdef IPCONFIG_DHCP
919 if (ic_proto_enabled & IC_USE_DHCP) { 920 if (ic_proto_enabled & IC_USE_DHCP) {
920 u32 server_id = INADDR_NONE; 921 __be32 server_id = NONE;
921 int mt = 0; 922 int mt = 0;
922 923
923 ext = &b->exten[4]; 924 ext = &b->exten[4];
@@ -949,7 +950,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
949 /* While in the process of accepting one offer, 950 /* While in the process of accepting one offer,
950 * ignore all others. 951 * ignore all others.
951 */ 952 */
952 if (ic_myaddr != INADDR_NONE) 953 if (ic_myaddr != NONE)
953 goto drop_unlock; 954 goto drop_unlock;
954 955
955 /* Let's accept that offer. */ 956 /* Let's accept that offer. */
@@ -965,7 +966,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
965 * precedence over the bootp header one if 966 * precedence over the bootp header one if
966 * they are different. 967 * they are different.
967 */ 968 */
968 if ((server_id != INADDR_NONE) && 969 if ((server_id != NONE) &&
969 (b->server_ip != server_id)) 970 (b->server_ip != server_id))
970 b->server_ip = ic_servaddr; 971 b->server_ip = ic_servaddr;
971 break; 972 break;
@@ -979,8 +980,8 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
979 980
980 default: 981 default:
981 /* Urque. Forget it*/ 982 /* Urque. Forget it*/
982 ic_myaddr = INADDR_NONE; 983 ic_myaddr = NONE;
983 ic_servaddr = INADDR_NONE; 984 ic_servaddr = NONE;
984 goto drop_unlock; 985 goto drop_unlock;
985 }; 986 };
986 987
@@ -1004,9 +1005,9 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
1004 ic_dev = dev; 1005 ic_dev = dev;
1005 ic_myaddr = b->your_ip; 1006 ic_myaddr = b->your_ip;
1006 ic_servaddr = b->server_ip; 1007 ic_servaddr = b->server_ip;
1007 if (ic_gateway == INADDR_NONE && b->relay_ip) 1008 if (ic_gateway == NONE && b->relay_ip)
1008 ic_gateway = b->relay_ip; 1009 ic_gateway = b->relay_ip;
1009 if (ic_nameservers[0] == INADDR_NONE) 1010 if (ic_nameservers[0] == NONE)
1010 ic_nameservers[0] = ic_servaddr; 1011 ic_nameservers[0] = ic_servaddr;
1011 ic_got_reply = IC_BOOTP; 1012 ic_got_reply = IC_BOOTP;
1012 1013
@@ -1150,7 +1151,7 @@ static int __init ic_dynamic(void)
1150#endif 1151#endif
1151 1152
1152 if (!ic_got_reply) { 1153 if (!ic_got_reply) {
1153 ic_myaddr = INADDR_NONE; 1154 ic_myaddr = NONE;
1154 return -1; 1155 return -1;
1155 } 1156 }
1156 1157
@@ -1182,12 +1183,12 @@ static int pnp_seq_show(struct seq_file *seq, void *v)
1182 seq_printf(seq, 1183 seq_printf(seq,
1183 "domain %s\n", ic_domain); 1184 "domain %s\n", ic_domain);
1184 for (i = 0; i < CONF_NAMESERVERS_MAX; i++) { 1185 for (i = 0; i < CONF_NAMESERVERS_MAX; i++) {
1185 if (ic_nameservers[i] != INADDR_NONE) 1186 if (ic_nameservers[i] != NONE)
1186 seq_printf(seq, 1187 seq_printf(seq,
1187 "nameserver %u.%u.%u.%u\n", 1188 "nameserver %u.%u.%u.%u\n",
1188 NIPQUAD(ic_nameservers[i])); 1189 NIPQUAD(ic_nameservers[i]));
1189 } 1190 }
1190 if (ic_servaddr != INADDR_NONE) 1191 if (ic_servaddr != NONE)
1191 seq_printf(seq, 1192 seq_printf(seq,
1192 "bootserver %u.%u.%u.%u\n", 1193 "bootserver %u.%u.%u.%u\n",
1193 NIPQUAD(ic_servaddr)); 1194 NIPQUAD(ic_servaddr));
@@ -1213,9 +1214,9 @@ static struct file_operations pnp_seq_fops = {
1213 * need to have root_server_addr set _before_ IPConfig gets called as it 1214 * need to have root_server_addr set _before_ IPConfig gets called as it
1214 * can override it. 1215 * can override it.
1215 */ 1216 */
1216u32 __init root_nfs_parse_addr(char *name) 1217__be32 __init root_nfs_parse_addr(char *name)
1217{ 1218{
1218 u32 addr; 1219 __be32 addr;
1219 int octets = 0; 1220 int octets = 0;
1220 char *cp, *cq; 1221 char *cp, *cq;
1221 1222
@@ -1237,7 +1238,7 @@ u32 __init root_nfs_parse_addr(char *name)
1237 addr = in_aton(name); 1238 addr = in_aton(name);
1238 memmove(name, cp, strlen(cp) + 1); 1239 memmove(name, cp, strlen(cp) + 1);
1239 } else 1240 } else
1240 addr = INADDR_NONE; 1241 addr = NONE;
1241 1242
1242 return addr; 1243 return addr;
1243} 1244}
@@ -1248,7 +1249,7 @@ u32 __init root_nfs_parse_addr(char *name)
1248 1249
1249static int __init ip_auto_config(void) 1250static int __init ip_auto_config(void)
1250{ 1251{
1251 u32 addr; 1252 __be32 addr;
1252 1253
1253#ifdef CONFIG_PROC_FS 1254#ifdef CONFIG_PROC_FS
1254 proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops); 1255 proc_net_fops_create("pnp", S_IRUGO, &pnp_seq_fops);
@@ -1277,11 +1278,11 @@ static int __init ip_auto_config(void)
1277 * interfaces and no default was set), use BOOTP or RARP to get the 1278 * interfaces and no default was set), use BOOTP or RARP to get the
1278 * missing values. 1279 * missing values.
1279 */ 1280 */
1280 if (ic_myaddr == INADDR_NONE || 1281 if (ic_myaddr == NONE ||
1281#ifdef CONFIG_ROOT_NFS 1282#ifdef CONFIG_ROOT_NFS
1282 (MAJOR(ROOT_DEV) == UNNAMED_MAJOR 1283 (MAJOR(ROOT_DEV) == UNNAMED_MAJOR
1283 && root_server_addr == INADDR_NONE 1284 && root_server_addr == NONE
1284 && ic_servaddr == INADDR_NONE) || 1285 && ic_servaddr == NONE) ||
1285#endif 1286#endif
1286 ic_first_dev->next) { 1287 ic_first_dev->next) {
1287#ifdef IPCONFIG_DYNAMIC 1288#ifdef IPCONFIG_DYNAMIC
@@ -1334,7 +1335,7 @@ static int __init ip_auto_config(void)
1334 } 1335 }
1335 1336
1336 addr = root_nfs_parse_addr(root_server_path); 1337 addr = root_nfs_parse_addr(root_server_path);
1337 if (root_server_addr == INADDR_NONE) 1338 if (root_server_addr == NONE)
1338 root_server_addr = addr; 1339 root_server_addr = addr;
1339 1340
1340 /* 1341 /*
@@ -1461,19 +1462,19 @@ static int __init ip_auto_config_setup(char *addrs)
1461 switch (num) { 1462 switch (num) {
1462 case 0: 1463 case 0:
1463 if ((ic_myaddr = in_aton(ip)) == INADDR_ANY) 1464 if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
1464 ic_myaddr = INADDR_NONE; 1465 ic_myaddr = NONE;
1465 break; 1466 break;
1466 case 1: 1467 case 1:
1467 if ((ic_servaddr = in_aton(ip)) == INADDR_ANY) 1468 if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
1468 ic_servaddr = INADDR_NONE; 1469 ic_servaddr = NONE;
1469 break; 1470 break;
1470 case 2: 1471 case 2:
1471 if ((ic_gateway = in_aton(ip)) == INADDR_ANY) 1472 if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
1472 ic_gateway = INADDR_NONE; 1473 ic_gateway = NONE;
1473 break; 1474 break;
1474 case 3: 1475 case 3:
1475 if ((ic_netmask = in_aton(ip)) == INADDR_ANY) 1476 if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
1476 ic_netmask = INADDR_NONE; 1477 ic_netmask = NONE;
1477 break; 1478 break;
1478 case 4: 1479 case 4:
1479 if ((dp = strchr(ip, '.'))) { 1480 if ((dp = strchr(ip, '.'))) {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 0c4556529228..9d719d664e5b 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -118,7 +118,7 @@
118#include <net/xfrm.h> 118#include <net/xfrm.h>
119 119
120#define HASH_SIZE 16 120#define HASH_SIZE 16
121#define HASH(addr) ((addr^(addr>>4))&0xF) 121#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
122 122
123static int ipip_fb_tunnel_init(struct net_device *dev); 123static int ipip_fb_tunnel_init(struct net_device *dev);
124static int ipip_tunnel_init(struct net_device *dev); 124static int ipip_tunnel_init(struct net_device *dev);
@@ -134,7 +134,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne
134 134
135static DEFINE_RWLOCK(ipip_lock); 135static DEFINE_RWLOCK(ipip_lock);
136 136
137static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local) 137static struct ip_tunnel * ipip_tunnel_lookup(__be32 remote, __be32 local)
138{ 138{
139 unsigned h0 = HASH(remote); 139 unsigned h0 = HASH(remote);
140 unsigned h1 = HASH(local); 140 unsigned h1 = HASH(local);
@@ -160,8 +160,8 @@ static struct ip_tunnel * ipip_tunnel_lookup(u32 remote, u32 local)
160 160
161static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t) 161static struct ip_tunnel **ipip_bucket(struct ip_tunnel *t)
162{ 162{
163 u32 remote = t->parms.iph.daddr; 163 __be32 remote = t->parms.iph.daddr;
164 u32 local = t->parms.iph.saddr; 164 __be32 local = t->parms.iph.saddr;
165 unsigned h = 0; 165 unsigned h = 0;
166 int prio = 0; 166 int prio = 0;
167 167
@@ -203,8 +203,8 @@ static void ipip_tunnel_link(struct ip_tunnel *t)
203 203
204static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) 204static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create)
205{ 205{
206 u32 remote = parms->iph.daddr; 206 __be32 remote = parms->iph.daddr;
207 u32 local = parms->iph.saddr; 207 __be32 local = parms->iph.saddr;
208 struct ip_tunnel *t, **tp, *nt; 208 struct ip_tunnel *t, **tp, *nt;
209 struct net_device *dev; 209 struct net_device *dev;
210 unsigned h = 0; 210 unsigned h = 0;
@@ -519,13 +519,13 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
519 struct net_device_stats *stats = &tunnel->stat; 519 struct net_device_stats *stats = &tunnel->stat;
520 struct iphdr *tiph = &tunnel->parms.iph; 520 struct iphdr *tiph = &tunnel->parms.iph;
521 u8 tos = tunnel->parms.iph.tos; 521 u8 tos = tunnel->parms.iph.tos;
522 u16 df = tiph->frag_off; 522 __be16 df = tiph->frag_off;
523 struct rtable *rt; /* Route to the other host */ 523 struct rtable *rt; /* Route to the other host */
524 struct net_device *tdev; /* Device to other host */ 524 struct net_device *tdev; /* Device to other host */
525 struct iphdr *old_iph = skb->nh.iph; 525 struct iphdr *old_iph = skb->nh.iph;
526 struct iphdr *iph; /* Our new IP header */ 526 struct iphdr *iph; /* Our new IP header */
527 int max_headroom; /* The extra header space needed */ 527 int max_headroom; /* The extra header space needed */
528 u32 dst = tiph->daddr; 528 __be32 dst = tiph->daddr;
529 int mtu; 529 int mtu;
530 530
531 if (tunnel->recursion++) { 531 if (tunnel->recursion++) {
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 97cfa97c8abb..efcf45ecc818 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1493,7 +1493,7 @@ static int pim_rcv(struct sk_buff * skb)
1493 if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) || 1493 if (pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
1494 (pim->flags&PIM_NULL_REGISTER) || 1494 (pim->flags&PIM_NULL_REGISTER) ||
1495 (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 && 1495 (ip_compute_csum((void *)pim, sizeof(*pim)) != 0 &&
1496 (u16)csum_fold(skb_checksum(skb, 0, skb->len, 0)))) 1496 csum_fold(skb_checksum(skb, 0, skb->len, 0))))
1497 goto drop; 1497 goto drop;
1498 1498
1499 /* check if the inner packet is destined to mcast group */ 1499 /* check if the inner packet is destined to mcast group */
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c
index e7752334d296..6c40899aa161 100644
--- a/net/ipv4/ipvs/ip_vs_app.c
+++ b/net/ipv4/ipvs/ip_vs_app.c
@@ -80,10 +80,9 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port)
80 if (!pp->unregister_app) 80 if (!pp->unregister_app)
81 return -EOPNOTSUPP; 81 return -EOPNOTSUPP;
82 82
83 inc = kmalloc(sizeof(struct ip_vs_app), GFP_KERNEL); 83 inc = kmemdup(app, sizeof(*inc), GFP_KERNEL);
84 if (!inc) 84 if (!inc)
85 return -ENOMEM; 85 return -ENOMEM;
86 memcpy(inc, app, sizeof(*inc));
87 INIT_LIST_HEAD(&inc->p_list); 86 INIT_LIST_HEAD(&inc->p_list);
88 INIT_LIST_HEAD(&inc->incs_list); 87 INIT_LIST_HEAD(&inc->incs_list);
89 inc->app = app; 88 inc->app = app;
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
index 1445bb47fea4..34257520a3a6 100644
--- a/net/ipv4/ipvs/ip_vs_core.c
+++ b/net/ipv4/ipvs/ip_vs_core.c
@@ -536,9 +536,9 @@ static unsigned int ip_vs_post_routing(unsigned int hooknum,
536 return NF_STOP; 536 return NF_STOP;
537} 537}
538 538
539u16 ip_vs_checksum_complete(struct sk_buff *skb, int offset) 539__sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
540{ 540{
541 return (u16) csum_fold(skb_checksum(skb, offset, skb->len - offset, 0)); 541 return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
542} 542}
543 543
544static inline struct sk_buff * 544static inline struct sk_buff *
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
index c4528b5c800d..e844ddb82b9a 100644
--- a/net/ipv4/ipvs/ip_vs_proto.c
+++ b/net/ipv4/ipvs/ip_vs_proto.c
@@ -118,13 +118,7 @@ void ip_vs_protocol_timeout_change(int flags)
118int * 118int *
119ip_vs_create_timeout_table(int *table, int size) 119ip_vs_create_timeout_table(int *table, int size)
120{ 120{
121 int *t; 121 return kmemdup(table, size, GFP_ATOMIC);
122
123 t = kmalloc(size, GFP_ATOMIC);
124 if (t == NULL)
125 return NULL;
126 memcpy(t, table, size);
127 return t;
128} 122}
129 123
130 124
diff --git a/net/ipv4/ipvs/ip_vs_proto_tcp.c b/net/ipv4/ipvs/ip_vs_proto_tcp.c
index 6ff05c3a32e6..16a9ebee2fe6 100644
--- a/net/ipv4/ipvs/ip_vs_proto_tcp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_tcp.c
@@ -84,7 +84,7 @@ tcp_conn_schedule(struct sk_buff *skb,
84 } 84 }
85 85
86 if (th->syn && 86 if (th->syn &&
87 (svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, 87 (svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
88 skb->nh.iph->daddr, th->dest))) { 88 skb->nh.iph->daddr, th->dest))) {
89 if (ip_vs_todrop()) { 89 if (ip_vs_todrop()) {
90 /* 90 /*
@@ -116,9 +116,9 @@ tcp_fast_csum_update(struct tcphdr *tcph, __be32 oldip, __be32 newip,
116 __be16 oldport, __be16 newport) 116 __be16 oldport, __be16 newport)
117{ 117{
118 tcph->check = 118 tcph->check =
119 ip_vs_check_diff(~oldip, newip, 119 csum_fold(ip_vs_check_diff4(oldip, newip,
120 ip_vs_check_diff(oldport ^ htons(0xFFFF), 120 ip_vs_check_diff2(oldport, newport,
121 newport, tcph->check)); 121 ~csum_unfold(tcph->check))));
122} 122}
123 123
124 124
@@ -490,16 +490,18 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
490static struct list_head tcp_apps[TCP_APP_TAB_SIZE]; 490static struct list_head tcp_apps[TCP_APP_TAB_SIZE];
491static DEFINE_SPINLOCK(tcp_app_lock); 491static DEFINE_SPINLOCK(tcp_app_lock);
492 492
493static inline __u16 tcp_app_hashkey(__u16 port) 493static inline __u16 tcp_app_hashkey(__be16 port)
494{ 494{
495 return ((port >> TCP_APP_TAB_BITS) ^ port) & TCP_APP_TAB_MASK; 495 return (((__force u16)port >> TCP_APP_TAB_BITS) ^ (__force u16)port)
496 & TCP_APP_TAB_MASK;
496} 497}
497 498
498 499
499static int tcp_register_app(struct ip_vs_app *inc) 500static int tcp_register_app(struct ip_vs_app *inc)
500{ 501{
501 struct ip_vs_app *i; 502 struct ip_vs_app *i;
502 __u16 hash, port = inc->port; 503 __u16 hash;
504 __be16 port = inc->port;
503 int ret = 0; 505 int ret = 0;
504 506
505 hash = tcp_app_hashkey(port); 507 hash = tcp_app_hashkey(port);
diff --git a/net/ipv4/ipvs/ip_vs_proto_udp.c b/net/ipv4/ipvs/ip_vs_proto_udp.c
index 691c8b637b29..03f0a414cfa4 100644
--- a/net/ipv4/ipvs/ip_vs_proto_udp.c
+++ b/net/ipv4/ipvs/ip_vs_proto_udp.c
@@ -89,7 +89,7 @@ udp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
89 return 0; 89 return 0;
90 } 90 }
91 91
92 if ((svc = ip_vs_service_get(skb->nfmark, skb->nh.iph->protocol, 92 if ((svc = ip_vs_service_get(skb->mark, skb->nh.iph->protocol,
93 skb->nh.iph->daddr, uh->dest))) { 93 skb->nh.iph->daddr, uh->dest))) {
94 if (ip_vs_todrop()) { 94 if (ip_vs_todrop()) {
95 /* 95 /*
@@ -121,11 +121,11 @@ udp_fast_csum_update(struct udphdr *uhdr, __be32 oldip, __be32 newip,
121 __be16 oldport, __be16 newport) 121 __be16 oldport, __be16 newport)
122{ 122{
123 uhdr->check = 123 uhdr->check =
124 ip_vs_check_diff(~oldip, newip, 124 csum_fold(ip_vs_check_diff4(oldip, newip,
125 ip_vs_check_diff(oldport ^ htons(0xFFFF), 125 ip_vs_check_diff2(oldport, newport,
126 newport, uhdr->check)); 126 ~csum_unfold(uhdr->check))));
127 if (!uhdr->check) 127 if (!uhdr->check)
128 uhdr->check = -1; 128 uhdr->check = CSUM_MANGLED_0;
129} 129}
130 130
131static int 131static int
@@ -173,7 +173,7 @@ udp_snat_handler(struct sk_buff **pskb,
173 cp->protocol, 173 cp->protocol,
174 (*pskb)->csum); 174 (*pskb)->csum);
175 if (udph->check == 0) 175 if (udph->check == 0)
176 udph->check = -1; 176 udph->check = CSUM_MANGLED_0;
177 IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n", 177 IP_VS_DBG(11, "O-pkt: %s O-csum=%d (+%zd)\n",
178 pp->name, udph->check, 178 pp->name, udph->check,
179 (char*)&(udph->check) - (char*)udph); 179 (char*)&(udph->check) - (char*)udph);
@@ -228,7 +228,7 @@ udp_dnat_handler(struct sk_buff **pskb,
228 cp->protocol, 228 cp->protocol,
229 (*pskb)->csum); 229 (*pskb)->csum);
230 if (udph->check == 0) 230 if (udph->check == 0)
231 udph->check = -1; 231 udph->check = CSUM_MANGLED_0;
232 (*pskb)->ip_summed = CHECKSUM_UNNECESSARY; 232 (*pskb)->ip_summed = CHECKSUM_UNNECESSARY;
233 } 233 }
234 return 1; 234 return 1;
@@ -282,16 +282,18 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
282static struct list_head udp_apps[UDP_APP_TAB_SIZE]; 282static struct list_head udp_apps[UDP_APP_TAB_SIZE];
283static DEFINE_SPINLOCK(udp_app_lock); 283static DEFINE_SPINLOCK(udp_app_lock);
284 284
285static inline __u16 udp_app_hashkey(__u16 port) 285static inline __u16 udp_app_hashkey(__be16 port)
286{ 286{
287 return ((port >> UDP_APP_TAB_BITS) ^ port) & UDP_APP_TAB_MASK; 287 return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port)
288 & UDP_APP_TAB_MASK;
288} 289}
289 290
290 291
291static int udp_register_app(struct ip_vs_app *inc) 292static int udp_register_app(struct ip_vs_app *inc)
292{ 293{
293 struct ip_vs_app *i; 294 struct ip_vs_app *i;
294 __u16 hash, port = inc->port; 295 __u16 hash;
296 __be16 port = inc->port;
295 int ret = 0; 297 int ret = 0;
296 298
297 hash = udp_app_hashkey(port); 299 hash = udp_app_hashkey(port);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index e2005c6810a4..a68966059b50 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -27,9 +27,7 @@ int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
27 fl.nl_u.ip4_u.saddr = iph->saddr; 27 fl.nl_u.ip4_u.saddr = iph->saddr;
28 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); 28 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
29 fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0; 29 fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
30#ifdef CONFIG_IP_ROUTE_FWMARK 30 fl.mark = (*pskb)->mark;
31 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
32#endif
33 if (ip_route_output_key(&rt, &fl) != 0) 31 if (ip_route_output_key(&rt, &fl) != 0)
34 return -1; 32 return -1;
35 33
@@ -164,17 +162,17 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
164 return 0; 162 return 0;
165} 163}
166 164
167unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, 165__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
168 unsigned int dataoff, u_int8_t protocol) 166 unsigned int dataoff, u_int8_t protocol)
169{ 167{
170 struct iphdr *iph = skb->nh.iph; 168 struct iphdr *iph = skb->nh.iph;
171 unsigned int csum = 0; 169 __sum16 csum = 0;
172 170
173 switch (skb->ip_summed) { 171 switch (skb->ip_summed) {
174 case CHECKSUM_COMPLETE: 172 case CHECKSUM_COMPLETE:
175 if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) 173 if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN)
176 break; 174 break;
177 if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || 175 if ((protocol == 0 && !csum_fold(skb->csum)) ||
178 !csum_tcpudp_magic(iph->saddr, iph->daddr, 176 !csum_tcpudp_magic(iph->saddr, iph->daddr,
179 skb->len - dataoff, protocol, 177 skb->len - dataoff, protocol,
180 skb->csum)) { 178 skb->csum)) {
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d88c292f118c..363df9976c9d 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -6,7 +6,7 @@ menu "IP: Netfilter Configuration"
6 depends on INET && NETFILTER 6 depends on INET && NETFILTER
7 7
8config NF_CONNTRACK_IPV4 8config NF_CONNTRACK_IPV4
9 tristate "IPv4 support for new connection tracking (EXPERIMENTAL)" 9 tristate "IPv4 connection tracking support (required for NAT) (EXPERIMENTAL)"
10 depends on EXPERIMENTAL && NF_CONNTRACK 10 depends on EXPERIMENTAL && NF_CONNTRACK
11 ---help--- 11 ---help---
12 Connection tracking keeps a record of what packets have passed 12 Connection tracking keeps a record of what packets have passed
@@ -19,21 +19,18 @@ config NF_CONNTRACK_IPV4
19 19
20 To compile it as a module, choose M here. If unsure, say N. 20 To compile it as a module, choose M here. If unsure, say N.
21 21
22# connection tracking, helpers and protocols 22config NF_CONNTRACK_PROC_COMPAT
23config IP_NF_CONNTRACK 23 bool "proc/sysctl compatibility with old connection tracking"
24 tristate "Connection tracking (required for masq/NAT)" 24 depends on NF_CONNTRACK_IPV4
25 ---help--- 25 default y
26 Connection tracking keeps a record of what packets have passed 26 help
27 through your machine, in order to figure out how they are related 27 This option enables /proc and sysctl compatibility with the old
28 into connections. 28 layer 3 dependant connection tracking. This is needed to keep
29 29 old programs that have not been adapted to the new names working.
30 This is required to do Masquerading or other kinds of Network
31 Address Translation (except for Fast NAT). It can also be used to
32 enhance packet filtering (see `Connection state match support'
33 below).
34 30
35 To compile it as a module, choose M here. If unsure, say N. 31 If unsure, say Y.
36 32
33# connection tracking, helpers and protocols
37config IP_NF_CT_ACCT 34config IP_NF_CT_ACCT
38 bool "Connection tracking flow accounting" 35 bool "Connection tracking flow accounting"
39 depends on IP_NF_CONNTRACK 36 depends on IP_NF_CONNTRACK
@@ -315,20 +312,6 @@ config IP_NF_MATCH_ADDRTYPE
315 If you want to compile it as a module, say M here and read 312 If you want to compile it as a module, say M here and read
316 <file:Documentation/modules.txt>. If unsure, say `N'. 313 <file:Documentation/modules.txt>. If unsure, say `N'.
317 314
318config IP_NF_MATCH_HASHLIMIT
319 tristate 'hashlimit match support'
320 depends on IP_NF_IPTABLES
321 help
322 This option adds a new iptables `hashlimit' match.
323
324 As opposed to `limit', this match dynamically creates a hash table
325 of limit buckets, based on your selection of source/destination
326 ip addresses and/or ports.
327
328 It enables you to express policies like `10kpps for any given
329 destination IP' or `500pps from any given source IP' with a single
330 IPtables rule.
331
332# `filter', generic and specific targets 315# `filter', generic and specific targets
333config IP_NF_FILTER 316config IP_NF_FILTER
334 tristate "Packet filtering" 317 tristate "Packet filtering"
@@ -404,7 +387,7 @@ config IP_NF_TARGET_TCPMSS
404 387
405 To compile it as a module, choose M here. If unsure, say N. 388 To compile it as a module, choose M here. If unsure, say N.
406 389
407# NAT + specific targets 390# NAT + specific targets: ip_conntrack
408config IP_NF_NAT 391config IP_NF_NAT
409 tristate "Full NAT" 392 tristate "Full NAT"
410 depends on IP_NF_IPTABLES && IP_NF_CONNTRACK 393 depends on IP_NF_IPTABLES && IP_NF_CONNTRACK
@@ -415,14 +398,30 @@ config IP_NF_NAT
415 398
416 To compile it as a module, choose M here. If unsure, say N. 399 To compile it as a module, choose M here. If unsure, say N.
417 400
401# NAT + specific targets: nf_conntrack
402config NF_NAT
403 tristate "Full NAT"
404 depends on IP_NF_IPTABLES && NF_CONNTRACK
405 help
406 The Full NAT option allows masquerading, port forwarding and other
407 forms of full Network Address Port Translation. It is controlled by
408 the `nat' table in iptables: see the man page for iptables(8).
409
410 To compile it as a module, choose M here. If unsure, say N.
411
418config IP_NF_NAT_NEEDED 412config IP_NF_NAT_NEEDED
419 bool 413 bool
420 depends on IP_NF_NAT != n 414 depends on IP_NF_NAT
415 default y
416
417config NF_NAT_NEEDED
418 bool
419 depends on NF_NAT
421 default y 420 default y
422 421
423config IP_NF_TARGET_MASQUERADE 422config IP_NF_TARGET_MASQUERADE
424 tristate "MASQUERADE target support" 423 tristate "MASQUERADE target support"
425 depends on IP_NF_NAT 424 depends on (NF_NAT || IP_NF_NAT)
426 help 425 help
427 Masquerading is a special case of NAT: all outgoing connections are 426 Masquerading is a special case of NAT: all outgoing connections are
428 changed to seem to come from a particular interface's address, and 427 changed to seem to come from a particular interface's address, and
@@ -434,7 +433,7 @@ config IP_NF_TARGET_MASQUERADE
434 433
435config IP_NF_TARGET_REDIRECT 434config IP_NF_TARGET_REDIRECT
436 tristate "REDIRECT target support" 435 tristate "REDIRECT target support"
437 depends on IP_NF_NAT 436 depends on (NF_NAT || IP_NF_NAT)
438 help 437 help
439 REDIRECT is a special case of NAT: all incoming connections are 438 REDIRECT is a special case of NAT: all incoming connections are
440 mapped onto the incoming interface's address, causing the packets to 439 mapped onto the incoming interface's address, causing the packets to
@@ -445,7 +444,7 @@ config IP_NF_TARGET_REDIRECT
445 444
446config IP_NF_TARGET_NETMAP 445config IP_NF_TARGET_NETMAP
447 tristate "NETMAP target support" 446 tristate "NETMAP target support"
448 depends on IP_NF_NAT 447 depends on (NF_NAT || IP_NF_NAT)
449 help 448 help
450 NETMAP is an implementation of static 1:1 NAT mapping of network 449 NETMAP is an implementation of static 1:1 NAT mapping of network
451 addresses. It maps the network address part, while keeping the host 450 addresses. It maps the network address part, while keeping the host
@@ -456,7 +455,7 @@ config IP_NF_TARGET_NETMAP
456 455
457config IP_NF_TARGET_SAME 456config IP_NF_TARGET_SAME
458 tristate "SAME target support" 457 tristate "SAME target support"
459 depends on IP_NF_NAT 458 depends on (NF_NAT || IP_NF_NAT)
460 help 459 help
461 This option adds a `SAME' target, which works like the standard SNAT 460 This option adds a `SAME' target, which works like the standard SNAT
462 target, but attempts to give clients the same IP for all connections. 461 target, but attempts to give clients the same IP for all connections.
@@ -478,19 +477,52 @@ config IP_NF_NAT_SNMP_BASIC
478 477
479 To compile it as a module, choose M here. If unsure, say N. 478 To compile it as a module, choose M here. If unsure, say N.
480 479
480config NF_NAT_SNMP_BASIC
481 tristate "Basic SNMP-ALG support (EXPERIMENTAL)"
482 depends on EXPERIMENTAL && NF_NAT
483 ---help---
484
485 This module implements an Application Layer Gateway (ALG) for
486 SNMP payloads. In conjunction with NAT, it allows a network
487 management system to access multiple private networks with
488 conflicting addresses. It works by modifying IP addresses
489 inside SNMP payloads to match IP-layer NAT mapping.
490
491 This is the "basic" form of SNMP-ALG, as described in RFC 2962
492
493 To compile it as a module, choose M here. If unsure, say N.
494
495# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
496# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.
497# From kconfig-language.txt:
498#
499# <expr> '&&' <expr> (6)
500#
501# (6) Returns the result of min(/expr/, /expr/).
502config NF_NAT_PROTO_GRE
503 tristate
504 depends on NF_NAT && NF_CT_PROTO_GRE
505
506config IP_NF_NAT_FTP
507 tristate
508 depends on IP_NF_IPTABLES && IP_NF_CONNTRACK && IP_NF_NAT
509 default IP_NF_NAT && IP_NF_FTP
510
511config NF_NAT_FTP
512 tristate
513 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
514 default NF_NAT && NF_CONNTRACK_FTP
515
481config IP_NF_NAT_IRC 516config IP_NF_NAT_IRC
482 tristate 517 tristate
483 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 518 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
484 default IP_NF_NAT if IP_NF_IRC=y 519 default IP_NF_NAT if IP_NF_IRC=y
485 default m if IP_NF_IRC=m 520 default m if IP_NF_IRC=m
486 521
487# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), 522config NF_NAT_IRC
488# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. Argh.
489config IP_NF_NAT_FTP
490 tristate 523 tristate
491 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 524 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
492 default IP_NF_NAT if IP_NF_FTP=y 525 default NF_NAT && NF_CONNTRACK_IRC
493 default m if IP_NF_FTP=m
494 526
495config IP_NF_NAT_TFTP 527config IP_NF_NAT_TFTP
496 tristate 528 tristate
@@ -498,30 +530,56 @@ config IP_NF_NAT_TFTP
498 default IP_NF_NAT if IP_NF_TFTP=y 530 default IP_NF_NAT if IP_NF_TFTP=y
499 default m if IP_NF_TFTP=m 531 default m if IP_NF_TFTP=m
500 532
533config NF_NAT_TFTP
534 tristate
535 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
536 default NF_NAT && NF_CONNTRACK_TFTP
537
501config IP_NF_NAT_AMANDA 538config IP_NF_NAT_AMANDA
502 tristate 539 tristate
503 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 540 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
504 default IP_NF_NAT if IP_NF_AMANDA=y 541 default IP_NF_NAT if IP_NF_AMANDA=y
505 default m if IP_NF_AMANDA=m 542 default m if IP_NF_AMANDA=m
506 543
544config NF_NAT_AMANDA
545 tristate
546 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
547 default NF_NAT && NF_CONNTRACK_AMANDA
548
507config IP_NF_NAT_PPTP 549config IP_NF_NAT_PPTP
508 tristate 550 tristate
509 depends on IP_NF_NAT!=n && IP_NF_PPTP!=n 551 depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
510 default IP_NF_NAT if IP_NF_PPTP=y 552 default IP_NF_NAT if IP_NF_PPTP=y
511 default m if IP_NF_PPTP=m 553 default m if IP_NF_PPTP=m
512 554
555config NF_NAT_PPTP
556 tristate
557 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
558 default NF_NAT && NF_CONNTRACK_PPTP
559 select NF_NAT_PROTO_GRE
560
513config IP_NF_NAT_H323 561config IP_NF_NAT_H323
514 tristate 562 tristate
515 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 563 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
516 default IP_NF_NAT if IP_NF_H323=y 564 default IP_NF_NAT if IP_NF_H323=y
517 default m if IP_NF_H323=m 565 default m if IP_NF_H323=m
518 566
567config NF_NAT_H323
568 tristate
569 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
570 default NF_NAT && NF_CONNTRACK_H323
571
519config IP_NF_NAT_SIP 572config IP_NF_NAT_SIP
520 tristate 573 tristate
521 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n 574 depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
522 default IP_NF_NAT if IP_NF_SIP=y 575 default IP_NF_NAT if IP_NF_SIP=y
523 default m if IP_NF_SIP=m 576 default m if IP_NF_SIP=m
524 577
578config NF_NAT_SIP
579 tristate
580 depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT
581 default NF_NAT && NF_CONNTRACK_SIP
582
525# mangle + specific targets 583# mangle + specific targets
526config IP_NF_MANGLE 584config IP_NF_MANGLE
527 tristate "Packet mangling" 585 tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 09aaed1a8063..15e741aeb291 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -5,17 +5,23 @@
5# objects for the standalone - connection tracking / NAT 5# objects for the standalone - connection tracking / NAT
6ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o 6ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
7ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o 7ip_nat-objs := ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
8nf_nat-objs := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
9ifneq ($(CONFIG_NF_NAT),)
10iptable_nat-objs := nf_nat_rule.o nf_nat_standalone.o
11else
8iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o 12iptable_nat-objs := ip_nat_rule.o ip_nat_standalone.o
13endif
9 14
10ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o 15ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
11ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o 16ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
12 17
13ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ip_conntrack_helper_h323_asn1.o 18ip_conntrack_h323-objs := ip_conntrack_helper_h323.o ../../netfilter/nf_conntrack_h323_asn1.o
14ip_nat_h323-objs := ip_nat_helper_h323.o 19ip_nat_h323-objs := ip_nat_helper_h323.o
15 20
16# connection tracking 21# connection tracking
17obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o 22obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
18obj-$(CONFIG_IP_NF_NAT) += ip_nat.o 23obj-$(CONFIG_IP_NF_NAT) += ip_nat.o
24obj-$(CONFIG_NF_NAT) += nf_nat.o
19 25
20# conntrack netlink interface 26# conntrack netlink interface
21obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o 27obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
@@ -34,7 +40,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
34obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o 40obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
35obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o 41obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
36 42
37# NAT helpers 43# NAT helpers (ip_conntrack)
38obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o 44obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
39obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o 45obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
40obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o 46obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
@@ -43,6 +49,19 @@ obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
43obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o 49obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
44obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o 50obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
45 51
52# NAT helpers (nf_conntrack)
53obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
54obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
55obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
56obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
57obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
58obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o
59obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
60obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
61
62# NAT protocols (nf_nat)
63obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
64
46# generic IP tables 65# generic IP tables
47obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o 66obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
48 67
@@ -50,10 +69,10 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
50obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o 69obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
51obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o 70obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
52obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o 71obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
72obj-$(CONFIG_NF_NAT) += iptable_nat.o
53obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o 73obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
54 74
55# matches 75# matches
56obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
57obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o 76obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
58obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 77obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
59obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 78obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -89,6 +108,11 @@ obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
89 108
90# objects for l3 independent conntrack 109# objects for l3 independent conntrack
91nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o 110nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
111ifeq ($(CONFIG_NF_CONNTRACK_PROC_COMPAT),y)
112ifeq ($(CONFIG_PROC_FS),y)
113nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
114endif
115endif
92 116
93# l3 independent conntrack 117# l3 independent conntrack
94obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o 118obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 6c7383a8e42b..ad246ba7790b 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -92,6 +92,7 @@ static int help(struct sk_buff **pskb,
92 char pbuf[sizeof("65535")], *tmp; 92 char pbuf[sizeof("65535")], *tmp;
93 u_int16_t port, len; 93 u_int16_t port, len;
94 int ret = NF_ACCEPT; 94 int ret = NF_ACCEPT;
95 typeof(ip_nat_amanda_hook) ip_nat_amanda;
95 96
96 /* Only look at packets from the Amanda server */ 97 /* Only look at packets from the Amanda server */
97 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) 98 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL)
@@ -161,9 +162,11 @@ static int help(struct sk_buff **pskb,
161 exp->mask.dst.protonum = 0xFF; 162 exp->mask.dst.protonum = 0xFF;
162 exp->mask.dst.u.tcp.port = htons(0xFFFF); 163 exp->mask.dst.u.tcp.port = htons(0xFFFF);
163 164
164 if (ip_nat_amanda_hook) 165 /* RCU read locked by nf_hook_slow */
165 ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff, 166 ip_nat_amanda = rcu_dereference(ip_nat_amanda_hook);
166 len, exp); 167 if (ip_nat_amanda)
168 ret = ip_nat_amanda(pskb, ctinfo, off - dataoff,
169 len, exp);
167 else if (ip_conntrack_expect_related(exp) != 0) 170 else if (ip_conntrack_expect_related(exp) != 0)
168 ret = NF_DROP; 171 ret = NF_DROP;
169 ip_conntrack_expect_put(exp); 172 ip_conntrack_expect_put(exp);
@@ -180,7 +183,7 @@ static struct ip_conntrack_helper amanda_helper = {
180 .help = help, 183 .help = help,
181 .name = "amanda", 184 .name = "amanda",
182 185
183 .tuple = { .src = { .u = { __constant_htons(10080) } }, 186 .tuple = { .src = { .u = { .udp = {.port = __constant_htons(10080) } } },
184 .dst = { .protonum = IPPROTO_UDP }, 187 .dst = { .protonum = IPPROTO_UDP },
185 }, 188 },
186 .mask = { .src = { .u = { 0xFFFF } }, 189 .mask = { .src = { .u = { 0xFFFF } },
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 143c4668538b..f4b0e68a16d2 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -40,9 +40,6 @@
40 40
41/* ip_conntrack_lock protects the main hash table, protocol/helper/expected 41/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
42 registrations, conntrack timers*/ 42 registrations, conntrack timers*/
43#define ASSERT_READ_LOCK(x)
44#define ASSERT_WRITE_LOCK(x)
45
46#include <linux/netfilter_ipv4/ip_conntrack.h> 43#include <linux/netfilter_ipv4/ip_conntrack.h>
47#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 44#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
48#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 45#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -201,7 +198,6 @@ ip_ct_invert_tuple(struct ip_conntrack_tuple *inverse,
201/* ip_conntrack_expect helper functions */ 198/* ip_conntrack_expect helper functions */
202void ip_ct_unlink_expect(struct ip_conntrack_expect *exp) 199void ip_ct_unlink_expect(struct ip_conntrack_expect *exp)
203{ 200{
204 ASSERT_WRITE_LOCK(&ip_conntrack_lock);
205 IP_NF_ASSERT(!timer_pending(&exp->timeout)); 201 IP_NF_ASSERT(!timer_pending(&exp->timeout));
206 list_del(&exp->list); 202 list_del(&exp->list);
207 CONNTRACK_STAT_INC(expect_delete); 203 CONNTRACK_STAT_INC(expect_delete);
@@ -225,22 +221,22 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
225 struct ip_conntrack_expect *i; 221 struct ip_conntrack_expect *i;
226 222
227 list_for_each_entry(i, &ip_conntrack_expect_list, list) { 223 list_for_each_entry(i, &ip_conntrack_expect_list, list) {
228 if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { 224 if (ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
229 atomic_inc(&i->use);
230 return i; 225 return i;
231 }
232 } 226 }
233 return NULL; 227 return NULL;
234} 228}
235 229
236/* Just find a expectation corresponding to a tuple. */ 230/* Just find a expectation corresponding to a tuple. */
237struct ip_conntrack_expect * 231struct ip_conntrack_expect *
238ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) 232ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
239{ 233{
240 struct ip_conntrack_expect *i; 234 struct ip_conntrack_expect *i;
241 235
242 read_lock_bh(&ip_conntrack_lock); 236 read_lock_bh(&ip_conntrack_lock);
243 i = __ip_conntrack_expect_find(tuple); 237 i = __ip_conntrack_expect_find(tuple);
238 if (i)
239 atomic_inc(&i->use);
244 read_unlock_bh(&ip_conntrack_lock); 240 read_unlock_bh(&ip_conntrack_lock);
245 241
246 return i; 242 return i;
@@ -294,7 +290,6 @@ static void
294clean_from_lists(struct ip_conntrack *ct) 290clean_from_lists(struct ip_conntrack *ct)
295{ 291{
296 DEBUGP("clean_from_lists(%p)\n", ct); 292 DEBUGP("clean_from_lists(%p)\n", ct);
297 ASSERT_WRITE_LOCK(&ip_conntrack_lock);
298 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); 293 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
299 list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); 294 list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
300 295
@@ -373,7 +368,6 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
373 struct ip_conntrack_tuple_hash *h; 368 struct ip_conntrack_tuple_hash *h;
374 unsigned int hash = hash_conntrack(tuple); 369 unsigned int hash = hash_conntrack(tuple);
375 370
376 ASSERT_READ_LOCK(&ip_conntrack_lock);
377 list_for_each_entry(h, &ip_conntrack_hash[hash], list) { 371 list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
378 if (tuplehash_to_ctrack(h) != ignored_conntrack && 372 if (tuplehash_to_ctrack(h) != ignored_conntrack &&
379 ip_ct_tuple_equal(tuple, &h->tuple)) { 373 ip_ct_tuple_equal(tuple, &h->tuple)) {
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 93dcf960662f..0410c99cacae 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -310,6 +310,7 @@ static int help(struct sk_buff **pskb,
310 struct ip_conntrack_expect *exp; 310 struct ip_conntrack_expect *exp;
311 unsigned int i; 311 unsigned int i;
312 int found = 0, ends_in_nl; 312 int found = 0, ends_in_nl;
313 typeof(ip_nat_ftp_hook) ip_nat_ftp;
313 314
314 /* Until there's been traffic both ways, don't look in packets. */ 315 /* Until there's been traffic both ways, don't look in packets. */
315 if (ctinfo != IP_CT_ESTABLISHED 316 if (ctinfo != IP_CT_ESTABLISHED
@@ -433,9 +434,10 @@ static int help(struct sk_buff **pskb,
433 434
434 /* Now, NAT might want to mangle the packet, and register the 435 /* Now, NAT might want to mangle the packet, and register the
435 * (possibly changed) expectation itself. */ 436 * (possibly changed) expectation itself. */
436 if (ip_nat_ftp_hook) 437 ip_nat_ftp = rcu_dereference(ip_nat_ftp_hook);
437 ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype, 438 if (ip_nat_ftp)
438 matchoff, matchlen, exp, &seq); 439 ret = ip_nat_ftp(pskb, ctinfo, search[dir][i].ftptype,
440 matchoff, matchlen, exp, &seq);
439 else { 441 else {
440 /* Can't expect this? Best to drop packet now. */ 442 /* Can't expect this? Best to drop packet now. */
441 if (ip_conntrack_expect_related(exp) != 0) 443 if (ip_conntrack_expect_related(exp) != 0)
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 7b7441202bfd..aabfe1c06905 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -237,6 +237,7 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
237 u_int16_t rtp_port; 237 u_int16_t rtp_port;
238 struct ip_conntrack_expect *rtp_exp; 238 struct ip_conntrack_expect *rtp_exp;
239 struct ip_conntrack_expect *rtcp_exp; 239 struct ip_conntrack_expect *rtcp_exp;
240 typeof(nat_rtp_rtcp_hook) nat_rtp_rtcp;
240 241
241 /* Read RTP or RTCP address */ 242 /* Read RTP or RTCP address */
242 if (!get_h245_addr(*data, addr, &ip, &port) || 243 if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -279,11 +280,11 @@ static int expect_rtp_rtcp(struct sk_buff **pskb, struct ip_conntrack *ct,
279 rtcp_exp->flags = 0; 280 rtcp_exp->flags = 0;
280 281
281 if (ct->tuplehash[dir].tuple.src.ip != 282 if (ct->tuplehash[dir].tuple.src.ip !=
282 ct->tuplehash[!dir].tuple.dst.ip && nat_rtp_rtcp_hook) { 283 ct->tuplehash[!dir].tuple.dst.ip &&
284 (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook))) {
283 /* NAT needed */ 285 /* NAT needed */
284 ret = nat_rtp_rtcp_hook(pskb, ct, ctinfo, data, dataoff, 286 ret = nat_rtp_rtcp(pskb, ct, ctinfo, data, dataoff,
285 addr, port, rtp_port, rtp_exp, 287 addr, port, rtp_port, rtp_exp, rtcp_exp);
286 rtcp_exp);
287 } else { /* Conntrack only */ 288 } else { /* Conntrack only */
288 rtp_exp->expectfn = NULL; 289 rtp_exp->expectfn = NULL;
289 rtcp_exp->expectfn = NULL; 290 rtcp_exp->expectfn = NULL;
@@ -328,6 +329,7 @@ static int expect_t120(struct sk_buff **pskb,
328 __be32 ip; 329 __be32 ip;
329 u_int16_t port; 330 u_int16_t port;
330 struct ip_conntrack_expect *exp = NULL; 331 struct ip_conntrack_expect *exp = NULL;
332 typeof(nat_t120_hook) nat_t120;
331 333
332 /* Read T.120 address */ 334 /* Read T.120 address */
333 if (!get_h245_addr(*data, addr, &ip, &port) || 335 if (!get_h245_addr(*data, addr, &ip, &port) ||
@@ -350,10 +352,11 @@ static int expect_t120(struct sk_buff **pskb,
350 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */ 352 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple channels */
351 353
352 if (ct->tuplehash[dir].tuple.src.ip != 354 if (ct->tuplehash[dir].tuple.src.ip !=
353 ct->tuplehash[!dir].tuple.dst.ip && nat_t120_hook) { 355 ct->tuplehash[!dir].tuple.dst.ip &&
356 (nat_t120 = rcu_dereference(nat_t120_hook))) {
354 /* NAT needed */ 357 /* NAT needed */
355 ret = nat_t120_hook(pskb, ct, ctinfo, data, dataoff, addr, 358 ret = nat_t120(pskb, ct, ctinfo, data, dataoff, addr,
356 port, exp); 359 port, exp);
357 } else { /* Conntrack only */ 360 } else { /* Conntrack only */
358 exp->expectfn = NULL; 361 exp->expectfn = NULL;
359 if (ip_conntrack_expect_related(exp) == 0) { 362 if (ip_conntrack_expect_related(exp) == 0) {
@@ -651,6 +654,7 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
651 __be32 ip; 654 __be32 ip;
652 u_int16_t port; 655 u_int16_t port;
653 struct ip_conntrack_expect *exp = NULL; 656 struct ip_conntrack_expect *exp = NULL;
657 typeof(nat_h245_hook) nat_h245;
654 658
655 /* Read h245Address */ 659 /* Read h245Address */
656 if (!get_h225_addr(*data, addr, &ip, &port) || 660 if (!get_h225_addr(*data, addr, &ip, &port) ||
@@ -673,10 +677,11 @@ static int expect_h245(struct sk_buff **pskb, struct ip_conntrack *ct,
673 exp->flags = 0; 677 exp->flags = 0;
674 678
675 if (ct->tuplehash[dir].tuple.src.ip != 679 if (ct->tuplehash[dir].tuple.src.ip !=
676 ct->tuplehash[!dir].tuple.dst.ip && nat_h245_hook) { 680 ct->tuplehash[!dir].tuple.dst.ip &&
681 (nat_h245 = rcu_dereference(nat_h245_hook))) {
677 /* NAT needed */ 682 /* NAT needed */
678 ret = nat_h245_hook(pskb, ct, ctinfo, data, dataoff, addr, 683 ret = nat_h245(pskb, ct, ctinfo, data, dataoff, addr,
679 port, exp); 684 port, exp);
680 } else { /* Conntrack only */ 685 } else { /* Conntrack only */
681 exp->expectfn = ip_conntrack_h245_expect; 686 exp->expectfn = ip_conntrack_h245_expect;
682 687
@@ -712,6 +717,7 @@ static int expect_callforwarding(struct sk_buff **pskb,
712 __be32 ip; 717 __be32 ip;
713 u_int16_t port; 718 u_int16_t port;
714 struct ip_conntrack_expect *exp = NULL; 719 struct ip_conntrack_expect *exp = NULL;
720 typeof(nat_callforwarding_hook) nat_callforwarding;
715 721
716 /* Read alternativeAddress */ 722 /* Read alternativeAddress */
717 if (!get_h225_addr(*data, addr, &ip, &port) || port == 0) 723 if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
@@ -759,10 +765,11 @@ static int expect_callforwarding(struct sk_buff **pskb,
759 exp->flags = 0; 765 exp->flags = 0;
760 766
761 if (ct->tuplehash[dir].tuple.src.ip != 767 if (ct->tuplehash[dir].tuple.src.ip !=
762 ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) { 768 ct->tuplehash[!dir].tuple.dst.ip &&
769 (nat_callforwarding = rcu_dereference(nat_callforwarding_hook))) {
763 /* Need NAT */ 770 /* Need NAT */
764 ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff, 771 ret = nat_callforwarding(pskb, ct, ctinfo, data, dataoff,
765 addr, port, exp); 772 addr, port, exp);
766 } else { /* Conntrack only */ 773 } else { /* Conntrack only */
767 exp->expectfn = ip_conntrack_q931_expect; 774 exp->expectfn = ip_conntrack_q931_expect;
768 775
@@ -793,6 +800,7 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
793 int i; 800 int i;
794 __be32 ip; 801 __be32 ip;
795 u_int16_t port; 802 u_int16_t port;
803 typeof(set_h225_addr_hook) set_h225_addr;
796 804
797 DEBUGP("ip_ct_q931: Setup\n"); 805 DEBUGP("ip_ct_q931: Setup\n");
798 806
@@ -803,8 +811,10 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
803 return -1; 811 return -1;
804 } 812 }
805 813
814 set_h225_addr = rcu_dereference(set_h225_addr_hook);
815
806 if ((setup->options & eSetup_UUIE_destCallSignalAddress) && 816 if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
807 (set_h225_addr_hook) && 817 (set_h225_addr) &&
808 get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) && 818 get_h225_addr(*data, &setup->destCallSignalAddress, &ip, &port) &&
809 ip != ct->tuplehash[!dir].tuple.src.ip) { 819 ip != ct->tuplehash[!dir].tuple.src.ip) {
810 DEBUGP("ip_ct_q931: set destCallSignalAddress " 820 DEBUGP("ip_ct_q931: set destCallSignalAddress "
@@ -812,17 +822,17 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
812 NIPQUAD(ip), port, 822 NIPQUAD(ip), port,
813 NIPQUAD(ct->tuplehash[!dir].tuple.src.ip), 823 NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
814 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); 824 ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
815 ret = set_h225_addr_hook(pskb, data, dataoff, 825 ret = set_h225_addr(pskb, data, dataoff,
816 &setup->destCallSignalAddress, 826 &setup->destCallSignalAddress,
817 ct->tuplehash[!dir].tuple.src.ip, 827 ct->tuplehash[!dir].tuple.src.ip,
818 ntohs(ct->tuplehash[!dir].tuple.src. 828 ntohs(ct->tuplehash[!dir].tuple.src.
819 u.tcp.port)); 829 u.tcp.port));
820 if (ret < 0) 830 if (ret < 0)
821 return -1; 831 return -1;
822 } 832 }
823 833
824 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && 834 if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
825 (set_h225_addr_hook) && 835 (set_h225_addr) &&
826 get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port) 836 get_h225_addr(*data, &setup->sourceCallSignalAddress, &ip, &port)
827 && ip != ct->tuplehash[!dir].tuple.dst.ip) { 837 && ip != ct->tuplehash[!dir].tuple.dst.ip) {
828 DEBUGP("ip_ct_q931: set sourceCallSignalAddress " 838 DEBUGP("ip_ct_q931: set sourceCallSignalAddress "
@@ -830,11 +840,11 @@ static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
830 NIPQUAD(ip), port, 840 NIPQUAD(ip), port,
831 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip), 841 NIPQUAD(ct->tuplehash[!dir].tuple.dst.ip),
832 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); 842 ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
833 ret = set_h225_addr_hook(pskb, data, dataoff, 843 ret = set_h225_addr(pskb, data, dataoff,
834 &setup->sourceCallSignalAddress, 844 &setup->sourceCallSignalAddress,
835 ct->tuplehash[!dir].tuple.dst.ip, 845 ct->tuplehash[!dir].tuple.dst.ip,
836 ntohs(ct->tuplehash[!dir].tuple.dst. 846 ntohs(ct->tuplehash[!dir].tuple.dst.
837 u.tcp.port)); 847 u.tcp.port));
838 if (ret < 0) 848 if (ret < 0)
839 return -1; 849 return -1;
840 } 850 }
@@ -1153,7 +1163,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_q931 = {
1153 .me = THIS_MODULE, 1163 .me = THIS_MODULE,
1154 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ , 1164 .max_expected = H323_RTP_CHANNEL_MAX * 4 + 4 /* T.120 and H.245 */ ,
1155 .timeout = 240, 1165 .timeout = 240,
1156 .tuple = {.src = {.u = {__constant_htons(Q931_PORT)}}, 1166 .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(Q931_PORT)}}},
1157 .dst = {.protonum = IPPROTO_TCP}}, 1167 .dst = {.protonum = IPPROTO_TCP}},
1158 .mask = {.src = {.u = {0xFFFF}}, 1168 .mask = {.src = {.u = {0xFFFF}},
1159 .dst = {.protonum = 0xFF}}, 1169 .dst = {.protonum = 0xFF}},
@@ -1231,6 +1241,7 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1231 __be32 ip; 1241 __be32 ip;
1232 u_int16_t port; 1242 u_int16_t port;
1233 struct ip_conntrack_expect *exp; 1243 struct ip_conntrack_expect *exp;
1244 typeof(nat_q931_hook) nat_q931;
1234 1245
1235 /* Look for the first related address */ 1246 /* Look for the first related address */
1236 for (i = 0; i < count; i++) { 1247 for (i = 0; i < count; i++) {
@@ -1258,9 +1269,9 @@ static int expect_q931(struct sk_buff **pskb, struct ip_conntrack *ct,
1258 exp->mask.dst.protonum = 0xFF; 1269 exp->mask.dst.protonum = 0xFF;
1259 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */ 1270 exp->flags = IP_CT_EXPECT_PERMANENT; /* Accept multiple calls */
1260 1271
1261 if (nat_q931_hook) { /* Need NAT */ 1272 nat_q931 = rcu_dereference(nat_q931_hook);
1262 ret = nat_q931_hook(pskb, ct, ctinfo, data, addr, i, 1273 if (nat_q931) { /* Need NAT */
1263 port, exp); 1274 ret = nat_q931(pskb, ct, ctinfo, data, addr, i, port, exp);
1264 } else { /* Conntrack only */ 1275 } else { /* Conntrack only */
1265 exp->expectfn = ip_conntrack_q931_expect; 1276 exp->expectfn = ip_conntrack_q931_expect;
1266 1277
@@ -1288,11 +1299,14 @@ static int process_grq(struct sk_buff **pskb, struct ip_conntrack *ct,
1288 enum ip_conntrack_info ctinfo, 1299 enum ip_conntrack_info ctinfo,
1289 unsigned char **data, GatekeeperRequest * grq) 1300 unsigned char **data, GatekeeperRequest * grq)
1290{ 1301{
1302 typeof(set_ras_addr_hook) set_ras_addr;
1303
1291 DEBUGP("ip_ct_ras: GRQ\n"); 1304 DEBUGP("ip_ct_ras: GRQ\n");
1292 1305
1293 if (set_ras_addr_hook) /* NATed */ 1306 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1294 return set_ras_addr_hook(pskb, ct, ctinfo, data, 1307 if (set_ras_addr) /* NATed */
1295 &grq->rasAddress, 1); 1308 return set_ras_addr(pskb, ct, ctinfo, data,
1309 &grq->rasAddress, 1);
1296 return 0; 1310 return 0;
1297} 1311}
1298 1312
@@ -1362,6 +1376,7 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1362{ 1376{
1363 struct ip_ct_h323_master *info = &ct->help.ct_h323_info; 1377 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1364 int ret; 1378 int ret;
1379 typeof(set_ras_addr_hook) set_ras_addr;
1365 1380
1366 DEBUGP("ip_ct_ras: RRQ\n"); 1381 DEBUGP("ip_ct_ras: RRQ\n");
1367 1382
@@ -1371,10 +1386,11 @@ static int process_rrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1371 if (ret < 0) 1386 if (ret < 0)
1372 return -1; 1387 return -1;
1373 1388
1374 if (set_ras_addr_hook) { 1389 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1375 ret = set_ras_addr_hook(pskb, ct, ctinfo, data, 1390 if (set_ras_addr) {
1376 rrq->rasAddress.item, 1391 ret = set_ras_addr(pskb, ct, ctinfo, data,
1377 rrq->rasAddress.count); 1392 rrq->rasAddress.item,
1393 rrq->rasAddress.count);
1378 if (ret < 0) 1394 if (ret < 0)
1379 return -1; 1395 return -1;
1380 } 1396 }
@@ -1397,13 +1413,15 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1397 int dir = CTINFO2DIR(ctinfo); 1413 int dir = CTINFO2DIR(ctinfo);
1398 int ret; 1414 int ret;
1399 struct ip_conntrack_expect *exp; 1415 struct ip_conntrack_expect *exp;
1416 typeof(set_sig_addr_hook) set_sig_addr;
1400 1417
1401 DEBUGP("ip_ct_ras: RCF\n"); 1418 DEBUGP("ip_ct_ras: RCF\n");
1402 1419
1403 if (set_sig_addr_hook) { 1420 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1404 ret = set_sig_addr_hook(pskb, ct, ctinfo, data, 1421 if (set_sig_addr) {
1405 rcf->callSignalAddress.item, 1422 ret = set_sig_addr(pskb, ct, ctinfo, data,
1406 rcf->callSignalAddress.count); 1423 rcf->callSignalAddress.item,
1424 rcf->callSignalAddress.count);
1407 if (ret < 0) 1425 if (ret < 0)
1408 return -1; 1426 return -1;
1409 } 1427 }
@@ -1417,7 +1435,7 @@ static int process_rcf(struct sk_buff **pskb, struct ip_conntrack *ct,
1417 DEBUGP 1435 DEBUGP
1418 ("ip_ct_ras: set RAS connection timeout to %u seconds\n", 1436 ("ip_ct_ras: set RAS connection timeout to %u seconds\n",
1419 info->timeout); 1437 info->timeout);
1420 ip_ct_refresh_acct(ct, ctinfo, NULL, info->timeout * HZ); 1438 ip_ct_refresh(ct, *pskb, info->timeout * HZ);
1421 1439
1422 /* Set expect timeout */ 1440 /* Set expect timeout */
1423 read_lock_bh(&ip_conntrack_lock); 1441 read_lock_bh(&ip_conntrack_lock);
@@ -1448,13 +1466,15 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
1448 struct ip_ct_h323_master *info = &ct->help.ct_h323_info; 1466 struct ip_ct_h323_master *info = &ct->help.ct_h323_info;
1449 int dir = CTINFO2DIR(ctinfo); 1467 int dir = CTINFO2DIR(ctinfo);
1450 int ret; 1468 int ret;
1469 typeof(set_sig_addr_hook) set_sig_addr;
1451 1470
1452 DEBUGP("ip_ct_ras: URQ\n"); 1471 DEBUGP("ip_ct_ras: URQ\n");
1453 1472
1454 if (set_sig_addr_hook) { 1473 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1455 ret = set_sig_addr_hook(pskb, ct, ctinfo, data, 1474 if (set_sig_addr) {
1456 urq->callSignalAddress.item, 1475 ret = set_sig_addr(pskb, ct, ctinfo, data,
1457 urq->callSignalAddress.count); 1476 urq->callSignalAddress.item,
1477 urq->callSignalAddress.count);
1458 if (ret < 0) 1478 if (ret < 0)
1459 return -1; 1479 return -1;
1460 } 1480 }
@@ -1465,7 +1485,7 @@ static int process_urq(struct sk_buff **pskb, struct ip_conntrack *ct,
1465 info->sig_port[!dir] = 0; 1485 info->sig_port[!dir] = 0;
1466 1486
1467 /* Give it 30 seconds for UCF or URJ */ 1487 /* Give it 30 seconds for UCF or URJ */
1468 ip_ct_refresh_acct(ct, ctinfo, NULL, 30 * HZ); 1488 ip_ct_refresh(ct, *pskb, 30 * HZ);
1469 1489
1470 return 0; 1490 return 0;
1471} 1491}
@@ -1479,28 +1499,30 @@ static int process_arq(struct sk_buff **pskb, struct ip_conntrack *ct,
1479 int dir = CTINFO2DIR(ctinfo); 1499 int dir = CTINFO2DIR(ctinfo);
1480 __be32 ip; 1500 __be32 ip;
1481 u_int16_t port; 1501 u_int16_t port;
1502 typeof(set_h225_addr_hook) set_h225_addr;
1482 1503
1483 DEBUGP("ip_ct_ras: ARQ\n"); 1504 DEBUGP("ip_ct_ras: ARQ\n");
1484 1505
1506 set_h225_addr = rcu_dereference(set_h225_addr_hook);
1485 if ((arq->options & eAdmissionRequest_destCallSignalAddress) && 1507 if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
1486 get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) && 1508 get_h225_addr(*data, &arq->destCallSignalAddress, &ip, &port) &&
1487 ip == ct->tuplehash[dir].tuple.src.ip && 1509 ip == ct->tuplehash[dir].tuple.src.ip &&
1488 port == info->sig_port[dir] && set_h225_addr_hook) { 1510 port == info->sig_port[dir] && set_h225_addr) {
1489 /* Answering ARQ */ 1511 /* Answering ARQ */
1490 return set_h225_addr_hook(pskb, data, 0, 1512 return set_h225_addr(pskb, data, 0,
1491 &arq->destCallSignalAddress, 1513 &arq->destCallSignalAddress,
1492 ct->tuplehash[!dir].tuple.dst.ip, 1514 ct->tuplehash[!dir].tuple.dst.ip,
1493 info->sig_port[!dir]); 1515 info->sig_port[!dir]);
1494 } 1516 }
1495 1517
1496 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) && 1518 if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
1497 get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) && 1519 get_h225_addr(*data, &arq->srcCallSignalAddress, &ip, &port) &&
1498 ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr_hook) { 1520 ip == ct->tuplehash[dir].tuple.src.ip && set_h225_addr) {
1499 /* Calling ARQ */ 1521 /* Calling ARQ */
1500 return set_h225_addr_hook(pskb, data, 0, 1522 return set_h225_addr(pskb, data, 0,
1501 &arq->srcCallSignalAddress, 1523 &arq->srcCallSignalAddress,
1502 ct->tuplehash[!dir].tuple.dst.ip, 1524 ct->tuplehash[!dir].tuple.dst.ip,
1503 port); 1525 port);
1504 } 1526 }
1505 1527
1506 return 0; 1528 return 0;
@@ -1516,6 +1538,7 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
1516 __be32 ip; 1538 __be32 ip;
1517 u_int16_t port; 1539 u_int16_t port;
1518 struct ip_conntrack_expect *exp; 1540 struct ip_conntrack_expect *exp;
1541 typeof(set_sig_addr_hook) set_sig_addr;
1519 1542
1520 DEBUGP("ip_ct_ras: ACF\n"); 1543 DEBUGP("ip_ct_ras: ACF\n");
1521 1544
@@ -1523,10 +1546,10 @@ static int process_acf(struct sk_buff **pskb, struct ip_conntrack *ct,
1523 return 0; 1546 return 0;
1524 1547
1525 if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */ 1548 if (ip == ct->tuplehash[dir].tuple.dst.ip) { /* Answering ACF */
1526 if (set_sig_addr_hook) 1549 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1527 return set_sig_addr_hook(pskb, ct, ctinfo, data, 1550 if (set_sig_addr)
1528 &acf->destCallSignalAddress, 1551 return set_sig_addr(pskb, ct, ctinfo, data,
1529 1); 1552 &acf->destCallSignalAddress, 1);
1530 return 0; 1553 return 0;
1531 } 1554 }
1532 1555
@@ -1566,11 +1589,14 @@ static int process_lrq(struct sk_buff **pskb, struct ip_conntrack *ct,
1566 enum ip_conntrack_info ctinfo, 1589 enum ip_conntrack_info ctinfo,
1567 unsigned char **data, LocationRequest * lrq) 1590 unsigned char **data, LocationRequest * lrq)
1568{ 1591{
1592 typeof(set_ras_addr_hook) set_ras_addr;
1593
1569 DEBUGP("ip_ct_ras: LRQ\n"); 1594 DEBUGP("ip_ct_ras: LRQ\n");
1570 1595
1571 if (set_ras_addr_hook) 1596 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1572 return set_ras_addr_hook(pskb, ct, ctinfo, data, 1597 if (set_ras_addr)
1573 &lrq->replyAddress, 1); 1598 return set_ras_addr(pskb, ct, ctinfo, data,
1599 &lrq->replyAddress, 1);
1574 return 0; 1600 return 0;
1575} 1601}
1576 1602
@@ -1629,20 +1655,24 @@ static int process_irr(struct sk_buff **pskb, struct ip_conntrack *ct,
1629 unsigned char **data, InfoRequestResponse * irr) 1655 unsigned char **data, InfoRequestResponse * irr)
1630{ 1656{
1631 int ret; 1657 int ret;
1658 typeof(set_ras_addr_hook) set_ras_addr;
1659 typeof(set_sig_addr_hook) set_sig_addr;
1632 1660
1633 DEBUGP("ip_ct_ras: IRR\n"); 1661 DEBUGP("ip_ct_ras: IRR\n");
1634 1662
1635 if (set_ras_addr_hook) { 1663 set_ras_addr = rcu_dereference(set_ras_addr_hook);
1636 ret = set_ras_addr_hook(pskb, ct, ctinfo, data, 1664 if (set_ras_addr) {
1637 &irr->rasAddress, 1); 1665 ret = set_ras_addr(pskb, ct, ctinfo, data,
1666 &irr->rasAddress, 1);
1638 if (ret < 0) 1667 if (ret < 0)
1639 return -1; 1668 return -1;
1640 } 1669 }
1641 1670
1642 if (set_sig_addr_hook) { 1671 set_sig_addr = rcu_dereference(set_sig_addr_hook);
1643 ret = set_sig_addr_hook(pskb, ct, ctinfo, data, 1672 if (set_sig_addr) {
1644 irr->callSignalAddress.item, 1673 ret = set_sig_addr(pskb, ct, ctinfo, data,
1645 irr->callSignalAddress.count); 1674 irr->callSignalAddress.item,
1675 irr->callSignalAddress.count);
1646 if (ret < 0) 1676 if (ret < 0)
1647 return -1; 1677 return -1;
1648 } 1678 }
@@ -1746,7 +1776,7 @@ static struct ip_conntrack_helper ip_conntrack_helper_ras = {
1746 .me = THIS_MODULE, 1776 .me = THIS_MODULE,
1747 .max_expected = 32, 1777 .max_expected = 32,
1748 .timeout = 240, 1778 .timeout = 240,
1749 .tuple = {.src = {.u = {__constant_htons(RAS_PORT)}}, 1779 .tuple = {.src = {.u = {.tcp = {.port = __constant_htons(RAS_PORT)}}},
1750 .dst = {.protonum = IPPROTO_UDP}}, 1780 .dst = {.protonum = IPPROTO_UDP}},
1751 .mask = {.src = {.u = {0xFFFE}}, 1781 .mask = {.src = {.u = {0xFFFE}},
1752 .dst = {.protonum = 0xFF}}, 1782 .dst = {.protonum = 0xFF}},
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
deleted file mode 100644
index 26dfecadb335..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c
+++ /dev/null
@@ -1,874 +0,0 @@
1/****************************************************************************
2 * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323
3 * conntrack/NAT module.
4 *
5 * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net>
6 *
7 * This source code is licensed under General Public License version 2.
8 *
9 * See ip_conntrack_helper_h323_asn1.h for details.
10 *
11 ****************************************************************************/
12
13#ifdef __KERNEL__
14#include <linux/kernel.h>
15#else
16#include <stdio.h>
17#endif
18#include <linux/netfilter_ipv4/ip_conntrack_helper_h323_asn1.h>
19
20/* Trace Flag */
21#ifndef H323_TRACE
22#define H323_TRACE 0
23#endif
24
25#if H323_TRACE
26#define TAB_SIZE 4
27#define IFTHEN(cond, act) if(cond){act;}
28#ifdef __KERNEL__
29#define PRINT printk
30#else
31#define PRINT printf
32#endif
33#define FNAME(name) name,
34#else
35#define IFTHEN(cond, act)
36#define PRINT(fmt, args...)
37#define FNAME(name)
38#endif
39
40/* ASN.1 Types */
41#define NUL 0
42#define BOOL 1
43#define OID 2
44#define INT 3
45#define ENUM 4
46#define BITSTR 5
47#define NUMSTR 6
48#define NUMDGT 6
49#define TBCDSTR 6
50#define OCTSTR 7
51#define PRTSTR 7
52#define IA5STR 7
53#define GENSTR 7
54#define BMPSTR 8
55#define SEQ 9
56#define SET 9
57#define SEQOF 10
58#define SETOF 10
59#define CHOICE 11
60
61/* Constraint Types */
62#define FIXD 0
63/* #define BITS 1-8 */
64#define BYTE 9
65#define WORD 10
66#define CONS 11
67#define SEMI 12
68#define UNCO 13
69
70/* ASN.1 Type Attributes */
71#define SKIP 0
72#define STOP 1
73#define DECODE 2
74#define EXT 4
75#define OPEN 8
76#define OPT 16
77
78
79/* ASN.1 Field Structure */
80typedef struct field_t {
81#if H323_TRACE
82 char *name;
83#endif
84 unsigned char type;
85 unsigned char sz;
86 unsigned char lb;
87 unsigned char ub;
88 unsigned short attr;
89 unsigned short offset;
90 struct field_t *fields;
91} field_t;
92
93/* Bit Stream */
94typedef struct {
95 unsigned char *buf;
96 unsigned char *beg;
97 unsigned char *end;
98 unsigned char *cur;
99 unsigned bit;
100} bitstr_t;
101
102/* Tool Functions */
103#define INC_BIT(bs) if((++bs->bit)>7){bs->cur++;bs->bit=0;}
104#define INC_BITS(bs,b) if((bs->bit+=b)>7){bs->cur+=bs->bit>>3;bs->bit&=7;}
105#define BYTE_ALIGN(bs) if(bs->bit){bs->cur++;bs->bit=0;}
106#define CHECK_BOUND(bs,n) if(bs->cur+(n)>bs->end)return(H323_ERROR_BOUND)
107static unsigned get_len(bitstr_t * bs);
108static unsigned get_bit(bitstr_t * bs);
109static unsigned get_bits(bitstr_t * bs, unsigned b);
110static unsigned get_bitmap(bitstr_t * bs, unsigned b);
111static unsigned get_uint(bitstr_t * bs, int b);
112
113/* Decoder Functions */
114static int decode_nul(bitstr_t * bs, field_t * f, char *base, int level);
115static int decode_bool(bitstr_t * bs, field_t * f, char *base, int level);
116static int decode_oid(bitstr_t * bs, field_t * f, char *base, int level);
117static int decode_int(bitstr_t * bs, field_t * f, char *base, int level);
118static int decode_enum(bitstr_t * bs, field_t * f, char *base, int level);
119static int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level);
120static int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level);
121static int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level);
122static int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level);
123static int decode_seq(bitstr_t * bs, field_t * f, char *base, int level);
124static int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level);
125static int decode_choice(bitstr_t * bs, field_t * f, char *base, int level);
126
127/* Decoder Functions Vector */
128typedef int (*decoder_t) (bitstr_t *, field_t *, char *, int);
129static decoder_t Decoders[] = {
130 decode_nul,
131 decode_bool,
132 decode_oid,
133 decode_int,
134 decode_enum,
135 decode_bitstr,
136 decode_numstr,
137 decode_octstr,
138 decode_bmpstr,
139 decode_seq,
140 decode_seqof,
141 decode_choice,
142};
143
144/****************************************************************************
145 * H.323 Types
146 ****************************************************************************/
147#include "ip_conntrack_helper_h323_types.c"
148
149/****************************************************************************
150 * Functions
151 ****************************************************************************/
152/* Assume bs is aligned && v < 16384 */
153unsigned get_len(bitstr_t * bs)
154{
155 unsigned v;
156
157 v = *bs->cur++;
158
159 if (v & 0x80) {
160 v &= 0x3f;
161 v <<= 8;
162 v += *bs->cur++;
163 }
164
165 return v;
166}
167
168/****************************************************************************/
169unsigned get_bit(bitstr_t * bs)
170{
171 unsigned b = (*bs->cur) & (0x80 >> bs->bit);
172
173 INC_BIT(bs);
174
175 return b;
176}
177
178/****************************************************************************/
179/* Assume b <= 8 */
180unsigned get_bits(bitstr_t * bs, unsigned b)
181{
182 unsigned v, l;
183
184 v = (*bs->cur) & (0xffU >> bs->bit);
185 l = b + bs->bit;
186
187 if (l < 8) {
188 v >>= 8 - l;
189 bs->bit = l;
190 } else if (l == 8) {
191 bs->cur++;
192 bs->bit = 0;
193 } else { /* l > 8 */
194
195 v <<= 8;
196 v += *(++bs->cur);
197 v >>= 16 - l;
198 bs->bit = l - 8;
199 }
200
201 return v;
202}
203
204/****************************************************************************/
205/* Assume b <= 32 */
206unsigned get_bitmap(bitstr_t * bs, unsigned b)
207{
208 unsigned v, l, shift, bytes;
209
210 if (!b)
211 return 0;
212
213 l = bs->bit + b;
214
215 if (l < 8) {
216 v = (unsigned) (*bs->cur) << (bs->bit + 24);
217 bs->bit = l;
218 } else if (l == 8) {
219 v = (unsigned) (*bs->cur++) << (bs->bit + 24);
220 bs->bit = 0;
221 } else {
222 for (bytes = l >> 3, shift = 24, v = 0; bytes;
223 bytes--, shift -= 8)
224 v |= (unsigned) (*bs->cur++) << shift;
225
226 if (l < 32) {
227 v |= (unsigned) (*bs->cur) << shift;
228 v <<= bs->bit;
229 } else if (l > 32) {
230 v <<= bs->bit;
231 v |= (*bs->cur) >> (8 - bs->bit);
232 }
233
234 bs->bit = l & 0x7;
235 }
236
237 v &= 0xffffffff << (32 - b);
238
239 return v;
240}
241
242/****************************************************************************
243 * Assume bs is aligned and sizeof(unsigned int) == 4
244 ****************************************************************************/
245unsigned get_uint(bitstr_t * bs, int b)
246{
247 unsigned v = 0;
248
249 switch (b) {
250 case 4:
251 v |= *bs->cur++;
252 v <<= 8;
253 case 3:
254 v |= *bs->cur++;
255 v <<= 8;
256 case 2:
257 v |= *bs->cur++;
258 v <<= 8;
259 case 1:
260 v |= *bs->cur++;
261 break;
262 }
263 return v;
264}
265
266/****************************************************************************/
267int decode_nul(bitstr_t * bs, field_t * f, char *base, int level)
268{
269 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
270
271 return H323_ERROR_NONE;
272}
273
274/****************************************************************************/
275int decode_bool(bitstr_t * bs, field_t * f, char *base, int level)
276{
277 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
278
279 INC_BIT(bs);
280
281 CHECK_BOUND(bs, 0);
282 return H323_ERROR_NONE;
283}
284
285/****************************************************************************/
286int decode_oid(bitstr_t * bs, field_t * f, char *base, int level)
287{
288 int len;
289
290 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
291
292 BYTE_ALIGN(bs);
293 CHECK_BOUND(bs, 1);
294 len = *bs->cur++;
295 bs->cur += len;
296
297 CHECK_BOUND(bs, 0);
298 return H323_ERROR_NONE;
299}
300
301/****************************************************************************/
302int decode_int(bitstr_t * bs, field_t * f, char *base, int level)
303{
304 unsigned len;
305
306 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
307
308 switch (f->sz) {
309 case BYTE: /* Range == 256 */
310 BYTE_ALIGN(bs);
311 bs->cur++;
312 break;
313 case WORD: /* 257 <= Range <= 64K */
314 BYTE_ALIGN(bs);
315 bs->cur += 2;
316 break;
317 case CONS: /* 64K < Range < 4G */
318 len = get_bits(bs, 2) + 1;
319 BYTE_ALIGN(bs);
320 if (base && (f->attr & DECODE)) { /* timeToLive */
321 unsigned v = get_uint(bs, len) + f->lb;
322 PRINT(" = %u", v);
323 *((unsigned *) (base + f->offset)) = v;
324 }
325 bs->cur += len;
326 break;
327 case UNCO:
328 BYTE_ALIGN(bs);
329 CHECK_BOUND(bs, 2);
330 len = get_len(bs);
331 bs->cur += len;
332 break;
333 default: /* 2 <= Range <= 255 */
334 INC_BITS(bs, f->sz);
335 break;
336 }
337
338 PRINT("\n");
339
340 CHECK_BOUND(bs, 0);
341 return H323_ERROR_NONE;
342}
343
344/****************************************************************************/
345int decode_enum(bitstr_t * bs, field_t * f, char *base, int level)
346{
347 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
348
349 if ((f->attr & EXT) && get_bit(bs)) {
350 INC_BITS(bs, 7);
351 } else {
352 INC_BITS(bs, f->sz);
353 }
354
355 CHECK_BOUND(bs, 0);
356 return H323_ERROR_NONE;
357}
358
359/****************************************************************************/
360int decode_bitstr(bitstr_t * bs, field_t * f, char *base, int level)
361{
362 unsigned len;
363
364 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
365
366 BYTE_ALIGN(bs);
367 switch (f->sz) {
368 case FIXD: /* fixed length > 16 */
369 len = f->lb;
370 break;
371 case WORD: /* 2-byte length */
372 CHECK_BOUND(bs, 2);
373 len = (*bs->cur++) << 8;
374 len += (*bs->cur++) + f->lb;
375 break;
376 case SEMI:
377 CHECK_BOUND(bs, 2);
378 len = get_len(bs);
379 break;
380 default:
381 len = 0;
382 break;
383 }
384
385 bs->cur += len >> 3;
386 bs->bit = len & 7;
387
388 CHECK_BOUND(bs, 0);
389 return H323_ERROR_NONE;
390}
391
392/****************************************************************************/
393int decode_numstr(bitstr_t * bs, field_t * f, char *base, int level)
394{
395 unsigned len;
396
397 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
398
399 /* 2 <= Range <= 255 */
400 len = get_bits(bs, f->sz) + f->lb;
401
402 BYTE_ALIGN(bs);
403 INC_BITS(bs, (len << 2));
404
405 CHECK_BOUND(bs, 0);
406 return H323_ERROR_NONE;
407}
408
409/****************************************************************************/
410int decode_octstr(bitstr_t * bs, field_t * f, char *base, int level)
411{
412 unsigned len;
413
414 PRINT("%*.s%s", level * TAB_SIZE, " ", f->name);
415
416 switch (f->sz) {
417 case FIXD: /* Range == 1 */
418 if (f->lb > 2) {
419 BYTE_ALIGN(bs);
420 if (base && (f->attr & DECODE)) {
421 /* The IP Address */
422 IFTHEN(f->lb == 4,
423 PRINT(" = %d.%d.%d.%d:%d",
424 bs->cur[0], bs->cur[1],
425 bs->cur[2], bs->cur[3],
426 bs->cur[4] * 256 + bs->cur[5]));
427 *((unsigned *) (base + f->offset)) =
428 bs->cur - bs->buf;
429 }
430 }
431 len = f->lb;
432 break;
433 case BYTE: /* Range == 256 */
434 BYTE_ALIGN(bs);
435 CHECK_BOUND(bs, 1);
436 len = (*bs->cur++) + f->lb;
437 break;
438 case SEMI:
439 BYTE_ALIGN(bs);
440 CHECK_BOUND(bs, 2);
441 len = get_len(bs) + f->lb;
442 break;
443 default: /* 2 <= Range <= 255 */
444 len = get_bits(bs, f->sz) + f->lb;
445 BYTE_ALIGN(bs);
446 break;
447 }
448
449 bs->cur += len;
450
451 PRINT("\n");
452
453 CHECK_BOUND(bs, 0);
454 return H323_ERROR_NONE;
455}
456
457/****************************************************************************/
458int decode_bmpstr(bitstr_t * bs, field_t * f, char *base, int level)
459{
460 unsigned len;
461
462 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
463
464 switch (f->sz) {
465 case BYTE: /* Range == 256 */
466 BYTE_ALIGN(bs);
467 CHECK_BOUND(bs, 1);
468 len = (*bs->cur++) + f->lb;
469 break;
470 default: /* 2 <= Range <= 255 */
471 len = get_bits(bs, f->sz) + f->lb;
472 BYTE_ALIGN(bs);
473 break;
474 }
475
476 bs->cur += len << 1;
477
478 CHECK_BOUND(bs, 0);
479 return H323_ERROR_NONE;
480}
481
482/****************************************************************************/
483int decode_seq(bitstr_t * bs, field_t * f, char *base, int level)
484{
485 unsigned ext, bmp, i, opt, len = 0, bmp2, bmp2_len;
486 int err;
487 field_t *son;
488 unsigned char *beg = NULL;
489
490 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
491
492 /* Decode? */
493 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
494
495 /* Extensible? */
496 ext = (f->attr & EXT) ? get_bit(bs) : 0;
497
498 /* Get fields bitmap */
499 bmp = get_bitmap(bs, f->sz);
500 if (base)
501 *(unsigned *) base = bmp;
502
503 /* Decode the root components */
504 for (i = opt = 0, son = f->fields; i < f->lb; i++, son++) {
505 if (son->attr & STOP) {
506 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
507 son->name);
508 return H323_ERROR_STOP;
509 }
510
511 if (son->attr & OPT) { /* Optional component */
512 if (!((0x80000000U >> (opt++)) & bmp)) /* Not exist */
513 continue;
514 }
515
516 /* Decode */
517 if (son->attr & OPEN) { /* Open field */
518 CHECK_BOUND(bs, 2);
519 len = get_len(bs);
520 CHECK_BOUND(bs, len);
521 if (!base) {
522 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
523 " ", son->name);
524 bs->cur += len;
525 continue;
526 }
527 beg = bs->cur;
528
529 /* Decode */
530 if ((err = (Decoders[son->type]) (bs, son, base,
531 level + 1)) <
532 H323_ERROR_NONE)
533 return err;
534
535 bs->cur = beg + len;
536 bs->bit = 0;
537 } else if ((err = (Decoders[son->type]) (bs, son, base,
538 level + 1)) <
539 H323_ERROR_NONE)
540 return err;
541 }
542
543 /* No extension? */
544 if (!ext)
545 return H323_ERROR_NONE;
546
547 /* Get the extension bitmap */
548 bmp2_len = get_bits(bs, 7) + 1;
549 CHECK_BOUND(bs, (bmp2_len + 7) >> 3);
550 bmp2 = get_bitmap(bs, bmp2_len);
551 bmp |= bmp2 >> f->sz;
552 if (base)
553 *(unsigned *) base = bmp;
554 BYTE_ALIGN(bs);
555
556 /* Decode the extension components */
557 for (opt = 0; opt < bmp2_len; opt++, i++, son++) {
558 if (i < f->ub && son->attr & STOP) {
559 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
560 son->name);
561 return H323_ERROR_STOP;
562 }
563
564 if (!((0x80000000 >> opt) & bmp2)) /* Not present */
565 continue;
566
567 /* Check Range */
568 if (i >= f->ub) { /* Newer Version? */
569 CHECK_BOUND(bs, 2);
570 len = get_len(bs);
571 CHECK_BOUND(bs, len);
572 bs->cur += len;
573 continue;
574 }
575
576 CHECK_BOUND(bs, 2);
577 len = get_len(bs);
578 CHECK_BOUND(bs, len);
579 if (!base || !(son->attr & DECODE)) {
580 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
581 son->name);
582 bs->cur += len;
583 continue;
584 }
585 beg = bs->cur;
586
587 if ((err = (Decoders[son->type]) (bs, son, base,
588 level + 1)) <
589 H323_ERROR_NONE)
590 return err;
591
592 bs->cur = beg + len;
593 bs->bit = 0;
594 }
595 return H323_ERROR_NONE;
596}
597
598/****************************************************************************/
599int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level)
600{
601 unsigned count, effective_count = 0, i, len = 0;
602 int err;
603 field_t *son;
604 unsigned char *beg = NULL;
605
606 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
607
608 /* Decode? */
609 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
610
611 /* Decode item count */
612 switch (f->sz) {
613 case BYTE:
614 BYTE_ALIGN(bs);
615 CHECK_BOUND(bs, 1);
616 count = *bs->cur++;
617 break;
618 case WORD:
619 BYTE_ALIGN(bs);
620 CHECK_BOUND(bs, 2);
621 count = *bs->cur++;
622 count <<= 8;
623 count = *bs->cur++;
624 break;
625 case SEMI:
626 BYTE_ALIGN(bs);
627 CHECK_BOUND(bs, 2);
628 count = get_len(bs);
629 break;
630 default:
631 count = get_bits(bs, f->sz);
632 break;
633 }
634 count += f->lb;
635
636 /* Write Count */
637 if (base) {
638 effective_count = count > f->ub ? f->ub : count;
639 *(unsigned *) base = effective_count;
640 base += sizeof(unsigned);
641 }
642
643 /* Decode nested field */
644 son = f->fields;
645 if (base)
646 base -= son->offset;
647 for (i = 0; i < count; i++) {
648 if (son->attr & OPEN) {
649 BYTE_ALIGN(bs);
650 len = get_len(bs);
651 CHECK_BOUND(bs, len);
652 if (!base || !(son->attr & DECODE)) {
653 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE,
654 " ", son->name);
655 bs->cur += len;
656 continue;
657 }
658 beg = bs->cur;
659
660 if ((err = (Decoders[son->type]) (bs, son,
661 i <
662 effective_count ?
663 base : NULL,
664 level + 1)) <
665 H323_ERROR_NONE)
666 return err;
667
668 bs->cur = beg + len;
669 bs->bit = 0;
670 } else
671 if ((err = (Decoders[son->type]) (bs, son,
672 i <
673 effective_count ?
674 base : NULL,
675 level + 1)) <
676 H323_ERROR_NONE)
677 return err;
678
679 if (base)
680 base += son->offset;
681 }
682
683 return H323_ERROR_NONE;
684}
685
686
687/****************************************************************************/
688int decode_choice(bitstr_t * bs, field_t * f, char *base, int level)
689{
690 unsigned type, ext, len = 0;
691 int err;
692 field_t *son;
693 unsigned char *beg = NULL;
694
695 PRINT("%*.s%s\n", level * TAB_SIZE, " ", f->name);
696
697 /* Decode? */
698 base = (base && (f->attr & DECODE)) ? base + f->offset : NULL;
699
700 /* Decode the choice index number */
701 if ((f->attr & EXT) && get_bit(bs)) {
702 ext = 1;
703 type = get_bits(bs, 7) + f->lb;
704 } else {
705 ext = 0;
706 type = get_bits(bs, f->sz);
707 }
708
709 /* Write Type */
710 if (base)
711 *(unsigned *) base = type;
712
713 /* Check Range */
714 if (type >= f->ub) { /* Newer version? */
715 BYTE_ALIGN(bs);
716 len = get_len(bs);
717 CHECK_BOUND(bs, len);
718 bs->cur += len;
719 return H323_ERROR_NONE;
720 }
721
722 /* Transfer to son level */
723 son = &f->fields[type];
724 if (son->attr & STOP) {
725 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name);
726 return H323_ERROR_STOP;
727 }
728
729 if (ext || (son->attr & OPEN)) {
730 BYTE_ALIGN(bs);
731 len = get_len(bs);
732 CHECK_BOUND(bs, len);
733 if (!base || !(son->attr & DECODE)) {
734 PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ",
735 son->name);
736 bs->cur += len;
737 return H323_ERROR_NONE;
738 }
739 beg = bs->cur;
740
741 if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
742 H323_ERROR_NONE)
743 return err;
744
745 bs->cur = beg + len;
746 bs->bit = 0;
747 } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) <
748 H323_ERROR_NONE)
749 return err;
750
751 return H323_ERROR_NONE;
752}
753
754/****************************************************************************/
755int DecodeRasMessage(unsigned char *buf, size_t sz, RasMessage * ras)
756{
757 static field_t ras_message = {
758 FNAME("RasMessage") CHOICE, 5, 24, 32, DECODE | EXT,
759 0, _RasMessage
760 };
761 bitstr_t bs;
762
763 bs.buf = bs.beg = bs.cur = buf;
764 bs.end = buf + sz;
765 bs.bit = 0;
766
767 return decode_choice(&bs, &ras_message, (char *) ras, 0);
768}
769
770/****************************************************************************/
771static int DecodeH323_UserInformation(unsigned char *buf, unsigned char *beg,
772 size_t sz, H323_UserInformation * uuie)
773{
774 static field_t h323_userinformation = {
775 FNAME("H323-UserInformation") SEQ, 1, 2, 2, DECODE | EXT,
776 0, _H323_UserInformation
777 };
778 bitstr_t bs;
779
780 bs.buf = buf;
781 bs.beg = bs.cur = beg;
782 bs.end = beg + sz;
783 bs.bit = 0;
784
785 return decode_seq(&bs, &h323_userinformation, (char *) uuie, 0);
786}
787
788/****************************************************************************/
789int DecodeMultimediaSystemControlMessage(unsigned char *buf, size_t sz,
790 MultimediaSystemControlMessage *
791 mscm)
792{
793 static field_t multimediasystemcontrolmessage = {
794 FNAME("MultimediaSystemControlMessage") CHOICE, 2, 4, 4,
795 DECODE | EXT, 0, _MultimediaSystemControlMessage
796 };
797 bitstr_t bs;
798
799 bs.buf = bs.beg = bs.cur = buf;
800 bs.end = buf + sz;
801 bs.bit = 0;
802
803 return decode_choice(&bs, &multimediasystemcontrolmessage,
804 (char *) mscm, 0);
805}
806
807/****************************************************************************/
808int DecodeQ931(unsigned char *buf, size_t sz, Q931 * q931)
809{
810 unsigned char *p = buf;
811 int len;
812
813 if (!p || sz < 1)
814 return H323_ERROR_BOUND;
815
816 /* Protocol Discriminator */
817 if (*p != 0x08) {
818 PRINT("Unknown Protocol Discriminator\n");
819 return H323_ERROR_RANGE;
820 }
821 p++;
822 sz--;
823
824 /* CallReferenceValue */
825 if (sz < 1)
826 return H323_ERROR_BOUND;
827 len = *p++;
828 sz--;
829 if (sz < len)
830 return H323_ERROR_BOUND;
831 p += len;
832 sz -= len;
833
834 /* Message Type */
835 if (sz < 1)
836 return H323_ERROR_BOUND;
837 q931->MessageType = *p++;
838 PRINT("MessageType = %02X\n", q931->MessageType);
839 if (*p & 0x80) {
840 p++;
841 sz--;
842 }
843
844 /* Decode Information Elements */
845 while (sz > 0) {
846 if (*p == 0x7e) { /* UserUserIE */
847 if (sz < 3)
848 break;
849 p++;
850 len = *p++ << 8;
851 len |= *p++;
852 sz -= 3;
853 if (sz < len)
854 break;
855 p++;
856 len--;
857 return DecodeH323_UserInformation(buf, p, len,
858 &q931->UUIE);
859 }
860 p++;
861 sz--;
862 if (sz < 1)
863 break;
864 len = *p++;
865 if (sz < len)
866 break;
867 p += len;
868 sz -= len;
869 }
870
871 PRINT("Q.931 UUIE not found\n");
872
873 return H323_ERROR_BOUND;
874}
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
deleted file mode 100644
index 4b359618bedd..000000000000
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
+++ /dev/null
@@ -1,1926 +0,0 @@
1/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
2 *
3 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
4 *
5 * This source code is licensed under General Public License version 2.
6 */
7
8static field_t _TransportAddress_ipAddress[] = { /* SEQUENCE */
9 {FNAME("ip") OCTSTR, FIXD, 4, 0, DECODE,
10 offsetof(TransportAddress_ipAddress, ip), NULL},
11 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
12};
13
14static field_t _TransportAddress_ipSourceRoute_route[] = { /* SEQUENCE OF */
15 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
16};
17
18static field_t _TransportAddress_ipSourceRoute_routing[] = { /* CHOICE */
19 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
20 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
21};
22
23static field_t _TransportAddress_ipSourceRoute[] = { /* SEQUENCE */
24 {FNAME("ip") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
25 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
26 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
27 _TransportAddress_ipSourceRoute_route},
28 {FNAME("routing") CHOICE, 1, 2, 2, SKIP | EXT, 0,
29 _TransportAddress_ipSourceRoute_routing},
30};
31
32static field_t _TransportAddress_ipxAddress[] = { /* SEQUENCE */
33 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
34 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
35 {FNAME("port") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
36};
37
38static field_t _TransportAddress_ip6Address[] = { /* SEQUENCE */
39 {FNAME("ip") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
40 {FNAME("port") INT, WORD, 0, 0, SKIP, 0, NULL},
41};
42
43static field_t _H221NonStandard[] = { /* SEQUENCE */
44 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
45 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
46 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
47};
48
49static field_t _NonStandardIdentifier[] = { /* CHOICE */
50 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
51 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP | EXT, 0,
52 _H221NonStandard},
53};
54
55static field_t _NonStandardParameter[] = { /* SEQUENCE */
56 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP | EXT, 0,
57 _NonStandardIdentifier},
58 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
59};
60
61static field_t _TransportAddress[] = { /* CHOICE */
62 {FNAME("ipAddress") SEQ, 0, 2, 2, DECODE,
63 offsetof(TransportAddress, ipAddress), _TransportAddress_ipAddress},
64 {FNAME("ipSourceRoute") SEQ, 0, 4, 4, SKIP | EXT, 0,
65 _TransportAddress_ipSourceRoute},
66 {FNAME("ipxAddress") SEQ, 0, 3, 3, SKIP, 0,
67 _TransportAddress_ipxAddress},
68 {FNAME("ip6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
69 _TransportAddress_ip6Address},
70 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
71 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
72 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0,
73 _NonStandardParameter},
74};
75
76static field_t _AliasAddress[] = { /* CHOICE */
77 {FNAME("dialedDigits") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
78 {FNAME("h323-ID") BMPSTR, BYTE, 1, 0, SKIP, 0, NULL},
79 {FNAME("url-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
80 {FNAME("transportID") CHOICE, 3, 7, 7, SKIP | EXT, 0, NULL},
81 {FNAME("email-ID") IA5STR, WORD, 1, 0, SKIP, 0, NULL},
82 {FNAME("partyNumber") CHOICE, 3, 5, 5, SKIP | EXT, 0, NULL},
83 {FNAME("mobileUIM") CHOICE, 1, 2, 2, SKIP | EXT, 0, NULL},
84};
85
86static field_t _Setup_UUIE_sourceAddress[] = { /* SEQUENCE OF */
87 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
88};
89
90static field_t _VendorIdentifier[] = { /* SEQUENCE */
91 {FNAME("vendor") SEQ, 0, 3, 3, SKIP | EXT, 0, _H221NonStandard},
92 {FNAME("productId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
93 {FNAME("versionId") OCTSTR, BYTE, 1, 0, SKIP | OPT, 0, NULL},
94};
95
96static field_t _GatekeeperInfo[] = { /* SEQUENCE */
97 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
98 _NonStandardParameter},
99};
100
101static field_t _H310Caps[] = { /* SEQUENCE */
102 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
103 _NonStandardParameter},
104 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
105 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
106};
107
108static field_t _H320Caps[] = { /* SEQUENCE */
109 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
110 _NonStandardParameter},
111 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
112 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
113};
114
115static field_t _H321Caps[] = { /* SEQUENCE */
116 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
117 _NonStandardParameter},
118 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
119 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
120};
121
122static field_t _H322Caps[] = { /* SEQUENCE */
123 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
124 _NonStandardParameter},
125 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
126 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
127};
128
129static field_t _H323Caps[] = { /* SEQUENCE */
130 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
131 _NonStandardParameter},
132 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
133 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
134};
135
136static field_t _H324Caps[] = { /* SEQUENCE */
137 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
138 _NonStandardParameter},
139 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
140 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
141};
142
143static field_t _VoiceCaps[] = { /* SEQUENCE */
144 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
145 _NonStandardParameter},
146 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
147 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
148};
149
150static field_t _T120OnlyCaps[] = { /* SEQUENCE */
151 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
152 _NonStandardParameter},
153 {FNAME("dataRatesSupported") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
154 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, SKIP, 0, NULL},
155};
156
157static field_t _SupportedProtocols[] = { /* CHOICE */
158 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP, 0,
159 _NonStandardParameter},
160 {FNAME("h310") SEQ, 1, 1, 3, SKIP | EXT, 0, _H310Caps},
161 {FNAME("h320") SEQ, 1, 1, 3, SKIP | EXT, 0, _H320Caps},
162 {FNAME("h321") SEQ, 1, 1, 3, SKIP | EXT, 0, _H321Caps},
163 {FNAME("h322") SEQ, 1, 1, 3, SKIP | EXT, 0, _H322Caps},
164 {FNAME("h323") SEQ, 1, 1, 3, SKIP | EXT, 0, _H323Caps},
165 {FNAME("h324") SEQ, 1, 1, 3, SKIP | EXT, 0, _H324Caps},
166 {FNAME("voice") SEQ, 1, 1, 3, SKIP | EXT, 0, _VoiceCaps},
167 {FNAME("t120-only") SEQ, 1, 1, 3, SKIP | EXT, 0, _T120OnlyCaps},
168 {FNAME("nonStandardProtocol") SEQ, 2, 3, 3, SKIP | EXT, 0, NULL},
169 {FNAME("t38FaxAnnexbOnly") SEQ, 2, 5, 5, SKIP | EXT, 0, NULL},
170};
171
172static field_t _GatewayInfo_protocol[] = { /* SEQUENCE OF */
173 {FNAME("item") CHOICE, 4, 9, 11, SKIP | EXT, 0, _SupportedProtocols},
174};
175
176static field_t _GatewayInfo[] = { /* SEQUENCE */
177 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
178 _GatewayInfo_protocol},
179 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
180 _NonStandardParameter},
181};
182
183static field_t _McuInfo[] = { /* SEQUENCE */
184 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
185 _NonStandardParameter},
186 {FNAME("protocol") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
187};
188
189static field_t _TerminalInfo[] = { /* SEQUENCE */
190 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
191 _NonStandardParameter},
192};
193
194static field_t _EndpointType[] = { /* SEQUENCE */
195 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
196 _NonStandardParameter},
197 {FNAME("vendor") SEQ, 2, 3, 3, SKIP | EXT | OPT, 0,
198 _VendorIdentifier},
199 {FNAME("gatekeeper") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0,
200 _GatekeeperInfo},
201 {FNAME("gateway") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, _GatewayInfo},
202 {FNAME("mcu") SEQ, 1, 1, 2, SKIP | EXT | OPT, 0, _McuInfo},
203 {FNAME("terminal") SEQ, 1, 1, 1, SKIP | EXT | OPT, 0, _TerminalInfo},
204 {FNAME("mc") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
205 {FNAME("undefinedNode") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
206 {FNAME("set") BITSTR, FIXD, 32, 0, SKIP | OPT, 0, NULL},
207 {FNAME("supportedTunnelledProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT,
208 0, NULL},
209};
210
211static field_t _Setup_UUIE_destinationAddress[] = { /* SEQUENCE OF */
212 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
213};
214
215static field_t _Setup_UUIE_destExtraCallInfo[] = { /* SEQUENCE OF */
216 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
217};
218
219static field_t _Setup_UUIE_destExtraCRV[] = { /* SEQUENCE OF */
220 {FNAME("item") INT, WORD, 0, 0, SKIP, 0, NULL},
221};
222
223static field_t _Setup_UUIE_conferenceGoal[] = { /* CHOICE */
224 {FNAME("create") NUL, FIXD, 0, 0, SKIP, 0, NULL},
225 {FNAME("join") NUL, FIXD, 0, 0, SKIP, 0, NULL},
226 {FNAME("invite") NUL, FIXD, 0, 0, SKIP, 0, NULL},
227 {FNAME("capability-negotiation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
228 {FNAME("callIndependentSupplementaryService") NUL, FIXD, 0, 0, SKIP,
229 0, NULL},
230};
231
232static field_t _Q954Details[] = { /* SEQUENCE */
233 {FNAME("conferenceCalling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
234 {FNAME("threePartyService") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
235};
236
237static field_t _QseriesOptions[] = { /* SEQUENCE */
238 {FNAME("q932Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
239 {FNAME("q951Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
240 {FNAME("q952Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
241 {FNAME("q953Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
242 {FNAME("q955Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
243 {FNAME("q956Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
244 {FNAME("q957Full") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
245 {FNAME("q954Info") SEQ, 0, 2, 2, SKIP | EXT, 0, _Q954Details},
246};
247
248static field_t _CallType[] = { /* CHOICE */
249 {FNAME("pointToPoint") NUL, FIXD, 0, 0, SKIP, 0, NULL},
250 {FNAME("oneToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
251 {FNAME("nToOne") NUL, FIXD, 0, 0, SKIP, 0, NULL},
252 {FNAME("nToN") NUL, FIXD, 0, 0, SKIP, 0, NULL},
253};
254
255static field_t _H245_NonStandardIdentifier_h221NonStandard[] = { /* SEQUENCE */
256 {FNAME("t35CountryCode") INT, BYTE, 0, 0, SKIP, 0, NULL},
257 {FNAME("t35Extension") INT, BYTE, 0, 0, SKIP, 0, NULL},
258 {FNAME("manufacturerCode") INT, WORD, 0, 0, SKIP, 0, NULL},
259};
260
261static field_t _H245_NonStandardIdentifier[] = { /* CHOICE */
262 {FNAME("object") OID, BYTE, 0, 0, SKIP, 0, NULL},
263 {FNAME("h221NonStandard") SEQ, 0, 3, 3, SKIP, 0,
264 _H245_NonStandardIdentifier_h221NonStandard},
265};
266
267static field_t _H245_NonStandardParameter[] = { /* SEQUENCE */
268 {FNAME("nonStandardIdentifier") CHOICE, 1, 2, 2, SKIP, 0,
269 _H245_NonStandardIdentifier},
270 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
271};
272
273static field_t _H261VideoCapability[] = { /* SEQUENCE */
274 {FNAME("qcifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
275 {FNAME("cifMPI") INT, 2, 1, 0, SKIP | OPT, 0, NULL},
276 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
277 NULL},
278 {FNAME("maxBitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
279 {FNAME("stillImageTransmission") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
280 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
281};
282
283static field_t _H262VideoCapability[] = { /* SEQUENCE */
284 {FNAME("profileAndLevel-SPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
285 {FNAME("profileAndLevel-MPatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
286 {FNAME("profileAndLevel-MPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
287 {FNAME("profileAndLevel-MPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
288 {FNAME("profileAndLevel-MPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
289 {FNAME("profileAndLevel-SNRatLL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
290 {FNAME("profileAndLevel-SNRatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
291 {FNAME("profileAndLevel-SpatialatH-14") BOOL, FIXD, 0, 0, SKIP, 0,
292 NULL},
293 {FNAME("profileAndLevel-HPatML") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
294 {FNAME("profileAndLevel-HPatH-14") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
295 {FNAME("profileAndLevel-HPatHL") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
296 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
297 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
298 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
299 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
300 {FNAME("framesPerSecond") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
301 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
302 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
303};
304
305static field_t _H263VideoCapability[] = { /* SEQUENCE */
306 {FNAME("sqcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
307 {FNAME("qcifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
308 {FNAME("cifMPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
309 {FNAME("cif4MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
310 {FNAME("cif16MPI") INT, 5, 1, 0, SKIP | OPT, 0, NULL},
311 {FNAME("maxBitRate") INT, CONS, 1, 0, SKIP, 0, NULL},
312 {FNAME("unrestrictedVector") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
313 {FNAME("arithmeticCoding") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
314 {FNAME("advancedPrediction") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
315 {FNAME("pbFrames") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
316 {FNAME("temporalSpatialTradeOffCapability") BOOL, FIXD, 0, 0, SKIP, 0,
317 NULL},
318 {FNAME("hrd-B") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
319 {FNAME("bppMaxKb") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
320 {FNAME("slowSqcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
321 {FNAME("slowQcifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
322 {FNAME("slowCifMPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
323 {FNAME("slowCif4MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
324 {FNAME("slowCif16MPI") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
325 {FNAME("errorCompensation") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
326 {FNAME("enhancementLayerInfo") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0,
327 NULL},
328 {FNAME("h263Options") SEQ, 5, 29, 31, SKIP | EXT | OPT, 0, NULL},
329};
330
331static field_t _IS11172VideoCapability[] = { /* SEQUENCE */
332 {FNAME("constrainedBitstream") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
333 {FNAME("videoBitRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
334 {FNAME("vbvBufferSize") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
335 {FNAME("samplesPerLine") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
336 {FNAME("linesPerFrame") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
337 {FNAME("pictureRate") INT, 4, 0, 0, SKIP | OPT, 0, NULL},
338 {FNAME("luminanceSampleRate") INT, CONS, 0, 0, SKIP | OPT, 0, NULL},
339 {FNAME("videoBadMBsCap") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
340};
341
342static field_t _VideoCapability[] = { /* CHOICE */
343 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
344 _H245_NonStandardParameter},
345 {FNAME("h261VideoCapability") SEQ, 2, 5, 6, SKIP | EXT, 0,
346 _H261VideoCapability},
347 {FNAME("h262VideoCapability") SEQ, 6, 17, 18, SKIP | EXT, 0,
348 _H262VideoCapability},
349 {FNAME("h263VideoCapability") SEQ, 7, 13, 21, SKIP | EXT, 0,
350 _H263VideoCapability},
351 {FNAME("is11172VideoCapability") SEQ, 6, 7, 8, SKIP | EXT, 0,
352 _IS11172VideoCapability},
353 {FNAME("genericVideoCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
354};
355
356static field_t _AudioCapability_g7231[] = { /* SEQUENCE */
357 {FNAME("maxAl-sduAudioFrames") INT, BYTE, 1, 0, SKIP, 0, NULL},
358 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
359};
360
361static field_t _IS11172AudioCapability[] = { /* SEQUENCE */
362 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
363 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
364 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
365 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
366 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
367 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
368 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
369 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
370 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
371};
372
373static field_t _IS13818AudioCapability[] = { /* SEQUENCE */
374 {FNAME("audioLayer1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
375 {FNAME("audioLayer2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
376 {FNAME("audioLayer3") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
377 {FNAME("audioSampling16k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
378 {FNAME("audioSampling22k05") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
379 {FNAME("audioSampling24k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
380 {FNAME("audioSampling32k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
381 {FNAME("audioSampling44k1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
382 {FNAME("audioSampling48k") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
383 {FNAME("singleChannel") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
384 {FNAME("twoChannels") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
385 {FNAME("threeChannels2-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
386 {FNAME("threeChannels3-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
387 {FNAME("fourChannels2-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
388 {FNAME("fourChannels2-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
389 {FNAME("fourChannels3-1") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
390 {FNAME("fiveChannels3-0-2-0") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
391 {FNAME("fiveChannels3-2") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
392 {FNAME("lowFrequencyEnhancement") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
393 {FNAME("multilingual") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
394 {FNAME("bitRate") INT, WORD, 1, 0, SKIP, 0, NULL},
395};
396
397static field_t _AudioCapability[] = { /* CHOICE */
398 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
399 _H245_NonStandardParameter},
400 {FNAME("g711Alaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
401 {FNAME("g711Alaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
402 {FNAME("g711Ulaw64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
403 {FNAME("g711Ulaw56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
404 {FNAME("g722-64k") INT, BYTE, 1, 0, SKIP, 0, NULL},
405 {FNAME("g722-56k") INT, BYTE, 1, 0, SKIP, 0, NULL},
406 {FNAME("g722-48k") INT, BYTE, 1, 0, SKIP, 0, NULL},
407 {FNAME("g7231") SEQ, 0, 2, 2, SKIP, 0, _AudioCapability_g7231},
408 {FNAME("g728") INT, BYTE, 1, 0, SKIP, 0, NULL},
409 {FNAME("g729") INT, BYTE, 1, 0, SKIP, 0, NULL},
410 {FNAME("g729AnnexA") INT, BYTE, 1, 0, SKIP, 0, NULL},
411 {FNAME("is11172AudioCapability") SEQ, 0, 9, 9, SKIP | EXT, 0,
412 _IS11172AudioCapability},
413 {FNAME("is13818AudioCapability") SEQ, 0, 21, 21, SKIP | EXT, 0,
414 _IS13818AudioCapability},
415 {FNAME("g729wAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
416 {FNAME("g729AnnexAwAnnexB") INT, BYTE, 1, 0, SKIP, 0, NULL},
417 {FNAME("g7231AnnexCCapability") SEQ, 1, 3, 3, SKIP | EXT, 0, NULL},
418 {FNAME("gsmFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
419 {FNAME("gsmHalfRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
420 {FNAME("gsmEnhancedFullRate") SEQ, 0, 3, 3, SKIP | EXT, 0, NULL},
421 {FNAME("genericAudioCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
422 {FNAME("g729Extensions") SEQ, 1, 8, 8, SKIP | EXT, 0, NULL},
423};
424
425static field_t _DataProtocolCapability[] = { /* CHOICE */
426 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
427 _H245_NonStandardParameter},
428 {FNAME("v14buffered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
429 {FNAME("v42lapm") NUL, FIXD, 0, 0, SKIP, 0, NULL},
430 {FNAME("hdlcFrameTunnelling") NUL, FIXD, 0, 0, SKIP, 0, NULL},
431 {FNAME("h310SeparateVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
432 {FNAME("h310SingleVCStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
433 {FNAME("transparent") NUL, FIXD, 0, 0, SKIP, 0, NULL},
434 {FNAME("segmentationAndReassembly") NUL, FIXD, 0, 0, SKIP, 0, NULL},
435 {FNAME("hdlcFrameTunnelingwSAR") NUL, FIXD, 0, 0, SKIP, 0, NULL},
436 {FNAME("v120") NUL, FIXD, 0, 0, SKIP, 0, NULL},
437 {FNAME("separateLANStack") NUL, FIXD, 0, 0, SKIP, 0, NULL},
438 {FNAME("v76wCompression") CHOICE, 2, 3, 3, SKIP | EXT, 0, NULL},
439 {FNAME("tcp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
440 {FNAME("udp") NUL, FIXD, 0, 0, SKIP, 0, NULL},
441};
442
443static field_t _T84Profile_t84Restricted[] = { /* SEQUENCE */
444 {FNAME("qcif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
445 {FNAME("cif") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
446 {FNAME("ccir601Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
447 {FNAME("ccir601Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
448 {FNAME("hdtvSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
449 {FNAME("hdtvProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
450 {FNAME("g3FacsMH200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
451 {FNAME("g3FacsMH200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
452 {FNAME("g4FacsMMR200x100") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
453 {FNAME("g4FacsMMR200x200") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
454 {FNAME("jbig200x200Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
455 {FNAME("jbig200x200Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
456 {FNAME("jbig300x300Seq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
457 {FNAME("jbig300x300Prog") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
458 {FNAME("digPhotoLow") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
459 {FNAME("digPhotoMedSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
460 {FNAME("digPhotoMedProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
461 {FNAME("digPhotoHighSeq") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
462 {FNAME("digPhotoHighProg") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
463};
464
465static field_t _T84Profile[] = { /* CHOICE */
466 {FNAME("t84Unrestricted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
467 {FNAME("t84Restricted") SEQ, 0, 19, 19, SKIP | EXT, 0,
468 _T84Profile_t84Restricted},
469};
470
471static field_t _DataApplicationCapability_application_t84[] = { /* SEQUENCE */
472 {FNAME("t84Protocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
473 _DataProtocolCapability},
474 {FNAME("t84Profile") CHOICE, 1, 2, 2, SKIP, 0, _T84Profile},
475};
476
477static field_t _DataApplicationCapability_application_nlpid[] = { /* SEQUENCE */
478 {FNAME("nlpidProtocol") CHOICE, 3, 7, 14, SKIP | EXT, 0,
479 _DataProtocolCapability},
480 {FNAME("nlpidData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
481};
482
483static field_t _DataApplicationCapability_application[] = { /* CHOICE */
484 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
485 _H245_NonStandardParameter},
486 {FNAME("t120") CHOICE, 3, 7, 14, DECODE | EXT,
487 offsetof(DataApplicationCapability_application, t120),
488 _DataProtocolCapability},
489 {FNAME("dsm-cc") CHOICE, 3, 7, 14, SKIP | EXT, 0,
490 _DataProtocolCapability},
491 {FNAME("userData") CHOICE, 3, 7, 14, SKIP | EXT, 0,
492 _DataProtocolCapability},
493 {FNAME("t84") SEQ, 0, 2, 2, SKIP, 0,
494 _DataApplicationCapability_application_t84},
495 {FNAME("t434") CHOICE, 3, 7, 14, SKIP | EXT, 0,
496 _DataProtocolCapability},
497 {FNAME("h224") CHOICE, 3, 7, 14, SKIP | EXT, 0,
498 _DataProtocolCapability},
499 {FNAME("nlpid") SEQ, 0, 2, 2, SKIP, 0,
500 _DataApplicationCapability_application_nlpid},
501 {FNAME("dsvdControl") NUL, FIXD, 0, 0, SKIP, 0, NULL},
502 {FNAME("h222DataPartitioning") CHOICE, 3, 7, 14, SKIP | EXT, 0,
503 _DataProtocolCapability},
504 {FNAME("t30fax") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
505 {FNAME("t140") CHOICE, 3, 7, 14, SKIP | EXT, 0, NULL},
506 {FNAME("t38fax") SEQ, 0, 2, 2, SKIP, 0, NULL},
507 {FNAME("genericDataCapability") SEQ, 5, 6, 6, SKIP | EXT, 0, NULL},
508};
509
510static field_t _DataApplicationCapability[] = { /* SEQUENCE */
511 {FNAME("application") CHOICE, 4, 10, 14, DECODE | EXT,
512 offsetof(DataApplicationCapability, application),
513 _DataApplicationCapability_application},
514 {FNAME("maxBitRate") INT, CONS, 0, 0, SKIP, 0, NULL},
515};
516
517static field_t _EncryptionMode[] = { /* CHOICE */
518 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
519 _H245_NonStandardParameter},
520 {FNAME("h233Encryption") NUL, FIXD, 0, 0, SKIP, 0, NULL},
521};
522
523static field_t _DataType[] = { /* CHOICE */
524 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
525 _H245_NonStandardParameter},
526 {FNAME("nullData") NUL, FIXD, 0, 0, SKIP, 0, NULL},
527 {FNAME("videoData") CHOICE, 3, 5, 6, SKIP | EXT, 0, _VideoCapability},
528 {FNAME("audioData") CHOICE, 4, 14, 22, SKIP | EXT, 0,
529 _AudioCapability},
530 {FNAME("data") SEQ, 0, 2, 2, DECODE | EXT, offsetof(DataType, data),
531 _DataApplicationCapability},
532 {FNAME("encryptionData") CHOICE, 1, 2, 2, SKIP | EXT, 0,
533 _EncryptionMode},
534 {FNAME("h235Control") SEQ, 0, 2, 2, SKIP, 0, NULL},
535 {FNAME("h235Media") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
536 {FNAME("multiplexedStream") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
537};
538
539static field_t _H222LogicalChannelParameters[] = { /* SEQUENCE */
540 {FNAME("resourceID") INT, WORD, 0, 0, SKIP, 0, NULL},
541 {FNAME("subChannelID") INT, WORD, 0, 0, SKIP, 0, NULL},
542 {FNAME("pcr-pid") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
543 {FNAME("programDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
544 {FNAME("streamDescriptors") OCTSTR, SEMI, 0, 0, SKIP | OPT, 0, NULL},
545};
546
547static field_t _H223LogicalChannelParameters_adaptationLayerType_al3[] = { /* SEQUENCE */
548 {FNAME("controlFieldOctets") INT, 2, 0, 0, SKIP, 0, NULL},
549 {FNAME("sendBufferSize") INT, CONS, 0, 0, SKIP, 0, NULL},
550};
551
552static field_t _H223LogicalChannelParameters_adaptationLayerType[] = { /* CHOICE */
553 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0,
554 _H245_NonStandardParameter},
555 {FNAME("al1Framed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
556 {FNAME("al1NotFramed") NUL, FIXD, 0, 0, SKIP, 0, NULL},
557 {FNAME("al2WithoutSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
558 {FNAME("al2WithSequenceNumbers") NUL, FIXD, 0, 0, SKIP, 0, NULL},
559 {FNAME("al3") SEQ, 0, 2, 2, SKIP, 0,
560 _H223LogicalChannelParameters_adaptationLayerType_al3},
561 {FNAME("al1M") SEQ, 0, 7, 8, SKIP | EXT, 0, NULL},
562 {FNAME("al2M") SEQ, 0, 2, 2, SKIP | EXT, 0, NULL},
563 {FNAME("al3M") SEQ, 0, 5, 6, SKIP | EXT, 0, NULL},
564};
565
566static field_t _H223LogicalChannelParameters[] = { /* SEQUENCE */
567 {FNAME("adaptationLayerType") CHOICE, 3, 6, 9, SKIP | EXT, 0,
568 _H223LogicalChannelParameters_adaptationLayerType},
569 {FNAME("segmentableFlag") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
570};
571
572static field_t _CRCLength[] = { /* CHOICE */
573 {FNAME("crc8bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
574 {FNAME("crc16bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
575 {FNAME("crc32bit") NUL, FIXD, 0, 0, SKIP, 0, NULL},
576};
577
578static field_t _V76HDLCParameters[] = { /* SEQUENCE */
579 {FNAME("crcLength") CHOICE, 2, 3, 3, SKIP | EXT, 0, _CRCLength},
580 {FNAME("n401") INT, WORD, 1, 0, SKIP, 0, NULL},
581 {FNAME("loopbackTestProcedure") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
582};
583
584static field_t _V76LogicalChannelParameters_suspendResume[] = { /* CHOICE */
585 {FNAME("noSuspendResume") NUL, FIXD, 0, 0, SKIP, 0, NULL},
586 {FNAME("suspendResumewAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
587 {FNAME("suspendResumewoAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
588};
589
590static field_t _V76LogicalChannelParameters_mode_eRM_recovery[] = { /* CHOICE */
591 {FNAME("rej") NUL, FIXD, 0, 0, SKIP, 0, NULL},
592 {FNAME("sREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
593 {FNAME("mSREJ") NUL, FIXD, 0, 0, SKIP, 0, NULL},
594};
595
596static field_t _V76LogicalChannelParameters_mode_eRM[] = { /* SEQUENCE */
597 {FNAME("windowSize") INT, 7, 1, 0, SKIP, 0, NULL},
598 {FNAME("recovery") CHOICE, 2, 3, 3, SKIP | EXT, 0,
599 _V76LogicalChannelParameters_mode_eRM_recovery},
600};
601
602static field_t _V76LogicalChannelParameters_mode[] = { /* CHOICE */
603 {FNAME("eRM") SEQ, 0, 2, 2, SKIP | EXT, 0,
604 _V76LogicalChannelParameters_mode_eRM},
605 {FNAME("uNERM") NUL, FIXD, 0, 0, SKIP, 0, NULL},
606};
607
608static field_t _V75Parameters[] = { /* SEQUENCE */
609 {FNAME("audioHeaderPresent") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
610};
611
612static field_t _V76LogicalChannelParameters[] = { /* SEQUENCE */
613 {FNAME("hdlcParameters") SEQ, 0, 3, 3, SKIP | EXT, 0,
614 _V76HDLCParameters},
615 {FNAME("suspendResume") CHOICE, 2, 3, 3, SKIP | EXT, 0,
616 _V76LogicalChannelParameters_suspendResume},
617 {FNAME("uIH") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
618 {FNAME("mode") CHOICE, 1, 2, 2, SKIP | EXT, 0,
619 _V76LogicalChannelParameters_mode},
620 {FNAME("v75Parameters") SEQ, 0, 1, 1, SKIP | EXT, 0, _V75Parameters},
621};
622
623static field_t _H2250LogicalChannelParameters_nonStandard[] = { /* SEQUENCE OF */
624 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
625};
626
627static field_t _UnicastAddress_iPAddress[] = { /* SEQUENCE */
628 {FNAME("network") OCTSTR, FIXD, 4, 0, DECODE,
629 offsetof(UnicastAddress_iPAddress, network), NULL},
630 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
631};
632
633static field_t _UnicastAddress_iPXAddress[] = { /* SEQUENCE */
634 {FNAME("node") OCTSTR, FIXD, 6, 0, SKIP, 0, NULL},
635 {FNAME("netnum") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
636 {FNAME("tsapIdentifier") OCTSTR, FIXD, 2, 0, SKIP, 0, NULL},
637};
638
639static field_t _UnicastAddress_iP6Address[] = { /* SEQUENCE */
640 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
641 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
642};
643
644static field_t _UnicastAddress_iPSourceRouteAddress_routing[] = { /* CHOICE */
645 {FNAME("strict") NUL, FIXD, 0, 0, SKIP, 0, NULL},
646 {FNAME("loose") NUL, FIXD, 0, 0, SKIP, 0, NULL},
647};
648
649static field_t _UnicastAddress_iPSourceRouteAddress_route[] = { /* SEQUENCE OF */
650 {FNAME("item") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
651};
652
653static field_t _UnicastAddress_iPSourceRouteAddress[] = { /* SEQUENCE */
654 {FNAME("routing") CHOICE, 1, 2, 2, SKIP, 0,
655 _UnicastAddress_iPSourceRouteAddress_routing},
656 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
657 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
658 {FNAME("route") SEQOF, SEMI, 0, 0, SKIP, 0,
659 _UnicastAddress_iPSourceRouteAddress_route},
660};
661
662static field_t _UnicastAddress[] = { /* CHOICE */
663 {FNAME("iPAddress") SEQ, 0, 2, 2, DECODE | EXT,
664 offsetof(UnicastAddress, iPAddress), _UnicastAddress_iPAddress},
665 {FNAME("iPXAddress") SEQ, 0, 3, 3, SKIP | EXT, 0,
666 _UnicastAddress_iPXAddress},
667 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
668 _UnicastAddress_iP6Address},
669 {FNAME("netBios") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
670 {FNAME("iPSourceRouteAddress") SEQ, 0, 4, 4, SKIP | EXT, 0,
671 _UnicastAddress_iPSourceRouteAddress},
672 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
673 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
674};
675
676static field_t _MulticastAddress_iPAddress[] = { /* SEQUENCE */
677 {FNAME("network") OCTSTR, FIXD, 4, 0, SKIP, 0, NULL},
678 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
679};
680
681static field_t _MulticastAddress_iP6Address[] = { /* SEQUENCE */
682 {FNAME("network") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
683 {FNAME("tsapIdentifier") INT, WORD, 0, 0, SKIP, 0, NULL},
684};
685
686static field_t _MulticastAddress[] = { /* CHOICE */
687 {FNAME("iPAddress") SEQ, 0, 2, 2, SKIP | EXT, 0,
688 _MulticastAddress_iPAddress},
689 {FNAME("iP6Address") SEQ, 0, 2, 2, SKIP | EXT, 0,
690 _MulticastAddress_iP6Address},
691 {FNAME("nsap") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
692 {FNAME("nonStandardAddress") SEQ, 0, 2, 2, SKIP, 0, NULL},
693};
694
695static field_t _H245_TransportAddress[] = { /* CHOICE */
696 {FNAME("unicastAddress") CHOICE, 3, 5, 7, DECODE | EXT,
697 offsetof(H245_TransportAddress, unicastAddress), _UnicastAddress},
698 {FNAME("multicastAddress") CHOICE, 1, 2, 4, SKIP | EXT, 0,
699 _MulticastAddress},
700};
701
702static field_t _H2250LogicalChannelParameters[] = { /* SEQUENCE */
703 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
704 _H2250LogicalChannelParameters_nonStandard},
705 {FNAME("sessionID") INT, BYTE, 0, 0, SKIP, 0, NULL},
706 {FNAME("associatedSessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
707 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
708 offsetof(H2250LogicalChannelParameters, mediaChannel),
709 _H245_TransportAddress},
710 {FNAME("mediaGuaranteedDelivery") BOOL, FIXD, 0, 0, SKIP | OPT, 0,
711 NULL},
712 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
713 offsetof(H2250LogicalChannelParameters, mediaControlChannel),
714 _H245_TransportAddress},
715 {FNAME("mediaControlGuaranteedDelivery") BOOL, FIXD, 0, 0, STOP | OPT,
716 0, NULL},
717 {FNAME("silenceSuppression") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
718 {FNAME("destination") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
719 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, STOP | OPT, 0, NULL},
720 {FNAME("mediaPacketization") CHOICE, 0, 1, 2, STOP | EXT | OPT, 0,
721 NULL},
722 {FNAME("transportCapability") SEQ, 3, 3, 3, STOP | EXT | OPT, 0,
723 NULL},
724 {FNAME("redundancyEncoding") SEQ, 1, 2, 2, STOP | EXT | OPT, 0, NULL},
725 {FNAME("source") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0, NULL},
726};
727
728static field_t _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
729 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
730 _H222LogicalChannelParameters},
731 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
732 _H223LogicalChannelParameters},
733 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
734 _V76LogicalChannelParameters},
735 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
736 offsetof
737 (OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters,
738 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
739 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
740};
741
742static field_t _OpenLogicalChannel_forwardLogicalChannelParameters[] = { /* SEQUENCE */
743 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
744 {FNAME("dataType") CHOICE, 3, 6, 9, DECODE | EXT,
745 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
746 dataType), _DataType},
747 {FNAME("multiplexParameters") CHOICE, 2, 3, 5, DECODE | EXT,
748 offsetof(OpenLogicalChannel_forwardLogicalChannelParameters,
749 multiplexParameters),
750 _OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters},
751 {FNAME("forwardLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
752 0, NULL},
753 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
754};
755
756static field_t _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
757 {FNAME("h223LogicalChannelParameters") SEQ, 0, 2, 2, SKIP | EXT, 0,
758 _H223LogicalChannelParameters},
759 {FNAME("v76LogicalChannelParameters") SEQ, 0, 5, 5, SKIP | EXT, 0,
760 _V76LogicalChannelParameters},
761 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
762 offsetof
763 (OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters,
764 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
765};
766
767static field_t _OpenLogicalChannel_reverseLogicalChannelParameters[] = { /* SEQUENCE */
768 {FNAME("dataType") CHOICE, 3, 6, 9, SKIP | EXT, 0, _DataType},
769 {FNAME("multiplexParameters") CHOICE, 1, 2, 3, DECODE | EXT | OPT,
770 offsetof(OpenLogicalChannel_reverseLogicalChannelParameters,
771 multiplexParameters),
772 _OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters},
773 {FNAME("reverseLogicalChannelDependency") INT, WORD, 1, 0, SKIP | OPT,
774 0, NULL},
775 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
776};
777
778static field_t _NetworkAccessParameters_distribution[] = { /* CHOICE */
779 {FNAME("unicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
780 {FNAME("multicast") NUL, FIXD, 0, 0, SKIP, 0, NULL},
781};
782
783static field_t _Q2931Address_address[] = { /* CHOICE */
784 {FNAME("internationalNumber") NUMSTR, 4, 1, 0, SKIP, 0, NULL},
785 {FNAME("nsapAddress") OCTSTR, 5, 1, 0, SKIP, 0, NULL},
786};
787
788static field_t _Q2931Address[] = { /* SEQUENCE */
789 {FNAME("address") CHOICE, 1, 2, 2, SKIP | EXT, 0,
790 _Q2931Address_address},
791 {FNAME("subaddress") OCTSTR, 5, 1, 0, SKIP | OPT, 0, NULL},
792};
793
794static field_t _NetworkAccessParameters_networkAddress[] = { /* CHOICE */
795 {FNAME("q2931Address") SEQ, 1, 2, 2, SKIP | EXT, 0, _Q2931Address},
796 {FNAME("e164Address") NUMDGT, 7, 1, 0, SKIP, 0, NULL},
797 {FNAME("localAreaAddress") CHOICE, 1, 2, 2, DECODE | EXT,
798 offsetof(NetworkAccessParameters_networkAddress, localAreaAddress),
799 _H245_TransportAddress},
800};
801
802static field_t _NetworkAccessParameters[] = { /* SEQUENCE */
803 {FNAME("distribution") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0,
804 _NetworkAccessParameters_distribution},
805 {FNAME("networkAddress") CHOICE, 2, 3, 3, DECODE | EXT,
806 offsetof(NetworkAccessParameters, networkAddress),
807 _NetworkAccessParameters_networkAddress},
808 {FNAME("associateConference") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
809 {FNAME("externalReference") OCTSTR, 8, 1, 0, SKIP | OPT, 0, NULL},
810 {FNAME("t120SetupProcedure") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
811 NULL},
812};
813
814static field_t _OpenLogicalChannel[] = { /* SEQUENCE */
815 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
816 {FNAME("forwardLogicalChannelParameters") SEQ, 1, 3, 5, DECODE | EXT,
817 offsetof(OpenLogicalChannel, forwardLogicalChannelParameters),
818 _OpenLogicalChannel_forwardLogicalChannelParameters},
819 {FNAME("reverseLogicalChannelParameters") SEQ, 1, 2, 4,
820 DECODE | EXT | OPT, offsetof(OpenLogicalChannel,
821 reverseLogicalChannelParameters),
822 _OpenLogicalChannel_reverseLogicalChannelParameters},
823 {FNAME("separateStack") SEQ, 2, 4, 5, DECODE | EXT | OPT,
824 offsetof(OpenLogicalChannel, separateStack),
825 _NetworkAccessParameters},
826 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
827};
828
829static field_t _Setup_UUIE_fastStart[] = { /* SEQUENCE OF */
830 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
831 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
832 ,
833};
834
835static field_t _Setup_UUIE[] = { /* SEQUENCE */
836 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
837 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
838 offsetof(Setup_UUIE, h245Address), _TransportAddress},
839 {FNAME("sourceAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
840 _Setup_UUIE_sourceAddress},
841 {FNAME("sourceInfo") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
842 {FNAME("destinationAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
843 _Setup_UUIE_destinationAddress},
844 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
845 offsetof(Setup_UUIE, destCallSignalAddress), _TransportAddress},
846 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
847 _Setup_UUIE_destExtraCallInfo},
848 {FNAME("destExtraCRV") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
849 _Setup_UUIE_destExtraCRV},
850 {FNAME("activeMC") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
851 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
852 {FNAME("conferenceGoal") CHOICE, 2, 3, 5, SKIP | EXT, 0,
853 _Setup_UUIE_conferenceGoal},
854 {FNAME("callServices") SEQ, 0, 8, 8, SKIP | EXT | OPT, 0,
855 _QseriesOptions},
856 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
857 {FNAME("sourceCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
858 offsetof(Setup_UUIE, sourceCallSignalAddress), _TransportAddress},
859 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
860 NULL},
861 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
862 {FNAME("h245SecurityCapability") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
863 NULL},
864 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
865 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
866 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
867 offsetof(Setup_UUIE, fastStart), _Setup_UUIE_fastStart},
868 {FNAME("mediaWaitForConnect") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
869 {FNAME("canOverlapSend") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
870 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
871 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
872 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
873 {FNAME("connectionParameters") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0,
874 NULL},
875 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
876 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
877 NULL},
878 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
879 NULL},
880 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
881 {FNAME("symmetricOperationRequired") NUL, FIXD, 0, 0, SKIP | OPT, 0,
882 NULL},
883 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
884 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
885 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
886 {FNAME("neededFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
887 {FNAME("desiredFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
888 {FNAME("supportedFeatures") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
889 {FNAME("parallelH245Control") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
890 {FNAME("additionalSourceAddresses") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
891 NULL},
892};
893
894static field_t _CallProceeding_UUIE_fastStart[] = { /* SEQUENCE OF */
895 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
896 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
897 ,
898};
899
900static field_t _CallProceeding_UUIE[] = { /* SEQUENCE */
901 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
902 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
903 _EndpointType},
904 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
905 offsetof(CallProceeding_UUIE, h245Address), _TransportAddress},
906 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
907 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
908 NULL},
909 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
910 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
911 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
912 offsetof(CallProceeding_UUIE, fastStart),
913 _CallProceeding_UUIE_fastStart},
914 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
915 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
916 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
917 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
918};
919
920static field_t _Connect_UUIE_fastStart[] = { /* SEQUENCE OF */
921 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
922 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
923 ,
924};
925
926static field_t _Connect_UUIE[] = { /* SEQUENCE */
927 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
928 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
929 offsetof(Connect_UUIE, h245Address), _TransportAddress},
930 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
931 _EndpointType},
932 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
933 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
934 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
935 NULL},
936 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
937 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
938 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
939 offsetof(Connect_UUIE, fastStart), _Connect_UUIE_fastStart},
940 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
941 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
942 {FNAME("language") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
943 {FNAME("connectedAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
944 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
945 NULL},
946 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
947 NULL},
948 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
949 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
950 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
951 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
952};
953
954static field_t _Alerting_UUIE_fastStart[] = { /* SEQUENCE OF */
955 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
956 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
957 ,
958};
959
960static field_t _Alerting_UUIE[] = { /* SEQUENCE */
961 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
962 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
963 _EndpointType},
964 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
965 offsetof(Alerting_UUIE, h245Address), _TransportAddress},
966 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
967 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
968 NULL},
969 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
970 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
971 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
972 offsetof(Alerting_UUIE, fastStart), _Alerting_UUIE_fastStart},
973 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
974 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
975 {FNAME("alertingAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
976 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
977 NULL},
978 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
979 NULL},
980 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
981 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
982 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
983 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
984};
985
986static field_t _Information_UUIE_fastStart[] = { /* SEQUENCE OF */
987 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
988 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
989 ,
990};
991
992static field_t _Information_UUIE[] = { /* SEQUENCE */
993 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
994 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
995 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
996 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
997 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
998 offsetof(Information_UUIE, fastStart), _Information_UUIE_fastStart},
999 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1000 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1001};
1002
1003static field_t _ReleaseCompleteReason[] = { /* CHOICE */
1004 {FNAME("noBandwidth") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1005 {FNAME("gatekeeperResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1006 {FNAME("unreachableDestination") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1007 {FNAME("destinationRejection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1008 {FNAME("invalidRevision") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1009 {FNAME("noPermission") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1010 {FNAME("unreachableGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1011 {FNAME("gatewayResources") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1012 {FNAME("badFormatAddress") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1013 {FNAME("adaptiveBusy") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1014 {FNAME("inConf") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1015 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1016 {FNAME("facilityCallDeflection") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1017 {FNAME("securityDenied") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1018 {FNAME("calledPartyNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1019 {FNAME("callerNotRegistered") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1020 {FNAME("newConnectionNeeded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1021 {FNAME("nonStandardReason") SEQ, 0, 2, 2, SKIP, 0, NULL},
1022 {FNAME("replaceWithConferenceInvite") OCTSTR, FIXD, 16, 0, SKIP, 0,
1023 NULL},
1024 {FNAME("genericDataReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1025 {FNAME("neededFeatureNotSupported") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1026 {FNAME("tunnelledSignallingRejected") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1027};
1028
1029static field_t _ReleaseComplete_UUIE[] = { /* SEQUENCE */
1030 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1031 {FNAME("reason") CHOICE, 4, 12, 22, SKIP | EXT | OPT, 0,
1032 _ReleaseCompleteReason},
1033 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1034 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1035 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1036 {FNAME("busyAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1037 {FNAME("presentationIndicator") CHOICE, 2, 3, 3, SKIP | EXT | OPT, 0,
1038 NULL},
1039 {FNAME("screeningIndicator") ENUM, 2, 0, 0, SKIP | EXT | OPT, 0,
1040 NULL},
1041 {FNAME("capacity") SEQ, 2, 2, 2, SKIP | EXT | OPT, 0, NULL},
1042 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1043 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1044};
1045
1046static field_t _Facility_UUIE_alternativeAliasAddress[] = { /* SEQUENCE OF */
1047 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1048};
1049
1050static field_t _FacilityReason[] = { /* CHOICE */
1051 {FNAME("routeCallToGatekeeper") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1052 {FNAME("callForwarded") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1053 {FNAME("routeCallToMC") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1054 {FNAME("undefinedReason") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1055 {FNAME("conferenceListChoice") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1056 {FNAME("startH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1057 {FNAME("noH245") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1058 {FNAME("newTokens") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1059 {FNAME("featureSetUpdate") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1060 {FNAME("forwardedElements") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1061 {FNAME("transportedInformation") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1062};
1063
1064static field_t _Facility_UUIE_fastStart[] = { /* SEQUENCE OF */
1065 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1066 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1067 ,
1068};
1069
1070static field_t _Facility_UUIE[] = { /* SEQUENCE */
1071 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1072 {FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1073 offsetof(Facility_UUIE, alternativeAddress), _TransportAddress},
1074 {FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1075 _Facility_UUIE_alternativeAliasAddress},
1076 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1077 {FNAME("reason") CHOICE, 2, 4, 11, DECODE | EXT,
1078 offsetof(Facility_UUIE, reason), _FacilityReason},
1079 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0, NULL},
1080 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1081 {FNAME("remoteExtensionAddress") CHOICE, 1, 2, 7, SKIP | EXT | OPT, 0,
1082 NULL},
1083 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1084 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1085 {FNAME("conferences") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1086 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1087 offsetof(Facility_UUIE, h245Address), _TransportAddress},
1088 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1089 offsetof(Facility_UUIE, fastStart), _Facility_UUIE_fastStart},
1090 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1091 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1092 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1093 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1094 {FNAME("circuitInfo") SEQ, 3, 3, 3, SKIP | EXT | OPT, 0, NULL},
1095 {FNAME("featureSet") SEQ, 3, 4, 4, SKIP | EXT | OPT, 0, NULL},
1096 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT | OPT, 0, NULL},
1097 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1098 NULL},
1099};
1100
1101static field_t _CallIdentifier[] = { /* SEQUENCE */
1102 {FNAME("guid") OCTSTR, FIXD, 16, 0, SKIP, 0, NULL},
1103};
1104
1105static field_t _SecurityServiceMode[] = { /* CHOICE */
1106 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1107 {FNAME("none") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1108 {FNAME("default") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1109};
1110
1111static field_t _SecurityCapabilities[] = { /* SEQUENCE */
1112 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1113 _NonStandardParameter},
1114 {FNAME("encryption") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1115 _SecurityServiceMode},
1116 {FNAME("authenticaton") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1117 _SecurityServiceMode},
1118 {FNAME("integrity") CHOICE, 2, 3, 3, SKIP | EXT, 0,
1119 _SecurityServiceMode},
1120};
1121
1122static field_t _H245Security[] = { /* CHOICE */
1123 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP, 0, _NonStandardParameter},
1124 {FNAME("noSecurity") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1125 {FNAME("tls") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1126 {FNAME("ipsec") SEQ, 1, 4, 4, SKIP | EXT, 0, _SecurityCapabilities},
1127};
1128
1129static field_t _DHset[] = { /* SEQUENCE */
1130 {FNAME("halfkey") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1131 {FNAME("modSize") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1132 {FNAME("generator") BITSTR, WORD, 0, 0, SKIP, 0, NULL},
1133};
1134
1135static field_t _TypedCertificate[] = { /* SEQUENCE */
1136 {FNAME("type") OID, BYTE, 0, 0, SKIP, 0, NULL},
1137 {FNAME("certificate") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1138};
1139
1140static field_t _H235_NonStandardParameter[] = { /* SEQUENCE */
1141 {FNAME("nonStandardIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1142 {FNAME("data") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1143};
1144
1145static field_t _ClearToken[] = { /* SEQUENCE */
1146 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1147 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP | OPT, 0, NULL},
1148 {FNAME("password") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1149 {FNAME("dhkey") SEQ, 0, 3, 3, SKIP | EXT | OPT, 0, _DHset},
1150 {FNAME("challenge") OCTSTR, 7, 8, 0, SKIP | OPT, 0, NULL},
1151 {FNAME("random") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1152 {FNAME("certificate") SEQ, 0, 2, 2, SKIP | EXT | OPT, 0,
1153 _TypedCertificate},
1154 {FNAME("generalID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1155 {FNAME("nonStandard") SEQ, 0, 2, 2, SKIP | OPT, 0,
1156 _H235_NonStandardParameter},
1157 {FNAME("eckasdhkey") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, NULL},
1158 {FNAME("sendersID") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1159};
1160
1161static field_t _Progress_UUIE_tokens[] = { /* SEQUENCE OF */
1162 {FNAME("item") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1163};
1164
1165static field_t _Params[] = { /* SEQUENCE */
1166 {FNAME("ranInt") INT, UNCO, 0, 0, SKIP | OPT, 0, NULL},
1167 {FNAME("iv8") OCTSTR, FIXD, 8, 0, SKIP | OPT, 0, NULL},
1168 {FNAME("iv16") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
1169};
1170
1171static field_t _CryptoH323Token_cryptoEPPwdHash_token[] = { /* SEQUENCE */
1172 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1173 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1174 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1175};
1176
1177static field_t _CryptoH323Token_cryptoEPPwdHash[] = { /* SEQUENCE */
1178 {FNAME("alias") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1179 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1180 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1181 _CryptoH323Token_cryptoEPPwdHash_token},
1182};
1183
1184static field_t _CryptoH323Token_cryptoGKPwdHash_token[] = { /* SEQUENCE */
1185 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1186 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1187 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1188};
1189
1190static field_t _CryptoH323Token_cryptoGKPwdHash[] = { /* SEQUENCE */
1191 {FNAME("gatekeeperId") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1192 {FNAME("timeStamp") INT, CONS, 1, 0, SKIP, 0, NULL},
1193 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1194 _CryptoH323Token_cryptoGKPwdHash_token},
1195};
1196
1197static field_t _CryptoH323Token_cryptoEPPwdEncr[] = { /* SEQUENCE */
1198 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1199 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1200 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1201};
1202
1203static field_t _CryptoH323Token_cryptoGKPwdEncr[] = { /* SEQUENCE */
1204 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1205 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1206 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1207};
1208
1209static field_t _CryptoH323Token_cryptoEPCert[] = { /* SEQUENCE */
1210 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1211 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1212 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1213 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1214};
1215
1216static field_t _CryptoH323Token_cryptoGKCert[] = { /* SEQUENCE */
1217 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1218 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1219 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1220 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1221};
1222
1223static field_t _CryptoH323Token_cryptoFastStart[] = { /* SEQUENCE */
1224 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1225 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1226 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1227 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1228};
1229
1230static field_t _CryptoToken_cryptoEncryptedToken_token[] = { /* SEQUENCE */
1231 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1232 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1233 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1234};
1235
1236static field_t _CryptoToken_cryptoEncryptedToken[] = { /* SEQUENCE */
1237 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1238 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1239 _CryptoToken_cryptoEncryptedToken_token},
1240};
1241
1242static field_t _CryptoToken_cryptoSignedToken_token[] = { /* SEQUENCE */
1243 {FNAME("toBeSigned") SEQ, 8, 9, 11, SKIP | OPEN | EXT, 0, NULL},
1244 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1245 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1246 {FNAME("signature") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1247};
1248
1249static field_t _CryptoToken_cryptoSignedToken[] = { /* SEQUENCE */
1250 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1251 {FNAME("token") SEQ, 0, 4, 4, SKIP, 0,
1252 _CryptoToken_cryptoSignedToken_token},
1253};
1254
1255static field_t _CryptoToken_cryptoHashedToken_token[] = { /* SEQUENCE */
1256 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1257 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1258 {FNAME("hash") BITSTR, SEMI, 0, 0, SKIP, 0, NULL},
1259};
1260
1261static field_t _CryptoToken_cryptoHashedToken[] = { /* SEQUENCE */
1262 {FNAME("tokenOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1263 {FNAME("hashedVals") SEQ, 8, 9, 11, SKIP | EXT, 0, _ClearToken},
1264 {FNAME("token") SEQ, 0, 3, 3, SKIP, 0,
1265 _CryptoToken_cryptoHashedToken_token},
1266};
1267
1268static field_t _CryptoToken_cryptoPwdEncr[] = { /* SEQUENCE */
1269 {FNAME("algorithmOID") OID, BYTE, 0, 0, SKIP, 0, NULL},
1270 {FNAME("paramS") SEQ, 2, 2, 3, SKIP | EXT, 0, _Params},
1271 {FNAME("encryptedData") OCTSTR, SEMI, 0, 0, SKIP, 0, NULL},
1272};
1273
1274static field_t _CryptoToken[] = { /* CHOICE */
1275 {FNAME("cryptoEncryptedToken") SEQ, 0, 2, 2, SKIP, 0,
1276 _CryptoToken_cryptoEncryptedToken},
1277 {FNAME("cryptoSignedToken") SEQ, 0, 2, 2, SKIP, 0,
1278 _CryptoToken_cryptoSignedToken},
1279 {FNAME("cryptoHashedToken") SEQ, 0, 3, 3, SKIP, 0,
1280 _CryptoToken_cryptoHashedToken},
1281 {FNAME("cryptoPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1282 _CryptoToken_cryptoPwdEncr},
1283};
1284
1285static field_t _CryptoH323Token[] = { /* CHOICE */
1286 {FNAME("cryptoEPPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1287 _CryptoH323Token_cryptoEPPwdHash},
1288 {FNAME("cryptoGKPwdHash") SEQ, 0, 3, 3, SKIP, 0,
1289 _CryptoH323Token_cryptoGKPwdHash},
1290 {FNAME("cryptoEPPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1291 _CryptoH323Token_cryptoEPPwdEncr},
1292 {FNAME("cryptoGKPwdEncr") SEQ, 0, 3, 3, SKIP, 0,
1293 _CryptoH323Token_cryptoGKPwdEncr},
1294 {FNAME("cryptoEPCert") SEQ, 0, 4, 4, SKIP, 0,
1295 _CryptoH323Token_cryptoEPCert},
1296 {FNAME("cryptoGKCert") SEQ, 0, 4, 4, SKIP, 0,
1297 _CryptoH323Token_cryptoGKCert},
1298 {FNAME("cryptoFastStart") SEQ, 0, 4, 4, SKIP, 0,
1299 _CryptoH323Token_cryptoFastStart},
1300 {FNAME("nestedcryptoToken") CHOICE, 2, 4, 4, SKIP | EXT, 0,
1301 _CryptoToken},
1302};
1303
1304static field_t _Progress_UUIE_cryptoTokens[] = { /* SEQUENCE OF */
1305 {FNAME("item") CHOICE, 3, 8, 8, SKIP | EXT, 0, _CryptoH323Token},
1306};
1307
1308static field_t _Progress_UUIE_fastStart[] = { /* SEQUENCE OF */
1309 {FNAME("item") SEQ, 1, 3, 5, DECODE | OPEN | EXT,
1310 sizeof(OpenLogicalChannel), _OpenLogicalChannel}
1311 ,
1312};
1313
1314static field_t _Progress_UUIE[] = { /* SEQUENCE */
1315 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1316 {FNAME("destinationInfo") SEQ, 6, 8, 10, SKIP | EXT, 0,
1317 _EndpointType},
1318 {FNAME("h245Address") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1319 offsetof(Progress_UUIE, h245Address), _TransportAddress},
1320 {FNAME("callIdentifier") SEQ, 0, 1, 1, SKIP | EXT, 0,
1321 _CallIdentifier},
1322 {FNAME("h245SecurityMode") CHOICE, 2, 4, 4, SKIP | EXT | OPT, 0,
1323 _H245Security},
1324 {FNAME("tokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1325 _Progress_UUIE_tokens},
1326 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1327 _Progress_UUIE_cryptoTokens},
1328 {FNAME("fastStart") SEQOF, SEMI, 0, 30, DECODE | OPT,
1329 offsetof(Progress_UUIE, fastStart), _Progress_UUIE_fastStart},
1330 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1331 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1332 {FNAME("fastConnectRefused") NUL, FIXD, 0, 0, SKIP | OPT, 0, NULL},
1333};
1334
1335static field_t _H323_UU_PDU_h323_message_body[] = { /* CHOICE */
1336 {FNAME("setup") SEQ, 7, 13, 39, DECODE | EXT,
1337 offsetof(H323_UU_PDU_h323_message_body, setup), _Setup_UUIE},
1338 {FNAME("callProceeding") SEQ, 1, 3, 12, DECODE | EXT,
1339 offsetof(H323_UU_PDU_h323_message_body, callProceeding),
1340 _CallProceeding_UUIE},
1341 {FNAME("connect") SEQ, 1, 4, 19, DECODE | EXT,
1342 offsetof(H323_UU_PDU_h323_message_body, connect), _Connect_UUIE},
1343 {FNAME("alerting") SEQ, 1, 3, 17, DECODE | EXT,
1344 offsetof(H323_UU_PDU_h323_message_body, alerting), _Alerting_UUIE},
1345 {FNAME("information") SEQ, 0, 1, 7, DECODE | EXT,
1346 offsetof(H323_UU_PDU_h323_message_body, information),
1347 _Information_UUIE},
1348 {FNAME("releaseComplete") SEQ, 1, 2, 11, SKIP | EXT, 0,
1349 _ReleaseComplete_UUIE},
1350 {FNAME("facility") SEQ, 3, 5, 21, DECODE | EXT,
1351 offsetof(H323_UU_PDU_h323_message_body, facility), _Facility_UUIE},
1352 {FNAME("progress") SEQ, 5, 8, 11, DECODE | EXT,
1353 offsetof(H323_UU_PDU_h323_message_body, progress), _Progress_UUIE},
1354 {FNAME("empty") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1355 {FNAME("status") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1356 {FNAME("statusInquiry") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1357 {FNAME("setupAcknowledge") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1358 {FNAME("notify") SEQ, 2, 4, 4, SKIP | EXT, 0, NULL},
1359};
1360
1361static field_t _RequestMessage[] = { /* CHOICE */
1362 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1363 {FNAME("masterSlaveDetermination") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1364 {FNAME("terminalCapabilitySet") SEQ, 3, 5, 5, STOP | EXT, 0, NULL},
1365 {FNAME("openLogicalChannel") SEQ, 1, 3, 5, DECODE | EXT,
1366 offsetof(RequestMessage, openLogicalChannel), _OpenLogicalChannel},
1367 {FNAME("closeLogicalChannel") SEQ, 0, 2, 3, STOP | EXT, 0, NULL},
1368 {FNAME("requestChannelClose") SEQ, 0, 1, 3, STOP | EXT, 0, NULL},
1369 {FNAME("multiplexEntrySend") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1370 {FNAME("requestMultiplexEntry") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1371 {FNAME("requestMode") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1372 {FNAME("roundTripDelayRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1373 {FNAME("maintenanceLoopRequest") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1374 {FNAME("communicationModeRequest") SEQ, 0, 0, 0, STOP | EXT, 0, NULL},
1375 {FNAME("conferenceRequest") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1376 {FNAME("multilinkRequest") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1377 {FNAME("logicalChannelRateRequest") SEQ, 0, 3, 3, STOP | EXT, 0,
1378 NULL},
1379};
1380
1381static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters[] = { /* CHOICE */
1382 {FNAME("h222LogicalChannelParameters") SEQ, 3, 5, 5, SKIP | EXT, 0,
1383 _H222LogicalChannelParameters},
1384 {FNAME("h2250LogicalChannelParameters") SEQ, 10, 11, 14, DECODE | EXT,
1385 offsetof
1386 (OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters,
1387 h2250LogicalChannelParameters), _H2250LogicalChannelParameters},
1388};
1389
1390static field_t _OpenLogicalChannelAck_reverseLogicalChannelParameters[] = { /* SEQUENCE */
1391 {FNAME("reverseLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1392 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1393 {FNAME("multiplexParameters") CHOICE, 0, 1, 2, DECODE | EXT | OPT,
1394 offsetof(OpenLogicalChannelAck_reverseLogicalChannelParameters,
1395 multiplexParameters),
1396 _OpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters},
1397 {FNAME("replacementFor") INT, WORD, 1, 0, SKIP | OPT, 0, NULL},
1398};
1399
1400static field_t _H2250LogicalChannelAckParameters_nonStandard[] = { /* SEQUENCE OF */
1401 {FNAME("item") SEQ, 0, 2, 2, SKIP, 0, _H245_NonStandardParameter},
1402};
1403
1404static field_t _H2250LogicalChannelAckParameters[] = { /* SEQUENCE */
1405 {FNAME("nonStandard") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1406 _H2250LogicalChannelAckParameters_nonStandard},
1407 {FNAME("sessionID") INT, 8, 1, 0, SKIP | OPT, 0, NULL},
1408 {FNAME("mediaChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1409 offsetof(H2250LogicalChannelAckParameters, mediaChannel),
1410 _H245_TransportAddress},
1411 {FNAME("mediaControlChannel") CHOICE, 1, 2, 2, DECODE | EXT | OPT,
1412 offsetof(H2250LogicalChannelAckParameters, mediaControlChannel),
1413 _H245_TransportAddress},
1414 {FNAME("dynamicRTPPayloadType") INT, 5, 96, 0, SKIP | OPT, 0, NULL},
1415 {FNAME("flowControlToZero") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1416 {FNAME("portNumber") INT, WORD, 0, 0, SKIP | OPT, 0, NULL},
1417};
1418
1419static field_t _OpenLogicalChannelAck_forwardMultiplexAckParameters[] = { /* CHOICE */
1420 {FNAME("h2250LogicalChannelAckParameters") SEQ, 5, 5, 7, DECODE | EXT,
1421 offsetof(OpenLogicalChannelAck_forwardMultiplexAckParameters,
1422 h2250LogicalChannelAckParameters),
1423 _H2250LogicalChannelAckParameters},
1424};
1425
1426static field_t _OpenLogicalChannelAck[] = { /* SEQUENCE */
1427 {FNAME("forwardLogicalChannelNumber") INT, WORD, 1, 0, SKIP, 0, NULL},
1428 {FNAME("reverseLogicalChannelParameters") SEQ, 2, 3, 4,
1429 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1430 reverseLogicalChannelParameters),
1431 _OpenLogicalChannelAck_reverseLogicalChannelParameters},
1432 {FNAME("separateStack") SEQ, 2, 4, 5, SKIP | EXT | OPT, 0, NULL},
1433 {FNAME("forwardMultiplexAckParameters") CHOICE, 0, 1, 1,
1434 DECODE | EXT | OPT, offsetof(OpenLogicalChannelAck,
1435 forwardMultiplexAckParameters),
1436 _OpenLogicalChannelAck_forwardMultiplexAckParameters},
1437 {FNAME("encryptionSync") SEQ, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1438};
1439
1440static field_t _ResponseMessage[] = { /* CHOICE */
1441 {FNAME("nonStandard") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1442 {FNAME("masterSlaveDeterminationAck") SEQ, 0, 1, 1, STOP | EXT, 0,
1443 NULL},
1444 {FNAME("masterSlaveDeterminationReject") SEQ, 0, 1, 1, STOP | EXT, 0,
1445 NULL},
1446 {FNAME("terminalCapabilitySetAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1447 {FNAME("terminalCapabilitySetReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1448 NULL},
1449 {FNAME("openLogicalChannelAck") SEQ, 1, 2, 5, DECODE | EXT,
1450 offsetof(ResponseMessage, openLogicalChannelAck),
1451 _OpenLogicalChannelAck},
1452 {FNAME("openLogicalChannelReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1453 {FNAME("closeLogicalChannelAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1454 {FNAME("requestChannelCloseAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1455 {FNAME("requestChannelCloseReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1456 NULL},
1457 {FNAME("multiplexEntrySendAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1458 {FNAME("multiplexEntrySendReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1459 {FNAME("requestMultiplexEntryAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1460 {FNAME("requestMultiplexEntryReject") SEQ, 0, 2, 2, STOP | EXT, 0,
1461 NULL},
1462 {FNAME("requestModeAck") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1463 {FNAME("requestModeReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1464 {FNAME("roundTripDelayResponse") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1465 {FNAME("maintenanceLoopAck") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1466 {FNAME("maintenanceLoopReject") SEQ, 0, 2, 2, STOP | EXT, 0, NULL},
1467 {FNAME("communicationModeResponse") CHOICE, 0, 1, 1, STOP | EXT, 0,
1468 NULL},
1469 {FNAME("conferenceResponse") CHOICE, 3, 8, 16, STOP | EXT, 0, NULL},
1470 {FNAME("multilinkResponse") CHOICE, 3, 5, 5, STOP | EXT, 0, NULL},
1471 {FNAME("logicalChannelRateAcknowledge") SEQ, 0, 3, 3, STOP | EXT, 0,
1472 NULL},
1473 {FNAME("logicalChannelRateReject") SEQ, 1, 4, 4, STOP | EXT, 0, NULL},
1474};
1475
1476static field_t _MultimediaSystemControlMessage[] = { /* CHOICE */
1477 {FNAME("request") CHOICE, 4, 11, 15, DECODE | EXT,
1478 offsetof(MultimediaSystemControlMessage, request), _RequestMessage},
1479 {FNAME("response") CHOICE, 5, 19, 24, DECODE | EXT,
1480 offsetof(MultimediaSystemControlMessage, response),
1481 _ResponseMessage},
1482 {FNAME("command") CHOICE, 3, 7, 12, STOP | EXT, 0, NULL},
1483 {FNAME("indication") CHOICE, 4, 14, 23, STOP | EXT, 0, NULL},
1484};
1485
1486static field_t _H323_UU_PDU_h245Control[] = { /* SEQUENCE OF */
1487 {FNAME("item") CHOICE, 2, 4, 4, DECODE | OPEN | EXT,
1488 sizeof(MultimediaSystemControlMessage),
1489 _MultimediaSystemControlMessage}
1490 ,
1491};
1492
1493static field_t _H323_UU_PDU[] = { /* SEQUENCE */
1494 {FNAME("h323-message-body") CHOICE, 3, 7, 13, DECODE | EXT,
1495 offsetof(H323_UU_PDU, h323_message_body),
1496 _H323_UU_PDU_h323_message_body},
1497 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1498 _NonStandardParameter},
1499 {FNAME("h4501SupplementaryService") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1500 NULL},
1501 {FNAME("h245Tunneling") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1502 {FNAME("h245Control") SEQOF, SEMI, 0, 4, DECODE | OPT,
1503 offsetof(H323_UU_PDU, h245Control), _H323_UU_PDU_h245Control},
1504 {FNAME("nonStandardControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1505 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1506 {FNAME("tunnelledSignallingMessage") SEQ, 2, 4, 4, STOP | EXT | OPT,
1507 0, NULL},
1508 {FNAME("provisionalRespToH245Tunneling") NUL, FIXD, 0, 0, STOP | OPT,
1509 0, NULL},
1510 {FNAME("stimulusControl") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1511 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1512};
1513
1514static field_t _H323_UserInformation[] = { /* SEQUENCE */
1515 {FNAME("h323-uu-pdu") SEQ, 1, 2, 11, DECODE | EXT,
1516 offsetof(H323_UserInformation, h323_uu_pdu), _H323_UU_PDU},
1517 {FNAME("user-data") SEQ, 0, 2, 2, STOP | EXT | OPT, 0, NULL},
1518};
1519
1520static field_t _GatekeeperRequest[] = { /* SEQUENCE */
1521 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1522 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1523 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1524 _NonStandardParameter},
1525 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1526 offsetof(GatekeeperRequest, rasAddress), _TransportAddress},
1527 {FNAME("endpointType") SEQ, 6, 8, 10, STOP | EXT, 0, NULL},
1528 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1529 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1530 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1531 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1532 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1533 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1534 {FNAME("authenticationCapability") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1535 NULL},
1536 {FNAME("algorithmOIDs") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1537 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1538 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1539 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1540 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1541 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1542};
1543
1544static field_t _GatekeeperConfirm[] = { /* SEQUENCE */
1545 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1546 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1547 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1548 _NonStandardParameter},
1549 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1550 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1551 offsetof(GatekeeperConfirm, rasAddress), _TransportAddress},
1552 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1553 {FNAME("authenticationMode") CHOICE, 3, 7, 8, STOP | EXT | OPT, 0,
1554 NULL},
1555 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1556 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1557 {FNAME("algorithmOID") OID, BYTE, 0, 0, STOP | OPT, 0, NULL},
1558 {FNAME("integrity") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1559 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1560 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1561 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1562};
1563
1564static field_t _RegistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1565 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1566 sizeof(TransportAddress), _TransportAddress}
1567 ,
1568};
1569
1570static field_t _RegistrationRequest_rasAddress[] = { /* SEQUENCE OF */
1571 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1572 sizeof(TransportAddress), _TransportAddress}
1573 ,
1574};
1575
1576static field_t _RegistrationRequest_terminalAlias[] = { /* SEQUENCE OF */
1577 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1578};
1579
1580static field_t _RegistrationRequest[] = { /* SEQUENCE */
1581 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1582 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1583 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1584 _NonStandardParameter},
1585 {FNAME("discoveryComplete") BOOL, FIXD, 0, 0, SKIP, 0, NULL},
1586 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1587 offsetof(RegistrationRequest, callSignalAddress),
1588 _RegistrationRequest_callSignalAddress},
1589 {FNAME("rasAddress") SEQOF, SEMI, 0, 10, DECODE,
1590 offsetof(RegistrationRequest, rasAddress),
1591 _RegistrationRequest_rasAddress},
1592 {FNAME("terminalType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1593 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1594 _RegistrationRequest_terminalAlias},
1595 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1596 {FNAME("endpointVendor") SEQ, 2, 3, 3, SKIP | EXT, 0,
1597 _VendorIdentifier},
1598 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1599 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1600 offsetof(RegistrationRequest, timeToLive), NULL},
1601 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1602 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1603 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1604 {FNAME("keepAlive") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1605 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1606 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1607 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1608 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1609 0, NULL},
1610 {FNAME("additiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1611 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1612 NULL},
1613 {FNAME("supportsAltGK") NUL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1614 {FNAME("usageReportingCapability") SEQ, 3, 4, 4, STOP | EXT | OPT, 0,
1615 NULL},
1616 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1617 {FNAME("supportedH248Packages") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1618 NULL},
1619 {FNAME("callCreditCapability") SEQ, 2, 2, 2, STOP | EXT | OPT, 0,
1620 NULL},
1621 {FNAME("capacityReportingCapability") SEQ, 0, 1, 1, STOP | EXT | OPT,
1622 0, NULL},
1623 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1624 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1625 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1626};
1627
1628static field_t _RegistrationConfirm_callSignalAddress[] = { /* SEQUENCE OF */
1629 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1630 sizeof(TransportAddress), _TransportAddress}
1631 ,
1632};
1633
1634static field_t _RegistrationConfirm_terminalAlias[] = { /* SEQUENCE OF */
1635 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1636};
1637
1638static field_t _RegistrationConfirm[] = { /* SEQUENCE */
1639 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1640 {FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
1641 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1642 _NonStandardParameter},
1643 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1644 offsetof(RegistrationConfirm, callSignalAddress),
1645 _RegistrationConfirm_callSignalAddress},
1646 {FNAME("terminalAlias") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1647 _RegistrationConfirm_terminalAlias},
1648 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1649 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1650 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, SKIP | OPT, 0, NULL},
1651 {FNAME("timeToLive") INT, CONS, 1, 0, DECODE | OPT,
1652 offsetof(RegistrationConfirm, timeToLive), NULL},
1653 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1654 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1655 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1656 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1657 {FNAME("preGrantedARQ") SEQ, 0, 4, 8, STOP | EXT | OPT, 0, NULL},
1658 {FNAME("maintainConnection") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1659 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1660 {FNAME("supportsAdditiveRegistration") NUL, FIXD, 0, 0, STOP | OPT, 0,
1661 NULL},
1662 {FNAME("terminalAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1663 NULL},
1664 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1665 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1666 {FNAME("featureServerAlias") CHOICE, 1, 2, 7, STOP | EXT | OPT, 0,
1667 NULL},
1668 {FNAME("capacityReportingSpec") SEQ, 0, 1, 1, STOP | EXT | OPT, 0,
1669 NULL},
1670 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1671 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1672};
1673
1674static field_t _UnregistrationRequest_callSignalAddress[] = { /* SEQUENCE OF */
1675 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1676 sizeof(TransportAddress), _TransportAddress}
1677 ,
1678};
1679
1680static field_t _UnregistrationRequest[] = { /* SEQUENCE */
1681 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1682 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1683 offsetof(UnregistrationRequest, callSignalAddress),
1684 _UnregistrationRequest_callSignalAddress},
1685 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1686 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1687 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1688 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1689 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1690 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1691 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1692 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1693 {FNAME("reason") CHOICE, 2, 4, 5, STOP | EXT | OPT, 0, NULL},
1694 {FNAME("endpointAliasPattern") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1695 NULL},
1696 {FNAME("supportedPrefixes") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1697 {FNAME("alternateGatekeeper") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1698 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1699};
1700
1701static field_t _CallModel[] = { /* CHOICE */
1702 {FNAME("direct") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1703 {FNAME("gatekeeperRouted") NUL, FIXD, 0, 0, SKIP, 0, NULL},
1704};
1705
1706static field_t _AdmissionRequest_destinationInfo[] = { /* SEQUENCE OF */
1707 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1708};
1709
1710static field_t _AdmissionRequest_destExtraCallInfo[] = { /* SEQUENCE OF */
1711 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1712};
1713
1714static field_t _AdmissionRequest_srcInfo[] = { /* SEQUENCE OF */
1715 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1716};
1717
1718static field_t _AdmissionRequest[] = { /* SEQUENCE */
1719 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1720 {FNAME("callType") CHOICE, 2, 4, 4, SKIP | EXT, 0, _CallType},
1721 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT | OPT, 0, _CallModel},
1722 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1723 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1724 _AdmissionRequest_destinationInfo},
1725 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1726 offsetof(AdmissionRequest, destCallSignalAddress),
1727 _TransportAddress},
1728 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
1729 _AdmissionRequest_destExtraCallInfo},
1730 {FNAME("srcInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1731 _AdmissionRequest_srcInfo},
1732 {FNAME("srcCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
1733 offsetof(AdmissionRequest, srcCallSignalAddress), _TransportAddress},
1734 {FNAME("bandWidth") INT, CONS, 0, 0, STOP, 0, NULL},
1735 {FNAME("callReferenceValue") INT, WORD, 0, 0, STOP, 0, NULL},
1736 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1737 {FNAME("callServices") SEQ, 0, 8, 8, STOP | EXT | OPT, 0, NULL},
1738 {FNAME("conferenceID") OCTSTR, FIXD, 16, 0, STOP, 0, NULL},
1739 {FNAME("activeMC") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1740 {FNAME("answerCall") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1741 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1742 {FNAME("callIdentifier") SEQ, 0, 1, 1, STOP | EXT, 0, NULL},
1743 {FNAME("srcAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1744 {FNAME("destAlternatives") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1745 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1746 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1747 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1748 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1749 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1750 {FNAME("willSupplyUUIEs") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1751 {FNAME("callLinkage") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1752 {FNAME("gatewayDataRate") SEQ, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1753 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1754 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1755 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1756 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1757 NULL},
1758 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1759 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1760};
1761
1762static field_t _AdmissionConfirm[] = { /* SEQUENCE */
1763 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1764 {FNAME("bandWidth") INT, CONS, 0, 0, SKIP, 0, NULL},
1765 {FNAME("callModel") CHOICE, 1, 2, 2, SKIP | EXT, 0, _CallModel},
1766 {FNAME("destCallSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1767 offsetof(AdmissionConfirm, destCallSignalAddress),
1768 _TransportAddress},
1769 {FNAME("irrFrequency") INT, WORD, 1, 0, STOP | OPT, 0, NULL},
1770 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1771 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1772 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1773 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1774 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1775 NULL},
1776 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1777 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1778 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1779 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1780 {FNAME("transportQOS") CHOICE, 2, 3, 3, STOP | EXT | OPT, 0, NULL},
1781 {FNAME("willRespondToIRR") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1782 {FNAME("uuiesRequested") SEQ, 0, 9, 13, STOP | EXT, 0, NULL},
1783 {FNAME("language") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1784 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1785 0, NULL},
1786 {FNAME("useSpecifiedTransport") CHOICE, 1, 2, 2, STOP | EXT | OPT, 0,
1787 NULL},
1788 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1789 {FNAME("usageSpec") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1790 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1791 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1792 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1793 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1794 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1795};
1796
1797static field_t _LocationRequest_destinationInfo[] = { /* SEQUENCE OF */
1798 {FNAME("item") CHOICE, 1, 2, 7, SKIP | EXT, 0, _AliasAddress},
1799};
1800
1801static field_t _LocationRequest[] = { /* SEQUENCE */
1802 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1803 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP | OPT, 0, NULL},
1804 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, SKIP, 0,
1805 _LocationRequest_destinationInfo},
1806 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1807 _NonStandardParameter},
1808 {FNAME("replyAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1809 offsetof(LocationRequest, replyAddress), _TransportAddress},
1810 {FNAME("sourceInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1811 {FNAME("canMapAlias") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1812 {FNAME("gatekeeperIdentifier") BMPSTR, 7, 1, 0, STOP | OPT, 0, NULL},
1813 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1814 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1815 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1816 {FNAME("desiredProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1817 {FNAME("desiredTunnelledProtocol") SEQ, 1, 2, 2, STOP | EXT | OPT, 0,
1818 NULL},
1819 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1820 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1821 {FNAME("hopCount") INT, 8, 1, 0, STOP | OPT, 0, NULL},
1822 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1823};
1824
1825static field_t _LocationConfirm[] = { /* SEQUENCE */
1826 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1827 {FNAME("callSignalAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1828 offsetof(LocationConfirm, callSignalAddress), _TransportAddress},
1829 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1830 offsetof(LocationConfirm, rasAddress), _TransportAddress},
1831 {FNAME("nonStandardData") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1832 {FNAME("destinationInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1833 {FNAME("destExtraCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1834 {FNAME("destinationType") SEQ, 6, 8, 10, STOP | EXT | OPT, 0, NULL},
1835 {FNAME("remoteExtensionAddress") SEQOF, SEMI, 0, 0, STOP | OPT, 0,
1836 NULL},
1837 {FNAME("alternateEndpoints") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1838 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1839 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1840 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1841 {FNAME("alternateTransportAddresses") SEQ, 1, 1, 1, STOP | EXT | OPT,
1842 0, NULL},
1843 {FNAME("supportedProtocols") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1844 {FNAME("multipleCalls") BOOL, FIXD, 0, 0, STOP | OPT, 0, NULL},
1845 {FNAME("featureSet") SEQ, 3, 4, 4, STOP | EXT | OPT, 0, NULL},
1846 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1847 {FNAME("circuitInfo") SEQ, 3, 3, 3, STOP | EXT | OPT, 0, NULL},
1848 {FNAME("serviceControl") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1849};
1850
1851static field_t _InfoRequestResponse_callSignalAddress[] = { /* SEQUENCE OF */
1852 {FNAME("item") CHOICE, 3, 7, 7, DECODE | EXT,
1853 sizeof(TransportAddress), _TransportAddress}
1854 ,
1855};
1856
1857static field_t _InfoRequestResponse[] = { /* SEQUENCE */
1858 {FNAME("nonStandardData") SEQ, 0, 2, 2, SKIP | OPT, 0,
1859 _NonStandardParameter},
1860 {FNAME("requestSeqNum") INT, WORD, 1, 0, SKIP, 0, NULL},
1861 {FNAME("endpointType") SEQ, 6, 8, 10, SKIP | EXT, 0, _EndpointType},
1862 {FNAME("endpointIdentifier") BMPSTR, 7, 1, 0, SKIP, 0, NULL},
1863 {FNAME("rasAddress") CHOICE, 3, 7, 7, DECODE | EXT,
1864 offsetof(InfoRequestResponse, rasAddress), _TransportAddress},
1865 {FNAME("callSignalAddress") SEQOF, SEMI, 0, 10, DECODE,
1866 offsetof(InfoRequestResponse, callSignalAddress),
1867 _InfoRequestResponse_callSignalAddress},
1868 {FNAME("endpointAlias") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1869 {FNAME("perCallInfo") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1870 {FNAME("tokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1871 {FNAME("cryptoTokens") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1872 {FNAME("integrityCheckValue") SEQ, 0, 2, 2, STOP | OPT, 0, NULL},
1873 {FNAME("needResponse") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1874 {FNAME("capacity") SEQ, 2, 2, 2, STOP | EXT | OPT, 0, NULL},
1875 {FNAME("irrStatus") CHOICE, 2, 4, 4, STOP | EXT | OPT, 0, NULL},
1876 {FNAME("unsolicited") BOOL, FIXD, 0, 0, STOP, 0, NULL},
1877 {FNAME("genericData") SEQOF, SEMI, 0, 0, STOP | OPT, 0, NULL},
1878};
1879
1880static field_t _RasMessage[] = { /* CHOICE */
1881 {FNAME("gatekeeperRequest") SEQ, 4, 8, 18, DECODE | EXT,
1882 offsetof(RasMessage, gatekeeperRequest), _GatekeeperRequest},
1883 {FNAME("gatekeeperConfirm") SEQ, 2, 5, 14, DECODE | EXT,
1884 offsetof(RasMessage, gatekeeperConfirm), _GatekeeperConfirm},
1885 {FNAME("gatekeeperReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1886 {FNAME("registrationRequest") SEQ, 3, 10, 31, DECODE | EXT,
1887 offsetof(RasMessage, registrationRequest), _RegistrationRequest},
1888 {FNAME("registrationConfirm") SEQ, 3, 7, 24, DECODE | EXT,
1889 offsetof(RasMessage, registrationConfirm), _RegistrationConfirm},
1890 {FNAME("registrationReject") SEQ, 2, 5, 11, STOP | EXT, 0, NULL},
1891 {FNAME("unregistrationRequest") SEQ, 3, 5, 15, DECODE | EXT,
1892 offsetof(RasMessage, unregistrationRequest), _UnregistrationRequest},
1893 {FNAME("unregistrationConfirm") SEQ, 1, 2, 6, STOP | EXT, 0, NULL},
1894 {FNAME("unregistrationReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1895 {FNAME("admissionRequest") SEQ, 7, 16, 34, DECODE | EXT,
1896 offsetof(RasMessage, admissionRequest), _AdmissionRequest},
1897 {FNAME("admissionConfirm") SEQ, 2, 6, 27, DECODE | EXT,
1898 offsetof(RasMessage, admissionConfirm), _AdmissionConfirm},
1899 {FNAME("admissionReject") SEQ, 1, 3, 11, STOP | EXT, 0, NULL},
1900 {FNAME("bandwidthRequest") SEQ, 2, 7, 18, STOP | EXT, 0, NULL},
1901 {FNAME("bandwidthConfirm") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1902 {FNAME("bandwidthReject") SEQ, 1, 4, 9, STOP | EXT, 0, NULL},
1903 {FNAME("disengageRequest") SEQ, 1, 6, 19, STOP | EXT, 0, NULL},
1904 {FNAME("disengageConfirm") SEQ, 1, 2, 9, STOP | EXT, 0, NULL},
1905 {FNAME("disengageReject") SEQ, 1, 3, 8, STOP | EXT, 0, NULL},
1906 {FNAME("locationRequest") SEQ, 2, 5, 17, DECODE | EXT,
1907 offsetof(RasMessage, locationRequest), _LocationRequest},
1908 {FNAME("locationConfirm") SEQ, 1, 4, 19, DECODE | EXT,
1909 offsetof(RasMessage, locationConfirm), _LocationConfirm},
1910 {FNAME("locationReject") SEQ, 1, 3, 10, STOP | EXT, 0, NULL},
1911 {FNAME("infoRequest") SEQ, 2, 4, 15, STOP | EXT, 0, NULL},
1912 {FNAME("infoRequestResponse") SEQ, 3, 8, 16, DECODE | EXT,
1913 offsetof(RasMessage, infoRequestResponse), _InfoRequestResponse},
1914 {FNAME("nonStandardMessage") SEQ, 0, 2, 7, STOP | EXT, 0, NULL},
1915 {FNAME("unknownMessageResponse") SEQ, 0, 1, 5, STOP | EXT, 0, NULL},
1916 {FNAME("requestInProgress") SEQ, 4, 6, 6, STOP | EXT, 0, NULL},
1917 {FNAME("resourcesAvailableIndicate") SEQ, 4, 9, 11, STOP | EXT, 0,
1918 NULL},
1919 {FNAME("resourcesAvailableConfirm") SEQ, 4, 6, 7, STOP | EXT, 0,
1920 NULL},
1921 {FNAME("infoRequestAck") SEQ, 4, 5, 5, STOP | EXT, 0, NULL},
1922 {FNAME("infoRequestNak") SEQ, 5, 7, 7, STOP | EXT, 0, NULL},
1923 {FNAME("serviceControlIndication") SEQ, 8, 10, 10, STOP | EXT, 0,
1924 NULL},
1925 {FNAME("serviceControlResponse") SEQ, 7, 8, 8, STOP | EXT, 0, NULL},
1926};
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index a2af5e0c7f99..4d19373bbf0d 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -124,6 +124,8 @@ EXPORT_SYMBOL(pptp_msg_name);
124static void pptp_expectfn(struct ip_conntrack *ct, 124static void pptp_expectfn(struct ip_conntrack *ct,
125 struct ip_conntrack_expect *exp) 125 struct ip_conntrack_expect *exp)
126{ 126{
127 typeof(ip_nat_pptp_hook_expectfn) ip_nat_pptp_expectfn;
128
127 DEBUGP("increasing timeouts\n"); 129 DEBUGP("increasing timeouts\n");
128 130
129 /* increase timeout of GRE data channel conntrack entry */ 131 /* increase timeout of GRE data channel conntrack entry */
@@ -133,7 +135,9 @@ static void pptp_expectfn(struct ip_conntrack *ct,
133 /* Can you see how rusty this code is, compared with the pre-2.6.11 135 /* Can you see how rusty this code is, compared with the pre-2.6.11
134 * one? That's what happened to my shiny newnat of 2002 ;( -HW */ 136 * one? That's what happened to my shiny newnat of 2002 ;( -HW */
135 137
136 if (!ip_nat_pptp_hook_expectfn) { 138 rcu_read_lock();
139 ip_nat_pptp_expectfn = rcu_dereference(ip_nat_pptp_hook_expectfn);
140 if (!ip_nat_pptp_expectfn) {
137 struct ip_conntrack_tuple inv_t; 141 struct ip_conntrack_tuple inv_t;
138 struct ip_conntrack_expect *exp_other; 142 struct ip_conntrack_expect *exp_other;
139 143
@@ -142,7 +146,7 @@ static void pptp_expectfn(struct ip_conntrack *ct,
142 DEBUGP("trying to unexpect other dir: "); 146 DEBUGP("trying to unexpect other dir: ");
143 DUMP_TUPLE(&inv_t); 147 DUMP_TUPLE(&inv_t);
144 148
145 exp_other = ip_conntrack_expect_find(&inv_t); 149 exp_other = ip_conntrack_expect_find_get(&inv_t);
146 if (exp_other) { 150 if (exp_other) {
147 /* delete other expectation. */ 151 /* delete other expectation. */
148 DEBUGP("found\n"); 152 DEBUGP("found\n");
@@ -153,8 +157,9 @@ static void pptp_expectfn(struct ip_conntrack *ct,
153 } 157 }
154 } else { 158 } else {
155 /* we need more than simple inversion */ 159 /* we need more than simple inversion */
156 ip_nat_pptp_hook_expectfn(ct, exp); 160 ip_nat_pptp_expectfn(ct, exp);
157 } 161 }
162 rcu_read_unlock();
158} 163}
159 164
160static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) 165static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
@@ -176,7 +181,7 @@ static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
176 ip_conntrack_put(sibling); 181 ip_conntrack_put(sibling);
177 return 1; 182 return 1;
178 } else { 183 } else {
179 exp = ip_conntrack_expect_find(t); 184 exp = ip_conntrack_expect_find_get(t);
180 if (exp) { 185 if (exp) {
181 DEBUGP("unexpect_related of expect %p\n", exp); 186 DEBUGP("unexpect_related of expect %p\n", exp);
182 ip_conntrack_unexpect_related(exp); 187 ip_conntrack_unexpect_related(exp);
@@ -226,6 +231,7 @@ exp_gre(struct ip_conntrack *ct,
226{ 231{
227 struct ip_conntrack_expect *exp_orig, *exp_reply; 232 struct ip_conntrack_expect *exp_orig, *exp_reply;
228 int ret = 1; 233 int ret = 1;
234 typeof(ip_nat_pptp_hook_exp_gre) ip_nat_pptp_exp_gre;
229 235
230 exp_orig = ip_conntrack_expect_alloc(ct); 236 exp_orig = ip_conntrack_expect_alloc(ct);
231 if (exp_orig == NULL) 237 if (exp_orig == NULL)
@@ -262,8 +268,9 @@ exp_gre(struct ip_conntrack *ct,
262 exp_reply->tuple.dst.u.gre.key = peer_callid; 268 exp_reply->tuple.dst.u.gre.key = peer_callid;
263 exp_reply->tuple.dst.protonum = IPPROTO_GRE; 269 exp_reply->tuple.dst.protonum = IPPROTO_GRE;
264 270
265 if (ip_nat_pptp_hook_exp_gre) 271 ip_nat_pptp_exp_gre = rcu_dereference(ip_nat_pptp_hook_exp_gre);
266 ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); 272 if (ip_nat_pptp_exp_gre)
273 ip_nat_pptp_exp_gre(exp_orig, exp_reply);
267 if (ip_conntrack_expect_related(exp_orig) != 0) 274 if (ip_conntrack_expect_related(exp_orig) != 0)
268 goto out_put_both; 275 goto out_put_both;
269 if (ip_conntrack_expect_related(exp_reply) != 0) 276 if (ip_conntrack_expect_related(exp_reply) != 0)
@@ -303,6 +310,7 @@ pptp_inbound_pkt(struct sk_buff **pskb,
303 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; 310 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
304 u_int16_t msg; 311 u_int16_t msg;
305 __be16 cid = 0, pcid = 0; 312 __be16 cid = 0, pcid = 0;
313 typeof(ip_nat_pptp_hook_inbound) ip_nat_pptp_inbound;
306 314
307 msg = ntohs(ctlh->messageType); 315 msg = ntohs(ctlh->messageType);
308 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); 316 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
@@ -402,9 +410,9 @@ pptp_inbound_pkt(struct sk_buff **pskb,
402 goto invalid; 410 goto invalid;
403 } 411 }
404 412
405 if (ip_nat_pptp_hook_inbound) 413 ip_nat_pptp_inbound = rcu_dereference(ip_nat_pptp_hook_inbound);
406 return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, 414 if (ip_nat_pptp_inbound)
407 pptpReq); 415 return ip_nat_pptp_inbound(pskb, ct, ctinfo, ctlh, pptpReq);
408 return NF_ACCEPT; 416 return NF_ACCEPT;
409 417
410invalid: 418invalid:
@@ -427,6 +435,7 @@ pptp_outbound_pkt(struct sk_buff **pskb,
427 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; 435 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
428 u_int16_t msg; 436 u_int16_t msg;
429 __be16 cid = 0, pcid = 0; 437 __be16 cid = 0, pcid = 0;
438 typeof(ip_nat_pptp_hook_outbound) ip_nat_pptp_outbound;
430 439
431 msg = ntohs(ctlh->messageType); 440 msg = ntohs(ctlh->messageType);
432 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); 441 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
@@ -492,9 +501,9 @@ pptp_outbound_pkt(struct sk_buff **pskb,
492 goto invalid; 501 goto invalid;
493 } 502 }
494 503
495 if (ip_nat_pptp_hook_outbound) 504 ip_nat_pptp_outbound = rcu_dereference(ip_nat_pptp_hook_outbound);
496 return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, 505 if (ip_nat_pptp_outbound)
497 pptpReq); 506 return ip_nat_pptp_outbound(pskb, ct, ctinfo, ctlh, pptpReq);
498 return NF_ACCEPT; 507 return NF_ACCEPT;
499 508
500invalid: 509invalid:
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 75f7c3db1619..91832eca4106 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -114,6 +114,7 @@ static int help(struct sk_buff **pskb,
114 u_int16_t dcc_port; 114 u_int16_t dcc_port;
115 int i, ret = NF_ACCEPT; 115 int i, ret = NF_ACCEPT;
116 char *addr_beg_p, *addr_end_p; 116 char *addr_beg_p, *addr_end_p;
117 typeof(ip_nat_irc_hook) ip_nat_irc;
117 118
118 DEBUGP("entered\n"); 119 DEBUGP("entered\n");
119 120
@@ -222,11 +223,12 @@ static int help(struct sk_buff **pskb,
222 { .tcp = { htons(0xFFFF) } }, 0xFF }}); 223 { .tcp = { htons(0xFFFF) } }, 0xFF }});
223 exp->expectfn = NULL; 224 exp->expectfn = NULL;
224 exp->flags = 0; 225 exp->flags = 0;
225 if (ip_nat_irc_hook) 226 ip_nat_irc = rcu_dereference(ip_nat_irc_hook);
226 ret = ip_nat_irc_hook(pskb, ctinfo, 227 if (ip_nat_irc)
227 addr_beg_p - ib_ptr, 228 ret = ip_nat_irc(pskb, ctinfo,
228 addr_end_p - addr_beg_p, 229 addr_beg_p - ib_ptr,
229 exp); 230 addr_end_p - addr_beg_p,
231 exp);
230 else if (ip_conntrack_expect_related(exp) != 0) 232 else if (ip_conntrack_expect_related(exp) != 0)
231 ret = NF_DROP; 233 ret = NF_DROP;
232 ip_conntrack_expect_put(exp); 234 ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 262d0d44ec1b..5fcf91d617cd 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -153,6 +153,7 @@ ctnetlink_dump_protoinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
153 return ret; 153 return ret;
154 154
155nfattr_failure: 155nfattr_failure:
156 ip_conntrack_proto_put(proto);
156 return -1; 157 return -1;
157} 158}
158 159
@@ -319,8 +320,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
319 } else if (events & (IPCT_NEW | IPCT_RELATED)) { 320 } else if (events & (IPCT_NEW | IPCT_RELATED)) {
320 type = IPCTNL_MSG_CT_NEW; 321 type = IPCTNL_MSG_CT_NEW;
321 flags = NLM_F_CREATE|NLM_F_EXCL; 322 flags = NLM_F_CREATE|NLM_F_EXCL;
322 /* dump everything */
323 events = ~0UL;
324 group = NFNLGRP_CONNTRACK_NEW; 323 group = NFNLGRP_CONNTRACK_NEW;
325 } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { 324 } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) {
326 type = IPCTNL_MSG_CT_NEW; 325 type = IPCTNL_MSG_CT_NEW;
@@ -355,28 +354,35 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
355 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0) 354 if (ctnetlink_dump_tuples(skb, tuple(ct, IP_CT_DIR_REPLY)) < 0)
356 goto nfattr_failure; 355 goto nfattr_failure;
357 NFA_NEST_END(skb, nest_parms); 356 NFA_NEST_END(skb, nest_parms);
358
359 /* NAT stuff is now a status flag */
360 if ((events & IPCT_STATUS || events & IPCT_NATINFO)
361 && ctnetlink_dump_status(skb, ct) < 0)
362 goto nfattr_failure;
363 if (events & IPCT_REFRESH
364 && ctnetlink_dump_timeout(skb, ct) < 0)
365 goto nfattr_failure;
366 if (events & IPCT_PROTOINFO
367 && ctnetlink_dump_protoinfo(skb, ct) < 0)
368 goto nfattr_failure;
369 if (events & IPCT_HELPINFO
370 && ctnetlink_dump_helpinfo(skb, ct) < 0)
371 goto nfattr_failure;
372 357
373 if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || 358 if (events & IPCT_DESTROY) {
374 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) 359 if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
375 goto nfattr_failure; 360 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
361 goto nfattr_failure;
362 } else {
363 if (ctnetlink_dump_status(skb, ct) < 0)
364 goto nfattr_failure;
376 365
377 if (events & IPCT_MARK 366 if (ctnetlink_dump_timeout(skb, ct) < 0)
378 && ctnetlink_dump_mark(skb, ct) < 0) 367 goto nfattr_failure;
379 goto nfattr_failure; 368
369 if (events & IPCT_PROTOINFO
370 && ctnetlink_dump_protoinfo(skb, ct) < 0)
371 goto nfattr_failure;
372
373 if ((events & IPCT_HELPER || ct->helper)
374 && ctnetlink_dump_helpinfo(skb, ct) < 0)
375 goto nfattr_failure;
376
377 if ((events & IPCT_MARK || ct->mark)
378 && ctnetlink_dump_mark(skb, ct) < 0)
379 goto nfattr_failure;
380
381 if (events & IPCT_COUNTER_FILLING &&
382 (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
383 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0))
384 goto nfattr_failure;
385 }
380 386
381 nlh->nlmsg_len = skb->tail - b; 387 nlh->nlmsg_len = skb->tail - b;
382 nfnetlink_send(skb, 0, group, 0); 388 nfnetlink_send(skb, 0, group, 0);
@@ -742,7 +748,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
742 ip_conntrack_put(ct); 748 ip_conntrack_put(ct);
743 return -ENOMEM; 749 return -ENOMEM;
744 } 750 }
745 NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
746 751
747 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 752 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
748 IPCTNL_MSG_CT_NEW, 1, ct); 753 IPCTNL_MSG_CT_NEW, 1, ct);
@@ -945,9 +950,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
945 ct->timeout.expires = jiffies + ct->timeout.expires * HZ; 950 ct->timeout.expires = jiffies + ct->timeout.expires * HZ;
946 ct->status |= IPS_CONFIRMED; 951 ct->status |= IPS_CONFIRMED;
947 952
948 err = ctnetlink_change_status(ct, cda); 953 if (cda[CTA_STATUS-1]) {
949 if (err < 0) 954 err = ctnetlink_change_status(ct, cda);
950 goto err; 955 if (err < 0)
956 goto err;
957 }
951 958
952 if (cda[CTA_PROTOINFO-1]) { 959 if (cda[CTA_PROTOINFO-1]) {
953 err = ctnetlink_change_protoinfo(ct, cda); 960 err = ctnetlink_change_protoinfo(ct, cda);
@@ -1256,7 +1263,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1256 if (err < 0) 1263 if (err < 0)
1257 return err; 1264 return err;
1258 1265
1259 exp = ip_conntrack_expect_find(&tuple); 1266 exp = ip_conntrack_expect_find_get(&tuple);
1260 if (!exp) 1267 if (!exp)
1261 return -ENOENT; 1268 return -ENOENT;
1262 1269
@@ -1272,8 +1279,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1272 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 1279 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
1273 if (!skb2) 1280 if (!skb2)
1274 goto out; 1281 goto out;
1275 NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid; 1282
1276
1277 err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 1283 err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
1278 nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, 1284 nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW,
1279 1, exp); 1285 1, exp);
@@ -1310,7 +1316,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1310 return err; 1316 return err;
1311 1317
1312 /* bump usage count to 2 */ 1318 /* bump usage count to 2 */
1313 exp = ip_conntrack_expect_find(&tuple); 1319 exp = ip_conntrack_expect_find_get(&tuple);
1314 if (!exp) 1320 if (!exp)
1315 return -ENOENT; 1321 return -ENOENT;
1316 1322
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 5fe026f467d3..ac1c49ef36a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -34,8 +34,6 @@
34#include <linux/interrupt.h> 34#include <linux/interrupt.h>
35 35
36static DEFINE_RWLOCK(ip_ct_gre_lock); 36static DEFINE_RWLOCK(ip_ct_gre_lock);
37#define ASSERT_READ_LOCK(x)
38#define ASSERT_WRITE_LOCK(x)
39 37
40#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 38#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
41#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 39#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
index f4f75995a9e4..3a26d63eed88 100644
--- a/net/ipv4/netfilter/ip_conntrack_sip.c
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -52,20 +52,56 @@ unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
52 const char *dptr); 52 const char *dptr);
53EXPORT_SYMBOL_GPL(ip_nat_sdp_hook); 53EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
54 54
55int ct_sip_get_info(const char *dptr, size_t dlen,
56 unsigned int *matchoff,
57 unsigned int *matchlen,
58 struct sip_header_nfo *hnfo);
59EXPORT_SYMBOL_GPL(ct_sip_get_info);
60
61
62static int digits_len(const char *dptr, const char *limit, int *shift); 55static int digits_len(const char *dptr, const char *limit, int *shift);
63static int epaddr_len(const char *dptr, const char *limit, int *shift); 56static int epaddr_len(const char *dptr, const char *limit, int *shift);
64static int skp_digits_len(const char *dptr, const char *limit, int *shift); 57static int skp_digits_len(const char *dptr, const char *limit, int *shift);
65static int skp_epaddr_len(const char *dptr, const char *limit, int *shift); 58static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
66 59
67struct sip_header_nfo ct_sip_hdrs[] = { 60struct sip_header_nfo {
68 { /* Via header */ 61 const char *lname;
62 const char *sname;
63 const char *ln_str;
64 size_t lnlen;
65 size_t snlen;
66 size_t ln_strlen;
67 int case_sensitive;
68 int (*match_len)(const char *, const char *, int *);
69};
70
71static struct sip_header_nfo ct_sip_hdrs[] = {
72 [POS_REG_REQ_URI] = { /* SIP REGISTER request URI */
73 .lname = "sip:",
74 .lnlen = sizeof("sip:") - 1,
75 .ln_str = ":",
76 .ln_strlen = sizeof(":") - 1,
77 .match_len = epaddr_len
78 },
79 [POS_REQ_URI] = { /* SIP request URI */
80 .lname = "sip:",
81 .lnlen = sizeof("sip:") - 1,
82 .ln_str = "@",
83 .ln_strlen = sizeof("@") - 1,
84 .match_len = epaddr_len
85 },
86 [POS_FROM] = { /* SIP From header */
87 .lname = "From:",
88 .lnlen = sizeof("From:") - 1,
89 .sname = "\r\nf:",
90 .snlen = sizeof("\r\nf:") - 1,
91 .ln_str = "sip:",
92 .ln_strlen = sizeof("sip:") - 1,
93 .match_len = skp_epaddr_len,
94 },
95 [POS_TO] = { /* SIP To header */
96 .lname = "To:",
97 .lnlen = sizeof("To:") - 1,
98 .sname = "\r\nt:",
99 .snlen = sizeof("\r\nt:") - 1,
100 .ln_str = "sip:",
101 .ln_strlen = sizeof("sip:") - 1,
102 .match_len = skp_epaddr_len,
103 },
104 [POS_VIA] = { /* SIP Via header */
69 .lname = "Via:", 105 .lname = "Via:",
70 .lnlen = sizeof("Via:") - 1, 106 .lnlen = sizeof("Via:") - 1,
71 .sname = "\r\nv:", 107 .sname = "\r\nv:",
@@ -74,7 +110,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
74 .ln_strlen = sizeof("UDP ") - 1, 110 .ln_strlen = sizeof("UDP ") - 1,
75 .match_len = epaddr_len, 111 .match_len = epaddr_len,
76 }, 112 },
77 { /* Contact header */ 113 [POS_CONTACT] = { /* SIP Contact header */
78 .lname = "Contact:", 114 .lname = "Contact:",
79 .lnlen = sizeof("Contact:") - 1, 115 .lnlen = sizeof("Contact:") - 1,
80 .sname = "\r\nm:", 116 .sname = "\r\nm:",
@@ -83,7 +119,7 @@ struct sip_header_nfo ct_sip_hdrs[] = {
83 .ln_strlen = sizeof("sip:") - 1, 119 .ln_strlen = sizeof("sip:") - 1,
84 .match_len = skp_epaddr_len 120 .match_len = skp_epaddr_len
85 }, 121 },
86 { /* Content length header */ 122 [POS_CONTENT] = { /* SIP Content length header */
87 .lname = "Content-Length:", 123 .lname = "Content-Length:",
88 .lnlen = sizeof("Content-Length:") - 1, 124 .lnlen = sizeof("Content-Length:") - 1,
89 .sname = "\r\nl:", 125 .sname = "\r\nl:",
@@ -92,7 +128,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
92 .ln_strlen = sizeof(":") - 1, 128 .ln_strlen = sizeof(":") - 1,
93 .match_len = skp_digits_len 129 .match_len = skp_digits_len
94 }, 130 },
95 { /* SDP media info */ 131 [POS_MEDIA] = { /* SDP media info */
132 .case_sensitive = 1,
96 .lname = "\nm=", 133 .lname = "\nm=",
97 .lnlen = sizeof("\nm=") - 1, 134 .lnlen = sizeof("\nm=") - 1,
98 .sname = "\rm=", 135 .sname = "\rm=",
@@ -101,7 +138,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
101 .ln_strlen = sizeof("audio ") - 1, 138 .ln_strlen = sizeof("audio ") - 1,
102 .match_len = digits_len 139 .match_len = digits_len
103 }, 140 },
104 { /* SDP owner address*/ 141 [POS_OWNER] = { /* SDP owner address*/
142 .case_sensitive = 1,
105 .lname = "\no=", 143 .lname = "\no=",
106 .lnlen = sizeof("\no=") - 1, 144 .lnlen = sizeof("\no=") - 1,
107 .sname = "\ro=", 145 .sname = "\ro=",
@@ -110,7 +148,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
110 .ln_strlen = sizeof("IN IP4 ") - 1, 148 .ln_strlen = sizeof("IN IP4 ") - 1,
111 .match_len = epaddr_len 149 .match_len = epaddr_len
112 }, 150 },
113 { /* SDP connection info */ 151 [POS_CONNECTION] = { /* SDP connection info */
152 .case_sensitive = 1,
114 .lname = "\nc=", 153 .lname = "\nc=",
115 .lnlen = sizeof("\nc=") - 1, 154 .lnlen = sizeof("\nc=") - 1,
116 .sname = "\rc=", 155 .sname = "\rc=",
@@ -119,16 +158,8 @@ struct sip_header_nfo ct_sip_hdrs[] = {
119 .ln_strlen = sizeof("IN IP4 ") - 1, 158 .ln_strlen = sizeof("IN IP4 ") - 1,
120 .match_len = epaddr_len 159 .match_len = epaddr_len
121 }, 160 },
122 { /* Requests headers */ 161 [POS_SDP_HEADER] = { /* SDP version header */
123 .lname = "sip:", 162 .case_sensitive = 1,
124 .lnlen = sizeof("sip:") - 1,
125 .sname = "sip:",
126 .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */
127 .ln_str = "@",
128 .ln_strlen = sizeof("@") - 1,
129 .match_len = epaddr_len
130 },
131 { /* SDP version header */
132 .lname = "\nv=", 163 .lname = "\nv=",
133 .lnlen = sizeof("\nv=") - 1, 164 .lnlen = sizeof("\nv=") - 1,
134 .sname = "\rv=", 165 .sname = "\rv=",
@@ -138,7 +169,6 @@ struct sip_header_nfo ct_sip_hdrs[] = {
138 .match_len = digits_len 169 .match_len = digits_len
139 } 170 }
140}; 171};
141EXPORT_SYMBOL_GPL(ct_sip_hdrs);
142 172
143/* get line lenght until first CR or LF seen. */ 173/* get line lenght until first CR or LF seen. */
144int ct_sip_lnlen(const char *line, const char *limit) 174int ct_sip_lnlen(const char *line, const char *limit)
@@ -159,13 +189,19 @@ EXPORT_SYMBOL_GPL(ct_sip_lnlen);
159 189
160/* Linear string search, case sensitive. */ 190/* Linear string search, case sensitive. */
161const char *ct_sip_search(const char *needle, const char *haystack, 191const char *ct_sip_search(const char *needle, const char *haystack,
162 size_t needle_len, size_t haystack_len) 192 size_t needle_len, size_t haystack_len,
193 int case_sensitive)
163{ 194{
164 const char *limit = haystack + (haystack_len - needle_len); 195 const char *limit = haystack + (haystack_len - needle_len);
165 196
166 while (haystack <= limit) { 197 while (haystack <= limit) {
167 if (memcmp(haystack, needle, needle_len) == 0) 198 if (case_sensitive) {
168 return haystack; 199 if (strncmp(haystack, needle, needle_len) == 0)
200 return haystack;
201 } else {
202 if (strnicmp(haystack, needle, needle_len) == 0)
203 return haystack;
204 }
169 haystack++; 205 haystack++;
170 } 206 }
171 return NULL; 207 return NULL;
@@ -263,8 +299,9 @@ static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
263int ct_sip_get_info(const char *dptr, size_t dlen, 299int ct_sip_get_info(const char *dptr, size_t dlen,
264 unsigned int *matchoff, 300 unsigned int *matchoff,
265 unsigned int *matchlen, 301 unsigned int *matchlen,
266 struct sip_header_nfo *hnfo) 302 enum sip_header_pos pos)
267{ 303{
304 struct sip_header_nfo *hnfo = &ct_sip_hdrs[pos];
268 const char *limit, *aux, *k = dptr; 305 const char *limit, *aux, *k = dptr;
269 int shift = 0; 306 int shift = 0;
270 307
@@ -272,12 +309,14 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
272 309
273 while (dptr <= limit) { 310 while (dptr <= limit) {
274 if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) && 311 if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
275 (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { 312 (hnfo->sname == NULL ||
313 strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
276 dptr++; 314 dptr++;
277 continue; 315 continue;
278 } 316 }
279 aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen, 317 aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
280 ct_sip_lnlen(dptr, limit)); 318 ct_sip_lnlen(dptr, limit),
319 hnfo->case_sensitive);
281 if (!aux) { 320 if (!aux) {
282 DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, 321 DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
283 hnfo->lname); 322 hnfo->lname);
@@ -298,6 +337,7 @@ int ct_sip_get_info(const char *dptr, size_t dlen,
298 DEBUGP("%s header not found.\n", hnfo->lname); 337 DEBUGP("%s header not found.\n", hnfo->lname);
299 return 0; 338 return 0;
300} 339}
340EXPORT_SYMBOL_GPL(ct_sip_get_info);
301 341
302static int set_expected_rtp(struct sk_buff **pskb, 342static int set_expected_rtp(struct sk_buff **pskb,
303 struct ip_conntrack *ct, 343 struct ip_conntrack *ct,
@@ -308,6 +348,7 @@ static int set_expected_rtp(struct sk_buff **pskb,
308 struct ip_conntrack_expect *exp; 348 struct ip_conntrack_expect *exp;
309 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 349 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
310 int ret; 350 int ret;
351 typeof(ip_nat_sdp_hook) ip_nat_sdp;
311 352
312 exp = ip_conntrack_expect_alloc(ct); 353 exp = ip_conntrack_expect_alloc(ct);
313 if (exp == NULL) 354 if (exp == NULL)
@@ -328,8 +369,9 @@ static int set_expected_rtp(struct sk_buff **pskb,
328 exp->expectfn = NULL; 369 exp->expectfn = NULL;
329 exp->flags = 0; 370 exp->flags = 0;
330 371
331 if (ip_nat_sdp_hook) 372 ip_nat_sdp = rcu_dereference(ip_nat_sdp_hook);
332 ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr); 373 if (ip_nat_sdp)
374 ret = ip_nat_sdp(pskb, ctinfo, exp, dptr);
333 else { 375 else {
334 if (ip_conntrack_expect_related(exp) != 0) 376 if (ip_conntrack_expect_related(exp) != 0)
335 ret = NF_DROP; 377 ret = NF_DROP;
@@ -351,6 +393,7 @@ static int sip_help(struct sk_buff **pskb,
351 int matchoff, matchlen; 393 int matchoff, matchlen;
352 __be32 ipaddr; 394 __be32 ipaddr;
353 u_int16_t port; 395 u_int16_t port;
396 typeof(ip_nat_sip_hook) ip_nat_sip;
354 397
355 /* No Data ? */ 398 /* No Data ? */
356 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); 399 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
@@ -368,8 +411,9 @@ static int sip_help(struct sk_buff **pskb,
368 goto out; 411 goto out;
369 } 412 }
370 413
371 if (ip_nat_sip_hook) { 414 ip_nat_sip = rcu_dereference(ip_nat_sip_hook);
372 if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) { 415 if (ip_nat_sip) {
416 if (!ip_nat_sip(pskb, ctinfo, ct, &dptr)) {
373 ret = NF_DROP; 417 ret = NF_DROP;
374 goto out; 418 goto out;
375 } 419 }
@@ -389,7 +433,7 @@ static int sip_help(struct sk_buff **pskb,
389 } 433 }
390 /* Get ip and port address from SDP packet. */ 434 /* Get ip and port address from SDP packet. */
391 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, 435 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
392 &ct_sip_hdrs[POS_CONNECTION]) > 0) { 436 POS_CONNECTION) > 0) {
393 437
394 /* We'll drop only if there are parse problems. */ 438 /* We'll drop only if there are parse problems. */
395 if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr, 439 if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
@@ -398,7 +442,7 @@ static int sip_help(struct sk_buff **pskb,
398 goto out; 442 goto out;
399 } 443 }
400 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, 444 if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
401 &ct_sip_hdrs[POS_MEDIA]) > 0) { 445 POS_MEDIA) > 0) {
402 446
403 port = simple_strtoul(dptr + matchoff, NULL, 10); 447 port = simple_strtoul(dptr + matchoff, NULL, 10);
404 if (port < 1024) { 448 if (port < 1024) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 02135756562e..86efb5449676 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -28,9 +28,6 @@
28#include <net/ip.h> 28#include <net/ip.h>
29#include <net/route.h> 29#include <net/route.h>
30 30
31#define ASSERT_READ_LOCK(x)
32#define ASSERT_WRITE_LOCK(x)
33
34#include <linux/netfilter_ipv4/ip_conntrack.h> 31#include <linux/netfilter_ipv4/ip_conntrack.h>
35#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 32#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
36#include <linux/netfilter_ipv4/ip_conntrack_core.h> 33#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -139,7 +136,6 @@ static int ct_seq_show(struct seq_file *s, void *v)
139 const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash); 136 const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
140 struct ip_conntrack_protocol *proto; 137 struct ip_conntrack_protocol *proto;
141 138
142 ASSERT_READ_LOCK(&ip_conntrack_lock);
143 IP_NF_ASSERT(conntrack); 139 IP_NF_ASSERT(conntrack);
144 140
145 /* we only want to print DIR_ORIGINAL */ 141 /* we only want to print DIR_ORIGINAL */
@@ -926,7 +922,7 @@ EXPORT_SYMBOL(__ip_ct_refresh_acct);
926EXPORT_SYMBOL(ip_conntrack_expect_alloc); 922EXPORT_SYMBOL(ip_conntrack_expect_alloc);
927EXPORT_SYMBOL(ip_conntrack_expect_put); 923EXPORT_SYMBOL(ip_conntrack_expect_put);
928EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); 924EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
929EXPORT_SYMBOL_GPL(ip_conntrack_expect_find); 925EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get);
930EXPORT_SYMBOL(ip_conntrack_expect_related); 926EXPORT_SYMBOL(ip_conntrack_expect_related);
931EXPORT_SYMBOL(ip_conntrack_unexpect_related); 927EXPORT_SYMBOL(ip_conntrack_unexpect_related);
932EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); 928EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c
index fe0b634dd377..ef56de2eff0c 100644
--- a/net/ipv4/netfilter/ip_conntrack_tftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_tftp.c
@@ -50,6 +50,7 @@ static int tftp_help(struct sk_buff **pskb,
50 struct tftphdr _tftph, *tfh; 50 struct tftphdr _tftph, *tfh;
51 struct ip_conntrack_expect *exp; 51 struct ip_conntrack_expect *exp;
52 unsigned int ret = NF_ACCEPT; 52 unsigned int ret = NF_ACCEPT;
53 typeof(ip_nat_tftp_hook) ip_nat_tftp;
53 54
54 tfh = skb_header_pointer(*pskb, 55 tfh = skb_header_pointer(*pskb,
55 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), 56 (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr),
@@ -81,8 +82,9 @@ static int tftp_help(struct sk_buff **pskb,
81 DEBUGP("expect: "); 82 DEBUGP("expect: ");
82 DUMP_TUPLE(&exp->tuple); 83 DUMP_TUPLE(&exp->tuple);
83 DUMP_TUPLE(&exp->mask); 84 DUMP_TUPLE(&exp->mask);
84 if (ip_nat_tftp_hook) 85 ip_nat_tftp = rcu_dereference(ip_nat_tftp_hook);
85 ret = ip_nat_tftp_hook(pskb, ctinfo, exp); 86 if (ip_nat_tftp)
87 ret = ip_nat_tftp(pskb, ctinfo, exp);
86 else if (ip_conntrack_expect_related(exp) != 0) 88 else if (ip_conntrack_expect_related(exp) != 0)
87 ret = NF_DROP; 89 ret = NF_DROP;
88 ip_conntrack_expect_put(exp); 90 ip_conntrack_expect_put(exp);
diff --git a/net/ipv4/netfilter/ip_nat_amanda.c b/net/ipv4/netfilter/ip_nat_amanda.c
index 3a888715bbf3..85df1a9aed33 100644
--- a/net/ipv4/netfilter/ip_nat_amanda.c
+++ b/net/ipv4/netfilter/ip_nat_amanda.c
@@ -70,15 +70,14 @@ static unsigned int help(struct sk_buff **pskb,
70 70
71static void __exit ip_nat_amanda_fini(void) 71static void __exit ip_nat_amanda_fini(void)
72{ 72{
73 ip_nat_amanda_hook = NULL; 73 rcu_assign_pointer(ip_nat_amanda_hook, NULL);
74 /* Make sure noone calls it, meanwhile. */ 74 synchronize_rcu();
75 synchronize_net();
76} 75}
77 76
78static int __init ip_nat_amanda_init(void) 77static int __init ip_nat_amanda_init(void)
79{ 78{
80 BUG_ON(ip_nat_amanda_hook); 79 BUG_ON(rcu_dereference(ip_nat_amanda_hook));
81 ip_nat_amanda_hook = help; 80 rcu_assign_pointer(ip_nat_amanda_hook, help);
82 return 0; 81 return 0;
83} 82}
84 83
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 4b6260a97408..9d1a5175dcd4 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -362,12 +362,10 @@ manip_pkt(u_int16_t proto,
362 iph = (void *)(*pskb)->data + iphdroff; 362 iph = (void *)(*pskb)->data + iphdroff;
363 363
364 if (maniptype == IP_NAT_MANIP_SRC) { 364 if (maniptype == IP_NAT_MANIP_SRC) {
365 iph->check = nf_csum_update(~iph->saddr, target->src.ip, 365 nf_csum_replace4(&iph->check, iph->saddr, target->src.ip);
366 iph->check);
367 iph->saddr = target->src.ip; 366 iph->saddr = target->src.ip;
368 } else { 367 } else {
369 iph->check = nf_csum_update(~iph->daddr, target->dst.ip, 368 nf_csum_replace4(&iph->check, iph->daddr, target->dst.ip);
370 iph->check);
371 iph->daddr = target->dst.ip; 369 iph->daddr = target->dst.ip;
372 } 370 }
373 return 1; 371 return 1;
diff --git a/net/ipv4/netfilter/ip_nat_ftp.c b/net/ipv4/netfilter/ip_nat_ftp.c
index a71c233d8112..913960e1380f 100644
--- a/net/ipv4/netfilter/ip_nat_ftp.c
+++ b/net/ipv4/netfilter/ip_nat_ftp.c
@@ -156,15 +156,14 @@ static unsigned int ip_nat_ftp(struct sk_buff **pskb,
156 156
157static void __exit ip_nat_ftp_fini(void) 157static void __exit ip_nat_ftp_fini(void)
158{ 158{
159 ip_nat_ftp_hook = NULL; 159 rcu_assign_pointer(ip_nat_ftp_hook, NULL);
160 /* Make sure noone calls it, meanwhile. */ 160 synchronize_rcu();
161 synchronize_net();
162} 161}
163 162
164static int __init ip_nat_ftp_init(void) 163static int __init ip_nat_ftp_init(void)
165{ 164{
166 BUG_ON(ip_nat_ftp_hook); 165 BUG_ON(rcu_dereference(ip_nat_ftp_hook));
167 ip_nat_ftp_hook = ip_nat_ftp; 166 rcu_assign_pointer(ip_nat_ftp_hook, ip_nat_ftp);
168 return 0; 167 return 0;
169} 168}
170 169
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 3bf858480558..ee80feb4b2a9 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -188,10 +188,8 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
188 csum_partial((char *)tcph, 188 csum_partial((char *)tcph,
189 datalen, 0)); 189 datalen, 0));
190 } else 190 } else
191 tcph->check = nf_proto_csum_update(*pskb, 191 nf_proto_csum_replace2(&tcph->check, *pskb,
192 htons(oldlen) ^ htons(0xFFFF), 192 htons(oldlen), htons(datalen), 1);
193 htons(datalen),
194 tcph->check, 1);
195 193
196 if (rep_len != match_len) { 194 if (rep_len != match_len) {
197 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 195 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
@@ -264,12 +262,10 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
264 csum_partial((char *)udph, 262 csum_partial((char *)udph,
265 datalen, 0)); 263 datalen, 0));
266 if (!udph->check) 264 if (!udph->check)
267 udph->check = -1; 265 udph->check = CSUM_MANGLED_0;
268 } else 266 } else
269 udph->check = nf_proto_csum_update(*pskb, 267 nf_proto_csum_replace2(&udph->check, *pskb,
270 htons(oldlen) ^ htons(0xFFFF), 268 htons(oldlen), htons(datalen), 1);
271 htons(datalen),
272 udph->check, 1);
273 return 1; 269 return 1;
274} 270}
275EXPORT_SYMBOL(ip_nat_mangle_udp_packet); 271EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
@@ -307,14 +303,10 @@ sack_adjust(struct sk_buff *skb,
307 ntohl(sack->start_seq), new_start_seq, 303 ntohl(sack->start_seq), new_start_seq,
308 ntohl(sack->end_seq), new_end_seq); 304 ntohl(sack->end_seq), new_end_seq);
309 305
310 tcph->check = nf_proto_csum_update(skb, 306 nf_proto_csum_replace4(&tcph->check, skb,
311 ~sack->start_seq, 307 sack->start_seq, new_start_seq, 0);
312 new_start_seq, 308 nf_proto_csum_replace4(&tcph->check, skb,
313 tcph->check, 0); 309 sack->end_seq, new_end_seq, 0);
314 tcph->check = nf_proto_csum_update(skb,
315 ~sack->end_seq,
316 new_end_seq,
317 tcph->check, 0);
318 sack->start_seq = new_start_seq; 310 sack->start_seq = new_start_seq;
319 sack->end_seq = new_end_seq; 311 sack->end_seq = new_end_seq;
320 sackoff += sizeof(*sack); 312 sackoff += sizeof(*sack);
@@ -397,10 +389,8 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
397 else 389 else
398 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); 390 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
399 391
400 tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq, 392 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
401 tcph->check, 0); 393 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
402 tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack,
403 tcph->check, 0);
404 394
405 DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", 395 DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
406 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), 396 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index 4a7d34466ee2..bdc99ef6159e 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -563,25 +563,25 @@ static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
563/****************************************************************************/ 563/****************************************************************************/
564static int __init init(void) 564static int __init init(void)
565{ 565{
566 BUG_ON(set_h245_addr_hook != NULL); 566 BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
567 BUG_ON(set_h225_addr_hook != NULL); 567 BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
568 BUG_ON(set_sig_addr_hook != NULL); 568 BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
569 BUG_ON(set_ras_addr_hook != NULL); 569 BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
570 BUG_ON(nat_rtp_rtcp_hook != NULL); 570 BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
571 BUG_ON(nat_t120_hook != NULL); 571 BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
572 BUG_ON(nat_h245_hook != NULL); 572 BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
573 BUG_ON(nat_callforwarding_hook != NULL); 573 BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
574 BUG_ON(nat_q931_hook != NULL); 574 BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
575 575
576 set_h245_addr_hook = set_h245_addr; 576 rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
577 set_h225_addr_hook = set_h225_addr; 577 rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
578 set_sig_addr_hook = set_sig_addr; 578 rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
579 set_ras_addr_hook = set_ras_addr; 579 rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
580 nat_rtp_rtcp_hook = nat_rtp_rtcp; 580 rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
581 nat_t120_hook = nat_t120; 581 rcu_assign_pointer(nat_t120_hook, nat_t120);
582 nat_h245_hook = nat_h245; 582 rcu_assign_pointer(nat_h245_hook, nat_h245);
583 nat_callforwarding_hook = nat_callforwarding; 583 rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
584 nat_q931_hook = nat_q931; 584 rcu_assign_pointer(nat_q931_hook, nat_q931);
585 585
586 DEBUGP("ip_nat_h323: init success\n"); 586 DEBUGP("ip_nat_h323: init success\n");
587 return 0; 587 return 0;
@@ -590,16 +590,16 @@ static int __init init(void)
590/****************************************************************************/ 590/****************************************************************************/
591static void __exit fini(void) 591static void __exit fini(void)
592{ 592{
593 set_h245_addr_hook = NULL; 593 rcu_assign_pointer(set_h245_addr_hook, NULL);
594 set_h225_addr_hook = NULL; 594 rcu_assign_pointer(set_h225_addr_hook, NULL);
595 set_sig_addr_hook = NULL; 595 rcu_assign_pointer(set_sig_addr_hook, NULL);
596 set_ras_addr_hook = NULL; 596 rcu_assign_pointer(set_ras_addr_hook, NULL);
597 nat_rtp_rtcp_hook = NULL; 597 rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
598 nat_t120_hook = NULL; 598 rcu_assign_pointer(nat_t120_hook, NULL);
599 nat_h245_hook = NULL; 599 rcu_assign_pointer(nat_h245_hook, NULL);
600 nat_callforwarding_hook = NULL; 600 rcu_assign_pointer(nat_callforwarding_hook, NULL);
601 nat_q931_hook = NULL; 601 rcu_assign_pointer(nat_q931_hook, NULL);
602 synchronize_net(); 602 synchronize_rcu();
603} 603}
604 604
605/****************************************************************************/ 605/****************************************************************************/
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
index 329fdcd7d702..ec957bbb5366 100644
--- a/net/ipv4/netfilter/ip_nat_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -101,7 +101,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct,
101 101
102 DEBUGP("trying to unexpect other dir: "); 102 DEBUGP("trying to unexpect other dir: ");
103 DUMP_TUPLE(&t); 103 DUMP_TUPLE(&t);
104 other_exp = ip_conntrack_expect_find(&t); 104 other_exp = ip_conntrack_expect_find_get(&t);
105 if (other_exp) { 105 if (other_exp) {
106 ip_conntrack_unexpect_related(other_exp); 106 ip_conntrack_unexpect_related(other_exp);
107 ip_conntrack_expect_put(other_exp); 107 ip_conntrack_expect_put(other_exp);
@@ -315,17 +315,17 @@ static int __init ip_nat_helper_pptp_init(void)
315 if (ret < 0) 315 if (ret < 0)
316 return ret; 316 return ret;
317 317
318 BUG_ON(ip_nat_pptp_hook_outbound); 318 BUG_ON(rcu_dereference(ip_nat_pptp_hook_outbound));
319 ip_nat_pptp_hook_outbound = &pptp_outbound_pkt; 319 rcu_assign_pointer(ip_nat_pptp_hook_outbound, pptp_outbound_pkt);
320 320
321 BUG_ON(ip_nat_pptp_hook_inbound); 321 BUG_ON(rcu_dereference(ip_nat_pptp_hook_inbound));
322 ip_nat_pptp_hook_inbound = &pptp_inbound_pkt; 322 rcu_assign_pointer(ip_nat_pptp_hook_inbound, pptp_inbound_pkt);
323 323
324 BUG_ON(ip_nat_pptp_hook_exp_gre); 324 BUG_ON(rcu_dereference(ip_nat_pptp_hook_exp_gre));
325 ip_nat_pptp_hook_exp_gre = &pptp_exp_gre; 325 rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, pptp_exp_gre);
326 326
327 BUG_ON(ip_nat_pptp_hook_expectfn); 327 BUG_ON(rcu_dereference(ip_nat_pptp_hook_expectfn));
328 ip_nat_pptp_hook_expectfn = &pptp_nat_expected; 328 rcu_assign_pointer(ip_nat_pptp_hook_expectfn, pptp_nat_expected);
329 329
330 printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); 330 printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
331 return 0; 331 return 0;
@@ -335,14 +335,13 @@ static void __exit ip_nat_helper_pptp_fini(void)
335{ 335{
336 DEBUGP("cleanup_module\n" ); 336 DEBUGP("cleanup_module\n" );
337 337
338 ip_nat_pptp_hook_expectfn = NULL; 338 rcu_assign_pointer(ip_nat_pptp_hook_expectfn, NULL);
339 ip_nat_pptp_hook_exp_gre = NULL; 339 rcu_assign_pointer(ip_nat_pptp_hook_exp_gre, NULL);
340 ip_nat_pptp_hook_inbound = NULL; 340 rcu_assign_pointer(ip_nat_pptp_hook_inbound, NULL);
341 ip_nat_pptp_hook_outbound = NULL; 341 rcu_assign_pointer(ip_nat_pptp_hook_outbound, NULL);
342 synchronize_rcu();
342 343
343 ip_nat_proto_gre_fini(); 344 ip_nat_proto_gre_fini();
344 /* Make sure noone calls it, meanwhile */
345 synchronize_net();
346 345
347 printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); 346 printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
348} 347}
diff --git a/net/ipv4/netfilter/ip_nat_irc.c b/net/ipv4/netfilter/ip_nat_irc.c
index a767123e082c..feb26b48f1d5 100644
--- a/net/ipv4/netfilter/ip_nat_irc.c
+++ b/net/ipv4/netfilter/ip_nat_irc.c
@@ -98,15 +98,14 @@ static unsigned int help(struct sk_buff **pskb,
98 98
99static void __exit ip_nat_irc_fini(void) 99static void __exit ip_nat_irc_fini(void)
100{ 100{
101 ip_nat_irc_hook = NULL; 101 rcu_assign_pointer(ip_nat_irc_hook, NULL);
102 /* Make sure noone calls it, meanwhile. */ 102 synchronize_rcu();
103 synchronize_net();
104} 103}
105 104
106static int __init ip_nat_irc_init(void) 105static int __init ip_nat_irc_init(void)
107{ 106{
108 BUG_ON(ip_nat_irc_hook); 107 BUG_ON(rcu_dereference(ip_nat_irc_hook));
109 ip_nat_irc_hook = help; 108 rcu_assign_pointer(ip_nat_irc_hook, help);
110 return 0; 109 return 0;
111} 110}
112 111
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
index bf91f9312b3c..95810202d849 100644
--- a/net/ipv4/netfilter/ip_nat_proto_gre.c
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -129,11 +129,9 @@ gre_manip_pkt(struct sk_buff **pskb,
129 } 129 }
130 if (greh->csum) { 130 if (greh->csum) {
131 /* FIXME: Never tested this code... */ 131 /* FIXME: Never tested this code... */
132 *(gre_csum(greh)) = 132 nf_proto_csum_replace4(gre_csum(greh), *pskb,
133 nf_proto_csum_update(*pskb, 133 *(gre_key(greh)),
134 ~*(gre_key(greh)), 134 tuple->dst.u.gre.key, 0);
135 tuple->dst.u.gre.key,
136 *(gre_csum(greh)), 0);
137 } 135 }
138 *(gre_key(greh)) = tuple->dst.u.gre.key; 136 *(gre_key(greh)) = tuple->dst.u.gre.key;
139 break; 137 break;
diff --git a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c
index 3f6efc13ac74..fb716edd5bc6 100644
--- a/net/ipv4/netfilter/ip_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c
@@ -24,8 +24,8 @@ icmp_in_range(const struct ip_conntrack_tuple *tuple,
24 const union ip_conntrack_manip_proto *min, 24 const union ip_conntrack_manip_proto *min,
25 const union ip_conntrack_manip_proto *max) 25 const union ip_conntrack_manip_proto *max)
26{ 26{
27 return (tuple->src.u.icmp.id >= min->icmp.id 27 return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
28 && tuple->src.u.icmp.id <= max->icmp.id); 28 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
29} 29}
30 30
31static int 31static int
@@ -66,10 +66,8 @@ icmp_manip_pkt(struct sk_buff **pskb,
66 return 0; 66 return 0;
67 67
68 hdr = (struct icmphdr *)((*pskb)->data + hdroff); 68 hdr = (struct icmphdr *)((*pskb)->data + hdroff);
69 hdr->checksum = nf_proto_csum_update(*pskb, 69 nf_proto_csum_replace2(&hdr->checksum, *pskb,
70 hdr->un.echo.id ^ htons(0xFFFF), 70 hdr->un.echo.id, tuple->src.u.icmp.id, 0);
71 tuple->src.u.icmp.id,
72 hdr->checksum, 0);
73 hdr->un.echo.id = tuple->src.u.icmp.id; 71 hdr->un.echo.id = tuple->src.u.icmp.id;
74 return 1; 72 return 1;
75} 73}
diff --git a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c
index 12deb13b93b1..b586d18b3fb3 100644
--- a/net/ipv4/netfilter/ip_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c
@@ -129,9 +129,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
129 if (hdrsize < sizeof(*hdr)) 129 if (hdrsize < sizeof(*hdr))
130 return 1; 130 return 1;
131 131
132 hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1); 132 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
133 hdr->check = nf_proto_csum_update(*pskb, oldport ^ htons(0xFFFF), newport, 133 nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
134 hdr->check, 0);
135 return 1; 134 return 1;
136} 135}
137 136
diff --git a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c
index 4bbec7730d18..5ced0877b32f 100644
--- a/net/ipv4/netfilter/ip_nat_proto_udp.c
+++ b/net/ipv4/netfilter/ip_nat_proto_udp.c
@@ -115,13 +115,10 @@ udp_manip_pkt(struct sk_buff **pskb,
115 } 115 }
116 116
117 if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { 117 if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
118 hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, 118 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
119 hdr->check, 1); 119 nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport, 0);
120 hdr->check = nf_proto_csum_update(*pskb,
121 *portptr ^ htons(0xFFFF), newport,
122 hdr->check, 0);
123 if (!hdr->check) 120 if (!hdr->check)
124 hdr->check = -1; 121 hdr->check = CSUM_MANGLED_0;
125 } 122 }
126 *portptr = newport; 123 *portptr = newport;
127 return 1; 124 return 1;
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
index 71fc2730a007..6223abc924ff 100644
--- a/net/ipv4/netfilter/ip_nat_sip.c
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -29,27 +29,70 @@ MODULE_DESCRIPTION("SIP NAT helper");
29#define DEBUGP(format, args...) 29#define DEBUGP(format, args...)
30#endif 30#endif
31 31
32extern struct sip_header_nfo ct_sip_hdrs[]; 32struct addr_map {
33 struct {
34 char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
35 char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
36 unsigned int srclen, srciplen;
37 unsigned int dstlen, dstiplen;
38 } addr[IP_CT_DIR_MAX];
39};
40
41static void addr_map_init(struct ip_conntrack *ct, struct addr_map *map)
42{
43 struct ip_conntrack_tuple *t;
44 enum ip_conntrack_dir dir;
45 unsigned int n;
46
47 for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
48 t = &ct->tuplehash[dir].tuple;
49
50 n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
51 NIPQUAD(t->src.ip));
52 map->addr[dir].srciplen = n;
53 n += sprintf(map->addr[dir].src + n, ":%u",
54 ntohs(t->src.u.udp.port));
55 map->addr[dir].srclen = n;
56
57 n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
58 NIPQUAD(t->dst.ip));
59 map->addr[dir].dstiplen = n;
60 n += sprintf(map->addr[dir].dst + n, ":%u",
61 ntohs(t->dst.u.udp.port));
62 map->addr[dir].dstlen = n;
63 }
64}
33 65
34static unsigned int mangle_sip_packet(struct sk_buff **pskb, 66static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
35 enum ip_conntrack_info ctinfo, 67 struct ip_conntrack *ct, const char **dptr, size_t dlen,
36 struct ip_conntrack *ct, 68 enum sip_header_pos pos, struct addr_map *map)
37 const char **dptr, size_t dlen,
38 char *buffer, int bufflen,
39 struct sip_header_nfo *hnfo)
40{ 69{
41 unsigned int matchlen, matchoff; 70 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
71 unsigned int matchlen, matchoff, addrlen;
72 char *addr;
42 73
43 if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0) 74 if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
44 return 0; 75 return 1;
76
77 if ((matchlen == map->addr[dir].srciplen ||
78 matchlen == map->addr[dir].srclen) &&
79 memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
80 addr = map->addr[!dir].dst;
81 addrlen = map->addr[!dir].dstlen;
82 } else if ((matchlen == map->addr[dir].dstiplen ||
83 matchlen == map->addr[dir].dstlen) &&
84 memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
85 addr = map->addr[!dir].src;
86 addrlen = map->addr[!dir].srclen;
87 } else
88 return 1;
45 89
46 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, 90 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
47 matchoff, matchlen, buffer, bufflen)) 91 matchoff, matchlen, addr, addrlen))
48 return 0; 92 return 0;
49
50 /* We need to reload this. Thanks Patrick. */
51 *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); 93 *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
52 return 1; 94 return 1;
95
53} 96}
54 97
55static unsigned int ip_nat_sip(struct sk_buff **pskb, 98static unsigned int ip_nat_sip(struct sk_buff **pskb,
@@ -57,70 +100,61 @@ static unsigned int ip_nat_sip(struct sk_buff **pskb,
57 struct ip_conntrack *ct, 100 struct ip_conntrack *ct,
58 const char **dptr) 101 const char **dptr)
59{ 102{
60 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 103 enum sip_header_pos pos;
61 char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; 104 struct addr_map map;
62 unsigned int bufflen, dataoff; 105 int dataoff, datalen;
63 __be32 ip;
64 __be16 port;
65 106
66 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); 107 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
108 datalen = (*pskb)->len - dataoff;
109 if (datalen < sizeof("SIP/2.0") - 1)
110 return NF_DROP;
111
112 addr_map_init(ct, &map);
113
114 /* Basic rules: requests and responses. */
115 if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
116 /* 10.2: Constructing the REGISTER Request:
117 *
118 * The "userinfo" and "@" components of the SIP URI MUST NOT
119 * be present.
120 */
121 if (datalen >= sizeof("REGISTER") - 1 &&
122 strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
123 pos = POS_REG_REQ_URI;
124 else
125 pos = POS_REQ_URI;
126
127 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
128 return NF_DROP;
129 }
130
131 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
132 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
133 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
134 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
135 return NF_DROP;
136 return NF_ACCEPT;
137}
67 138
68 ip = ct->tuplehash[!dir].tuple.dst.ip; 139static unsigned int mangle_sip_packet(struct sk_buff **pskb,
69 port = ct->tuplehash[!dir].tuple.dst.u.udp.port; 140 enum ip_conntrack_info ctinfo,
70 bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port)); 141 struct ip_conntrack *ct,
142 const char **dptr, size_t dlen,
143 char *buffer, int bufflen,
144 enum sip_header_pos pos)
145{
146 unsigned int matchlen, matchoff;
71 147
72 /* short packet ? */ 148 if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, pos) <= 0)
73 if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
74 return 0; 149 return 0;
75 150
76 /* Basic rules: requests and responses. */ 151 if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
77 if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) { 152 matchoff, matchlen, buffer, bufflen))
78 const char *aux; 153 return 0;
79
80 if ((ctinfo) < IP_CT_IS_REPLY) {
81 mangle_sip_packet(pskb, ctinfo, ct, dptr,
82 (*pskb)->len - dataoff,
83 buffer, bufflen,
84 &ct_sip_hdrs[POS_CONTACT]);
85 return 1;
86 }
87 154
88 if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, 155 /* We need to reload this. Thanks Patrick. */
89 (*pskb)->len - dataoff, 156 *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
90 buffer, bufflen, &ct_sip_hdrs[POS_VIA])) 157 return 1;
91 return 0;
92
93 /* This search should ignore case, but later.. */
94 aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
95 (*pskb)->len - dataoff);
96 if (!aux)
97 return 0;
98
99 if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
100 ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
101 return 1;
102
103 return mangle_sip_packet(pskb, ctinfo, ct, dptr,
104 (*pskb)->len - dataoff,
105 buffer, bufflen,
106 &ct_sip_hdrs[POS_CONTACT]);
107 }
108 if ((ctinfo) < IP_CT_IS_REPLY) {
109 if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
110 (*pskb)->len - dataoff,
111 buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
112 return 0;
113
114 /* Mangle Contact if exists only. - watch udp_nat_mangle()! */
115 mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
116 buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
117 return 1;
118 }
119 /* This mangle requests headers. */
120 return mangle_sip_packet(pskb, ctinfo, ct, dptr,
121 ct_sip_lnlen(*dptr,
122 *dptr + (*pskb)->len - dataoff),
123 buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
124} 158}
125 159
126static int mangle_content_len(struct sk_buff **pskb, 160static int mangle_content_len(struct sk_buff **pskb,
@@ -136,7 +170,7 @@ static int mangle_content_len(struct sk_buff **pskb,
136 170
137 /* Get actual SDP lenght */ 171 /* Get actual SDP lenght */
138 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, 172 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
139 &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) { 173 &matchlen, POS_SDP_HEADER) > 0) {
140 174
141 /* since ct_sip_get_info() give us a pointer passing 'v=' 175 /* since ct_sip_get_info() give us a pointer passing 'v='
142 we need to add 2 bytes in this count. */ 176 we need to add 2 bytes in this count. */
@@ -144,7 +178,7 @@ static int mangle_content_len(struct sk_buff **pskb,
144 178
145 /* Now, update SDP lenght */ 179 /* Now, update SDP lenght */
146 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, 180 if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
147 &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) { 181 &matchlen, POS_CONTENT) > 0) {
148 182
149 bufflen = sprintf(buffer, "%u", c_len); 183 bufflen = sprintf(buffer, "%u", c_len);
150 184
@@ -170,17 +204,17 @@ static unsigned int mangle_sdp(struct sk_buff **pskb,
170 /* Mangle owner and contact info. */ 204 /* Mangle owner and contact info. */
171 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); 205 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
172 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, 206 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
173 buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) 207 buffer, bufflen, POS_OWNER))
174 return 0; 208 return 0;
175 209
176 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, 210 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
177 buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION])) 211 buffer, bufflen, POS_CONNECTION))
178 return 0; 212 return 0;
179 213
180 /* Mangle media port. */ 214 /* Mangle media port. */
181 bufflen = sprintf(buffer, "%u", port); 215 bufflen = sprintf(buffer, "%u", port);
182 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, 216 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
183 buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) 217 buffer, bufflen, POS_MEDIA))
184 return 0; 218 return 0;
185 219
186 return mangle_content_len(pskb, ctinfo, ct, dptr); 220 return mangle_content_len(pskb, ctinfo, ct, dptr);
@@ -230,18 +264,17 @@ static unsigned int ip_nat_sdp(struct sk_buff **pskb,
230 264
231static void __exit fini(void) 265static void __exit fini(void)
232{ 266{
233 ip_nat_sip_hook = NULL; 267 rcu_assign_pointer(ip_nat_sip_hook, NULL);
234 ip_nat_sdp_hook = NULL; 268 rcu_assign_pointer(ip_nat_sdp_hook, NULL);
235 /* Make sure noone calls it, meanwhile. */ 269 synchronize_rcu();
236 synchronize_net();
237} 270}
238 271
239static int __init init(void) 272static int __init init(void)
240{ 273{
241 BUG_ON(ip_nat_sip_hook); 274 BUG_ON(rcu_dereference(ip_nat_sip_hook));
242 BUG_ON(ip_nat_sdp_hook); 275 BUG_ON(rcu_dereference(ip_nat_sdp_hook));
243 ip_nat_sip_hook = ip_nat_sip; 276 rcu_assign_pointer(ip_nat_sip_hook, ip_nat_sip);
244 ip_nat_sdp_hook = ip_nat_sdp; 277 rcu_assign_pointer(ip_nat_sdp_hook, ip_nat_sdp);
245 return 0; 278 return 0;
246} 279}
247 280
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index 168f45fa1898..c3d9f3b090c4 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -64,7 +64,7 @@ MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
64 64
65#define SNMP_PORT 161 65#define SNMP_PORT 161
66#define SNMP_TRAP_PORT 162 66#define SNMP_TRAP_PORT 162
67#define NOCT1(n) (u_int8_t )((n) & 0xff) 67#define NOCT1(n) (*(u8 *)n)
68 68
69static int debug; 69static int debug;
70static DEFINE_SPINLOCK(snmp_lock); 70static DEFINE_SPINLOCK(snmp_lock);
@@ -613,7 +613,7 @@ struct snmp_v1_trap
613static inline void mangle_address(unsigned char *begin, 613static inline void mangle_address(unsigned char *begin,
614 unsigned char *addr, 614 unsigned char *addr,
615 const struct oct1_map *map, 615 const struct oct1_map *map,
616 u_int16_t *check); 616 __sum16 *check);
617struct snmp_cnv 617struct snmp_cnv
618{ 618{
619 unsigned int class; 619 unsigned int class;
@@ -873,38 +873,24 @@ static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
873 * Fast checksum update for possibly oddly-aligned UDP byte, from the 873 * Fast checksum update for possibly oddly-aligned UDP byte, from the
874 * code example in the draft. 874 * code example in the draft.
875 */ 875 */
876static void fast_csum(unsigned char *csum, 876static void fast_csum(__sum16 *csum,
877 const unsigned char *optr, 877 const unsigned char *optr,
878 const unsigned char *nptr, 878 const unsigned char *nptr,
879 int odd) 879 int offset)
880{ 880{
881 long x, old, new; 881 unsigned char s[4];
882 882
883 x = csum[0] * 256 + csum[1]; 883 if (offset & 1) {
884 884 s[0] = s[2] = 0;
885 x =~ x & 0xFFFF; 885 s[1] = ~*optr;
886 886 s[3] = *nptr;
887 if (odd) old = optr[0] * 256; 887 } else {
888 else old = optr[0]; 888 s[1] = s[3] = 0;
889 889 s[0] = ~*optr;
890 x -= old & 0xFFFF; 890 s[2] = *nptr;
891 if (x <= 0) {
892 x--;
893 x &= 0xFFFF;
894 }
895
896 if (odd) new = nptr[0] * 256;
897 else new = nptr[0];
898
899 x += new & 0xFFFF;
900 if (x & 0x10000) {
901 x++;
902 x &= 0xFFFF;
903 } 891 }
904 892
905 x =~ x & 0xFFFF; 893 *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
906 csum[0] = x / 256;
907 csum[1] = x & 0xFF;
908} 894}
909 895
910/* 896/*
@@ -915,9 +901,9 @@ static void fast_csum(unsigned char *csum,
915static inline void mangle_address(unsigned char *begin, 901static inline void mangle_address(unsigned char *begin,
916 unsigned char *addr, 902 unsigned char *addr,
917 const struct oct1_map *map, 903 const struct oct1_map *map,
918 u_int16_t *check) 904 __sum16 *check)
919{ 905{
920 if (map->from == NOCT1(*addr)) { 906 if (map->from == NOCT1(addr)) {
921 u_int32_t old; 907 u_int32_t old;
922 908
923 if (debug) 909 if (debug)
@@ -927,11 +913,8 @@ static inline void mangle_address(unsigned char *begin,
927 913
928 /* Update UDP checksum if being used */ 914 /* Update UDP checksum if being used */
929 if (*check) { 915 if (*check) {
930 unsigned char odd = !((addr - begin) % 2); 916 fast_csum(check,
931 917 &map->from, &map->to, addr - begin);
932 fast_csum((unsigned char *)check,
933 &map->from, &map->to, odd);
934
935 } 918 }
936 919
937 if (debug) 920 if (debug)
@@ -943,7 +926,7 @@ static inline void mangle_address(unsigned char *begin,
943static unsigned char snmp_trap_decode(struct asn1_ctx *ctx, 926static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
944 struct snmp_v1_trap *trap, 927 struct snmp_v1_trap *trap,
945 const struct oct1_map *map, 928 const struct oct1_map *map,
946 u_int16_t *check) 929 __sum16 *check)
947{ 930{
948 unsigned int cls, con, tag, len; 931 unsigned int cls, con, tag, len;
949 unsigned char *end; 932 unsigned char *end;
@@ -1037,7 +1020,7 @@ static void hex_dump(unsigned char *buf, size_t len)
1037static int snmp_parse_mangle(unsigned char *msg, 1020static int snmp_parse_mangle(unsigned char *msg,
1038 u_int16_t len, 1021 u_int16_t len,
1039 const struct oct1_map *map, 1022 const struct oct1_map *map,
1040 u_int16_t *check) 1023 __sum16 *check)
1041{ 1024{
1042 unsigned char *eoc, *end; 1025 unsigned char *eoc, *end;
1043 unsigned int cls, con, tag, vers, pdutype; 1026 unsigned int cls, con, tag, vers, pdutype;
@@ -1223,12 +1206,12 @@ static int snmp_translate(struct ip_conntrack *ct,
1223 */ 1206 */
1224 if (dir == IP_CT_DIR_ORIGINAL) { 1207 if (dir == IP_CT_DIR_ORIGINAL) {
1225 /* SNAT traps */ 1208 /* SNAT traps */
1226 map.from = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip); 1209 map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip);
1227 map.to = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip); 1210 map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip);
1228 } else { 1211 } else {
1229 /* DNAT replies */ 1212 /* DNAT replies */
1230 map.from = NOCT1(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); 1213 map.from = NOCT1(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip);
1231 map.to = NOCT1(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip); 1214 map.to = NOCT1(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip);
1232 } 1215 }
1233 1216
1234 if (map.from == map.to) 1217 if (map.from == map.to)
@@ -1294,11 +1277,11 @@ static struct ip_conntrack_helper snmp_helper = {
1294 .help = help, 1277 .help = help,
1295 .name = "snmp", 1278 .name = "snmp",
1296 1279
1297 .tuple = { .src = { .u = { __constant_htons(SNMP_PORT) } }, 1280 .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_PORT)}}},
1298 .dst = { .protonum = IPPROTO_UDP }, 1281 .dst = {.protonum = IPPROTO_UDP},
1299 }, 1282 },
1300 .mask = { .src = { .u = { 0xFFFF } }, 1283 .mask = {.src = {.u = {0xFFFF}},
1301 .dst = { .protonum = 0xFF }, 1284 .dst = {.protonum = 0xFF},
1302 }, 1285 },
1303}; 1286};
1304 1287
@@ -1309,11 +1292,11 @@ static struct ip_conntrack_helper snmp_trap_helper = {
1309 .help = help, 1292 .help = help,
1310 .name = "snmp_trap", 1293 .name = "snmp_trap",
1311 1294
1312 .tuple = { .src = { .u = { __constant_htons(SNMP_TRAP_PORT) } }, 1295 .tuple = {.src = {.u = {.udp = {.port = __constant_htons(SNMP_TRAP_PORT)}}},
1313 .dst = { .protonum = IPPROTO_UDP }, 1296 .dst = {.protonum = IPPROTO_UDP},
1314 }, 1297 },
1315 .mask = { .src = { .u = { 0xFFFF } }, 1298 .mask = {.src = {.u = {0xFFFF}},
1316 .dst = { .protonum = 0xFF }, 1299 .dst = {.protonum = 0xFF},
1317 }, 1300 },
1318}; 1301};
1319 1302
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index d85d2de50449..ad66328baa5d 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -44,12 +44,6 @@
44#define DEBUGP(format, args...) 44#define DEBUGP(format, args...)
45#endif 45#endif
46 46
47#define HOOKNAME(hooknum) ((hooknum) == NF_IP_POST_ROUTING ? "POST_ROUTING" \
48 : ((hooknum) == NF_IP_PRE_ROUTING ? "PRE_ROUTING" \
49 : ((hooknum) == NF_IP_LOCAL_OUT ? "LOCAL_OUT" \
50 : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \
51 : "*ERROR*")))
52
53#ifdef CONFIG_XFRM 47#ifdef CONFIG_XFRM
54static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) 48static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
55{ 49{
diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c
index 94a78015451c..604793536fc1 100644
--- a/net/ipv4/netfilter/ip_nat_tftp.c
+++ b/net/ipv4/netfilter/ip_nat_tftp.c
@@ -55,15 +55,14 @@ static unsigned int help(struct sk_buff **pskb,
55 55
56static void __exit ip_nat_tftp_fini(void) 56static void __exit ip_nat_tftp_fini(void)
57{ 57{
58 ip_nat_tftp_hook = NULL; 58 rcu_assign_pointer(ip_nat_tftp_hook, NULL);
59 /* Make sure noone calls it, meanwhile. */ 59 synchronize_rcu();
60 synchronize_net();
61} 60}
62 61
63static int __init ip_nat_tftp_init(void) 62static int __init ip_nat_tftp_init(void)
64{ 63{
65 BUG_ON(ip_nat_tftp_hook); 64 BUG_ON(rcu_dereference(ip_nat_tftp_hook));
66 ip_nat_tftp_hook = help; 65 rcu_assign_pointer(ip_nat_tftp_hook, help);
67 return 0; 66 return 0;
68} 67}
69 68
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 97556cc2e4e0..cd520df4dcf4 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -243,7 +243,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
243 pmsg->data_len = data_len; 243 pmsg->data_len = data_len;
244 pmsg->timestamp_sec = entry->skb->tstamp.off_sec; 244 pmsg->timestamp_sec = entry->skb->tstamp.off_sec;
245 pmsg->timestamp_usec = entry->skb->tstamp.off_usec; 245 pmsg->timestamp_usec = entry->skb->tstamp.off_usec;
246 pmsg->mark = entry->skb->nfmark; 246 pmsg->mark = entry->skb->mark;
247 pmsg->hook = entry->info->hook; 247 pmsg->hook = entry->info->hook;
248 pmsg->hw_protocol = entry->skb->protocol; 248 pmsg->hw_protocol = entry->skb->protocol;
249 249
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 7a29d6e7baa7..098365062234 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -40,8 +40,6 @@
40#define DEBUGP 40#define DEBUGP
41#endif 41#endif
42 42
43#define ASSERT_READ_LOCK(x)
44
45MODULE_LICENSE("GPL"); 43MODULE_LICENSE("GPL");
46MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 44MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
47MODULE_DESCRIPTION("iptables target for CLUSTERIP"); 45MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -123,7 +121,6 @@ __clusterip_config_find(__be32 clusterip)
123{ 121{
124 struct list_head *pos; 122 struct list_head *pos;
125 123
126 ASSERT_READ_LOCK(&clusterip_lock);
127 list_for_each(pos, &clusterip_configs) { 124 list_for_each(pos, &clusterip_configs) {
128 struct clusterip_config *c = list_entry(pos, 125 struct clusterip_config *c = list_entry(pos,
129 struct clusterip_config, list); 126 struct clusterip_config, list);
@@ -170,7 +167,6 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
170 struct net_device *dev) 167 struct net_device *dev)
171{ 168{
172 struct clusterip_config *c; 169 struct clusterip_config *c;
173 char buffer[16];
174 170
175 c = kzalloc(sizeof(*c), GFP_ATOMIC); 171 c = kzalloc(sizeof(*c), GFP_ATOMIC);
176 if (!c) 172 if (!c)
@@ -187,12 +183,17 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
187 atomic_set(&c->entries, 1); 183 atomic_set(&c->entries, 1);
188 184
189#ifdef CONFIG_PROC_FS 185#ifdef CONFIG_PROC_FS
190 /* create proc dir entry */ 186 {
191 sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip)); 187 char buffer[16];
192 c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR, clusterip_procdir); 188
193 if (!c->pde) { 189 /* create proc dir entry */
194 kfree(c); 190 sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(ip));
195 return NULL; 191 c->pde = create_proc_entry(buffer, S_IWUSR|S_IRUSR,
192 clusterip_procdir);
193 if (!c->pde) {
194 kfree(c);
195 return NULL;
196 }
196 } 197 }
197 c->pde->proc_fops = &clusterip_proc_fops; 198 c->pde->proc_fops = &clusterip_proc_fops;
198 c->pde->data = c; 199 c->pde->data = c;
@@ -205,6 +206,7 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, __be32 ip,
205 return c; 206 return c;
206} 207}
207 208
209#ifdef CONFIG_PROC_FS
208static int 210static int
209clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) 211clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
210{ 212{
@@ -232,6 +234,7 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
232 234
233 return 1; 235 return 1;
234} 236}
237#endif
235 238
236static inline u_int32_t 239static inline u_int32_t
237clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) 240clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config)
@@ -737,8 +740,10 @@ static int __init ipt_clusterip_init(void)
737 CLUSTERIP_VERSION); 740 CLUSTERIP_VERSION);
738 return 0; 741 return 0;
739 742
743#ifdef CONFIG_PROC_FS
740cleanup_hook: 744cleanup_hook:
741 nf_unregister_hook(&cip_arp_ops); 745 nf_unregister_hook(&cip_arp_ops);
746#endif /* CONFIG_PROC_FS */
742cleanup_target: 747cleanup_target:
743 ipt_unregister_target(&clusterip_tgt); 748 ipt_unregister_target(&clusterip_tgt);
744 return ret; 749 return ret;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 1aa4517fbcdb..b55d670a24df 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -28,17 +28,16 @@ static inline int
28set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) 28set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
29{ 29{
30 struct iphdr *iph = (*pskb)->nh.iph; 30 struct iphdr *iph = (*pskb)->nh.iph;
31 u_int16_t oldtos;
32 31
33 if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { 32 if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
33 __u8 oldtos;
34 if (!skb_make_writable(pskb, sizeof(struct iphdr))) 34 if (!skb_make_writable(pskb, sizeof(struct iphdr)))
35 return 0; 35 return 0;
36 iph = (*pskb)->nh.iph; 36 iph = (*pskb)->nh.iph;
37 oldtos = iph->tos; 37 oldtos = iph->tos;
38 iph->tos &= ~IPT_ECN_IP_MASK; 38 iph->tos &= ~IPT_ECN_IP_MASK;
39 iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); 39 iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
40 iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), 40 nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
41 htons(iph->tos), iph->check);
42 } 41 }
43 return 1; 42 return 1;
44} 43}
@@ -72,10 +71,8 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
72 if (einfo->operation & IPT_ECN_OP_SET_CWR) 71 if (einfo->operation & IPT_ECN_OP_SET_CWR)
73 tcph->cwr = einfo->proto.tcp.cwr; 72 tcph->cwr = einfo->proto.tcp.cwr;
74 73
75 tcph->check = nf_proto_csum_update((*pskb), 74 nf_proto_csum_replace2(&tcph->check, *pskb,
76 oldval ^ htons(0xFFFF), 75 oldval, ((__be16 *)tcph)[6], 0);
77 ((__be16 *)tcph)[6],
78 tcph->check, 0);
79 return 1; 76 return 1;
80} 77}
81 78
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 7dc820df8bc5..c96de16fefae 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -171,11 +171,15 @@ static void dump_packet(const struct nf_loginfo *info,
171 } 171 }
172 break; 172 break;
173 } 173 }
174 case IPPROTO_UDP: { 174 case IPPROTO_UDP:
175 case IPPROTO_UDPLITE: {
175 struct udphdr _udph, *uh; 176 struct udphdr _udph, *uh;
176 177
177 /* Max length: 10 "PROTO=UDP " */ 178 if (ih->protocol == IPPROTO_UDP)
178 printk("PROTO=UDP "); 179 /* Max length: 10 "PROTO=UDP " */
180 printk("PROTO=UDP " );
181 else /* Max length: 14 "PROTO=UDPLITE " */
182 printk("PROTO=UDPLITE ");
179 183
180 if (ntohs(ih->frag_off) & IP_OFFSET) 184 if (ntohs(ih->frag_off) & IP_OFFSET)
181 break; 185 break;
@@ -341,6 +345,7 @@ static void dump_packet(const struct nf_loginfo *info,
341 /* IP: 40+46+6+11+127 = 230 */ 345 /* IP: 40+46+6+11+127 = 230 */
342 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ 346 /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
343 /* UDP: 10+max(25,20) = 35 */ 347 /* UDP: 10+max(25,20) = 35 */
348 /* UDPLITE: 14+max(25,20) = 39 */
344 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ 349 /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
345 /* ESP: 10+max(25)+15 = 50 */ 350 /* ESP: 10+max(25)+15 = 50 */
346 /* AH: 9+max(25)+15 = 49 */ 351 /* AH: 9+max(25)+15 = 49 */
@@ -425,13 +430,8 @@ ipt_log_target(struct sk_buff **pskb,
425 li.u.log.level = loginfo->level; 430 li.u.log.level = loginfo->level;
426 li.u.log.logflags = loginfo->logflags; 431 li.u.log.logflags = loginfo->logflags;
427 432
428 if (loginfo->logflags & IPT_LOG_NFLOG) 433 ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
429 nf_log_packet(PF_INET, hooknum, *pskb, in, out, &li, 434 loginfo->prefix);
430 "%s", loginfo->prefix);
431 else
432 ipt_log_packet(PF_INET, hooknum, *pskb, in, out, &li,
433 loginfo->prefix);
434
435 return IPT_CONTINUE; 435 return IPT_CONTINUE;
436} 436}
437 437
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 3dbfcfac8a84..28b9233956b5 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -2,7 +2,7 @@
2 (depending on route). */ 2 (depending on route). */
3 3
4/* (C) 1999-2001 Paul `Rusty' Russell 4/* (C) 1999-2001 Paul `Rusty' Russell
5 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 5 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -20,7 +20,11 @@
20#include <net/checksum.h> 20#include <net/checksum.h>
21#include <net/route.h> 21#include <net/route.h>
22#include <linux/netfilter_ipv4.h> 22#include <linux/netfilter_ipv4.h>
23#ifdef CONFIG_NF_NAT_NEEDED
24#include <net/netfilter/nf_nat_rule.h>
25#else
23#include <linux/netfilter_ipv4/ip_nat_rule.h> 26#include <linux/netfilter_ipv4/ip_nat_rule.h>
27#endif
24#include <linux/netfilter_ipv4/ip_tables.h> 28#include <linux/netfilter_ipv4/ip_tables.h>
25 29
26MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
@@ -65,23 +69,33 @@ masquerade_target(struct sk_buff **pskb,
65 const struct xt_target *target, 69 const struct xt_target *target,
66 const void *targinfo) 70 const void *targinfo)
67{ 71{
72#ifdef CONFIG_NF_NAT_NEEDED
73 struct nf_conn_nat *nat;
74#endif
68 struct ip_conntrack *ct; 75 struct ip_conntrack *ct;
69 enum ip_conntrack_info ctinfo; 76 enum ip_conntrack_info ctinfo;
70 const struct ip_nat_multi_range_compat *mr;
71 struct ip_nat_range newrange; 77 struct ip_nat_range newrange;
78 const struct ip_nat_multi_range_compat *mr;
72 struct rtable *rt; 79 struct rtable *rt;
73 __be32 newsrc; 80 __be32 newsrc;
74 81
75 IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); 82 IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
76 83
77 ct = ip_conntrack_get(*pskb, &ctinfo); 84 ct = ip_conntrack_get(*pskb, &ctinfo);
85#ifdef CONFIG_NF_NAT_NEEDED
86 nat = nfct_nat(ct);
87#endif
78 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED 88 IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED
79 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); 89 || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
80 90
81 /* Source address is 0.0.0.0 - locally generated packet that is 91 /* Source address is 0.0.0.0 - locally generated packet that is
82 * probably not supposed to be masqueraded. 92 * probably not supposed to be masqueraded.
83 */ 93 */
94#ifdef CONFIG_NF_NAT_NEEDED
95 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 0)
96#else
84 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0) 97 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0)
98#endif
85 return NF_ACCEPT; 99 return NF_ACCEPT;
86 100
87 mr = targinfo; 101 mr = targinfo;
@@ -93,7 +107,11 @@ masquerade_target(struct sk_buff **pskb,
93 } 107 }
94 108
95 write_lock_bh(&masq_lock); 109 write_lock_bh(&masq_lock);
110#ifdef CONFIG_NF_NAT_NEEDED
111 nat->masq_index = out->ifindex;
112#else
96 ct->nat.masq_index = out->ifindex; 113 ct->nat.masq_index = out->ifindex;
114#endif
97 write_unlock_bh(&masq_lock); 115 write_unlock_bh(&masq_lock);
98 116
99 /* Transfer from original range. */ 117 /* Transfer from original range. */
@@ -109,10 +127,17 @@ masquerade_target(struct sk_buff **pskb,
109static inline int 127static inline int
110device_cmp(struct ip_conntrack *i, void *ifindex) 128device_cmp(struct ip_conntrack *i, void *ifindex)
111{ 129{
130#ifdef CONFIG_NF_NAT_NEEDED
131 struct nf_conn_nat *nat = nfct_nat(i);
132#endif
112 int ret; 133 int ret;
113 134
114 read_lock_bh(&masq_lock); 135 read_lock_bh(&masq_lock);
136#ifdef CONFIG_NF_NAT_NEEDED
137 ret = (nat->masq_index == (int)(long)ifindex);
138#else
115 ret = (i->nat.masq_index == (int)(long)ifindex); 139 ret = (i->nat.masq_index == (int)(long)ifindex);
140#endif
116 read_unlock_bh(&masq_lock); 141 read_unlock_bh(&masq_lock);
117 142
118 return ret; 143 return ret;
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 58a88f227108..9390e90f2b25 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -15,7 +15,11 @@
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#ifdef CONFIG_NF_NAT_NEEDED
19#include <net/netfilter/nf_nat_rule.h>
20#else
18#include <linux/netfilter_ipv4/ip_nat_rule.h> 21#include <linux/netfilter_ipv4/ip_nat_rule.h>
22#endif
19 23
20#define MODULENAME "NETMAP" 24#define MODULENAME "NETMAP"
21MODULE_LICENSE("GPL"); 25MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index c0dcfe9d610c..462eceb3a1b1 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -1,6 +1,6 @@
1/* Redirect. Simple mapping which alters dst to a local IP address. */ 1/* Redirect. Simple mapping which alters dst to a local IP address. */
2/* (C) 1999-2001 Paul `Rusty' Russell 2/* (C) 1999-2001 Paul `Rusty' Russell
3 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 3 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -18,7 +18,11 @@
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#ifdef CONFIG_NF_NAT_NEEDED
22#include <net/netfilter/nf_nat_rule.h>
23#else
21#include <linux/netfilter_ipv4/ip_nat_rule.h> 24#include <linux/netfilter_ipv4/ip_nat_rule.h>
25#endif
22 26
23MODULE_LICENSE("GPL"); 27MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 28MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index ad0312d0e4fd..f0319e5ee437 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -76,7 +76,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
76 76
77 /* This packet will not be the same as the other: clear nf fields */ 77 /* This packet will not be the same as the other: clear nf fields */
78 nf_reset(nskb); 78 nf_reset(nskb);
79 nskb->nfmark = 0; 79 nskb->mark = 0;
80 skb_init_secmark(nskb); 80 skb_init_secmark(nskb);
81 81
82 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl); 82 tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
@@ -114,6 +114,14 @@ static void send_reset(struct sk_buff *oldskb, int hook)
114 tcph->window = 0; 114 tcph->window = 0;
115 tcph->urg_ptr = 0; 115 tcph->urg_ptr = 0;
116 116
117 /* Adjust TCP checksum */
118 tcph->check = 0;
119 tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
120 nskb->nh.iph->saddr,
121 nskb->nh.iph->daddr,
122 csum_partial((char *)tcph,
123 sizeof(struct tcphdr), 0));
124
117 /* Set DF, id = 0 */ 125 /* Set DF, id = 0 */
118 nskb->nh.iph->frag_off = htons(IP_DF); 126 nskb->nh.iph->frag_off = htons(IP_DF);
119 nskb->nh.iph->id = 0; 127 nskb->nh.iph->id = 0;
@@ -129,14 +137,8 @@ static void send_reset(struct sk_buff *oldskb, int hook)
129 if (ip_route_me_harder(&nskb, addr_type)) 137 if (ip_route_me_harder(&nskb, addr_type))
130 goto free_nskb; 138 goto free_nskb;
131 139
132 /* Adjust TCP checksum */
133 nskb->ip_summed = CHECKSUM_NONE; 140 nskb->ip_summed = CHECKSUM_NONE;
134 tcph->check = 0; 141
135 tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
136 nskb->nh.iph->saddr,
137 nskb->nh.iph->daddr,
138 csum_partial((char *)tcph,
139 sizeof(struct tcphdr), 0));
140 /* Adjust IP TTL */ 142 /* Adjust IP TTL */
141 nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT); 143 nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
142 144
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c
index b38b13328d73..3dcf29411337 100644
--- a/net/ipv4/netfilter/ipt_SAME.c
+++ b/net/ipv4/netfilter/ipt_SAME.c
@@ -34,7 +34,11 @@
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#ifdef CONFIG_NF_NAT_NEEDED
38#include <net/netfilter/nf_nat_rule.h>
39#else
37#include <linux/netfilter_ipv4/ip_nat_rule.h> 40#include <linux/netfilter_ipv4/ip_nat_rule.h>
41#endif
38#include <linux/netfilter_ipv4/ipt_SAME.h> 42#include <linux/netfilter_ipv4/ipt_SAME.h>
39 43
40MODULE_LICENSE("GPL"); 44MODULE_LICENSE("GPL");
@@ -152,11 +156,17 @@ same_target(struct sk_buff **pskb,
152 Here we calculate the index in same->iparray which 156 Here we calculate the index in same->iparray which
153 holds the ipaddress we should use */ 157 holds the ipaddress we should use */
154 158
159#ifdef CONFIG_NF_NAT_NEEDED
160 tmpip = ntohl(t->src.u3.ip);
161
162 if (!(same->info & IPT_SAME_NODST))
163 tmpip += ntohl(t->dst.u3.ip);
164#else
155 tmpip = ntohl(t->src.ip); 165 tmpip = ntohl(t->src.ip);
156 166
157 if (!(same->info & IPT_SAME_NODST)) 167 if (!(same->info & IPT_SAME_NODST))
158 tmpip += ntohl(t->dst.ip); 168 tmpip += ntohl(t->dst.ip);
159 169#endif
160 aindex = tmpip % same->ipnum; 170 aindex = tmpip % same->ipnum;
161 171
162 new_ip = htonl(same->iparray[aindex]); 172 new_ip = htonl(same->iparray[aindex]);
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c
index 108b6b76311f..93eb5c3c1884 100644
--- a/net/ipv4/netfilter/ipt_TCPMSS.c
+++ b/net/ipv4/netfilter/ipt_TCPMSS.c
@@ -97,10 +97,8 @@ ipt_tcpmss_target(struct sk_buff **pskb,
97 opt[i+2] = (newmss & 0xff00) >> 8; 97 opt[i+2] = (newmss & 0xff00) >> 8;
98 opt[i+3] = (newmss & 0x00ff); 98 opt[i+3] = (newmss & 0x00ff);
99 99
100 tcph->check = nf_proto_csum_update(*pskb, 100 nf_proto_csum_replace2(&tcph->check, *pskb,
101 htons(oldmss)^htons(0xFFFF), 101 htons(oldmss), htons(newmss), 0);
102 htons(newmss),
103 tcph->check, 0);
104 return IPT_CONTINUE; 102 return IPT_CONTINUE;
105 } 103 }
106 } 104 }
@@ -126,28 +124,22 @@ ipt_tcpmss_target(struct sk_buff **pskb,
126 opt = (u_int8_t *)tcph + sizeof(struct tcphdr); 124 opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
127 memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); 125 memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
128 126
129 tcph->check = nf_proto_csum_update(*pskb, 127 nf_proto_csum_replace2(&tcph->check, *pskb,
130 htons(tcplen) ^ htons(0xFFFF), 128 htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
131 htons(tcplen + TCPOLEN_MSS),
132 tcph->check, 1);
133 opt[0] = TCPOPT_MSS; 129 opt[0] = TCPOPT_MSS;
134 opt[1] = TCPOLEN_MSS; 130 opt[1] = TCPOLEN_MSS;
135 opt[2] = (newmss & 0xff00) >> 8; 131 opt[2] = (newmss & 0xff00) >> 8;
136 opt[3] = (newmss & 0x00ff); 132 opt[3] = (newmss & 0x00ff);
137 133
138 tcph->check = nf_proto_csum_update(*pskb, htonl(~0), *((__be32 *)opt), 134 nf_proto_csum_replace4(&tcph->check, *pskb, 0, *((__be32 *)opt), 0);
139 tcph->check, 0);
140 135
141 oldval = ((__be16 *)tcph)[6]; 136 oldval = ((__be16 *)tcph)[6];
142 tcph->doff += TCPOLEN_MSS/4; 137 tcph->doff += TCPOLEN_MSS/4;
143 tcph->check = nf_proto_csum_update(*pskb, 138 nf_proto_csum_replace2(&tcph->check, *pskb,
144 oldval ^ htons(0xFFFF), 139 oldval, ((__be16 *)tcph)[6], 0);
145 ((__be16 *)tcph)[6],
146 tcph->check, 0);
147 140
148 newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); 141 newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS);
149 iph->check = nf_csum_update(iph->tot_len ^ htons(0xFFFF), 142 nf_csum_replace2(&iph->check, iph->tot_len, newtotlen);
150 newtotlen, iph->check);
151 iph->tot_len = newtotlen; 143 iph->tot_len = newtotlen;
152 return IPT_CONTINUE; 144 return IPT_CONTINUE;
153} 145}
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 83b80b3a5d2f..18e74ac4d425 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -30,16 +30,15 @@ target(struct sk_buff **pskb,
30{ 30{
31 const struct ipt_tos_target_info *tosinfo = targinfo; 31 const struct ipt_tos_target_info *tosinfo = targinfo;
32 struct iphdr *iph = (*pskb)->nh.iph; 32 struct iphdr *iph = (*pskb)->nh.iph;
33 u_int16_t oldtos;
34 33
35 if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { 34 if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
35 __u8 oldtos;
36 if (!skb_make_writable(pskb, sizeof(struct iphdr))) 36 if (!skb_make_writable(pskb, sizeof(struct iphdr)))
37 return NF_DROP; 37 return NF_DROP;
38 iph = (*pskb)->nh.iph; 38 iph = (*pskb)->nh.iph;
39 oldtos = iph->tos; 39 oldtos = iph->tos;
40 iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; 40 iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
41 iph->check = nf_csum_update(htons(oldtos) ^ htons(0xFFFF), 41 nf_csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
42 htons(iph->tos), iph->check);
43 } 42 }
44 return IPT_CONTINUE; 43 return IPT_CONTINUE;
45} 44}
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index ac9517d62af0..fffe5ca82e91 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -54,9 +54,8 @@ ipt_ttl_target(struct sk_buff **pskb,
54 } 54 }
55 55
56 if (new_ttl != iph->ttl) { 56 if (new_ttl != iph->ttl) {
57 iph->check = nf_csum_update(htons((iph->ttl << 8)) ^ htons(0xFFFF), 57 nf_csum_replace2(&iph->check, htons(iph->ttl << 8),
58 htons(new_ttl << 8), 58 htons(new_ttl << 8));
59 iph->check);
60 iph->ttl = new_ttl; 59 iph->ttl = new_ttl;
61 } 60 }
62 61
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 2b104ea54f48..dbd34783a64d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -239,7 +239,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
239 pm->data_len = copy_len; 239 pm->data_len = copy_len;
240 pm->timestamp_sec = skb->tstamp.off_sec; 240 pm->timestamp_sec = skb->tstamp.off_sec;
241 pm->timestamp_usec = skb->tstamp.off_usec; 241 pm->timestamp_usec = skb->tstamp.off_usec;
242 pm->mark = skb->nfmark; 242 pm->mark = skb->mark;
243 pm->hook = hooknum; 243 pm->hook = hooknum;
244 if (prefix != NULL) 244 if (prefix != NULL)
245 strncpy(pm->prefix, prefix, sizeof(pm->prefix)); 245 strncpy(pm->prefix, prefix, sizeof(pm->prefix));
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
deleted file mode 100644
index 33ccdbf8e794..000000000000
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ /dev/null
@@ -1,733 +0,0 @@
1/* iptables match extension to limit the number of packets per second
2 * seperately for each hashbucket (sourceip/sourceport/dstip/dstport)
3 *
4 * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
5 *
6 * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $
7 *
8 * Development of this code was funded by Astaro AG, http://www.astaro.com/
9 *
10 * based on ipt_limit.c by:
11 * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
12 * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
13 * Rusty Russell <rusty@rustcorp.com.au>
14 *
15 * The general idea is to create a hash table for every dstip and have a
16 * seperate limit counter per tuple. This way you can do something like 'limit
17 * the number of syn packets for each of my internal addresses.
18 *
19 * Ideally this would just be implemented as a general 'hash' match, which would
20 * allow us to attach any iptables target to it's hash buckets. But this is
21 * not possible in the current iptables architecture. As always, pkttables for
22 * 2.7.x will help ;)
23 */
24#include <linux/module.h>
25#include <linux/skbuff.h>
26#include <linux/spinlock.h>
27#include <linux/random.h>
28#include <linux/jhash.h>
29#include <linux/slab.h>
30#include <linux/vmalloc.h>
31#include <linux/proc_fs.h>
32#include <linux/seq_file.h>
33#include <linux/list.h>
34
35#include <linux/netfilter_ipv4/ip_tables.h>
36#include <linux/netfilter_ipv4/ipt_hashlimit.h>
37
38/* FIXME: this is just for IP_NF_ASSERRT */
39#include <linux/netfilter_ipv4/ip_conntrack.h>
40#include <linux/mutex.h>
41
42MODULE_LICENSE("GPL");
43MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
44MODULE_DESCRIPTION("iptables match for limiting per hash-bucket");
45
46/* need to declare this at the top */
47static struct proc_dir_entry *hashlimit_procdir;
48static struct file_operations dl_file_ops;
49
50/* hash table crap */
51
52struct dsthash_dst {
53 __be32 src_ip;
54 __be32 dst_ip;
55 /* ports have to be consecutive !!! */
56 __be16 src_port;
57 __be16 dst_port;
58};
59
60struct dsthash_ent {
61 /* static / read-only parts in the beginning */
62 struct hlist_node node;
63 struct dsthash_dst dst;
64
65 /* modified structure members in the end */
66 unsigned long expires; /* precalculated expiry time */
67 struct {
68 unsigned long prev; /* last modification */
69 u_int32_t credit;
70 u_int32_t credit_cap, cost;
71 } rateinfo;
72};
73
74struct ipt_hashlimit_htable {
75 struct hlist_node node; /* global list of all htables */
76 atomic_t use;
77
78 struct hashlimit_cfg cfg; /* config */
79
80 /* used internally */
81 spinlock_t lock; /* lock for list_head */
82 u_int32_t rnd; /* random seed for hash */
83 int rnd_initialized;
84 struct timer_list timer; /* timer for gc */
85 atomic_t count; /* number entries in table */
86
87 /* seq_file stuff */
88 struct proc_dir_entry *pde;
89
90 struct hlist_head hash[0]; /* hashtable itself */
91};
92
93static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */
94static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */
95static HLIST_HEAD(hashlimit_htables);
96static kmem_cache_t *hashlimit_cachep __read_mostly;
97
98static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
99{
100 return (ent->dst.dst_ip == b->dst_ip
101 && ent->dst.dst_port == b->dst_port
102 && ent->dst.src_port == b->src_port
103 && ent->dst.src_ip == b->src_ip);
104}
105
106static inline u_int32_t
107hash_dst(const struct ipt_hashlimit_htable *ht, const struct dsthash_dst *dst)
108{
109 return (jhash_3words((__force u32)dst->dst_ip,
110 ((__force u32)dst->dst_port<<16 |
111 (__force u32)dst->src_port),
112 (__force u32)dst->src_ip, ht->rnd) % ht->cfg.size);
113}
114
115static inline struct dsthash_ent *
116__dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
117{
118 struct dsthash_ent *ent;
119 struct hlist_node *pos;
120 u_int32_t hash = hash_dst(ht, dst);
121
122 if (!hlist_empty(&ht->hash[hash]))
123 hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
124 if (dst_cmp(ent, dst)) {
125 return ent;
126 }
127 }
128
129 return NULL;
130}
131
132/* allocate dsthash_ent, initialize dst, put in htable and lock it */
133static struct dsthash_ent *
134__dsthash_alloc_init(struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
135{
136 struct dsthash_ent *ent;
137
138 /* initialize hash with random val at the time we allocate
139 * the first hashtable entry */
140 if (!ht->rnd_initialized) {
141 get_random_bytes(&ht->rnd, 4);
142 ht->rnd_initialized = 1;
143 }
144
145 if (ht->cfg.max &&
146 atomic_read(&ht->count) >= ht->cfg.max) {
147 /* FIXME: do something. question is what.. */
148 if (net_ratelimit())
149 printk(KERN_WARNING
150 "ipt_hashlimit: max count of %u reached\n",
151 ht->cfg.max);
152 return NULL;
153 }
154
155 ent = kmem_cache_alloc(hashlimit_cachep, GFP_ATOMIC);
156 if (!ent) {
157 if (net_ratelimit())
158 printk(KERN_ERR
159 "ipt_hashlimit: can't allocate dsthash_ent\n");
160 return NULL;
161 }
162
163 atomic_inc(&ht->count);
164
165 ent->dst.dst_ip = dst->dst_ip;
166 ent->dst.dst_port = dst->dst_port;
167 ent->dst.src_ip = dst->src_ip;
168 ent->dst.src_port = dst->src_port;
169
170 hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
171
172 return ent;
173}
174
175static inline void
176__dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
177{
178 hlist_del(&ent->node);
179 kmem_cache_free(hashlimit_cachep, ent);
180 atomic_dec(&ht->count);
181}
182static void htable_gc(unsigned long htlong);
183
184static int htable_create(struct ipt_hashlimit_info *minfo)
185{
186 int i;
187 unsigned int size;
188 struct ipt_hashlimit_htable *hinfo;
189
190 if (minfo->cfg.size)
191 size = minfo->cfg.size;
192 else {
193 size = (((num_physpages << PAGE_SHIFT) / 16384)
194 / sizeof(struct list_head));
195 if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
196 size = 8192;
197 if (size < 16)
198 size = 16;
199 }
200 /* FIXME: don't use vmalloc() here or anywhere else -HW */
201 hinfo = vmalloc(sizeof(struct ipt_hashlimit_htable)
202 + (sizeof(struct list_head) * size));
203 if (!hinfo) {
204 printk(KERN_ERR "ipt_hashlimit: Unable to create hashtable\n");
205 return -1;
206 }
207 minfo->hinfo = hinfo;
208
209 /* copy match config into hashtable config */
210 memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
211 hinfo->cfg.size = size;
212 if (!hinfo->cfg.max)
213 hinfo->cfg.max = 8 * hinfo->cfg.size;
214 else if (hinfo->cfg.max < hinfo->cfg.size)
215 hinfo->cfg.max = hinfo->cfg.size;
216
217 for (i = 0; i < hinfo->cfg.size; i++)
218 INIT_HLIST_HEAD(&hinfo->hash[i]);
219
220 atomic_set(&hinfo->count, 0);
221 atomic_set(&hinfo->use, 1);
222 hinfo->rnd_initialized = 0;
223 spin_lock_init(&hinfo->lock);
224 hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir);
225 if (!hinfo->pde) {
226 vfree(hinfo);
227 return -1;
228 }
229 hinfo->pde->proc_fops = &dl_file_ops;
230 hinfo->pde->data = hinfo;
231
232 init_timer(&hinfo->timer);
233 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
234 hinfo->timer.data = (unsigned long )hinfo;
235 hinfo->timer.function = htable_gc;
236 add_timer(&hinfo->timer);
237
238 spin_lock_bh(&hashlimit_lock);
239 hlist_add_head(&hinfo->node, &hashlimit_htables);
240 spin_unlock_bh(&hashlimit_lock);
241
242 return 0;
243}
244
245static int select_all(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
246{
247 return 1;
248}
249
250static int select_gc(struct ipt_hashlimit_htable *ht, struct dsthash_ent *he)
251{
252 return (jiffies >= he->expires);
253}
254
255static void htable_selective_cleanup(struct ipt_hashlimit_htable *ht,
256 int (*select)(struct ipt_hashlimit_htable *ht,
257 struct dsthash_ent *he))
258{
259 int i;
260
261 IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
262
263 /* lock hash table and iterate over it */
264 spin_lock_bh(&ht->lock);
265 for (i = 0; i < ht->cfg.size; i++) {
266 struct dsthash_ent *dh;
267 struct hlist_node *pos, *n;
268 hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
269 if ((*select)(ht, dh))
270 __dsthash_free(ht, dh);
271 }
272 }
273 spin_unlock_bh(&ht->lock);
274}
275
276/* hash table garbage collector, run by timer */
277static void htable_gc(unsigned long htlong)
278{
279 struct ipt_hashlimit_htable *ht = (struct ipt_hashlimit_htable *)htlong;
280
281 htable_selective_cleanup(ht, select_gc);
282
283 /* re-add the timer accordingly */
284 ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval);
285 add_timer(&ht->timer);
286}
287
288static void htable_destroy(struct ipt_hashlimit_htable *hinfo)
289{
290 /* remove timer, if it is pending */
291 if (timer_pending(&hinfo->timer))
292 del_timer(&hinfo->timer);
293
294 /* remove proc entry */
295 remove_proc_entry(hinfo->pde->name, hashlimit_procdir);
296
297 htable_selective_cleanup(hinfo, select_all);
298 vfree(hinfo);
299}
300
301static struct ipt_hashlimit_htable *htable_find_get(char *name)
302{
303 struct ipt_hashlimit_htable *hinfo;
304 struct hlist_node *pos;
305
306 spin_lock_bh(&hashlimit_lock);
307 hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
308 if (!strcmp(name, hinfo->pde->name)) {
309 atomic_inc(&hinfo->use);
310 spin_unlock_bh(&hashlimit_lock);
311 return hinfo;
312 }
313 }
314 spin_unlock_bh(&hashlimit_lock);
315
316 return NULL;
317}
318
319static void htable_put(struct ipt_hashlimit_htable *hinfo)
320{
321 if (atomic_dec_and_test(&hinfo->use)) {
322 spin_lock_bh(&hashlimit_lock);
323 hlist_del(&hinfo->node);
324 spin_unlock_bh(&hashlimit_lock);
325 htable_destroy(hinfo);
326 }
327}
328
329
330/* The algorithm used is the Simple Token Bucket Filter (TBF)
331 * see net/sched/sch_tbf.c in the linux source tree
332 */
333
334/* Rusty: This is my (non-mathematically-inclined) understanding of
335 this algorithm. The `average rate' in jiffies becomes your initial
336 amount of credit `credit' and the most credit you can ever have
337 `credit_cap'. The `peak rate' becomes the cost of passing the
338 test, `cost'.
339
340 `prev' tracks the last packet hit: you gain one credit per jiffy.
341 If you get credit balance more than this, the extra credit is
342 discarded. Every time the match passes, you lose `cost' credits;
343 if you don't have that many, the test fails.
344
345 See Alexey's formal explanation in net/sched/sch_tbf.c.
346
347 To get the maximum range, we multiply by this factor (ie. you get N
348 credits per jiffy). We want to allow a rate as low as 1 per day
349 (slowest userspace tool allows), which means
350 CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
351*/
352#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
353
354/* Repeated shift and or gives us all 1s, final shift and add 1 gives
355 * us the power of 2 below the theoretical max, so GCC simply does a
356 * shift. */
357#define _POW2_BELOW2(x) ((x)|((x)>>1))
358#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
359#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
360#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
361#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
362#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
363
364#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
365
366/* Precision saver. */
367static inline u_int32_t
368user2credits(u_int32_t user)
369{
370 /* If multiplying would overflow... */
371 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
372 /* Divide first. */
373 return (user / IPT_HASHLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
374
375 return (user * HZ * CREDITS_PER_JIFFY) / IPT_HASHLIMIT_SCALE;
376}
377
378static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
379{
380 dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
381 * CREDITS_PER_JIFFY;
382 if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
383 dh->rateinfo.credit = dh->rateinfo.credit_cap;
384}
385
386static int
387hashlimit_match(const struct sk_buff *skb,
388 const struct net_device *in,
389 const struct net_device *out,
390 const struct xt_match *match,
391 const void *matchinfo,
392 int offset,
393 unsigned int protoff,
394 int *hotdrop)
395{
396 struct ipt_hashlimit_info *r =
397 ((struct ipt_hashlimit_info *)matchinfo)->u.master;
398 struct ipt_hashlimit_htable *hinfo = r->hinfo;
399 unsigned long now = jiffies;
400 struct dsthash_ent *dh;
401 struct dsthash_dst dst;
402
403 /* build 'dst' according to hinfo->cfg and current packet */
404 memset(&dst, 0, sizeof(dst));
405 if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DIP)
406 dst.dst_ip = skb->nh.iph->daddr;
407 if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SIP)
408 dst.src_ip = skb->nh.iph->saddr;
409 if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
410 ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
411 __be16 _ports[2], *ports;
412
413 switch (skb->nh.iph->protocol) {
414 case IPPROTO_TCP:
415 case IPPROTO_UDP:
416 case IPPROTO_SCTP:
417 case IPPROTO_DCCP:
418 ports = skb_header_pointer(skb, skb->nh.iph->ihl*4,
419 sizeof(_ports), &_ports);
420 break;
421 default:
422 _ports[0] = _ports[1] = 0;
423 ports = _ports;
424 break;
425 }
426 if (!ports) {
427 /* We've been asked to examine this packet, and we
428 can't. Hence, no choice but to drop. */
429 *hotdrop = 1;
430 return 0;
431 }
432 if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT)
433 dst.src_port = ports[0];
434 if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT)
435 dst.dst_port = ports[1];
436 }
437
438 spin_lock_bh(&hinfo->lock);
439 dh = __dsthash_find(hinfo, &dst);
440 if (!dh) {
441 dh = __dsthash_alloc_init(hinfo, &dst);
442
443 if (!dh) {
444 /* enomem... don't match == DROP */
445 if (net_ratelimit())
446 printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
447 spin_unlock_bh(&hinfo->lock);
448 return 0;
449 }
450
451 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
452
453 dh->rateinfo.prev = jiffies;
454 dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
455 hinfo->cfg.burst);
456 dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
457 hinfo->cfg.burst);
458 dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
459 } else {
460 /* update expiration timeout */
461 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
462 rateinfo_recalc(dh, now);
463 }
464
465 if (dh->rateinfo.credit >= dh->rateinfo.cost) {
466 /* We're underlimit. */
467 dh->rateinfo.credit -= dh->rateinfo.cost;
468 spin_unlock_bh(&hinfo->lock);
469 return 1;
470 }
471
472 spin_unlock_bh(&hinfo->lock);
473
474 /* default case: we're overlimit, thus don't match */
475 return 0;
476}
477
478static int
479hashlimit_checkentry(const char *tablename,
480 const void *inf,
481 const struct xt_match *match,
482 void *matchinfo,
483 unsigned int hook_mask)
484{
485 struct ipt_hashlimit_info *r = matchinfo;
486
487 /* Check for overflow. */
488 if (r->cfg.burst == 0
489 || user2credits(r->cfg.avg * r->cfg.burst) <
490 user2credits(r->cfg.avg)) {
491 printk(KERN_ERR "ipt_hashlimit: Overflow, try lower: %u/%u\n",
492 r->cfg.avg, r->cfg.burst);
493 return 0;
494 }
495
496 if (r->cfg.mode == 0
497 || r->cfg.mode > (IPT_HASHLIMIT_HASH_DPT
498 |IPT_HASHLIMIT_HASH_DIP
499 |IPT_HASHLIMIT_HASH_SIP
500 |IPT_HASHLIMIT_HASH_SPT))
501 return 0;
502
503 if (!r->cfg.gc_interval)
504 return 0;
505
506 if (!r->cfg.expire)
507 return 0;
508
509 if (r->name[sizeof(r->name) - 1] != '\0')
510 return 0;
511
512 /* This is the best we've got: We cannot release and re-grab lock,
513 * since checkentry() is called before ip_tables.c grabs ipt_mutex.
514 * We also cannot grab the hashtable spinlock, since htable_create will
515 * call vmalloc, and that can sleep. And we cannot just re-search
516 * the list of htable's in htable_create(), since then we would
517 * create duplicate proc files. -HW */
518 mutex_lock(&hlimit_mutex);
519 r->hinfo = htable_find_get(r->name);
520 if (!r->hinfo && (htable_create(r) != 0)) {
521 mutex_unlock(&hlimit_mutex);
522 return 0;
523 }
524 mutex_unlock(&hlimit_mutex);
525
526 /* Ugly hack: For SMP, we only want to use one set */
527 r->u.master = r;
528
529 return 1;
530}
531
532static void
533hashlimit_destroy(const struct xt_match *match, void *matchinfo)
534{
535 struct ipt_hashlimit_info *r = matchinfo;
536
537 htable_put(r->hinfo);
538}
539
540#ifdef CONFIG_COMPAT
541struct compat_ipt_hashlimit_info {
542 char name[IFNAMSIZ];
543 struct hashlimit_cfg cfg;
544 compat_uptr_t hinfo;
545 compat_uptr_t master;
546};
547
548static void compat_from_user(void *dst, void *src)
549{
550 int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
551
552 memcpy(dst, src, off);
553 memset(dst + off, 0, sizeof(struct compat_ipt_hashlimit_info) - off);
554}
555
556static int compat_to_user(void __user *dst, void *src)
557{
558 int off = offsetof(struct compat_ipt_hashlimit_info, hinfo);
559
560 return copy_to_user(dst, src, off) ? -EFAULT : 0;
561}
562#endif
563
564static struct ipt_match ipt_hashlimit = {
565 .name = "hashlimit",
566 .match = hashlimit_match,
567 .matchsize = sizeof(struct ipt_hashlimit_info),
568#ifdef CONFIG_COMPAT
569 .compatsize = sizeof(struct compat_ipt_hashlimit_info),
570 .compat_from_user = compat_from_user,
571 .compat_to_user = compat_to_user,
572#endif
573 .checkentry = hashlimit_checkentry,
574 .destroy = hashlimit_destroy,
575 .me = THIS_MODULE
576};
577
578/* PROC stuff */
579
580static void *dl_seq_start(struct seq_file *s, loff_t *pos)
581{
582 struct proc_dir_entry *pde = s->private;
583 struct ipt_hashlimit_htable *htable = pde->data;
584 unsigned int *bucket;
585
586 spin_lock_bh(&htable->lock);
587 if (*pos >= htable->cfg.size)
588 return NULL;
589
590 bucket = kmalloc(sizeof(unsigned int), GFP_ATOMIC);
591 if (!bucket)
592 return ERR_PTR(-ENOMEM);
593
594 *bucket = *pos;
595 return bucket;
596}
597
598static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
599{
600 struct proc_dir_entry *pde = s->private;
601 struct ipt_hashlimit_htable *htable = pde->data;
602 unsigned int *bucket = (unsigned int *)v;
603
604 *pos = ++(*bucket);
605 if (*pos >= htable->cfg.size) {
606 kfree(v);
607 return NULL;
608 }
609 return bucket;
610}
611
612static void dl_seq_stop(struct seq_file *s, void *v)
613{
614 struct proc_dir_entry *pde = s->private;
615 struct ipt_hashlimit_htable *htable = pde->data;
616 unsigned int *bucket = (unsigned int *)v;
617
618 kfree(bucket);
619
620 spin_unlock_bh(&htable->lock);
621}
622
623static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
624{
625 /* recalculate to show accurate numbers */
626 rateinfo_recalc(ent, jiffies);
627
628 return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
629 (long)(ent->expires - jiffies)/HZ,
630 NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
631 NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
632 ent->rateinfo.credit, ent->rateinfo.credit_cap,
633 ent->rateinfo.cost);
634}
635
636static int dl_seq_show(struct seq_file *s, void *v)
637{
638 struct proc_dir_entry *pde = s->private;
639 struct ipt_hashlimit_htable *htable = pde->data;
640 unsigned int *bucket = (unsigned int *)v;
641 struct dsthash_ent *ent;
642 struct hlist_node *pos;
643
644 if (!hlist_empty(&htable->hash[*bucket]))
645 hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) {
646 if (dl_seq_real_show(ent, s)) {
647 /* buffer was filled and unable to print that tuple */
648 return 1;
649 }
650 }
651
652 return 0;
653}
654
655static struct seq_operations dl_seq_ops = {
656 .start = dl_seq_start,
657 .next = dl_seq_next,
658 .stop = dl_seq_stop,
659 .show = dl_seq_show
660};
661
662static int dl_proc_open(struct inode *inode, struct file *file)
663{
664 int ret = seq_open(file, &dl_seq_ops);
665
666 if (!ret) {
667 struct seq_file *sf = file->private_data;
668 sf->private = PDE(inode);
669 }
670 return ret;
671}
672
673static struct file_operations dl_file_ops = {
674 .owner = THIS_MODULE,
675 .open = dl_proc_open,
676 .read = seq_read,
677 .llseek = seq_lseek,
678 .release = seq_release
679};
680
681static int init_or_fini(int fini)
682{
683 int ret = 0;
684
685 if (fini)
686 goto cleanup;
687
688 if (ipt_register_match(&ipt_hashlimit)) {
689 ret = -EINVAL;
690 goto cleanup_nothing;
691 }
692
693 hashlimit_cachep = kmem_cache_create("ipt_hashlimit",
694 sizeof(struct dsthash_ent), 0,
695 0, NULL, NULL);
696 if (!hashlimit_cachep) {
697 printk(KERN_ERR "Unable to create ipt_hashlimit slab cache\n");
698 ret = -ENOMEM;
699 goto cleanup_unreg_match;
700 }
701
702 hashlimit_procdir = proc_mkdir("ipt_hashlimit", proc_net);
703 if (!hashlimit_procdir) {
704 printk(KERN_ERR "Unable to create proc dir entry\n");
705 ret = -ENOMEM;
706 goto cleanup_free_slab;
707 }
708
709 return ret;
710
711cleanup:
712 remove_proc_entry("ipt_hashlimit", proc_net);
713cleanup_free_slab:
714 kmem_cache_destroy(hashlimit_cachep);
715cleanup_unreg_match:
716 ipt_unregister_match(&ipt_hashlimit);
717cleanup_nothing:
718 return ret;
719
720}
721
722static int __init ipt_hashlimit_init(void)
723{
724 return init_or_fini(0);
725}
726
727static void __exit ipt_hashlimit_fini(void)
728{
729 init_or_fini(1);
730}
731
732module_init(ipt_hashlimit_init);
733module_exit(ipt_hashlimit_fini);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index b91f3582359b..af2939889444 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -132,7 +132,7 @@ ipt_local_hook(unsigned int hook,
132 unsigned int ret; 132 unsigned int ret;
133 u_int8_t tos; 133 u_int8_t tos;
134 __be32 saddr, daddr; 134 __be32 saddr, daddr;
135 unsigned long nfmark; 135 u_int32_t mark;
136 136
137 /* root is playing with raw sockets. */ 137 /* root is playing with raw sockets. */
138 if ((*pskb)->len < sizeof(struct iphdr) 138 if ((*pskb)->len < sizeof(struct iphdr)
@@ -143,7 +143,7 @@ ipt_local_hook(unsigned int hook,
143 } 143 }
144 144
145 /* Save things which could affect route */ 145 /* Save things which could affect route */
146 nfmark = (*pskb)->nfmark; 146 mark = (*pskb)->mark;
147 saddr = (*pskb)->nh.iph->saddr; 147 saddr = (*pskb)->nh.iph->saddr;
148 daddr = (*pskb)->nh.iph->daddr; 148 daddr = (*pskb)->nh.iph->daddr;
149 tos = (*pskb)->nh.iph->tos; 149 tos = (*pskb)->nh.iph->tos;
@@ -153,9 +153,7 @@ ipt_local_hook(unsigned int hook,
153 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE 153 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
154 && ((*pskb)->nh.iph->saddr != saddr 154 && ((*pskb)->nh.iph->saddr != saddr
155 || (*pskb)->nh.iph->daddr != daddr 155 || (*pskb)->nh.iph->daddr != daddr
156#ifdef CONFIG_IP_ROUTE_FWMARK 156 || (*pskb)->mark != mark
157 || (*pskb)->nfmark != nfmark
158#endif
159 || (*pskb)->nh.iph->tos != tos)) 157 || (*pskb)->nh.iph->tos != tos))
160 if (ip_route_me_harder(pskb, RTN_UNSPEC)) 158 if (ip_route_me_harder(pskb, RTN_UNSPEC))
161 ret = NF_DROP; 159 ret = NF_DROP;
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 0af803df82b0..471b638cedec 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -27,7 +27,7 @@
27#include <linux/netfilter_ipv4.h> 27#include <linux/netfilter_ipv4.h>
28#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack.h>
29#include <net/netfilter/nf_conntrack_helper.h> 29#include <net/netfilter/nf_conntrack_helper.h>
30#include <net/netfilter/nf_conntrack_protocol.h> 30#include <net/netfilter/nf_conntrack_l4proto.h>
31#include <net/netfilter/nf_conntrack_l3proto.h> 31#include <net/netfilter/nf_conntrack_l3proto.h>
32#include <net/netfilter/nf_conntrack_core.h> 32#include <net/netfilter/nf_conntrack_core.h>
33#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 33#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
@@ -38,12 +38,10 @@
38#define DEBUGP(format, args...) 38#define DEBUGP(format, args...)
39#endif 39#endif
40 40
41DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat);
42
43static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 41static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
44 struct nf_conntrack_tuple *tuple) 42 struct nf_conntrack_tuple *tuple)
45{ 43{
46 u_int32_t _addrs[2], *ap; 44 __be32 _addrs[2], *ap;
47 ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), 45 ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr),
48 sizeof(u_int32_t) * 2, _addrs); 46 sizeof(u_int32_t) * 2, _addrs);
49 if (ap == NULL) 47 if (ap == NULL)
@@ -113,10 +111,12 @@ ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff,
113 return NF_ACCEPT; 111 return NF_ACCEPT;
114} 112}
115 113
116int nat_module_is_loaded = 0; 114int nf_nat_module_is_loaded = 0;
115EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded);
116
117static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) 117static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple)
118{ 118{
119 if (nat_module_is_loaded) 119 if (nf_nat_module_is_loaded)
120 return NF_CT_F_NAT; 120 return NF_CT_F_NAT;
121 121
122 return NF_CT_F_BASIC; 122 return NF_CT_F_BASIC;
@@ -268,43 +268,59 @@ static struct nf_hook_ops ipv4_conntrack_ops[] = {
268 }, 268 },
269}; 269};
270 270
271#ifdef CONFIG_SYSCTL 271#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
272/* From nf_conntrack_proto_icmp.c */ 272static int log_invalid_proto_min = 0;
273extern unsigned int nf_ct_icmp_timeout; 273static int log_invalid_proto_max = 255;
274static struct ctl_table_header *nf_ct_ipv4_sysctl_header;
275 274
276static ctl_table nf_ct_sysctl_table[] = { 275static ctl_table ip_ct_sysctl_table[] = {
277 { 276 {
278 .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT, 277 .ctl_name = NET_IPV4_NF_CONNTRACK_MAX,
279 .procname = "nf_conntrack_icmp_timeout", 278 .procname = "ip_conntrack_max",
280 .data = &nf_ct_icmp_timeout, 279 .data = &nf_conntrack_max,
281 .maxlen = sizeof(unsigned int), 280 .maxlen = sizeof(int),
282 .mode = 0644, 281 .mode = 0644,
283 .proc_handler = &proc_dointvec_jiffies, 282 .proc_handler = &proc_dointvec,
284 }, 283 },
285 { .ctl_name = 0 }
286};
287
288static ctl_table nf_ct_netfilter_table[] = {
289 { 284 {
290 .ctl_name = NET_NETFILTER, 285 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT,
291 .procname = "netfilter", 286 .procname = "ip_conntrack_count",
292 .mode = 0555, 287 .data = &nf_conntrack_count,
293 .child = nf_ct_sysctl_table, 288 .maxlen = sizeof(int),
289 .mode = 0444,
290 .proc_handler = &proc_dointvec,
291 },
292 {
293 .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS,
294 .procname = "ip_conntrack_buckets",
295 .data = &nf_conntrack_htable_size,
296 .maxlen = sizeof(unsigned int),
297 .mode = 0444,
298 .proc_handler = &proc_dointvec,
299 },
300 {
301 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM,
302 .procname = "ip_conntrack_checksum",
303 .data = &nf_conntrack_checksum,
304 .maxlen = sizeof(int),
305 .mode = 0644,
306 .proc_handler = &proc_dointvec,
294 }, 307 },
295 { .ctl_name = 0 }
296};
297
298static ctl_table nf_ct_net_table[] = {
299 { 308 {
300 .ctl_name = CTL_NET, 309 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID,
301 .procname = "net", 310 .procname = "ip_conntrack_log_invalid",
302 .mode = 0555, 311 .data = &nf_ct_log_invalid,
303 .child = nf_ct_netfilter_table, 312 .maxlen = sizeof(unsigned int),
313 .mode = 0644,
314 .proc_handler = &proc_dointvec_minmax,
315 .strategy = &sysctl_intvec,
316 .extra1 = &log_invalid_proto_min,
317 .extra2 = &log_invalid_proto_max,
304 }, 318 },
305 { .ctl_name = 0 } 319 {
320 .ctl_name = 0
321 }
306}; 322};
307#endif 323#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */
308 324
309/* Fast function for those who don't want to parse /proc (and I don't 325/* Fast function for those who don't want to parse /proc (and I don't
310 blame them). */ 326 blame them). */
@@ -396,10 +412,8 @@ static int ipv4_nfattr_to_tuple(struct nfattr *tb[],
396 if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) 412 if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip))
397 return -EINVAL; 413 return -EINVAL;
398 414
399 t->src.u3.ip = 415 t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
400 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); 416 t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
401 t->dst.u3.ip =
402 *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
403 417
404 return 0; 418 return 0;
405} 419}
@@ -426,14 +440,15 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = {
426 .tuple_to_nfattr = ipv4_tuple_to_nfattr, 440 .tuple_to_nfattr = ipv4_tuple_to_nfattr,
427 .nfattr_to_tuple = ipv4_nfattr_to_tuple, 441 .nfattr_to_tuple = ipv4_nfattr_to_tuple,
428#endif 442#endif
443#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
444 .ctl_table_path = nf_net_ipv4_netfilter_sysctl_path,
445 .ctl_table = ip_ct_sysctl_table,
446#endif
429 .me = THIS_MODULE, 447 .me = THIS_MODULE,
430}; 448};
431 449
432extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;
433extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;
434extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;
435
436MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); 450MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
451MODULE_ALIAS("ip_conntrack");
437MODULE_LICENSE("GPL"); 452MODULE_LICENSE("GPL");
438 453
439static int __init nf_conntrack_l3proto_ipv4_init(void) 454static int __init nf_conntrack_l3proto_ipv4_init(void)
@@ -448,19 +463,19 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
448 return ret; 463 return ret;
449 } 464 }
450 465
451 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); 466 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4);
452 if (ret < 0) { 467 if (ret < 0) {
453 printk("nf_conntrack_ipv4: can't register tcp.\n"); 468 printk("nf_conntrack_ipv4: can't register tcp.\n");
454 goto cleanup_sockopt; 469 goto cleanup_sockopt;
455 } 470 }
456 471
457 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4); 472 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4);
458 if (ret < 0) { 473 if (ret < 0) {
459 printk("nf_conntrack_ipv4: can't register udp.\n"); 474 printk("nf_conntrack_ipv4: can't register udp.\n");
460 goto cleanup_tcp; 475 goto cleanup_tcp;
461 } 476 }
462 477
463 ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp); 478 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp);
464 if (ret < 0) { 479 if (ret < 0) {
465 printk("nf_conntrack_ipv4: can't register icmp.\n"); 480 printk("nf_conntrack_ipv4: can't register icmp.\n");
466 goto cleanup_udp; 481 goto cleanup_udp;
@@ -478,28 +493,24 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
478 printk("nf_conntrack_ipv4: can't register hooks.\n"); 493 printk("nf_conntrack_ipv4: can't register hooks.\n");
479 goto cleanup_ipv4; 494 goto cleanup_ipv4;
480 } 495 }
481#ifdef CONFIG_SYSCTL 496#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
482 nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); 497 ret = nf_conntrack_ipv4_compat_init();
483 if (nf_ct_ipv4_sysctl_header == NULL) { 498 if (ret < 0)
484 printk("nf_conntrack: can't register to sysctl.\n");
485 ret = -ENOMEM;
486 goto cleanup_hooks; 499 goto cleanup_hooks;
487 }
488#endif 500#endif
489 return ret; 501 return ret;
490 502#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
491#ifdef CONFIG_SYSCTL
492 cleanup_hooks: 503 cleanup_hooks:
493 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 504 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
494#endif 505#endif
495 cleanup_ipv4: 506 cleanup_ipv4:
496 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 507 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
497 cleanup_icmp: 508 cleanup_icmp:
498 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); 509 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
499 cleanup_udp: 510 cleanup_udp:
500 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); 511 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
501 cleanup_tcp: 512 cleanup_tcp:
502 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); 513 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
503 cleanup_sockopt: 514 cleanup_sockopt:
504 nf_unregister_sockopt(&so_getorigdst); 515 nf_unregister_sockopt(&so_getorigdst);
505 return ret; 516 return ret;
@@ -508,18 +519,16 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
508static void __exit nf_conntrack_l3proto_ipv4_fini(void) 519static void __exit nf_conntrack_l3proto_ipv4_fini(void)
509{ 520{
510 synchronize_net(); 521 synchronize_net();
511#ifdef CONFIG_SYSCTL 522#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT)
512 unregister_sysctl_table(nf_ct_ipv4_sysctl_header); 523 nf_conntrack_ipv4_compat_fini();
513#endif 524#endif
514 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 525 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops));
515 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 526 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4);
516 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); 527 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp);
517 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); 528 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4);
518 nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); 529 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4);
519 nf_unregister_sockopt(&so_getorigdst); 530 nf_unregister_sockopt(&so_getorigdst);
520} 531}
521 532
522module_init(nf_conntrack_l3proto_ipv4_init); 533module_init(nf_conntrack_l3proto_ipv4_init);
523module_exit(nf_conntrack_l3proto_ipv4_fini); 534module_exit(nf_conntrack_l3proto_ipv4_fini);
524
525EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
new file mode 100644
index 000000000000..3b31bc649608
--- /dev/null
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -0,0 +1,412 @@
1/* ip_conntrack proc compat - based on ip_conntrack_standalone.c
2 *
3 * (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
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#include <linux/types.h>
11#include <linux/proc_fs.h>
12#include <linux/seq_file.h>
13#include <linux/percpu.h>
14
15#include <linux/netfilter.h>
16#include <net/netfilter/nf_conntrack_core.h>
17#include <net/netfilter/nf_conntrack_l3proto.h>
18#include <net/netfilter/nf_conntrack_l4proto.h>
19#include <net/netfilter/nf_conntrack_expect.h>
20
21#if 0
22#define DEBUGP printk
23#else
24#define DEBUGP(format, args...)
25#endif
26
27#ifdef CONFIG_NF_CT_ACCT
28static unsigned int
29seq_print_counters(struct seq_file *s,
30 const struct ip_conntrack_counter *counter)
31{
32 return seq_printf(s, "packets=%llu bytes=%llu ",
33 (unsigned long long)counter->packets,
34 (unsigned long long)counter->bytes);
35}
36#else
37#define seq_print_counters(x, y) 0
38#endif
39
40struct ct_iter_state {
41 unsigned int bucket;
42};
43
44static struct list_head *ct_get_first(struct seq_file *seq)
45{
46 struct ct_iter_state *st = seq->private;
47
48 for (st->bucket = 0;
49 st->bucket < nf_conntrack_htable_size;
50 st->bucket++) {
51 if (!list_empty(&nf_conntrack_hash[st->bucket]))
52 return nf_conntrack_hash[st->bucket].next;
53 }
54 return NULL;
55}
56
57static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
58{
59 struct ct_iter_state *st = seq->private;
60
61 head = head->next;
62 while (head == &nf_conntrack_hash[st->bucket]) {
63 if (++st->bucket >= nf_conntrack_htable_size)
64 return NULL;
65 head = nf_conntrack_hash[st->bucket].next;
66 }
67 return head;
68}
69
70static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
71{
72 struct list_head *head = ct_get_first(seq);
73
74 if (head)
75 while (pos && (head = ct_get_next(seq, head)))
76 pos--;
77 return pos ? NULL : head;
78}
79
80static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
81{
82 read_lock_bh(&nf_conntrack_lock);
83 return ct_get_idx(seq, *pos);
84}
85
86static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
87{
88 (*pos)++;
89 return ct_get_next(s, v);
90}
91
92static void ct_seq_stop(struct seq_file *s, void *v)
93{
94 read_unlock_bh(&nf_conntrack_lock);
95}
96
97static int ct_seq_show(struct seq_file *s, void *v)
98{
99 const struct nf_conntrack_tuple_hash *hash = v;
100 const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash);
101 struct nf_conntrack_l3proto *l3proto;
102 struct nf_conntrack_l4proto *l4proto;
103
104 NF_CT_ASSERT(ct);
105
106 /* we only want to print DIR_ORIGINAL */
107 if (NF_CT_DIRECTION(hash))
108 return 0;
109 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num != AF_INET)
110 return 0;
111
112 l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
113 .tuple.src.l3num);
114 NF_CT_ASSERT(l3proto);
115 l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_ORIGINAL]
116 .tuple.src.l3num,
117 ct->tuplehash[IP_CT_DIR_ORIGINAL]
118 .tuple.dst.protonum);
119 NF_CT_ASSERT(l4proto);
120
121 if (seq_printf(s, "%-8s %u %ld ",
122 l4proto->name,
123 ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
124 timer_pending(&ct->timeout)
125 ? (long)(ct->timeout.expires - jiffies)/HZ : 0) != 0)
126 return -ENOSPC;
127
128 if (l3proto->print_conntrack(s, ct))
129 return -ENOSPC;
130
131 if (l4proto->print_conntrack(s, ct))
132 return -ENOSPC;
133
134 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
135 l3proto, l4proto))
136 return -ENOSPC;
137
138 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_ORIGINAL]))
139 return -ENOSPC;
140
141 if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
142 if (seq_printf(s, "[UNREPLIED] "))
143 return -ENOSPC;
144
145 if (print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple,
146 l3proto, l4proto))
147 return -ENOSPC;
148
149 if (seq_print_counters(s, &ct->counters[IP_CT_DIR_REPLY]))
150 return -ENOSPC;
151
152 if (test_bit(IPS_ASSURED_BIT, &ct->status))
153 if (seq_printf(s, "[ASSURED] "))
154 return -ENOSPC;
155
156#ifdef CONFIG_NF_CONNTRACK_MARK
157 if (seq_printf(s, "mark=%u ", ct->mark))
158 return -ENOSPC;
159#endif
160
161#ifdef CONFIG_NF_CONNTRACK_SECMARK
162 if (seq_printf(s, "secmark=%u ", ct->secmark))
163 return -ENOSPC;
164#endif
165
166 if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
167 return -ENOSPC;
168
169 return 0;
170}
171
172static struct seq_operations ct_seq_ops = {
173 .start = ct_seq_start,
174 .next = ct_seq_next,
175 .stop = ct_seq_stop,
176 .show = ct_seq_show
177};
178
179static int ct_open(struct inode *inode, struct file *file)
180{
181 struct seq_file *seq;
182 struct ct_iter_state *st;
183 int ret;
184
185 st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
186 if (st == NULL)
187 return -ENOMEM;
188 ret = seq_open(file, &ct_seq_ops);
189 if (ret)
190 goto out_free;
191 seq = file->private_data;
192 seq->private = st;
193 memset(st, 0, sizeof(struct ct_iter_state));
194 return ret;
195out_free:
196 kfree(st);
197 return ret;
198}
199
200static struct file_operations ct_file_ops = {
201 .owner = THIS_MODULE,
202 .open = ct_open,
203 .read = seq_read,
204 .llseek = seq_lseek,
205 .release = seq_release_private,
206};
207
208/* expects */
209static void *exp_seq_start(struct seq_file *s, loff_t *pos)
210{
211 struct list_head *e = &nf_conntrack_expect_list;
212 loff_t i;
213
214 /* strange seq_file api calls stop even if we fail,
215 * thus we need to grab lock since stop unlocks */
216 read_lock_bh(&nf_conntrack_lock);
217
218 if (list_empty(e))
219 return NULL;
220
221 for (i = 0; i <= *pos; i++) {
222 e = e->next;
223 if (e == &nf_conntrack_expect_list)
224 return NULL;
225 }
226 return e;
227}
228
229static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
230{
231 struct list_head *e = v;
232
233 ++*pos;
234 e = e->next;
235
236 if (e == &nf_conntrack_expect_list)
237 return NULL;
238
239 return e;
240}
241
242static void exp_seq_stop(struct seq_file *s, void *v)
243{
244 read_unlock_bh(&nf_conntrack_lock);
245}
246
247static int exp_seq_show(struct seq_file *s, void *v)
248{
249 struct nf_conntrack_expect *exp = v;
250
251 if (exp->tuple.src.l3num != AF_INET)
252 return 0;
253
254 if (exp->timeout.function)
255 seq_printf(s, "%ld ", timer_pending(&exp->timeout)
256 ? (long)(exp->timeout.expires - jiffies)/HZ : 0);
257 else
258 seq_printf(s, "- ");
259
260 seq_printf(s, "proto=%u ", exp->tuple.dst.protonum);
261
262 print_tuple(s, &exp->tuple,
263 __nf_ct_l3proto_find(exp->tuple.src.l3num),
264 __nf_ct_l4proto_find(exp->tuple.src.l3num,
265 exp->tuple.dst.protonum));
266 return seq_putc(s, '\n');
267}
268
269static struct seq_operations exp_seq_ops = {
270 .start = exp_seq_start,
271 .next = exp_seq_next,
272 .stop = exp_seq_stop,
273 .show = exp_seq_show
274};
275
276static int exp_open(struct inode *inode, struct file *file)
277{
278 return seq_open(file, &exp_seq_ops);
279}
280
281static struct file_operations ip_exp_file_ops = {
282 .owner = THIS_MODULE,
283 .open = exp_open,
284 .read = seq_read,
285 .llseek = seq_lseek,
286 .release = seq_release
287};
288
289static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
290{
291 int cpu;
292
293 if (*pos == 0)
294 return SEQ_START_TOKEN;
295
296 for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
297 if (!cpu_possible(cpu))
298 continue;
299 *pos = cpu+1;
300 return &per_cpu(nf_conntrack_stat, cpu);
301 }
302
303 return NULL;
304}
305
306static void *ct_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos)
307{
308 int cpu;
309
310 for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
311 if (!cpu_possible(cpu))
312 continue;
313 *pos = cpu+1;
314 return &per_cpu(nf_conntrack_stat, cpu);
315 }
316
317 return NULL;
318}
319
320static void ct_cpu_seq_stop(struct seq_file *seq, void *v)
321{
322}
323
324static int ct_cpu_seq_show(struct seq_file *seq, void *v)
325{
326 unsigned int nr_conntracks = atomic_read(&nf_conntrack_count);
327 struct ip_conntrack_stat *st = v;
328
329 if (v == SEQ_START_TOKEN) {
330 seq_printf(seq, "entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete\n");
331 return 0;
332 }
333
334 seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x "
335 "%08x %08x %08x %08x %08x %08x %08x %08x \n",
336 nr_conntracks,
337 st->searched,
338 st->found,
339 st->new,
340 st->invalid,
341 st->ignore,
342 st->delete,
343 st->delete_list,
344 st->insert,
345 st->insert_failed,
346 st->drop,
347 st->early_drop,
348 st->error,
349
350 st->expect_new,
351 st->expect_create,
352 st->expect_delete
353 );
354 return 0;
355}
356
357static struct seq_operations ct_cpu_seq_ops = {
358 .start = ct_cpu_seq_start,
359 .next = ct_cpu_seq_next,
360 .stop = ct_cpu_seq_stop,
361 .show = ct_cpu_seq_show,
362};
363
364static int ct_cpu_seq_open(struct inode *inode, struct file *file)
365{
366 return seq_open(file, &ct_cpu_seq_ops);
367}
368
369static struct file_operations ct_cpu_seq_fops = {
370 .owner = THIS_MODULE,
371 .open = ct_cpu_seq_open,
372 .read = seq_read,
373 .llseek = seq_lseek,
374 .release = seq_release_private,
375};
376
377int __init nf_conntrack_ipv4_compat_init(void)
378{
379 struct proc_dir_entry *proc, *proc_exp, *proc_stat;
380
381 proc = proc_net_fops_create("ip_conntrack", 0440, &ct_file_ops);
382 if (!proc)
383 goto err1;
384
385 proc_exp = proc_net_fops_create("ip_conntrack_expect", 0440,
386 &ip_exp_file_ops);
387 if (!proc_exp)
388 goto err2;
389
390 proc_stat = create_proc_entry("ip_conntrack", S_IRUGO, proc_net_stat);
391 if (!proc_stat)
392 goto err3;
393
394 proc_stat->proc_fops = &ct_cpu_seq_fops;
395 proc_stat->owner = THIS_MODULE;
396
397 return 0;
398
399err3:
400 proc_net_remove("ip_conntrack_expect");
401err2:
402 proc_net_remove("ip_conntrack");
403err1:
404 return -ENOMEM;
405}
406
407void __exit nf_conntrack_ipv4_compat_fini(void)
408{
409 remove_proc_entry("ip_conntrack", proc_net_stat);
410 proc_net_remove("ip_conntrack_expect");
411 proc_net_remove("ip_conntrack");
412}
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 790f00d500c3..db9e7c45d3b4 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -22,10 +22,10 @@
22#include <net/checksum.h> 22#include <net/checksum.h>
23#include <linux/netfilter_ipv4.h> 23#include <linux/netfilter_ipv4.h>
24#include <net/netfilter/nf_conntrack_tuple.h> 24#include <net/netfilter/nf_conntrack_tuple.h>
25#include <net/netfilter/nf_conntrack_protocol.h> 25#include <net/netfilter/nf_conntrack_l4proto.h>
26#include <net/netfilter/nf_conntrack_core.h> 26#include <net/netfilter/nf_conntrack_core.h>
27 27
28unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; 28static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
29 29
30#if 0 30#if 0
31#define DEBUGP printk 31#define DEBUGP printk
@@ -152,7 +152,7 @@ icmp_error_message(struct sk_buff *skb,
152 struct icmphdr icmp; 152 struct icmphdr icmp;
153 struct iphdr ip; 153 struct iphdr ip;
154 } _in, *inside; 154 } _in, *inside;
155 struct nf_conntrack_protocol *innerproto; 155 struct nf_conntrack_l4proto *innerproto;
156 struct nf_conntrack_tuple_hash *h; 156 struct nf_conntrack_tuple_hash *h;
157 int dataoff; 157 int dataoff;
158 158
@@ -170,7 +170,7 @@ icmp_error_message(struct sk_buff *skb,
170 return -NF_ACCEPT; 170 return -NF_ACCEPT;
171 } 171 }
172 172
173 innerproto = __nf_ct_proto_find(PF_INET, inside->ip.protocol); 173 innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
174 dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp); 174 dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp);
175 /* Are they talking about one of our connections? */ 175 /* Are they talking about one of our connections? */
176 if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, 176 if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
@@ -311,7 +311,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
311 tuple->dst.u.icmp.code = 311 tuple->dst.u.icmp.code =
312 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); 312 *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
313 tuple->src.u.icmp.id = 313 tuple->src.u.icmp.id =
314 *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); 314 *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
315 315
316 if (tuple->dst.u.icmp.type >= sizeof(invmap) 316 if (tuple->dst.u.icmp.type >= sizeof(invmap)
317 || !invmap[tuple->dst.u.icmp.type]) 317 || !invmap[tuple->dst.u.icmp.type])
@@ -321,11 +321,42 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[],
321} 321}
322#endif 322#endif
323 323
324struct nf_conntrack_protocol nf_conntrack_protocol_icmp = 324#ifdef CONFIG_SYSCTL
325static struct ctl_table_header *icmp_sysctl_header;
326static struct ctl_table icmp_sysctl_table[] = {
327 {
328 .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT,
329 .procname = "nf_conntrack_icmp_timeout",
330 .data = &nf_ct_icmp_timeout,
331 .maxlen = sizeof(unsigned int),
332 .mode = 0644,
333 .proc_handler = &proc_dointvec_jiffies,
334 },
335 {
336 .ctl_name = 0
337 }
338};
339#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
340static struct ctl_table icmp_compat_sysctl_table[] = {
341 {
342 .ctl_name = NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT,
343 .procname = "ip_conntrack_icmp_timeout",
344 .data = &nf_ct_icmp_timeout,
345 .maxlen = sizeof(unsigned int),
346 .mode = 0644,
347 .proc_handler = &proc_dointvec_jiffies,
348 },
349 {
350 .ctl_name = 0
351 }
352};
353#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
354#endif /* CONFIG_SYSCTL */
355
356struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
325{ 357{
326 .list = { NULL, NULL },
327 .l3proto = PF_INET, 358 .l3proto = PF_INET,
328 .proto = IPPROTO_ICMP, 359 .l4proto = IPPROTO_ICMP,
329 .name = "icmp", 360 .name = "icmp",
330 .pkt_to_tuple = icmp_pkt_to_tuple, 361 .pkt_to_tuple = icmp_pkt_to_tuple,
331 .invert_tuple = icmp_invert_tuple, 362 .invert_tuple = icmp_invert_tuple,
@@ -341,6 +372,12 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmp =
341 .tuple_to_nfattr = icmp_tuple_to_nfattr, 372 .tuple_to_nfattr = icmp_tuple_to_nfattr,
342 .nfattr_to_tuple = icmp_nfattr_to_tuple, 373 .nfattr_to_tuple = icmp_nfattr_to_tuple,
343#endif 374#endif
375#ifdef CONFIG_SYSCTL
376 .ctl_table_header = &icmp_sysctl_header,
377 .ctl_table = icmp_sysctl_table,
378#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
379 .ctl_compat_table = icmp_compat_sysctl_table,
380#endif
381#endif
344}; 382};
345 383EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_icmp);
346EXPORT_SYMBOL(nf_conntrack_protocol_icmp);
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
new file mode 100644
index 000000000000..0f17098917bc
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -0,0 +1,78 @@
1/* Amanda extension for TCP NAT alteration.
2 * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
3 * based on a copy of HW's ip_nat_irc.c as well as other modules
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/udp.h>
15
16#include <net/netfilter/nf_nat_helper.h>
17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_conntrack_helper.h>
19#include <net/netfilter/nf_conntrack_expect.h>
20#include <linux/netfilter/nf_conntrack_amanda.h>
21
22MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
23MODULE_DESCRIPTION("Amanda NAT helper");
24MODULE_LICENSE("GPL");
25MODULE_ALIAS("ip_nat_amanda");
26
27static unsigned int help(struct sk_buff **pskb,
28 enum ip_conntrack_info ctinfo,
29 unsigned int matchoff,
30 unsigned int matchlen,
31 struct nf_conntrack_expect *exp)
32{
33 char buffer[sizeof("65535")];
34 u_int16_t port;
35 unsigned int ret;
36
37 /* Connection comes from client. */
38 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
39 exp->dir = IP_CT_DIR_ORIGINAL;
40
41 /* When you see the packet, we need to NAT it the same as the
42 * this one (ie. same IP: it will be TCP and master is UDP). */
43 exp->expectfn = nf_nat_follow_master;
44
45 /* Try to get same port: if not, try to change it. */
46 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
47 exp->tuple.dst.u.tcp.port = htons(port);
48 if (nf_conntrack_expect_related(exp) == 0)
49 break;
50 }
51
52 if (port == 0)
53 return NF_DROP;
54
55 sprintf(buffer, "%u", port);
56 ret = nf_nat_mangle_udp_packet(pskb, exp->master, ctinfo,
57 matchoff, matchlen,
58 buffer, strlen(buffer));
59 if (ret != NF_ACCEPT)
60 nf_conntrack_unexpect_related(exp);
61 return ret;
62}
63
64static void __exit nf_nat_amanda_fini(void)
65{
66 rcu_assign_pointer(nf_nat_amanda_hook, NULL);
67 synchronize_rcu();
68}
69
70static int __init nf_nat_amanda_init(void)
71{
72 BUG_ON(rcu_dereference(nf_nat_amanda_hook));
73 rcu_assign_pointer(nf_nat_amanda_hook, help);
74 return 0;
75}
76
77module_init(nf_nat_amanda_init);
78module_exit(nf_nat_amanda_fini);
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
new file mode 100644
index 000000000000..86a92272b053
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -0,0 +1,647 @@
1/* NAT for netfilter; shared with compatibility layer. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
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/types.h>
13#include <linux/timer.h>
14#include <linux/skbuff.h>
15#include <linux/vmalloc.h>
16#include <net/checksum.h>
17#include <net/icmp.h>
18#include <net/ip.h>
19#include <net/tcp.h> /* For tcp_prot in getorigdst */
20#include <linux/icmp.h>
21#include <linux/udp.h>
22#include <linux/jhash.h>
23
24#include <linux/netfilter_ipv4.h>
25#include <net/netfilter/nf_conntrack.h>
26#include <net/netfilter/nf_conntrack_core.h>
27#include <net/netfilter/nf_nat.h>
28#include <net/netfilter/nf_nat_protocol.h>
29#include <net/netfilter/nf_nat_core.h>
30#include <net/netfilter/nf_nat_helper.h>
31#include <net/netfilter/nf_conntrack_helper.h>
32#include <net/netfilter/nf_conntrack_l3proto.h>
33#include <net/netfilter/nf_conntrack_l4proto.h>
34
35#if 0
36#define DEBUGP printk
37#else
38#define DEBUGP(format, args...)
39#endif
40
41static DEFINE_RWLOCK(nf_nat_lock);
42
43static struct nf_conntrack_l3proto *l3proto = NULL;
44
45/* Calculated at init based on memory size */
46static unsigned int nf_nat_htable_size;
47
48static struct list_head *bysource;
49
50#define MAX_IP_NAT_PROTO 256
51static struct nf_nat_protocol *nf_nat_protos[MAX_IP_NAT_PROTO];
52
53static inline struct nf_nat_protocol *
54__nf_nat_proto_find(u_int8_t protonum)
55{
56 return nf_nat_protos[protonum];
57}
58
59struct nf_nat_protocol *
60nf_nat_proto_find_get(u_int8_t protonum)
61{
62 struct nf_nat_protocol *p;
63
64 /* we need to disable preemption to make sure 'p' doesn't get
65 * removed until we've grabbed the reference */
66 preempt_disable();
67 p = __nf_nat_proto_find(protonum);
68 if (!try_module_get(p->me))
69 p = &nf_nat_unknown_protocol;
70 preempt_enable();
71
72 return p;
73}
74EXPORT_SYMBOL_GPL(nf_nat_proto_find_get);
75
76void
77nf_nat_proto_put(struct nf_nat_protocol *p)
78{
79 module_put(p->me);
80}
81EXPORT_SYMBOL_GPL(nf_nat_proto_put);
82
83/* We keep an extra hash for each conntrack, for fast searching. */
84static inline unsigned int
85hash_by_src(const struct nf_conntrack_tuple *tuple)
86{
87 /* Original src, to ensure we map it consistently if poss. */
88 return jhash_3words((__force u32)tuple->src.u3.ip, tuple->src.u.all,
89 tuple->dst.protonum, 0) % nf_nat_htable_size;
90}
91
92/* Noone using conntrack by the time this called. */
93static void nf_nat_cleanup_conntrack(struct nf_conn *conn)
94{
95 struct nf_conn_nat *nat;
96 if (!(conn->status & IPS_NAT_DONE_MASK))
97 return;
98
99 nat = nfct_nat(conn);
100 write_lock_bh(&nf_nat_lock);
101 list_del(&nat->info.bysource);
102 write_unlock_bh(&nf_nat_lock);
103}
104
105/* Is this tuple already taken? (not by us) */
106int
107nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
108 const struct nf_conn *ignored_conntrack)
109{
110 /* Conntrack tracking doesn't keep track of outgoing tuples; only
111 incoming ones. NAT means they don't have a fixed mapping,
112 so we invert the tuple and look for the incoming reply.
113
114 We could keep a separate hash if this proves too slow. */
115 struct nf_conntrack_tuple reply;
116
117 nf_ct_invert_tuplepr(&reply, tuple);
118 return nf_conntrack_tuple_taken(&reply, ignored_conntrack);
119}
120EXPORT_SYMBOL(nf_nat_used_tuple);
121
122/* If we source map this tuple so reply looks like reply_tuple, will
123 * that meet the constraints of range. */
124static int
125in_range(const struct nf_conntrack_tuple *tuple,
126 const struct nf_nat_range *range)
127{
128 struct nf_nat_protocol *proto;
129
130 proto = __nf_nat_proto_find(tuple->dst.protonum);
131 /* If we are supposed to map IPs, then we must be in the
132 range specified, otherwise let this drag us onto a new src IP. */
133 if (range->flags & IP_NAT_RANGE_MAP_IPS) {
134 if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) ||
135 ntohl(tuple->src.u3.ip) > ntohl(range->max_ip))
136 return 0;
137 }
138
139 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
140 proto->in_range(tuple, IP_NAT_MANIP_SRC,
141 &range->min, &range->max))
142 return 1;
143
144 return 0;
145}
146
147static inline int
148same_src(const struct nf_conn *ct,
149 const struct nf_conntrack_tuple *tuple)
150{
151 const struct nf_conntrack_tuple *t;
152
153 t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
154 return (t->dst.protonum == tuple->dst.protonum &&
155 t->src.u3.ip == tuple->src.u3.ip &&
156 t->src.u.all == tuple->src.u.all);
157}
158
159/* Only called for SRC manip */
160static int
161find_appropriate_src(const struct nf_conntrack_tuple *tuple,
162 struct nf_conntrack_tuple *result,
163 const struct nf_nat_range *range)
164{
165 unsigned int h = hash_by_src(tuple);
166 struct nf_conn_nat *nat;
167 struct nf_conn *ct;
168
169 read_lock_bh(&nf_nat_lock);
170 list_for_each_entry(nat, &bysource[h], info.bysource) {
171 ct = (struct nf_conn *)((char *)nat - offsetof(struct nf_conn, data));
172 if (same_src(ct, tuple)) {
173 /* Copy source part from reply tuple. */
174 nf_ct_invert_tuplepr(result,
175 &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
176 result->dst = tuple->dst;
177
178 if (in_range(result, range)) {
179 read_unlock_bh(&nf_nat_lock);
180 return 1;
181 }
182 }
183 }
184 read_unlock_bh(&nf_nat_lock);
185 return 0;
186}
187
188/* For [FUTURE] fragmentation handling, we want the least-used
189 src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus
190 if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports
191 1-65535, we don't do pro-rata allocation based on ports; we choose
192 the ip with the lowest src-ip/dst-ip/proto usage.
193*/
194static void
195find_best_ips_proto(struct nf_conntrack_tuple *tuple,
196 const struct nf_nat_range *range,
197 const struct nf_conn *ct,
198 enum nf_nat_manip_type maniptype)
199{
200 __be32 *var_ipp;
201 /* Host order */
202 u_int32_t minip, maxip, j;
203
204 /* No IP mapping? Do nothing. */
205 if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
206 return;
207
208 if (maniptype == IP_NAT_MANIP_SRC)
209 var_ipp = &tuple->src.u3.ip;
210 else
211 var_ipp = &tuple->dst.u3.ip;
212
213 /* Fast path: only one choice. */
214 if (range->min_ip == range->max_ip) {
215 *var_ipp = range->min_ip;
216 return;
217 }
218
219 /* Hashing source and destination IPs gives a fairly even
220 * spread in practice (if there are a small number of IPs
221 * involved, there usually aren't that many connections
222 * anyway). The consistency means that servers see the same
223 * client coming from the same IP (some Internet Banking sites
224 * like this), even across reboots. */
225 minip = ntohl(range->min_ip);
226 maxip = ntohl(range->max_ip);
227 j = jhash_2words((__force u32)tuple->src.u3.ip,
228 (__force u32)tuple->dst.u3.ip, 0);
229 *var_ipp = htonl(minip + j % (maxip - minip + 1));
230}
231
232/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING,
233 * we change the source to map into the range. For NF_IP_PRE_ROUTING
234 * and NF_IP_LOCAL_OUT, we change the destination to map into the
235 * range. It might not be possible to get a unique tuple, but we try.
236 * At worst (or if we race), we will end up with a final duplicate in
237 * __ip_conntrack_confirm and drop the packet. */
238static void
239get_unique_tuple(struct nf_conntrack_tuple *tuple,
240 const struct nf_conntrack_tuple *orig_tuple,
241 const struct nf_nat_range *range,
242 struct nf_conn *ct,
243 enum nf_nat_manip_type maniptype)
244{
245 struct nf_nat_protocol *proto;
246
247 /* 1) If this srcip/proto/src-proto-part is currently mapped,
248 and that same mapping gives a unique tuple within the given
249 range, use that.
250
251 This is only required for source (ie. NAT/masq) mappings.
252 So far, we don't do local source mappings, so multiple
253 manips not an issue. */
254 if (maniptype == IP_NAT_MANIP_SRC) {
255 if (find_appropriate_src(orig_tuple, tuple, range)) {
256 DEBUGP("get_unique_tuple: Found current src map\n");
257 if (!nf_nat_used_tuple(tuple, ct))
258 return;
259 }
260 }
261
262 /* 2) Select the least-used IP/proto combination in the given
263 range. */
264 *tuple = *orig_tuple;
265 find_best_ips_proto(tuple, range, ct, maniptype);
266
267 /* 3) The per-protocol part of the manip is made to map into
268 the range to make a unique tuple. */
269
270 proto = nf_nat_proto_find_get(orig_tuple->dst.protonum);
271
272 /* Only bother mapping if it's not already in range and unique */
273 if ((!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) ||
274 proto->in_range(tuple, maniptype, &range->min, &range->max)) &&
275 !nf_nat_used_tuple(tuple, ct)) {
276 nf_nat_proto_put(proto);
277 return;
278 }
279
280 /* Last change: get protocol to try to obtain unique tuple. */
281 proto->unique_tuple(tuple, range, maniptype, ct);
282
283 nf_nat_proto_put(proto);
284}
285
286unsigned int
287nf_nat_setup_info(struct nf_conn *ct,
288 const struct nf_nat_range *range,
289 unsigned int hooknum)
290{
291 struct nf_conntrack_tuple curr_tuple, new_tuple;
292 struct nf_conn_nat *nat = nfct_nat(ct);
293 struct nf_nat_info *info = &nat->info;
294 int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
295 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
296
297 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
298 hooknum == NF_IP_POST_ROUTING ||
299 hooknum == NF_IP_LOCAL_IN ||
300 hooknum == NF_IP_LOCAL_OUT);
301 BUG_ON(nf_nat_initialized(ct, maniptype));
302
303 /* What we've got will look like inverse of reply. Normally
304 this is what is in the conntrack, except for prior
305 manipulations (future optimization: if num_manips == 0,
306 orig_tp =
307 conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */
308 nf_ct_invert_tuplepr(&curr_tuple,
309 &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
310
311 get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype);
312
313 if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) {
314 struct nf_conntrack_tuple reply;
315
316 /* Alter conntrack table so will recognize replies. */
317 nf_ct_invert_tuplepr(&reply, &new_tuple);
318 nf_conntrack_alter_reply(ct, &reply);
319
320 /* Non-atomic: we own this at the moment. */
321 if (maniptype == IP_NAT_MANIP_SRC)
322 ct->status |= IPS_SRC_NAT;
323 else
324 ct->status |= IPS_DST_NAT;
325 }
326
327 /* Place in source hash if this is the first time. */
328 if (have_to_hash) {
329 unsigned int srchash;
330
331 srchash = hash_by_src(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
332 write_lock_bh(&nf_nat_lock);
333 list_add(&info->bysource, &bysource[srchash]);
334 write_unlock_bh(&nf_nat_lock);
335 }
336
337 /* It's done. */
338 if (maniptype == IP_NAT_MANIP_DST)
339 set_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
340 else
341 set_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
342
343 return NF_ACCEPT;
344}
345EXPORT_SYMBOL(nf_nat_setup_info);
346
347/* Returns true if succeeded. */
348static int
349manip_pkt(u_int16_t proto,
350 struct sk_buff **pskb,
351 unsigned int iphdroff,
352 const struct nf_conntrack_tuple *target,
353 enum nf_nat_manip_type maniptype)
354{
355 struct iphdr *iph;
356 struct nf_nat_protocol *p;
357
358 if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))
359 return 0;
360
361 iph = (void *)(*pskb)->data + iphdroff;
362
363 /* Manipulate protcol part. */
364 p = nf_nat_proto_find_get(proto);
365 if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {
366 nf_nat_proto_put(p);
367 return 0;
368 }
369 nf_nat_proto_put(p);
370
371 iph = (void *)(*pskb)->data + iphdroff;
372
373 if (maniptype == IP_NAT_MANIP_SRC) {
374 nf_csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
375 iph->saddr = target->src.u3.ip;
376 } else {
377 nf_csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
378 iph->daddr = target->dst.u3.ip;
379 }
380 return 1;
381}
382
383/* Do packet manipulations according to nf_nat_setup_info. */
384unsigned int nf_nat_packet(struct nf_conn *ct,
385 enum ip_conntrack_info ctinfo,
386 unsigned int hooknum,
387 struct sk_buff **pskb)
388{
389 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
390 unsigned long statusbit;
391 enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
392
393 if (mtype == IP_NAT_MANIP_SRC)
394 statusbit = IPS_SRC_NAT;
395 else
396 statusbit = IPS_DST_NAT;
397
398 /* Invert if this is reply dir. */
399 if (dir == IP_CT_DIR_REPLY)
400 statusbit ^= IPS_NAT_MASK;
401
402 /* Non-atomic: these bits don't change. */
403 if (ct->status & statusbit) {
404 struct nf_conntrack_tuple target;
405
406 /* We are aiming to look like inverse of other direction. */
407 nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
408
409 if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))
410 return NF_DROP;
411 }
412 return NF_ACCEPT;
413}
414EXPORT_SYMBOL_GPL(nf_nat_packet);
415
416/* Dir is direction ICMP is coming from (opposite to packet it contains) */
417int nf_nat_icmp_reply_translation(struct nf_conn *ct,
418 enum ip_conntrack_info ctinfo,
419 unsigned int hooknum,
420 struct sk_buff **pskb)
421{
422 struct {
423 struct icmphdr icmp;
424 struct iphdr ip;
425 } *inside;
426 struct nf_conntrack_tuple inner, target;
427 int hdrlen = (*pskb)->nh.iph->ihl * 4;
428 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
429 unsigned long statusbit;
430 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
431
432 if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))
433 return 0;
434
435 inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
436
437 /* We're actually going to mangle it beyond trivial checksum
438 adjustment, so make sure the current checksum is correct. */
439 if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0))
440 return 0;
441
442 /* Must be RELATED */
443 NF_CT_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||
444 (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);
445
446 /* Redirects on non-null nats must be dropped, else they'll
447 start talking to each other without our translation, and be
448 confused... --RR */
449 if (inside->icmp.type == ICMP_REDIRECT) {
450 /* If NAT isn't finished, assume it and drop. */
451 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
452 return 0;
453
454 if (ct->status & IPS_NAT_MASK)
455 return 0;
456 }
457
458 DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",
459 *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
460
461 if (!nf_ct_get_tuple(*pskb,
462 (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr),
463 (*pskb)->nh.iph->ihl*4 +
464 sizeof(struct icmphdr) + inside->ip.ihl*4,
465 (u_int16_t)AF_INET,
466 inside->ip.protocol,
467 &inner,
468 l3proto,
469 __nf_ct_l4proto_find((u_int16_t)PF_INET,
470 inside->ip.protocol)))
471 return 0;
472
473 /* Change inner back to look like incoming packet. We do the
474 opposite manip on this hook to normal, because it might not
475 pass all hooks (locally-generated ICMP). Consider incoming
476 packet: PREROUTING (DST manip), routing produces ICMP, goes
477 through POSTROUTING (which must correct the DST manip). */
478 if (!manip_pkt(inside->ip.protocol, pskb,
479 (*pskb)->nh.iph->ihl*4 + sizeof(inside->icmp),
480 &ct->tuplehash[!dir].tuple,
481 !manip))
482 return 0;
483
484 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
485 /* Reloading "inside" here since manip_pkt inner. */
486 inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
487 inside->icmp.checksum = 0;
488 inside->icmp.checksum =
489 csum_fold(skb_checksum(*pskb, hdrlen,
490 (*pskb)->len - hdrlen, 0));
491 }
492
493 /* Change outer to look the reply to an incoming packet
494 * (proto 0 means don't invert per-proto part). */
495 if (manip == IP_NAT_MANIP_SRC)
496 statusbit = IPS_SRC_NAT;
497 else
498 statusbit = IPS_DST_NAT;
499
500 /* Invert if this is reply dir. */
501 if (dir == IP_CT_DIR_REPLY)
502 statusbit ^= IPS_NAT_MASK;
503
504 if (ct->status & statusbit) {
505 nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
506 if (!manip_pkt(0, pskb, 0, &target, manip))
507 return 0;
508 }
509
510 return 1;
511}
512EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
513
514/* Protocol registration. */
515int nf_nat_protocol_register(struct nf_nat_protocol *proto)
516{
517 int ret = 0;
518
519 write_lock_bh(&nf_nat_lock);
520 if (nf_nat_protos[proto->protonum] != &nf_nat_unknown_protocol) {
521 ret = -EBUSY;
522 goto out;
523 }
524 nf_nat_protos[proto->protonum] = proto;
525 out:
526 write_unlock_bh(&nf_nat_lock);
527 return ret;
528}
529EXPORT_SYMBOL(nf_nat_protocol_register);
530
531/* Noone stores the protocol anywhere; simply delete it. */
532void nf_nat_protocol_unregister(struct nf_nat_protocol *proto)
533{
534 write_lock_bh(&nf_nat_lock);
535 nf_nat_protos[proto->protonum] = &nf_nat_unknown_protocol;
536 write_unlock_bh(&nf_nat_lock);
537
538 /* Someone could be still looking at the proto in a bh. */
539 synchronize_net();
540}
541EXPORT_SYMBOL(nf_nat_protocol_unregister);
542
543#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
544 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
545int
546nf_nat_port_range_to_nfattr(struct sk_buff *skb,
547 const struct nf_nat_range *range)
548{
549 NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(__be16),
550 &range->min.tcp.port);
551 NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(__be16),
552 &range->max.tcp.port);
553
554 return 0;
555
556nfattr_failure:
557 return -1;
558}
559EXPORT_SYMBOL_GPL(nf_nat_port_nfattr_to_range);
560
561int
562nf_nat_port_nfattr_to_range(struct nfattr *tb[], struct nf_nat_range *range)
563{
564 int ret = 0;
565
566 /* we have to return whether we actually parsed something or not */
567
568 if (tb[CTA_PROTONAT_PORT_MIN-1]) {
569 ret = 1;
570 range->min.tcp.port =
571 *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);
572 }
573
574 if (!tb[CTA_PROTONAT_PORT_MAX-1]) {
575 if (ret)
576 range->max.tcp.port = range->min.tcp.port;
577 } else {
578 ret = 1;
579 range->max.tcp.port =
580 *(__be16 *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);
581 }
582
583 return ret;
584}
585EXPORT_SYMBOL_GPL(nf_nat_port_range_to_nfattr);
586#endif
587
588static int __init nf_nat_init(void)
589{
590 size_t i;
591
592 /* Leave them the same for the moment. */
593 nf_nat_htable_size = nf_conntrack_htable_size;
594
595 /* One vmalloc for both hash tables */
596 bysource = vmalloc(sizeof(struct list_head) * nf_nat_htable_size);
597 if (!bysource)
598 return -ENOMEM;
599
600 /* Sew in builtin protocols. */
601 write_lock_bh(&nf_nat_lock);
602 for (i = 0; i < MAX_IP_NAT_PROTO; i++)
603 nf_nat_protos[i] = &nf_nat_unknown_protocol;
604 nf_nat_protos[IPPROTO_TCP] = &nf_nat_protocol_tcp;
605 nf_nat_protos[IPPROTO_UDP] = &nf_nat_protocol_udp;
606 nf_nat_protos[IPPROTO_ICMP] = &nf_nat_protocol_icmp;
607 write_unlock_bh(&nf_nat_lock);
608
609 for (i = 0; i < nf_nat_htable_size; i++) {
610 INIT_LIST_HEAD(&bysource[i]);
611 }
612
613 /* FIXME: Man, this is a hack. <SIGH> */
614 NF_CT_ASSERT(nf_conntrack_destroyed == NULL);
615 nf_conntrack_destroyed = &nf_nat_cleanup_conntrack;
616
617 /* Initialize fake conntrack so that NAT will skip it */
618 nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
619
620 l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);
621 return 0;
622}
623
624/* Clear NAT section of all conntracks, in case we're loaded again. */
625static int clean_nat(struct nf_conn *i, void *data)
626{
627 struct nf_conn_nat *nat = nfct_nat(i);
628
629 if (!nat)
630 return 0;
631 memset(nat, 0, sizeof(nat));
632 i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);
633 return 0;
634}
635
636static void __exit nf_nat_cleanup(void)
637{
638 nf_ct_iterate_cleanup(&clean_nat, NULL);
639 nf_conntrack_destroyed = NULL;
640 vfree(bysource);
641 nf_ct_l3proto_put(l3proto);
642}
643
644MODULE_LICENSE("GPL");
645
646module_init(nf_nat_init);
647module_exit(nf_nat_cleanup);
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
new file mode 100644
index 000000000000..751b59801755
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -0,0 +1,179 @@
1/* FTP extension for TCP NAT alteration. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
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/moduleparam.h>
13#include <linux/ip.h>
14#include <linux/tcp.h>
15#include <linux/netfilter_ipv4.h>
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nf_nat_helper.h>
18#include <net/netfilter/nf_nat_rule.h>
19#include <net/netfilter/nf_conntrack_helper.h>
20#include <net/netfilter/nf_conntrack_expect.h>
21#include <linux/netfilter/nf_conntrack_ftp.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
25MODULE_DESCRIPTION("ftp NAT helper");
26MODULE_ALIAS("ip_nat_ftp");
27
28#if 0
29#define DEBUGP printk
30#else
31#define DEBUGP(format, args...)
32#endif
33
34/* FIXME: Time out? --RR */
35
36static int
37mangle_rfc959_packet(struct sk_buff **pskb,
38 __be32 newip,
39 u_int16_t port,
40 unsigned int matchoff,
41 unsigned int matchlen,
42 struct nf_conn *ct,
43 enum ip_conntrack_info ctinfo,
44 u32 *seq)
45{
46 char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];
47
48 sprintf(buffer, "%u,%u,%u,%u,%u,%u",
49 NIPQUAD(newip), port>>8, port&0xFF);
50
51 DEBUGP("calling nf_nat_mangle_tcp_packet\n");
52
53 *seq += strlen(buffer) - matchlen;
54 return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
55 matchlen, buffer, strlen(buffer));
56}
57
58/* |1|132.235.1.2|6275| */
59static int
60mangle_eprt_packet(struct sk_buff **pskb,
61 __be32 newip,
62 u_int16_t port,
63 unsigned int matchoff,
64 unsigned int matchlen,
65 struct nf_conn *ct,
66 enum ip_conntrack_info ctinfo,
67 u32 *seq)
68{
69 char buffer[sizeof("|1|255.255.255.255|65535|")];
70
71 sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
72
73 DEBUGP("calling nf_nat_mangle_tcp_packet\n");
74
75 *seq += strlen(buffer) - matchlen;
76 return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
77 matchlen, buffer, strlen(buffer));
78}
79
80/* |1|132.235.1.2|6275| */
81static int
82mangle_epsv_packet(struct sk_buff **pskb,
83 __be32 newip,
84 u_int16_t port,
85 unsigned int matchoff,
86 unsigned int matchlen,
87 struct nf_conn *ct,
88 enum ip_conntrack_info ctinfo,
89 u32 *seq)
90{
91 char buffer[sizeof("|||65535|")];
92
93 sprintf(buffer, "|||%u|", port);
94
95 DEBUGP("calling nf_nat_mangle_tcp_packet\n");
96
97 *seq += strlen(buffer) - matchlen;
98 return nf_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff,
99 matchlen, buffer, strlen(buffer));
100}
101
102static int (*mangle[])(struct sk_buff **, __be32, u_int16_t,
103 unsigned int, unsigned int, struct nf_conn *,
104 enum ip_conntrack_info, u32 *seq)
105= {
106 [NF_CT_FTP_PORT] = mangle_rfc959_packet,
107 [NF_CT_FTP_PASV] = mangle_rfc959_packet,
108 [NF_CT_FTP_EPRT] = mangle_eprt_packet,
109 [NF_CT_FTP_EPSV] = mangle_epsv_packet
110};
111
112/* So, this packet has hit the connection tracking matching code.
113 Mangle it, and change the expectation to match the new version. */
114static unsigned int nf_nat_ftp(struct sk_buff **pskb,
115 enum ip_conntrack_info ctinfo,
116 enum nf_ct_ftp_type type,
117 unsigned int matchoff,
118 unsigned int matchlen,
119 struct nf_conntrack_expect *exp,
120 u32 *seq)
121{
122 __be32 newip;
123 u_int16_t port;
124 int dir = CTINFO2DIR(ctinfo);
125 struct nf_conn *ct = exp->master;
126
127 DEBUGP("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
128
129 /* Connection will come from wherever this packet goes, hence !dir */
130 newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
131 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
132 exp->dir = !dir;
133
134 /* When you see the packet, we need to NAT it the same as the
135 * this one. */
136 exp->expectfn = nf_nat_follow_master;
137
138 /* Try to get same port: if not, try to change it. */
139 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
140 exp->tuple.dst.u.tcp.port = htons(port);
141 if (nf_conntrack_expect_related(exp) == 0)
142 break;
143 }
144
145 if (port == 0)
146 return NF_DROP;
147
148 if (!mangle[type](pskb, newip, port, matchoff, matchlen, ct, ctinfo,
149 seq)) {
150 nf_conntrack_unexpect_related(exp);
151 return NF_DROP;
152 }
153 return NF_ACCEPT;
154}
155
156static void __exit nf_nat_ftp_fini(void)
157{
158 rcu_assign_pointer(nf_nat_ftp_hook, NULL);
159 synchronize_rcu();
160}
161
162static int __init nf_nat_ftp_init(void)
163{
164 BUG_ON(rcu_dereference(nf_nat_ftp_hook));
165 rcu_assign_pointer(nf_nat_ftp_hook, nf_nat_ftp);
166 return 0;
167}
168
169/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
170static int warn_set(const char *val, struct kernel_param *kp)
171{
172 printk(KERN_INFO KBUILD_MODNAME
173 ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
174 return 0;
175}
176module_param_call(ports, warn_set, NULL, NULL, 0);
177
178module_init(nf_nat_ftp_init);
179module_exit(nf_nat_ftp_fini);
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
new file mode 100644
index 000000000000..fb9ab0114c23
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -0,0 +1,596 @@
1/*
2 * H.323 extension for NAT alteration.
3 *
4 * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
5 *
6 * This source code is licensed under General Public License version 2.
7 *
8 * Based on the 'brute force' H.323 NAT module by
9 * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/tcp.h>
15#include <net/tcp.h>
16
17#include <net/netfilter/nf_nat.h>
18#include <net/netfilter/nf_nat_helper.h>
19#include <net/netfilter/nf_nat_rule.h>
20#include <net/netfilter/nf_conntrack_helper.h>
21#include <net/netfilter/nf_conntrack_expect.h>
22#include <linux/netfilter/nf_conntrack_h323.h>
23
24#if 0
25#define DEBUGP printk
26#else
27#define DEBUGP(format, args...)
28#endif
29
30/****************************************************************************/
31static int set_addr(struct sk_buff **pskb,
32 unsigned char **data, int dataoff,
33 unsigned int addroff, __be32 ip, __be16 port)
34{
35 enum ip_conntrack_info ctinfo;
36 struct nf_conn *ct = ip_conntrack_get(*pskb, &ctinfo);
37 struct {
38 __be32 ip;
39 __be16 port;
40 } __attribute__ ((__packed__)) buf;
41 struct tcphdr _tcph, *th;
42
43 buf.ip = ip;
44 buf.port = port;
45 addroff += dataoff;
46
47 if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
48 if (!nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
49 addroff, sizeof(buf),
50 (char *) &buf, sizeof(buf))) {
51 if (net_ratelimit())
52 printk("nf_nat_h323: nf_nat_mangle_tcp_packet"
53 " error\n");
54 return -1;
55 }
56
57 /* Relocate data pointer */
58 th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
59 sizeof(_tcph), &_tcph);
60 if (th == NULL)
61 return -1;
62 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
63 th->doff * 4 + dataoff;
64 } else {
65 if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
66 addroff, sizeof(buf),
67 (char *) &buf, sizeof(buf))) {
68 if (net_ratelimit())
69 printk("nf_nat_h323: nf_nat_mangle_udp_packet"
70 " error\n");
71 return -1;
72 }
73 /* nf_nat_mangle_udp_packet uses skb_make_writable() to copy
74 * or pull everything in a linear buffer, so we can safely
75 * use the skb pointers now */
76 *data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
77 sizeof(struct udphdr);
78 }
79
80 return 0;
81}
82
83/****************************************************************************/
84static int set_h225_addr(struct sk_buff **pskb,
85 unsigned char **data, int dataoff,
86 TransportAddress *taddr,
87 union nf_conntrack_address *addr, __be16 port)
88{
89 return set_addr(pskb, data, dataoff, taddr->ipAddress.ip,
90 addr->ip, port);
91}
92
93/****************************************************************************/
94static int set_h245_addr(struct sk_buff **pskb,
95 unsigned char **data, int dataoff,
96 H245_TransportAddress *taddr,
97 union nf_conntrack_address *addr, __be16 port)
98{
99 return set_addr(pskb, data, dataoff,
100 taddr->unicastAddress.iPAddress.network,
101 addr->ip, port);
102}
103
104/****************************************************************************/
105static int set_sig_addr(struct sk_buff **pskb, struct nf_conn *ct,
106 enum ip_conntrack_info ctinfo,
107 unsigned char **data,
108 TransportAddress *taddr, int count)
109{
110 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
111 int dir = CTINFO2DIR(ctinfo);
112 int i;
113 __be16 port;
114 union nf_conntrack_address addr;
115
116 for (i = 0; i < count; i++) {
117 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
118 if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
119 port == info->sig_port[dir]) {
120 /* GW->GK */
121
122 /* Fix for Gnomemeeting */
123 if (i > 0 &&
124 get_h225_addr(ct, *data, &taddr[0],
125 &addr, &port) &&
126 (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
127 i = 0;
128
129 DEBUGP
130 ("nf_nat_ras: set signal address "
131 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
132 NIPQUAD(ip), port,
133 NIPQUAD(ct->tuplehash[!dir].tuple.dst.
134 ip), info->sig_port[!dir]);
135 return set_h225_addr(pskb, data, 0, &taddr[i],
136 &ct->tuplehash[!dir].
137 tuple.dst.u3,
138 info->sig_port[!dir]);
139 } else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
140 port == info->sig_port[dir]) {
141 /* GK->GW */
142 DEBUGP
143 ("nf_nat_ras: set signal address "
144 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
145 NIPQUAD(ip), port,
146 NIPQUAD(ct->tuplehash[!dir].tuple.src.
147 ip), info->sig_port[!dir]);
148 return set_h225_addr(pskb, data, 0, &taddr[i],
149 &ct->tuplehash[!dir].
150 tuple.src.u3,
151 info->sig_port[!dir]);
152 }
153 }
154 }
155
156 return 0;
157}
158
159/****************************************************************************/
160static int set_ras_addr(struct sk_buff **pskb, struct nf_conn *ct,
161 enum ip_conntrack_info ctinfo,
162 unsigned char **data,
163 TransportAddress *taddr, int count)
164{
165 int dir = CTINFO2DIR(ctinfo);
166 int i;
167 __be16 port;
168 union nf_conntrack_address addr;
169
170 for (i = 0; i < count; i++) {
171 if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
172 addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
173 port == ct->tuplehash[dir].tuple.src.u.udp.port) {
174 DEBUGP("nf_nat_ras: set rasAddress "
175 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
176 NIPQUAD(ip), ntohs(port),
177 NIPQUAD(ct->tuplehash[!dir].tuple.dst.u3.ip),
178 ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.
179 port));
180 return set_h225_addr(pskb, data, 0, &taddr[i],
181 &ct->tuplehash[!dir].tuple.dst.u3,
182 ct->tuplehash[!dir].tuple.
183 dst.u.udp.port);
184 }
185 }
186
187 return 0;
188}
189
190/****************************************************************************/
191static int nat_rtp_rtcp(struct sk_buff **pskb, struct nf_conn *ct,
192 enum ip_conntrack_info ctinfo,
193 unsigned char **data, int dataoff,
194 H245_TransportAddress *taddr,
195 __be16 port, __be16 rtp_port,
196 struct nf_conntrack_expect *rtp_exp,
197 struct nf_conntrack_expect *rtcp_exp)
198{
199 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
200 int dir = CTINFO2DIR(ctinfo);
201 int i;
202 u_int16_t nated_port;
203
204 /* Set expectations for NAT */
205 rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
206 rtp_exp->expectfn = nf_nat_follow_master;
207 rtp_exp->dir = !dir;
208 rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
209 rtcp_exp->expectfn = nf_nat_follow_master;
210 rtcp_exp->dir = !dir;
211
212 /* Lookup existing expects */
213 for (i = 0; i < H323_RTP_CHANNEL_MAX; i++) {
214 if (info->rtp_port[i][dir] == rtp_port) {
215 /* Expected */
216
217 /* Use allocated ports first. This will refresh
218 * the expects */
219 rtp_exp->tuple.dst.u.udp.port = info->rtp_port[i][dir];
220 rtcp_exp->tuple.dst.u.udp.port =
221 htons(ntohs(info->rtp_port[i][dir]) + 1);
222 break;
223 } else if (info->rtp_port[i][dir] == 0) {
224 /* Not expected */
225 break;
226 }
227 }
228
229 /* Run out of expectations */
230 if (i >= H323_RTP_CHANNEL_MAX) {
231 if (net_ratelimit())
232 printk("nf_nat_h323: out of expectations\n");
233 return 0;
234 }
235
236 /* Try to get a pair of ports. */
237 for (nated_port = ntohs(rtp_exp->tuple.dst.u.udp.port);
238 nated_port != 0; nated_port += 2) {
239 rtp_exp->tuple.dst.u.udp.port = htons(nated_port);
240 if (nf_conntrack_expect_related(rtp_exp) == 0) {
241 rtcp_exp->tuple.dst.u.udp.port =
242 htons(nated_port + 1);
243 if (nf_conntrack_expect_related(rtcp_exp) == 0)
244 break;
245 nf_conntrack_unexpect_related(rtp_exp);
246 }
247 }
248
249 if (nated_port == 0) { /* No port available */
250 if (net_ratelimit())
251 printk("nf_nat_h323: out of RTP ports\n");
252 return 0;
253 }
254
255 /* Modify signal */
256 if (set_h245_addr(pskb, data, dataoff, taddr,
257 &ct->tuplehash[!dir].tuple.dst.u3,
258 htons((port & htons(1)) ? nated_port + 1 :
259 nated_port)) == 0) {
260 /* Save ports */
261 info->rtp_port[i][dir] = rtp_port;
262 info->rtp_port[i][!dir] = htons(nated_port);
263 } else {
264 nf_conntrack_unexpect_related(rtp_exp);
265 nf_conntrack_unexpect_related(rtcp_exp);
266 return -1;
267 }
268
269 /* Success */
270 DEBUGP("nf_nat_h323: expect RTP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
271 NIPQUAD(rtp_exp->tuple.src.ip),
272 ntohs(rtp_exp->tuple.src.u.udp.port),
273 NIPQUAD(rtp_exp->tuple.dst.ip),
274 ntohs(rtp_exp->tuple.dst.u.udp.port));
275 DEBUGP("nf_nat_h323: expect RTCP %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
276 NIPQUAD(rtcp_exp->tuple.src.ip),
277 ntohs(rtcp_exp->tuple.src.u.udp.port),
278 NIPQUAD(rtcp_exp->tuple.dst.ip),
279 ntohs(rtcp_exp->tuple.dst.u.udp.port));
280
281 return 0;
282}
283
284/****************************************************************************/
285static int nat_t120(struct sk_buff **pskb, struct nf_conn *ct,
286 enum ip_conntrack_info ctinfo,
287 unsigned char **data, int dataoff,
288 H245_TransportAddress *taddr, __be16 port,
289 struct nf_conntrack_expect *exp)
290{
291 int dir = CTINFO2DIR(ctinfo);
292 u_int16_t nated_port = ntohs(port);
293
294 /* Set expectations for NAT */
295 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
296 exp->expectfn = nf_nat_follow_master;
297 exp->dir = !dir;
298
299 /* Try to get same port: if not, try to change it. */
300 for (; nated_port != 0; nated_port++) {
301 exp->tuple.dst.u.tcp.port = htons(nated_port);
302 if (nf_conntrack_expect_related(exp) == 0)
303 break;
304 }
305
306 if (nated_port == 0) { /* No port available */
307 if (net_ratelimit())
308 printk("nf_nat_h323: out of TCP ports\n");
309 return 0;
310 }
311
312 /* Modify signal */
313 if (set_h245_addr(pskb, data, dataoff, taddr,
314 &ct->tuplehash[!dir].tuple.dst.u3,
315 htons(nated_port)) < 0) {
316 nf_conntrack_unexpect_related(exp);
317 return -1;
318 }
319
320 DEBUGP("nf_nat_h323: expect T.120 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
321 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
322 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
323
324 return 0;
325}
326
327/****************************************************************************/
328static int nat_h245(struct sk_buff **pskb, struct nf_conn *ct,
329 enum ip_conntrack_info ctinfo,
330 unsigned char **data, int dataoff,
331 TransportAddress *taddr, __be16 port,
332 struct nf_conntrack_expect *exp)
333{
334 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
335 int dir = CTINFO2DIR(ctinfo);
336 u_int16_t nated_port = ntohs(port);
337
338 /* Set expectations for NAT */
339 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
340 exp->expectfn = nf_nat_follow_master;
341 exp->dir = !dir;
342
343 /* Check existing expects */
344 if (info->sig_port[dir] == port)
345 nated_port = ntohs(info->sig_port[!dir]);
346
347 /* Try to get same port: if not, try to change it. */
348 for (; nated_port != 0; nated_port++) {
349 exp->tuple.dst.u.tcp.port = htons(nated_port);
350 if (nf_conntrack_expect_related(exp) == 0)
351 break;
352 }
353
354 if (nated_port == 0) { /* No port available */
355 if (net_ratelimit())
356 printk("nf_nat_q931: out of TCP ports\n");
357 return 0;
358 }
359
360 /* Modify signal */
361 if (set_h225_addr(pskb, data, dataoff, taddr,
362 &ct->tuplehash[!dir].tuple.dst.u3,
363 htons(nated_port)) == 0) {
364 /* Save ports */
365 info->sig_port[dir] = port;
366 info->sig_port[!dir] = htons(nated_port);
367 } else {
368 nf_conntrack_unexpect_related(exp);
369 return -1;
370 }
371
372 DEBUGP("nf_nat_q931: expect H.245 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
373 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
374 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
375
376 return 0;
377}
378
379/****************************************************************************
380 * This conntrack expect function replaces nf_conntrack_q931_expect()
381 * which was set by nf_conntrack_h323.c.
382 ****************************************************************************/
383static void ip_nat_q931_expect(struct nf_conn *new,
384 struct nf_conntrack_expect *this)
385{
386 struct ip_nat_range range;
387
388 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
389 nf_nat_follow_master(new, this);
390 return;
391 }
392
393 /* This must be a fresh one. */
394 BUG_ON(new->status & IPS_NAT_DONE_MASK);
395
396 /* Change src to where master sends to */
397 range.flags = IP_NAT_RANGE_MAP_IPS;
398 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
399
400 /* hook doesn't matter, but it has to do source manip */
401 nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
402
403 /* For DST manip, map port here to where it's expected. */
404 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
405 range.min = range.max = this->saved_proto;
406 range.min_ip = range.max_ip =
407 new->master->tuplehash[!this->dir].tuple.src.u3.ip;
408
409 /* hook doesn't matter, but it has to do destination manip */
410 nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
411}
412
413/****************************************************************************/
414static int nat_q931(struct sk_buff **pskb, struct nf_conn *ct,
415 enum ip_conntrack_info ctinfo,
416 unsigned char **data, TransportAddress *taddr, int idx,
417 __be16 port, struct nf_conntrack_expect *exp)
418{
419 struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
420 int dir = CTINFO2DIR(ctinfo);
421 u_int16_t nated_port = ntohs(port);
422 union nf_conntrack_address addr;
423
424 /* Set expectations for NAT */
425 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
426 exp->expectfn = ip_nat_q931_expect;
427 exp->dir = !dir;
428
429 /* Check existing expects */
430 if (info->sig_port[dir] == port)
431 nated_port = ntohs(info->sig_port[!dir]);
432
433 /* Try to get same port: if not, try to change it. */
434 for (; nated_port != 0; nated_port++) {
435 exp->tuple.dst.u.tcp.port = htons(nated_port);
436 if (nf_conntrack_expect_related(exp) == 0)
437 break;
438 }
439
440 if (nated_port == 0) { /* No port available */
441 if (net_ratelimit())
442 printk("nf_nat_ras: out of TCP ports\n");
443 return 0;
444 }
445
446 /* Modify signal */
447 if (set_h225_addr(pskb, data, 0, &taddr[idx],
448 &ct->tuplehash[!dir].tuple.dst.u3,
449 htons(nated_port)) == 0) {
450 /* Save ports */
451 info->sig_port[dir] = port;
452 info->sig_port[!dir] = htons(nated_port);
453
454 /* Fix for Gnomemeeting */
455 if (idx > 0 &&
456 get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
457 (ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
458 set_h225_addr_hook(pskb, data, 0, &taddr[0],
459 &ct->tuplehash[!dir].tuple.dst.u3,
460 info->sig_port[!dir]);
461 }
462 } else {
463 nf_conntrack_unexpect_related(exp);
464 return -1;
465 }
466
467 /* Success */
468 DEBUGP("nf_nat_ras: expect Q.931 %u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
469 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
470 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
471
472 return 0;
473}
474
475/****************************************************************************/
476static void ip_nat_callforwarding_expect(struct nf_conn *new,
477 struct nf_conntrack_expect *this)
478{
479 struct nf_nat_range range;
480
481 /* This must be a fresh one. */
482 BUG_ON(new->status & IPS_NAT_DONE_MASK);
483
484 /* Change src to where master sends to */
485 range.flags = IP_NAT_RANGE_MAP_IPS;
486 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
487
488 /* hook doesn't matter, but it has to do source manip */
489 nf_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
490
491 /* For DST manip, map port here to where it's expected. */
492 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
493 range.min = range.max = this->saved_proto;
494 range.min_ip = range.max_ip = this->saved_ip;
495
496 /* hook doesn't matter, but it has to do destination manip */
497 nf_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
498}
499
500/****************************************************************************/
501static int nat_callforwarding(struct sk_buff **pskb, struct nf_conn *ct,
502 enum ip_conntrack_info ctinfo,
503 unsigned char **data, int dataoff,
504 TransportAddress *taddr, __be16 port,
505 struct nf_conntrack_expect *exp)
506{
507 int dir = CTINFO2DIR(ctinfo);
508 u_int16_t nated_port;
509
510 /* Set expectations for NAT */
511 exp->saved_ip = exp->tuple.dst.u3.ip;
512 exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
513 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
514 exp->expectfn = ip_nat_callforwarding_expect;
515 exp->dir = !dir;
516
517 /* Try to get same port: if not, try to change it. */
518 for (nated_port = ntohs(port); nated_port != 0; nated_port++) {
519 exp->tuple.dst.u.tcp.port = htons(nated_port);
520 if (nf_conntrack_expect_related(exp) == 0)
521 break;
522 }
523
524 if (nated_port == 0) { /* No port available */
525 if (net_ratelimit())
526 printk("nf_nat_q931: out of TCP ports\n");
527 return 0;
528 }
529
530 /* Modify signal */
531 if (!set_h225_addr(pskb, data, dataoff, taddr,
532 &ct->tuplehash[!dir].tuple.dst.u3,
533 htons(nated_port)) == 0) {
534 nf_conntrack_unexpect_related(exp);
535 return -1;
536 }
537
538 /* Success */
539 DEBUGP("nf_nat_q931: expect Call Forwarding "
540 "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
541 NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
542 NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
543
544 return 0;
545}
546
547/****************************************************************************/
548static int __init init(void)
549{
550 BUG_ON(rcu_dereference(set_h245_addr_hook) != NULL);
551 BUG_ON(rcu_dereference(set_h225_addr_hook) != NULL);
552 BUG_ON(rcu_dereference(set_sig_addr_hook) != NULL);
553 BUG_ON(rcu_dereference(set_ras_addr_hook) != NULL);
554 BUG_ON(rcu_dereference(nat_rtp_rtcp_hook) != NULL);
555 BUG_ON(rcu_dereference(nat_t120_hook) != NULL);
556 BUG_ON(rcu_dereference(nat_h245_hook) != NULL);
557 BUG_ON(rcu_dereference(nat_callforwarding_hook) != NULL);
558 BUG_ON(rcu_dereference(nat_q931_hook) != NULL);
559
560 rcu_assign_pointer(set_h245_addr_hook, set_h245_addr);
561 rcu_assign_pointer(set_h225_addr_hook, set_h225_addr);
562 rcu_assign_pointer(set_sig_addr_hook, set_sig_addr);
563 rcu_assign_pointer(set_ras_addr_hook, set_ras_addr);
564 rcu_assign_pointer(nat_rtp_rtcp_hook, nat_rtp_rtcp);
565 rcu_assign_pointer(nat_t120_hook, nat_t120);
566 rcu_assign_pointer(nat_h245_hook, nat_h245);
567 rcu_assign_pointer(nat_callforwarding_hook, nat_callforwarding);
568 rcu_assign_pointer(nat_q931_hook, nat_q931);
569
570 DEBUGP("nf_nat_h323: init success\n");
571 return 0;
572}
573
574/****************************************************************************/
575static void __exit fini(void)
576{
577 rcu_assign_pointer(set_h245_addr_hook, NULL);
578 rcu_assign_pointer(set_h225_addr_hook, NULL);
579 rcu_assign_pointer(set_sig_addr_hook, NULL);
580 rcu_assign_pointer(set_ras_addr_hook, NULL);
581 rcu_assign_pointer(nat_rtp_rtcp_hook, NULL);
582 rcu_assign_pointer(nat_t120_hook, NULL);
583 rcu_assign_pointer(nat_h245_hook, NULL);
584 rcu_assign_pointer(nat_callforwarding_hook, NULL);
585 rcu_assign_pointer(nat_q931_hook, NULL);
586 synchronize_rcu();
587}
588
589/****************************************************************************/
590module_init(init);
591module_exit(fini);
592
593MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
594MODULE_DESCRIPTION("H.323 NAT helper");
595MODULE_LICENSE("GPL");
596MODULE_ALIAS("ip_nat_h323");
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
new file mode 100644
index 000000000000..98fbfc84d183
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -0,0 +1,433 @@
1/* ip_nat_helper.c - generic support functions for NAT helpers
2 *
3 * (C) 2000-2002 Harald Welte <laforge@netfilter.org>
4 * (C) 2003-2006 Netfilter Core Team <coreteam@netfilter.org>
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#include <linux/module.h>
11#include <linux/kmod.h>
12#include <linux/types.h>
13#include <linux/timer.h>
14#include <linux/skbuff.h>
15#include <linux/tcp.h>
16#include <linux/udp.h>
17#include <net/checksum.h>
18#include <net/tcp.h>
19
20#include <linux/netfilter_ipv4.h>
21#include <net/netfilter/nf_conntrack.h>
22#include <net/netfilter/nf_conntrack_helper.h>
23#include <net/netfilter/nf_conntrack_expect.h>
24#include <net/netfilter/nf_nat.h>
25#include <net/netfilter/nf_nat_protocol.h>
26#include <net/netfilter/nf_nat_core.h>
27#include <net/netfilter/nf_nat_helper.h>
28
29#if 0
30#define DEBUGP printk
31#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
32#else
33#define DEBUGP(format, args...)
34#define DUMP_OFFSET(x)
35#endif
36
37static DEFINE_SPINLOCK(nf_nat_seqofs_lock);
38
39/* Setup TCP sequence correction given this change at this sequence */
40static inline void
41adjust_tcp_sequence(u32 seq,
42 int sizediff,
43 struct nf_conn *ct,
44 enum ip_conntrack_info ctinfo)
45{
46 int dir;
47 struct nf_nat_seq *this_way, *other_way;
48 struct nf_conn_nat *nat = nfct_nat(ct);
49
50 DEBUGP("nf_nat_resize_packet: old_size = %u, new_size = %u\n",
51 (*skb)->len, new_size);
52
53 dir = CTINFO2DIR(ctinfo);
54
55 this_way = &nat->info.seq[dir];
56 other_way = &nat->info.seq[!dir];
57
58 DEBUGP("nf_nat_resize_packet: Seq_offset before: ");
59 DUMP_OFFSET(this_way);
60
61 spin_lock_bh(&nf_nat_seqofs_lock);
62
63 /* SYN adjust. If it's uninitialized, or this is after last
64 * correction, record it: we don't handle more than one
65 * adjustment in the window, but do deal with common case of a
66 * retransmit */
67 if (this_way->offset_before == this_way->offset_after ||
68 before(this_way->correction_pos, seq)) {
69 this_way->correction_pos = seq;
70 this_way->offset_before = this_way->offset_after;
71 this_way->offset_after += sizediff;
72 }
73 spin_unlock_bh(&nf_nat_seqofs_lock);
74
75 DEBUGP("nf_nat_resize_packet: Seq_offset after: ");
76 DUMP_OFFSET(this_way);
77}
78
79/* Frobs data inside this packet, which is linear. */
80static void mangle_contents(struct sk_buff *skb,
81 unsigned int dataoff,
82 unsigned int match_offset,
83 unsigned int match_len,
84 const char *rep_buffer,
85 unsigned int rep_len)
86{
87 unsigned char *data;
88
89 BUG_ON(skb_is_nonlinear(skb));
90 data = (unsigned char *)skb->nh.iph + dataoff;
91
92 /* move post-replacement */
93 memmove(data + match_offset + rep_len,
94 data + match_offset + match_len,
95 skb->tail - (data + match_offset + match_len));
96
97 /* insert data from buffer */
98 memcpy(data + match_offset, rep_buffer, rep_len);
99
100 /* update skb info */
101 if (rep_len > match_len) {
102 DEBUGP("nf_nat_mangle_packet: Extending packet by "
103 "%u from %u bytes\n", rep_len - match_len,
104 skb->len);
105 skb_put(skb, rep_len - match_len);
106 } else {
107 DEBUGP("nf_nat_mangle_packet: Shrinking packet from "
108 "%u from %u bytes\n", match_len - rep_len,
109 skb->len);
110 __skb_trim(skb, skb->len + rep_len - match_len);
111 }
112
113 /* fix IP hdr checksum information */
114 skb->nh.iph->tot_len = htons(skb->len);
115 ip_send_check(skb->nh.iph);
116}
117
118/* Unusual, but possible case. */
119static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
120{
121 struct sk_buff *nskb;
122
123 if ((*pskb)->len + extra > 65535)
124 return 0;
125
126 nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC);
127 if (!nskb)
128 return 0;
129
130 /* Transfer socket to new skb. */
131 if ((*pskb)->sk)
132 skb_set_owner_w(nskb, (*pskb)->sk);
133 kfree_skb(*pskb);
134 *pskb = nskb;
135 return 1;
136}
137
138/* Generic function for mangling variable-length address changes inside
139 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
140 * command in FTP).
141 *
142 * Takes care about all the nasty sequence number changes, checksumming,
143 * skb enlargement, ...
144 *
145 * */
146int
147nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
148 struct nf_conn *ct,
149 enum ip_conntrack_info ctinfo,
150 unsigned int match_offset,
151 unsigned int match_len,
152 const char *rep_buffer,
153 unsigned int rep_len)
154{
155 struct iphdr *iph;
156 struct tcphdr *tcph;
157 int oldlen, datalen;
158
159 if (!skb_make_writable(pskb, (*pskb)->len))
160 return 0;
161
162 if (rep_len > match_len &&
163 rep_len - match_len > skb_tailroom(*pskb) &&
164 !enlarge_skb(pskb, rep_len - match_len))
165 return 0;
166
167 SKB_LINEAR_ASSERT(*pskb);
168
169 iph = (*pskb)->nh.iph;
170 tcph = (void *)iph + iph->ihl*4;
171
172 oldlen = (*pskb)->len - iph->ihl*4;
173 mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
174 match_offset, match_len, rep_buffer, rep_len);
175
176 datalen = (*pskb)->len - iph->ihl*4;
177 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
178 tcph->check = 0;
179 tcph->check = tcp_v4_check(tcph, datalen,
180 iph->saddr, iph->daddr,
181 csum_partial((char *)tcph,
182 datalen, 0));
183 } else
184 nf_proto_csum_replace2(&tcph->check, *pskb,
185 htons(oldlen), htons(datalen), 1);
186
187 if (rep_len != match_len) {
188 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
189 adjust_tcp_sequence(ntohl(tcph->seq),
190 (int)rep_len - (int)match_len,
191 ct, ctinfo);
192 /* Tell TCP window tracking about seq change */
193 nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4,
194 ct, CTINFO2DIR(ctinfo));
195 }
196 return 1;
197}
198EXPORT_SYMBOL(nf_nat_mangle_tcp_packet);
199
200/* Generic function for mangling variable-length address changes inside
201 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
202 * command in the Amanda protocol)
203 *
204 * Takes care about all the nasty sequence number changes, checksumming,
205 * skb enlargement, ...
206 *
207 * XXX - This function could be merged with nf_nat_mangle_tcp_packet which
208 * should be fairly easy to do.
209 */
210int
211nf_nat_mangle_udp_packet(struct sk_buff **pskb,
212 struct nf_conn *ct,
213 enum ip_conntrack_info ctinfo,
214 unsigned int match_offset,
215 unsigned int match_len,
216 const char *rep_buffer,
217 unsigned int rep_len)
218{
219 struct iphdr *iph;
220 struct udphdr *udph;
221 int datalen, oldlen;
222
223 /* UDP helpers might accidentally mangle the wrong packet */
224 iph = (*pskb)->nh.iph;
225 if ((*pskb)->len < iph->ihl*4 + sizeof(*udph) +
226 match_offset + match_len)
227 return 0;
228
229 if (!skb_make_writable(pskb, (*pskb)->len))
230 return 0;
231
232 if (rep_len > match_len &&
233 rep_len - match_len > skb_tailroom(*pskb) &&
234 !enlarge_skb(pskb, rep_len - match_len))
235 return 0;
236
237 iph = (*pskb)->nh.iph;
238 udph = (void *)iph + iph->ihl*4;
239
240 oldlen = (*pskb)->len - iph->ihl*4;
241 mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
242 match_offset, match_len, rep_buffer, rep_len);
243
244 /* update the length of the UDP packet */
245 datalen = (*pskb)->len - iph->ihl*4;
246 udph->len = htons(datalen);
247
248 /* fix udp checksum if udp checksum was previously calculated */
249 if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
250 return 1;
251
252 if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
253 udph->check = 0;
254 udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
255 datalen, IPPROTO_UDP,
256 csum_partial((char *)udph,
257 datalen, 0));
258 if (!udph->check)
259 udph->check = CSUM_MANGLED_0;
260 } else
261 nf_proto_csum_replace2(&udph->check, *pskb,
262 htons(oldlen), htons(datalen), 1);
263
264 return 1;
265}
266EXPORT_SYMBOL(nf_nat_mangle_udp_packet);
267
268/* Adjust one found SACK option including checksum correction */
269static void
270sack_adjust(struct sk_buff *skb,
271 struct tcphdr *tcph,
272 unsigned int sackoff,
273 unsigned int sackend,
274 struct nf_nat_seq *natseq)
275{
276 while (sackoff < sackend) {
277 struct tcp_sack_block_wire *sack;
278 __be32 new_start_seq, new_end_seq;
279
280 sack = (void *)skb->data + sackoff;
281 if (after(ntohl(sack->start_seq) - natseq->offset_before,
282 natseq->correction_pos))
283 new_start_seq = htonl(ntohl(sack->start_seq)
284 - natseq->offset_after);
285 else
286 new_start_seq = htonl(ntohl(sack->start_seq)
287 - natseq->offset_before);
288
289 if (after(ntohl(sack->end_seq) - natseq->offset_before,
290 natseq->correction_pos))
291 new_end_seq = htonl(ntohl(sack->end_seq)
292 - natseq->offset_after);
293 else
294 new_end_seq = htonl(ntohl(sack->end_seq)
295 - natseq->offset_before);
296
297 DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
298 ntohl(sack->start_seq), new_start_seq,
299 ntohl(sack->end_seq), new_end_seq);
300
301 nf_proto_csum_replace4(&tcph->check, skb,
302 sack->start_seq, new_start_seq, 0);
303 nf_proto_csum_replace4(&tcph->check, skb,
304 sack->end_seq, new_end_seq, 0);
305 sack->start_seq = new_start_seq;
306 sack->end_seq = new_end_seq;
307 sackoff += sizeof(*sack);
308 }
309}
310
311/* TCP SACK sequence number adjustment */
312static inline unsigned int
313nf_nat_sack_adjust(struct sk_buff **pskb,
314 struct tcphdr *tcph,
315 struct nf_conn *ct,
316 enum ip_conntrack_info ctinfo)
317{
318 unsigned int dir, optoff, optend;
319 struct nf_conn_nat *nat = nfct_nat(ct);
320
321 optoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct tcphdr);
322 optend = (*pskb)->nh.iph->ihl*4 + tcph->doff*4;
323
324 if (!skb_make_writable(pskb, optend))
325 return 0;
326
327 dir = CTINFO2DIR(ctinfo);
328
329 while (optoff < optend) {
330 /* Usually: option, length. */
331 unsigned char *op = (*pskb)->data + optoff;
332
333 switch (op[0]) {
334 case TCPOPT_EOL:
335 return 1;
336 case TCPOPT_NOP:
337 optoff++;
338 continue;
339 default:
340 /* no partial options */
341 if (optoff + 1 == optend ||
342 optoff + op[1] > optend ||
343 op[1] < 2)
344 return 0;
345 if (op[0] == TCPOPT_SACK &&
346 op[1] >= 2+TCPOLEN_SACK_PERBLOCK &&
347 ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0)
348 sack_adjust(*pskb, tcph, optoff+2,
349 optoff+op[1],
350 &nat->info.seq[!dir]);
351 optoff += op[1];
352 }
353 }
354 return 1;
355}
356
357/* TCP sequence number adjustment. Returns 1 on success, 0 on failure */
358int
359nf_nat_seq_adjust(struct sk_buff **pskb,
360 struct nf_conn *ct,
361 enum ip_conntrack_info ctinfo)
362{
363 struct tcphdr *tcph;
364 int dir;
365 __be32 newseq, newack;
366 struct nf_conn_nat *nat = nfct_nat(ct);
367 struct nf_nat_seq *this_way, *other_way;
368
369 dir = CTINFO2DIR(ctinfo);
370
371 this_way = &nat->info.seq[dir];
372 other_way = &nat->info.seq[!dir];
373
374 if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
375 return 0;
376
377 tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
378 if (after(ntohl(tcph->seq), this_way->correction_pos))
379 newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
380 else
381 newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);
382
383 if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
384 other_way->correction_pos))
385 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
386 else
387 newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);
388
389 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
390 nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);
391
392 DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
393 ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
394 ntohl(newack));
395
396 tcph->seq = newseq;
397 tcph->ack_seq = newack;
398
399 if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo))
400 return 0;
401
402 nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, ct, dir);
403
404 return 1;
405}
406EXPORT_SYMBOL(nf_nat_seq_adjust);
407
408/* Setup NAT on this expected conntrack so it follows master. */
409/* If we fail to get a free NAT slot, we'll get dropped on confirm */
410void nf_nat_follow_master(struct nf_conn *ct,
411 struct nf_conntrack_expect *exp)
412{
413 struct nf_nat_range range;
414
415 /* This must be a fresh one. */
416 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
417
418 /* Change src to where master sends to */
419 range.flags = IP_NAT_RANGE_MAP_IPS;
420 range.min_ip = range.max_ip
421 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
422 /* hook doesn't matter, but it has to do source manip */
423 nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
424
425 /* For DST manip, map port here to where it's expected. */
426 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
427 range.min = range.max = exp->saved_proto;
428 range.min_ip = range.max_ip
429 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
430 /* hook doesn't matter, but it has to do destination manip */
431 nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
432}
433EXPORT_SYMBOL(nf_nat_follow_master);
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/ipv4/netfilter/nf_nat_irc.c
new file mode 100644
index 000000000000..9b8c0daea744
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_irc.c
@@ -0,0 +1,101 @@
1/* IRC extension for TCP NAT alteration.
2 *
3 * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2004 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
5 * based on a copy of RR's ip_nat_ftp.c
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/tcp.h>
16#include <linux/kernel.h>
17
18#include <net/netfilter/nf_nat.h>
19#include <net/netfilter/nf_nat_helper.h>
20#include <net/netfilter/nf_nat_rule.h>
21#include <net/netfilter/nf_conntrack_helper.h>
22#include <net/netfilter/nf_conntrack_expect.h>
23#include <linux/netfilter/nf_conntrack_irc.h>
24
25#if 0
26#define DEBUGP printk
27#else
28#define DEBUGP(format, args...)
29#endif
30
31MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
32MODULE_DESCRIPTION("IRC (DCC) NAT helper");
33MODULE_LICENSE("GPL");
34MODULE_ALIAS("ip_nat_irc");
35
36static unsigned int help(struct sk_buff **pskb,
37 enum ip_conntrack_info ctinfo,
38 unsigned int matchoff,
39 unsigned int matchlen,
40 struct nf_conntrack_expect *exp)
41{
42 char buffer[sizeof("4294967296 65635")];
43 u_int32_t ip;
44 u_int16_t port;
45 unsigned int ret;
46
47 DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
48 expect->seq, exp_irc_info->len, ntohl(tcph->seq));
49
50 /* Reply comes from server. */
51 exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
52 exp->dir = IP_CT_DIR_REPLY;
53 exp->expectfn = nf_nat_follow_master;
54
55 /* Try to get same port: if not, try to change it. */
56 for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
57 exp->tuple.dst.u.tcp.port = htons(port);
58 if (nf_conntrack_expect_related(exp) == 0)
59 break;
60 }
61
62 if (port == 0)
63 return NF_DROP;
64
65 ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip);
66 sprintf(buffer, "%u %u", ip, port);
67 DEBUGP("nf_nat_irc: inserting '%s' == %u.%u.%u.%u, port %u\n",
68 buffer, NIPQUAD(ip), port);
69
70 ret = nf_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
71 matchoff, matchlen, buffer,
72 strlen(buffer));
73 if (ret != NF_ACCEPT)
74 nf_conntrack_unexpect_related(exp);
75 return ret;
76}
77
78static void __exit nf_nat_irc_fini(void)
79{
80 rcu_assign_pointer(nf_nat_irc_hook, NULL);
81 synchronize_rcu();
82}
83
84static int __init nf_nat_irc_init(void)
85{
86 BUG_ON(rcu_dereference(nf_nat_irc_hook));
87 rcu_assign_pointer(nf_nat_irc_hook, help);
88 return 0;
89}
90
91/* Prior to 2.6.11, we had a ports param. No longer, but don't break users. */
92static int warn_set(const char *val, struct kernel_param *kp)
93{
94 printk(KERN_INFO KBUILD_MODNAME
95 ": kernel >= 2.6.10 only uses 'ports' for conntrack modules\n");
96 return 0;
97}
98module_param_call(ports, warn_set, NULL, NULL, 0);
99
100module_init(nf_nat_irc_init);
101module_exit(nf_nat_irc_fini);
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
new file mode 100644
index 000000000000..0ae45b79a4eb
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -0,0 +1,315 @@
1/*
2 * nf_nat_pptp.c
3 *
4 * NAT support for PPTP (Point to Point Tunneling Protocol).
5 * PPTP is a a protocol for creating virtual private networks.
6 * It is a specification defined by Microsoft and some vendors
7 * working with Microsoft. PPTP is built on top of a modified
8 * version of the Internet Generic Routing Encapsulation Protocol.
9 * GRE is defined in RFC 1701 and RFC 1702. Documentation of
10 * PPTP can be found in RFC 2637
11 *
12 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
13 *
14 * Development of this code funded by Astaro AG (http://www.astaro.com/)
15 *
16 * TODO: - NAT to a unique tuple, not to TCP source port
17 * (needs netfilter tuple reservation)
18 */
19
20#include <linux/module.h>
21#include <linux/tcp.h>
22
23#include <net/netfilter/nf_nat.h>
24#include <net/netfilter/nf_nat_helper.h>
25#include <net/netfilter/nf_nat_rule.h>
26#include <net/netfilter/nf_conntrack_helper.h>
27#include <net/netfilter/nf_conntrack_expect.h>
28#include <linux/netfilter/nf_conntrack_proto_gre.h>
29#include <linux/netfilter/nf_conntrack_pptp.h>
30
31#define NF_NAT_PPTP_VERSION "3.0"
32
33#define REQ_CID(req, off) (*(__be16 *)((char *)(req) + (off)))
34
35MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
37MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
38MODULE_ALIAS("ip_nat_pptp");
39
40#if 0
41extern const char *pptp_msg_name[];
42#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
43 __FUNCTION__, ## args)
44#else
45#define DEBUGP(format, args...)
46#endif
47
48static void pptp_nat_expected(struct nf_conn *ct,
49 struct nf_conntrack_expect *exp)
50{
51 struct nf_conn *master = ct->master;
52 struct nf_conntrack_expect *other_exp;
53 struct nf_conntrack_tuple t;
54 struct nf_ct_pptp_master *ct_pptp_info;
55 struct nf_nat_pptp *nat_pptp_info;
56 struct ip_nat_range range;
57
58 ct_pptp_info = &nfct_help(master)->help.ct_pptp_info;
59 nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
60
61 /* And here goes the grand finale of corrosion... */
62 if (exp->dir == IP_CT_DIR_ORIGINAL) {
63 DEBUGP("we are PNS->PAC\n");
64 /* therefore, build tuple for PAC->PNS */
65 t.src.l3num = AF_INET;
66 t.src.u3.ip = master->tuplehash[!exp->dir].tuple.src.u3.ip;
67 t.src.u.gre.key = ct_pptp_info->pac_call_id;
68 t.dst.u3.ip = master->tuplehash[!exp->dir].tuple.dst.u3.ip;
69 t.dst.u.gre.key = ct_pptp_info->pns_call_id;
70 t.dst.protonum = IPPROTO_GRE;
71 } else {
72 DEBUGP("we are PAC->PNS\n");
73 /* build tuple for PNS->PAC */
74 t.src.l3num = AF_INET;
75 t.src.u3.ip = master->tuplehash[exp->dir].tuple.src.u3.ip;
76 t.src.u.gre.key = nat_pptp_info->pns_call_id;
77 t.dst.u3.ip = master->tuplehash[exp->dir].tuple.dst.u3.ip;
78 t.dst.u.gre.key = nat_pptp_info->pac_call_id;
79 t.dst.protonum = IPPROTO_GRE;
80 }
81
82 DEBUGP("trying to unexpect other dir: ");
83 NF_CT_DUMP_TUPLE(&t);
84 other_exp = nf_conntrack_expect_find_get(&t);
85 if (other_exp) {
86 nf_conntrack_unexpect_related(other_exp);
87 nf_conntrack_expect_put(other_exp);
88 DEBUGP("success\n");
89 } else {
90 DEBUGP("not found!\n");
91 }
92
93 /* This must be a fresh one. */
94 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
95
96 /* Change src to where master sends to */
97 range.flags = IP_NAT_RANGE_MAP_IPS;
98 range.min_ip = range.max_ip
99 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
100 if (exp->dir == IP_CT_DIR_ORIGINAL) {
101 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
102 range.min = range.max = exp->saved_proto;
103 }
104 /* hook doesn't matter, but it has to do source manip */
105 nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
106
107 /* For DST manip, map port here to where it's expected. */
108 range.flags = IP_NAT_RANGE_MAP_IPS;
109 range.min_ip = range.max_ip
110 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
111 if (exp->dir == IP_CT_DIR_REPLY) {
112 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
113 range.min = range.max = exp->saved_proto;
114 }
115 /* hook doesn't matter, but it has to do destination manip */
116 nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
117}
118
119/* outbound packets == from PNS to PAC */
120static int
121pptp_outbound_pkt(struct sk_buff **pskb,
122 struct nf_conn *ct,
123 enum ip_conntrack_info ctinfo,
124 struct PptpControlHeader *ctlh,
125 union pptp_ctrl_union *pptpReq)
126
127{
128 struct nf_ct_pptp_master *ct_pptp_info;
129 struct nf_nat_pptp *nat_pptp_info;
130 u_int16_t msg;
131 __be16 new_callid;
132 unsigned int cid_off;
133
134 ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info;
135 nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
136
137 new_callid = ct_pptp_info->pns_call_id;
138
139 switch (msg = ntohs(ctlh->messageType)) {
140 case PPTP_OUT_CALL_REQUEST:
141 cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
142 /* FIXME: ideally we would want to reserve a call ID
143 * here. current netfilter NAT core is not able to do
144 * this :( For now we use TCP source port. This breaks
145 * multiple calls within one control session */
146
147 /* save original call ID in nat_info */
148 nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
149
150 /* don't use tcph->source since we are at a DSTmanip
151 * hook (e.g. PREROUTING) and pkt is not mangled yet */
152 new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
153
154 /* save new call ID in ct info */
155 ct_pptp_info->pns_call_id = new_callid;
156 break;
157 case PPTP_IN_CALL_REPLY:
158 cid_off = offsetof(union pptp_ctrl_union, icack.callID);
159 break;
160 case PPTP_CALL_CLEAR_REQUEST:
161 cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
162 break;
163 default:
164 DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
165 (msg <= PPTP_MSG_MAX)?
166 pptp_msg_name[msg]:pptp_msg_name[0]);
167 /* fall through */
168 case PPTP_SET_LINK_INFO:
169 /* only need to NAT in case PAC is behind NAT box */
170 case PPTP_START_SESSION_REQUEST:
171 case PPTP_START_SESSION_REPLY:
172 case PPTP_STOP_SESSION_REQUEST:
173 case PPTP_STOP_SESSION_REPLY:
174 case PPTP_ECHO_REQUEST:
175 case PPTP_ECHO_REPLY:
176 /* no need to alter packet */
177 return NF_ACCEPT;
178 }
179
180 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
181 * down to here */
182 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
183 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
184
185 /* mangle packet */
186 if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
187 cid_off + sizeof(struct pptp_pkt_hdr) +
188 sizeof(struct PptpControlHeader),
189 sizeof(new_callid), (char *)&new_callid,
190 sizeof(new_callid)) == 0)
191 return NF_DROP;
192 return NF_ACCEPT;
193}
194
195static void
196pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
197 struct nf_conntrack_expect *expect_reply)
198{
199 struct nf_conn *ct = expect_orig->master;
200 struct nf_ct_pptp_master *ct_pptp_info;
201 struct nf_nat_pptp *nat_pptp_info;
202
203 ct_pptp_info = &nfct_help(ct)->help.ct_pptp_info;
204 nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
205
206 /* save original PAC call ID in nat_info */
207 nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
208
209 /* alter expectation for PNS->PAC direction */
210 expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
211 expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
212 expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
213 expect_orig->dir = IP_CT_DIR_ORIGINAL;
214
215 /* alter expectation for PAC->PNS direction */
216 expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
217 expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
218 expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
219 expect_reply->dir = IP_CT_DIR_REPLY;
220}
221
222/* inbound packets == from PAC to PNS */
223static int
224pptp_inbound_pkt(struct sk_buff **pskb,
225 struct nf_conn *ct,
226 enum ip_conntrack_info ctinfo,
227 struct PptpControlHeader *ctlh,
228 union pptp_ctrl_union *pptpReq)
229{
230 struct nf_nat_pptp *nat_pptp_info;
231 u_int16_t msg;
232 __be16 new_pcid;
233 unsigned int pcid_off;
234
235 nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
236 new_pcid = nat_pptp_info->pns_call_id;
237
238 switch (msg = ntohs(ctlh->messageType)) {
239 case PPTP_OUT_CALL_REPLY:
240 pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
241 break;
242 case PPTP_IN_CALL_CONNECT:
243 pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
244 break;
245 case PPTP_IN_CALL_REQUEST:
246 /* only need to nat in case PAC is behind NAT box */
247 return NF_ACCEPT;
248 case PPTP_WAN_ERROR_NOTIFY:
249 pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
250 break;
251 case PPTP_CALL_DISCONNECT_NOTIFY:
252 pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
253 break;
254 case PPTP_SET_LINK_INFO:
255 pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
256 break;
257 default:
258 DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
259 pptp_msg_name[msg]:pptp_msg_name[0]);
260 /* fall through */
261 case PPTP_START_SESSION_REQUEST:
262 case PPTP_START_SESSION_REPLY:
263 case PPTP_STOP_SESSION_REQUEST:
264 case PPTP_STOP_SESSION_REPLY:
265 case PPTP_ECHO_REQUEST:
266 case PPTP_ECHO_REPLY:
267 /* no need to alter packet */
268 return NF_ACCEPT;
269 }
270
271 /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
272 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
273
274 /* mangle packet */
275 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
276 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
277
278 if (nf_nat_mangle_tcp_packet(pskb, ct, ctinfo,
279 pcid_off + sizeof(struct pptp_pkt_hdr) +
280 sizeof(struct PptpControlHeader),
281 sizeof(new_pcid), (char *)&new_pcid,
282 sizeof(new_pcid)) == 0)
283 return NF_DROP;
284 return NF_ACCEPT;
285}
286
287static int __init nf_nat_helper_pptp_init(void)
288{
289 nf_nat_need_gre();
290
291 BUG_ON(rcu_dereference(nf_nat_pptp_hook_outbound));
292 rcu_assign_pointer(nf_nat_pptp_hook_outbound, pptp_outbound_pkt);
293
294 BUG_ON(rcu_dereference(nf_nat_pptp_hook_inbound));
295 rcu_assign_pointer(nf_nat_pptp_hook_inbound, pptp_inbound_pkt);
296
297 BUG_ON(rcu_dereference(nf_nat_pptp_hook_exp_gre));
298 rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, pptp_exp_gre);
299
300 BUG_ON(rcu_dereference(nf_nat_pptp_hook_expectfn));
301 rcu_assign_pointer(nf_nat_pptp_hook_expectfn, pptp_nat_expected);
302 return 0;
303}
304
305static void __exit nf_nat_helper_pptp_fini(void)
306{
307 rcu_assign_pointer(nf_nat_pptp_hook_expectfn, NULL);
308 rcu_assign_pointer(nf_nat_pptp_hook_exp_gre, NULL);
309 rcu_assign_pointer(nf_nat_pptp_hook_inbound, NULL);
310 rcu_assign_pointer(nf_nat_pptp_hook_outbound, NULL);
311 synchronize_rcu();
312}
313
314module_init(nf_nat_helper_pptp_init);
315module_exit(nf_nat_helper_pptp_fini);
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
new file mode 100644
index 000000000000..d3de579e09d2
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -0,0 +1,179 @@
1/*
2 * nf_nat_proto_gre.c
3 *
4 * NAT protocol helper module for GRE.
5 *
6 * GRE is a generic encapsulation protocol, which is generally not very
7 * suited for NAT, as it has no protocol-specific part as port numbers.
8 *
9 * It has an optional key field, which may help us distinguishing two
10 * connections between the same two hosts.
11 *
12 * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
13 *
14 * PPTP is built on top of a modified version of GRE, and has a mandatory
15 * field called "CallID", which serves us for the same purpose as the key
16 * field in plain GRE.
17 *
18 * Documentation about PPTP can be found in RFC 2637
19 *
20 * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
21 *
22 * Development of this code funded by Astaro AG (http://www.astaro.com/)
23 *
24 */
25
26#include <linux/module.h>
27#include <linux/skbuff.h>
28#include <linux/ip.h>
29
30#include <net/netfilter/nf_nat.h>
31#include <net/netfilter/nf_nat_rule.h>
32#include <net/netfilter/nf_nat_protocol.h>
33#include <linux/netfilter/nf_conntrack_proto_gre.h>
34
35MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
37MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
38
39#if 0
40#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
41 __FUNCTION__, ## args)
42#else
43#define DEBUGP(x, args...)
44#endif
45
46/* is key in given range between min and max */
47static int
48gre_in_range(const struct nf_conntrack_tuple *tuple,
49 enum nf_nat_manip_type maniptype,
50 const union nf_conntrack_man_proto *min,
51 const union nf_conntrack_man_proto *max)
52{
53 __be16 key;
54
55 if (maniptype == IP_NAT_MANIP_SRC)
56 key = tuple->src.u.gre.key;
57 else
58 key = tuple->dst.u.gre.key;
59
60 return ntohs(key) >= ntohs(min->gre.key) &&
61 ntohs(key) <= ntohs(max->gre.key);
62}
63
64/* generate unique tuple ... */
65static int
66gre_unique_tuple(struct nf_conntrack_tuple *tuple,
67 const struct nf_nat_range *range,
68 enum nf_nat_manip_type maniptype,
69 const struct nf_conn *conntrack)
70{
71 static u_int16_t key;
72 __be16 *keyptr;
73 unsigned int min, i, range_size;
74
75 if (maniptype == IP_NAT_MANIP_SRC)
76 keyptr = &tuple->src.u.gre.key;
77 else
78 keyptr = &tuple->dst.u.gre.key;
79
80 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
81 DEBUGP("%p: NATing GRE PPTP\n", conntrack);
82 min = 1;
83 range_size = 0xffff;
84 } else {
85 min = ntohs(range->min.gre.key);
86 range_size = ntohs(range->max.gre.key) - min + 1;
87 }
88
89 DEBUGP("min = %u, range_size = %u\n", min, range_size);
90
91 for (i = 0; i < range_size; i++, key++) {
92 *keyptr = htons(min + key % range_size);
93 if (!nf_nat_used_tuple(tuple, conntrack))
94 return 1;
95 }
96
97 DEBUGP("%p: no NAT mapping\n", conntrack);
98 return 0;
99}
100
101/* manipulate a GRE packet according to maniptype */
102static int
103gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
104 const struct nf_conntrack_tuple *tuple,
105 enum nf_nat_manip_type maniptype)
106{
107 struct gre_hdr *greh;
108 struct gre_hdr_pptp *pgreh;
109 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
110 unsigned int hdroff = iphdroff + iph->ihl * 4;
111
112 /* pgreh includes two optional 32bit fields which are not required
113 * to be there. That's where the magic '8' comes from */
114 if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8))
115 return 0;
116
117 greh = (void *)(*pskb)->data + hdroff;
118 pgreh = (struct gre_hdr_pptp *)greh;
119
120 /* we only have destination manip of a packet, since 'source key'
121 * is not present in the packet itself */
122 if (maniptype != IP_NAT_MANIP_DST)
123 return 1;
124 switch (greh->version) {
125 case 0:
126 if (!greh->key) {
127 DEBUGP("can't nat GRE w/o key\n");
128 break;
129 }
130 if (greh->csum) {
131 /* FIXME: Never tested this code... */
132 nf_proto_csum_replace4(gre_csum(greh), *pskb,
133 *(gre_key(greh)),
134 tuple->dst.u.gre.key, 0);
135 }
136 *(gre_key(greh)) = tuple->dst.u.gre.key;
137 break;
138 case GRE_VERSION_PPTP:
139 DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
140 pgreh->call_id = tuple->dst.u.gre.key;
141 break;
142 default:
143 DEBUGP("can't nat unknown GRE version\n");
144 return 0;
145 }
146 return 1;
147}
148
149static struct nf_nat_protocol gre __read_mostly = {
150 .name = "GRE",
151 .protonum = IPPROTO_GRE,
152 .manip_pkt = gre_manip_pkt,
153 .in_range = gre_in_range,
154 .unique_tuple = gre_unique_tuple,
155#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
156 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
157 .range_to_nfattr = nf_nat_port_range_to_nfattr,
158 .nfattr_to_range = nf_nat_port_nfattr_to_range,
159#endif
160};
161
162int __init nf_nat_proto_gre_init(void)
163{
164 return nf_nat_protocol_register(&gre);
165}
166
167void __exit nf_nat_proto_gre_fini(void)
168{
169 nf_nat_protocol_unregister(&gre);
170}
171
172module_init(nf_nat_proto_gre_init);
173module_exit(nf_nat_proto_gre_fini);
174
175void nf_nat_need_gre(void)
176{
177 return;
178}
179EXPORT_SYMBOL_GPL(nf_nat_need_gre);
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
new file mode 100644
index 000000000000..dcfd772972d7
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -0,0 +1,86 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/ip.h>
12#include <linux/icmp.h>
13
14#include <linux/netfilter.h>
15#include <net/netfilter/nf_nat.h>
16#include <net/netfilter/nf_nat_core.h>
17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_nat_protocol.h>
19
20static int
21icmp_in_range(const struct nf_conntrack_tuple *tuple,
22 enum nf_nat_manip_type maniptype,
23 const union nf_conntrack_man_proto *min,
24 const union nf_conntrack_man_proto *max)
25{
26 return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
27 ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
28}
29
30static int
31icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
32 const struct nf_nat_range *range,
33 enum nf_nat_manip_type maniptype,
34 const struct nf_conn *ct)
35{
36 static u_int16_t id;
37 unsigned int range_size;
38 unsigned int i;
39
40 range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
41 /* If no range specified... */
42 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED))
43 range_size = 0xFFFF;
44
45 for (i = 0; i < range_size; i++, id++) {
46 tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
47 (id % range_size));
48 if (!nf_nat_used_tuple(tuple, ct))
49 return 1;
50 }
51 return 0;
52}
53
54static int
55icmp_manip_pkt(struct sk_buff **pskb,
56 unsigned int iphdroff,
57 const struct nf_conntrack_tuple *tuple,
58 enum nf_nat_manip_type maniptype)
59{
60 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
61 struct icmphdr *hdr;
62 unsigned int hdroff = iphdroff + iph->ihl*4;
63
64 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
65 return 0;
66
67 hdr = (struct icmphdr *)((*pskb)->data + hdroff);
68 nf_proto_csum_replace2(&hdr->checksum, *pskb,
69 hdr->un.echo.id, tuple->src.u.icmp.id, 0);
70 hdr->un.echo.id = tuple->src.u.icmp.id;
71 return 1;
72}
73
74struct nf_nat_protocol nf_nat_protocol_icmp = {
75 .name = "ICMP",
76 .protonum = IPPROTO_ICMP,
77 .me = THIS_MODULE,
78 .manip_pkt = icmp_manip_pkt,
79 .in_range = icmp_in_range,
80 .unique_tuple = icmp_unique_tuple,
81#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
82 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
83 .range_to_nfattr = nf_nat_port_range_to_nfattr,
84 .nfattr_to_range = nf_nat_port_nfattr_to_range,
85#endif
86};
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
new file mode 100644
index 000000000000..7e26a7e9bee1
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -0,0 +1,148 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/ip.h>
12#include <linux/tcp.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter/nfnetlink_conntrack.h>
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_nat_protocol.h>
19#include <net/netfilter/nf_nat_core.h>
20
21static int
22tcp_in_range(const struct nf_conntrack_tuple *tuple,
23 enum nf_nat_manip_type maniptype,
24 const union nf_conntrack_man_proto *min,
25 const union nf_conntrack_man_proto *max)
26{
27 __be16 port;
28
29 if (maniptype == IP_NAT_MANIP_SRC)
30 port = tuple->src.u.tcp.port;
31 else
32 port = tuple->dst.u.tcp.port;
33
34 return ntohs(port) >= ntohs(min->tcp.port) &&
35 ntohs(port) <= ntohs(max->tcp.port);
36}
37
38static int
39tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
40 const struct nf_nat_range *range,
41 enum nf_nat_manip_type maniptype,
42 const struct nf_conn *ct)
43{
44 static u_int16_t port;
45 __be16 *portptr;
46 unsigned int range_size, min, i;
47
48 if (maniptype == IP_NAT_MANIP_SRC)
49 portptr = &tuple->src.u.tcp.port;
50 else
51 portptr = &tuple->dst.u.tcp.port;
52
53 /* If no range specified... */
54 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
55 /* If it's dst rewrite, can't change port */
56 if (maniptype == IP_NAT_MANIP_DST)
57 return 0;
58
59 /* Map privileged onto privileged. */
60 if (ntohs(*portptr) < 1024) {
61 /* Loose convention: >> 512 is credential passing */
62 if (ntohs(*portptr)<512) {
63 min = 1;
64 range_size = 511 - min + 1;
65 } else {
66 min = 600;
67 range_size = 1023 - min + 1;
68 }
69 } else {
70 min = 1024;
71 range_size = 65535 - 1024 + 1;
72 }
73 } else {
74 min = ntohs(range->min.tcp.port);
75 range_size = ntohs(range->max.tcp.port) - min + 1;
76 }
77
78 for (i = 0; i < range_size; i++, port++) {
79 *portptr = htons(min + port % range_size);
80 if (!nf_nat_used_tuple(tuple, ct))
81 return 1;
82 }
83 return 0;
84}
85
86static int
87tcp_manip_pkt(struct sk_buff **pskb,
88 unsigned int iphdroff,
89 const struct nf_conntrack_tuple *tuple,
90 enum nf_nat_manip_type maniptype)
91{
92 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
93 struct tcphdr *hdr;
94 unsigned int hdroff = iphdroff + iph->ihl*4;
95 __be32 oldip, newip;
96 __be16 *portptr, newport, oldport;
97 int hdrsize = 8; /* TCP connection tracking guarantees this much */
98
99 /* this could be a inner header returned in icmp packet; in such
100 cases we cannot update the checksum field since it is outside of
101 the 8 bytes of transport layer headers we are guaranteed */
102 if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
103 hdrsize = sizeof(struct tcphdr);
104
105 if (!skb_make_writable(pskb, hdroff + hdrsize))
106 return 0;
107
108 iph = (struct iphdr *)((*pskb)->data + iphdroff);
109 hdr = (struct tcphdr *)((*pskb)->data + hdroff);
110
111 if (maniptype == IP_NAT_MANIP_SRC) {
112 /* Get rid of src ip and src pt */
113 oldip = iph->saddr;
114 newip = tuple->src.u3.ip;
115 newport = tuple->src.u.tcp.port;
116 portptr = &hdr->source;
117 } else {
118 /* Get rid of dst ip and dst pt */
119 oldip = iph->daddr;
120 newip = tuple->dst.u3.ip;
121 newport = tuple->dst.u.tcp.port;
122 portptr = &hdr->dest;
123 }
124
125 oldport = *portptr;
126 *portptr = newport;
127
128 if (hdrsize < sizeof(*hdr))
129 return 1;
130
131 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
132 nf_proto_csum_replace2(&hdr->check, *pskb, oldport, newport, 0);
133 return 1;
134}
135
136struct nf_nat_protocol nf_nat_protocol_tcp = {
137 .name = "TCP",
138 .protonum = IPPROTO_TCP,
139 .me = THIS_MODULE,
140 .manip_pkt = tcp_manip_pkt,
141 .in_range = tcp_in_range,
142 .unique_tuple = tcp_unique_tuple,
143#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
144 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
145 .range_to_nfattr = nf_nat_port_range_to_nfattr,
146 .nfattr_to_range = nf_nat_port_nfattr_to_range,
147#endif
148};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
new file mode 100644
index 000000000000..ab0ce4c8699f
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -0,0 +1,138 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/types.h>
10#include <linux/init.h>
11#include <linux/ip.h>
12#include <linux/udp.h>
13
14#include <linux/netfilter.h>
15#include <net/netfilter/nf_nat.h>
16#include <net/netfilter/nf_nat_core.h>
17#include <net/netfilter/nf_nat_rule.h>
18#include <net/netfilter/nf_nat_protocol.h>
19
20static int
21udp_in_range(const struct nf_conntrack_tuple *tuple,
22 enum nf_nat_manip_type maniptype,
23 const union nf_conntrack_man_proto *min,
24 const union nf_conntrack_man_proto *max)
25{
26 __be16 port;
27
28 if (maniptype == IP_NAT_MANIP_SRC)
29 port = tuple->src.u.udp.port;
30 else
31 port = tuple->dst.u.udp.port;
32
33 return ntohs(port) >= ntohs(min->udp.port) &&
34 ntohs(port) <= ntohs(max->udp.port);
35}
36
37static int
38udp_unique_tuple(struct nf_conntrack_tuple *tuple,
39 const struct nf_nat_range *range,
40 enum nf_nat_manip_type maniptype,
41 const struct nf_conn *ct)
42{
43 static u_int16_t port;
44 __be16 *portptr;
45 unsigned int range_size, min, i;
46
47 if (maniptype == IP_NAT_MANIP_SRC)
48 portptr = &tuple->src.u.udp.port;
49 else
50 portptr = &tuple->dst.u.udp.port;
51
52 /* If no range specified... */
53 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
54 /* If it's dst rewrite, can't change port */
55 if (maniptype == IP_NAT_MANIP_DST)
56 return 0;
57
58 if (ntohs(*portptr) < 1024) {
59 /* Loose convention: >> 512 is credential passing */
60 if (ntohs(*portptr)<512) {
61 min = 1;
62 range_size = 511 - min + 1;
63 } else {
64 min = 600;
65 range_size = 1023 - min + 1;
66 }
67 } else {
68 min = 1024;
69 range_size = 65535 - 1024 + 1;
70 }
71 } else {
72 min = ntohs(range->min.udp.port);
73 range_size = ntohs(range->max.udp.port) - min + 1;
74 }
75
76 for (i = 0; i < range_size; i++, port++) {
77 *portptr = htons(min + port % range_size);
78 if (!nf_nat_used_tuple(tuple, ct))
79 return 1;
80 }
81 return 0;
82}
83
84static int
85udp_manip_pkt(struct sk_buff **pskb,
86 unsigned int iphdroff,
87 const struct nf_conntrack_tuple *tuple,
88 enum nf_nat_manip_type maniptype)
89{
90 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
91 struct udphdr *hdr;
92 unsigned int hdroff = iphdroff + iph->ihl*4;
93 __be32 oldip, newip;
94 __be16 *portptr, newport;
95
96 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
97 return 0;
98
99 iph = (struct iphdr *)((*pskb)->data + iphdroff);
100 hdr = (struct udphdr *)((*pskb)->data + hdroff);
101
102 if (maniptype == IP_NAT_MANIP_SRC) {
103 /* Get rid of src ip and src pt */
104 oldip = iph->saddr;
105 newip = tuple->src.u3.ip;
106 newport = tuple->src.u.udp.port;
107 portptr = &hdr->source;
108 } else {
109 /* Get rid of dst ip and dst pt */
110 oldip = iph->daddr;
111 newip = tuple->dst.u3.ip;
112 newport = tuple->dst.u.udp.port;
113 portptr = &hdr->dest;
114 }
115 if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) {
116 nf_proto_csum_replace4(&hdr->check, *pskb, oldip, newip, 1);
117 nf_proto_csum_replace2(&hdr->check, *pskb, *portptr, newport,
118 0);
119 if (!hdr->check)
120 hdr->check = CSUM_MANGLED_0;
121 }
122 *portptr = newport;
123 return 1;
124}
125
126struct nf_nat_protocol nf_nat_protocol_udp = {
127 .name = "UDP",
128 .protonum = IPPROTO_UDP,
129 .me = THIS_MODULE,
130 .manip_pkt = udp_manip_pkt,
131 .in_range = udp_in_range,
132 .unique_tuple = udp_unique_tuple,
133#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
134 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
135 .range_to_nfattr = nf_nat_port_range_to_nfattr,
136 .nfattr_to_range = nf_nat_port_nfattr_to_range,
137#endif
138};
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
new file mode 100644
index 000000000000..f50d0203f9c0
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
@@ -0,0 +1,54 @@
1/* The "unknown" protocol. This is what is used for protocols we
2 * don't understand. It's returned by ip_ct_find_proto().
3 */
4
5/* (C) 1999-2001 Paul `Rusty' Russell
6 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/types.h>
14#include <linux/init.h>
15
16#include <linux/netfilter.h>
17#include <net/netfilter/nf_nat.h>
18#include <net/netfilter/nf_nat_rule.h>
19#include <net/netfilter/nf_nat_protocol.h>
20
21static int unknown_in_range(const struct nf_conntrack_tuple *tuple,
22 enum nf_nat_manip_type manip_type,
23 const union nf_conntrack_man_proto *min,
24 const union nf_conntrack_man_proto *max)
25{
26 return 1;
27}
28
29static int unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
30 const struct nf_nat_range *range,
31 enum nf_nat_manip_type maniptype,
32 const struct nf_conn *ct)
33{
34 /* Sorry: we can't help you; if it's not unique, we can't frob
35 anything. */
36 return 0;
37}
38
39static int
40unknown_manip_pkt(struct sk_buff **pskb,
41 unsigned int iphdroff,
42 const struct nf_conntrack_tuple *tuple,
43 enum nf_nat_manip_type maniptype)
44{
45 return 1;
46}
47
48struct nf_nat_protocol nf_nat_unknown_protocol = {
49 .name = "unknown",
50 /* .me isn't set: getting a ref to this cannot fail. */
51 .manip_pkt = unknown_manip_pkt,
52 .in_range = unknown_in_range,
53 .unique_tuple = unknown_unique_tuple,
54};
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
new file mode 100644
index 000000000000..b868ee0195d4
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -0,0 +1,343 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9/* Everything about the rules for NAT. */
10#include <linux/types.h>
11#include <linux/ip.h>
12#include <linux/netfilter.h>
13#include <linux/netfilter_ipv4.h>
14#include <linux/module.h>
15#include <linux/kmod.h>
16#include <linux/skbuff.h>
17#include <linux/proc_fs.h>
18#include <net/checksum.h>
19#include <net/route.h>
20#include <linux/bitops.h>
21
22#include <linux/netfilter_ipv4/ip_tables.h>
23#include <net/netfilter/nf_nat.h>
24#include <net/netfilter/nf_nat_core.h>
25#include <net/netfilter/nf_nat_rule.h>
26
27#if 0
28#define DEBUGP printk
29#else
30#define DEBUGP(format, args...)
31#endif
32
33#define NAT_VALID_HOOKS ((1<<NF_IP_PRE_ROUTING) | (1<<NF_IP_POST_ROUTING) | (1<<NF_IP_LOCAL_OUT))
34
35static struct
36{
37 struct ipt_replace repl;
38 struct ipt_standard entries[3];
39 struct ipt_error term;
40} nat_initial_table __initdata = {
41 .repl = {
42 .name = "nat",
43 .valid_hooks = NAT_VALID_HOOKS,
44 .num_entries = 4,
45 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
46 .hook_entry = {
47 [NF_IP_PRE_ROUTING] = 0,
48 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
49 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
50 .underflow = {
51 [NF_IP_PRE_ROUTING] = 0,
52 [NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
53 [NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
54 },
55 .entries = {
56 /* PRE_ROUTING */
57 {
58 .entry = {
59 .target_offset = sizeof(struct ipt_entry),
60 .next_offset = sizeof(struct ipt_standard),
61 },
62 .target = {
63 .target = {
64 .u = {
65 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
66 },
67 },
68 .verdict = -NF_ACCEPT - 1,
69 },
70 },
71 /* POST_ROUTING */
72 {
73 .entry = {
74 .target_offset = sizeof(struct ipt_entry),
75 .next_offset = sizeof(struct ipt_standard),
76 },
77 .target = {
78 .target = {
79 .u = {
80 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
81 },
82 },
83 .verdict = -NF_ACCEPT - 1,
84 },
85 },
86 /* LOCAL_OUT */
87 {
88 .entry = {
89 .target_offset = sizeof(struct ipt_entry),
90 .next_offset = sizeof(struct ipt_standard),
91 },
92 .target = {
93 .target = {
94 .u = {
95 .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
96 },
97 },
98 .verdict = -NF_ACCEPT - 1,
99 },
100 },
101 },
102 /* ERROR */
103 .term = {
104 .entry = {
105 .target_offset = sizeof(struct ipt_entry),
106 .next_offset = sizeof(struct ipt_error),
107 },
108 .target = {
109 .target = {
110 .u = {
111 .user = {
112 .target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
113 .name = IPT_ERROR_TARGET,
114 },
115 },
116 },
117 .errorname = "ERROR",
118 },
119 }
120};
121
122static struct ipt_table nat_table = {
123 .name = "nat",
124 .valid_hooks = NAT_VALID_HOOKS,
125 .lock = RW_LOCK_UNLOCKED,
126 .me = THIS_MODULE,
127 .af = AF_INET,
128};
129
130/* Source NAT */
131static unsigned int ipt_snat_target(struct sk_buff **pskb,
132 const struct net_device *in,
133 const struct net_device *out,
134 unsigned int hooknum,
135 const struct xt_target *target,
136 const void *targinfo)
137{
138 struct nf_conn *ct;
139 enum ip_conntrack_info ctinfo;
140 const struct nf_nat_multi_range_compat *mr = targinfo;
141
142 NF_CT_ASSERT(hooknum == NF_IP_POST_ROUTING);
143
144 ct = nf_ct_get(*pskb, &ctinfo);
145
146 /* Connection must be valid and new. */
147 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
148 ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
149 NF_CT_ASSERT(out);
150
151 return nf_nat_setup_info(ct, &mr->range[0], hooknum);
152}
153
154/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */
155static void warn_if_extra_mangle(__be32 dstip, __be32 srcip)
156{
157 static int warned = 0;
158 struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } };
159 struct rtable *rt;
160
161 if (ip_route_output_key(&rt, &fl) != 0)
162 return;
163
164 if (rt->rt_src != srcip && !warned) {
165 printk("NAT: no longer support implicit source local NAT\n");
166 printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n",
167 NIPQUAD(srcip), NIPQUAD(dstip));
168 warned = 1;
169 }
170 ip_rt_put(rt);
171}
172
173static unsigned int ipt_dnat_target(struct sk_buff **pskb,
174 const struct net_device *in,
175 const struct net_device *out,
176 unsigned int hooknum,
177 const struct xt_target *target,
178 const void *targinfo)
179{
180 struct nf_conn *ct;
181 enum ip_conntrack_info ctinfo;
182 const struct nf_nat_multi_range_compat *mr = targinfo;
183
184 NF_CT_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
185 hooknum == NF_IP_LOCAL_OUT);
186
187 ct = nf_ct_get(*pskb, &ctinfo);
188
189 /* Connection must be valid and new. */
190 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
191
192 if (hooknum == NF_IP_LOCAL_OUT &&
193 mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)
194 warn_if_extra_mangle((*pskb)->nh.iph->daddr,
195 mr->range[0].min_ip);
196
197 return nf_nat_setup_info(ct, &mr->range[0], hooknum);
198}
199
200static int ipt_snat_checkentry(const char *tablename,
201 const void *entry,
202 const struct xt_target *target,
203 void *targinfo,
204 unsigned int hook_mask)
205{
206 struct nf_nat_multi_range_compat *mr = targinfo;
207
208 /* Must be a valid range */
209 if (mr->rangesize != 1) {
210 printk("SNAT: multiple ranges no longer supported\n");
211 return 0;
212 }
213 return 1;
214}
215
216static int ipt_dnat_checkentry(const char *tablename,
217 const void *entry,
218 const struct xt_target *target,
219 void *targinfo,
220 unsigned int hook_mask)
221{
222 struct nf_nat_multi_range_compat *mr = targinfo;
223
224 /* Must be a valid range */
225 if (mr->rangesize != 1) {
226 printk("DNAT: multiple ranges no longer supported\n");
227 return 0;
228 }
229 return 1;
230}
231
232inline unsigned int
233alloc_null_binding(struct nf_conn *ct,
234 struct nf_nat_info *info,
235 unsigned int hooknum)
236{
237 /* Force range to this IP; let proto decide mapping for
238 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
239 Use reply in case it's already been mangled (eg local packet).
240 */
241 __be32 ip
242 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
243 ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
244 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
245 struct nf_nat_range range
246 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } };
247
248 DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n",
249 ct, NIPQUAD(ip));
250 return nf_nat_setup_info(ct, &range, hooknum);
251}
252
253unsigned int
254alloc_null_binding_confirmed(struct nf_conn *ct,
255 struct nf_nat_info *info,
256 unsigned int hooknum)
257{
258 __be32 ip
259 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
260 ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip
261 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
262 u_int16_t all
263 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
264 ? ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all
265 : ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.all);
266 struct nf_nat_range range
267 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { all }, { all } };
268
269 DEBUGP("Allocating NULL binding for confirmed %p (%u.%u.%u.%u)\n",
270 ct, NIPQUAD(ip));
271 return nf_nat_setup_info(ct, &range, hooknum);
272}
273
274int nf_nat_rule_find(struct sk_buff **pskb,
275 unsigned int hooknum,
276 const struct net_device *in,
277 const struct net_device *out,
278 struct nf_conn *ct,
279 struct nf_nat_info *info)
280{
281 int ret;
282
283 ret = ipt_do_table(pskb, hooknum, in, out, &nat_table);
284
285 if (ret == NF_ACCEPT) {
286 if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
287 /* NUL mapping */
288 ret = alloc_null_binding(ct, info, hooknum);
289 }
290 return ret;
291}
292
293static struct ipt_target ipt_snat_reg = {
294 .name = "SNAT",
295 .target = ipt_snat_target,
296 .targetsize = sizeof(struct nf_nat_multi_range_compat),
297 .table = "nat",
298 .hooks = 1 << NF_IP_POST_ROUTING,
299 .checkentry = ipt_snat_checkentry,
300 .family = AF_INET,
301};
302
303static struct xt_target ipt_dnat_reg = {
304 .name = "DNAT",
305 .target = ipt_dnat_target,
306 .targetsize = sizeof(struct nf_nat_multi_range_compat),
307 .table = "nat",
308 .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT),
309 .checkentry = ipt_dnat_checkentry,
310 .family = AF_INET,
311};
312
313int __init nf_nat_rule_init(void)
314{
315 int ret;
316
317 ret = ipt_register_table(&nat_table, &nat_initial_table.repl);
318 if (ret != 0)
319 return ret;
320 ret = xt_register_target(&ipt_snat_reg);
321 if (ret != 0)
322 goto unregister_table;
323
324 ret = xt_register_target(&ipt_dnat_reg);
325 if (ret != 0)
326 goto unregister_snat;
327
328 return ret;
329
330 unregister_snat:
331 xt_unregister_target(&ipt_snat_reg);
332 unregister_table:
333 ipt_unregister_table(&nat_table);
334
335 return ret;
336}
337
338void nf_nat_rule_cleanup(void)
339{
340 xt_unregister_target(&ipt_dnat_reg);
341 xt_unregister_target(&ipt_snat_reg);
342 ipt_unregister_table(&nat_table);
343}
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
new file mode 100644
index 000000000000..3d524b957310
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -0,0 +1,283 @@
1/* SIP extension for UDP NAT alteration.
2 *
3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
4 * based on RR's ip_nat_ftp.c and other modules.
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#include <linux/ip.h>
14#include <linux/udp.h>
15
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nf_nat_helper.h>
18#include <net/netfilter/nf_nat_rule.h>
19#include <net/netfilter/nf_conntrack_helper.h>
20#include <net/netfilter/nf_conntrack_expect.h>
21#include <linux/netfilter/nf_conntrack_sip.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
25MODULE_DESCRIPTION("SIP NAT helper");
26MODULE_ALIAS("ip_nat_sip");
27
28#if 0
29#define DEBUGP printk
30#else
31#define DEBUGP(format, args...)
32#endif
33
34struct addr_map {
35 struct {
36 char src[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
37 char dst[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
38 unsigned int srclen, srciplen;
39 unsigned int dstlen, dstiplen;
40 } addr[IP_CT_DIR_MAX];
41};
42
43static void addr_map_init(struct nf_conn *ct, struct addr_map *map)
44{
45 struct nf_conntrack_tuple *t;
46 enum ip_conntrack_dir dir;
47 unsigned int n;
48
49 for (dir = 0; dir < IP_CT_DIR_MAX; dir++) {
50 t = &ct->tuplehash[dir].tuple;
51
52 n = sprintf(map->addr[dir].src, "%u.%u.%u.%u",
53 NIPQUAD(t->src.u3.ip));
54 map->addr[dir].srciplen = n;
55 n += sprintf(map->addr[dir].src + n, ":%u",
56 ntohs(t->src.u.udp.port));
57 map->addr[dir].srclen = n;
58
59 n = sprintf(map->addr[dir].dst, "%u.%u.%u.%u",
60 NIPQUAD(t->dst.u3.ip));
61 map->addr[dir].dstiplen = n;
62 n += sprintf(map->addr[dir].dst + n, ":%u",
63 ntohs(t->dst.u.udp.port));
64 map->addr[dir].dstlen = n;
65 }
66}
67
68static int map_sip_addr(struct sk_buff **pskb, enum ip_conntrack_info ctinfo,
69 struct nf_conn *ct, const char **dptr, size_t dlen,
70 enum sip_header_pos pos, struct addr_map *map)
71{
72 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
73 unsigned int matchlen, matchoff, addrlen;
74 char *addr;
75
76 if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
77 return 1;
78
79 if ((matchlen == map->addr[dir].srciplen ||
80 matchlen == map->addr[dir].srclen) &&
81 memcmp(*dptr + matchoff, map->addr[dir].src, matchlen) == 0) {
82 addr = map->addr[!dir].dst;
83 addrlen = map->addr[!dir].dstlen;
84 } else if ((matchlen == map->addr[dir].dstiplen ||
85 matchlen == map->addr[dir].dstlen) &&
86 memcmp(*dptr + matchoff, map->addr[dir].dst, matchlen) == 0) {
87 addr = map->addr[!dir].src;
88 addrlen = map->addr[!dir].srclen;
89 } else
90 return 1;
91
92 if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
93 matchoff, matchlen, addr, addrlen))
94 return 0;
95 *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
96 return 1;
97
98}
99
100static unsigned int ip_nat_sip(struct sk_buff **pskb,
101 enum ip_conntrack_info ctinfo,
102 struct nf_conn *ct,
103 const char **dptr)
104{
105 enum sip_header_pos pos;
106 struct addr_map map;
107 int dataoff, datalen;
108
109 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
110 datalen = (*pskb)->len - dataoff;
111 if (datalen < sizeof("SIP/2.0") - 1)
112 return NF_DROP;
113
114 addr_map_init(ct, &map);
115
116 /* Basic rules: requests and responses. */
117 if (strncmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) != 0) {
118 /* 10.2: Constructing the REGISTER Request:
119 *
120 * The "userinfo" and "@" components of the SIP URI MUST NOT
121 * be present.
122 */
123 if (datalen >= sizeof("REGISTER") - 1 &&
124 strncmp(*dptr, "REGISTER", sizeof("REGISTER") - 1) == 0)
125 pos = POS_REG_REQ_URI;
126 else
127 pos = POS_REQ_URI;
128
129 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, pos, &map))
130 return NF_DROP;
131 }
132
133 if (!map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_FROM, &map) ||
134 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_TO, &map) ||
135 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_VIA, &map) ||
136 !map_sip_addr(pskb, ctinfo, ct, dptr, datalen, POS_CONTACT, &map))
137 return NF_DROP;
138 return NF_ACCEPT;
139}
140
141static unsigned int mangle_sip_packet(struct sk_buff **pskb,
142 enum ip_conntrack_info ctinfo,
143 struct nf_conn *ct,
144 const char **dptr, size_t dlen,
145 char *buffer, int bufflen,
146 enum sip_header_pos pos)
147{
148 unsigned int matchlen, matchoff;
149
150 if (ct_sip_get_info(ct, *dptr, dlen, &matchoff, &matchlen, pos) <= 0)
151 return 0;
152
153 if (!nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
154 matchoff, matchlen, buffer, bufflen))
155 return 0;
156
157 /* We need to reload this. Thanks Patrick. */
158 *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
159 return 1;
160}
161
162static int mangle_content_len(struct sk_buff **pskb,
163 enum ip_conntrack_info ctinfo,
164 struct nf_conn *ct,
165 const char *dptr)
166{
167 unsigned int dataoff, matchoff, matchlen;
168 char buffer[sizeof("65536")];
169 int bufflen;
170
171 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
172
173 /* Get actual SDP lenght */
174 if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
175 &matchlen, POS_SDP_HEADER) > 0) {
176
177 /* since ct_sip_get_info() give us a pointer passing 'v='
178 we need to add 2 bytes in this count. */
179 int c_len = (*pskb)->len - dataoff - matchoff + 2;
180
181 /* Now, update SDP length */
182 if (ct_sip_get_info(ct, dptr, (*pskb)->len - dataoff, &matchoff,
183 &matchlen, POS_CONTENT) > 0) {
184
185 bufflen = sprintf(buffer, "%u", c_len);
186 return nf_nat_mangle_udp_packet(pskb, ct, ctinfo,
187 matchoff, matchlen,
188 buffer, bufflen);
189 }
190 }
191 return 0;
192}
193
194static unsigned int mangle_sdp(struct sk_buff **pskb,
195 enum ip_conntrack_info ctinfo,
196 struct nf_conn *ct,
197 __be32 newip, u_int16_t port,
198 const char *dptr)
199{
200 char buffer[sizeof("nnn.nnn.nnn.nnn")];
201 unsigned int dataoff, bufflen;
202
203 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
204
205 /* Mangle owner and contact info. */
206 bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
207 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
208 buffer, bufflen, POS_OWNER_IP4))
209 return 0;
210
211 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
212 buffer, bufflen, POS_CONNECTION_IP4))
213 return 0;
214
215 /* Mangle media port. */
216 bufflen = sprintf(buffer, "%u", port);
217 if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
218 buffer, bufflen, POS_MEDIA))
219 return 0;
220
221 return mangle_content_len(pskb, ctinfo, ct, dptr);
222}
223
224/* So, this packet has hit the connection tracking matching code.
225 Mangle it, and change the expectation to match the new version. */
226static unsigned int ip_nat_sdp(struct sk_buff **pskb,
227 enum ip_conntrack_info ctinfo,
228 struct nf_conntrack_expect *exp,
229 const char *dptr)
230{
231 struct nf_conn *ct = exp->master;
232 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
233 __be32 newip;
234 u_int16_t port;
235
236 DEBUGP("ip_nat_sdp():\n");
237
238 /* Connection will come from reply */
239 newip = ct->tuplehash[!dir].tuple.dst.u3.ip;
240
241 exp->tuple.dst.u3.ip = newip;
242 exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
243 exp->dir = !dir;
244
245 /* When you see the packet, we need to NAT it the same as the
246 this one. */
247 exp->expectfn = nf_nat_follow_master;
248
249 /* Try to get same port: if not, try to change it. */
250 for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
251 exp->tuple.dst.u.udp.port = htons(port);
252 if (nf_conntrack_expect_related(exp) == 0)
253 break;
254 }
255
256 if (port == 0)
257 return NF_DROP;
258
259 if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
260 nf_conntrack_unexpect_related(exp);
261 return NF_DROP;
262 }
263 return NF_ACCEPT;
264}
265
266static void __exit nf_nat_sip_fini(void)
267{
268 rcu_assign_pointer(nf_nat_sip_hook, NULL);
269 rcu_assign_pointer(nf_nat_sdp_hook, NULL);
270 synchronize_rcu();
271}
272
273static int __init nf_nat_sip_init(void)
274{
275 BUG_ON(rcu_dereference(nf_nat_sip_hook));
276 BUG_ON(rcu_dereference(nf_nat_sdp_hook));
277 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
278 rcu_assign_pointer(nf_nat_sdp_hook, ip_nat_sdp);
279 return 0;
280}
281
282module_init(nf_nat_sip_init);
283module_exit(nf_nat_sip_fini);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
new file mode 100644
index 000000000000..f12528fe1bf9
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -0,0 +1,1332 @@
1/*
2 * nf_nat_snmp_basic.c
3 *
4 * Basic SNMP Application Layer Gateway
5 *
6 * This IP NAT module is intended for use with SNMP network
7 * discovery and monitoring applications where target networks use
8 * conflicting private address realms.
9 *
10 * Static NAT is used to remap the networks from the view of the network
11 * management system at the IP layer, and this module remaps some application
12 * layer addresses to match.
13 *
14 * The simplest form of ALG is performed, where only tagged IP addresses
15 * are modified. The module does not need to be MIB aware and only scans
16 * messages at the ASN.1/BER level.
17 *
18 * Currently, only SNMPv1 and SNMPv2 are supported.
19 *
20 * More information on ALG and associated issues can be found in
21 * RFC 2962
22 *
23 * The ASB.1/BER parsing code is derived from the gxsnmp package by Gregory
24 * McLean & Jochen Friedrich, stripped down for use in the kernel.
25 *
26 * Copyright (c) 2000 RP Internet (www.rpi.net.au).
27 *
28 * This program is free software; you can redistribute it and/or modify
29 * it under the terms of the GNU General Public License as published by
30 * the Free Software Foundation; either version 2 of the License, or
31 * (at your option) any later version.
32 * This program is distributed in the hope that it will be useful,
33 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, write to the Free Software
38 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 *
40 * Author: James Morris <jmorris@intercode.com.au>
41 *
42 * Updates:
43 * 2000-08-06: Convert to new helper API (Harald Welte).
44 *
45 */
46#include <linux/module.h>
47#include <linux/moduleparam.h>
48#include <linux/types.h>
49#include <linux/kernel.h>
50#include <linux/in.h>
51#include <linux/ip.h>
52#include <linux/udp.h>
53#include <net/checksum.h>
54#include <net/udp.h>
55
56#include <net/netfilter/nf_nat.h>
57#include <net/netfilter/nf_conntrack_helper.h>
58#include <net/netfilter/nf_nat_helper.h>
59
60MODULE_LICENSE("GPL");
61MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
62MODULE_DESCRIPTION("Basic SNMP Application Layer Gateway");
63MODULE_ALIAS("ip_nat_snmp_basic");
64
65#define SNMP_PORT 161
66#define SNMP_TRAP_PORT 162
67#define NOCT1(n) (*(u8 *)n)
68
69static int debug;
70static DEFINE_SPINLOCK(snmp_lock);
71
72/*
73 * Application layer address mapping mimics the NAT mapping, but
74 * only for the first octet in this case (a more flexible system
75 * can be implemented if needed).
76 */
77struct oct1_map
78{
79 u_int8_t from;
80 u_int8_t to;
81};
82
83
84/*****************************************************************************
85 *
86 * Basic ASN.1 decoding routines (gxsnmp author Dirk Wisse)
87 *
88 *****************************************************************************/
89
90/* Class */
91#define ASN1_UNI 0 /* Universal */
92#define ASN1_APL 1 /* Application */
93#define ASN1_CTX 2 /* Context */
94#define ASN1_PRV 3 /* Private */
95
96/* Tag */
97#define ASN1_EOC 0 /* End Of Contents */
98#define ASN1_BOL 1 /* Boolean */
99#define ASN1_INT 2 /* Integer */
100#define ASN1_BTS 3 /* Bit String */
101#define ASN1_OTS 4 /* Octet String */
102#define ASN1_NUL 5 /* Null */
103#define ASN1_OJI 6 /* Object Identifier */
104#define ASN1_OJD 7 /* Object Description */
105#define ASN1_EXT 8 /* External */
106#define ASN1_SEQ 16 /* Sequence */
107#define ASN1_SET 17 /* Set */
108#define ASN1_NUMSTR 18 /* Numerical String */
109#define ASN1_PRNSTR 19 /* Printable String */
110#define ASN1_TEXSTR 20 /* Teletext String */
111#define ASN1_VIDSTR 21 /* Video String */
112#define ASN1_IA5STR 22 /* IA5 String */
113#define ASN1_UNITIM 23 /* Universal Time */
114#define ASN1_GENTIM 24 /* General Time */
115#define ASN1_GRASTR 25 /* Graphical String */
116#define ASN1_VISSTR 26 /* Visible String */
117#define ASN1_GENSTR 27 /* General String */
118
119/* Primitive / Constructed methods*/
120#define ASN1_PRI 0 /* Primitive */
121#define ASN1_CON 1 /* Constructed */
122
123/*
124 * Error codes.
125 */
126#define ASN1_ERR_NOERROR 0
127#define ASN1_ERR_DEC_EMPTY 2
128#define ASN1_ERR_DEC_EOC_MISMATCH 3
129#define ASN1_ERR_DEC_LENGTH_MISMATCH 4
130#define ASN1_ERR_DEC_BADVALUE 5
131
132/*
133 * ASN.1 context.
134 */
135struct asn1_ctx
136{
137 int error; /* Error condition */
138 unsigned char *pointer; /* Octet just to be decoded */
139 unsigned char *begin; /* First octet */
140 unsigned char *end; /* Octet after last octet */
141};
142
143/*
144 * Octet string (not null terminated)
145 */
146struct asn1_octstr
147{
148 unsigned char *data;
149 unsigned int len;
150};
151
152static void asn1_open(struct asn1_ctx *ctx,
153 unsigned char *buf,
154 unsigned int len)
155{
156 ctx->begin = buf;
157 ctx->end = buf + len;
158 ctx->pointer = buf;
159 ctx->error = ASN1_ERR_NOERROR;
160}
161
162static unsigned char asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch)
163{
164 if (ctx->pointer >= ctx->end) {
165 ctx->error = ASN1_ERR_DEC_EMPTY;
166 return 0;
167 }
168 *ch = *(ctx->pointer)++;
169 return 1;
170}
171
172static unsigned char asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag)
173{
174 unsigned char ch;
175
176 *tag = 0;
177
178 do
179 {
180 if (!asn1_octet_decode(ctx, &ch))
181 return 0;
182 *tag <<= 7;
183 *tag |= ch & 0x7F;
184 } while ((ch & 0x80) == 0x80);
185 return 1;
186}
187
188static unsigned char asn1_id_decode(struct asn1_ctx *ctx,
189 unsigned int *cls,
190 unsigned int *con,
191 unsigned int *tag)
192{
193 unsigned char ch;
194
195 if (!asn1_octet_decode(ctx, &ch))
196 return 0;
197
198 *cls = (ch & 0xC0) >> 6;
199 *con = (ch & 0x20) >> 5;
200 *tag = (ch & 0x1F);
201
202 if (*tag == 0x1F) {
203 if (!asn1_tag_decode(ctx, tag))
204 return 0;
205 }
206 return 1;
207}
208
209static unsigned char asn1_length_decode(struct asn1_ctx *ctx,
210 unsigned int *def,
211 unsigned int *len)
212{
213 unsigned char ch, cnt;
214
215 if (!asn1_octet_decode(ctx, &ch))
216 return 0;
217
218 if (ch == 0x80)
219 *def = 0;
220 else {
221 *def = 1;
222
223 if (ch < 0x80)
224 *len = ch;
225 else {
226 cnt = (unsigned char) (ch & 0x7F);
227 *len = 0;
228
229 while (cnt > 0) {
230 if (!asn1_octet_decode(ctx, &ch))
231 return 0;
232 *len <<= 8;
233 *len |= ch;
234 cnt--;
235 }
236 }
237 }
238 return 1;
239}
240
241static unsigned char asn1_header_decode(struct asn1_ctx *ctx,
242 unsigned char **eoc,
243 unsigned int *cls,
244 unsigned int *con,
245 unsigned int *tag)
246{
247 unsigned int def, len;
248
249 if (!asn1_id_decode(ctx, cls, con, tag))
250 return 0;
251
252 def = len = 0;
253 if (!asn1_length_decode(ctx, &def, &len))
254 return 0;
255
256 if (def)
257 *eoc = ctx->pointer + len;
258 else
259 *eoc = NULL;
260 return 1;
261}
262
263static unsigned char asn1_eoc_decode(struct asn1_ctx *ctx, unsigned char *eoc)
264{
265 unsigned char ch;
266
267 if (eoc == 0) {
268 if (!asn1_octet_decode(ctx, &ch))
269 return 0;
270
271 if (ch != 0x00) {
272 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
273 return 0;
274 }
275
276 if (!asn1_octet_decode(ctx, &ch))
277 return 0;
278
279 if (ch != 0x00) {
280 ctx->error = ASN1_ERR_DEC_EOC_MISMATCH;
281 return 0;
282 }
283 return 1;
284 } else {
285 if (ctx->pointer != eoc) {
286 ctx->error = ASN1_ERR_DEC_LENGTH_MISMATCH;
287 return 0;
288 }
289 return 1;
290 }
291}
292
293static unsigned char asn1_null_decode(struct asn1_ctx *ctx, unsigned char *eoc)
294{
295 ctx->pointer = eoc;
296 return 1;
297}
298
299static unsigned char asn1_long_decode(struct asn1_ctx *ctx,
300 unsigned char *eoc,
301 long *integer)
302{
303 unsigned char ch;
304 unsigned int len;
305
306 if (!asn1_octet_decode(ctx, &ch))
307 return 0;
308
309 *integer = (signed char) ch;
310 len = 1;
311
312 while (ctx->pointer < eoc) {
313 if (++len > sizeof (long)) {
314 ctx->error = ASN1_ERR_DEC_BADVALUE;
315 return 0;
316 }
317
318 if (!asn1_octet_decode(ctx, &ch))
319 return 0;
320
321 *integer <<= 8;
322 *integer |= ch;
323 }
324 return 1;
325}
326
327static unsigned char asn1_uint_decode(struct asn1_ctx *ctx,
328 unsigned char *eoc,
329 unsigned int *integer)
330{
331 unsigned char ch;
332 unsigned int len;
333
334 if (!asn1_octet_decode(ctx, &ch))
335 return 0;
336
337 *integer = ch;
338 if (ch == 0) len = 0;
339 else len = 1;
340
341 while (ctx->pointer < eoc) {
342 if (++len > sizeof (unsigned int)) {
343 ctx->error = ASN1_ERR_DEC_BADVALUE;
344 return 0;
345 }
346
347 if (!asn1_octet_decode(ctx, &ch))
348 return 0;
349
350 *integer <<= 8;
351 *integer |= ch;
352 }
353 return 1;
354}
355
356static unsigned char asn1_ulong_decode(struct asn1_ctx *ctx,
357 unsigned char *eoc,
358 unsigned long *integer)
359{
360 unsigned char ch;
361 unsigned int len;
362
363 if (!asn1_octet_decode(ctx, &ch))
364 return 0;
365
366 *integer = ch;
367 if (ch == 0) len = 0;
368 else len = 1;
369
370 while (ctx->pointer < eoc) {
371 if (++len > sizeof (unsigned long)) {
372 ctx->error = ASN1_ERR_DEC_BADVALUE;
373 return 0;
374 }
375
376 if (!asn1_octet_decode(ctx, &ch))
377 return 0;
378
379 *integer <<= 8;
380 *integer |= ch;
381 }
382 return 1;
383}
384
385static unsigned char asn1_octets_decode(struct asn1_ctx *ctx,
386 unsigned char *eoc,
387 unsigned char **octets,
388 unsigned int *len)
389{
390 unsigned char *ptr;
391
392 *len = 0;
393
394 *octets = kmalloc(eoc - ctx->pointer, GFP_ATOMIC);
395 if (*octets == NULL) {
396 if (net_ratelimit())
397 printk("OOM in bsalg (%d)\n", __LINE__);
398 return 0;
399 }
400
401 ptr = *octets;
402 while (ctx->pointer < eoc) {
403 if (!asn1_octet_decode(ctx, (unsigned char *)ptr++)) {
404 kfree(*octets);
405 *octets = NULL;
406 return 0;
407 }
408 (*len)++;
409 }
410 return 1;
411}
412
413static unsigned char asn1_subid_decode(struct asn1_ctx *ctx,
414 unsigned long *subid)
415{
416 unsigned char ch;
417
418 *subid = 0;
419
420 do {
421 if (!asn1_octet_decode(ctx, &ch))
422 return 0;
423
424 *subid <<= 7;
425 *subid |= ch & 0x7F;
426 } while ((ch & 0x80) == 0x80);
427 return 1;
428}
429
430static unsigned char asn1_oid_decode(struct asn1_ctx *ctx,
431 unsigned char *eoc,
432 unsigned long **oid,
433 unsigned int *len)
434{
435 unsigned long subid;
436 unsigned int size;
437 unsigned long *optr;
438
439 size = eoc - ctx->pointer + 1;
440 *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
441 if (*oid == NULL) {
442 if (net_ratelimit())
443 printk("OOM in bsalg (%d)\n", __LINE__);
444 return 0;
445 }
446
447 optr = *oid;
448
449 if (!asn1_subid_decode(ctx, &subid)) {
450 kfree(*oid);
451 *oid = NULL;
452 return 0;
453 }
454
455 if (subid < 40) {
456 optr [0] = 0;
457 optr [1] = subid;
458 } else if (subid < 80) {
459 optr [0] = 1;
460 optr [1] = subid - 40;
461 } else {
462 optr [0] = 2;
463 optr [1] = subid - 80;
464 }
465
466 *len = 2;
467 optr += 2;
468
469 while (ctx->pointer < eoc) {
470 if (++(*len) > size) {
471 ctx->error = ASN1_ERR_DEC_BADVALUE;
472 kfree(*oid);
473 *oid = NULL;
474 return 0;
475 }
476
477 if (!asn1_subid_decode(ctx, optr++)) {
478 kfree(*oid);
479 *oid = NULL;
480 return 0;
481 }
482 }
483 return 1;
484}
485
486/*****************************************************************************
487 *
488 * SNMP decoding routines (gxsnmp author Dirk Wisse)
489 *
490 *****************************************************************************/
491
492/* SNMP Versions */
493#define SNMP_V1 0
494#define SNMP_V2C 1
495#define SNMP_V2 2
496#define SNMP_V3 3
497
498/* Default Sizes */
499#define SNMP_SIZE_COMM 256
500#define SNMP_SIZE_OBJECTID 128
501#define SNMP_SIZE_BUFCHR 256
502#define SNMP_SIZE_BUFINT 128
503#define SNMP_SIZE_SMALLOBJECTID 16
504
505/* Requests */
506#define SNMP_PDU_GET 0
507#define SNMP_PDU_NEXT 1
508#define SNMP_PDU_RESPONSE 2
509#define SNMP_PDU_SET 3
510#define SNMP_PDU_TRAP1 4
511#define SNMP_PDU_BULK 5
512#define SNMP_PDU_INFORM 6
513#define SNMP_PDU_TRAP2 7
514
515/* Errors */
516#define SNMP_NOERROR 0
517#define SNMP_TOOBIG 1
518#define SNMP_NOSUCHNAME 2
519#define SNMP_BADVALUE 3
520#define SNMP_READONLY 4
521#define SNMP_GENERROR 5
522#define SNMP_NOACCESS 6
523#define SNMP_WRONGTYPE 7
524#define SNMP_WRONGLENGTH 8
525#define SNMP_WRONGENCODING 9
526#define SNMP_WRONGVALUE 10
527#define SNMP_NOCREATION 11
528#define SNMP_INCONSISTENTVALUE 12
529#define SNMP_RESOURCEUNAVAILABLE 13
530#define SNMP_COMMITFAILED 14
531#define SNMP_UNDOFAILED 15
532#define SNMP_AUTHORIZATIONERROR 16
533#define SNMP_NOTWRITABLE 17
534#define SNMP_INCONSISTENTNAME 18
535
536/* General SNMP V1 Traps */
537#define SNMP_TRAP_COLDSTART 0
538#define SNMP_TRAP_WARMSTART 1
539#define SNMP_TRAP_LINKDOWN 2
540#define SNMP_TRAP_LINKUP 3
541#define SNMP_TRAP_AUTFAILURE 4
542#define SNMP_TRAP_EQPNEIGHBORLOSS 5
543#define SNMP_TRAP_ENTSPECIFIC 6
544
545/* SNMPv1 Types */
546#define SNMP_NULL 0
547#define SNMP_INTEGER 1 /* l */
548#define SNMP_OCTETSTR 2 /* c */
549#define SNMP_DISPLAYSTR 2 /* c */
550#define SNMP_OBJECTID 3 /* ul */
551#define SNMP_IPADDR 4 /* uc */
552#define SNMP_COUNTER 5 /* ul */
553#define SNMP_GAUGE 6 /* ul */
554#define SNMP_TIMETICKS 7 /* ul */
555#define SNMP_OPAQUE 8 /* c */
556
557/* Additional SNMPv2 Types */
558#define SNMP_UINTEGER 5 /* ul */
559#define SNMP_BITSTR 9 /* uc */
560#define SNMP_NSAP 10 /* uc */
561#define SNMP_COUNTER64 11 /* ul */
562#define SNMP_NOSUCHOBJECT 12
563#define SNMP_NOSUCHINSTANCE 13
564#define SNMP_ENDOFMIBVIEW 14
565
566union snmp_syntax
567{
568 unsigned char uc[0]; /* 8 bit unsigned */
569 char c[0]; /* 8 bit signed */
570 unsigned long ul[0]; /* 32 bit unsigned */
571 long l[0]; /* 32 bit signed */
572};
573
574struct snmp_object
575{
576 unsigned long *id;
577 unsigned int id_len;
578 unsigned short type;
579 unsigned int syntax_len;
580 union snmp_syntax syntax;
581};
582
583struct snmp_request
584{
585 unsigned long id;
586 unsigned int error_status;
587 unsigned int error_index;
588};
589
590struct snmp_v1_trap
591{
592 unsigned long *id;
593 unsigned int id_len;
594 unsigned long ip_address; /* pointer */
595 unsigned int general;
596 unsigned int specific;
597 unsigned long time;
598};
599
600/* SNMP types */
601#define SNMP_IPA 0
602#define SNMP_CNT 1
603#define SNMP_GGE 2
604#define SNMP_TIT 3
605#define SNMP_OPQ 4
606#define SNMP_C64 6
607
608/* SNMP errors */
609#define SERR_NSO 0
610#define SERR_NSI 1
611#define SERR_EOM 2
612
613static inline void mangle_address(unsigned char *begin,
614 unsigned char *addr,
615 const struct oct1_map *map,
616 __sum16 *check);
617struct snmp_cnv
618{
619 unsigned int class;
620 unsigned int tag;
621 int syntax;
622};
623
624static struct snmp_cnv snmp_conv [] =
625{
626 {ASN1_UNI, ASN1_NUL, SNMP_NULL},
627 {ASN1_UNI, ASN1_INT, SNMP_INTEGER},
628 {ASN1_UNI, ASN1_OTS, SNMP_OCTETSTR},
629 {ASN1_UNI, ASN1_OTS, SNMP_DISPLAYSTR},
630 {ASN1_UNI, ASN1_OJI, SNMP_OBJECTID},
631 {ASN1_APL, SNMP_IPA, SNMP_IPADDR},
632 {ASN1_APL, SNMP_CNT, SNMP_COUNTER}, /* Counter32 */
633 {ASN1_APL, SNMP_GGE, SNMP_GAUGE}, /* Gauge32 == Unsigned32 */
634 {ASN1_APL, SNMP_TIT, SNMP_TIMETICKS},
635 {ASN1_APL, SNMP_OPQ, SNMP_OPAQUE},
636
637 /* SNMPv2 data types and errors */
638 {ASN1_UNI, ASN1_BTS, SNMP_BITSTR},
639 {ASN1_APL, SNMP_C64, SNMP_COUNTER64},
640 {ASN1_CTX, SERR_NSO, SNMP_NOSUCHOBJECT},
641 {ASN1_CTX, SERR_NSI, SNMP_NOSUCHINSTANCE},
642 {ASN1_CTX, SERR_EOM, SNMP_ENDOFMIBVIEW},
643 {0, 0, -1}
644};
645
646static unsigned char snmp_tag_cls2syntax(unsigned int tag,
647 unsigned int cls,
648 unsigned short *syntax)
649{
650 struct snmp_cnv *cnv;
651
652 cnv = snmp_conv;
653
654 while (cnv->syntax != -1) {
655 if (cnv->tag == tag && cnv->class == cls) {
656 *syntax = cnv->syntax;
657 return 1;
658 }
659 cnv++;
660 }
661 return 0;
662}
663
664static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
665 struct snmp_object **obj)
666{
667 unsigned int cls, con, tag, len, idlen;
668 unsigned short type;
669 unsigned char *eoc, *end, *p;
670 unsigned long *lp, *id;
671 unsigned long ul;
672 long l;
673
674 *obj = NULL;
675 id = NULL;
676
677 if (!asn1_header_decode(ctx, &eoc, &cls, &con, &tag))
678 return 0;
679
680 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
681 return 0;
682
683 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
684 return 0;
685
686 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
687 return 0;
688
689 if (!asn1_oid_decode(ctx, end, &id, &idlen))
690 return 0;
691
692 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag)) {
693 kfree(id);
694 return 0;
695 }
696
697 if (con != ASN1_PRI) {
698 kfree(id);
699 return 0;
700 }
701
702 type = 0;
703 if (!snmp_tag_cls2syntax(tag, cls, &type)) {
704 kfree(id);
705 return 0;
706 }
707
708 l = 0;
709 switch (type) {
710 case SNMP_INTEGER:
711 len = sizeof(long);
712 if (!asn1_long_decode(ctx, end, &l)) {
713 kfree(id);
714 return 0;
715 }
716 *obj = kmalloc(sizeof(struct snmp_object) + len,
717 GFP_ATOMIC);
718 if (*obj == NULL) {
719 kfree(id);
720 if (net_ratelimit())
721 printk("OOM in bsalg (%d)\n", __LINE__);
722 return 0;
723 }
724 (*obj)->syntax.l[0] = l;
725 break;
726 case SNMP_OCTETSTR:
727 case SNMP_OPAQUE:
728 if (!asn1_octets_decode(ctx, end, &p, &len)) {
729 kfree(id);
730 return 0;
731 }
732 *obj = kmalloc(sizeof(struct snmp_object) + len,
733 GFP_ATOMIC);
734 if (*obj == NULL) {
735 kfree(id);
736 if (net_ratelimit())
737 printk("OOM in bsalg (%d)\n", __LINE__);
738 return 0;
739 }
740 memcpy((*obj)->syntax.c, p, len);
741 kfree(p);
742 break;
743 case SNMP_NULL:
744 case SNMP_NOSUCHOBJECT:
745 case SNMP_NOSUCHINSTANCE:
746 case SNMP_ENDOFMIBVIEW:
747 len = 0;
748 *obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
749 if (*obj == NULL) {
750 kfree(id);
751 if (net_ratelimit())
752 printk("OOM in bsalg (%d)\n", __LINE__);
753 return 0;
754 }
755 if (!asn1_null_decode(ctx, end)) {
756 kfree(id);
757 kfree(*obj);
758 *obj = NULL;
759 return 0;
760 }
761 break;
762 case SNMP_OBJECTID:
763 if (!asn1_oid_decode(ctx, end, (unsigned long **)&lp, &len)) {
764 kfree(id);
765 return 0;
766 }
767 len *= sizeof(unsigned long);
768 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
769 if (*obj == NULL) {
770 kfree(lp);
771 kfree(id);
772 if (net_ratelimit())
773 printk("OOM in bsalg (%d)\n", __LINE__);
774 return 0;
775 }
776 memcpy((*obj)->syntax.ul, lp, len);
777 kfree(lp);
778 break;
779 case SNMP_IPADDR:
780 if (!asn1_octets_decode(ctx, end, &p, &len)) {
781 kfree(id);
782 return 0;
783 }
784 if (len != 4) {
785 kfree(p);
786 kfree(id);
787 return 0;
788 }
789 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
790 if (*obj == NULL) {
791 kfree(p);
792 kfree(id);
793 if (net_ratelimit())
794 printk("OOM in bsalg (%d)\n", __LINE__);
795 return 0;
796 }
797 memcpy((*obj)->syntax.uc, p, len);
798 kfree(p);
799 break;
800 case SNMP_COUNTER:
801 case SNMP_GAUGE:
802 case SNMP_TIMETICKS:
803 len = sizeof(unsigned long);
804 if (!asn1_ulong_decode(ctx, end, &ul)) {
805 kfree(id);
806 return 0;
807 }
808 *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC);
809 if (*obj == NULL) {
810 kfree(id);
811 if (net_ratelimit())
812 printk("OOM in bsalg (%d)\n", __LINE__);
813 return 0;
814 }
815 (*obj)->syntax.ul[0] = ul;
816 break;
817 default:
818 kfree(id);
819 return 0;
820 }
821
822 (*obj)->syntax_len = len;
823 (*obj)->type = type;
824 (*obj)->id = id;
825 (*obj)->id_len = idlen;
826
827 if (!asn1_eoc_decode(ctx, eoc)) {
828 kfree(id);
829 kfree(*obj);
830 *obj = NULL;
831 return 0;
832 }
833 return 1;
834}
835
836static unsigned char snmp_request_decode(struct asn1_ctx *ctx,
837 struct snmp_request *request)
838{
839 unsigned int cls, con, tag;
840 unsigned char *end;
841
842 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
843 return 0;
844
845 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
846 return 0;
847
848 if (!asn1_ulong_decode(ctx, end, &request->id))
849 return 0;
850
851 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
852 return 0;
853
854 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
855 return 0;
856
857 if (!asn1_uint_decode(ctx, end, &request->error_status))
858 return 0;
859
860 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
861 return 0;
862
863 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
864 return 0;
865
866 if (!asn1_uint_decode(ctx, end, &request->error_index))
867 return 0;
868
869 return 1;
870}
871
872/*
873 * Fast checksum update for possibly oddly-aligned UDP byte, from the
874 * code example in the draft.
875 */
876static void fast_csum(__sum16 *csum,
877 const unsigned char *optr,
878 const unsigned char *nptr,
879 int offset)
880{
881 unsigned char s[4];
882
883 if (offset & 1) {
884 s[0] = s[2] = 0;
885 s[1] = ~*optr;
886 s[3] = *nptr;
887 } else {
888 s[1] = s[3] = 0;
889 s[0] = ~*optr;
890 s[2] = *nptr;
891 }
892
893 *csum = csum_fold(csum_partial(s, 4, ~csum_unfold(*csum)));
894}
895
896/*
897 * Mangle IP address.
898 * - begin points to the start of the snmp messgae
899 * - addr points to the start of the address
900 */
901static inline void mangle_address(unsigned char *begin,
902 unsigned char *addr,
903 const struct oct1_map *map,
904 __sum16 *check)
905{
906 if (map->from == NOCT1(addr)) {
907 u_int32_t old;
908
909 if (debug)
910 memcpy(&old, (unsigned char *)addr, sizeof(old));
911
912 *addr = map->to;
913
914 /* Update UDP checksum if being used */
915 if (*check) {
916 fast_csum(check,
917 &map->from, &map->to, addr - begin);
918
919 }
920
921 if (debug)
922 printk(KERN_DEBUG "bsalg: mapped %u.%u.%u.%u to "
923 "%u.%u.%u.%u\n", NIPQUAD(old), NIPQUAD(*addr));
924 }
925}
926
927static unsigned char snmp_trap_decode(struct asn1_ctx *ctx,
928 struct snmp_v1_trap *trap,
929 const struct oct1_map *map,
930 __sum16 *check)
931{
932 unsigned int cls, con, tag, len;
933 unsigned char *end;
934
935 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
936 return 0;
937
938 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI)
939 return 0;
940
941 if (!asn1_oid_decode(ctx, end, &trap->id, &trap->id_len))
942 return 0;
943
944 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
945 goto err_id_free;
946
947 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_IPA) ||
948 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_OTS)))
949 goto err_id_free;
950
951 if (!asn1_octets_decode(ctx, end, (unsigned char **)&trap->ip_address, &len))
952 goto err_id_free;
953
954 /* IPv4 only */
955 if (len != 4)
956 goto err_addr_free;
957
958 mangle_address(ctx->begin, ctx->pointer - 4, map, check);
959
960 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
961 goto err_addr_free;
962
963 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
964 goto err_addr_free;
965
966 if (!asn1_uint_decode(ctx, end, &trap->general))
967 goto err_addr_free;
968
969 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
970 goto err_addr_free;
971
972 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
973 goto err_addr_free;
974
975 if (!asn1_uint_decode(ctx, end, &trap->specific))
976 goto err_addr_free;
977
978 if (!asn1_header_decode(ctx, &end, &cls, &con, &tag))
979 goto err_addr_free;
980
981 if (!((cls == ASN1_APL && con == ASN1_PRI && tag == SNMP_TIT) ||
982 (cls == ASN1_UNI && con == ASN1_PRI && tag == ASN1_INT)))
983 goto err_addr_free;
984
985 if (!asn1_ulong_decode(ctx, end, &trap->time))
986 goto err_addr_free;
987
988 return 1;
989
990err_addr_free:
991 kfree((unsigned long *)trap->ip_address);
992
993err_id_free:
994 kfree(trap->id);
995
996 return 0;
997}
998
999/*****************************************************************************
1000 *
1001 * Misc. routines
1002 *
1003 *****************************************************************************/
1004
1005static void hex_dump(unsigned char *buf, size_t len)
1006{
1007 size_t i;
1008
1009 for (i = 0; i < len; i++) {
1010 if (i && !(i % 16))
1011 printk("\n");
1012 printk("%02x ", *(buf + i));
1013 }
1014 printk("\n");
1015}
1016
1017/*
1018 * Parse and mangle SNMP message according to mapping.
1019 * (And this is the fucking 'basic' method).
1020 */
1021static int snmp_parse_mangle(unsigned char *msg,
1022 u_int16_t len,
1023 const struct oct1_map *map,
1024 __sum16 *check)
1025{
1026 unsigned char *eoc, *end;
1027 unsigned int cls, con, tag, vers, pdutype;
1028 struct asn1_ctx ctx;
1029 struct asn1_octstr comm;
1030 struct snmp_object **obj;
1031
1032 if (debug > 1)
1033 hex_dump(msg, len);
1034
1035 asn1_open(&ctx, msg, len);
1036
1037 /*
1038 * Start of SNMP message.
1039 */
1040 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1041 return 0;
1042 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1043 return 0;
1044
1045 /*
1046 * Version 1 or 2 handled.
1047 */
1048 if (!asn1_header_decode(&ctx, &end, &cls, &con, &tag))
1049 return 0;
1050 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT)
1051 return 0;
1052 if (!asn1_uint_decode (&ctx, end, &vers))
1053 return 0;
1054 if (debug > 1)
1055 printk(KERN_DEBUG "bsalg: snmp version: %u\n", vers + 1);
1056 if (vers > 1)
1057 return 1;
1058
1059 /*
1060 * Community.
1061 */
1062 if (!asn1_header_decode (&ctx, &end, &cls, &con, &tag))
1063 return 0;
1064 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OTS)
1065 return 0;
1066 if (!asn1_octets_decode(&ctx, end, &comm.data, &comm.len))
1067 return 0;
1068 if (debug > 1) {
1069 unsigned int i;
1070
1071 printk(KERN_DEBUG "bsalg: community: ");
1072 for (i = 0; i < comm.len; i++)
1073 printk("%c", comm.data[i]);
1074 printk("\n");
1075 }
1076 kfree(comm.data);
1077
1078 /*
1079 * PDU type
1080 */
1081 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &pdutype))
1082 return 0;
1083 if (cls != ASN1_CTX || con != ASN1_CON)
1084 return 0;
1085 if (debug > 1) {
1086 unsigned char *pdus[] = {
1087 [SNMP_PDU_GET] = "get",
1088 [SNMP_PDU_NEXT] = "get-next",
1089 [SNMP_PDU_RESPONSE] = "response",
1090 [SNMP_PDU_SET] = "set",
1091 [SNMP_PDU_TRAP1] = "trapv1",
1092 [SNMP_PDU_BULK] = "bulk",
1093 [SNMP_PDU_INFORM] = "inform",
1094 [SNMP_PDU_TRAP2] = "trapv2"
1095 };
1096
1097 if (pdutype > SNMP_PDU_TRAP2)
1098 printk(KERN_DEBUG "bsalg: bad pdu type %u\n", pdutype);
1099 else
1100 printk(KERN_DEBUG "bsalg: pdu: %s\n", pdus[pdutype]);
1101 }
1102 if (pdutype != SNMP_PDU_RESPONSE &&
1103 pdutype != SNMP_PDU_TRAP1 && pdutype != SNMP_PDU_TRAP2)
1104 return 1;
1105
1106 /*
1107 * Request header or v1 trap
1108 */
1109 if (pdutype == SNMP_PDU_TRAP1) {
1110 struct snmp_v1_trap trap;
1111 unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check);
1112
1113 if (ret) {
1114 kfree(trap.id);
1115 kfree((unsigned long *)trap.ip_address);
1116 } else
1117 return ret;
1118
1119 } else {
1120 struct snmp_request req;
1121
1122 if (!snmp_request_decode(&ctx, &req))
1123 return 0;
1124
1125 if (debug > 1)
1126 printk(KERN_DEBUG "bsalg: request: id=0x%lx error_status=%u "
1127 "error_index=%u\n", req.id, req.error_status,
1128 req.error_index);
1129 }
1130
1131 /*
1132 * Loop through objects, look for IP addresses to mangle.
1133 */
1134 if (!asn1_header_decode(&ctx, &eoc, &cls, &con, &tag))
1135 return 0;
1136
1137 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1138 return 0;
1139
1140 obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
1141 if (obj == NULL) {
1142 if (net_ratelimit())
1143 printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
1144 return 0;
1145 }
1146
1147 while (!asn1_eoc_decode(&ctx, eoc)) {
1148 unsigned int i;
1149
1150 if (!snmp_object_decode(&ctx, obj)) {
1151 if (*obj) {
1152 kfree((*obj)->id);
1153 kfree(*obj);
1154 }
1155 kfree(obj);
1156 return 0;
1157 }
1158
1159 if (debug > 1) {
1160 printk(KERN_DEBUG "bsalg: object: ");
1161 for (i = 0; i < (*obj)->id_len; i++) {
1162 if (i > 0)
1163 printk(".");
1164 printk("%lu", (*obj)->id[i]);
1165 }
1166 printk(": type=%u\n", (*obj)->type);
1167
1168 }
1169
1170 if ((*obj)->type == SNMP_IPADDR)
1171 mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
1172
1173 kfree((*obj)->id);
1174 kfree(*obj);
1175 }
1176 kfree(obj);
1177
1178 if (!asn1_eoc_decode(&ctx, eoc))
1179 return 0;
1180
1181 return 1;
1182}
1183
1184/*****************************************************************************
1185 *
1186 * NAT routines.
1187 *
1188 *****************************************************************************/
1189
1190/*
1191 * SNMP translation routine.
1192 */
1193static int snmp_translate(struct nf_conn *ct,
1194 enum ip_conntrack_info ctinfo,
1195 struct sk_buff **pskb)
1196{
1197 struct iphdr *iph = (*pskb)->nh.iph;
1198 struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
1199 u_int16_t udplen = ntohs(udph->len);
1200 u_int16_t paylen = udplen - sizeof(struct udphdr);
1201 int dir = CTINFO2DIR(ctinfo);
1202 struct oct1_map map;
1203
1204 /*
1205 * Determine mappping for application layer addresses based
1206 * on NAT manipulations for the packet.
1207 */
1208 if (dir == IP_CT_DIR_ORIGINAL) {
1209 /* SNAT traps */
1210 map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
1211 map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
1212 } else {
1213 /* DNAT replies */
1214 map.from = NOCT1(&ct->tuplehash[dir].tuple.src.u3.ip);
1215 map.to = NOCT1(&ct->tuplehash[!dir].tuple.dst.u3.ip);
1216 }
1217
1218 if (map.from == map.to)
1219 return NF_ACCEPT;
1220
1221 if (!snmp_parse_mangle((unsigned char *)udph + sizeof(struct udphdr),
1222 paylen, &map, &udph->check)) {
1223 if (net_ratelimit())
1224 printk(KERN_WARNING "bsalg: parser failed\n");
1225 return NF_DROP;
1226 }
1227 return NF_ACCEPT;
1228}
1229
1230/* We don't actually set up expectations, just adjust internal IP
1231 * addresses if this is being NATted */
1232static int help(struct sk_buff **pskb, unsigned int protoff,
1233 struct nf_conn *ct,
1234 enum ip_conntrack_info ctinfo)
1235{
1236 int dir = CTINFO2DIR(ctinfo);
1237 unsigned int ret;
1238 struct iphdr *iph = (*pskb)->nh.iph;
1239 struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
1240
1241 /* SNMP replies and originating SNMP traps get mangled */
1242 if (udph->source == htons(SNMP_PORT) && dir != IP_CT_DIR_REPLY)
1243 return NF_ACCEPT;
1244 if (udph->dest == htons(SNMP_TRAP_PORT) && dir != IP_CT_DIR_ORIGINAL)
1245 return NF_ACCEPT;
1246
1247 /* No NAT? */
1248 if (!(ct->status & IPS_NAT_MASK))
1249 return NF_ACCEPT;
1250
1251 /*
1252 * Make sure the packet length is ok. So far, we were only guaranteed
1253 * to have a valid length IP header plus 8 bytes, which means we have
1254 * enough room for a UDP header. Just verify the UDP length field so we
1255 * can mess around with the payload.
1256 */
1257 if (ntohs(udph->len) != (*pskb)->len - (iph->ihl << 2)) {
1258 if (net_ratelimit())
1259 printk(KERN_WARNING "SNMP: dropping malformed packet "
1260 "src=%u.%u.%u.%u dst=%u.%u.%u.%u\n",
1261 NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1262 return NF_DROP;
1263 }
1264
1265 if (!skb_make_writable(pskb, (*pskb)->len))
1266 return NF_DROP;
1267
1268 spin_lock_bh(&snmp_lock);
1269 ret = snmp_translate(ct, ctinfo, pskb);
1270 spin_unlock_bh(&snmp_lock);
1271 return ret;
1272}
1273
1274static struct nf_conntrack_helper snmp_helper __read_mostly = {
1275 .max_expected = 0,
1276 .timeout = 180,
1277 .me = THIS_MODULE,
1278 .help = help,
1279 .name = "snmp",
1280 .tuple.src.l3num = AF_INET,
1281 .tuple.src.u.udp.port = __constant_htons(SNMP_PORT),
1282 .tuple.dst.protonum = IPPROTO_UDP,
1283 .mask.src.l3num = 0xFFFF,
1284 .mask.src.u.udp.port = __constant_htons(0xFFFF),
1285 .mask.dst.protonum = 0xFF,
1286};
1287
1288static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
1289 .max_expected = 0,
1290 .timeout = 180,
1291 .me = THIS_MODULE,
1292 .help = help,
1293 .name = "snmp_trap",
1294 .tuple.src.l3num = AF_INET,
1295 .tuple.src.u.udp.port = __constant_htons(SNMP_TRAP_PORT),
1296 .tuple.dst.protonum = IPPROTO_UDP,
1297 .mask.src.l3num = 0xFFFF,
1298 .mask.src.u.udp.port = __constant_htons(0xFFFF),
1299 .mask.dst.protonum = 0xFF,
1300};
1301
1302/*****************************************************************************
1303 *
1304 * Module stuff.
1305 *
1306 *****************************************************************************/
1307
1308static int __init nf_nat_snmp_basic_init(void)
1309{
1310 int ret = 0;
1311
1312 ret = nf_conntrack_helper_register(&snmp_helper);
1313 if (ret < 0)
1314 return ret;
1315 ret = nf_conntrack_helper_register(&snmp_trap_helper);
1316 if (ret < 0) {
1317 nf_conntrack_helper_unregister(&snmp_helper);
1318 return ret;
1319 }
1320 return ret;
1321}
1322
1323static void __exit nf_nat_snmp_basic_fini(void)
1324{
1325 nf_conntrack_helper_unregister(&snmp_helper);
1326 nf_conntrack_helper_unregister(&snmp_trap_helper);
1327}
1328
1329module_init(nf_nat_snmp_basic_init);
1330module_exit(nf_nat_snmp_basic_fini);
1331
1332module_param(debug, int, 0600);
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
new file mode 100644
index 000000000000..730a7a44c883
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -0,0 +1,406 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <linux/types.h>
9#include <linux/icmp.h>
10#include <linux/ip.h>
11#include <linux/netfilter.h>
12#include <linux/netfilter_ipv4.h>
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/proc_fs.h>
16#include <net/ip.h>
17#include <net/checksum.h>
18#include <linux/spinlock.h>
19
20#include <net/netfilter/nf_conntrack.h>
21#include <net/netfilter/nf_conntrack_core.h>
22#include <net/netfilter/nf_nat.h>
23#include <net/netfilter/nf_nat_rule.h>
24#include <net/netfilter/nf_nat_protocol.h>
25#include <net/netfilter/nf_nat_core.h>
26#include <net/netfilter/nf_nat_helper.h>
27#include <linux/netfilter_ipv4/ip_tables.h>
28
29#if 0
30#define DEBUGP printk
31#else
32#define DEBUGP(format, args...)
33#endif
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
42static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
43{
44 struct nf_conn *ct;
45 struct nf_conntrack_tuple *t;
46 enum ip_conntrack_info ctinfo;
47 enum ip_conntrack_dir dir;
48 unsigned long statusbit;
49
50 ct = nf_ct_get(skb, &ctinfo);
51 if (ct == NULL)
52 return;
53 dir = CTINFO2DIR(ctinfo);
54 t = &ct->tuplehash[dir].tuple;
55
56 if (dir == IP_CT_DIR_ORIGINAL)
57 statusbit = IPS_DST_NAT;
58 else
59 statusbit = IPS_SRC_NAT;
60
61 if (ct->status & statusbit) {
62 fl->fl4_dst = t->dst.u3.ip;
63 if (t->dst.protonum == IPPROTO_TCP ||
64 t->dst.protonum == IPPROTO_UDP)
65 fl->fl_ip_dport = t->dst.u.tcp.port;
66 }
67
68 statusbit ^= IPS_NAT_MASK;
69
70 if (ct->status & statusbit) {
71 fl->fl4_src = t->src.u3.ip;
72 if (t->dst.protonum == IPPROTO_TCP ||
73 t->dst.protonum == IPPROTO_UDP)
74 fl->fl_ip_sport = t->src.u.tcp.port;
75 }
76}
77#endif
78
79static unsigned int
80nf_nat_fn(unsigned int hooknum,
81 struct sk_buff **pskb,
82 const struct net_device *in,
83 const struct net_device *out,
84 int (*okfn)(struct sk_buff *))
85{
86 struct nf_conn *ct;
87 enum ip_conntrack_info ctinfo;
88 struct nf_conn_nat *nat;
89 struct nf_nat_info *info;
90 /* maniptype == SRC for postrouting. */
91 enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
92
93 /* We never see fragments: conntrack defrags on pre-routing
94 and local-out, and nf_nat_out protects post-routing. */
95 NF_CT_ASSERT(!((*pskb)->nh.iph->frag_off
96 & htons(IP_MF|IP_OFFSET)));
97
98 ct = nf_ct_get(*pskb, &ctinfo);
99 /* Can't track? It's not due to stress, or conntrack would
100 have dropped it. Hence it's the user's responsibilty to
101 packet filter it out, or implement conntrack/NAT for that
102 protocol. 8) --RR */
103 if (!ct) {
104 /* Exception: ICMP redirect to new connection (not in
105 hash table yet). We must not let this through, in
106 case we're doing NAT to the same network. */
107 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
108 struct icmphdr _hdr, *hp;
109
110 hp = skb_header_pointer(*pskb,
111 (*pskb)->nh.iph->ihl*4,
112 sizeof(_hdr), &_hdr);
113 if (hp != NULL &&
114 hp->type == ICMP_REDIRECT)
115 return NF_DROP;
116 }
117 return NF_ACCEPT;
118 }
119
120 /* Don't try to NAT if this packet is not conntracked */
121 if (ct == &nf_conntrack_untracked)
122 return NF_ACCEPT;
123
124 nat = nfct_nat(ct);
125 if (!nat)
126 return NF_DROP;
127
128 switch (ctinfo) {
129 case IP_CT_RELATED:
130 case IP_CT_RELATED+IP_CT_IS_REPLY:
131 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
132 if (!nf_nat_icmp_reply_translation(ct, ctinfo,
133 hooknum, pskb))
134 return NF_DROP;
135 else
136 return NF_ACCEPT;
137 }
138 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
139 case IP_CT_NEW:
140 info = &nat->info;
141
142 /* Seen it before? This can happen for loopback, retrans,
143 or local packets.. */
144 if (!nf_nat_initialized(ct, maniptype)) {
145 unsigned int ret;
146
147 if (unlikely(nf_ct_is_confirmed(ct)))
148 /* NAT module was loaded late */
149 ret = alloc_null_binding_confirmed(ct, info,
150 hooknum);
151 else if (hooknum == NF_IP_LOCAL_IN)
152 /* LOCAL_IN hook doesn't have a chain! */
153 ret = alloc_null_binding(ct, info, hooknum);
154 else
155 ret = nf_nat_rule_find(pskb, hooknum, in, out,
156 ct, info);
157
158 if (ret != NF_ACCEPT) {
159 return ret;
160 }
161 } else
162 DEBUGP("Already setup manip %s for ct %p\n",
163 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
164 ct);
165 break;
166
167 default:
168 /* ESTABLISHED */
169 NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
170 ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
171 info = &nat->info;
172 }
173
174 NF_CT_ASSERT(info);
175 return nf_nat_packet(ct, ctinfo, hooknum, pskb);
176}
177
178static unsigned int
179nf_nat_in(unsigned int hooknum,
180 struct sk_buff **pskb,
181 const struct net_device *in,
182 const struct net_device *out,
183 int (*okfn)(struct sk_buff *))
184{
185 unsigned int ret;
186 __be32 daddr = (*pskb)->nh.iph->daddr;
187
188 ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
189 if (ret != NF_DROP && ret != NF_STOLEN &&
190 daddr != (*pskb)->nh.iph->daddr) {
191 dst_release((*pskb)->dst);
192 (*pskb)->dst = NULL;
193 }
194 return ret;
195}
196
197static unsigned int
198nf_nat_out(unsigned int hooknum,
199 struct sk_buff **pskb,
200 const struct net_device *in,
201 const struct net_device *out,
202 int (*okfn)(struct sk_buff *))
203{
204#ifdef CONFIG_XFRM
205 struct nf_conn *ct;
206 enum ip_conntrack_info ctinfo;
207#endif
208 unsigned int ret;
209
210 /* root is playing with raw sockets. */
211 if ((*pskb)->len < sizeof(struct iphdr) ||
212 (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
213 return NF_ACCEPT;
214
215 ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
216#ifdef CONFIG_XFRM
217 if (ret != NF_DROP && ret != NF_STOLEN &&
218 (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
219 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
220
221 if (ct->tuplehash[dir].tuple.src.u3.ip !=
222 ct->tuplehash[!dir].tuple.dst.u3.ip
223 || ct->tuplehash[dir].tuple.src.u.all !=
224 ct->tuplehash[!dir].tuple.dst.u.all
225 )
226 return ip_xfrm_me_harder(pskb) == 0 ? ret : NF_DROP;
227 }
228#endif
229 return ret;
230}
231
232static unsigned int
233nf_nat_local_fn(unsigned int hooknum,
234 struct sk_buff **pskb,
235 const struct net_device *in,
236 const struct net_device *out,
237 int (*okfn)(struct sk_buff *))
238{
239 struct nf_conn *ct;
240 enum ip_conntrack_info ctinfo;
241 unsigned int ret;
242
243 /* root is playing with raw sockets. */
244 if ((*pskb)->len < sizeof(struct iphdr) ||
245 (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
246 return NF_ACCEPT;
247
248 ret = nf_nat_fn(hooknum, pskb, in, out, okfn);
249 if (ret != NF_DROP && ret != NF_STOLEN &&
250 (ct = nf_ct_get(*pskb, &ctinfo)) != NULL) {
251 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
252
253 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
254 ct->tuplehash[!dir].tuple.src.u3.ip
255#ifdef CONFIG_XFRM
256 || ct->tuplehash[dir].tuple.dst.u.all !=
257 ct->tuplehash[!dir].tuple.src.u.all
258#endif
259 )
260 if (ip_route_me_harder(pskb, RTN_UNSPEC))
261 ret = NF_DROP;
262 }
263 return ret;
264}
265
266static unsigned int
267nf_nat_adjust(unsigned int hooknum,
268 struct sk_buff **pskb,
269 const struct net_device *in,
270 const struct net_device *out,
271 int (*okfn)(struct sk_buff *))
272{
273 struct nf_conn *ct;
274 enum ip_conntrack_info ctinfo;
275
276 ct = nf_ct_get(*pskb, &ctinfo);
277 if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
278 DEBUGP("nf_nat_standalone: adjusting sequence number\n");
279 if (!nf_nat_seq_adjust(pskb, ct, ctinfo))
280 return NF_DROP;
281 }
282 return NF_ACCEPT;
283}
284
285/* We must be after connection tracking and before packet filtering. */
286
287static struct nf_hook_ops nf_nat_ops[] = {
288 /* Before packet filtering, change destination */
289 {
290 .hook = nf_nat_in,
291 .owner = THIS_MODULE,
292 .pf = PF_INET,
293 .hooknum = NF_IP_PRE_ROUTING,
294 .priority = NF_IP_PRI_NAT_DST,
295 },
296 /* After packet filtering, change source */
297 {
298 .hook = nf_nat_out,
299 .owner = THIS_MODULE,
300 .pf = PF_INET,
301 .hooknum = NF_IP_POST_ROUTING,
302 .priority = NF_IP_PRI_NAT_SRC,
303 },
304 /* After conntrack, adjust sequence number */
305 {
306 .hook = nf_nat_adjust,
307 .owner = THIS_MODULE,
308 .pf = PF_INET,
309 .hooknum = NF_IP_POST_ROUTING,
310 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
311 },
312 /* Before packet filtering, change destination */
313 {
314 .hook = nf_nat_local_fn,
315 .owner = THIS_MODULE,
316 .pf = PF_INET,
317 .hooknum = NF_IP_LOCAL_OUT,
318 .priority = NF_IP_PRI_NAT_DST,
319 },
320 /* After packet filtering, change source */
321 {
322 .hook = nf_nat_fn,
323 .owner = THIS_MODULE,
324 .pf = PF_INET,
325 .hooknum = NF_IP_LOCAL_IN,
326 .priority = NF_IP_PRI_NAT_SRC,
327 },
328 /* After conntrack, adjust sequence number */
329 {
330 .hook = nf_nat_adjust,
331 .owner = THIS_MODULE,
332 .pf = PF_INET,
333 .hooknum = NF_IP_LOCAL_IN,
334 .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
335 },
336};
337
338static int __init nf_nat_standalone_init(void)
339{
340 int size, ret = 0;
341
342 need_conntrack();
343
344 size = ALIGN(sizeof(struct nf_conn), __alignof__(struct nf_conn_nat)) +
345 sizeof(struct nf_conn_nat);
346 ret = nf_conntrack_register_cache(NF_CT_F_NAT, "nf_nat:base", size);
347 if (ret < 0) {
348 printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
349 return ret;
350 }
351
352 size = ALIGN(size, __alignof__(struct nf_conn_help)) +
353 sizeof(struct nf_conn_help);
354 ret = nf_conntrack_register_cache(NF_CT_F_NAT|NF_CT_F_HELP,
355 "nf_nat:help", size);
356 if (ret < 0) {
357 printk(KERN_ERR "nf_nat_init: Unable to create slab cache\n");
358 goto cleanup_register_cache;
359 }
360#ifdef CONFIG_XFRM
361 BUG_ON(ip_nat_decode_session != NULL);
362 ip_nat_decode_session = nat_decode_session;
363#endif
364 ret = nf_nat_rule_init();
365 if (ret < 0) {
366 printk("nf_nat_init: can't setup rules.\n");
367 goto cleanup_decode_session;
368 }
369 ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
370 if (ret < 0) {
371 printk("nf_nat_init: can't register hooks.\n");
372 goto cleanup_rule_init;
373 }
374 nf_nat_module_is_loaded = 1;
375 return ret;
376
377 cleanup_rule_init:
378 nf_nat_rule_cleanup();
379 cleanup_decode_session:
380#ifdef CONFIG_XFRM
381 ip_nat_decode_session = NULL;
382 synchronize_net();
383#endif
384 nf_conntrack_unregister_cache(NF_CT_F_NAT|NF_CT_F_HELP);
385 cleanup_register_cache:
386 nf_conntrack_unregister_cache(NF_CT_F_NAT);
387 return ret;
388}
389
390static void __exit nf_nat_standalone_fini(void)
391{
392 nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
393 nf_nat_rule_cleanup();
394 nf_nat_module_is_loaded = 0;
395#ifdef CONFIG_XFRM
396 ip_nat_decode_session = NULL;
397 synchronize_net();
398#endif
399 /* Conntrack caches are unregistered in nf_conntrack_cleanup */
400}
401
402module_init(nf_nat_standalone_init);
403module_exit(nf_nat_standalone_fini);
404
405MODULE_LICENSE("GPL");
406MODULE_ALIAS("ip_nat");
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/ipv4/netfilter/nf_nat_tftp.c
new file mode 100644
index 000000000000..2566b79de224
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_tftp.c
@@ -0,0 +1,52 @@
1/* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8#include <linux/module.h>
9#include <linux/moduleparam.h>
10#include <linux/udp.h>
11
12#include <net/netfilter/nf_nat_helper.h>
13#include <net/netfilter/nf_nat_rule.h>
14#include <net/netfilter/nf_conntrack_helper.h>
15#include <net/netfilter/nf_conntrack_expect.h>
16#include <linux/netfilter/nf_conntrack_tftp.h>
17
18MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
19MODULE_DESCRIPTION("TFTP NAT helper");
20MODULE_LICENSE("GPL");
21MODULE_ALIAS("ip_nat_tftp");
22
23static unsigned int help(struct sk_buff **pskb,
24 enum ip_conntrack_info ctinfo,
25 struct nf_conntrack_expect *exp)
26{
27 struct nf_conn *ct = exp->master;
28
29 exp->saved_proto.udp.port
30 = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
31 exp->dir = IP_CT_DIR_REPLY;
32 exp->expectfn = nf_nat_follow_master;
33 if (nf_conntrack_expect_related(exp) != 0)
34 return NF_DROP;
35 return NF_ACCEPT;
36}
37
38static void __exit nf_nat_tftp_fini(void)
39{
40 rcu_assign_pointer(nf_nat_tftp_hook, NULL);
41 synchronize_rcu();
42}
43
44static int __init nf_nat_tftp_init(void)
45{
46 BUG_ON(rcu_dereference(nf_nat_tftp_hook));
47 rcu_assign_pointer(nf_nat_tftp_hook, help);
48 return 0;
49}
50
51module_init(nf_nat_tftp_init);
52module_exit(nf_nat_tftp_fini);
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 9c6cbe3d9fb8..cd873da54cbe 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -38,6 +38,7 @@
38#include <net/protocol.h> 38#include <net/protocol.h>
39#include <net/tcp.h> 39#include <net/tcp.h>
40#include <net/udp.h> 40#include <net/udp.h>
41#include <net/udplite.h>
41#include <linux/inetdevice.h> 42#include <linux/inetdevice.h>
42#include <linux/proc_fs.h> 43#include <linux/proc_fs.h>
43#include <linux/seq_file.h> 44#include <linux/seq_file.h>
@@ -66,6 +67,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
66 tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated), 67 tcp_death_row.tw_count, atomic_read(&tcp_sockets_allocated),
67 atomic_read(&tcp_memory_allocated)); 68 atomic_read(&tcp_memory_allocated));
68 seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot)); 69 seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
70 seq_printf(seq, "UDPLITE: inuse %d\n", fold_prot_inuse(&udplite_prot));
69 seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot)); 71 seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
70 seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues, 72 seq_printf(seq, "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
71 atomic_read(&ip_frag_mem)); 73 atomic_read(&ip_frag_mem));
@@ -304,6 +306,17 @@ static int snmp_seq_show(struct seq_file *seq, void *v)
304 fold_field((void **) udp_statistics, 306 fold_field((void **) udp_statistics,
305 snmp4_udp_list[i].entry)); 307 snmp4_udp_list[i].entry));
306 308
309 /* the UDP and UDP-Lite MIBs are the same */
310 seq_puts(seq, "\nUdpLite:");
311 for (i = 0; snmp4_udp_list[i].name != NULL; i++)
312 seq_printf(seq, " %s", snmp4_udp_list[i].name);
313
314 seq_puts(seq, "\nUdpLite:");
315 for (i = 0; snmp4_udp_list[i].name != NULL; i++)
316 seq_printf(seq, " %lu",
317 fold_field((void **) udplite_statistics,
318 snmp4_udp_list[i].entry) );
319
307 seq_putc(seq, '\n'); 320 seq_putc(seq, '\n');
308 return 0; 321 return 0;
309} 322}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 5c31dead2bdc..a6c63bbd9ddb 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -854,8 +854,8 @@ static void raw_seq_stop(struct seq_file *seq, void *v)
854static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i) 854static __inline__ char *get_raw_sock(struct sock *sp, char *tmpbuf, int i)
855{ 855{
856 struct inet_sock *inet = inet_sk(sp); 856 struct inet_sock *inet = inet_sk(sp);
857 unsigned int dest = inet->daddr, 857 __be32 dest = inet->daddr,
858 src = inet->rcv_saddr; 858 src = inet->rcv_saddr;
859 __u16 destp = 0, 859 __u16 destp = 0,
860 srcp = inet->num; 860 srcp = inet->num;
861 861
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 925ee4dfc32c..9f3924c4905e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -566,11 +566,9 @@ static inline u32 rt_score(struct rtable *rt)
566 566
567static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) 567static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
568{ 568{
569 return ((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) | 569 return ((__force u32)((fl1->nl_u.ip4_u.daddr ^ fl2->nl_u.ip4_u.daddr) |
570 (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr) | 570 (fl1->nl_u.ip4_u.saddr ^ fl2->nl_u.ip4_u.saddr)) |
571#ifdef CONFIG_IP_ROUTE_FWMARK 571 (fl1->mark ^ fl2->mark) |
572 (fl1->nl_u.ip4_u.fwmark ^ fl2->nl_u.ip4_u.fwmark) |
573#endif
574 (*(u16 *)&fl1->nl_u.ip4_u.tos ^ 572 (*(u16 *)&fl1->nl_u.ip4_u.tos ^
575 *(u16 *)&fl2->nl_u.ip4_u.tos) | 573 *(u16 *)&fl2->nl_u.ip4_u.tos) |
576 (fl1->oif ^ fl2->oif) | 574 (fl1->oif ^ fl2->oif) |
@@ -1643,9 +1641,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1643 rth->fl.fl4_dst = daddr; 1641 rth->fl.fl4_dst = daddr;
1644 rth->rt_dst = daddr; 1642 rth->rt_dst = daddr;
1645 rth->fl.fl4_tos = tos; 1643 rth->fl.fl4_tos = tos;
1646#ifdef CONFIG_IP_ROUTE_FWMARK 1644 rth->fl.mark = skb->mark;
1647 rth->fl.fl4_fwmark= skb->nfmark;
1648#endif
1649 rth->fl.fl4_src = saddr; 1645 rth->fl.fl4_src = saddr;
1650 rth->rt_src = saddr; 1646 rth->rt_src = saddr;
1651#ifdef CONFIG_NET_CLS_ROUTE 1647#ifdef CONFIG_NET_CLS_ROUTE
@@ -1789,9 +1785,7 @@ static inline int __mkroute_input(struct sk_buff *skb,
1789 rth->fl.fl4_dst = daddr; 1785 rth->fl.fl4_dst = daddr;
1790 rth->rt_dst = daddr; 1786 rth->rt_dst = daddr;
1791 rth->fl.fl4_tos = tos; 1787 rth->fl.fl4_tos = tos;
1792#ifdef CONFIG_IP_ROUTE_FWMARK 1788 rth->fl.mark = skb->mark;
1793 rth->fl.fl4_fwmark= skb->nfmark;
1794#endif
1795 rth->fl.fl4_src = saddr; 1789 rth->fl.fl4_src = saddr;
1796 rth->rt_src = saddr; 1790 rth->rt_src = saddr;
1797 rth->rt_gateway = daddr; 1791 rth->rt_gateway = daddr;
@@ -1920,10 +1914,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1920 .saddr = saddr, 1914 .saddr = saddr,
1921 .tos = tos, 1915 .tos = tos,
1922 .scope = RT_SCOPE_UNIVERSE, 1916 .scope = RT_SCOPE_UNIVERSE,
1923#ifdef CONFIG_IP_ROUTE_FWMARK
1924 .fwmark = skb->nfmark
1925#endif
1926 } }, 1917 } },
1918 .mark = skb->mark,
1927 .iif = dev->ifindex }; 1919 .iif = dev->ifindex };
1928 unsigned flags = 0; 1920 unsigned flags = 0;
1929 u32 itag = 0; 1921 u32 itag = 0;
@@ -2034,9 +2026,7 @@ local_input:
2034 rth->fl.fl4_dst = daddr; 2026 rth->fl.fl4_dst = daddr;
2035 rth->rt_dst = daddr; 2027 rth->rt_dst = daddr;
2036 rth->fl.fl4_tos = tos; 2028 rth->fl.fl4_tos = tos;
2037#ifdef CONFIG_IP_ROUTE_FWMARK 2029 rth->fl.mark = skb->mark;
2038 rth->fl.fl4_fwmark= skb->nfmark;
2039#endif
2040 rth->fl.fl4_src = saddr; 2030 rth->fl.fl4_src = saddr;
2041 rth->rt_src = saddr; 2031 rth->rt_src = saddr;
2042#ifdef CONFIG_NET_CLS_ROUTE 2032#ifdef CONFIG_NET_CLS_ROUTE
@@ -2113,9 +2103,7 @@ int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2113 rth->fl.fl4_src == saddr && 2103 rth->fl.fl4_src == saddr &&
2114 rth->fl.iif == iif && 2104 rth->fl.iif == iif &&
2115 rth->fl.oif == 0 && 2105 rth->fl.oif == 0 &&
2116#ifdef CONFIG_IP_ROUTE_FWMARK 2106 rth->fl.mark == skb->mark &&
2117 rth->fl.fl4_fwmark == skb->nfmark &&
2118#endif
2119 rth->fl.fl4_tos == tos) { 2107 rth->fl.fl4_tos == tos) {
2120 rth->u.dst.lastuse = jiffies; 2108 rth->u.dst.lastuse = jiffies;
2121 dst_hold(&rth->u.dst); 2109 dst_hold(&rth->u.dst);
@@ -2239,9 +2227,7 @@ static inline int __mkroute_output(struct rtable **result,
2239 rth->fl.fl4_tos = tos; 2227 rth->fl.fl4_tos = tos;
2240 rth->fl.fl4_src = oldflp->fl4_src; 2228 rth->fl.fl4_src = oldflp->fl4_src;
2241 rth->fl.oif = oldflp->oif; 2229 rth->fl.oif = oldflp->oif;
2242#ifdef CONFIG_IP_ROUTE_FWMARK 2230 rth->fl.mark = oldflp->mark;
2243 rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
2244#endif
2245 rth->rt_dst = fl->fl4_dst; 2231 rth->rt_dst = fl->fl4_dst;
2246 rth->rt_src = fl->fl4_src; 2232 rth->rt_src = fl->fl4_src;
2247 rth->rt_iif = oldflp->oif ? : dev_out->ifindex; 2233 rth->rt_iif = oldflp->oif ? : dev_out->ifindex;
@@ -2385,10 +2371,8 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
2385 .scope = ((tos & RTO_ONLINK) ? 2371 .scope = ((tos & RTO_ONLINK) ?
2386 RT_SCOPE_LINK : 2372 RT_SCOPE_LINK :
2387 RT_SCOPE_UNIVERSE), 2373 RT_SCOPE_UNIVERSE),
2388#ifdef CONFIG_IP_ROUTE_FWMARK
2389 .fwmark = oldflp->fl4_fwmark
2390#endif
2391 } }, 2374 } },
2375 .mark = oldflp->mark,
2392 .iif = loopback_dev.ifindex, 2376 .iif = loopback_dev.ifindex,
2393 .oif = oldflp->oif }; 2377 .oif = oldflp->oif };
2394 struct fib_result res; 2378 struct fib_result res;
@@ -2583,9 +2567,7 @@ int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
2583 rth->fl.fl4_src == flp->fl4_src && 2567 rth->fl.fl4_src == flp->fl4_src &&
2584 rth->fl.iif == 0 && 2568 rth->fl.iif == 0 &&
2585 rth->fl.oif == flp->oif && 2569 rth->fl.oif == flp->oif &&
2586#ifdef CONFIG_IP_ROUTE_FWMARK 2570 rth->fl.mark == flp->mark &&
2587 rth->fl.fl4_fwmark == flp->fl4_fwmark &&
2588#endif
2589 !((rth->fl.fl4_tos ^ flp->fl4_tos) & 2571 !((rth->fl.fl4_tos ^ flp->fl4_tos) &
2590 (IPTOS_RT_MASK | RTO_ONLINK))) { 2572 (IPTOS_RT_MASK | RTO_ONLINK))) {
2591 2573
@@ -2647,7 +2629,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2647 struct rtable *rt = (struct rtable*)skb->dst; 2629 struct rtable *rt = (struct rtable*)skb->dst;
2648 struct rtmsg *r; 2630 struct rtmsg *r;
2649 struct nlmsghdr *nlh; 2631 struct nlmsghdr *nlh;
2650 struct rta_cacheinfo ci; 2632 long expires;
2633 u32 id = 0, ts = 0, tsage = 0, error;
2651 2634
2652 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); 2635 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
2653 if (nlh == NULL) 2636 if (nlh == NULL)
@@ -2694,20 +2677,13 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2694 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) 2677 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
2695 goto nla_put_failure; 2678 goto nla_put_failure;
2696 2679
2697 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); 2680 error = rt->u.dst.error;
2698 ci.rta_used = rt->u.dst.__use; 2681 expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
2699 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
2700 if (rt->u.dst.expires)
2701 ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
2702 else
2703 ci.rta_expires = 0;
2704 ci.rta_error = rt->u.dst.error;
2705 ci.rta_id = ci.rta_ts = ci.rta_tsage = 0;
2706 if (rt->peer) { 2682 if (rt->peer) {
2707 ci.rta_id = rt->peer->ip_id_count; 2683 id = rt->peer->ip_id_count;
2708 if (rt->peer->tcp_ts_stamp) { 2684 if (rt->peer->tcp_ts_stamp) {
2709 ci.rta_ts = rt->peer->tcp_ts; 2685 ts = rt->peer->tcp_ts;
2710 ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; 2686 tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp;
2711 } 2687 }
2712 } 2688 }
2713 2689
@@ -2726,7 +2702,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2726 } else { 2702 } else {
2727 if (err == -EMSGSIZE) 2703 if (err == -EMSGSIZE)
2728 goto nla_put_failure; 2704 goto nla_put_failure;
2729 ci.rta_error = err; 2705 error = err;
2730 } 2706 }
2731 } 2707 }
2732 } else 2708 } else
@@ -2734,7 +2710,9 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2734 NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif); 2710 NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
2735 } 2711 }
2736 2712
2737 NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); 2713 if (rtnl_put_cacheinfo(skb, &rt->u.dst, id, ts, tsage,
2714 expires, error) < 0)
2715 goto nla_put_failure;
2738 2716
2739 return nlmsg_end(skb, nlh); 2717 return nlmsg_end(skb, nlh);
2740 2718
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 661e0a4bca72..6b19530905af 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -35,23 +35,23 @@ module_init(init_syncookies);
35#define COOKIEBITS 24 /* Upper bits store count */ 35#define COOKIEBITS 24 /* Upper bits store count */
36#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) 36#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
37 37
38static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, 38static u32 cookie_hash(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport,
39 u32 count, int c) 39 u32 count, int c)
40{ 40{
41 __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; 41 __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
42 42
43 memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); 43 memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
44 tmp[0] = saddr; 44 tmp[0] = (__force u32)saddr;
45 tmp[1] = daddr; 45 tmp[1] = (__force u32)daddr;
46 tmp[2] = (sport << 16) + dport; 46 tmp[2] = ((__force u32)sport << 16) + (__force u32)dport;
47 tmp[3] = count; 47 tmp[3] = count;
48 sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); 48 sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
49 49
50 return tmp[17]; 50 return tmp[17];
51} 51}
52 52
53static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, 53static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
54 __u16 dport, __u32 sseq, __u32 count, 54 __be16 dport, __u32 sseq, __u32 count,
55 __u32 data) 55 __u32 data)
56{ 56{
57 /* 57 /*
@@ -80,8 +80,8 @@ static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
80 * "maxdiff" if the current (passed-in) "count". The return value 80 * "maxdiff" if the current (passed-in) "count". The return value
81 * is (__u32)-1 if this test fails. 81 * is (__u32)-1 if this test fails.
82 */ 82 */
83static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, 83static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
84 __u16 sport, __u16 dport, __u32 sseq, 84 __be16 sport, __be16 dport, __u32 sseq,
85 __u32 count, __u32 maxdiff) 85 __u32 count, __u32 maxdiff)
86{ 86{
87 __u32 diff; 87 __u32 diff;
@@ -220,7 +220,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
220 } 220 }
221 ireq = inet_rsk(req); 221 ireq = inet_rsk(req);
222 treq = tcp_rsk(req); 222 treq = tcp_rsk(req);
223 treq->rcv_isn = htonl(skb->h.th->seq) - 1; 223 treq->rcv_isn = ntohl(skb->h.th->seq) - 1;
224 treq->snt_isn = cookie; 224 treq->snt_isn = cookie;
225 req->mss = mss; 225 req->mss = mss;
226 ireq->rmt_port = skb->h.th->source; 226 ireq->rmt_port = skb->h.th->source;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 15061b314411..dfcf47f10f88 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -129,6 +129,67 @@ static int sysctl_tcp_congestion_control(ctl_table *table, int __user *name,
129 return ret; 129 return ret;
130} 130}
131 131
132static int proc_tcp_available_congestion_control(ctl_table *ctl,
133 int write, struct file * filp,
134 void __user *buffer, size_t *lenp,
135 loff_t *ppos)
136{
137 ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX, };
138 int ret;
139
140 tbl.data = kmalloc(tbl.maxlen, GFP_USER);
141 if (!tbl.data)
142 return -ENOMEM;
143 tcp_get_available_congestion_control(tbl.data, TCP_CA_BUF_MAX);
144 ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
145 kfree(tbl.data);
146 return ret;
147}
148
149static int proc_allowed_congestion_control(ctl_table *ctl,
150 int write, struct file * filp,
151 void __user *buffer, size_t *lenp,
152 loff_t *ppos)
153{
154 ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
155 int ret;
156
157 tbl.data = kmalloc(tbl.maxlen, GFP_USER);
158 if (!tbl.data)
159 return -ENOMEM;
160
161 tcp_get_allowed_congestion_control(tbl.data, tbl.maxlen);
162 ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
163 if (write && ret == 0)
164 ret = tcp_set_allowed_congestion_control(tbl.data);
165 kfree(tbl.data);
166 return ret;
167}
168
169static int strategy_allowed_congestion_control(ctl_table *table, int __user *name,
170 int nlen, void __user *oldval,
171 size_t __user *oldlenp,
172 void __user *newval, size_t newlen,
173 void **context)
174{
175 ctl_table tbl = { .maxlen = TCP_CA_BUF_MAX };
176 int ret;
177
178 tbl.data = kmalloc(tbl.maxlen, GFP_USER);
179 if (!tbl.data)
180 return -ENOMEM;
181
182 tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
183 ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
184 context);
185 if (ret == 0 && newval && newlen)
186 ret = tcp_set_allowed_congestion_control(tbl.data);
187 kfree(tbl.data);
188
189 return ret;
190
191}
192
132ctl_table ipv4_table[] = { 193ctl_table ipv4_table[] = {
133 { 194 {
134 .ctl_name = NET_IPV4_TCP_TIMESTAMPS, 195 .ctl_name = NET_IPV4_TCP_TIMESTAMPS,
@@ -731,6 +792,21 @@ ctl_table ipv4_table[] = {
731 .proc_handler = &proc_dointvec, 792 .proc_handler = &proc_dointvec,
732 }, 793 },
733#endif /* CONFIG_NETLABEL */ 794#endif /* CONFIG_NETLABEL */
795 {
796 .ctl_name = NET_TCP_AVAIL_CONG_CONTROL,
797 .procname = "tcp_available_congestion_control",
798 .maxlen = TCP_CA_BUF_MAX,
799 .mode = 0444,
800 .proc_handler = &proc_tcp_available_congestion_control,
801 },
802 {
803 .ctl_name = NET_TCP_ALLOWED_CONG_CONTROL,
804 .procname = "tcp_allowed_congestion_control",
805 .maxlen = TCP_CA_BUF_MAX,
806 .mode = 0644,
807 .proc_handler = &proc_allowed_congestion_control,
808 .strategy = &strategy_allowed_congestion_control,
809 },
734 { .ctl_name = 0 } 810 { .ctl_name = 0 }
735}; 811};
736 812
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c05e8edaf544..090c690627e5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -258,6 +258,7 @@
258#include <linux/bootmem.h> 258#include <linux/bootmem.h>
259#include <linux/cache.h> 259#include <linux/cache.h>
260#include <linux/err.h> 260#include <linux/err.h>
261#include <linux/crypto.h>
261 262
262#include <net/icmp.h> 263#include <net/icmp.h>
263#include <net/tcp.h> 264#include <net/tcp.h>
@@ -462,11 +463,12 @@ static inline int forced_push(struct tcp_sock *tp)
462static inline void skb_entail(struct sock *sk, struct tcp_sock *tp, 463static inline void skb_entail(struct sock *sk, struct tcp_sock *tp,
463 struct sk_buff *skb) 464 struct sk_buff *skb)
464{ 465{
465 skb->csum = 0; 466 struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
466 TCP_SKB_CB(skb)->seq = tp->write_seq; 467
467 TCP_SKB_CB(skb)->end_seq = tp->write_seq; 468 skb->csum = 0;
468 TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK; 469 tcb->seq = tcb->end_seq = tp->write_seq;
469 TCP_SKB_CB(skb)->sacked = 0; 470 tcb->flags = TCPCB_FLAG_ACK;
471 tcb->sacked = 0;
470 skb_header_release(skb); 472 skb_header_release(skb);
471 __skb_queue_tail(&sk->sk_write_queue, skb); 473 __skb_queue_tail(&sk->sk_write_queue, skb);
472 sk_charge_skb(sk, skb); 474 sk_charge_skb(sk, skb);
@@ -1942,6 +1944,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
1942 } 1944 }
1943 break; 1945 break;
1944 1946
1947#ifdef CONFIG_TCP_MD5SIG
1948 case TCP_MD5SIG:
1949 /* Read the IP->Key mappings from userspace */
1950 err = tp->af_specific->md5_parse(sk, optval, optlen);
1951 break;
1952#endif
1953
1945 default: 1954 default:
1946 err = -ENOPROTOOPT; 1955 err = -ENOPROTOOPT;
1947 break; 1956 break;
@@ -2154,7 +2163,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
2154 struct tcphdr *th; 2163 struct tcphdr *th;
2155 unsigned thlen; 2164 unsigned thlen;
2156 unsigned int seq; 2165 unsigned int seq;
2157 unsigned int delta; 2166 __be32 delta;
2158 unsigned int oldlen; 2167 unsigned int oldlen;
2159 unsigned int len; 2168 unsigned int len;
2160 2169
@@ -2207,7 +2216,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
2207 do { 2216 do {
2208 th->fin = th->psh = 0; 2217 th->fin = th->psh = 0;
2209 2218
2210 th->check = ~csum_fold(th->check + delta); 2219 th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
2220 (__force u32)delta));
2211 if (skb->ip_summed != CHECKSUM_PARTIAL) 2221 if (skb->ip_summed != CHECKSUM_PARTIAL)
2212 th->check = csum_fold(csum_partial(skb->h.raw, thlen, 2222 th->check = csum_fold(csum_partial(skb->h.raw, thlen,
2213 skb->csum)); 2223 skb->csum));
@@ -2221,7 +2231,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
2221 } while (skb->next); 2231 } while (skb->next);
2222 2232
2223 delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); 2233 delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
2224 th->check = ~csum_fold(th->check + delta); 2234 th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
2235 (__force u32)delta));
2225 if (skb->ip_summed != CHECKSUM_PARTIAL) 2236 if (skb->ip_summed != CHECKSUM_PARTIAL)
2226 th->check = csum_fold(csum_partial(skb->h.raw, thlen, 2237 th->check = csum_fold(csum_partial(skb->h.raw, thlen,
2227 skb->csum)); 2238 skb->csum));
@@ -2231,6 +2242,135 @@ out:
2231} 2242}
2232EXPORT_SYMBOL(tcp_tso_segment); 2243EXPORT_SYMBOL(tcp_tso_segment);
2233 2244
2245#ifdef CONFIG_TCP_MD5SIG
2246static unsigned long tcp_md5sig_users;
2247static struct tcp_md5sig_pool **tcp_md5sig_pool;
2248static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);
2249
2250static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
2251{
2252 int cpu;
2253 for_each_possible_cpu(cpu) {
2254 struct tcp_md5sig_pool *p = *per_cpu_ptr(pool, cpu);
2255 if (p) {
2256 if (p->md5_desc.tfm)
2257 crypto_free_hash(p->md5_desc.tfm);
2258 kfree(p);
2259 p = NULL;
2260 }
2261 }
2262 free_percpu(pool);
2263}
2264
2265void tcp_free_md5sig_pool(void)
2266{
2267 struct tcp_md5sig_pool **pool = NULL;
2268
2269 spin_lock(&tcp_md5sig_pool_lock);
2270 if (--tcp_md5sig_users == 0) {
2271 pool = tcp_md5sig_pool;
2272 tcp_md5sig_pool = NULL;
2273 }
2274 spin_unlock(&tcp_md5sig_pool_lock);
2275 if (pool)
2276 __tcp_free_md5sig_pool(pool);
2277}
2278
2279EXPORT_SYMBOL(tcp_free_md5sig_pool);
2280
2281static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void)
2282{
2283 int cpu;
2284 struct tcp_md5sig_pool **pool;
2285
2286 pool = alloc_percpu(struct tcp_md5sig_pool *);
2287 if (!pool)
2288 return NULL;
2289
2290 for_each_possible_cpu(cpu) {
2291 struct tcp_md5sig_pool *p;
2292 struct crypto_hash *hash;
2293
2294 p = kzalloc(sizeof(*p), GFP_KERNEL);
2295 if (!p)
2296 goto out_free;
2297 *per_cpu_ptr(pool, cpu) = p;
2298
2299 hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
2300 if (!hash || IS_ERR(hash))
2301 goto out_free;
2302
2303 p->md5_desc.tfm = hash;
2304 }
2305 return pool;
2306out_free:
2307 __tcp_free_md5sig_pool(pool);
2308 return NULL;
2309}
2310
2311struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void)
2312{
2313 struct tcp_md5sig_pool **pool;
2314 int alloc = 0;
2315
2316retry:
2317 spin_lock(&tcp_md5sig_pool_lock);
2318 pool = tcp_md5sig_pool;
2319 if (tcp_md5sig_users++ == 0) {
2320 alloc = 1;
2321 spin_unlock(&tcp_md5sig_pool_lock);
2322 } else if (!pool) {
2323 tcp_md5sig_users--;
2324 spin_unlock(&tcp_md5sig_pool_lock);
2325 cpu_relax();
2326 goto retry;
2327 } else
2328 spin_unlock(&tcp_md5sig_pool_lock);
2329
2330 if (alloc) {
2331 /* we cannot hold spinlock here because this may sleep. */
2332 struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool();
2333 spin_lock(&tcp_md5sig_pool_lock);
2334 if (!p) {
2335 tcp_md5sig_users--;
2336 spin_unlock(&tcp_md5sig_pool_lock);
2337 return NULL;
2338 }
2339 pool = tcp_md5sig_pool;
2340 if (pool) {
2341 /* oops, it has already been assigned. */
2342 spin_unlock(&tcp_md5sig_pool_lock);
2343 __tcp_free_md5sig_pool(p);
2344 } else {
2345 tcp_md5sig_pool = pool = p;
2346 spin_unlock(&tcp_md5sig_pool_lock);
2347 }
2348 }
2349 return pool;
2350}
2351
2352EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
2353
2354struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu)
2355{
2356 struct tcp_md5sig_pool **p;
2357 spin_lock(&tcp_md5sig_pool_lock);
2358 p = tcp_md5sig_pool;
2359 if (p)
2360 tcp_md5sig_users++;
2361 spin_unlock(&tcp_md5sig_pool_lock);
2362 return (p ? *per_cpu_ptr(p, cpu) : NULL);
2363}
2364
2365EXPORT_SYMBOL(__tcp_get_md5sig_pool);
2366
2367void __tcp_put_md5sig_pool(void) {
2368 __tcp_free_md5sig_pool(tcp_md5sig_pool);
2369}
2370
2371EXPORT_SYMBOL(__tcp_put_md5sig_pool);
2372#endif
2373
2234extern void __skb_cb_too_small_for_tcp(int, int); 2374extern void __skb_cb_too_small_for_tcp(int, int);
2235extern struct tcp_congestion_ops tcp_reno; 2375extern struct tcp_congestion_ops tcp_reno;
2236 2376
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1e2982f4acd4..5ca7723d0798 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -113,7 +113,7 @@ int tcp_set_default_congestion_control(const char *name)
113 spin_lock(&tcp_cong_list_lock); 113 spin_lock(&tcp_cong_list_lock);
114 ca = tcp_ca_find(name); 114 ca = tcp_ca_find(name);
115#ifdef CONFIG_KMOD 115#ifdef CONFIG_KMOD
116 if (!ca) { 116 if (!ca && capable(CAP_SYS_MODULE)) {
117 spin_unlock(&tcp_cong_list_lock); 117 spin_unlock(&tcp_cong_list_lock);
118 118
119 request_module("tcp_%s", name); 119 request_module("tcp_%s", name);
@@ -123,6 +123,7 @@ int tcp_set_default_congestion_control(const char *name)
123#endif 123#endif
124 124
125 if (ca) { 125 if (ca) {
126 ca->non_restricted = 1; /* default is always allowed */
126 list_move(&ca->list, &tcp_cong_list); 127 list_move(&ca->list, &tcp_cong_list);
127 ret = 0; 128 ret = 0;
128 } 129 }
@@ -139,6 +140,22 @@ static int __init tcp_congestion_default(void)
139late_initcall(tcp_congestion_default); 140late_initcall(tcp_congestion_default);
140 141
141 142
143/* Build string with list of available congestion control values */
144void tcp_get_available_congestion_control(char *buf, size_t maxlen)
145{
146 struct tcp_congestion_ops *ca;
147 size_t offs = 0;
148
149 rcu_read_lock();
150 list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
151 offs += snprintf(buf + offs, maxlen - offs,
152 "%s%s",
153 offs == 0 ? "" : " ", ca->name);
154
155 }
156 rcu_read_unlock();
157}
158
142/* Get current default congestion control */ 159/* Get current default congestion control */
143void tcp_get_default_congestion_control(char *name) 160void tcp_get_default_congestion_control(char *name)
144{ 161{
@@ -152,6 +169,64 @@ void tcp_get_default_congestion_control(char *name)
152 rcu_read_unlock(); 169 rcu_read_unlock();
153} 170}
154 171
172/* Built list of non-restricted congestion control values */
173void tcp_get_allowed_congestion_control(char *buf, size_t maxlen)
174{
175 struct tcp_congestion_ops *ca;
176 size_t offs = 0;
177
178 *buf = '\0';
179 rcu_read_lock();
180 list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
181 if (!ca->non_restricted)
182 continue;
183 offs += snprintf(buf + offs, maxlen - offs,
184 "%s%s",
185 offs == 0 ? "" : " ", ca->name);
186
187 }
188 rcu_read_unlock();
189}
190
191/* Change list of non-restricted congestion control */
192int tcp_set_allowed_congestion_control(char *val)
193{
194 struct tcp_congestion_ops *ca;
195 char *clone, *name;
196 int ret = 0;
197
198 clone = kstrdup(val, GFP_USER);
199 if (!clone)
200 return -ENOMEM;
201
202 spin_lock(&tcp_cong_list_lock);
203 /* pass 1 check for bad entries */
204 while ((name = strsep(&clone, " ")) && *name) {
205 ca = tcp_ca_find(name);
206 if (!ca) {
207 ret = -ENOENT;
208 goto out;
209 }
210 }
211
212 /* pass 2 clear */
213 list_for_each_entry_rcu(ca, &tcp_cong_list, list)
214 ca->non_restricted = 0;
215
216 /* pass 3 mark as allowed */
217 while ((name = strsep(&val, " ")) && *name) {
218 ca = tcp_ca_find(name);
219 WARN_ON(!ca);
220 if (ca)
221 ca->non_restricted = 1;
222 }
223out:
224 spin_unlock(&tcp_cong_list_lock);
225
226 return ret;
227}
228
229
155/* Change congestion control for socket */ 230/* Change congestion control for socket */
156int tcp_set_congestion_control(struct sock *sk, const char *name) 231int tcp_set_congestion_control(struct sock *sk, const char *name)
157{ 232{
@@ -161,12 +236,25 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
161 236
162 rcu_read_lock(); 237 rcu_read_lock();
163 ca = tcp_ca_find(name); 238 ca = tcp_ca_find(name);
239 /* no change asking for existing value */
164 if (ca == icsk->icsk_ca_ops) 240 if (ca == icsk->icsk_ca_ops)
165 goto out; 241 goto out;
166 242
243#ifdef CONFIG_KMOD
244 /* not found attempt to autoload module */
245 if (!ca && capable(CAP_SYS_MODULE)) {
246 rcu_read_unlock();
247 request_module("tcp_%s", name);
248 rcu_read_lock();
249 ca = tcp_ca_find(name);
250 }
251#endif
167 if (!ca) 252 if (!ca)
168 err = -ENOENT; 253 err = -ENOENT;
169 254
255 else if (!(ca->non_restricted || capable(CAP_NET_ADMIN)))
256 err = -EPERM;
257
170 else if (!try_module_get(ca->owner)) 258 else if (!try_module_get(ca->owner))
171 err = -EBUSY; 259 err = -EBUSY;
172 260
@@ -268,6 +356,7 @@ EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd);
268 356
269struct tcp_congestion_ops tcp_reno = { 357struct tcp_congestion_ops tcp_reno = {
270 .name = "reno", 358 .name = "reno",
359 .non_restricted = 1,
271 .owner = THIS_MODULE, 360 .owner = THIS_MODULE,
272 .ssthresh = tcp_reno_ssthresh, 361 .ssthresh = tcp_reno_ssthresh,
273 .cong_avoid = tcp_reno_cong_avoid, 362 .cong_avoid = tcp_reno_cong_avoid,
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 283be3cb4667..753987a1048f 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -26,12 +26,12 @@ struct htcp {
26 u32 alpha; /* Fixed point arith, << 7 */ 26 u32 alpha; /* Fixed point arith, << 7 */
27 u8 beta; /* Fixed point arith, << 7 */ 27 u8 beta; /* Fixed point arith, << 7 */
28 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */ 28 u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
29 u32 last_cong; /* Time since last congestion event end */
30 u32 undo_last_cong;
31 u16 pkts_acked; 29 u16 pkts_acked;
32 u32 packetcount; 30 u32 packetcount;
33 u32 minRTT; 31 u32 minRTT;
34 u32 maxRTT; 32 u32 maxRTT;
33 u32 last_cong; /* Time since last congestion event end */
34 u32 undo_last_cong;
35 35
36 u32 undo_maxRTT; 36 u32 undo_maxRTT;
37 u32 undo_old_maxB; 37 u32 undo_old_maxB;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index cf06accbe687..9304034c0c47 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2677,6 +2677,14 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
2677 opt_rx->sack_ok) { 2677 opt_rx->sack_ok) {
2678 TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; 2678 TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
2679 } 2679 }
2680#ifdef CONFIG_TCP_MD5SIG
2681 case TCPOPT_MD5SIG:
2682 /*
2683 * The MD5 Hash has already been
2684 * checked (see tcp_v{4,6}_do_rcv()).
2685 */
2686 break;
2687#endif
2680 }; 2688 };
2681 ptr+=opsize-2; 2689 ptr+=opsize-2;
2682 length-=opsize; 2690 length-=opsize;
@@ -3782,9 +3790,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
3782 return err; 3790 return err;
3783} 3791}
3784 3792
3785static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) 3793static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
3786{ 3794{
3787 int result; 3795 __sum16 result;
3788 3796
3789 if (sock_owned_by_user(sk)) { 3797 if (sock_owned_by_user(sk)) {
3790 local_bh_enable(); 3798 local_bh_enable();
@@ -4230,6 +4238,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
4230 mb(); 4238 mb();
4231 tcp_set_state(sk, TCP_ESTABLISHED); 4239 tcp_set_state(sk, TCP_ESTABLISHED);
4232 4240
4241 security_inet_conn_established(sk, skb);
4242
4233 /* Make sure socket is routed, for correct metrics. */ 4243 /* Make sure socket is routed, for correct metrics. */
4234 icsk->icsk_af_ops->rebuild_header(sk); 4244 icsk->icsk_af_ops->rebuild_header(sk);
4235 4245
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 22ef8bd26620..a1222d6968c4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -78,6 +78,9 @@
78#include <linux/proc_fs.h> 78#include <linux/proc_fs.h>
79#include <linux/seq_file.h> 79#include <linux/seq_file.h>
80 80
81#include <linux/crypto.h>
82#include <linux/scatterlist.h>
83
81int sysctl_tcp_tw_reuse __read_mostly; 84int sysctl_tcp_tw_reuse __read_mostly;
82int sysctl_tcp_low_latency __read_mostly; 85int sysctl_tcp_low_latency __read_mostly;
83 86
@@ -89,10 +92,19 @@ static struct socket *tcp_socket;
89 92
90void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); 93void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
91 94
95#ifdef CONFIG_TCP_MD5SIG
96static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
97 __be32 addr);
98static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
99 __be32 saddr, __be32 daddr,
100 struct tcphdr *th, int protocol,
101 int tcplen);
102#endif
103
92struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { 104struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
93 .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), 105 .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
94 .lhash_users = ATOMIC_INIT(0), 106 .lhash_users = ATOMIC_INIT(0),
95 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), 107 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
96}; 108};
97 109
98static int tcp_v4_get_port(struct sock *sk, unsigned short snum) 110static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
@@ -111,7 +123,7 @@ void tcp_unhash(struct sock *sk)
111 inet_unhash(&tcp_hashinfo, sk); 123 inet_unhash(&tcp_hashinfo, sk);
112} 124}
113 125
114static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) 126static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
115{ 127{
116 return secure_tcp_sequence_number(skb->nh.iph->daddr, 128 return secure_tcp_sequence_number(skb->nh.iph->daddr,
117 skb->nh.iph->saddr, 129 skb->nh.iph->saddr,
@@ -205,13 +217,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
205 if (tcp_death_row.sysctl_tw_recycle && 217 if (tcp_death_row.sysctl_tw_recycle &&
206 !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { 218 !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
207 struct inet_peer *peer = rt_get_peer(rt); 219 struct inet_peer *peer = rt_get_peer(rt);
208 220 /*
209 /* VJ's idea. We save last timestamp seen from 221 * VJ's idea. We save last timestamp seen from
210 * the destination in peer table, when entering state TIME-WAIT 222 * the destination in peer table, when entering state
211 * and initialize rx_opt.ts_recent from it, when trying new connection. 223 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
224 * when trying new connection.
212 */ 225 */
213 226 if (peer != NULL &&
214 if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) { 227 peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
215 tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp; 228 tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
216 tp->rx_opt.ts_recent = peer->tcp_ts; 229 tp->rx_opt.ts_recent = peer->tcp_ts;
217 } 230 }
@@ -236,7 +249,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
236 if (err) 249 if (err)
237 goto failure; 250 goto failure;
238 251
239 err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk); 252 err = ip_route_newports(&rt, IPPROTO_TCP,
253 inet->sport, inet->dport, sk);
240 if (err) 254 if (err)
241 goto failure; 255 goto failure;
242 256
@@ -260,7 +274,10 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
260 return 0; 274 return 0;
261 275
262failure: 276failure:
263 /* This unhashes the socket and releases the local port, if necessary. */ 277 /*
278 * This unhashes the socket and releases the local port,
279 * if necessary.
280 */
264 tcp_set_state(sk, TCP_CLOSE); 281 tcp_set_state(sk, TCP_CLOSE);
265 ip_rt_put(rt); 282 ip_rt_put(rt);
266 sk->sk_route_caps = 0; 283 sk->sk_route_caps = 0;
@@ -485,8 +502,9 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
485 struct tcphdr *th = skb->h.th; 502 struct tcphdr *th = skb->h.th;
486 503
487 if (skb->ip_summed == CHECKSUM_PARTIAL) { 504 if (skb->ip_summed == CHECKSUM_PARTIAL) {
488 th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); 505 th->check = ~tcp_v4_check(th, len,
489 skb->csum = offsetof(struct tcphdr, check); 506 inet->saddr, inet->daddr, 0);
507 skb->csum_offset = offsetof(struct tcphdr, check);
490 } else { 508 } else {
491 th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, 509 th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr,
492 csum_partial((char *)th, 510 csum_partial((char *)th,
@@ -508,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
508 526
509 th->check = 0; 527 th->check = 0;
510 th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); 528 th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
511 skb->csum = offsetof(struct tcphdr, check); 529 skb->csum_offset = offsetof(struct tcphdr, check);
512 skb->ip_summed = CHECKSUM_PARTIAL; 530 skb->ip_summed = CHECKSUM_PARTIAL;
513 return 0; 531 return 0;
514} 532}
@@ -526,11 +544,19 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
526 * Exception: precedence violation. We do not implement it in any case. 544 * Exception: precedence violation. We do not implement it in any case.
527 */ 545 */
528 546
529static void tcp_v4_send_reset(struct sk_buff *skb) 547static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
530{ 548{
531 struct tcphdr *th = skb->h.th; 549 struct tcphdr *th = skb->h.th;
532 struct tcphdr rth; 550 struct {
551 struct tcphdr th;
552#ifdef CONFIG_TCP_MD5SIG
553 __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
554#endif
555 } rep;
533 struct ip_reply_arg arg; 556 struct ip_reply_arg arg;
557#ifdef CONFIG_TCP_MD5SIG
558 struct tcp_md5sig_key *key;
559#endif
534 560
535 /* Never send a reset in response to a reset. */ 561 /* Never send a reset in response to a reset. */
536 if (th->rst) 562 if (th->rst)
@@ -540,29 +566,49 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
540 return; 566 return;
541 567
542 /* Swap the send and the receive. */ 568 /* Swap the send and the receive. */
543 memset(&rth, 0, sizeof(struct tcphdr)); 569 memset(&rep, 0, sizeof(rep));
544 rth.dest = th->source; 570 rep.th.dest = th->source;
545 rth.source = th->dest; 571 rep.th.source = th->dest;
546 rth.doff = sizeof(struct tcphdr) / 4; 572 rep.th.doff = sizeof(struct tcphdr) / 4;
547 rth.rst = 1; 573 rep.th.rst = 1;
548 574
549 if (th->ack) { 575 if (th->ack) {
550 rth.seq = th->ack_seq; 576 rep.th.seq = th->ack_seq;
551 } else { 577 } else {
552 rth.ack = 1; 578 rep.th.ack = 1;
553 rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + 579 rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
554 skb->len - (th->doff << 2)); 580 skb->len - (th->doff << 2));
555 } 581 }
556 582
557 memset(&arg, 0, sizeof arg); 583 memset(&arg, 0, sizeof(arg));
558 arg.iov[0].iov_base = (unsigned char *)&rth; 584 arg.iov[0].iov_base = (unsigned char *)&rep;
559 arg.iov[0].iov_len = sizeof rth; 585 arg.iov[0].iov_len = sizeof(rep.th);
586
587#ifdef CONFIG_TCP_MD5SIG
588 key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL;
589 if (key) {
590 rep.opt[0] = htonl((TCPOPT_NOP << 24) |
591 (TCPOPT_NOP << 16) |
592 (TCPOPT_MD5SIG << 8) |
593 TCPOLEN_MD5SIG);
594 /* Update length and the length the header thinks exists */
595 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
596 rep.th.doff = arg.iov[0].iov_len / 4;
597
598 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
599 key,
600 skb->nh.iph->daddr,
601 skb->nh.iph->saddr,
602 &rep.th, IPPROTO_TCP,
603 arg.iov[0].iov_len);
604 }
605#endif
560 arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, 606 arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
561 skb->nh.iph->saddr, /*XXX*/ 607 skb->nh.iph->saddr, /* XXX */
562 sizeof(struct tcphdr), IPPROTO_TCP, 0); 608 sizeof(struct tcphdr), IPPROTO_TCP, 0);
563 arg.csumoffset = offsetof(struct tcphdr, check) / 2; 609 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
564 610
565 ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth); 611 ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
566 612
567 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); 613 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
568 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); 614 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -572,28 +618,37 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
572 outside socket context is ugly, certainly. What can I do? 618 outside socket context is ugly, certainly. What can I do?
573 */ 619 */
574 620
575static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, 621static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
622 struct sk_buff *skb, u32 seq, u32 ack,
576 u32 win, u32 ts) 623 u32 win, u32 ts)
577{ 624{
578 struct tcphdr *th = skb->h.th; 625 struct tcphdr *th = skb->h.th;
579 struct { 626 struct {
580 struct tcphdr th; 627 struct tcphdr th;
581 u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2]; 628 __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
629#ifdef CONFIG_TCP_MD5SIG
630 + (TCPOLEN_MD5SIG_ALIGNED >> 2)
631#endif
632 ];
582 } rep; 633 } rep;
583 struct ip_reply_arg arg; 634 struct ip_reply_arg arg;
635#ifdef CONFIG_TCP_MD5SIG
636 struct tcp_md5sig_key *key;
637 struct tcp_md5sig_key tw_key;
638#endif
584 639
585 memset(&rep.th, 0, sizeof(struct tcphdr)); 640 memset(&rep.th, 0, sizeof(struct tcphdr));
586 memset(&arg, 0, sizeof arg); 641 memset(&arg, 0, sizeof(arg));
587 642
588 arg.iov[0].iov_base = (unsigned char *)&rep; 643 arg.iov[0].iov_base = (unsigned char *)&rep;
589 arg.iov[0].iov_len = sizeof(rep.th); 644 arg.iov[0].iov_len = sizeof(rep.th);
590 if (ts) { 645 if (ts) {
591 rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | 646 rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
592 (TCPOPT_TIMESTAMP << 8) | 647 (TCPOPT_TIMESTAMP << 8) |
593 TCPOLEN_TIMESTAMP); 648 TCPOLEN_TIMESTAMP);
594 rep.tsopt[1] = htonl(tcp_time_stamp); 649 rep.opt[1] = htonl(tcp_time_stamp);
595 rep.tsopt[2] = htonl(ts); 650 rep.opt[2] = htonl(ts);
596 arg.iov[0].iov_len = sizeof(rep); 651 arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED;
597 } 652 }
598 653
599 /* Swap the send and the receive. */ 654 /* Swap the send and the receive. */
@@ -605,8 +660,44 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
605 rep.th.ack = 1; 660 rep.th.ack = 1;
606 rep.th.window = htons(win); 661 rep.th.window = htons(win);
607 662
663#ifdef CONFIG_TCP_MD5SIG
664 /*
665 * The SKB holds an imcoming packet, but may not have a valid ->sk
666 * pointer. This is especially the case when we're dealing with a
667 * TIME_WAIT ack, because the sk structure is long gone, and only
668 * the tcp_timewait_sock remains. So the md5 key is stashed in that
669 * structure, and we use it in preference. I believe that (twsk ||
670 * skb->sk) holds true, but we program defensively.
671 */
672 if (!twsk && skb->sk) {
673 key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr);
674 } else if (twsk && twsk->tw_md5_keylen) {
675 tw_key.key = twsk->tw_md5_key;
676 tw_key.keylen = twsk->tw_md5_keylen;
677 key = &tw_key;
678 } else
679 key = NULL;
680
681 if (key) {
682 int offset = (ts) ? 3 : 0;
683
684 rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
685 (TCPOPT_NOP << 16) |
686 (TCPOPT_MD5SIG << 8) |
687 TCPOLEN_MD5SIG);
688 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
689 rep.th.doff = arg.iov[0].iov_len/4;
690
691 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
692 key,
693 skb->nh.iph->daddr,
694 skb->nh.iph->saddr,
695 &rep.th, IPPROTO_TCP,
696 arg.iov[0].iov_len);
697 }
698#endif
608 arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, 699 arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr,
609 skb->nh.iph->saddr, /*XXX*/ 700 skb->nh.iph->saddr, /* XXX */
610 arg.iov[0].iov_len, IPPROTO_TCP, 0); 701 arg.iov[0].iov_len, IPPROTO_TCP, 0);
611 arg.csumoffset = offsetof(struct tcphdr, check) / 2; 702 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
612 703
@@ -618,17 +709,20 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
618static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) 709static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
619{ 710{
620 struct inet_timewait_sock *tw = inet_twsk(sk); 711 struct inet_timewait_sock *tw = inet_twsk(sk);
621 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); 712 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
622 713
623 tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, 714 tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
624 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); 715 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
716 tcptw->tw_ts_recent);
625 717
626 inet_twsk_put(tw); 718 inet_twsk_put(tw);
627} 719}
628 720
629static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) 721static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
722 struct request_sock *req)
630{ 723{
631 tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, 724 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
725 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
632 req->ts_recent); 726 req->ts_recent);
633} 727}
634 728
@@ -662,8 +756,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
662 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, 756 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
663 ireq->rmt_addr, 757 ireq->rmt_addr,
664 ireq->opt); 758 ireq->opt);
665 if (err == NET_XMIT_CN) 759 err = net_xmit_eval(err);
666 err = 0;
667 } 760 }
668 761
669out: 762out:
@@ -715,7 +808,423 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk,
715 return dopt; 808 return dopt;
716} 809}
717 810
718struct request_sock_ops tcp_request_sock_ops = { 811#ifdef CONFIG_TCP_MD5SIG
812/*
813 * RFC2385 MD5 checksumming requires a mapping of
814 * IP address->MD5 Key.
815 * We need to maintain these in the sk structure.
816 */
817
818/* Find the Key structure for an address. */
819static struct tcp_md5sig_key *
820 tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
821{
822 struct tcp_sock *tp = tcp_sk(sk);
823 int i;
824
825 if (!tp->md5sig_info || !tp->md5sig_info->entries4)
826 return NULL;
827 for (i = 0; i < tp->md5sig_info->entries4; i++) {
828 if (tp->md5sig_info->keys4[i].addr == addr)
829 return (struct tcp_md5sig_key *)
830 &tp->md5sig_info->keys4[i];
831 }
832 return NULL;
833}
834
835struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
836 struct sock *addr_sk)
837{
838 return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr);
839}
840
841EXPORT_SYMBOL(tcp_v4_md5_lookup);
842
843static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
844 struct request_sock *req)
845{
846 return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
847}
848
849/* This can be called on a newly created socket, from other files */
850int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
851 u8 *newkey, u8 newkeylen)
852{
853 /* Add Key to the list */
854 struct tcp4_md5sig_key *key;
855 struct tcp_sock *tp = tcp_sk(sk);
856 struct tcp4_md5sig_key *keys;
857
858 key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr);
859 if (key) {
860 /* Pre-existing entry - just update that one. */
861 kfree(key->key);
862 key->key = newkey;
863 key->keylen = newkeylen;
864 } else {
865 struct tcp_md5sig_info *md5sig;
866
867 if (!tp->md5sig_info) {
868 tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
869 GFP_ATOMIC);
870 if (!tp->md5sig_info) {
871 kfree(newkey);
872 return -ENOMEM;
873 }
874 }
875 if (tcp_alloc_md5sig_pool() == NULL) {
876 kfree(newkey);
877 return -ENOMEM;
878 }
879 md5sig = tp->md5sig_info;
880
881 if (md5sig->alloced4 == md5sig->entries4) {
882 keys = kmalloc((sizeof(*keys) *
883 (md5sig->entries4 + 1)), GFP_ATOMIC);
884 if (!keys) {
885 kfree(newkey);
886 tcp_free_md5sig_pool();
887 return -ENOMEM;
888 }
889
890 if (md5sig->entries4)
891 memcpy(keys, md5sig->keys4,
892 sizeof(*keys) * md5sig->entries4);
893
894 /* Free old key list, and reference new one */
895 if (md5sig->keys4)
896 kfree(md5sig->keys4);
897 md5sig->keys4 = keys;
898 md5sig->alloced4++;
899 }
900 md5sig->entries4++;
901 md5sig->keys4[md5sig->entries4 - 1].addr = addr;
902 md5sig->keys4[md5sig->entries4 - 1].key = newkey;
903 md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen;
904 }
905 return 0;
906}
907
908EXPORT_SYMBOL(tcp_v4_md5_do_add);
909
910static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
911 u8 *newkey, u8 newkeylen)
912{
913 return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr,
914 newkey, newkeylen);
915}
916
917int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
918{
919 struct tcp_sock *tp = tcp_sk(sk);
920 int i;
921
922 for (i = 0; i < tp->md5sig_info->entries4; i++) {
923 if (tp->md5sig_info->keys4[i].addr == addr) {
924 /* Free the key */
925 kfree(tp->md5sig_info->keys4[i].key);
926 tp->md5sig_info->entries4--;
927
928 if (tp->md5sig_info->entries4 == 0) {
929 kfree(tp->md5sig_info->keys4);
930 tp->md5sig_info->keys4 = NULL;
931 } else if (tp->md5sig_info->entries4 != i) {
932 /* Need to do some manipulation */
933 memcpy(&tp->md5sig_info->keys4[i],
934 &tp->md5sig_info->keys4[i+1],
935 (tp->md5sig_info->entries4 - i) *
936 sizeof(struct tcp4_md5sig_key));
937 }
938 tcp_free_md5sig_pool();
939 return 0;
940 }
941 }
942 return -ENOENT;
943}
944
945EXPORT_SYMBOL(tcp_v4_md5_do_del);
946
947static void tcp_v4_clear_md5_list(struct sock *sk)
948{
949 struct tcp_sock *tp = tcp_sk(sk);
950
951 /* Free each key, then the set of key keys,
952 * the crypto element, and then decrement our
953 * hold on the last resort crypto.
954 */
955 if (tp->md5sig_info->entries4) {
956 int i;
957 for (i = 0; i < tp->md5sig_info->entries4; i++)
958 kfree(tp->md5sig_info->keys4[i].key);
959 tp->md5sig_info->entries4 = 0;
960 tcp_free_md5sig_pool();
961 }
962 if (tp->md5sig_info->keys4) {
963 kfree(tp->md5sig_info->keys4);
964 tp->md5sig_info->keys4 = NULL;
965 tp->md5sig_info->alloced4 = 0;
966 }
967}
968
969static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
970 int optlen)
971{
972 struct tcp_md5sig cmd;
973 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
974 u8 *newkey;
975
976 if (optlen < sizeof(cmd))
977 return -EINVAL;
978
979 if (copy_from_user(&cmd, optval, sizeof(cmd)))
980 return -EFAULT;
981
982 if (sin->sin_family != AF_INET)
983 return -EINVAL;
984
985 if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
986 if (!tcp_sk(sk)->md5sig_info)
987 return -ENOENT;
988 return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
989 }
990
991 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
992 return -EINVAL;
993
994 if (!tcp_sk(sk)->md5sig_info) {
995 struct tcp_sock *tp = tcp_sk(sk);
996 struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
997
998 if (!p)
999 return -EINVAL;
1000
1001 tp->md5sig_info = p;
1002
1003 }
1004
1005 newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
1006 if (!newkey)
1007 return -ENOMEM;
1008 return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
1009 newkey, cmd.tcpm_keylen);
1010}
1011
1012static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1013 __be32 saddr, __be32 daddr,
1014 struct tcphdr *th, int protocol,
1015 int tcplen)
1016{
1017 struct scatterlist sg[4];
1018 __u16 data_len;
1019 int block = 0;
1020 __sum16 old_checksum;
1021 struct tcp_md5sig_pool *hp;
1022 struct tcp4_pseudohdr *bp;
1023 struct hash_desc *desc;
1024 int err;
1025 unsigned int nbytes = 0;
1026
1027 /*
1028 * Okay, so RFC2385 is turned on for this connection,
1029 * so we need to generate the MD5 hash for the packet now.
1030 */
1031
1032 hp = tcp_get_md5sig_pool();
1033 if (!hp)
1034 goto clear_hash_noput;
1035
1036 bp = &hp->md5_blk.ip4;
1037 desc = &hp->md5_desc;
1038
1039 /*
1040 * 1. the TCP pseudo-header (in the order: source IP address,
1041 * destination IP address, zero-padded protocol number, and
1042 * segment length)
1043 */
1044 bp->saddr = saddr;
1045 bp->daddr = daddr;
1046 bp->pad = 0;
1047 bp->protocol = protocol;
1048 bp->len = htons(tcplen);
1049 sg_set_buf(&sg[block++], bp, sizeof(*bp));
1050 nbytes += sizeof(*bp);
1051
1052 /* 2. the TCP header, excluding options, and assuming a
1053 * checksum of zero/
1054 */
1055 old_checksum = th->check;
1056 th->check = 0;
1057 sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
1058 nbytes += sizeof(struct tcphdr);
1059
1060 /* 3. the TCP segment data (if any) */
1061 data_len = tcplen - (th->doff << 2);
1062 if (data_len > 0) {
1063 unsigned char *data = (unsigned char *)th + (th->doff << 2);
1064 sg_set_buf(&sg[block++], data, data_len);
1065 nbytes += data_len;
1066 }
1067
1068 /* 4. an independently-specified key or password, known to both
1069 * TCPs and presumably connection-specific
1070 */
1071 sg_set_buf(&sg[block++], key->key, key->keylen);
1072 nbytes += key->keylen;
1073
1074 /* Now store the Hash into the packet */
1075 err = crypto_hash_init(desc);
1076 if (err)
1077 goto clear_hash;
1078 err = crypto_hash_update(desc, sg, nbytes);
1079 if (err)
1080 goto clear_hash;
1081 err = crypto_hash_final(desc, md5_hash);
1082 if (err)
1083 goto clear_hash;
1084
1085 /* Reset header, and free up the crypto */
1086 tcp_put_md5sig_pool();
1087 th->check = old_checksum;
1088
1089out:
1090 return 0;
1091clear_hash:
1092 tcp_put_md5sig_pool();
1093clear_hash_noput:
1094 memset(md5_hash, 0, 16);
1095 goto out;
1096}
1097
1098int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1099 struct sock *sk,
1100 struct dst_entry *dst,
1101 struct request_sock *req,
1102 struct tcphdr *th, int protocol,
1103 int tcplen)
1104{
1105 __be32 saddr, daddr;
1106
1107 if (sk) {
1108 saddr = inet_sk(sk)->saddr;
1109 daddr = inet_sk(sk)->daddr;
1110 } else {
1111 struct rtable *rt = (struct rtable *)dst;
1112 BUG_ON(!rt);
1113 saddr = rt->rt_src;
1114 daddr = rt->rt_dst;
1115 }
1116 return tcp_v4_do_calc_md5_hash(md5_hash, key,
1117 saddr, daddr,
1118 th, protocol, tcplen);
1119}
1120
1121EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
1122
1123static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
1124{
1125 /*
1126 * This gets called for each TCP segment that arrives
1127 * so we want to be efficient.
1128 * We have 3 drop cases:
1129 * o No MD5 hash and one expected.
1130 * o MD5 hash and we're not expecting one.
1131 * o MD5 hash and its wrong.
1132 */
1133 __u8 *hash_location = NULL;
1134 struct tcp_md5sig_key *hash_expected;
1135 struct iphdr *iph = skb->nh.iph;
1136 struct tcphdr *th = skb->h.th;
1137 int length = (th->doff << 2) - sizeof(struct tcphdr);
1138 int genhash;
1139 unsigned char *ptr;
1140 unsigned char newhash[16];
1141
1142 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
1143
1144 /*
1145 * If the TCP option length is less than the TCP_MD5SIG
1146 * option length, then we can shortcut
1147 */
1148 if (length < TCPOLEN_MD5SIG) {
1149 if (hash_expected)
1150 return 1;
1151 else
1152 return 0;
1153 }
1154
1155 /* Okay, we can't shortcut - we have to grub through the options */
1156 ptr = (unsigned char *)(th + 1);
1157 while (length > 0) {
1158 int opcode = *ptr++;
1159 int opsize;
1160
1161 switch (opcode) {
1162 case TCPOPT_EOL:
1163 goto done_opts;
1164 case TCPOPT_NOP:
1165 length--;
1166 continue;
1167 default:
1168 opsize = *ptr++;
1169 if (opsize < 2)
1170 goto done_opts;
1171 if (opsize > length)
1172 goto done_opts;
1173
1174 if (opcode == TCPOPT_MD5SIG) {
1175 hash_location = ptr;
1176 goto done_opts;
1177 }
1178 }
1179 ptr += opsize-2;
1180 length -= opsize;
1181 }
1182done_opts:
1183 /* We've parsed the options - do we have a hash? */
1184 if (!hash_expected && !hash_location)
1185 return 0;
1186
1187 if (hash_expected && !hash_location) {
1188 LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
1189 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
1190 NIPQUAD(iph->saddr), ntohs(th->source),
1191 NIPQUAD(iph->daddr), ntohs(th->dest));
1192 return 1;
1193 }
1194
1195 if (!hash_expected && hash_location) {
1196 LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
1197 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
1198 NIPQUAD(iph->saddr), ntohs(th->source),
1199 NIPQUAD(iph->daddr), ntohs(th->dest));
1200 return 1;
1201 }
1202
1203 /* Okay, so this is hash_expected and hash_location -
1204 * so we need to calculate the checksum.
1205 */
1206 genhash = tcp_v4_do_calc_md5_hash(newhash,
1207 hash_expected,
1208 iph->saddr, iph->daddr,
1209 th, sk->sk_protocol,
1210 skb->len);
1211
1212 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
1213 if (net_ratelimit()) {
1214 printk(KERN_INFO "MD5 Hash failed for "
1215 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
1216 NIPQUAD(iph->saddr), ntohs(th->source),
1217 NIPQUAD(iph->daddr), ntohs(th->dest),
1218 genhash ? " tcp_v4_calc_md5_hash failed" : "");
1219 }
1220 return 1;
1221 }
1222 return 0;
1223}
1224
1225#endif
1226
1227struct request_sock_ops tcp_request_sock_ops __read_mostly = {
719 .family = PF_INET, 1228 .family = PF_INET,
720 .obj_size = sizeof(struct tcp_request_sock), 1229 .obj_size = sizeof(struct tcp_request_sock),
721 .rtx_syn_ack = tcp_v4_send_synack, 1230 .rtx_syn_ack = tcp_v4_send_synack,
@@ -724,9 +1233,16 @@ struct request_sock_ops tcp_request_sock_ops = {
724 .send_reset = tcp_v4_send_reset, 1233 .send_reset = tcp_v4_send_reset,
725}; 1234};
726 1235
1236#ifdef CONFIG_TCP_MD5SIG
1237static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
1238 .md5_lookup = tcp_v4_reqsk_md5_lookup,
1239};
1240#endif
1241
727static struct timewait_sock_ops tcp_timewait_sock_ops = { 1242static struct timewait_sock_ops tcp_timewait_sock_ops = {
728 .twsk_obj_size = sizeof(struct tcp_timewait_sock), 1243 .twsk_obj_size = sizeof(struct tcp_timewait_sock),
729 .twsk_unique = tcp_twsk_unique, 1244 .twsk_unique = tcp_twsk_unique,
1245 .twsk_destructor= tcp_twsk_destructor,
730}; 1246};
731 1247
732int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) 1248int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
@@ -774,6 +1290,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
774 if (!req) 1290 if (!req)
775 goto drop; 1291 goto drop;
776 1292
1293#ifdef CONFIG_TCP_MD5SIG
1294 tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
1295#endif
1296
777 tcp_clear_options(&tmp_opt); 1297 tcp_clear_options(&tmp_opt);
778 tmp_opt.mss_clamp = 536; 1298 tmp_opt.mss_clamp = 536;
779 tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; 1299 tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss;
@@ -859,7 +1379,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
859 goto drop_and_free; 1379 goto drop_and_free;
860 } 1380 }
861 1381
862 isn = tcp_v4_init_sequence(sk, skb); 1382 isn = tcp_v4_init_sequence(skb);
863 } 1383 }
864 tcp_rsk(req)->snt_isn = isn; 1384 tcp_rsk(req)->snt_isn = isn;
865 1385
@@ -892,6 +1412,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
892 struct inet_sock *newinet; 1412 struct inet_sock *newinet;
893 struct tcp_sock *newtp; 1413 struct tcp_sock *newtp;
894 struct sock *newsk; 1414 struct sock *newsk;
1415#ifdef CONFIG_TCP_MD5SIG
1416 struct tcp_md5sig_key *key;
1417#endif
895 1418
896 if (sk_acceptq_is_full(sk)) 1419 if (sk_acceptq_is_full(sk))
897 goto exit_overflow; 1420 goto exit_overflow;
@@ -926,6 +1449,22 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
926 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 1449 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
927 tcp_initialize_rcv_mss(newsk); 1450 tcp_initialize_rcv_mss(newsk);
928 1451
1452#ifdef CONFIG_TCP_MD5SIG
1453 /* Copy over the MD5 key from the original socket */
1454 if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) {
1455 /*
1456 * We're using one, so create a matching key
1457 * on the newsk structure. If we fail to get
1458 * memory, then we end up not copying the key
1459 * across. Shucks.
1460 */
1461 char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
1462 if (newkey != NULL)
1463 tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
1464 newkey, key->keylen);
1465 }
1466#endif
1467
929 __inet_hash(&tcp_hashinfo, newsk, 0); 1468 __inet_hash(&tcp_hashinfo, newsk, 0);
930 __inet_inherit_port(&tcp_hashinfo, sk, newsk); 1469 __inet_inherit_port(&tcp_hashinfo, sk, newsk);
931 1470
@@ -971,7 +1510,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
971 return sk; 1510 return sk;
972} 1511}
973 1512
974static int tcp_v4_checksum_init(struct sk_buff *skb) 1513static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
975{ 1514{
976 if (skb->ip_summed == CHECKSUM_COMPLETE) { 1515 if (skb->ip_summed == CHECKSUM_COMPLETE) {
977 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, 1516 if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr,
@@ -1001,10 +1540,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb)
1001 */ 1540 */
1002int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) 1541int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
1003{ 1542{
1543 struct sock *rsk;
1544#ifdef CONFIG_TCP_MD5SIG
1545 /*
1546 * We really want to reject the packet as early as possible
1547 * if:
1548 * o We're expecting an MD5'd packet and this is no MD5 tcp option
1549 * o There is an MD5 option and we're not expecting one
1550 */
1551 if (tcp_v4_inbound_md5_hash(sk, skb))
1552 goto discard;
1553#endif
1554
1004 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ 1555 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1005 TCP_CHECK_TIMER(sk); 1556 TCP_CHECK_TIMER(sk);
1006 if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) 1557 if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) {
1558 rsk = sk;
1007 goto reset; 1559 goto reset;
1560 }
1008 TCP_CHECK_TIMER(sk); 1561 TCP_CHECK_TIMER(sk);
1009 return 0; 1562 return 0;
1010 } 1563 }
@@ -1018,20 +1571,24 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
1018 goto discard; 1571 goto discard;
1019 1572
1020 if (nsk != sk) { 1573 if (nsk != sk) {
1021 if (tcp_child_process(sk, nsk, skb)) 1574 if (tcp_child_process(sk, nsk, skb)) {
1575 rsk = nsk;
1022 goto reset; 1576 goto reset;
1577 }
1023 return 0; 1578 return 0;
1024 } 1579 }
1025 } 1580 }
1026 1581
1027 TCP_CHECK_TIMER(sk); 1582 TCP_CHECK_TIMER(sk);
1028 if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) 1583 if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) {
1584 rsk = sk;
1029 goto reset; 1585 goto reset;
1586 }
1030 TCP_CHECK_TIMER(sk); 1587 TCP_CHECK_TIMER(sk);
1031 return 0; 1588 return 0;
1032 1589
1033reset: 1590reset:
1034 tcp_v4_send_reset(skb); 1591 tcp_v4_send_reset(rsk, skb);
1035discard: 1592discard:
1036 kfree_skb(skb); 1593 kfree_skb(skb);
1037 /* Be careful here. If this function gets more complicated and 1594 /* Be careful here. If this function gets more complicated and
@@ -1140,7 +1697,7 @@ no_tcp_socket:
1140bad_packet: 1697bad_packet:
1141 TCP_INC_STATS_BH(TCP_MIB_INERRS); 1698 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1142 } else { 1699 } else {
1143 tcp_v4_send_reset(skb); 1700 tcp_v4_send_reset(NULL, skb);
1144 } 1701 }
1145 1702
1146discard_it: 1703discard_it:
@@ -1263,6 +1820,15 @@ struct inet_connection_sock_af_ops ipv4_specific = {
1263#endif 1820#endif
1264}; 1821};
1265 1822
1823#ifdef CONFIG_TCP_MD5SIG
1824static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
1825 .md5_lookup = tcp_v4_md5_lookup,
1826 .calc_md5_hash = tcp_v4_calc_md5_hash,
1827 .md5_add = tcp_v4_md5_add_func,
1828 .md5_parse = tcp_v4_parse_md5_keys,
1829};
1830#endif
1831
1266/* NOTE: A lot of things set to zero explicitly by call to 1832/* NOTE: A lot of things set to zero explicitly by call to
1267 * sk_alloc() so need not be done here. 1833 * sk_alloc() so need not be done here.
1268 */ 1834 */
@@ -1302,6 +1868,9 @@ static int tcp_v4_init_sock(struct sock *sk)
1302 1868
1303 icsk->icsk_af_ops = &ipv4_specific; 1869 icsk->icsk_af_ops = &ipv4_specific;
1304 icsk->icsk_sync_mss = tcp_sync_mss; 1870 icsk->icsk_sync_mss = tcp_sync_mss;
1871#ifdef CONFIG_TCP_MD5SIG
1872 tp->af_specific = &tcp_sock_ipv4_specific;
1873#endif
1305 1874
1306 sk->sk_sndbuf = sysctl_tcp_wmem[1]; 1875 sk->sk_sndbuf = sysctl_tcp_wmem[1];
1307 sk->sk_rcvbuf = sysctl_tcp_rmem[1]; 1876 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
@@ -1325,6 +1894,15 @@ int tcp_v4_destroy_sock(struct sock *sk)
1325 /* Cleans up our, hopefully empty, out_of_order_queue. */ 1894 /* Cleans up our, hopefully empty, out_of_order_queue. */
1326 __skb_queue_purge(&tp->out_of_order_queue); 1895 __skb_queue_purge(&tp->out_of_order_queue);
1327 1896
1897#ifdef CONFIG_TCP_MD5SIG
1898 /* Clean up the MD5 key list, if any */
1899 if (tp->md5sig_info) {
1900 tcp_v4_clear_md5_list(sk);
1901 kfree(tp->md5sig_info);
1902 tp->md5sig_info = NULL;
1903 }
1904#endif
1905
1328#ifdef CONFIG_NET_DMA 1906#ifdef CONFIG_NET_DMA
1329 /* Cleans up our sk_async_wait_queue */ 1907 /* Cleans up our sk_async_wait_queue */
1330 __skb_queue_purge(&sk->sk_async_wait_queue); 1908 __skb_queue_purge(&sk->sk_async_wait_queue);
@@ -1385,7 +1963,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
1385 if (st->state == TCP_SEQ_STATE_OPENREQ) { 1963 if (st->state == TCP_SEQ_STATE_OPENREQ) {
1386 struct request_sock *req = cur; 1964 struct request_sock *req = cur;
1387 1965
1388 icsk = inet_csk(st->syn_wait_sk); 1966 icsk = inet_csk(st->syn_wait_sk);
1389 req = req->dl_next; 1967 req = req->dl_next;
1390 while (1) { 1968 while (1) {
1391 while (req) { 1969 while (req) {
@@ -1395,7 +1973,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
1395 } 1973 }
1396 req = req->dl_next; 1974 req = req->dl_next;
1397 } 1975 }
1398 if (++st->sbucket >= TCP_SYNQ_HSIZE) 1976 if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
1399 break; 1977 break;
1400get_req: 1978get_req:
1401 req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; 1979 req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
@@ -1543,7 +2121,7 @@ static void *established_get_idx(struct seq_file *seq, loff_t pos)
1543 while (rc && pos) { 2121 while (rc && pos) {
1544 rc = established_get_next(seq, rc); 2122 rc = established_get_next(seq, rc);
1545 --pos; 2123 --pos;
1546 } 2124 }
1547 return rc; 2125 return rc;
1548} 2126}
1549 2127
@@ -1672,7 +2250,7 @@ int tcp_proc_register(struct tcp_seq_afinfo *afinfo)
1672 afinfo->seq_fops->read = seq_read; 2250 afinfo->seq_fops->read = seq_read;
1673 afinfo->seq_fops->llseek = seq_lseek; 2251 afinfo->seq_fops->llseek = seq_lseek;
1674 afinfo->seq_fops->release = seq_release_private; 2252 afinfo->seq_fops->release = seq_release_private;
1675 2253
1676 p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); 2254 p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops);
1677 if (p) 2255 if (p)
1678 p->data = afinfo; 2256 p->data = afinfo;
@@ -1686,7 +2264,7 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
1686 if (!afinfo) 2264 if (!afinfo)
1687 return; 2265 return;
1688 proc_net_remove(afinfo->name); 2266 proc_net_remove(afinfo->name);
1689 memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); 2267 memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
1690} 2268}
1691 2269
1692static void get_openreq4(struct sock *sk, struct request_sock *req, 2270static void get_openreq4(struct sock *sk, struct request_sock *req,
@@ -1721,8 +2299,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
1721 struct tcp_sock *tp = tcp_sk(sp); 2299 struct tcp_sock *tp = tcp_sk(sp);
1722 const struct inet_connection_sock *icsk = inet_csk(sp); 2300 const struct inet_connection_sock *icsk = inet_csk(sp);
1723 struct inet_sock *inet = inet_sk(sp); 2301 struct inet_sock *inet = inet_sk(sp);
1724 unsigned int dest = inet->daddr; 2302 __be32 dest = inet->daddr;
1725 unsigned int src = inet->rcv_saddr; 2303 __be32 src = inet->rcv_saddr;
1726 __u16 destp = ntohs(inet->dport); 2304 __u16 destp = ntohs(inet->dport);
1727 __u16 srcp = ntohs(inet->sport); 2305 __u16 srcp = ntohs(inet->sport);
1728 2306
@@ -1744,7 +2322,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
1744 "%08X %5d %8d %lu %d %p %u %u %u %u %d", 2322 "%08X %5d %8d %lu %d %p %u %u %u %u %d",
1745 i, src, srcp, dest, destp, sp->sk_state, 2323 i, src, srcp, dest, destp, sp->sk_state,
1746 tp->write_seq - tp->snd_una, 2324 tp->write_seq - tp->snd_una,
1747 (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), 2325 sp->sk_state == TCP_LISTEN ? sp->sk_ack_backlog :
2326 (tp->rcv_nxt - tp->copied_seq),
1748 timer_active, 2327 timer_active,
1749 jiffies_to_clock_t(timer_expires - jiffies), 2328 jiffies_to_clock_t(timer_expires - jiffies),
1750 icsk->icsk_retransmits, 2329 icsk->icsk_retransmits,
@@ -1759,7 +2338,8 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i)
1759 tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh); 2338 tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
1760} 2339}
1761 2340
1762static void get_timewait4_sock(struct inet_timewait_sock *tw, char *tmpbuf, int i) 2341static void get_timewait4_sock(struct inet_timewait_sock *tw,
2342 char *tmpbuf, int i)
1763{ 2343{
1764 __be32 dest, src; 2344 __be32 dest, src;
1765 __u16 destp, srcp; 2345 __u16 destp, srcp;
@@ -1872,7 +2452,8 @@ struct proto tcp_prot = {
1872 2452
1873void __init tcp_v4_init(struct net_proto_family *ops) 2453void __init tcp_v4_init(struct net_proto_family *ops)
1874{ 2454{
1875 if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW, IPPROTO_TCP) < 0) 2455 if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
2456 IPPROTO_TCP) < 0)
1876 panic("Failed to create the TCP control socket.\n"); 2457 panic("Failed to create the TCP control socket.\n");
1877} 2458}
1878 2459
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index af7b2c986b1f..4a3889dd1943 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -305,6 +305,28 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
305 tw->tw_ipv6only = np->ipv6only; 305 tw->tw_ipv6only = np->ipv6only;
306 } 306 }
307#endif 307#endif
308
309#ifdef CONFIG_TCP_MD5SIG
310 /*
311 * The timewait bucket does not have the key DB from the
312 * sock structure. We just make a quick copy of the
313 * md5 key being used (if indeed we are using one)
314 * so the timewait ack generating code has the key.
315 */
316 do {
317 struct tcp_md5sig_key *key;
318 memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key));
319 tcptw->tw_md5_keylen = 0;
320 key = tp->af_specific->md5_lookup(sk, sk);
321 if (key != NULL) {
322 memcpy(&tcptw->tw_md5_key, key->key, key->keylen);
323 tcptw->tw_md5_keylen = key->keylen;
324 if (tcp_alloc_md5sig_pool() == NULL)
325 BUG();
326 }
327 } while(0);
328#endif
329
308 /* Linkage updates. */ 330 /* Linkage updates. */
309 __inet_twsk_hashdance(tw, sk, &tcp_hashinfo); 331 __inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
310 332
@@ -328,14 +350,24 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
328 * socket up. We've got bigger problems than 350 * socket up. We've got bigger problems than
329 * non-graceful socket closings. 351 * non-graceful socket closings.
330 */ 352 */
331 if (net_ratelimit()) 353 LIMIT_NETDEBUG(KERN_INFO "TCP: time wait bucket table overflow\n");
332 printk(KERN_INFO "TCP: time wait bucket table overflow\n");
333 } 354 }
334 355
335 tcp_update_metrics(sk); 356 tcp_update_metrics(sk);
336 tcp_done(sk); 357 tcp_done(sk);
337} 358}
338 359
360void tcp_twsk_destructor(struct sock *sk)
361{
362#ifdef CONFIG_TCP_MD5SIG
363 struct tcp_timewait_sock *twsk = tcp_twsk(sk);
364 if (twsk->tw_md5_keylen)
365 tcp_put_md5sig_pool();
366#endif
367}
368
369EXPORT_SYMBOL_GPL(tcp_twsk_destructor);
370
339/* This is not only more efficient than what we used to do, it eliminates 371/* This is not only more efficient than what we used to do, it eliminates
340 * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM 372 * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
341 * 373 *
@@ -434,6 +466,11 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
434 newtp->rx_opt.ts_recent_stamp = 0; 466 newtp->rx_opt.ts_recent_stamp = 0;
435 newtp->tcp_header_len = sizeof(struct tcphdr); 467 newtp->tcp_header_len = sizeof(struct tcphdr);
436 } 468 }
469#ifdef CONFIG_TCP_MD5SIG
470 newtp->md5sig_info = NULL; /*XXX*/
471 if (newtp->af_specific->md5_lookup(sk, newsk))
472 newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
473#endif
437 if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len) 474 if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len)
438 newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; 475 newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
439 newtp->rx_opt.mss_clamp = req->mss; 476 newtp->rx_opt.mss_clamp = req->mss;
@@ -454,7 +491,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
454 struct request_sock **prev) 491 struct request_sock **prev)
455{ 492{
456 struct tcphdr *th = skb->h.th; 493 struct tcphdr *th = skb->h.th;
457 u32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); 494 __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
458 int paws_reject = 0; 495 int paws_reject = 0;
459 struct tcp_options_received tmp_opt; 496 struct tcp_options_received tmp_opt;
460 struct sock *child; 497 struct sock *child;
@@ -616,6 +653,30 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
616 req, NULL); 653 req, NULL);
617 if (child == NULL) 654 if (child == NULL)
618 goto listen_overflow; 655 goto listen_overflow;
656#ifdef CONFIG_TCP_MD5SIG
657 else {
658 /* Copy over the MD5 key from the original socket */
659 struct tcp_md5sig_key *key;
660 struct tcp_sock *tp = tcp_sk(sk);
661 key = tp->af_specific->md5_lookup(sk, child);
662 if (key != NULL) {
663 /*
664 * We're using one, so create a matching key on the
665 * newsk structure. If we fail to get memory then we
666 * end up not copying the key across. Shucks.
667 */
668 char *newkey = kmemdup(key->key, key->keylen,
669 GFP_ATOMIC);
670 if (newkey) {
671 if (!tcp_alloc_md5sig_pool())
672 BUG();
673 tp->af_specific->md5_add(child, child,
674 newkey,
675 key->keylen);
676 }
677 }
678 }
679#endif
619 680
620 inet_csk_reqsk_queue_unlink(sk, req, prev); 681 inet_csk_reqsk_queue_unlink(sk, req, prev);
621 inet_csk_reqsk_queue_removed(sk, req); 682 inet_csk_reqsk_queue_removed(sk, req);
@@ -632,7 +693,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
632 embryonic_reset: 693 embryonic_reset:
633 NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS); 694 NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS);
634 if (!(flg & TCP_FLAG_RST)) 695 if (!(flg & TCP_FLAG_RST))
635 req->rsk_ops->send_reset(skb); 696 req->rsk_ops->send_reset(sk, skb);
636 697
637 inet_csk_reqsk_queue_drop(sk, req, prev); 698 inet_csk_reqsk_queue_drop(sk, req, prev);
638 return NULL; 699 return NULL;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ca406157724c..32c1a972fa31 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -270,7 +270,7 @@ static u16 tcp_select_window(struct sock *sk)
270} 270}
271 271
272static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, 272static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
273 __u32 tstamp) 273 __u32 tstamp, __u8 **md5_hash)
274{ 274{
275 if (tp->rx_opt.tstamp_ok) { 275 if (tp->rx_opt.tstamp_ok) {
276 *ptr++ = htonl((TCPOPT_NOP << 24) | 276 *ptr++ = htonl((TCPOPT_NOP << 24) |
@@ -298,16 +298,29 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp,
298 tp->rx_opt.eff_sacks--; 298 tp->rx_opt.eff_sacks--;
299 } 299 }
300 } 300 }
301#ifdef CONFIG_TCP_MD5SIG
302 if (md5_hash) {
303 *ptr++ = htonl((TCPOPT_NOP << 24) |
304 (TCPOPT_NOP << 16) |
305 (TCPOPT_MD5SIG << 8) |
306 TCPOLEN_MD5SIG);
307 *md5_hash = (__u8 *)ptr;
308 }
309#endif
301} 310}
302 311
303/* Construct a tcp options header for a SYN or SYN_ACK packet. 312/* Construct a tcp options header for a SYN or SYN_ACK packet.
304 * If this is every changed make sure to change the definition of 313 * If this is every changed make sure to change the definition of
305 * MAX_SYN_SIZE to match the new maximum number of options that you 314 * MAX_SYN_SIZE to match the new maximum number of options that you
306 * can generate. 315 * can generate.
316 *
317 * Note - that with the RFC2385 TCP option, we make room for the
318 * 16 byte MD5 hash. This will be filled in later, so the pointer for the
319 * location to be filled is passed back up.
307 */ 320 */
308static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, 321static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
309 int offer_wscale, int wscale, __u32 tstamp, 322 int offer_wscale, int wscale, __u32 tstamp,
310 __u32 ts_recent) 323 __u32 ts_recent, __u8 **md5_hash)
311{ 324{
312 /* We always get an MSS option. 325 /* We always get an MSS option.
313 * The option bytes which will be seen in normal data 326 * The option bytes which will be seen in normal data
@@ -346,6 +359,20 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack,
346 (TCPOPT_WINDOW << 16) | 359 (TCPOPT_WINDOW << 16) |
347 (TCPOLEN_WINDOW << 8) | 360 (TCPOLEN_WINDOW << 8) |
348 (wscale)); 361 (wscale));
362#ifdef CONFIG_TCP_MD5SIG
363 /*
364 * If MD5 is enabled, then we set the option, and include the size
365 * (always 18). The actual MD5 hash is added just before the
366 * packet is sent.
367 */
368 if (md5_hash) {
369 *ptr++ = htonl((TCPOPT_NOP << 24) |
370 (TCPOPT_NOP << 16) |
371 (TCPOPT_MD5SIG << 8) |
372 TCPOLEN_MD5SIG);
373 *md5_hash = (__u8 *) ptr;
374 }
375#endif
349} 376}
350 377
351/* This routine actually transmits TCP packets queued in by 378/* This routine actually transmits TCP packets queued in by
@@ -366,6 +393,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
366 struct tcp_sock *tp; 393 struct tcp_sock *tp;
367 struct tcp_skb_cb *tcb; 394 struct tcp_skb_cb *tcb;
368 int tcp_header_size; 395 int tcp_header_size;
396#ifdef CONFIG_TCP_MD5SIG
397 struct tcp_md5sig_key *md5;
398 __u8 *md5_hash_location;
399#endif
369 struct tcphdr *th; 400 struct tcphdr *th;
370 int sysctl_flags; 401 int sysctl_flags;
371 int err; 402 int err;
@@ -424,9 +455,18 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
424 if (tcp_packets_in_flight(tp) == 0) 455 if (tcp_packets_in_flight(tp) == 0)
425 tcp_ca_event(sk, CA_EVENT_TX_START); 456 tcp_ca_event(sk, CA_EVENT_TX_START);
426 457
458#ifdef CONFIG_TCP_MD5SIG
459 /*
460 * Are we doing MD5 on this segment? If so - make
461 * room for it.
462 */
463 md5 = tp->af_specific->md5_lookup(sk, sk);
464 if (md5)
465 tcp_header_size += TCPOLEN_MD5SIG_ALIGNED;
466#endif
467
427 th = (struct tcphdr *) skb_push(skb, tcp_header_size); 468 th = (struct tcphdr *) skb_push(skb, tcp_header_size);
428 skb->h.th = th; 469 skb->h.th = th;
429 skb_set_owner_w(skb, sk);
430 470
431 /* Build TCP header and checksum it. */ 471 /* Build TCP header and checksum it. */
432 th->source = inet->sport; 472 th->source = inet->sport;
@@ -461,13 +501,34 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
461 (sysctl_flags & SYSCTL_FLAG_WSCALE), 501 (sysctl_flags & SYSCTL_FLAG_WSCALE),
462 tp->rx_opt.rcv_wscale, 502 tp->rx_opt.rcv_wscale,
463 tcb->when, 503 tcb->when,
464 tp->rx_opt.ts_recent); 504 tp->rx_opt.ts_recent,
505
506#ifdef CONFIG_TCP_MD5SIG
507 md5 ? &md5_hash_location :
508#endif
509 NULL);
465 } else { 510 } else {
466 tcp_build_and_update_options((__be32 *)(th + 1), 511 tcp_build_and_update_options((__be32 *)(th + 1),
467 tp, tcb->when); 512 tp, tcb->when,
513#ifdef CONFIG_TCP_MD5SIG
514 md5 ? &md5_hash_location :
515#endif
516 NULL);
468 TCP_ECN_send(sk, tp, skb, tcp_header_size); 517 TCP_ECN_send(sk, tp, skb, tcp_header_size);
469 } 518 }
470 519
520#ifdef CONFIG_TCP_MD5SIG
521 /* Calculate the MD5 hash, as we have all we need now */
522 if (md5) {
523 tp->af_specific->calc_md5_hash(md5_hash_location,
524 md5,
525 sk, NULL, NULL,
526 skb->h.th,
527 sk->sk_protocol,
528 skb->len);
529 }
530#endif
531
471 icsk->icsk_af_ops->send_check(sk, skb->len, skb); 532 icsk->icsk_af_ops->send_check(sk, skb->len, skb);
472 533
473 if (likely(tcb->flags & TCPCB_FLAG_ACK)) 534 if (likely(tcb->flags & TCPCB_FLAG_ACK))
@@ -479,19 +540,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
479 if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) 540 if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq)
480 TCP_INC_STATS(TCP_MIB_OUTSEGS); 541 TCP_INC_STATS(TCP_MIB_OUTSEGS);
481 542
482 err = icsk->icsk_af_ops->queue_xmit(skb, 0); 543 err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0);
483 if (likely(err <= 0)) 544 if (likely(err <= 0))
484 return err; 545 return err;
485 546
486 tcp_enter_cwr(sk); 547 tcp_enter_cwr(sk);
487 548
488 /* NET_XMIT_CN is special. It does not guarantee, 549 return net_xmit_eval(err);
489 * that this packet is lost. It tells that device
490 * is about to start to drop packets or already
491 * drops some packets of the same priority and
492 * invokes us to send less aggressively.
493 */
494 return err == NET_XMIT_CN ? 0 : err;
495 550
496#undef SYSCTL_FLAG_TSTAMPS 551#undef SYSCTL_FLAG_TSTAMPS
497#undef SYSCTL_FLAG_WSCALE 552#undef SYSCTL_FLAG_WSCALE
@@ -847,6 +902,11 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed)
847 mss_now -= (TCPOLEN_SACK_BASE_ALIGNED + 902 mss_now -= (TCPOLEN_SACK_BASE_ALIGNED +
848 (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK)); 903 (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK));
849 904
905#ifdef CONFIG_TCP_MD5SIG
906 if (tp->af_specific->md5_lookup(sk, sk))
907 mss_now -= TCPOLEN_MD5SIG_ALIGNED;
908#endif
909
850 xmit_size_goal = mss_now; 910 xmit_size_goal = mss_now;
851 911
852 if (doing_tso) { 912 if (doing_tso) {
@@ -2040,6 +2100,10 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2040 struct tcphdr *th; 2100 struct tcphdr *th;
2041 int tcp_header_size; 2101 int tcp_header_size;
2042 struct sk_buff *skb; 2102 struct sk_buff *skb;
2103#ifdef CONFIG_TCP_MD5SIG
2104 struct tcp_md5sig_key *md5;
2105 __u8 *md5_hash_location;
2106#endif
2043 2107
2044 skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); 2108 skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC);
2045 if (skb == NULL) 2109 if (skb == NULL)
@@ -2055,6 +2119,13 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2055 (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) + 2119 (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
2056 /* SACK_PERM is in the place of NOP NOP of TS */ 2120 /* SACK_PERM is in the place of NOP NOP of TS */
2057 ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0)); 2121 ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
2122
2123#ifdef CONFIG_TCP_MD5SIG
2124 /* Are we doing MD5 on this segment? If so - make room for it */
2125 md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req);
2126 if (md5)
2127 tcp_header_size += TCPOLEN_MD5SIG_ALIGNED;
2128#endif
2058 skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size); 2129 skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
2059 2130
2060 memset(th, 0, sizeof(struct tcphdr)); 2131 memset(th, 0, sizeof(struct tcphdr));
@@ -2092,11 +2163,29 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2092 tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok, 2163 tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
2093 ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale, 2164 ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
2094 TCP_SKB_CB(skb)->when, 2165 TCP_SKB_CB(skb)->when,
2095 req->ts_recent); 2166 req->ts_recent,
2167 (
2168#ifdef CONFIG_TCP_MD5SIG
2169 md5 ? &md5_hash_location :
2170#endif
2171 NULL)
2172 );
2096 2173
2097 skb->csum = 0; 2174 skb->csum = 0;
2098 th->doff = (tcp_header_size >> 2); 2175 th->doff = (tcp_header_size >> 2);
2099 TCP_INC_STATS(TCP_MIB_OUTSEGS); 2176 TCP_INC_STATS(TCP_MIB_OUTSEGS);
2177
2178#ifdef CONFIG_TCP_MD5SIG
2179 /* Okay, we have all we need - do the md5 hash if needed */
2180 if (md5) {
2181 tp->af_specific->calc_md5_hash(md5_hash_location,
2182 md5,
2183 NULL, dst, req,
2184 skb->h.th, sk->sk_protocol,
2185 skb->len);
2186 }
2187#endif
2188
2100 return skb; 2189 return skb;
2101} 2190}
2102 2191
@@ -2115,6 +2204,11 @@ static void tcp_connect_init(struct sock *sk)
2115 tp->tcp_header_len = sizeof(struct tcphdr) + 2204 tp->tcp_header_len = sizeof(struct tcphdr) +
2116 (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0); 2205 (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0);
2117 2206
2207#ifdef CONFIG_TCP_MD5SIG
2208 if (tp->af_specific->md5_lookup(sk, sk) != NULL)
2209 tp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
2210#endif
2211
2118 /* If user gave his TCP_MAXSEG, record it to clamp */ 2212 /* If user gave his TCP_MAXSEG, record it to clamp */
2119 if (tp->rx_opt.user_mss) 2213 if (tp->rx_opt.user_mss)
2120 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; 2214 tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
index 4be336f17883..f230eeecf092 100644
--- a/net/ipv4/tcp_probe.c
+++ b/net/ipv4/tcp_probe.c
@@ -156,6 +156,8 @@ static __init int tcpprobe_init(void)
156 init_waitqueue_head(&tcpw.wait); 156 init_waitqueue_head(&tcpw.wait);
157 spin_lock_init(&tcpw.lock); 157 spin_lock_init(&tcpw.lock);
158 tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); 158 tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
159 if (IS_ERR(tcpw.fifo))
160 return PTR_ERR(tcpw.fifo);
159 161
160 if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) 162 if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
161 goto err0; 163 goto err0;
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index fb09ade5897b..3355c276b611 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -297,7 +297,7 @@ static void tcp_retransmit_timer(struct sock *sk)
297 if (net_ratelimit()) { 297 if (net_ratelimit()) {
298 struct inet_sock *inet = inet_sk(sk); 298 struct inet_sock *inet = inet_sk(sk);
299 printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n", 299 printk(KERN_DEBUG "TCP: Treason uncloaked! Peer %u.%u.%u.%u:%u/%u shrinks window %u:%u. Repaired.\n",
300 NIPQUAD(inet->daddr), htons(inet->dport), 300 NIPQUAD(inet->daddr), ntohs(inet->dport),
301 inet->num, tp->snd_una, tp->snd_nxt); 301 inet->num, tp->snd_una, tp->snd_nxt);
302 } 302 }
303#endif 303#endif
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index a3b7aa015a2f..ddc4bcc5785e 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -42,8 +42,8 @@
42 * with V_PARAM_SHIFT bits to the right of the binary point. 42 * with V_PARAM_SHIFT bits to the right of the binary point.
43 */ 43 */
44#define V_PARAM_SHIFT 1 44#define V_PARAM_SHIFT 1
45static int alpha = 1<<V_PARAM_SHIFT; 45static int alpha = 2<<V_PARAM_SHIFT;
46static int beta = 3<<V_PARAM_SHIFT; 46static int beta = 4<<V_PARAM_SHIFT;
47static int gamma = 1<<V_PARAM_SHIFT; 47static int gamma = 1<<V_PARAM_SHIFT;
48 48
49module_param(alpha, int, 0644); 49module_param(alpha, int, 0644);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 865d75214a9a..035915fc9ed3 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -92,22 +92,16 @@
92#include <linux/timer.h> 92#include <linux/timer.h>
93#include <linux/mm.h> 93#include <linux/mm.h>
94#include <linux/inet.h> 94#include <linux/inet.h>
95#include <linux/ipv6.h>
96#include <linux/netdevice.h> 95#include <linux/netdevice.h>
97#include <net/snmp.h>
98#include <net/ip.h>
99#include <net/tcp_states.h> 96#include <net/tcp_states.h>
100#include <net/protocol.h>
101#include <linux/skbuff.h> 97#include <linux/skbuff.h>
102#include <linux/proc_fs.h> 98#include <linux/proc_fs.h>
103#include <linux/seq_file.h> 99#include <linux/seq_file.h>
104#include <net/sock.h>
105#include <net/udp.h>
106#include <net/icmp.h> 100#include <net/icmp.h>
107#include <net/route.h> 101#include <net/route.h>
108#include <net/inet_common.h>
109#include <net/checksum.h> 102#include <net/checksum.h>
110#include <net/xfrm.h> 103#include <net/xfrm.h>
104#include "udp_impl.h"
111 105
112/* 106/*
113 * Snmp MIB for the UDP layer 107 * Snmp MIB for the UDP layer
@@ -120,26 +114,30 @@ DEFINE_RWLOCK(udp_hash_lock);
120 114
121static int udp_port_rover; 115static int udp_port_rover;
122 116
123static inline int udp_lport_inuse(u16 num) 117static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[])
124{ 118{
125 struct sock *sk; 119 struct sock *sk;
126 struct hlist_node *node; 120 struct hlist_node *node;
127 121
128 sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) 122 sk_for_each(sk, node, &udptable[num & (UDP_HTABLE_SIZE - 1)])
129 if (inet_sk(sk)->num == num) 123 if (inet_sk(sk)->num == num)
130 return 1; 124 return 1;
131 return 0; 125 return 0;
132} 126}
133 127
134/** 128/**
135 * udp_get_port - common port lookup for IPv4 and IPv6 129 * __udp_lib_get_port - UDP/-Lite port lookup for IPv4 and IPv6
136 * 130 *
137 * @sk: socket struct in question 131 * @sk: socket struct in question
138 * @snum: port number to look up 132 * @snum: port number to look up
133 * @udptable: hash list table, must be of UDP_HTABLE_SIZE
134 * @port_rover: pointer to record of last unallocated port
139 * @saddr_comp: AF-dependent comparison of bound local IP addresses 135 * @saddr_comp: AF-dependent comparison of bound local IP addresses
140 */ 136 */
141int udp_get_port(struct sock *sk, unsigned short snum, 137int __udp_lib_get_port(struct sock *sk, unsigned short snum,
142 int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2)) 138 struct hlist_head udptable[], int *port_rover,
139 int (*saddr_comp)(const struct sock *sk1,
140 const struct sock *sk2 ) )
143{ 141{
144 struct hlist_node *node; 142 struct hlist_node *node;
145 struct hlist_head *head; 143 struct hlist_head *head;
@@ -150,15 +148,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
150 if (snum == 0) { 148 if (snum == 0) {
151 int best_size_so_far, best, result, i; 149 int best_size_so_far, best, result, i;
152 150
153 if (udp_port_rover > sysctl_local_port_range[1] || 151 if (*port_rover > sysctl_local_port_range[1] ||
154 udp_port_rover < sysctl_local_port_range[0]) 152 *port_rover < sysctl_local_port_range[0])
155 udp_port_rover = sysctl_local_port_range[0]; 153 *port_rover = sysctl_local_port_range[0];
156 best_size_so_far = 32767; 154 best_size_so_far = 32767;
157 best = result = udp_port_rover; 155 best = result = *port_rover;
158 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { 156 for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
159 int size; 157 int size;
160 158
161 head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; 159 head = &udptable[result & (UDP_HTABLE_SIZE - 1)];
162 if (hlist_empty(head)) { 160 if (hlist_empty(head)) {
163 if (result > sysctl_local_port_range[1]) 161 if (result > sysctl_local_port_range[1])
164 result = sysctl_local_port_range[0] + 162 result = sysctl_local_port_range[0] +
@@ -179,15 +177,15 @@ int udp_get_port(struct sock *sk, unsigned short snum,
179 result = sysctl_local_port_range[0] 177 result = sysctl_local_port_range[0]
180 + ((result - sysctl_local_port_range[0]) & 178 + ((result - sysctl_local_port_range[0]) &
181 (UDP_HTABLE_SIZE - 1)); 179 (UDP_HTABLE_SIZE - 1));
182 if (!udp_lport_inuse(result)) 180 if (! __udp_lib_lport_inuse(result, udptable))
183 break; 181 break;
184 } 182 }
185 if (i >= (1 << 16) / UDP_HTABLE_SIZE) 183 if (i >= (1 << 16) / UDP_HTABLE_SIZE)
186 goto fail; 184 goto fail;
187gotit: 185gotit:
188 udp_port_rover = snum = result; 186 *port_rover = snum = result;
189 } else { 187 } else {
190 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; 188 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
191 189
192 sk_for_each(sk2, node, head) 190 sk_for_each(sk2, node, head)
193 if (inet_sk(sk2)->num == snum && 191 if (inet_sk(sk2)->num == snum &&
@@ -195,12 +193,12 @@ gotit:
195 (!sk2->sk_reuse || !sk->sk_reuse) && 193 (!sk2->sk_reuse || !sk->sk_reuse) &&
196 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if 194 (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if
197 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && 195 || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
198 (*saddr_cmp)(sk, sk2) ) 196 (*saddr_comp)(sk, sk2) )
199 goto fail; 197 goto fail;
200 } 198 }
201 inet_sk(sk)->num = snum; 199 inet_sk(sk)->num = snum;
202 if (sk_unhashed(sk)) { 200 if (sk_unhashed(sk)) {
203 head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; 201 head = &udptable[snum & (UDP_HTABLE_SIZE - 1)];
204 sk_add_node(sk, head); 202 sk_add_node(sk, head);
205 sock_prot_inc_use(sk->sk_prot); 203 sock_prot_inc_use(sk->sk_prot);
206 } 204 }
@@ -210,7 +208,13 @@ fail:
210 return error; 208 return error;
211} 209}
212 210
213static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) 211__inline__ int udp_get_port(struct sock *sk, unsigned short snum,
212 int (*scmp)(const struct sock *, const struct sock *))
213{
214 return __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
215}
216
217inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
214{ 218{
215 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); 219 struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
216 220
@@ -224,34 +228,20 @@ static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
224 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); 228 return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
225} 229}
226 230
227
228static void udp_v4_hash(struct sock *sk)
229{
230 BUG();
231}
232
233static void udp_v4_unhash(struct sock *sk)
234{
235 write_lock_bh(&udp_hash_lock);
236 if (sk_del_node_init(sk)) {
237 inet_sk(sk)->num = 0;
238 sock_prot_dec_use(sk->sk_prot);
239 }
240 write_unlock_bh(&udp_hash_lock);
241}
242
243/* UDP is nearly always wildcards out the wazoo, it makes no sense to try 231/* UDP is nearly always wildcards out the wazoo, it makes no sense to try
244 * harder than this. -DaveM 232 * harder than this. -DaveM
245 */ 233 */
246static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport, 234static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,
247 __be32 daddr, __be16 dport, int dif) 235 __be32 daddr, __be16 dport,
236 int dif, struct hlist_head udptable[])
248{ 237{
249 struct sock *sk, *result = NULL; 238 struct sock *sk, *result = NULL;
250 struct hlist_node *node; 239 struct hlist_node *node;
251 unsigned short hnum = ntohs(dport); 240 unsigned short hnum = ntohs(dport);
252 int badness = -1; 241 int badness = -1;
253 242
254 sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { 243 read_lock(&udp_hash_lock);
244 sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) {
255 struct inet_sock *inet = inet_sk(sk); 245 struct inet_sock *inet = inet_sk(sk);
256 246
257 if (inet->num == hnum && !ipv6_only_sock(sk)) { 247 if (inet->num == hnum && !ipv6_only_sock(sk)) {
@@ -285,20 +275,10 @@ static struct sock *udp_v4_lookup_longway(__be32 saddr, __be16 sport,
285 } 275 }
286 } 276 }
287 } 277 }
288 return result; 278 if (result)
289} 279 sock_hold(result);
290
291static __inline__ struct sock *udp_v4_lookup(__be32 saddr, __be16 sport,
292 __be32 daddr, __be16 dport, int dif)
293{
294 struct sock *sk;
295
296 read_lock(&udp_hash_lock);
297 sk = udp_v4_lookup_longway(saddr, sport, daddr, dport, dif);
298 if (sk)
299 sock_hold(sk);
300 read_unlock(&udp_hash_lock); 280 read_unlock(&udp_hash_lock);
301 return sk; 281 return result;
302} 282}
303 283
304static inline struct sock *udp_v4_mcast_next(struct sock *sk, 284static inline struct sock *udp_v4_mcast_next(struct sock *sk,
@@ -340,7 +320,7 @@ found:
340 * to find the appropriate port. 320 * to find the appropriate port.
341 */ 321 */
342 322
343void udp_err(struct sk_buff *skb, u32 info) 323void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
344{ 324{
345 struct inet_sock *inet; 325 struct inet_sock *inet;
346 struct iphdr *iph = (struct iphdr*)skb->data; 326 struct iphdr *iph = (struct iphdr*)skb->data;
@@ -351,7 +331,8 @@ void udp_err(struct sk_buff *skb, u32 info)
351 int harderr; 331 int harderr;
352 int err; 332 int err;
353 333
354 sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex); 334 sk = __udp4_lib_lookup(iph->daddr, uh->dest, iph->saddr, uh->source,
335 skb->dev->ifindex, udptable );
355 if (sk == NULL) { 336 if (sk == NULL) {
356 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS); 337 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
357 return; /* No socket for error */ 338 return; /* No socket for error */
@@ -405,6 +386,11 @@ out:
405 sock_put(sk); 386 sock_put(sk);
406} 387}
407 388
389__inline__ void udp_err(struct sk_buff *skb, u32 info)
390{
391 return __udp4_lib_err(skb, info, udp_hash);
392}
393
408/* 394/*
409 * Throw away all pending data and cancel the corking. Socket is locked. 395 * Throw away all pending data and cancel the corking. Socket is locked.
410 */ 396 */
@@ -419,16 +405,58 @@ static void udp_flush_pending_frames(struct sock *sk)
419 } 405 }
420} 406}
421 407
408/**
409 * udp4_hwcsum_outgoing - handle outgoing HW checksumming
410 * @sk: socket we are sending on
411 * @skb: sk_buff containing the filled-in UDP header
412 * (checksum field must be zeroed out)
413 */
414static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
415 __be32 src, __be32 dst, int len )
416{
417 unsigned int offset;
418 struct udphdr *uh = skb->h.uh;
419 __wsum csum = 0;
420
421 if (skb_queue_len(&sk->sk_write_queue) == 1) {
422 /*
423 * Only one fragment on the socket.
424 */
425 skb->csum_offset = offsetof(struct udphdr, check);
426 uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
427 } else {
428 /*
429 * HW-checksum won't work as there are two or more
430 * fragments on the socket so that all csums of sk_buffs
431 * should be together
432 */
433 offset = skb->h.raw - skb->data;
434 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
435
436 skb->ip_summed = CHECKSUM_NONE;
437
438 skb_queue_walk(&sk->sk_write_queue, skb) {
439 csum = csum_add(csum, skb->csum);
440 }
441
442 uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);
443 if (uh->check == 0)
444 uh->check = CSUM_MANGLED_0;
445 }
446}
447
422/* 448/*
423 * Push out all pending data as one UDP datagram. Socket is locked. 449 * Push out all pending data as one UDP datagram. Socket is locked.
424 */ 450 */
425static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) 451static int udp_push_pending_frames(struct sock *sk)
426{ 452{
453 struct udp_sock *up = udp_sk(sk);
427 struct inet_sock *inet = inet_sk(sk); 454 struct inet_sock *inet = inet_sk(sk);
428 struct flowi *fl = &inet->cork.fl; 455 struct flowi *fl = &inet->cork.fl;
429 struct sk_buff *skb; 456 struct sk_buff *skb;
430 struct udphdr *uh; 457 struct udphdr *uh;
431 int err = 0; 458 int err = 0;
459 __wsum csum = 0;
432 460
433 /* Grab the skbuff where UDP header space exists. */ 461 /* Grab the skbuff where UDP header space exists. */
434 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) 462 if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
@@ -443,52 +471,28 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
443 uh->len = htons(up->len); 471 uh->len = htons(up->len);
444 uh->check = 0; 472 uh->check = 0;
445 473
446 if (sk->sk_no_check == UDP_CSUM_NOXMIT) { 474 if (up->pcflag) /* UDP-Lite */
475 csum = udplite_csum_outgoing(sk, skb);
476
477 else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */
478
447 skb->ip_summed = CHECKSUM_NONE; 479 skb->ip_summed = CHECKSUM_NONE;
448 goto send; 480 goto send;
449 }
450 481
451 if (skb_queue_len(&sk->sk_write_queue) == 1) { 482 } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
452 /*
453 * Only one fragment on the socket.
454 */
455 if (skb->ip_summed == CHECKSUM_PARTIAL) {
456 skb->csum = offsetof(struct udphdr, check);
457 uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
458 up->len, IPPROTO_UDP, 0);
459 } else {
460 skb->csum = csum_partial((char *)uh,
461 sizeof(struct udphdr), skb->csum);
462 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
463 up->len, IPPROTO_UDP, skb->csum);
464 if (uh->check == 0)
465 uh->check = -1;
466 }
467 } else {
468 unsigned int csum = 0;
469 /*
470 * HW-checksum won't work as there are two or more
471 * fragments on the socket so that all csums of sk_buffs
472 * should be together.
473 */
474 if (skb->ip_summed == CHECKSUM_PARTIAL) {
475 int offset = (unsigned char *)uh - skb->data;
476 skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
477 483
478 skb->ip_summed = CHECKSUM_NONE; 484 udp4_hwcsum_outgoing(sk, skb, fl->fl4_src,fl->fl4_dst, up->len);
479 } else { 485 goto send;
480 skb->csum = csum_partial((char *)uh, 486
481 sizeof(struct udphdr), skb->csum); 487 } else /* `normal' UDP */
482 } 488 csum = udp_csum_outgoing(sk, skb);
489
490 /* add protocol-dependent pseudo-header */
491 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
492 sk->sk_protocol, csum );
493 if (uh->check == 0)
494 uh->check = CSUM_MANGLED_0;
483 495
484 skb_queue_walk(&sk->sk_write_queue, skb) {
485 csum = csum_add(csum, skb->csum);
486 }
487 uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst,
488 up->len, IPPROTO_UDP, csum);
489 if (uh->check == 0)
490 uh->check = -1;
491 }
492send: 496send:
493 err = ip_push_pending_frames(sk); 497 err = ip_push_pending_frames(sk);
494out: 498out:
@@ -497,12 +501,6 @@ out:
497 return err; 501 return err;
498} 502}
499 503
500
501static unsigned short udp_check(struct udphdr *uh, int len, __be32 saddr, __be32 daddr, unsigned long base)
502{
503 return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base));
504}
505
506int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 504int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
507 size_t len) 505 size_t len)
508{ 506{
@@ -516,8 +514,9 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
516 __be32 daddr, faddr, saddr; 514 __be32 daddr, faddr, saddr;
517 __be16 dport; 515 __be16 dport;
518 u8 tos; 516 u8 tos;
519 int err; 517 int err, is_udplite = up->pcflag;
520 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; 518 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
519 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
521 520
522 if (len > 0xFFFF) 521 if (len > 0xFFFF)
523 return -EMSGSIZE; 522 return -EMSGSIZE;
@@ -622,7 +621,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
622 { .daddr = faddr, 621 { .daddr = faddr,
623 .saddr = saddr, 622 .saddr = saddr,
624 .tos = tos } }, 623 .tos = tos } },
625 .proto = IPPROTO_UDP, 624 .proto = sk->sk_protocol,
626 .uli_u = { .ports = 625 .uli_u = { .ports =
627 { .sport = inet->sport, 626 { .sport = inet->sport,
628 .dport = dport } } }; 627 .dport = dport } } };
@@ -668,13 +667,14 @@ back_from_confirm:
668 667
669do_append_data: 668do_append_data:
670 up->len += ulen; 669 up->len += ulen;
671 err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, 670 getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
672 sizeof(struct udphdr), &ipc, rt, 671 err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
672 sizeof(struct udphdr), &ipc, rt,
673 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); 673 corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
674 if (err) 674 if (err)
675 udp_flush_pending_frames(sk); 675 udp_flush_pending_frames(sk);
676 else if (!corkreq) 676 else if (!corkreq)
677 err = udp_push_pending_frames(sk, up); 677 err = udp_push_pending_frames(sk);
678 else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) 678 else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
679 up->pending = 0; 679 up->pending = 0;
680 release_sock(sk); 680 release_sock(sk);
@@ -684,7 +684,7 @@ out:
684 if (free) 684 if (free)
685 kfree(ipc.opt); 685 kfree(ipc.opt);
686 if (!err) { 686 if (!err) {
687 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); 687 UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite);
688 return len; 688 return len;
689 } 689 }
690 /* 690 /*
@@ -695,7 +695,7 @@ out:
695 * seems like overkill. 695 * seems like overkill.
696 */ 696 */
697 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { 697 if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
698 UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); 698 UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite);
699 } 699 }
700 return err; 700 return err;
701 701
@@ -707,8 +707,8 @@ do_confirm:
707 goto out; 707 goto out;
708} 708}
709 709
710static int udp_sendpage(struct sock *sk, struct page *page, int offset, 710int udp_sendpage(struct sock *sk, struct page *page, int offset,
711 size_t size, int flags) 711 size_t size, int flags)
712{ 712{
713 struct udp_sock *up = udp_sk(sk); 713 struct udp_sock *up = udp_sk(sk);
714 int ret; 714 int ret;
@@ -747,7 +747,7 @@ static int udp_sendpage(struct sock *sk, struct page *page, int offset,
747 747
748 up->len += size; 748 up->len += size;
749 if (!(up->corkflag || (flags&MSG_MORE))) 749 if (!(up->corkflag || (flags&MSG_MORE)))
750 ret = udp_push_pending_frames(sk, up); 750 ret = udp_push_pending_frames(sk);
751 if (!ret) 751 if (!ret)
752 ret = size; 752 ret = size;
753out: 753out:
@@ -795,29 +795,18 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
795 return(0); 795 return(0);
796} 796}
797 797
798static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
799{
800 return __skb_checksum_complete(skb);
801}
802
803static __inline__ int udp_checksum_complete(struct sk_buff *skb)
804{
805 return skb->ip_summed != CHECKSUM_UNNECESSARY &&
806 __udp_checksum_complete(skb);
807}
808
809/* 798/*
810 * This should be easy, if there is something there we 799 * This should be easy, if there is something there we
811 * return it, otherwise we block. 800 * return it, otherwise we block.
812 */ 801 */
813 802
814static int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 803int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
815 size_t len, int noblock, int flags, int *addr_len) 804 size_t len, int noblock, int flags, int *addr_len)
816{ 805{
817 struct inet_sock *inet = inet_sk(sk); 806 struct inet_sock *inet = inet_sk(sk);
818 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; 807 struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
819 struct sk_buff *skb; 808 struct sk_buff *skb;
820 int copied, err; 809 int copied, err, copy_only, is_udplite = IS_UDPLITE(sk);
821 810
822 /* 811 /*
823 * Check any passed addresses 812 * Check any passed addresses
@@ -839,15 +828,25 @@ try_again:
839 msg->msg_flags |= MSG_TRUNC; 828 msg->msg_flags |= MSG_TRUNC;
840 } 829 }
841 830
842 if (skb->ip_summed==CHECKSUM_UNNECESSARY) { 831 /*
843 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 832 * Decide whether to checksum and/or copy data.
844 copied); 833 *
845 } else if (msg->msg_flags&MSG_TRUNC) { 834 * UDP: checksum may have been computed in HW,
846 if (__udp_checksum_complete(skb)) 835 * (re-)compute it if message is truncated.
836 * UDP-Lite: always needs to checksum, no HW support.
837 */
838 copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY);
839
840 if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) {
841 if (__udp_lib_checksum_complete(skb))
847 goto csum_copy_err; 842 goto csum_copy_err;
848 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, 843 copy_only = 1;
849 copied); 844 }
850 } else { 845
846 if (copy_only)
847 err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
848 msg->msg_iov, copied );
849 else {
851 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); 850 err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
852 851
853 if (err == -EINVAL) 852 if (err == -EINVAL)
@@ -880,7 +879,7 @@ out:
880 return err; 879 return err;
881 880
882csum_copy_err: 881csum_copy_err:
883 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 882 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
884 883
885 skb_kill_datagram(sk, skb, flags); 884 skb_kill_datagram(sk, skb, flags);
886 885
@@ -912,11 +911,6 @@ int udp_disconnect(struct sock *sk, int flags)
912 return 0; 911 return 0;
913} 912}
914 913
915static void udp_close(struct sock *sk, long timeout)
916{
917 sk_common_release(sk);
918}
919
920/* return: 914/* return:
921 * 1 if the the UDP system should process it 915 * 1 if the the UDP system should process it
922 * 0 if we should drop this packet 916 * 0 if we should drop this packet
@@ -928,23 +922,32 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
928 return 1; 922 return 1;
929#else 923#else
930 struct udp_sock *up = udp_sk(sk); 924 struct udp_sock *up = udp_sk(sk);
931 struct udphdr *uh = skb->h.uh; 925 struct udphdr *uh;
932 struct iphdr *iph; 926 struct iphdr *iph;
933 int iphlen, len; 927 int iphlen, len;
934 928
935 __u8 *udpdata = (__u8 *)uh + sizeof(struct udphdr); 929 __u8 *udpdata;
936 __be32 *udpdata32 = (__be32 *)udpdata; 930 __be32 *udpdata32;
937 __u16 encap_type = up->encap_type; 931 __u16 encap_type = up->encap_type;
938 932
939 /* if we're overly short, let UDP handle it */ 933 /* if we're overly short, let UDP handle it */
940 if (udpdata > skb->tail) 934 len = skb->len - sizeof(struct udphdr);
935 if (len <= 0)
941 return 1; 936 return 1;
942 937
943 /* if this is not encapsulated socket, then just return now */ 938 /* if this is not encapsulated socket, then just return now */
944 if (!encap_type) 939 if (!encap_type)
945 return 1; 940 return 1;
946 941
947 len = skb->tail - udpdata; 942 /* If this is a paged skb, make sure we pull up
943 * whatever data we need to look at. */
944 if (!pskb_may_pull(skb, sizeof(struct udphdr) + min(len, 8)))
945 return 1;
946
947 /* Now we can get the pointers */
948 uh = skb->h.uh;
949 udpdata = (__u8 *)uh + sizeof(struct udphdr);
950 udpdata32 = (__be32 *)udpdata;
948 951
949 switch (encap_type) { 952 switch (encap_type) {
950 default: 953 default:
@@ -1013,7 +1016,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
1013 * Note that in the success and error cases, the skb is assumed to 1016 * Note that in the success and error cases, the skb is assumed to
1014 * have either been requeued or freed. 1017 * have either been requeued or freed.
1015 */ 1018 */
1016static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) 1019int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1017{ 1020{
1018 struct udp_sock *up = udp_sk(sk); 1021 struct udp_sock *up = udp_sk(sk);
1019 int rc; 1022 int rc;
@@ -1021,10 +1024,8 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1021 /* 1024 /*
1022 * Charge it to the socket, dropping if the queue is full. 1025 * Charge it to the socket, dropping if the queue is full.
1023 */ 1026 */
1024 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) { 1027 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
1025 kfree_skb(skb); 1028 goto drop;
1026 return -1;
1027 }
1028 nf_reset(skb); 1029 nf_reset(skb);
1029 1030
1030 if (up->encap_type) { 1031 if (up->encap_type) {
@@ -1048,31 +1049,68 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1048 if (ret < 0) { 1049 if (ret < 0) {
1049 /* process the ESP packet */ 1050 /* process the ESP packet */
1050 ret = xfrm4_rcv_encap(skb, up->encap_type); 1051 ret = xfrm4_rcv_encap(skb, up->encap_type);
1051 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); 1052 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
1052 return -ret; 1053 return -ret;
1053 } 1054 }
1054 /* FALLTHROUGH -- it's a UDP Packet */ 1055 /* FALLTHROUGH -- it's a UDP Packet */
1055 } 1056 }
1056 1057
1057 if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { 1058 /*
1058 if (__udp_checksum_complete(skb)) { 1059 * UDP-Lite specific tests, ignored on UDP sockets
1059 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1060 */
1060 kfree_skb(skb); 1061 if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) {
1061 return -1; 1062
1063 /*
1064 * MIB statistics other than incrementing the error count are
1065 * disabled for the following two types of errors: these depend
1066 * on the application settings, not on the functioning of the
1067 * protocol stack as such.
1068 *
1069 * RFC 3828 here recommends (sec 3.3): "There should also be a
1070 * way ... to ... at least let the receiving application block
1071 * delivery of packets with coverage values less than a value
1072 * provided by the application."
1073 */
1074 if (up->pcrlen == 0) { /* full coverage was set */
1075 LIMIT_NETDEBUG(KERN_WARNING "UDPLITE: partial coverage "
1076 "%d while full coverage %d requested\n",
1077 UDP_SKB_CB(skb)->cscov, skb->len);
1078 goto drop;
1062 } 1079 }
1080 /* The next case involves violating the min. coverage requested
1081 * by the receiver. This is subtle: if receiver wants x and x is
1082 * greater than the buffersize/MTU then receiver will complain
1083 * that it wants x while sender emits packets of smaller size y.
1084 * Therefore the above ...()->partial_cov statement is essential.
1085 */
1086 if (UDP_SKB_CB(skb)->cscov < up->pcrlen) {
1087 LIMIT_NETDEBUG(KERN_WARNING
1088 "UDPLITE: coverage %d too small, need min %d\n",
1089 UDP_SKB_CB(skb)->cscov, up->pcrlen);
1090 goto drop;
1091 }
1092 }
1093
1094 if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
1095 if (__udp_lib_checksum_complete(skb))
1096 goto drop;
1063 skb->ip_summed = CHECKSUM_UNNECESSARY; 1097 skb->ip_summed = CHECKSUM_UNNECESSARY;
1064 } 1098 }
1065 1099
1066 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { 1100 if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) {
1067 /* Note that an ENOMEM error is charged twice */ 1101 /* Note that an ENOMEM error is charged twice */
1068 if (rc == -ENOMEM) 1102 if (rc == -ENOMEM)
1069 UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); 1103 UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag);
1070 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1104 goto drop;
1071 kfree_skb(skb);
1072 return -1;
1073 } 1105 }
1074 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS); 1106
1107 UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag);
1075 return 0; 1108 return 0;
1109
1110drop:
1111 UDP_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag);
1112 kfree_skb(skb);
1113 return -1;
1076} 1114}
1077 1115
1078/* 1116/*
@@ -1081,14 +1119,16 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
1081 * Note: called only from the BH handler context, 1119 * Note: called only from the BH handler context,
1082 * so we don't need to lock the hashes. 1120 * so we don't need to lock the hashes.
1083 */ 1121 */
1084static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh, 1122static int __udp4_lib_mcast_deliver(struct sk_buff *skb,
1085 __be32 saddr, __be32 daddr) 1123 struct udphdr *uh,
1124 __be32 saddr, __be32 daddr,
1125 struct hlist_head udptable[])
1086{ 1126{
1087 struct sock *sk; 1127 struct sock *sk;
1088 int dif; 1128 int dif;
1089 1129
1090 read_lock(&udp_hash_lock); 1130 read_lock(&udp_hash_lock);
1091 sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); 1131 sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]);
1092 dif = skb->dev->ifindex; 1132 dif = skb->dev->ifindex;
1093 sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); 1133 sk = udp_v4_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif);
1094 if (sk) { 1134 if (sk) {
@@ -1122,65 +1162,75 @@ static int udp_v4_mcast_deliver(struct sk_buff *skb, struct udphdr *uh,
1122 * Otherwise, csum completion requires chacksumming packet body, 1162 * Otherwise, csum completion requires chacksumming packet body,
1123 * including udp header and folding it to skb->csum. 1163 * including udp header and folding it to skb->csum.
1124 */ 1164 */
1125static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, 1165static inline void udp4_csum_init(struct sk_buff *skb, struct udphdr *uh)
1126 unsigned short ulen, __be32 saddr, __be32 daddr)
1127{ 1166{
1128 if (uh->check == 0) { 1167 if (uh->check == 0) {
1129 skb->ip_summed = CHECKSUM_UNNECESSARY; 1168 skb->ip_summed = CHECKSUM_UNNECESSARY;
1130 } else if (skb->ip_summed == CHECKSUM_COMPLETE) { 1169 } else if (skb->ip_summed == CHECKSUM_COMPLETE) {
1131 if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) 1170 if (!csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr,
1171 skb->len, IPPROTO_UDP, skb->csum ))
1132 skb->ip_summed = CHECKSUM_UNNECESSARY; 1172 skb->ip_summed = CHECKSUM_UNNECESSARY;
1133 } 1173 }
1134 if (skb->ip_summed != CHECKSUM_UNNECESSARY) 1174 if (skb->ip_summed != CHECKSUM_UNNECESSARY)
1135 skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); 1175 skb->csum = csum_tcpudp_nofold(skb->nh.iph->saddr,
1176 skb->nh.iph->daddr,
1177 skb->len, IPPROTO_UDP, 0);
1136 /* Probably, we should checksum udp header (it should be in cache 1178 /* Probably, we should checksum udp header (it should be in cache
1137 * in any case) and data in tiny packets (< rx copybreak). 1179 * in any case) and data in tiny packets (< rx copybreak).
1138 */ 1180 */
1181
1182 /* UDP = UDP-Lite with a non-partial checksum coverage */
1183 UDP_SKB_CB(skb)->partial_cov = 0;
1139} 1184}
1140 1185
1141/* 1186/*
1142 * All we need to do is get the socket, and then do a checksum. 1187 * All we need to do is get the socket, and then do a checksum.
1143 */ 1188 */
1144 1189
1145int udp_rcv(struct sk_buff *skb) 1190int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1191 int is_udplite)
1146{ 1192{
1147 struct sock *sk; 1193 struct sock *sk;
1148 struct udphdr *uh; 1194 struct udphdr *uh = skb->h.uh;
1149 unsigned short ulen; 1195 unsigned short ulen;
1150 struct rtable *rt = (struct rtable*)skb->dst; 1196 struct rtable *rt = (struct rtable*)skb->dst;
1151 __be32 saddr = skb->nh.iph->saddr; 1197 __be32 saddr = skb->nh.iph->saddr;
1152 __be32 daddr = skb->nh.iph->daddr; 1198 __be32 daddr = skb->nh.iph->daddr;
1153 int len = skb->len;
1154 1199
1155 /* 1200 /*
1156 * Validate the packet and the UDP length. 1201 * Validate the packet.
1157 */ 1202 */
1158 if (!pskb_may_pull(skb, sizeof(struct udphdr))) 1203 if (!pskb_may_pull(skb, sizeof(struct udphdr)))
1159 goto no_header; 1204 goto drop; /* No space for header. */
1160
1161 uh = skb->h.uh;
1162 1205
1163 ulen = ntohs(uh->len); 1206 ulen = ntohs(uh->len);
1164 1207 if (ulen > skb->len)
1165 if (ulen > len || ulen < sizeof(*uh))
1166 goto short_packet; 1208 goto short_packet;
1167 1209
1168 if (pskb_trim_rcsum(skb, ulen)) 1210 if(! is_udplite ) { /* UDP validates ulen. */
1169 goto short_packet; 1211
1212 if (ulen < sizeof(*uh) || pskb_trim_rcsum(skb, ulen))
1213 goto short_packet;
1170 1214
1171 udp_checksum_init(skb, uh, ulen, saddr, daddr); 1215 udp4_csum_init(skb, uh);
1216
1217 } else { /* UDP-Lite validates cscov. */
1218 if (udplite4_csum_init(skb, uh))
1219 goto csum_error;
1220 }
1172 1221
1173 if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) 1222 if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1174 return udp_v4_mcast_deliver(skb, uh, saddr, daddr); 1223 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
1175 1224
1176 sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex); 1225 sk = __udp4_lib_lookup(saddr, uh->source, daddr, uh->dest,
1226 skb->dev->ifindex, udptable );
1177 1227
1178 if (sk != NULL) { 1228 if (sk != NULL) {
1179 int ret = udp_queue_rcv_skb(sk, skb); 1229 int ret = udp_queue_rcv_skb(sk, skb);
1180 sock_put(sk); 1230 sock_put(sk);
1181 1231
1182 /* a return value > 0 means to resubmit the input, but 1232 /* a return value > 0 means to resubmit the input, but
1183 * it it wants the return to be -protocol, or 0 1233 * it wants the return to be -protocol, or 0
1184 */ 1234 */
1185 if (ret > 0) 1235 if (ret > 0)
1186 return -ret; 1236 return -ret;
@@ -1192,10 +1242,10 @@ int udp_rcv(struct sk_buff *skb)
1192 nf_reset(skb); 1242 nf_reset(skb);
1193 1243
1194 /* No socket. Drop packet silently, if checksum is wrong */ 1244 /* No socket. Drop packet silently, if checksum is wrong */
1195 if (udp_checksum_complete(skb)) 1245 if (udp_lib_checksum_complete(skb))
1196 goto csum_error; 1246 goto csum_error;
1197 1247
1198 UDP_INC_STATS_BH(UDP_MIB_NOPORTS); 1248 UDP_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite);
1199 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); 1249 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
1200 1250
1201 /* 1251 /*
@@ -1206,36 +1256,40 @@ int udp_rcv(struct sk_buff *skb)
1206 return(0); 1256 return(0);
1207 1257
1208short_packet: 1258short_packet:
1209 LIMIT_NETDEBUG(KERN_DEBUG "UDP: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n", 1259 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: short packet: From %u.%u.%u.%u:%u %d/%d to %u.%u.%u.%u:%u\n",
1260 is_udplite? "-Lite" : "",
1210 NIPQUAD(saddr), 1261 NIPQUAD(saddr),
1211 ntohs(uh->source), 1262 ntohs(uh->source),
1212 ulen, 1263 ulen,
1213 len, 1264 skb->len,
1214 NIPQUAD(daddr), 1265 NIPQUAD(daddr),
1215 ntohs(uh->dest)); 1266 ntohs(uh->dest));
1216no_header: 1267 goto drop;
1217 UDP_INC_STATS_BH(UDP_MIB_INERRORS);
1218 kfree_skb(skb);
1219 return(0);
1220 1268
1221csum_error: 1269csum_error:
1222 /* 1270 /*
1223 * RFC1122: OK. Discards the bad packet silently (as far as 1271 * RFC1122: OK. Discards the bad packet silently (as far as
1224 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 1272 * the network is concerned, anyway) as per 4.1.3.4 (MUST).
1225 */ 1273 */
1226 LIMIT_NETDEBUG(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n", 1274 LIMIT_NETDEBUG(KERN_DEBUG "UDP%s: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
1275 is_udplite? "-Lite" : "",
1227 NIPQUAD(saddr), 1276 NIPQUAD(saddr),
1228 ntohs(uh->source), 1277 ntohs(uh->source),
1229 NIPQUAD(daddr), 1278 NIPQUAD(daddr),
1230 ntohs(uh->dest), 1279 ntohs(uh->dest),
1231 ulen); 1280 ulen);
1232drop: 1281drop:
1233 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1282 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite);
1234 kfree_skb(skb); 1283 kfree_skb(skb);
1235 return(0); 1284 return(0);
1236} 1285}
1237 1286
1238static int udp_destroy_sock(struct sock *sk) 1287__inline__ int udp_rcv(struct sk_buff *skb)
1288{
1289 return __udp4_lib_rcv(skb, udp_hash, 0);
1290}
1291
1292int udp_destroy_sock(struct sock *sk)
1239{ 1293{
1240 lock_sock(sk); 1294 lock_sock(sk);
1241 udp_flush_pending_frames(sk); 1295 udp_flush_pending_frames(sk);
@@ -1246,8 +1300,9 @@ static int udp_destroy_sock(struct sock *sk)
1246/* 1300/*
1247 * Socket option code for UDP 1301 * Socket option code for UDP
1248 */ 1302 */
1249static int do_udp_setsockopt(struct sock *sk, int level, int optname, 1303int udp_lib_setsockopt(struct sock *sk, int level, int optname,
1250 char __user *optval, int optlen) 1304 char __user *optval, int optlen,
1305 int (*push_pending_frames)(struct sock *))
1251{ 1306{
1252 struct udp_sock *up = udp_sk(sk); 1307 struct udp_sock *up = udp_sk(sk);
1253 int val; 1308 int val;
@@ -1266,7 +1321,7 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1266 } else { 1321 } else {
1267 up->corkflag = 0; 1322 up->corkflag = 0;
1268 lock_sock(sk); 1323 lock_sock(sk);
1269 udp_push_pending_frames(sk, up); 1324 (*push_pending_frames)(sk);
1270 release_sock(sk); 1325 release_sock(sk);
1271 } 1326 }
1272 break; 1327 break;
@@ -1284,6 +1339,32 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1284 } 1339 }
1285 break; 1340 break;
1286 1341
1342 /*
1343 * UDP-Lite's partial checksum coverage (RFC 3828).
1344 */
1345 /* The sender sets actual checksum coverage length via this option.
1346 * The case coverage > packet length is handled by send module. */
1347 case UDPLITE_SEND_CSCOV:
1348 if (!up->pcflag) /* Disable the option on UDP sockets */
1349 return -ENOPROTOOPT;
1350 if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
1351 val = 8;
1352 up->pcslen = val;
1353 up->pcflag |= UDPLITE_SEND_CC;
1354 break;
1355
1356 /* The receiver specifies a minimum checksum coverage value. To make
1357 * sense, this should be set to at least 8 (as done below). If zero is
1358 * used, this again means full checksum coverage. */
1359 case UDPLITE_RECV_CSCOV:
1360 if (!up->pcflag) /* Disable the option on UDP sockets */
1361 return -ENOPROTOOPT;
1362 if (val != 0 && val < 8) /* Avoid silly minimal values. */
1363 val = 8;
1364 up->pcrlen = val;
1365 up->pcflag |= UDPLITE_RECV_CC;
1366 break;
1367
1287 default: 1368 default:
1288 err = -ENOPROTOOPT; 1369 err = -ENOPROTOOPT;
1289 break; 1370 break;
@@ -1292,26 +1373,28 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
1292 return err; 1373 return err;
1293} 1374}
1294 1375
1295static int udp_setsockopt(struct sock *sk, int level, int optname, 1376int udp_setsockopt(struct sock *sk, int level, int optname,
1296 char __user *optval, int optlen) 1377 char __user *optval, int optlen)
1297{ 1378{
1298 if (level != SOL_UDP) 1379 if (level == SOL_UDP || level == SOL_UDPLITE)
1299 return ip_setsockopt(sk, level, optname, optval, optlen); 1380 return udp_lib_setsockopt(sk, level, optname, optval, optlen,
1300 return do_udp_setsockopt(sk, level, optname, optval, optlen); 1381 udp_push_pending_frames);
1382 return ip_setsockopt(sk, level, optname, optval, optlen);
1301} 1383}
1302 1384
1303#ifdef CONFIG_COMPAT 1385#ifdef CONFIG_COMPAT
1304static int compat_udp_setsockopt(struct sock *sk, int level, int optname, 1386int compat_udp_setsockopt(struct sock *sk, int level, int optname,
1305 char __user *optval, int optlen) 1387 char __user *optval, int optlen)
1306{ 1388{
1307 if (level != SOL_UDP) 1389 if (level == SOL_UDP || level == SOL_UDPLITE)
1308 return compat_ip_setsockopt(sk, level, optname, optval, optlen); 1390 return udp_lib_setsockopt(sk, level, optname, optval, optlen,
1309 return do_udp_setsockopt(sk, level, optname, optval, optlen); 1391 udp_push_pending_frames);
1392 return compat_ip_setsockopt(sk, level, optname, optval, optlen);
1310} 1393}
1311#endif 1394#endif
1312 1395
1313static int do_udp_getsockopt(struct sock *sk, int level, int optname, 1396int udp_lib_getsockopt(struct sock *sk, int level, int optname,
1314 char __user *optval, int __user *optlen) 1397 char __user *optval, int __user *optlen)
1315{ 1398{
1316 struct udp_sock *up = udp_sk(sk); 1399 struct udp_sock *up = udp_sk(sk);
1317 int val, len; 1400 int val, len;
@@ -1333,6 +1416,16 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1333 val = up->encap_type; 1416 val = up->encap_type;
1334 break; 1417 break;
1335 1418
1419 /* The following two cannot be changed on UDP sockets, the return is
1420 * always 0 (which corresponds to the full checksum coverage of UDP). */
1421 case UDPLITE_SEND_CSCOV:
1422 val = up->pcslen;
1423 break;
1424
1425 case UDPLITE_RECV_CSCOV:
1426 val = up->pcrlen;
1427 break;
1428
1336 default: 1429 default:
1337 return -ENOPROTOOPT; 1430 return -ENOPROTOOPT;
1338 }; 1431 };
@@ -1344,21 +1437,21 @@ static int do_udp_getsockopt(struct sock *sk, int level, int optname,
1344 return 0; 1437 return 0;
1345} 1438}
1346 1439
1347static int udp_getsockopt(struct sock *sk, int level, int optname, 1440int udp_getsockopt(struct sock *sk, int level, int optname,
1348 char __user *optval, int __user *optlen) 1441 char __user *optval, int __user *optlen)
1349{ 1442{
1350 if (level != SOL_UDP) 1443 if (level == SOL_UDP || level == SOL_UDPLITE)
1351 return ip_getsockopt(sk, level, optname, optval, optlen); 1444 return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1352 return do_udp_getsockopt(sk, level, optname, optval, optlen); 1445 return ip_getsockopt(sk, level, optname, optval, optlen);
1353} 1446}
1354 1447
1355#ifdef CONFIG_COMPAT 1448#ifdef CONFIG_COMPAT
1356static int compat_udp_getsockopt(struct sock *sk, int level, int optname, 1449int compat_udp_getsockopt(struct sock *sk, int level, int optname,
1357 char __user *optval, int __user *optlen) 1450 char __user *optval, int __user *optlen)
1358{ 1451{
1359 if (level != SOL_UDP) 1452 if (level == SOL_UDP || level == SOL_UDPLITE)
1360 return compat_ip_getsockopt(sk, level, optname, optval, optlen); 1453 return udp_lib_getsockopt(sk, level, optname, optval, optlen);
1361 return do_udp_getsockopt(sk, level, optname, optval, optlen); 1454 return compat_ip_getsockopt(sk, level, optname, optval, optlen);
1362} 1455}
1363#endif 1456#endif
1364/** 1457/**
@@ -1378,7 +1471,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1378{ 1471{
1379 unsigned int mask = datagram_poll(file, sock, wait); 1472 unsigned int mask = datagram_poll(file, sock, wait);
1380 struct sock *sk = sock->sk; 1473 struct sock *sk = sock->sk;
1381 1474 int is_lite = IS_UDPLITE(sk);
1475
1382 /* Check for false positives due to checksum errors */ 1476 /* Check for false positives due to checksum errors */
1383 if ( (mask & POLLRDNORM) && 1477 if ( (mask & POLLRDNORM) &&
1384 !(file->f_flags & O_NONBLOCK) && 1478 !(file->f_flags & O_NONBLOCK) &&
@@ -1388,8 +1482,8 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1388 1482
1389 spin_lock_bh(&rcvq->lock); 1483 spin_lock_bh(&rcvq->lock);
1390 while ((skb = skb_peek(rcvq)) != NULL) { 1484 while ((skb = skb_peek(rcvq)) != NULL) {
1391 if (udp_checksum_complete(skb)) { 1485 if (udp_lib_checksum_complete(skb)) {
1392 UDP_INC_STATS_BH(UDP_MIB_INERRORS); 1486 UDP_INC_STATS_BH(UDP_MIB_INERRORS, is_lite);
1393 __skb_unlink(skb, rcvq); 1487 __skb_unlink(skb, rcvq);
1394 kfree_skb(skb); 1488 kfree_skb(skb);
1395 } else { 1489 } else {
@@ -1411,7 +1505,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
1411struct proto udp_prot = { 1505struct proto udp_prot = {
1412 .name = "UDP", 1506 .name = "UDP",
1413 .owner = THIS_MODULE, 1507 .owner = THIS_MODULE,
1414 .close = udp_close, 1508 .close = udp_lib_close,
1415 .connect = ip4_datagram_connect, 1509 .connect = ip4_datagram_connect,
1416 .disconnect = udp_disconnect, 1510 .disconnect = udp_disconnect,
1417 .ioctl = udp_ioctl, 1511 .ioctl = udp_ioctl,
@@ -1422,8 +1516,8 @@ struct proto udp_prot = {
1422 .recvmsg = udp_recvmsg, 1516 .recvmsg = udp_recvmsg,
1423 .sendpage = udp_sendpage, 1517 .sendpage = udp_sendpage,
1424 .backlog_rcv = udp_queue_rcv_skb, 1518 .backlog_rcv = udp_queue_rcv_skb,
1425 .hash = udp_v4_hash, 1519 .hash = udp_lib_hash,
1426 .unhash = udp_v4_unhash, 1520 .unhash = udp_lib_unhash,
1427 .get_port = udp_v4_get_port, 1521 .get_port = udp_v4_get_port,
1428 .obj_size = sizeof(struct udp_sock), 1522 .obj_size = sizeof(struct udp_sock),
1429#ifdef CONFIG_COMPAT 1523#ifdef CONFIG_COMPAT
@@ -1442,7 +1536,7 @@ static struct sock *udp_get_first(struct seq_file *seq)
1442 1536
1443 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { 1537 for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) {
1444 struct hlist_node *node; 1538 struct hlist_node *node;
1445 sk_for_each(sk, node, &udp_hash[state->bucket]) { 1539 sk_for_each(sk, node, state->hashtable + state->bucket) {
1446 if (sk->sk_family == state->family) 1540 if (sk->sk_family == state->family)
1447 goto found; 1541 goto found;
1448 } 1542 }
@@ -1463,7 +1557,7 @@ try_again:
1463 } while (sk && sk->sk_family != state->family); 1557 } while (sk && sk->sk_family != state->family);
1464 1558
1465 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { 1559 if (!sk && ++state->bucket < UDP_HTABLE_SIZE) {
1466 sk = sk_head(&udp_hash[state->bucket]); 1560 sk = sk_head(state->hashtable + state->bucket);
1467 goto try_again; 1561 goto try_again;
1468 } 1562 }
1469 return sk; 1563 return sk;
@@ -1513,6 +1607,7 @@ static int udp_seq_open(struct inode *inode, struct file *file)
1513 if (!s) 1607 if (!s)
1514 goto out; 1608 goto out;
1515 s->family = afinfo->family; 1609 s->family = afinfo->family;
1610 s->hashtable = afinfo->hashtable;
1516 s->seq_ops.start = udp_seq_start; 1611 s->seq_ops.start = udp_seq_start;
1517 s->seq_ops.next = udp_seq_next; 1612 s->seq_ops.next = udp_seq_next;
1518 s->seq_ops.show = afinfo->seq_show; 1613 s->seq_ops.show = afinfo->seq_show;
@@ -1579,7 +1674,7 @@ static void udp4_format_sock(struct sock *sp, char *tmpbuf, int bucket)
1579 atomic_read(&sp->sk_refcnt), sp); 1674 atomic_read(&sp->sk_refcnt), sp);
1580} 1675}
1581 1676
1582static int udp4_seq_show(struct seq_file *seq, void *v) 1677int udp4_seq_show(struct seq_file *seq, void *v)
1583{ 1678{
1584 if (v == SEQ_START_TOKEN) 1679 if (v == SEQ_START_TOKEN)
1585 seq_printf(seq, "%-127s\n", 1680 seq_printf(seq, "%-127s\n",
@@ -1602,6 +1697,7 @@ static struct udp_seq_afinfo udp4_seq_afinfo = {
1602 .owner = THIS_MODULE, 1697 .owner = THIS_MODULE,
1603 .name = "udp", 1698 .name = "udp",
1604 .family = AF_INET, 1699 .family = AF_INET,
1700 .hashtable = udp_hash,
1605 .seq_show = udp4_seq_show, 1701 .seq_show = udp4_seq_show,
1606 .seq_fops = &udp4_seq_fops, 1702 .seq_fops = &udp4_seq_fops,
1607}; 1703};
@@ -1624,6 +1720,8 @@ EXPORT_SYMBOL(udp_ioctl);
1624EXPORT_SYMBOL(udp_get_port); 1720EXPORT_SYMBOL(udp_get_port);
1625EXPORT_SYMBOL(udp_prot); 1721EXPORT_SYMBOL(udp_prot);
1626EXPORT_SYMBOL(udp_sendmsg); 1722EXPORT_SYMBOL(udp_sendmsg);
1723EXPORT_SYMBOL(udp_lib_getsockopt);
1724EXPORT_SYMBOL(udp_lib_setsockopt);
1627EXPORT_SYMBOL(udp_poll); 1725EXPORT_SYMBOL(udp_poll);
1628 1726
1629#ifdef CONFIG_PROC_FS 1727#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
new file mode 100644
index 000000000000..f6f4277ba6dc
--- /dev/null
+++ b/net/ipv4/udp_impl.h
@@ -0,0 +1,38 @@
1#ifndef _UDP4_IMPL_H
2#define _UDP4_IMPL_H
3#include <net/udp.h>
4#include <net/udplite.h>
5#include <net/protocol.h>
6#include <net/inet_common.h>
7
8extern int __udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
9extern void __udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
10
11extern int __udp_lib_get_port(struct sock *sk, unsigned short snum,
12 struct hlist_head udptable[], int *port_rover,
13 int (*)(const struct sock*,const struct sock*));
14extern int ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
15
16
17extern int udp_setsockopt(struct sock *sk, int level, int optname,
18 char __user *optval, int optlen);
19extern int udp_getsockopt(struct sock *sk, int level, int optname,
20 char __user *optval, int __user *optlen);
21
22#ifdef CONFIG_COMPAT
23extern int compat_udp_setsockopt(struct sock *sk, int level, int optname,
24 char __user *optval, int optlen);
25extern int compat_udp_getsockopt(struct sock *sk, int level, int optname,
26 char __user *optval, int __user *optlen);
27#endif
28extern int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
29 size_t len, int noblock, int flags, int *addr_len);
30extern int udp_sendpage(struct sock *sk, struct page *page, int offset,
31 size_t size, int flags);
32extern int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb);
33extern int udp_destroy_sock(struct sock *sk);
34
35#ifdef CONFIG_PROC_FS
36extern int udp4_seq_show(struct seq_file *seq, void *v);
37#endif
38#endif /* _UDP4_IMPL_H */
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
new file mode 100644
index 000000000000..b28fe1edf98b
--- /dev/null
+++ b/net/ipv4/udplite.c
@@ -0,0 +1,119 @@
1/*
2 * UDPLITE An implementation of the UDP-Lite protocol (RFC 3828).
3 *
4 * Version: $Id: udplite.c,v 1.25 2006/10/19 07:22:36 gerrit Exp $
5 *
6 * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
7 *
8 * Changes:
9 * Fixes:
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15#include "udp_impl.h"
16DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly;
17
18struct hlist_head udplite_hash[UDP_HTABLE_SIZE];
19static int udplite_port_rover;
20
21int udplite_get_port(struct sock *sk, unsigned short p,
22 int (*c)(const struct sock *, const struct sock *))
23{
24 return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
25}
26
27static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
28{
29 return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
30}
31
32static int udplite_rcv(struct sk_buff *skb)
33{
34 return __udp4_lib_rcv(skb, udplite_hash, 1);
35}
36
37static void udplite_err(struct sk_buff *skb, u32 info)
38{
39 return __udp4_lib_err(skb, info, udplite_hash);
40}
41
42static struct net_protocol udplite_protocol = {
43 .handler = udplite_rcv,
44 .err_handler = udplite_err,
45 .no_policy = 1,
46};
47
48struct proto udplite_prot = {
49 .name = "UDP-Lite",
50 .owner = THIS_MODULE,
51 .close = udp_lib_close,
52 .connect = ip4_datagram_connect,
53 .disconnect = udp_disconnect,
54 .ioctl = udp_ioctl,
55 .init = udplite_sk_init,
56 .destroy = udp_destroy_sock,
57 .setsockopt = udp_setsockopt,
58 .getsockopt = udp_getsockopt,
59 .sendmsg = udp_sendmsg,
60 .recvmsg = udp_recvmsg,
61 .sendpage = udp_sendpage,
62 .backlog_rcv = udp_queue_rcv_skb,
63 .hash = udp_lib_hash,
64 .unhash = udp_lib_unhash,
65 .get_port = udplite_v4_get_port,
66 .obj_size = sizeof(struct udp_sock),
67#ifdef CONFIG_COMPAT
68 .compat_setsockopt = compat_udp_setsockopt,
69 .compat_getsockopt = compat_udp_getsockopt,
70#endif
71};
72
73static struct inet_protosw udplite4_protosw = {
74 .type = SOCK_DGRAM,
75 .protocol = IPPROTO_UDPLITE,
76 .prot = &udplite_prot,
77 .ops = &inet_dgram_ops,
78 .capability = -1,
79 .no_check = 0, /* must checksum (RFC 3828) */
80 .flags = INET_PROTOSW_PERMANENT,
81};
82
83#ifdef CONFIG_PROC_FS
84static struct file_operations udplite4_seq_fops;
85static struct udp_seq_afinfo udplite4_seq_afinfo = {
86 .owner = THIS_MODULE,
87 .name = "udplite",
88 .family = AF_INET,
89 .hashtable = udplite_hash,
90 .seq_show = udp4_seq_show,
91 .seq_fops = &udplite4_seq_fops,
92};
93#endif
94
95void __init udplite4_register(void)
96{
97 if (proto_register(&udplite_prot, 1))
98 goto out_register_err;
99
100 if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0)
101 goto out_unregister_proto;
102
103 inet_register_protosw(&udplite4_protosw);
104
105#ifdef CONFIG_PROC_FS
106 if (udp_proc_register(&udplite4_seq_afinfo)) /* udplite4_proc_init() */
107 printk(KERN_ERR "%s: Cannot register /proc!\n", __FUNCTION__);
108#endif
109 return;
110
111out_unregister_proto:
112 proto_unregister(&udplite_prot);
113out_register_err:
114 printk(KERN_CRIT "%s: Cannot add UDP-Lite protocol.\n", __FUNCTION__);
115}
116
117EXPORT_SYMBOL(udplite_hash);
118EXPORT_SYMBOL(udplite_prot);
119EXPORT_SYMBOL(udplite_get_port);
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 1bed0cdf53e3..d4107bb701b5 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -72,8 +72,8 @@ __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 u32 remote = fl->fl4_dst; 75 __be32 remote = fl->fl4_dst;
76 u32 local = fl->fl4_src; 76 __be32 local = fl->fl4_src;
77 struct flowi fl_tunnel = { 77 struct flowi fl_tunnel = {
78 .nl_u = { 78 .nl_u = {
79 .ip4_u = { 79 .ip4_u = {
@@ -199,11 +199,12 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl)
199 if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) { 199 if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
200 switch (iph->protocol) { 200 switch (iph->protocol) {
201 case IPPROTO_UDP: 201 case IPPROTO_UDP:
202 case IPPROTO_UDPLITE:
202 case IPPROTO_TCP: 203 case IPPROTO_TCP:
203 case IPPROTO_SCTP: 204 case IPPROTO_SCTP:
204 case IPPROTO_DCCP: 205 case IPPROTO_DCCP:
205 if (pskb_may_pull(skb, xprth + 4 - skb->data)) { 206 if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
206 u16 *ports = (u16 *)xprth; 207 __be16 *ports = (__be16 *)xprth;
207 208
208 fl->fl_ip_sport = ports[0]; 209 fl->fl_ip_sport = ports[0];
209 fl->fl_ip_dport = ports[1]; 210 fl->fl_ip_dport = ports[1];