aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/ipv4/fib_trie.c49
-rw-r--r--net/ipv4/netfilter/Kconfig22
-rw-r--r--net/ipv4/netfilter/Makefile5
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c51
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c806
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netbios_ns.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c327
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c6
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_pptp.c401
-rw-r--r--net/ipv4/netfilter/ip_nat_proto_gre.c214
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/tcp_minisocks.c2
-rw-r--r--net/ipv4/tcp_output.c19
-rw-r--r--net/ipv6/netfilter/ip6_tables.c52
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c81
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c88
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c73
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c90
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c88
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c83
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/packet/af_packet.c65
-rw-r--r--net/sctp/sm_statefuns.c22
28 files changed, 2002 insertions, 561 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 145f5cde96cf..b74864889670 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -120,7 +120,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
120 unsigned short vid; 120 unsigned short vid;
121 struct net_device_stats *stats; 121 struct net_device_stats *stats;
122 unsigned short vlan_TCI; 122 unsigned short vlan_TCI;
123 unsigned short proto; 123 __be16 proto;
124 124
125 /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ 125 /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
126 vlan_TCI = ntohs(vhdr->h_vlan_TCI); 126 vlan_TCI = ntohs(vhdr->h_vlan_TCI);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 069253f830c1..2d24fb400e0c 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -31,7 +31,8 @@ static inline int should_deliver(const struct net_bridge_port *p,
31 31
32int br_dev_queue_push_xmit(struct sk_buff *skb) 32int br_dev_queue_push_xmit(struct sk_buff *skb)
33{ 33{
34 if (skb->len > skb->dev->mtu) 34 /* drop mtu oversized packets except tso */
35 if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
35 kfree_skb(skb); 36 kfree_skb(skb);
36 else { 37 else {
37#ifdef CONFIG_BRIDGE_NETFILTER 38#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 1b63b4824164..50c0519cd70d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -43,7 +43,7 @@
43 * 2 of the License, or (at your option) any later version. 43 * 2 of the License, or (at your option) any later version.
44 */ 44 */
45 45
46#define VERSION "0.403" 46#define VERSION "0.404"
47 47
48#include <linux/config.h> 48#include <linux/config.h>
49#include <asm/uaccess.h> 49#include <asm/uaccess.h>
@@ -224,7 +224,7 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b)
224 Consider a node 'n' and its parent 'tp'. 224 Consider a node 'n' and its parent 'tp'.
225 225
226 If n is a leaf, every bit in its key is significant. Its presence is 226 If n is a leaf, every bit in its key is significant. Its presence is
227 necessitaded by path compression, since during a tree traversal (when 227 necessitated by path compression, since during a tree traversal (when
228 searching for a leaf - unless we are doing an insertion) we will completely 228 searching for a leaf - unless we are doing an insertion) we will completely
229 ignore all skipped bits we encounter. Thus we need to verify, at the end of 229 ignore all skipped bits we encounter. Thus we need to verify, at the end of
230 a potentially successful search, that we have indeed been walking the 230 a potentially successful search, that we have indeed been walking the
@@ -836,11 +836,12 @@ static void trie_init(struct trie *t)
836#endif 836#endif
837} 837}
838 838
839/* readside most use rcu_read_lock currently dump routines 839/* readside must use rcu_read_lock currently dump routines
840 via get_fa_head and dump */ 840 via get_fa_head and dump */
841 841
842static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) 842static struct leaf_info *find_leaf_info(struct leaf *l, int plen)
843{ 843{
844 struct hlist_head *head = &l->list;
844 struct hlist_node *node; 845 struct hlist_node *node;
845 struct leaf_info *li; 846 struct leaf_info *li;
846 847
@@ -853,7 +854,7 @@ static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
853 854
854static inline struct list_head * get_fa_head(struct leaf *l, int plen) 855static inline struct list_head * get_fa_head(struct leaf *l, int plen)
855{ 856{
856 struct leaf_info *li = find_leaf_info(&l->list, plen); 857 struct leaf_info *li = find_leaf_info(l, plen);
857 858
858 if (!li) 859 if (!li)
859 return NULL; 860 return NULL;
@@ -1085,7 +1086,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen)
1085 } 1086 }
1086 1087
1087 if (tp && tp->pos + tp->bits > 32) 1088 if (tp && tp->pos + tp->bits > 32)
1088 printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", 1089 printk(KERN_WARNING "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
1089 tp, tp->pos, tp->bits, key, plen); 1090 tp, tp->pos, tp->bits, key, plen);
1090 1091
1091 /* Rebalance the trie */ 1092 /* Rebalance the trie */
@@ -1248,7 +1249,7 @@ err:
1248} 1249}
1249 1250
1250 1251
1251/* should be clalled with rcu_read_lock */ 1252/* should be called with rcu_read_lock */
1252static inline int check_leaf(struct trie *t, struct leaf *l, 1253static inline int check_leaf(struct trie *t, struct leaf *l,
1253 t_key key, int *plen, const struct flowi *flp, 1254 t_key key, int *plen, const struct flowi *flp,
1254 struct fib_result *res) 1255 struct fib_result *res)
@@ -1590,7 +1591,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
1590 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); 1591 rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
1591 1592
1592 l = fib_find_node(t, key); 1593 l = fib_find_node(t, key);
1593 li = find_leaf_info(&l->list, plen); 1594 li = find_leaf_info(l, plen);
1594 1595
1595 list_del_rcu(&fa->fa_list); 1596 list_del_rcu(&fa->fa_list);
1596 1597
@@ -1714,7 +1715,6 @@ static int fn_trie_flush(struct fib_table *tb)
1714 1715
1715 t->revision++; 1716 t->revision++;
1716 1717
1717 rcu_read_lock();
1718 for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { 1718 for (h = 0; (l = nextleaf(t, l)) != NULL; h++) {
1719 found += trie_flush_leaf(t, l); 1719 found += trie_flush_leaf(t, l);
1720 1720
@@ -1722,7 +1722,6 @@ static int fn_trie_flush(struct fib_table *tb)
1722 trie_leaf_remove(t, ll->key); 1722 trie_leaf_remove(t, ll->key);
1723 ll = l; 1723 ll = l;
1724 } 1724 }
1725 rcu_read_unlock();
1726 1725
1727 if (ll && hlist_empty(&ll->list)) 1726 if (ll && hlist_empty(&ll->list))
1728 trie_leaf_remove(t, ll->key); 1727 trie_leaf_remove(t, ll->key);
@@ -1833,16 +1832,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi
1833 i++; 1832 i++;
1834 continue; 1833 continue;
1835 } 1834 }
1836 if (fa->fa_info->fib_nh == NULL) { 1835 BUG_ON(!fa->fa_info);
1837 printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
1838 i++;
1839 continue;
1840 }
1841 if (fa->fa_info == NULL) {
1842 printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
1843 i++;
1844 continue;
1845 }
1846 1836
1847 if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, 1837 if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
1848 cb->nlh->nlmsg_seq, 1838 cb->nlh->nlmsg_seq,
@@ -1965,7 +1955,7 @@ struct fib_table * __init fib_hash_init(int id)
1965 trie_main = t; 1955 trie_main = t;
1966 1956
1967 if (id == RT_TABLE_LOCAL) 1957 if (id == RT_TABLE_LOCAL)
1968 printk("IPv4 FIB: Using LC-trie version %s\n", VERSION); 1958 printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION);
1969 1959
1970 return tb; 1960 return tb;
1971} 1961}
@@ -2029,7 +2019,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
2029 iter->tnode = (struct tnode *) n; 2019 iter->tnode = (struct tnode *) n;
2030 iter->trie = t; 2020 iter->trie = t;
2031 iter->index = 0; 2021 iter->index = 0;
2032 iter->depth = 0; 2022 iter->depth = 1;
2033 return n; 2023 return n;
2034 } 2024 }
2035 return NULL; 2025 return NULL;
@@ -2274,11 +2264,12 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
2274 seq_puts(seq, "<local>:\n"); 2264 seq_puts(seq, "<local>:\n");
2275 else 2265 else
2276 seq_puts(seq, "<main>:\n"); 2266 seq_puts(seq, "<main>:\n");
2277 } else { 2267 }
2278 seq_indent(seq, iter->depth-1); 2268 seq_indent(seq, iter->depth-1);
2279 seq_printf(seq, " +-- %d.%d.%d.%d/%d\n", 2269 seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n",
2280 NIPQUAD(prf), tn->pos); 2270 NIPQUAD(prf), tn->pos, tn->bits, tn->full_children,
2281 } 2271 tn->empty_children);
2272
2282 } else { 2273 } else {
2283 struct leaf *l = (struct leaf *) n; 2274 struct leaf *l = (struct leaf *) n;
2284 int i; 2275 int i;
@@ -2287,7 +2278,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
2287 seq_indent(seq, iter->depth); 2278 seq_indent(seq, iter->depth);
2288 seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val)); 2279 seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val));
2289 for (i = 32; i >= 0; i--) { 2280 for (i = 32; i >= 0; i--) {
2290 struct leaf_info *li = find_leaf_info(&l->list, i); 2281 struct leaf_info *li = find_leaf_info(l, i);
2291 if (li) { 2282 if (li) {
2292 struct fib_alias *fa; 2283 struct fib_alias *fa;
2293 list_for_each_entry_rcu(fa, &li->falh, fa_list) { 2284 list_for_each_entry_rcu(fa, &li->falh, fa_list) {
@@ -2383,7 +2374,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
2383 return 0; 2374 return 0;
2384 2375
2385 for (i=32; i>=0; i--) { 2376 for (i=32; i>=0; i--) {
2386 struct leaf_info *li = find_leaf_info(&l->list, i); 2377 struct leaf_info *li = find_leaf_info(l, i);
2387 struct fib_alias *fa; 2378 struct fib_alias *fa;
2388 u32 mask, prefix; 2379 u32 mask, prefix;
2389 2380
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index e2162d270073..3cf9b451675c 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -137,6 +137,22 @@ config IP_NF_AMANDA
137 137
138 To compile it as a module, choose M here. If unsure, say Y. 138 To compile it as a module, choose M here. If unsure, say Y.
139 139
140config IP_NF_PPTP
141 tristate 'PPTP protocol support'
142 help
143 This module adds support for PPTP (Point to Point Tunnelling
144 Protocol, RFC2637) conncection tracking and NAT.
145
146 If you are running PPTP sessions over a stateful firewall or NAT
147 box, you may want to enable this feature.
148
149 Please note that not all PPTP modes of operation are supported yet.
150 For more info, read top of the file
151 net/ipv4/netfilter/ip_conntrack_pptp.c
152
153 If you want to compile it as a module, say M here and read
154 Documentation/modules.txt. If unsure, say `N'.
155
140config IP_NF_QUEUE 156config IP_NF_QUEUE
141 tristate "IP Userspace queueing via NETLINK (OBSOLETE)" 157 tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
142 help 158 help
@@ -621,6 +637,12 @@ config IP_NF_NAT_AMANDA
621 default IP_NF_NAT if IP_NF_AMANDA=y 637 default IP_NF_NAT if IP_NF_AMANDA=y
622 default m if IP_NF_AMANDA=m 638 default m if IP_NF_AMANDA=m
623 639
640config IP_NF_NAT_PPTP
641 tristate
642 depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
643 default IP_NF_NAT if IP_NF_PPTP=y
644 default m if IP_NF_PPTP=m
645
624# mangle + specific targets 646# mangle + specific targets
625config IP_NF_MANGLE 647config IP_NF_MANGLE
626 tristate "Packet mangling" 648 tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 1ba0db746817..3d45d3c0283c 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -6,6 +6,9 @@
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
7iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o 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 7iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o 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
8 8
9ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
10ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o
11
9# connection tracking 12# connection tracking
10obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o 13obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
11 14
@@ -17,6 +20,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
17obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o 20obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
18 21
19# connection tracking helpers 22# connection tracking helpers
23obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
20obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o 24obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
21obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o 25obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
22obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o 26obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
@@ -24,6 +28,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
24obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o 28obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
25 29
26# NAT helpers 30# NAT helpers
31obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
27obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o 32obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
28obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o 33obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
29obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o 34obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index dc20881004bc..fa3f914117ec 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -65,7 +65,7 @@ static int help(struct sk_buff **pskb,
65 65
66 /* increase the UDP timeout of the master connection as replies from 66 /* increase the UDP timeout of the master connection as replies from
67 * Amanda clients to the server can be quite delayed */ 67 * Amanda clients to the server can be quite delayed */
68 ip_ct_refresh_acct(ct, ctinfo, NULL, master_timeout * HZ); 68 ip_ct_refresh(ct, *pskb, master_timeout * HZ);
69 69
70 /* No data? */ 70 /* No data? */
71 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); 71 dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index f8cd8e42961e..ea65dd3e517a 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
233 233
234/* Just find a expectation corresponding to a tuple. */ 234/* Just find a expectation corresponding to a tuple. */
235struct ip_conntrack_expect * 235struct ip_conntrack_expect *
236ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple) 236ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
237{ 237{
238 struct ip_conntrack_expect *i; 238 struct ip_conntrack_expect *i;
239 239
@@ -1112,45 +1112,46 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1112 synchronize_net(); 1112 synchronize_net();
1113} 1113}
1114 1114
1115static inline void ct_add_counters(struct ip_conntrack *ct, 1115/* Refresh conntrack for this many jiffies and do accounting if do_acct is 1 */
1116 enum ip_conntrack_info ctinfo, 1116void __ip_ct_refresh_acct(struct ip_conntrack *ct,
1117 const struct sk_buff *skb)
1118{
1119#ifdef CONFIG_IP_NF_CT_ACCT
1120 if (skb) {
1121 ct->counters[CTINFO2DIR(ctinfo)].packets++;
1122 ct->counters[CTINFO2DIR(ctinfo)].bytes +=
1123 ntohs(skb->nh.iph->tot_len);
1124 }
1125#endif
1126}
1127
1128/* Refresh conntrack for this many jiffies and do accounting (if skb != NULL) */
1129void ip_ct_refresh_acct(struct ip_conntrack *ct,
1130 enum ip_conntrack_info ctinfo, 1117 enum ip_conntrack_info ctinfo,
1131 const struct sk_buff *skb, 1118 const struct sk_buff *skb,
1132 unsigned long extra_jiffies) 1119 unsigned long extra_jiffies,
1120 int do_acct)
1133{ 1121{
1122 int do_event = 0;
1123
1134 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); 1124 IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1125 IP_NF_ASSERT(skb);
1126
1127 write_lock_bh(&ip_conntrack_lock);
1135 1128
1136 /* If not in hash table, timer will not be active yet */ 1129 /* If not in hash table, timer will not be active yet */
1137 if (!is_confirmed(ct)) { 1130 if (!is_confirmed(ct)) {
1138 ct->timeout.expires = extra_jiffies; 1131 ct->timeout.expires = extra_jiffies;
1139 ct_add_counters(ct, ctinfo, skb); 1132 do_event = 1;
1140 } else { 1133 } else {
1141 write_lock_bh(&ip_conntrack_lock);
1142 /* Need del_timer for race avoidance (may already be dying). */ 1134 /* Need del_timer for race avoidance (may already be dying). */
1143 if (del_timer(&ct->timeout)) { 1135 if (del_timer(&ct->timeout)) {
1144 ct->timeout.expires = jiffies + extra_jiffies; 1136 ct->timeout.expires = jiffies + extra_jiffies;
1145 add_timer(&ct->timeout); 1137 add_timer(&ct->timeout);
1146 /* FIXME: We loose some REFRESH events if this function 1138 do_event = 1;
1147 * is called without an skb. I'll fix this later -HW */
1148 if (skb)
1149 ip_conntrack_event_cache(IPCT_REFRESH, skb);
1150 } 1139 }
1151 ct_add_counters(ct, ctinfo, skb);
1152 write_unlock_bh(&ip_conntrack_lock);
1153 } 1140 }
1141
1142#ifdef CONFIG_IP_NF_CT_ACCT
1143 if (do_acct) {
1144 ct->counters[CTINFO2DIR(ctinfo)].packets++;
1145 ct->counters[CTINFO2DIR(ctinfo)].bytes +=
1146 ntohs(skb->nh.iph->tot_len);
1147 }
1148#endif
1149
1150 write_unlock_bh(&ip_conntrack_lock);
1151
1152 /* must be unlocked when calling event cache */
1153 if (do_event)
1154 ip_conntrack_event_cache(IPCT_REFRESH, skb);
1154} 1155}
1155 1156
1156#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ 1157#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
new file mode 100644
index 000000000000..926a6684643d
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -0,0 +1,806 @@
1/*
2 * ip_conntrack_pptp.c - Version 3.0
3 *
4 * Connection tracking 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 * Limitations:
17 * - We blindly assume that control connections are always
18 * established in PNS->PAC direction. This is a violation
19 * of RFFC2673
20 * - We can only support one single call within each session
21 *
22 * TODO:
23 * - testing of incoming PPTP calls
24 *
25 * Changes:
26 * 2002-02-05 - Version 1.3
27 * - Call ip_conntrack_unexpect_related() from
28 * pptp_destroy_siblings() to destroy expectations in case
29 * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
30 * (Philip Craig <philipc@snapgear.com>)
31 * - Add Version information at module loadtime
32 * 2002-02-10 - Version 1.6
33 * - move to C99 style initializers
34 * - remove second expectation if first arrives
35 * 2004-10-22 - Version 2.0
36 * - merge Mandrake's 2.6.x port with recent 2.6.x API changes
37 * - fix lots of linear skb assumptions from Mandrake's port
38 * 2005-06-10 - Version 2.1
39 * - use ip_conntrack_expect_free() instead of kfree() on the
40 * expect's (which are from the slab for quite some time)
41 * 2005-06-10 - Version 3.0
42 * - port helper to post-2.6.11 API changes,
43 * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
44 * 2005-07-30 - Version 3.1
45 * - port helper to 2.6.13 API changes
46 *
47 */
48
49#include <linux/config.h>
50#include <linux/module.h>
51#include <linux/netfilter.h>
52#include <linux/ip.h>
53#include <net/checksum.h>
54#include <net/tcp.h>
55
56#include <linux/netfilter_ipv4/ip_conntrack.h>
57#include <linux/netfilter_ipv4/ip_conntrack_core.h>
58#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
59#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
60#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
61
62#define IP_CT_PPTP_VERSION "3.1"
63
64MODULE_LICENSE("GPL");
65MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
66MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
67
68static DEFINE_SPINLOCK(ip_pptp_lock);
69
70int
71(*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb,
72 struct ip_conntrack *ct,
73 enum ip_conntrack_info ctinfo,
74 struct PptpControlHeader *ctlh,
75 union pptp_ctrl_union *pptpReq);
76
77int
78(*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb,
79 struct ip_conntrack *ct,
80 enum ip_conntrack_info ctinfo,
81 struct PptpControlHeader *ctlh,
82 union pptp_ctrl_union *pptpReq);
83
84int
85(*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig,
86 struct ip_conntrack_expect *expect_reply);
87
88void
89(*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct,
90 struct ip_conntrack_expect *exp);
91
92#if 0
93/* PptpControlMessageType names */
94const char *pptp_msg_name[] = {
95 "UNKNOWN_MESSAGE",
96 "START_SESSION_REQUEST",
97 "START_SESSION_REPLY",
98 "STOP_SESSION_REQUEST",
99 "STOP_SESSION_REPLY",
100 "ECHO_REQUEST",
101 "ECHO_REPLY",
102 "OUT_CALL_REQUEST",
103 "OUT_CALL_REPLY",
104 "IN_CALL_REQUEST",
105 "IN_CALL_REPLY",
106 "IN_CALL_CONNECT",
107 "CALL_CLEAR_REQUEST",
108 "CALL_DISCONNECT_NOTIFY",
109 "WAN_ERROR_NOTIFY",
110 "SET_LINK_INFO"
111};
112EXPORT_SYMBOL(pptp_msg_name);
113#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
114#else
115#define DEBUGP(format, args...)
116#endif
117
118#define SECS *HZ
119#define MINS * 60 SECS
120#define HOURS * 60 MINS
121
122#define PPTP_GRE_TIMEOUT (10 MINS)
123#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
124
125static void pptp_expectfn(struct ip_conntrack *ct,
126 struct ip_conntrack_expect *exp)
127{
128 DEBUGP("increasing timeouts\n");
129
130 /* increase timeout of GRE data channel conntrack entry */
131 ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
132 ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
133
134 /* Can you see how rusty this code is, compared with the pre-2.6.11
135 * one? That's what happened to my shiny newnat of 2002 ;( -HW */
136
137 if (!ip_nat_pptp_hook_expectfn) {
138 struct ip_conntrack_tuple inv_t;
139 struct ip_conntrack_expect *exp_other;
140
141 /* obviously this tuple inversion only works until you do NAT */
142 invert_tuplepr(&inv_t, &exp->tuple);
143 DEBUGP("trying to unexpect other dir: ");
144 DUMP_TUPLE(&inv_t);
145
146 exp_other = ip_conntrack_expect_find(&inv_t);
147 if (exp_other) {
148 /* delete other expectation. */
149 DEBUGP("found\n");
150 ip_conntrack_unexpect_related(exp_other);
151 ip_conntrack_expect_put(exp_other);
152 } else {
153 DEBUGP("not found\n");
154 }
155 } else {
156 /* we need more than simple inversion */
157 ip_nat_pptp_hook_expectfn(ct, exp);
158 }
159}
160
161static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t)
162{
163 struct ip_conntrack_tuple_hash *h;
164 struct ip_conntrack_expect *exp;
165
166 DEBUGP("trying to timeout ct or exp for tuple ");
167 DUMP_TUPLE(t);
168
169 h = ip_conntrack_find_get(t, NULL);
170 if (h) {
171 struct ip_conntrack *sibling = tuplehash_to_ctrack(h);
172 DEBUGP("setting timeout of conntrack %p to 0\n", sibling);
173 sibling->proto.gre.timeout = 0;
174 sibling->proto.gre.stream_timeout = 0;
175 if (del_timer(&sibling->timeout))
176 sibling->timeout.function((unsigned long)sibling);
177 ip_conntrack_put(sibling);
178 return 1;
179 } else {
180 exp = ip_conntrack_expect_find(t);
181 if (exp) {
182 DEBUGP("unexpect_related of expect %p\n", exp);
183 ip_conntrack_unexpect_related(exp);
184 ip_conntrack_expect_put(exp);
185 return 1;
186 }
187 }
188
189 return 0;
190}
191
192
193/* timeout GRE data connections */
194static void pptp_destroy_siblings(struct ip_conntrack *ct)
195{
196 struct ip_conntrack_tuple t;
197
198 /* Since ct->sibling_list has literally rusted away in 2.6.11,
199 * we now need another way to find out about our sibling
200 * contrack and expects... -HW */
201
202 /* try original (pns->pac) tuple */
203 memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
204 t.dst.protonum = IPPROTO_GRE;
205 t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
206 t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
207
208 if (!destroy_sibling_or_exp(&t))
209 DEBUGP("failed to timeout original pns->pac ct/exp\n");
210
211 /* try reply (pac->pns) tuple */
212 memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
213 t.dst.protonum = IPPROTO_GRE;
214 t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id);
215 t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id);
216
217 if (!destroy_sibling_or_exp(&t))
218 DEBUGP("failed to timeout reply pac->pns ct/exp\n");
219}
220
221/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
222static inline int
223exp_gre(struct ip_conntrack *master,
224 u_int32_t seq,
225 __be16 callid,
226 __be16 peer_callid)
227{
228 struct ip_conntrack_tuple inv_tuple;
229 struct ip_conntrack_tuple exp_tuples[] = {
230 /* tuple in original direction, PNS->PAC */
231 { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
232 .u = { .gre = { .key = peer_callid } }
233 },
234 .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
235 .u = { .gre = { .key = callid } },
236 .protonum = IPPROTO_GRE
237 },
238 },
239 /* tuple in reply direction, PAC->PNS */
240 { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
241 .u = { .gre = { .key = callid } }
242 },
243 .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
244 .u = { .gre = { .key = peer_callid } },
245 .protonum = IPPROTO_GRE
246 },
247 }
248 };
249 struct ip_conntrack_expect *exp_orig, *exp_reply;
250 int ret = 1;
251
252 exp_orig = ip_conntrack_expect_alloc(master);
253 if (exp_orig == NULL)
254 goto out;
255
256 exp_reply = ip_conntrack_expect_alloc(master);
257 if (exp_reply == NULL)
258 goto out_put_orig;
259
260 memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple));
261
262 exp_orig->mask.src.ip = 0xffffffff;
263 exp_orig->mask.src.u.all = 0;
264 exp_orig->mask.dst.u.all = 0;
265 exp_orig->mask.dst.u.gre.key = htons(0xffff);
266 exp_orig->mask.dst.ip = 0xffffffff;
267 exp_orig->mask.dst.protonum = 0xff;
268
269 exp_orig->master = master;
270 exp_orig->expectfn = pptp_expectfn;
271 exp_orig->flags = 0;
272
273 exp_orig->dir = IP_CT_DIR_ORIGINAL;
274
275 /* both expectations are identical apart from tuple */
276 memcpy(exp_reply, exp_orig, sizeof(*exp_reply));
277 memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple));
278
279 exp_reply->dir = !exp_orig->dir;
280
281 if (ip_nat_pptp_hook_exp_gre)
282 ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply);
283 else {
284
285 DEBUGP("calling expect_related PNS->PAC");
286 DUMP_TUPLE(&exp_orig->tuple);
287
288 if (ip_conntrack_expect_related(exp_orig) != 0) {
289 DEBUGP("cannot expect_related()\n");
290 goto out_put_both;
291 }
292
293 DEBUGP("calling expect_related PAC->PNS");
294 DUMP_TUPLE(&exp_reply->tuple);
295
296 if (ip_conntrack_expect_related(exp_reply) != 0) {
297 DEBUGP("cannot expect_related()\n");
298 goto out_unexpect_orig;
299 }
300
301 /* Add GRE keymap entries */
302 if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) {
303 DEBUGP("cannot keymap_add() exp\n");
304 goto out_unexpect_both;
305 }
306
307 invert_tuplepr(&inv_tuple, &exp_reply->tuple);
308 if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) {
309 ip_ct_gre_keymap_destroy(master);
310 DEBUGP("cannot keymap_add() exp_inv\n");
311 goto out_unexpect_both;
312 }
313 ret = 0;
314 }
315
316out_put_both:
317 ip_conntrack_expect_put(exp_reply);
318out_put_orig:
319 ip_conntrack_expect_put(exp_orig);
320out:
321 return ret;
322
323out_unexpect_both:
324 ip_conntrack_unexpect_related(exp_reply);
325out_unexpect_orig:
326 ip_conntrack_unexpect_related(exp_orig);
327 goto out_put_both;
328}
329
330static inline int
331pptp_inbound_pkt(struct sk_buff **pskb,
332 struct tcphdr *tcph,
333 unsigned int nexthdr_off,
334 unsigned int datalen,
335 struct ip_conntrack *ct,
336 enum ip_conntrack_info ctinfo)
337{
338 struct PptpControlHeader _ctlh, *ctlh;
339 unsigned int reqlen;
340 union pptp_ctrl_union _pptpReq, *pptpReq;
341 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
342 u_int16_t msg;
343 __be16 *cid, *pcid;
344 u_int32_t seq;
345
346 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
347 if (!ctlh) {
348 DEBUGP("error during skb_header_pointer\n");
349 return NF_ACCEPT;
350 }
351 nexthdr_off += sizeof(_ctlh);
352 datalen -= sizeof(_ctlh);
353
354 reqlen = datalen;
355 if (reqlen > sizeof(*pptpReq))
356 reqlen = sizeof(*pptpReq);
357 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
358 if (!pptpReq) {
359 DEBUGP("error during skb_header_pointer\n");
360 return NF_ACCEPT;
361 }
362
363 msg = ntohs(ctlh->messageType);
364 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
365
366 switch (msg) {
367 case PPTP_START_SESSION_REPLY:
368 if (reqlen < sizeof(_pptpReq.srep)) {
369 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
370 break;
371 }
372
373 /* server confirms new control session */
374 if (info->sstate < PPTP_SESSION_REQUESTED) {
375 DEBUGP("%s without START_SESS_REQUEST\n",
376 pptp_msg_name[msg]);
377 break;
378 }
379 if (pptpReq->srep.resultCode == PPTP_START_OK)
380 info->sstate = PPTP_SESSION_CONFIRMED;
381 else
382 info->sstate = PPTP_SESSION_ERROR;
383 break;
384
385 case PPTP_STOP_SESSION_REPLY:
386 if (reqlen < sizeof(_pptpReq.strep)) {
387 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
388 break;
389 }
390
391 /* server confirms end of control session */
392 if (info->sstate > PPTP_SESSION_STOPREQ) {
393 DEBUGP("%s without STOP_SESS_REQUEST\n",
394 pptp_msg_name[msg]);
395 break;
396 }
397 if (pptpReq->strep.resultCode == PPTP_STOP_OK)
398 info->sstate = PPTP_SESSION_NONE;
399 else
400 info->sstate = PPTP_SESSION_ERROR;
401 break;
402
403 case PPTP_OUT_CALL_REPLY:
404 if (reqlen < sizeof(_pptpReq.ocack)) {
405 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
406 break;
407 }
408
409 /* server accepted call, we now expect GRE frames */
410 if (info->sstate != PPTP_SESSION_CONFIRMED) {
411 DEBUGP("%s but no session\n", pptp_msg_name[msg]);
412 break;
413 }
414 if (info->cstate != PPTP_CALL_OUT_REQ &&
415 info->cstate != PPTP_CALL_OUT_CONF) {
416 DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]);
417 break;
418 }
419 if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {
420 info->cstate = PPTP_CALL_NONE;
421 break;
422 }
423
424 cid = &pptpReq->ocack.callID;
425 pcid = &pptpReq->ocack.peersCallID;
426
427 info->pac_call_id = ntohs(*cid);
428
429 if (htons(info->pns_call_id) != *pcid) {
430 DEBUGP("%s for unknown callid %u\n",
431 pptp_msg_name[msg], ntohs(*pcid));
432 break;
433 }
434
435 DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
436 ntohs(*cid), ntohs(*pcid));
437
438 info->cstate = PPTP_CALL_OUT_CONF;
439
440 seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
441 + sizeof(struct PptpControlHeader)
442 + ((void *)pcid - (void *)pptpReq);
443
444 if (exp_gre(ct, seq, *cid, *pcid) != 0)
445 printk("ip_conntrack_pptp: error during exp_gre\n");
446 break;
447
448 case PPTP_IN_CALL_REQUEST:
449 if (reqlen < sizeof(_pptpReq.icack)) {
450 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
451 break;
452 }
453
454 /* server tells us about incoming call request */
455 if (info->sstate != PPTP_SESSION_CONFIRMED) {
456 DEBUGP("%s but no session\n", pptp_msg_name[msg]);
457 break;
458 }
459 pcid = &pptpReq->icack.peersCallID;
460 DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
461 info->cstate = PPTP_CALL_IN_REQ;
462 info->pac_call_id = ntohs(*pcid);
463 break;
464
465 case PPTP_IN_CALL_CONNECT:
466 if (reqlen < sizeof(_pptpReq.iccon)) {
467 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
468 break;
469 }
470
471 /* server tells us about incoming call established */
472 if (info->sstate != PPTP_SESSION_CONFIRMED) {
473 DEBUGP("%s but no session\n", pptp_msg_name[msg]);
474 break;
475 }
476 if (info->sstate != PPTP_CALL_IN_REP
477 && info->sstate != PPTP_CALL_IN_CONF) {
478 DEBUGP("%s but never sent IN_CALL_REPLY\n",
479 pptp_msg_name[msg]);
480 break;
481 }
482
483 pcid = &pptpReq->iccon.peersCallID;
484 cid = &info->pac_call_id;
485
486 if (info->pns_call_id != ntohs(*pcid)) {
487 DEBUGP("%s for unknown CallID %u\n",
488 pptp_msg_name[msg], ntohs(*pcid));
489 break;
490 }
491
492 DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
493 info->cstate = PPTP_CALL_IN_CONF;
494
495 /* we expect a GRE connection from PAC to PNS */
496 seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
497 + sizeof(struct PptpControlHeader)
498 + ((void *)pcid - (void *)pptpReq);
499
500 if (exp_gre(ct, seq, *cid, *pcid) != 0)
501 printk("ip_conntrack_pptp: error during exp_gre\n");
502
503 break;
504
505 case PPTP_CALL_DISCONNECT_NOTIFY:
506 if (reqlen < sizeof(_pptpReq.disc)) {
507 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
508 break;
509 }
510
511 /* server confirms disconnect */
512 cid = &pptpReq->disc.callID;
513 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
514 info->cstate = PPTP_CALL_NONE;
515
516 /* untrack this call id, unexpect GRE packets */
517 pptp_destroy_siblings(ct);
518 break;
519
520 case PPTP_WAN_ERROR_NOTIFY:
521 break;
522
523 case PPTP_ECHO_REQUEST:
524 case PPTP_ECHO_REPLY:
525 /* I don't have to explain these ;) */
526 break;
527 default:
528 DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
529 ? pptp_msg_name[msg]:pptp_msg_name[0], msg);
530 break;
531 }
532
533
534 if (ip_nat_pptp_hook_inbound)
535 return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh,
536 pptpReq);
537
538 return NF_ACCEPT;
539
540}
541
542static inline int
543pptp_outbound_pkt(struct sk_buff **pskb,
544 struct tcphdr *tcph,
545 unsigned int nexthdr_off,
546 unsigned int datalen,
547 struct ip_conntrack *ct,
548 enum ip_conntrack_info ctinfo)
549{
550 struct PptpControlHeader _ctlh, *ctlh;
551 unsigned int reqlen;
552 union pptp_ctrl_union _pptpReq, *pptpReq;
553 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
554 u_int16_t msg;
555 __be16 *cid, *pcid;
556
557 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
558 if (!ctlh)
559 return NF_ACCEPT;
560 nexthdr_off += sizeof(_ctlh);
561 datalen -= sizeof(_ctlh);
562
563 reqlen = datalen;
564 if (reqlen > sizeof(*pptpReq))
565 reqlen = sizeof(*pptpReq);
566 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
567 if (!pptpReq)
568 return NF_ACCEPT;
569
570 msg = ntohs(ctlh->messageType);
571 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
572
573 switch (msg) {
574 case PPTP_START_SESSION_REQUEST:
575 /* client requests for new control session */
576 if (info->sstate != PPTP_SESSION_NONE) {
577 DEBUGP("%s but we already have one",
578 pptp_msg_name[msg]);
579 }
580 info->sstate = PPTP_SESSION_REQUESTED;
581 break;
582 case PPTP_STOP_SESSION_REQUEST:
583 /* client requests end of control session */
584 info->sstate = PPTP_SESSION_STOPREQ;
585 break;
586
587 case PPTP_OUT_CALL_REQUEST:
588 if (reqlen < sizeof(_pptpReq.ocreq)) {
589 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
590 /* FIXME: break; */
591 }
592
593 /* client initiating connection to server */
594 if (info->sstate != PPTP_SESSION_CONFIRMED) {
595 DEBUGP("%s but no session\n",
596 pptp_msg_name[msg]);
597 break;
598 }
599 info->cstate = PPTP_CALL_OUT_REQ;
600 /* track PNS call id */
601 cid = &pptpReq->ocreq.callID;
602 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid));
603 info->pns_call_id = ntohs(*cid);
604 break;
605 case PPTP_IN_CALL_REPLY:
606 if (reqlen < sizeof(_pptpReq.icack)) {
607 DEBUGP("%s: short packet\n", pptp_msg_name[msg]);
608 break;
609 }
610
611 /* client answers incoming call */
612 if (info->cstate != PPTP_CALL_IN_REQ
613 && info->cstate != PPTP_CALL_IN_REP) {
614 DEBUGP("%s without incall_req\n",
615 pptp_msg_name[msg]);
616 break;
617 }
618 if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {
619 info->cstate = PPTP_CALL_NONE;
620 break;
621 }
622 pcid = &pptpReq->icack.peersCallID;
623 if (info->pac_call_id != ntohs(*pcid)) {
624 DEBUGP("%s for unknown call %u\n",
625 pptp_msg_name[msg], ntohs(*pcid));
626 break;
627 }
628 DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid));
629 /* part two of the three-way handshake */
630 info->cstate = PPTP_CALL_IN_REP;
631 info->pns_call_id = ntohs(pptpReq->icack.callID);
632 break;
633
634 case PPTP_CALL_CLEAR_REQUEST:
635 /* client requests hangup of call */
636 if (info->sstate != PPTP_SESSION_CONFIRMED) {
637 DEBUGP("CLEAR_CALL but no session\n");
638 break;
639 }
640 /* FUTURE: iterate over all calls and check if
641 * call ID is valid. We don't do this without newnat,
642 * because we only know about last call */
643 info->cstate = PPTP_CALL_CLEAR_REQ;
644 break;
645 case PPTP_SET_LINK_INFO:
646 break;
647 case PPTP_ECHO_REQUEST:
648 case PPTP_ECHO_REPLY:
649 /* I don't have to explain these ;) */
650 break;
651 default:
652 DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)?
653 pptp_msg_name[msg]:pptp_msg_name[0], msg);
654 /* unknown: no need to create GRE masq table entry */
655 break;
656 }
657
658 if (ip_nat_pptp_hook_outbound)
659 return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh,
660 pptpReq);
661
662 return NF_ACCEPT;
663}
664
665
666/* track caller id inside control connection, call expect_related */
667static int
668conntrack_pptp_help(struct sk_buff **pskb,
669 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
670
671{
672 struct pptp_pkt_hdr _pptph, *pptph;
673 struct tcphdr _tcph, *tcph;
674 u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
675 u_int32_t datalen;
676 int dir = CTINFO2DIR(ctinfo);
677 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
678 unsigned int nexthdr_off;
679
680 int oldsstate, oldcstate;
681 int ret;
682
683 /* don't do any tracking before tcp handshake complete */
684 if (ctinfo != IP_CT_ESTABLISHED
685 && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
686 DEBUGP("ctinfo = %u, skipping\n", ctinfo);
687 return NF_ACCEPT;
688 }
689
690 nexthdr_off = (*pskb)->nh.iph->ihl*4;
691 tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph);
692 BUG_ON(!tcph);
693 nexthdr_off += tcph->doff * 4;
694 datalen = tcplen - tcph->doff * 4;
695
696 if (tcph->fin || tcph->rst) {
697 DEBUGP("RST/FIN received, timeouting GRE\n");
698 /* can't do this after real newnat */
699 info->cstate = PPTP_CALL_NONE;
700
701 /* untrack this call id, unexpect GRE packets */
702 pptp_destroy_siblings(ct);
703 }
704
705 pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph);
706 if (!pptph) {
707 DEBUGP("no full PPTP header, can't track\n");
708 return NF_ACCEPT;
709 }
710 nexthdr_off += sizeof(_pptph);
711 datalen -= sizeof(_pptph);
712
713 /* if it's not a control message we can't do anything with it */
714 if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
715 ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
716 DEBUGP("not a control packet\n");
717 return NF_ACCEPT;
718 }
719
720 oldsstate = info->sstate;
721 oldcstate = info->cstate;
722
723 spin_lock_bh(&ip_pptp_lock);
724
725 /* FIXME: We just blindly assume that the control connection is always
726 * established from PNS->PAC. However, RFC makes no guarantee */
727 if (dir == IP_CT_DIR_ORIGINAL)
728 /* client -> server (PNS -> PAC) */
729 ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
730 ctinfo);
731 else
732 /* server -> client (PAC -> PNS) */
733 ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct,
734 ctinfo);
735 DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
736 oldsstate, info->sstate, oldcstate, info->cstate);
737 spin_unlock_bh(&ip_pptp_lock);
738
739 return ret;
740}
741
742/* control protocol helper */
743static struct ip_conntrack_helper pptp = {
744 .list = { NULL, NULL },
745 .name = "pptp",
746 .me = THIS_MODULE,
747 .max_expected = 2,
748 .timeout = 5 * 60,
749 .tuple = { .src = { .ip = 0,
750 .u = { .tcp = { .port =
751 __constant_htons(PPTP_CONTROL_PORT) } }
752 },
753 .dst = { .ip = 0,
754 .u = { .all = 0 },
755 .protonum = IPPROTO_TCP
756 }
757 },
758 .mask = { .src = { .ip = 0,
759 .u = { .tcp = { .port = __constant_htons(0xffff) } }
760 },
761 .dst = { .ip = 0,
762 .u = { .all = 0 },
763 .protonum = 0xff
764 }
765 },
766 .help = conntrack_pptp_help
767};
768
769extern void __exit ip_ct_proto_gre_fini(void);
770extern int __init ip_ct_proto_gre_init(void);
771
772/* ip_conntrack_pptp initialization */
773static int __init init(void)
774{
775 int retcode;
776
777 retcode = ip_ct_proto_gre_init();
778 if (retcode < 0)
779 return retcode;
780
781 DEBUGP(" registering helper\n");
782 if ((retcode = ip_conntrack_helper_register(&pptp))) {
783 printk(KERN_ERR "Unable to register conntrack application "
784 "helper for pptp: %d\n", retcode);
785 ip_ct_proto_gre_fini();
786 return retcode;
787 }
788
789 printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
790 return 0;
791}
792
793static void __exit fini(void)
794{
795 ip_conntrack_helper_unregister(&pptp);
796 ip_ct_proto_gre_fini();
797 printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
798}
799
800module_init(init);
801module_exit(fini);
802
803EXPORT_SYMBOL(ip_nat_pptp_hook_outbound);
804EXPORT_SYMBOL(ip_nat_pptp_hook_inbound);
805EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre);
806EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn);
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
index 71ef19d126d0..577bac22dcc6 100644
--- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
+++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c
@@ -91,7 +91,7 @@ static int help(struct sk_buff **pskb,
91 ip_conntrack_expect_related(exp); 91 ip_conntrack_expect_related(exp);
92 ip_conntrack_expect_put(exp); 92 ip_conntrack_expect_put(exp);
93 93
94 ip_ct_refresh_acct(ct, ctinfo, NULL, timeout * HZ); 94 ip_ct_refresh(ct, *pskb, timeout * HZ);
95out: 95out:
96 return NF_ACCEPT; 96 return NF_ACCEPT;
97} 97}
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 15aef3564742..b08a432efcf8 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -1270,7 +1270,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1270 if (err < 0) 1270 if (err < 0)
1271 return err; 1271 return err;
1272 1272
1273 exp = ip_conntrack_expect_find_get(&tuple); 1273 exp = ip_conntrack_expect_find(&tuple);
1274 if (!exp) 1274 if (!exp)
1275 return -ENOENT; 1275 return -ENOENT;
1276 1276
@@ -1318,7 +1318,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1318 return err; 1318 return err;
1319 1319
1320 /* bump usage count to 2 */ 1320 /* bump usage count to 2 */
1321 exp = ip_conntrack_expect_find_get(&tuple); 1321 exp = ip_conntrack_expect_find(&tuple);
1322 if (!exp) 1322 if (!exp)
1323 return -ENOENT; 1323 return -ENOENT;
1324 1324
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
new file mode 100644
index 000000000000..de3cb9db6f85
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -0,0 +1,327 @@
1/*
2 * ip_conntrack_proto_gre.c - Version 3.0
3 *
4 * Connection tracking 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/config.h>
27#include <linux/module.h>
28#include <linux/types.h>
29#include <linux/timer.h>
30#include <linux/netfilter.h>
31#include <linux/ip.h>
32#include <linux/in.h>
33#include <linux/list.h>
34
35static DEFINE_RWLOCK(ip_ct_gre_lock);
36#define ASSERT_READ_LOCK(x)
37#define ASSERT_WRITE_LOCK(x)
38
39#include <linux/netfilter_ipv4/listhelp.h>
40#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
41#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
42#include <linux/netfilter_ipv4/ip_conntrack_core.h>
43
44#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
45#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
46
47MODULE_LICENSE("GPL");
48MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
49MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
50
51/* shamelessly stolen from ip_conntrack_proto_udp.c */
52#define GRE_TIMEOUT (30*HZ)
53#define GRE_STREAM_TIMEOUT (180*HZ)
54
55#if 0
56#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
57#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \
58 NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \
59 NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key))
60#else
61#define DEBUGP(x, args...)
62#define DUMP_TUPLE_GRE(x)
63#endif
64
65/* GRE KEYMAP HANDLING FUNCTIONS */
66static LIST_HEAD(gre_keymap_list);
67
68static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
69 const struct ip_conntrack_tuple *t)
70{
71 return ((km->tuple.src.ip == t->src.ip) &&
72 (km->tuple.dst.ip == t->dst.ip) &&
73 (km->tuple.dst.protonum == t->dst.protonum) &&
74 (km->tuple.dst.u.all == t->dst.u.all));
75}
76
77/* look up the source key for a given tuple */
78static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
79{
80 struct ip_ct_gre_keymap *km;
81 u_int32_t key = 0;
82
83 read_lock_bh(&ip_ct_gre_lock);
84 km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
85 struct ip_ct_gre_keymap *, t);
86 if (km)
87 key = km->tuple.src.u.gre.key;
88 read_unlock_bh(&ip_ct_gre_lock);
89
90 DEBUGP("lookup src key 0x%x up key for ", key);
91 DUMP_TUPLE_GRE(t);
92
93 return key;
94}
95
96/* add a single keymap entry, associate with specified master ct */
97int
98ip_ct_gre_keymap_add(struct ip_conntrack *ct,
99 struct ip_conntrack_tuple *t, int reply)
100{
101 struct ip_ct_gre_keymap **exist_km, *km, *old;
102
103 if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
104 DEBUGP("refusing to add GRE keymap to non-pptp session\n");
105 return -1;
106 }
107
108 if (!reply)
109 exist_km = &ct->help.ct_pptp_info.keymap_orig;
110 else
111 exist_km = &ct->help.ct_pptp_info.keymap_reply;
112
113 if (*exist_km) {
114 /* check whether it's a retransmission */
115 old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
116 struct ip_ct_gre_keymap *, t);
117 if (old == *exist_km) {
118 DEBUGP("retransmission\n");
119 return 0;
120 }
121
122 DEBUGP("trying to override keymap_%s for ct %p\n",
123 reply? "reply":"orig", ct);
124 return -EEXIST;
125 }
126
127 km = kmalloc(sizeof(*km), GFP_ATOMIC);
128 if (!km)
129 return -ENOMEM;
130
131 memcpy(&km->tuple, t, sizeof(*t));
132 *exist_km = km;
133
134 DEBUGP("adding new entry %p: ", km);
135 DUMP_TUPLE_GRE(&km->tuple);
136
137 write_lock_bh(&ip_ct_gre_lock);
138 list_append(&gre_keymap_list, km);
139 write_unlock_bh(&ip_ct_gre_lock);
140
141 return 0;
142}
143
144/* destroy the keymap entries associated with specified master ct */
145void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct)
146{
147 DEBUGP("entering for ct %p\n", ct);
148
149 if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
150 DEBUGP("refusing to destroy GRE keymap to non-pptp session\n");
151 return;
152 }
153
154 write_lock_bh(&ip_ct_gre_lock);
155 if (ct->help.ct_pptp_info.keymap_orig) {
156 DEBUGP("removing %p from list\n",
157 ct->help.ct_pptp_info.keymap_orig);
158 list_del(&ct->help.ct_pptp_info.keymap_orig->list);
159 kfree(ct->help.ct_pptp_info.keymap_orig);
160 ct->help.ct_pptp_info.keymap_orig = NULL;
161 }
162 if (ct->help.ct_pptp_info.keymap_reply) {
163 DEBUGP("removing %p from list\n",
164 ct->help.ct_pptp_info.keymap_reply);
165 list_del(&ct->help.ct_pptp_info.keymap_reply->list);
166 kfree(ct->help.ct_pptp_info.keymap_reply);
167 ct->help.ct_pptp_info.keymap_reply = NULL;
168 }
169 write_unlock_bh(&ip_ct_gre_lock);
170}
171
172
173/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
174
175/* invert gre part of tuple */
176static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
177 const struct ip_conntrack_tuple *orig)
178{
179 tuple->dst.u.gre.key = orig->src.u.gre.key;
180 tuple->src.u.gre.key = orig->dst.u.gre.key;
181
182 return 1;
183}
184
185/* gre hdr info to tuple */
186static int gre_pkt_to_tuple(const struct sk_buff *skb,
187 unsigned int dataoff,
188 struct ip_conntrack_tuple *tuple)
189{
190 struct gre_hdr_pptp _pgrehdr, *pgrehdr;
191 u_int32_t srckey;
192 struct gre_hdr _grehdr, *grehdr;
193
194 /* first only delinearize old RFC1701 GRE header */
195 grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr);
196 if (!grehdr || grehdr->version != GRE_VERSION_PPTP) {
197 /* try to behave like "ip_conntrack_proto_generic" */
198 tuple->src.u.all = 0;
199 tuple->dst.u.all = 0;
200 return 1;
201 }
202
203 /* PPTP header is variable length, only need up to the call_id field */
204 pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr);
205 if (!pgrehdr)
206 return 1;
207
208 if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
209 DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
210 return 0;
211 }
212
213 tuple->dst.u.gre.key = pgrehdr->call_id;
214 srckey = gre_keymap_lookup(tuple);
215 tuple->src.u.gre.key = srckey;
216
217 return 1;
218}
219
220/* print gre part of tuple */
221static int gre_print_tuple(struct seq_file *s,
222 const struct ip_conntrack_tuple *tuple)
223{
224 return seq_printf(s, "srckey=0x%x dstkey=0x%x ",
225 ntohs(tuple->src.u.gre.key),
226 ntohs(tuple->dst.u.gre.key));
227}
228
229/* print private data for conntrack */
230static int gre_print_conntrack(struct seq_file *s,
231 const struct ip_conntrack *ct)
232{
233 return seq_printf(s, "timeout=%u, stream_timeout=%u ",
234 (ct->proto.gre.timeout / HZ),
235 (ct->proto.gre.stream_timeout / HZ));
236}
237
238/* Returns verdict for packet, and may modify conntrack */
239static int gre_packet(struct ip_conntrack *ct,
240 const struct sk_buff *skb,
241 enum ip_conntrack_info conntrackinfo)
242{
243 /* If we've seen traffic both ways, this is a GRE connection.
244 * Extend timeout. */
245 if (ct->status & IPS_SEEN_REPLY) {
246 ip_ct_refresh_acct(ct, conntrackinfo, skb,
247 ct->proto.gre.stream_timeout);
248 /* Also, more likely to be important, and not a probe. */
249 set_bit(IPS_ASSURED_BIT, &ct->status);
250 } else
251 ip_ct_refresh_acct(ct, conntrackinfo, skb,
252 ct->proto.gre.timeout);
253
254 return NF_ACCEPT;
255}
256
257/* Called when a new connection for this protocol found. */
258static int gre_new(struct ip_conntrack *ct,
259 const struct sk_buff *skb)
260{
261 DEBUGP(": ");
262 DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
263
264 /* initialize to sane value. Ideally a conntrack helper
265 * (e.g. in case of pptp) is increasing them */
266 ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
267 ct->proto.gre.timeout = GRE_TIMEOUT;
268
269 return 1;
270}
271
272/* Called when a conntrack entry has already been removed from the hashes
273 * and is about to be deleted from memory */
274static void gre_destroy(struct ip_conntrack *ct)
275{
276 struct ip_conntrack *master = ct->master;
277 DEBUGP(" entering\n");
278
279 if (!master)
280 DEBUGP("no master !?!\n");
281 else
282 ip_ct_gre_keymap_destroy(master);
283}
284
285/* protocol helper struct */
286static struct ip_conntrack_protocol gre = {
287 .proto = IPPROTO_GRE,
288 .name = "gre",
289 .pkt_to_tuple = gre_pkt_to_tuple,
290 .invert_tuple = gre_invert_tuple,
291 .print_tuple = gre_print_tuple,
292 .print_conntrack = gre_print_conntrack,
293 .packet = gre_packet,
294 .new = gre_new,
295 .destroy = gre_destroy,
296 .me = THIS_MODULE,
297#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
298 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
299 .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr,
300 .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple,
301#endif
302};
303
304/* ip_conntrack_proto_gre initialization */
305int __init ip_ct_proto_gre_init(void)
306{
307 return ip_conntrack_protocol_register(&gre);
308}
309
310void __exit ip_ct_proto_gre_fini(void)
311{
312 struct list_head *pos, *n;
313
314 /* delete all keymap entries */
315 write_lock_bh(&ip_ct_gre_lock);
316 list_for_each_safe(pos, n, &gre_keymap_list) {
317 DEBUGP("deleting keymap %p at module unload time\n", pos);
318 list_del(pos);
319 kfree(pos);
320 }
321 write_unlock_bh(&ip_ct_gre_lock);
322
323 ip_conntrack_protocol_unregister(&gre);
324}
325
326EXPORT_SYMBOL(ip_ct_gre_keymap_add);
327EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index ae3e3e655db5..dd476b191f4b 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -989,15 +989,15 @@ EXPORT_SYMBOL(need_ip_conntrack);
989EXPORT_SYMBOL(ip_conntrack_helper_register); 989EXPORT_SYMBOL(ip_conntrack_helper_register);
990EXPORT_SYMBOL(ip_conntrack_helper_unregister); 990EXPORT_SYMBOL(ip_conntrack_helper_unregister);
991EXPORT_SYMBOL(ip_ct_iterate_cleanup); 991EXPORT_SYMBOL(ip_ct_iterate_cleanup);
992EXPORT_SYMBOL(ip_ct_refresh_acct); 992EXPORT_SYMBOL(__ip_ct_refresh_acct);
993 993
994EXPORT_SYMBOL(ip_conntrack_expect_alloc); 994EXPORT_SYMBOL(ip_conntrack_expect_alloc);
995EXPORT_SYMBOL(ip_conntrack_expect_put); 995EXPORT_SYMBOL(ip_conntrack_expect_put);
996EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get); 996EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
997EXPORT_SYMBOL_GPL(ip_conntrack_expect_find);
997EXPORT_SYMBOL(ip_conntrack_expect_related); 998EXPORT_SYMBOL(ip_conntrack_expect_related);
998EXPORT_SYMBOL(ip_conntrack_unexpect_related); 999EXPORT_SYMBOL(ip_conntrack_unexpect_related);
999EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); 1000EXPORT_SYMBOL_GPL(ip_conntrack_expect_list);
1000EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find);
1001EXPORT_SYMBOL_GPL(ip_ct_unlink_expect); 1001EXPORT_SYMBOL_GPL(ip_ct_unlink_expect);
1002 1002
1003EXPORT_SYMBOL(ip_conntrack_tuple_taken); 1003EXPORT_SYMBOL(ip_conntrack_tuple_taken);
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 1adedb743f60..c3ea891d38e7 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -578,6 +578,8 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
578 578
579 return ret; 579 return ret;
580} 580}
581EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
582EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
581#endif 583#endif
582 584
583int __init ip_nat_init(void) 585int __init ip_nat_init(void)
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c
new file mode 100644
index 000000000000..3cdd0684d30d
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c
@@ -0,0 +1,401 @@
1/*
2 * ip_nat_pptp.c - Version 3.0
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 * Changes:
20 * 2002-02-10 - Version 1.3
21 * - Use ip_nat_mangle_tcp_packet() because of cloned skb's
22 * in local connections (Philip Craig <philipc@snapgear.com>)
23 * - add checks for magicCookie and pptp version
24 * - make argument list of pptp_{out,in}bound_packet() shorter
25 * - move to C99 style initializers
26 * - print version number at module loadtime
27 * 2003-09-22 - Version 1.5
28 * - use SNATed tcp sourceport as callid, since we get called before
29 * TCP header is mangled (Philip Craig <philipc@snapgear.com>)
30 * 2004-10-22 - Version 2.0
31 * - kernel 2.6.x version
32 * 2005-06-10 - Version 3.0
33 * - kernel >= 2.6.11 version,
34 * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
35 *
36 */
37
38#include <linux/config.h>
39#include <linux/module.h>
40#include <linux/ip.h>
41#include <linux/tcp.h>
42#include <net/tcp.h>
43
44#include <linux/netfilter_ipv4/ip_nat.h>
45#include <linux/netfilter_ipv4/ip_nat_rule.h>
46#include <linux/netfilter_ipv4/ip_nat_helper.h>
47#include <linux/netfilter_ipv4/ip_nat_pptp.h>
48#include <linux/netfilter_ipv4/ip_conntrack_core.h>
49#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
50#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
51#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
52
53#define IP_NAT_PPTP_VERSION "3.0"
54
55MODULE_LICENSE("GPL");
56MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
57MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
58
59
60#if 0
61extern const char *pptp_msg_name[];
62#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
63 __FUNCTION__, ## args)
64#else
65#define DEBUGP(format, args...)
66#endif
67
68static void pptp_nat_expected(struct ip_conntrack *ct,
69 struct ip_conntrack_expect *exp)
70{
71 struct ip_conntrack *master = ct->master;
72 struct ip_conntrack_expect *other_exp;
73 struct ip_conntrack_tuple t;
74 struct ip_ct_pptp_master *ct_pptp_info;
75 struct ip_nat_pptp *nat_pptp_info;
76
77 ct_pptp_info = &master->help.ct_pptp_info;
78 nat_pptp_info = &master->nat.help.nat_pptp_info;
79
80 /* And here goes the grand finale of corrosion... */
81
82 if (exp->dir == IP_CT_DIR_ORIGINAL) {
83 DEBUGP("we are PNS->PAC\n");
84 /* therefore, build tuple for PAC->PNS */
85 t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
86 t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id);
87 t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
88 t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id);
89 t.dst.protonum = IPPROTO_GRE;
90 } else {
91 DEBUGP("we are PAC->PNS\n");
92 /* build tuple for PNS->PAC */
93 t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
94 t.src.u.gre.key =
95 htons(master->nat.help.nat_pptp_info.pns_call_id);
96 t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
97 t.dst.u.gre.key =
98 htons(master->nat.help.nat_pptp_info.pac_call_id);
99 t.dst.protonum = IPPROTO_GRE;
100 }
101
102 DEBUGP("trying to unexpect other dir: ");
103 DUMP_TUPLE(&t);
104 other_exp = ip_conntrack_expect_find(&t);
105 if (other_exp) {
106 ip_conntrack_unexpect_related(other_exp);
107 ip_conntrack_expect_put(other_exp);
108 DEBUGP("success\n");
109 } else {
110 DEBUGP("not found!\n");
111 }
112
113 ip_nat_follow_master(ct, exp);
114}
115
116/* outbound packets == from PNS to PAC */
117static int
118pptp_outbound_pkt(struct sk_buff **pskb,
119 struct ip_conntrack *ct,
120 enum ip_conntrack_info ctinfo,
121 struct PptpControlHeader *ctlh,
122 union pptp_ctrl_union *pptpReq)
123
124{
125 struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
126 struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
127
128 u_int16_t msg, *cid = NULL, new_callid;
129
130 new_callid = htons(ct_pptp_info->pns_call_id);
131
132 switch (msg = ntohs(ctlh->messageType)) {
133 case PPTP_OUT_CALL_REQUEST:
134 cid = &pptpReq->ocreq.callID;
135 /* FIXME: ideally we would want to reserve a call ID
136 * here. current netfilter NAT core is not able to do
137 * this :( For now we use TCP source port. This breaks
138 * multiple calls within one control session */
139
140 /* save original call ID in nat_info */
141 nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
142
143 /* don't use tcph->source since we are at a DSTmanip
144 * hook (e.g. PREROUTING) and pkt is not mangled yet */
145 new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
146
147 /* save new call ID in ct info */
148 ct_pptp_info->pns_call_id = ntohs(new_callid);
149 break;
150 case PPTP_IN_CALL_REPLY:
151 cid = &pptpReq->icreq.callID;
152 break;
153 case PPTP_CALL_CLEAR_REQUEST:
154 cid = &pptpReq->clrreq.callID;
155 break;
156 default:
157 DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
158 (msg <= PPTP_MSG_MAX)?
159 pptp_msg_name[msg]:pptp_msg_name[0]);
160 /* fall through */
161
162 case PPTP_SET_LINK_INFO:
163 /* only need to NAT in case PAC is behind NAT box */
164 case PPTP_START_SESSION_REQUEST:
165 case PPTP_START_SESSION_REPLY:
166 case PPTP_STOP_SESSION_REQUEST:
167 case PPTP_STOP_SESSION_REPLY:
168 case PPTP_ECHO_REQUEST:
169 case PPTP_ECHO_REPLY:
170 /* no need to alter packet */
171 return NF_ACCEPT;
172 }
173
174 /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
175 * down to here */
176
177 IP_NF_ASSERT(cid);
178
179 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
180 ntohs(*cid), ntohs(new_callid));
181
182 /* mangle packet */
183 if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
184 (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
185 sizeof(new_callid),
186 (char *)&new_callid,
187 sizeof(new_callid)) == 0)
188 return NF_DROP;
189
190 return NF_ACCEPT;
191}
192
193static int
194pptp_exp_gre(struct ip_conntrack_expect *expect_orig,
195 struct ip_conntrack_expect *expect_reply)
196{
197 struct ip_ct_pptp_master *ct_pptp_info =
198 &expect_orig->master->help.ct_pptp_info;
199 struct ip_nat_pptp *nat_pptp_info =
200 &expect_orig->master->nat.help.nat_pptp_info;
201
202 struct ip_conntrack *ct = expect_orig->master;
203
204 struct ip_conntrack_tuple inv_t;
205 struct ip_conntrack_tuple *orig_t, *reply_t;
206
207 /* save original PAC call ID in nat_info */
208 nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
209
210 /* alter expectation */
211 orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
212 reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
213
214 /* alter expectation for PNS->PAC direction */
215 invert_tuplepr(&inv_t, &expect_orig->tuple);
216 expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id);
217 expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
218 expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
219 inv_t.src.ip = reply_t->src.ip;
220 inv_t.dst.ip = reply_t->dst.ip;
221 inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
222 inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
223
224 if (!ip_conntrack_expect_related(expect_orig)) {
225 DEBUGP("successfully registered expect\n");
226 } else {
227 DEBUGP("can't expect_related(expect_orig)\n");
228 return 1;
229 }
230
231 /* alter expectation for PAC->PNS direction */
232 invert_tuplepr(&inv_t, &expect_reply->tuple);
233 expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id);
234 expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id);
235 expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id);
236 inv_t.src.ip = orig_t->src.ip;
237 inv_t.dst.ip = orig_t->dst.ip;
238 inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id);
239 inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id);
240
241 if (!ip_conntrack_expect_related(expect_reply)) {
242 DEBUGP("successfully registered expect\n");
243 } else {
244 DEBUGP("can't expect_related(expect_reply)\n");
245 ip_conntrack_unexpect_related(expect_orig);
246 return 1;
247 }
248
249 if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) {
250 DEBUGP("can't register original keymap\n");
251 ip_conntrack_unexpect_related(expect_orig);
252 ip_conntrack_unexpect_related(expect_reply);
253 return 1;
254 }
255
256 if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) {
257 DEBUGP("can't register reply keymap\n");
258 ip_conntrack_unexpect_related(expect_orig);
259 ip_conntrack_unexpect_related(expect_reply);
260 ip_ct_gre_keymap_destroy(ct);
261 return 1;
262 }
263
264 return 0;
265}
266
267/* inbound packets == from PAC to PNS */
268static int
269pptp_inbound_pkt(struct sk_buff **pskb,
270 struct ip_conntrack *ct,
271 enum ip_conntrack_info ctinfo,
272 struct PptpControlHeader *ctlh,
273 union pptp_ctrl_union *pptpReq)
274{
275 struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
276 u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
277
278 int ret = NF_ACCEPT, rv;
279
280 new_pcid = htons(nat_pptp_info->pns_call_id);
281
282 switch (msg = ntohs(ctlh->messageType)) {
283 case PPTP_OUT_CALL_REPLY:
284 pcid = &pptpReq->ocack.peersCallID;
285 cid = &pptpReq->ocack.callID;
286 break;
287 case PPTP_IN_CALL_CONNECT:
288 pcid = &pptpReq->iccon.peersCallID;
289 break;
290 case PPTP_IN_CALL_REQUEST:
291 /* only need to nat in case PAC is behind NAT box */
292 break;
293 case PPTP_WAN_ERROR_NOTIFY:
294 pcid = &pptpReq->wanerr.peersCallID;
295 break;
296 case PPTP_CALL_DISCONNECT_NOTIFY:
297 pcid = &pptpReq->disc.callID;
298 break;
299 case PPTP_SET_LINK_INFO:
300 pcid = &pptpReq->setlink.peersCallID;
301 break;
302
303 default:
304 DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)?
305 pptp_msg_name[msg]:pptp_msg_name[0]);
306 /* fall through */
307
308 case PPTP_START_SESSION_REQUEST:
309 case PPTP_START_SESSION_REPLY:
310 case PPTP_STOP_SESSION_REQUEST:
311 case PPTP_STOP_SESSION_REPLY:
312 case PPTP_ECHO_REQUEST:
313 case PPTP_ECHO_REPLY:
314 /* no need to alter packet */
315 return NF_ACCEPT;
316 }
317
318 /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
319 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
320
321 /* mangle packet */
322 IP_NF_ASSERT(pcid);
323 DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
324 ntohs(*pcid), ntohs(new_pcid));
325
326 rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
327 (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
328 sizeof(new_pcid), (char *)&new_pcid,
329 sizeof(new_pcid));
330 if (rv != NF_ACCEPT)
331 return rv;
332
333 if (new_cid) {
334 IP_NF_ASSERT(cid);
335 DEBUGP("altering call id from 0x%04x to 0x%04x\n",
336 ntohs(*cid), ntohs(new_cid));
337 rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
338 (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
339 sizeof(new_cid),
340 (char *)&new_cid,
341 sizeof(new_cid));
342 if (rv != NF_ACCEPT)
343 return rv;
344 }
345
346 /* check for earlier return value of 'switch' above */
347 if (ret != NF_ACCEPT)
348 return ret;
349
350 /* great, at least we don't need to resize packets */
351 return NF_ACCEPT;
352}
353
354
355extern int __init ip_nat_proto_gre_init(void);
356extern void __exit ip_nat_proto_gre_fini(void);
357
358static int __init init(void)
359{
360 int ret;
361
362 DEBUGP("%s: registering NAT helper\n", __FILE__);
363
364 ret = ip_nat_proto_gre_init();
365 if (ret < 0)
366 return ret;
367
368 BUG_ON(ip_nat_pptp_hook_outbound);
369 ip_nat_pptp_hook_outbound = &pptp_outbound_pkt;
370
371 BUG_ON(ip_nat_pptp_hook_inbound);
372 ip_nat_pptp_hook_inbound = &pptp_inbound_pkt;
373
374 BUG_ON(ip_nat_pptp_hook_exp_gre);
375 ip_nat_pptp_hook_exp_gre = &pptp_exp_gre;
376
377 BUG_ON(ip_nat_pptp_hook_expectfn);
378 ip_nat_pptp_hook_expectfn = &pptp_nat_expected;
379
380 printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
381 return 0;
382}
383
384static void __exit fini(void)
385{
386 DEBUGP("cleanup_module\n" );
387
388 ip_nat_pptp_hook_expectfn = NULL;
389 ip_nat_pptp_hook_exp_gre = NULL;
390 ip_nat_pptp_hook_inbound = NULL;
391 ip_nat_pptp_hook_outbound = NULL;
392
393 ip_nat_proto_gre_fini();
394 /* Make sure noone calls it, meanwhile */
395 synchronize_net();
396
397 printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
398}
399
400module_init(init);
401module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c
new file mode 100644
index 000000000000..7c1285401672
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_proto_gre.c
@@ -0,0 +1,214 @@
1/*
2 * ip_nat_proto_gre.c - Version 2.0
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/config.h>
27#include <linux/module.h>
28#include <linux/ip.h>
29#include <linux/netfilter_ipv4/ip_nat.h>
30#include <linux/netfilter_ipv4/ip_nat_rule.h>
31#include <linux/netfilter_ipv4/ip_nat_protocol.h>
32#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
33
34MODULE_LICENSE("GPL");
35MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
36MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
37
38#if 0
39#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
40 __FUNCTION__, ## args)
41#else
42#define DEBUGP(x, args...)
43#endif
44
45/* is key in given range between min and max */
46static int
47gre_in_range(const struct ip_conntrack_tuple *tuple,
48 enum ip_nat_manip_type maniptype,
49 const union ip_conntrack_manip_proto *min,
50 const union ip_conntrack_manip_proto *max)
51{
52 u_int32_t key;
53
54 if (maniptype == IP_NAT_MANIP_SRC)
55 key = tuple->src.u.gre.key;
56 else
57 key = tuple->dst.u.gre.key;
58
59 return ntohl(key) >= ntohl(min->gre.key)
60 && ntohl(key) <= ntohl(max->gre.key);
61}
62
63/* generate unique tuple ... */
64static int
65gre_unique_tuple(struct ip_conntrack_tuple *tuple,
66 const struct ip_nat_range *range,
67 enum ip_nat_manip_type maniptype,
68 const struct ip_conntrack *conntrack)
69{
70 static u_int16_t key;
71 u_int16_t *keyptr;
72 unsigned int min, i, range_size;
73
74 if (maniptype == IP_NAT_MANIP_SRC)
75 keyptr = &tuple->src.u.gre.key;
76 else
77 keyptr = &tuple->dst.u.gre.key;
78
79 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
80 DEBUGP("%p: NATing GRE PPTP\n", conntrack);
81 min = 1;
82 range_size = 0xffff;
83 } else {
84 min = ntohl(range->min.gre.key);
85 range_size = ntohl(range->max.gre.key) - min + 1;
86 }
87
88 DEBUGP("min = %u, range_size = %u\n", min, range_size);
89
90 for (i = 0; i < range_size; i++, key++) {
91 *keyptr = htonl(min + key % range_size);
92 if (!ip_nat_used_tuple(tuple, conntrack))
93 return 1;
94 }
95
96 DEBUGP("%p: no NAT mapping\n", conntrack);
97
98 return 0;
99}
100
101/* manipulate a GRE packet according to maniptype */
102static int
103gre_manip_pkt(struct sk_buff **pskb,
104 unsigned int iphdroff,
105 const struct ip_conntrack_tuple *tuple,
106 enum ip_nat_manip_type maniptype)
107{
108 struct gre_hdr *greh;
109 struct gre_hdr_pptp *pgreh;
110 struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
111 unsigned int hdroff = iphdroff + iph->ihl*4;
112
113 /* pgreh includes two optional 32bit fields which are not required
114 * to be there. That's where the magic '8' comes from */
115 if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8))
116 return 0;
117
118 greh = (void *)(*pskb)->data + hdroff;
119 pgreh = (struct gre_hdr_pptp *) greh;
120
121 /* we only have destination manip of a packet, since 'source key'
122 * is not present in the packet itself */
123 if (maniptype == IP_NAT_MANIP_DST) {
124 /* key manipulation is always dest */
125 switch (greh->version) {
126 case 0:
127 if (!greh->key) {
128 DEBUGP("can't nat GRE w/o key\n");
129 break;
130 }
131 if (greh->csum) {
132 /* FIXME: Never tested this code... */
133 *(gre_csum(greh)) =
134 ip_nat_cheat_check(~*(gre_key(greh)),
135 tuple->dst.u.gre.key,
136 *(gre_csum(greh)));
137 }
138 *(gre_key(greh)) = tuple->dst.u.gre.key;
139 break;
140 case GRE_VERSION_PPTP:
141 DEBUGP("call_id -> 0x%04x\n",
142 ntohl(tuple->dst.u.gre.key));
143 pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key));
144 break;
145 default:
146 DEBUGP("can't nat unknown GRE version\n");
147 return 0;
148 break;
149 }
150 }
151 return 1;
152}
153
154/* print out a nat tuple */
155static unsigned int
156gre_print(char *buffer,
157 const struct ip_conntrack_tuple *match,
158 const struct ip_conntrack_tuple *mask)
159{
160 unsigned int len = 0;
161
162 if (mask->src.u.gre.key)
163 len += sprintf(buffer + len, "srckey=0x%x ",
164 ntohl(match->src.u.gre.key));
165
166 if (mask->dst.u.gre.key)
167 len += sprintf(buffer + len, "dstkey=0x%x ",
168 ntohl(match->src.u.gre.key));
169
170 return len;
171}
172
173/* print a range of keys */
174static unsigned int
175gre_print_range(char *buffer, const struct ip_nat_range *range)
176{
177 if (range->min.gre.key != 0
178 || range->max.gre.key != 0xFFFF) {
179 if (range->min.gre.key == range->max.gre.key)
180 return sprintf(buffer, "key 0x%x ",
181 ntohl(range->min.gre.key));
182 else
183 return sprintf(buffer, "keys 0x%u-0x%u ",
184 ntohl(range->min.gre.key),
185 ntohl(range->max.gre.key));
186 } else
187 return 0;
188}
189
190/* nat helper struct */
191static struct ip_nat_protocol gre = {
192 .name = "GRE",
193 .protonum = IPPROTO_GRE,
194 .manip_pkt = gre_manip_pkt,
195 .in_range = gre_in_range,
196 .unique_tuple = gre_unique_tuple,
197 .print = gre_print,
198 .print_range = gre_print_range,
199#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
200 defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
201 .range_to_nfattr = ip_nat_port_range_to_nfattr,
202 .nfattr_to_range = ip_nat_port_nfattr_to_range,
203#endif
204};
205
206int __init ip_nat_proto_gre_init(void)
207{
208 return ip_nat_protocol_register(&gre);
209}
210
211void __exit ip_nat_proto_gre_fini(void)
212{
213 ip_nat_protocol_unregister(&gre);
214}
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 304bb0a1d4f0..4b0d7e4d6269 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -361,7 +361,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
361 361
362 if (type && code) { 362 if (type && code) {
363 get_user(fl->fl_icmp_type, type); 363 get_user(fl->fl_icmp_type, type);
364 __get_user(fl->fl_icmp_code, code); 364 get_user(fl->fl_icmp_code, code);
365 probed = 1; 365 probed = 1;
366 } 366 }
367 break; 367 break;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index a88db28b0af7..b1a63b2c6b4a 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -384,7 +384,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
384 newtp->frto_counter = 0; 384 newtp->frto_counter = 0;
385 newtp->frto_highmark = 0; 385 newtp->frto_highmark = 0;
386 386
387 newicsk->icsk_ca_ops = &tcp_reno; 387 newicsk->icsk_ca_ops = &tcp_init_congestion_ops;
388 388
389 tcp_set_ca_state(newsk, TCP_CA_Open); 389 tcp_set_ca_state(newsk, TCP_CA_Open);
390 tcp_init_xmit_timers(newsk); 390 tcp_init_xmit_timers(newsk);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b018e31b6530..d6e3d269e906 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -461,9 +461,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
461 flags = TCP_SKB_CB(skb)->flags; 461 flags = TCP_SKB_CB(skb)->flags;
462 TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); 462 TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH);
463 TCP_SKB_CB(buff)->flags = flags; 463 TCP_SKB_CB(buff)->flags = flags;
464 TCP_SKB_CB(buff)->sacked = 464 TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked;
465 (TCP_SKB_CB(skb)->sacked &
466 (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL));
467 TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; 465 TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL;
468 466
469 if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { 467 if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) {
@@ -501,11 +499,26 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
501 tcp_skb_pcount(buff); 499 tcp_skb_pcount(buff);
502 500
503 tp->packets_out -= diff; 501 tp->packets_out -= diff;
502
503 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)
504 tp->sacked_out -= diff;
505 if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
506 tp->retrans_out -= diff;
507
504 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { 508 if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
505 tp->lost_out -= diff; 509 tp->lost_out -= diff;
506 tp->left_out -= diff; 510 tp->left_out -= diff;
507 } 511 }
512
508 if (diff > 0) { 513 if (diff > 0) {
514 /* Adjust Reno SACK estimate. */
515 if (!tp->rx_opt.sack_ok) {
516 tp->sacked_out -= diff;
517 if ((int)tp->sacked_out < 0)
518 tp->sacked_out = 0;
519 tcp_sync_left_out(tp);
520 }
521
509 tp->fackets_out -= diff; 522 tp->fackets_out -= diff;
510 if ((int)tp->fackets_out < 0) 523 if ((int)tp->fackets_out < 0)
511 tp->fackets_out = 0; 524 tp->fackets_out = 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 1cb8adb2787f..2da514b16d95 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -1955,6 +1955,57 @@ static void __exit fini(void)
1955#endif 1955#endif
1956} 1956}
1957 1957
1958/*
1959 * find specified header up to transport protocol header.
1960 * If found target header, the offset to the header is set to *offset
1961 * and return 0. otherwise, return -1.
1962 *
1963 * Notes: - non-1st Fragment Header isn't skipped.
1964 * - ESP header isn't skipped.
1965 * - The target header may be trancated.
1966 */
1967int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target)
1968{
1969 unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data;
1970 u8 nexthdr = skb->nh.ipv6h->nexthdr;
1971 unsigned int len = skb->len - start;
1972
1973 while (nexthdr != target) {
1974 struct ipv6_opt_hdr _hdr, *hp;
1975 unsigned int hdrlen;
1976
1977 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE)
1978 return -1;
1979 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
1980 if (hp == NULL)
1981 return -1;
1982 if (nexthdr == NEXTHDR_FRAGMENT) {
1983 unsigned short _frag_off, *fp;
1984 fp = skb_header_pointer(skb,
1985 start+offsetof(struct frag_hdr,
1986 frag_off),
1987 sizeof(_frag_off),
1988 &_frag_off);
1989 if (fp == NULL)
1990 return -1;
1991
1992 if (ntohs(*fp) & ~0x7)
1993 return -1;
1994 hdrlen = 8;
1995 } else if (nexthdr == NEXTHDR_AUTH)
1996 hdrlen = (hp->hdrlen + 2) << 2;
1997 else
1998 hdrlen = ipv6_optlen(hp);
1999
2000 nexthdr = hp->nexthdr;
2001 len -= hdrlen;
2002 start += hdrlen;
2003 }
2004
2005 *offset = start;
2006 return 0;
2007}
2008
1958EXPORT_SYMBOL(ip6t_register_table); 2009EXPORT_SYMBOL(ip6t_register_table);
1959EXPORT_SYMBOL(ip6t_unregister_table); 2010EXPORT_SYMBOL(ip6t_unregister_table);
1960EXPORT_SYMBOL(ip6t_do_table); 2011EXPORT_SYMBOL(ip6t_do_table);
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match);
1963EXPORT_SYMBOL(ip6t_register_target); 2014EXPORT_SYMBOL(ip6t_register_target);
1964EXPORT_SYMBOL(ip6t_unregister_target); 2015EXPORT_SYMBOL(ip6t_unregister_target);
1965EXPORT_SYMBOL(ip6t_ext_hdr); 2016EXPORT_SYMBOL(ip6t_ext_hdr);
2017EXPORT_SYMBOL(ipv6_find_hdr);
1966 2018
1967module_init(init); 2019module_init(init);
1968module_exit(fini); 2020module_exit(fini);
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index d5b94f142bba..dde37793d20b 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -48,92 +48,21 @@ match(const struct sk_buff *skb,
48 unsigned int protoff, 48 unsigned int protoff,
49 int *hotdrop) 49 int *hotdrop)
50{ 50{
51 struct ip_auth_hdr *ah = NULL, _ah; 51 struct ip_auth_hdr *ah, _ah;
52 const struct ip6t_ah *ahinfo = matchinfo; 52 const struct ip6t_ah *ahinfo = matchinfo;
53 unsigned int temp;
54 int len;
55 u8 nexthdr;
56 unsigned int ptr; 53 unsigned int ptr;
57 unsigned int hdrlen = 0; 54 unsigned int hdrlen = 0;
58 55
59 /*DEBUGP("IPv6 AH entered\n");*/ 56 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0)
60 /* if (opt->auth == 0) return 0;
61 * It does not filled on output */
62
63 /* type of the 1st exthdr */
64 nexthdr = skb->nh.ipv6h->nexthdr;
65 /* pointer to the 1st exthdr */
66 ptr = sizeof(struct ipv6hdr);
67 /* available length */
68 len = skb->len - ptr;
69 temp = 0;
70
71 while (ip6t_ext_hdr(nexthdr)) {
72 struct ipv6_opt_hdr _hdr, *hp;
73
74 DEBUGP("ipv6_ah header iteration \n");
75
76 /* Is there enough space for the next ext header? */
77 if (len < sizeof(struct ipv6_opt_hdr))
78 return 0;
79 /* No more exthdr -> evaluate */
80 if (nexthdr == NEXTHDR_NONE)
81 break;
82 /* ESP -> evaluate */
83 if (nexthdr == NEXTHDR_ESP)
84 break;
85
86 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
87 BUG_ON(hp == NULL);
88
89 /* Calculate the header length */
90 if (nexthdr == NEXTHDR_FRAGMENT)
91 hdrlen = 8;
92 else if (nexthdr == NEXTHDR_AUTH)
93 hdrlen = (hp->hdrlen+2)<<2;
94 else
95 hdrlen = ipv6_optlen(hp);
96
97 /* AH -> evaluate */
98 if (nexthdr == NEXTHDR_AUTH) {
99 temp |= MASK_AH;
100 break;
101 }
102
103
104 /* set the flag */
105 switch (nexthdr) {
106 case NEXTHDR_HOP:
107 case NEXTHDR_ROUTING:
108 case NEXTHDR_FRAGMENT:
109 case NEXTHDR_AUTH:
110 case NEXTHDR_DEST:
111 break;
112 default:
113 DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
114 return 0;
115 }
116
117 nexthdr = hp->nexthdr;
118 len -= hdrlen;
119 ptr += hdrlen;
120 if (ptr > skb->len) {
121 DEBUGP("ipv6_ah: new pointer too large! \n");
122 break;
123 }
124 }
125
126 /* AH header not found */
127 if (temp != MASK_AH)
128 return 0; 57 return 0;
129 58
130 if (len < sizeof(struct ip_auth_hdr)){ 59 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
60 if (ah == NULL) {
131 *hotdrop = 1; 61 *hotdrop = 1;
132 return 0; 62 return 0;
133 } 63 }
134 64
135 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); 65 hdrlen = (ah->hdrlen + 2) << 2;
136 BUG_ON(ah == NULL);
137 66
138 DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); 67 DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
139 DEBUGP("RES %04X ", ah->reserved); 68 DEBUGP("RES %04X ", ah->reserved);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 540925e4a7a8..c450a635e54b 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
63 struct ipv6_opt_hdr _optsh, *oh; 63 struct ipv6_opt_hdr _optsh, *oh;
64 const struct ip6t_opts *optinfo = matchinfo; 64 const struct ip6t_opts *optinfo = matchinfo;
65 unsigned int temp; 65 unsigned int temp;
66 unsigned int len;
67 u8 nexthdr;
68 unsigned int ptr; 66 unsigned int ptr;
69 unsigned int hdrlen = 0; 67 unsigned int hdrlen = 0;
70 unsigned int ret = 0; 68 unsigned int ret = 0;
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
72 u8 _optlen, *lp = NULL; 70 u8 _optlen, *lp = NULL;
73 unsigned int optlen; 71 unsigned int optlen;
74 72
75 /* type of the 1st exthdr */
76 nexthdr = skb->nh.ipv6h->nexthdr;
77 /* pointer to the 1st exthdr */
78 ptr = sizeof(struct ipv6hdr);
79 /* available length */
80 len = skb->len - ptr;
81 temp = 0;
82
83 while (ip6t_ext_hdr(nexthdr)) {
84 struct ipv6_opt_hdr _hdr, *hp;
85
86 DEBUGP("ipv6_opts header iteration \n");
87
88 /* Is there enough space for the next ext header? */
89 if (len < (int)sizeof(struct ipv6_opt_hdr))
90 return 0;
91 /* No more exthdr -> evaluate */
92 if (nexthdr == NEXTHDR_NONE) {
93 break;
94 }
95 /* ESP -> evaluate */
96 if (nexthdr == NEXTHDR_ESP) {
97 break;
98 }
99
100 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
101 BUG_ON(hp == NULL);
102
103 /* Calculate the header length */
104 if (nexthdr == NEXTHDR_FRAGMENT) {
105 hdrlen = 8;
106 } else if (nexthdr == NEXTHDR_AUTH)
107 hdrlen = (hp->hdrlen+2)<<2;
108 else
109 hdrlen = ipv6_optlen(hp);
110
111 /* OPTS -> evaluate */
112#if HOPBYHOP 73#if HOPBYHOP
113 if (nexthdr == NEXTHDR_HOP) { 74 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
114 temp |= MASK_HOPOPTS;
115#else 75#else
116 if (nexthdr == NEXTHDR_DEST) { 76 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
117 temp |= MASK_DSTOPTS;
118#endif 77#endif
119 break; 78 return 0;
120 }
121
122 79
123 /* set the flag */ 80 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
124 switch (nexthdr){ 81 if (oh == NULL){
125 case NEXTHDR_HOP:
126 case NEXTHDR_ROUTING:
127 case NEXTHDR_FRAGMENT:
128 case NEXTHDR_AUTH:
129 case NEXTHDR_DEST:
130 break;
131 default:
132 DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
133 return 0;
134 break;
135 }
136
137 nexthdr = hp->nexthdr;
138 len -= hdrlen;
139 ptr += hdrlen;
140 if ( ptr > skb->len ) {
141 DEBUGP("ipv6_opts: new pointer is too large! \n");
142 break;
143 }
144 }
145
146 /* OPTIONS header not found */
147#if HOPBYHOP
148 if ( temp != MASK_HOPOPTS ) return 0;
149#else
150 if ( temp != MASK_DSTOPTS ) return 0;
151#endif
152
153 if (len < (int)sizeof(struct ipv6_opt_hdr)){
154 *hotdrop = 1; 82 *hotdrop = 1;
155 return 0; 83 return 0;
156 } 84 }
157 85
158 if (len < hdrlen){ 86 hdrlen = ipv6_optlen(oh);
87 if (skb->len - ptr < hdrlen){
159 /* Packet smaller than it's length field */ 88 /* Packet smaller than it's length field */
160 return 0; 89 return 0;
161 } 90 }
162 91
163 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
164 BUG_ON(oh == NULL);
165
166 DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); 92 DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
167 93
168 DEBUGP("len %02X %04X %02X ", 94 DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index e39dd236fd8e..24bc0cde43a1 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -48,87 +48,22 @@ match(const struct sk_buff *skb,
48 unsigned int protoff, 48 unsigned int protoff,
49 int *hotdrop) 49 int *hotdrop)
50{ 50{
51 struct ip_esp_hdr _esp, *eh = NULL; 51 struct ip_esp_hdr _esp, *eh;
52 const struct ip6t_esp *espinfo = matchinfo; 52 const struct ip6t_esp *espinfo = matchinfo;
53 unsigned int temp;
54 int len;
55 u8 nexthdr;
56 unsigned int ptr; 53 unsigned int ptr;
57 54
58 /* Make sure this isn't an evil packet */ 55 /* Make sure this isn't an evil packet */
59 /*DEBUGP("ipv6_esp entered \n");*/ 56 /*DEBUGP("ipv6_esp entered \n");*/
60 57
61 /* type of the 1st exthdr */ 58 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0)
62 nexthdr = skb->nh.ipv6h->nexthdr;
63 /* pointer to the 1st exthdr */
64 ptr = sizeof(struct ipv6hdr);
65 /* available length */
66 len = skb->len - ptr;
67 temp = 0;
68
69 while (ip6t_ext_hdr(nexthdr)) {
70 struct ipv6_opt_hdr _hdr, *hp;
71 int hdrlen;
72
73 DEBUGP("ipv6_esp header iteration \n");
74
75 /* Is there enough space for the next ext header? */
76 if (len < sizeof(struct ipv6_opt_hdr))
77 return 0;
78 /* No more exthdr -> evaluate */
79 if (nexthdr == NEXTHDR_NONE)
80 break;
81 /* ESP -> evaluate */
82 if (nexthdr == NEXTHDR_ESP) {
83 temp |= MASK_ESP;
84 break;
85 }
86
87 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
88 BUG_ON(hp == NULL);
89
90 /* Calculate the header length */
91 if (nexthdr == NEXTHDR_FRAGMENT)
92 hdrlen = 8;
93 else if (nexthdr == NEXTHDR_AUTH)
94 hdrlen = (hp->hdrlen+2)<<2;
95 else
96 hdrlen = ipv6_optlen(hp);
97
98 /* set the flag */
99 switch (nexthdr) {
100 case NEXTHDR_HOP:
101 case NEXTHDR_ROUTING:
102 case NEXTHDR_FRAGMENT:
103 case NEXTHDR_AUTH:
104 case NEXTHDR_DEST:
105 break;
106 default:
107 DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
108 return 0;
109 }
110
111 nexthdr = hp->nexthdr;
112 len -= hdrlen;
113 ptr += hdrlen;
114 if (ptr > skb->len) {
115 DEBUGP("ipv6_esp: new pointer too large! \n");
116 break;
117 }
118 }
119
120 /* ESP header not found */
121 if (temp != MASK_ESP)
122 return 0; 59 return 0;
123 60
124 if (len < sizeof(struct ip_esp_hdr)) { 61 eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
62 if (eh == NULL) {
125 *hotdrop = 1; 63 *hotdrop = 1;
126 return 0; 64 return 0;
127 } 65 }
128 66
129 eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
130 BUG_ON(eh == NULL);
131
132 DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); 67 DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
133 68
134 return (eh != NULL) 69 return (eh != NULL)
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 4bfa30a9bc80..085d5f8eea29 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -48,90 +48,18 @@ match(const struct sk_buff *skb,
48 unsigned int protoff, 48 unsigned int protoff,
49 int *hotdrop) 49 int *hotdrop)
50{ 50{
51 struct frag_hdr _frag, *fh = NULL; 51 struct frag_hdr _frag, *fh;
52 const struct ip6t_frag *fraginfo = matchinfo; 52 const struct ip6t_frag *fraginfo = matchinfo;
53 unsigned int temp;
54 int len;
55 u8 nexthdr;
56 unsigned int ptr; 53 unsigned int ptr;
57 unsigned int hdrlen = 0;
58
59 /* type of the 1st exthdr */
60 nexthdr = skb->nh.ipv6h->nexthdr;
61 /* pointer to the 1st exthdr */
62 ptr = sizeof(struct ipv6hdr);
63 /* available length */
64 len = skb->len - ptr;
65 temp = 0;
66
67 while (ip6t_ext_hdr(nexthdr)) {
68 struct ipv6_opt_hdr _hdr, *hp;
69
70 DEBUGP("ipv6_frag header iteration \n");
71
72 /* Is there enough space for the next ext header? */
73 if (len < (int)sizeof(struct ipv6_opt_hdr))
74 return 0;
75 /* No more exthdr -> evaluate */
76 if (nexthdr == NEXTHDR_NONE) {
77 break;
78 }
79 /* ESP -> evaluate */
80 if (nexthdr == NEXTHDR_ESP) {
81 break;
82 }
83
84 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
85 BUG_ON(hp == NULL);
86
87 /* Calculate the header length */
88 if (nexthdr == NEXTHDR_FRAGMENT) {
89 hdrlen = 8;
90 } else if (nexthdr == NEXTHDR_AUTH)
91 hdrlen = (hp->hdrlen+2)<<2;
92 else
93 hdrlen = ipv6_optlen(hp);
94
95 /* FRAG -> evaluate */
96 if (nexthdr == NEXTHDR_FRAGMENT) {
97 temp |= MASK_FRAGMENT;
98 break;
99 }
100
101
102 /* set the flag */
103 switch (nexthdr){
104 case NEXTHDR_HOP:
105 case NEXTHDR_ROUTING:
106 case NEXTHDR_FRAGMENT:
107 case NEXTHDR_AUTH:
108 case NEXTHDR_DEST:
109 break;
110 default:
111 DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr);
112 return 0;
113 break;
114 }
115
116 nexthdr = hp->nexthdr;
117 len -= hdrlen;
118 ptr += hdrlen;
119 if ( ptr > skb->len ) {
120 DEBUGP("ipv6_frag: new pointer too large! \n");
121 break;
122 }
123 }
124
125 /* FRAG header not found */
126 if ( temp != MASK_FRAGMENT ) return 0;
127
128 if (len < sizeof(struct frag_hdr)){
129 *hotdrop = 1;
130 return 0;
131 }
132 54
133 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); 55 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0)
134 BUG_ON(fh == NULL); 56 return 0;
57
58 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
59 if (fh == NULL){
60 *hotdrop = 1;
61 return 0;
62 }
135 63
136 DEBUGP("INFO %04X ", fh->frag_off); 64 DEBUGP("INFO %04X ", fh->frag_off);
137 DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); 65 DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 27f3650d127e..1d09485111d0 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
63 struct ipv6_opt_hdr _optsh, *oh; 63 struct ipv6_opt_hdr _optsh, *oh;
64 const struct ip6t_opts *optinfo = matchinfo; 64 const struct ip6t_opts *optinfo = matchinfo;
65 unsigned int temp; 65 unsigned int temp;
66 unsigned int len;
67 u8 nexthdr;
68 unsigned int ptr; 66 unsigned int ptr;
69 unsigned int hdrlen = 0; 67 unsigned int hdrlen = 0;
70 unsigned int ret = 0; 68 unsigned int ret = 0;
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
72 u8 _optlen, *lp = NULL; 70 u8 _optlen, *lp = NULL;
73 unsigned int optlen; 71 unsigned int optlen;
74 72
75 /* type of the 1st exthdr */
76 nexthdr = skb->nh.ipv6h->nexthdr;
77 /* pointer to the 1st exthdr */
78 ptr = sizeof(struct ipv6hdr);
79 /* available length */
80 len = skb->len - ptr;
81 temp = 0;
82
83 while (ip6t_ext_hdr(nexthdr)) {
84 struct ipv6_opt_hdr _hdr, *hp;
85
86 DEBUGP("ipv6_opts header iteration \n");
87
88 /* Is there enough space for the next ext header? */
89 if (len < (int)sizeof(struct ipv6_opt_hdr))
90 return 0;
91 /* No more exthdr -> evaluate */
92 if (nexthdr == NEXTHDR_NONE) {
93 break;
94 }
95 /* ESP -> evaluate */
96 if (nexthdr == NEXTHDR_ESP) {
97 break;
98 }
99
100 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
101 BUG_ON(hp == NULL);
102
103 /* Calculate the header length */
104 if (nexthdr == NEXTHDR_FRAGMENT) {
105 hdrlen = 8;
106 } else if (nexthdr == NEXTHDR_AUTH)
107 hdrlen = (hp->hdrlen+2)<<2;
108 else
109 hdrlen = ipv6_optlen(hp);
110
111 /* OPTS -> evaluate */
112#if HOPBYHOP 73#if HOPBYHOP
113 if (nexthdr == NEXTHDR_HOP) { 74 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0)
114 temp |= MASK_HOPOPTS;
115#else 75#else
116 if (nexthdr == NEXTHDR_DEST) { 76 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0)
117 temp |= MASK_DSTOPTS;
118#endif 77#endif
119 break; 78 return 0;
120 }
121
122 79
123 /* set the flag */ 80 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
124 switch (nexthdr){ 81 if (oh == NULL){
125 case NEXTHDR_HOP:
126 case NEXTHDR_ROUTING:
127 case NEXTHDR_FRAGMENT:
128 case NEXTHDR_AUTH:
129 case NEXTHDR_DEST:
130 break;
131 default:
132 DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
133 return 0;
134 break;
135 }
136
137 nexthdr = hp->nexthdr;
138 len -= hdrlen;
139 ptr += hdrlen;
140 if ( ptr > skb->len ) {
141 DEBUGP("ipv6_opts: new pointer is too large! \n");
142 break;
143 }
144 }
145
146 /* OPTIONS header not found */
147#if HOPBYHOP
148 if ( temp != MASK_HOPOPTS ) return 0;
149#else
150 if ( temp != MASK_DSTOPTS ) return 0;
151#endif
152
153 if (len < (int)sizeof(struct ipv6_opt_hdr)){
154 *hotdrop = 1; 82 *hotdrop = 1;
155 return 0; 83 return 0;
156 } 84 }
157 85
158 if (len < hdrlen){ 86 hdrlen = ipv6_optlen(oh);
87 if (skb->len - ptr < hdrlen){
159 /* Packet smaller than it's length field */ 88 /* Packet smaller than it's length field */
160 return 0; 89 return 0;
161 } 90 }
162 91
163 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
164 BUG_ON(oh == NULL);
165
166 DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); 92 DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
167 93
168 DEBUGP("len %02X %04X %02X ", 94 DEBUGP("len %02X %04X %02X ",
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 2bb670037df3..beb2fd5cebbb 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -50,98 +50,29 @@ match(const struct sk_buff *skb,
50 unsigned int protoff, 50 unsigned int protoff,
51 int *hotdrop) 51 int *hotdrop)
52{ 52{
53 struct ipv6_rt_hdr _route, *rh = NULL; 53 struct ipv6_rt_hdr _route, *rh;
54 const struct ip6t_rt *rtinfo = matchinfo; 54 const struct ip6t_rt *rtinfo = matchinfo;
55 unsigned int temp; 55 unsigned int temp;
56 unsigned int len;
57 u8 nexthdr;
58 unsigned int ptr; 56 unsigned int ptr;
59 unsigned int hdrlen = 0; 57 unsigned int hdrlen = 0;
60 unsigned int ret = 0; 58 unsigned int ret = 0;
61 struct in6_addr *ap, _addr; 59 struct in6_addr *ap, _addr;
62 60
63 /* type of the 1st exthdr */ 61 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0)
64 nexthdr = skb->nh.ipv6h->nexthdr; 62 return 0;
65 /* pointer to the 1st exthdr */
66 ptr = sizeof(struct ipv6hdr);
67 /* available length */
68 len = skb->len - ptr;
69 temp = 0;
70 63
71 while (ip6t_ext_hdr(nexthdr)) { 64 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
72 struct ipv6_opt_hdr _hdr, *hp; 65 if (rh == NULL){
73
74 DEBUGP("ipv6_rt header iteration \n");
75
76 /* Is there enough space for the next ext header? */
77 if (len < (int)sizeof(struct ipv6_opt_hdr))
78 return 0;
79 /* No more exthdr -> evaluate */
80 if (nexthdr == NEXTHDR_NONE) {
81 break;
82 }
83 /* ESP -> evaluate */
84 if (nexthdr == NEXTHDR_ESP) {
85 break;
86 }
87
88 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
89 BUG_ON(hp == NULL);
90
91 /* Calculate the header length */
92 if (nexthdr == NEXTHDR_FRAGMENT) {
93 hdrlen = 8;
94 } else if (nexthdr == NEXTHDR_AUTH)
95 hdrlen = (hp->hdrlen+2)<<2;
96 else
97 hdrlen = ipv6_optlen(hp);
98
99 /* ROUTING -> evaluate */
100 if (nexthdr == NEXTHDR_ROUTING) {
101 temp |= MASK_ROUTING;
102 break;
103 }
104
105
106 /* set the flag */
107 switch (nexthdr){
108 case NEXTHDR_HOP:
109 case NEXTHDR_ROUTING:
110 case NEXTHDR_FRAGMENT:
111 case NEXTHDR_AUTH:
112 case NEXTHDR_DEST:
113 break;
114 default:
115 DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr);
116 return 0;
117 break;
118 }
119
120 nexthdr = hp->nexthdr;
121 len -= hdrlen;
122 ptr += hdrlen;
123 if ( ptr > skb->len ) {
124 DEBUGP("ipv6_rt: new pointer is too large! \n");
125 break;
126 }
127 }
128
129 /* ROUTING header not found */
130 if ( temp != MASK_ROUTING ) return 0;
131
132 if (len < (int)sizeof(struct ipv6_rt_hdr)){
133 *hotdrop = 1; 66 *hotdrop = 1;
134 return 0; 67 return 0;
135 } 68 }
136 69
137 if (len < hdrlen){ 70 hdrlen = ipv6_optlen(rh);
71 if (skb->len - ptr < hdrlen){
138 /* Pcket smaller than its length field */ 72 /* Pcket smaller than its length field */
139 return 0; 73 return 0;
140 } 74 }
141 75
142 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
143 BUG_ON(rh == NULL);
144
145 DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); 76 DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
146 DEBUGP("TYPE %04X ", rh->type); 77 DEBUGP("TYPE %04X ", rh->type);
147 DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); 78 DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 5aa3691c578d..a1265a320b11 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
627 627
628 if (type && code) { 628 if (type && code) {
629 get_user(fl->fl_icmp_type, type); 629 get_user(fl->fl_icmp_type, type);
630 __get_user(fl->fl_icmp_code, code); 630 get_user(fl->fl_icmp_code, code);
631 probed = 1; 631 probed = 1;
632 } 632 }
633 break; 633 break;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8690f171c1ef..ee865d88183b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -36,6 +36,11 @@
36 * Michal Ostrowski : Module initialization cleanup. 36 * Michal Ostrowski : Module initialization cleanup.
37 * Ulises Alonso : Frame number limit removal and 37 * Ulises Alonso : Frame number limit removal and
38 * packet_set_ring memory leak. 38 * packet_set_ring memory leak.
39 * Eric Biederman : Allow for > 8 byte hardware addresses.
40 * The convention is that longer addresses
41 * will simply extend the hardware address
42 * byte arrays at the end of sockaddr_ll
43 * and packet_mreq.
39 * 44 *
40 * This program is free software; you can redistribute it and/or 45 * This program is free software; you can redistribute it and/or
41 * modify it under the terms of the GNU General Public License 46 * modify it under the terms of the GNU General Public License
@@ -161,7 +166,17 @@ struct packet_mclist
161 int count; 166 int count;
162 unsigned short type; 167 unsigned short type;
163 unsigned short alen; 168 unsigned short alen;
164 unsigned char addr[8]; 169 unsigned char addr[MAX_ADDR_LEN];
170};
171/* identical to struct packet_mreq except it has
172 * a longer address field.
173 */
174struct packet_mreq_max
175{
176 int mr_ifindex;
177 unsigned short mr_type;
178 unsigned short mr_alen;
179 unsigned char mr_address[MAX_ADDR_LEN];
165}; 180};
166#endif 181#endif
167#ifdef CONFIG_PACKET_MMAP 182#ifdef CONFIG_PACKET_MMAP
@@ -716,6 +731,8 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
716 err = -EINVAL; 731 err = -EINVAL;
717 if (msg->msg_namelen < sizeof(struct sockaddr_ll)) 732 if (msg->msg_namelen < sizeof(struct sockaddr_ll))
718 goto out; 733 goto out;
734 if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr)))
735 goto out;
719 ifindex = saddr->sll_ifindex; 736 ifindex = saddr->sll_ifindex;
720 proto = saddr->sll_protocol; 737 proto = saddr->sll_protocol;
721 addr = saddr->sll_addr; 738 addr = saddr->sll_addr;
@@ -744,6 +761,12 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock,
744 if (dev->hard_header) { 761 if (dev->hard_header) {
745 int res; 762 int res;
746 err = -EINVAL; 763 err = -EINVAL;
764 if (saddr) {
765 if (saddr->sll_halen != dev->addr_len)
766 goto out_free;
767 if (saddr->sll_hatype != dev->type)
768 goto out_free;
769 }
747 res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); 770 res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len);
748 if (sock->type != SOCK_DGRAM) { 771 if (sock->type != SOCK_DGRAM) {
749 skb->tail = skb->data; 772 skb->tail = skb->data;
@@ -1045,6 +1068,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1045 struct sock *sk = sock->sk; 1068 struct sock *sk = sock->sk;
1046 struct sk_buff *skb; 1069 struct sk_buff *skb;
1047 int copied, err; 1070 int copied, err;
1071 struct sockaddr_ll *sll;
1048 1072
1049 err = -EINVAL; 1073 err = -EINVAL;
1050 if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) 1074 if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT))
@@ -1057,16 +1081,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1057#endif 1081#endif
1058 1082
1059 /* 1083 /*
1060 * If the address length field is there to be filled in, we fill
1061 * it in now.
1062 */
1063
1064 if (sock->type == SOCK_PACKET)
1065 msg->msg_namelen = sizeof(struct sockaddr_pkt);
1066 else
1067 msg->msg_namelen = sizeof(struct sockaddr_ll);
1068
1069 /*
1070 * Call the generic datagram receiver. This handles all sorts 1084 * Call the generic datagram receiver. This handles all sorts
1071 * of horrible races and re-entrancy so we can forget about it 1085 * of horrible races and re-entrancy so we can forget about it
1072 * in the protocol layers. 1086 * in the protocol layers.
@@ -1087,6 +1101,17 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
1087 goto out; 1101 goto out;
1088 1102
1089 /* 1103 /*
1104 * If the address length field is there to be filled in, we fill
1105 * it in now.
1106 */
1107
1108 sll = (struct sockaddr_ll*)skb->cb;
1109 if (sock->type == SOCK_PACKET)
1110 msg->msg_namelen = sizeof(struct sockaddr_pkt);
1111 else
1112 msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr);
1113
1114 /*
1090 * You lose any data beyond the buffer you gave. If it worries a 1115 * You lose any data beyond the buffer you gave. If it worries a
1091 * user program they can ask the device for its MTU anyway. 1116 * user program they can ask the device for its MTU anyway.
1092 */ 1117 */
@@ -1166,7 +1191,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
1166 sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ 1191 sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */
1167 sll->sll_halen = 0; 1192 sll->sll_halen = 0;
1168 } 1193 }
1169 *uaddr_len = sizeof(*sll); 1194 *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen;
1170 1195
1171 return 0; 1196 return 0;
1172} 1197}
@@ -1199,7 +1224,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i
1199 } 1224 }
1200} 1225}
1201 1226
1202static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) 1227static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq)
1203{ 1228{
1204 struct packet_sock *po = pkt_sk(sk); 1229 struct packet_sock *po = pkt_sk(sk);
1205 struct packet_mclist *ml, *i; 1230 struct packet_mclist *ml, *i;
@@ -1249,7 +1274,7 @@ done:
1249 return err; 1274 return err;
1250} 1275}
1251 1276
1252static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) 1277static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq)
1253{ 1278{
1254 struct packet_mclist *ml, **mlp; 1279 struct packet_mclist *ml, **mlp;
1255 1280
@@ -1315,11 +1340,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
1315 case PACKET_ADD_MEMBERSHIP: 1340 case PACKET_ADD_MEMBERSHIP:
1316 case PACKET_DROP_MEMBERSHIP: 1341 case PACKET_DROP_MEMBERSHIP:
1317 { 1342 {
1318 struct packet_mreq mreq; 1343 struct packet_mreq_max mreq;
1319 if (optlen<sizeof(mreq)) 1344 int len = optlen;
1345 memset(&mreq, 0, sizeof(mreq));
1346 if (len < sizeof(struct packet_mreq))
1320 return -EINVAL; 1347 return -EINVAL;
1321 if (copy_from_user(&mreq,optval,sizeof(mreq))) 1348 if (len > sizeof(mreq))
1349 len = sizeof(mreq);
1350 if (copy_from_user(&mreq,optval,len))
1322 return -EFAULT; 1351 return -EFAULT;
1352 if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address)))
1353 return -EINVAL;
1323 if (optname == PACKET_ADD_MEMBERSHIP) 1354 if (optname == PACKET_ADD_MEMBERSHIP)
1324 ret = packet_mc_add(sk, &mreq); 1355 ret = packet_mc_add(sk, &mreq);
1325 else 1356 else
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 86073df418f5..505c7de10c50 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2414,6 +2414,17 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2414 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); 2414 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
2415 chunk->subh.shutdown_hdr = sdh; 2415 chunk->subh.shutdown_hdr = sdh;
2416 2416
2417 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
2418 * When a peer sends a SHUTDOWN, SCTP delivers this notification to
2419 * inform the application that it should cease sending data.
2420 */
2421 ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
2422 if (!ev) {
2423 disposition = SCTP_DISPOSITION_NOMEM;
2424 goto out;
2425 }
2426 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
2427
2417 /* Upon the reception of the SHUTDOWN, the peer endpoint shall 2428 /* Upon the reception of the SHUTDOWN, the peer endpoint shall
2418 * - enter the SHUTDOWN-RECEIVED state, 2429 * - enter the SHUTDOWN-RECEIVED state,
2419 * - stop accepting new data from its SCTP user 2430 * - stop accepting new data from its SCTP user
@@ -2439,17 +2450,6 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2439 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, 2450 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
2440 SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack)); 2451 SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
2441 2452
2442 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
2443 * When a peer sends a SHUTDOWN, SCTP delivers this notification to
2444 * inform the application that it should cease sending data.
2445 */
2446 ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
2447 if (!ev) {
2448 disposition = SCTP_DISPOSITION_NOMEM;
2449 goto out;
2450 }
2451 sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
2452
2453out: 2453out:
2454 return disposition; 2454 return disposition;
2455} 2455}