From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- .../linux/net/ipv4/netfilter/ip_conntrack_pptp.c | 150 ++++++++++++++++++--- 1 file changed, 128 insertions(+), 22 deletions(-) (limited to 'release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c') diff --git a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c index 17cf2b7b..a0b41051 100644 --- a/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c +++ b/release/src/linux/linux/net/ipv4/netfilter/ip_conntrack_pptp.c @@ -1,5 +1,5 @@ /* - * ip_conntrack_pptp.c - Version 1.11 + * ip_conntrack_pptp.c - Version 1.9 * * Connection tracking support for PPTP (Point to Point Tunneling Protocol). * PPTP is a a protocol for creating virtual private networks. @@ -9,7 +9,7 @@ * GRE is defined in RFC 1701 and RFC 1702. Documentation of * PPTP can be found in RFC 2637 * - * (C) 2000-2002 by Harald Welte , + * (C) 2000-2003 by Harald Welte * * Development of this code funded by Astaro AG (http://www.astaro.com/) * @@ -21,6 +21,18 @@ * TODO: - finish support for multiple calls within one session * (needs expect reservations in newnat) * - testing of incoming PPTP calls + * + * Changes: + * 2002-02-05 - Version 1.3 + * - Call ip_conntrack_unexpect_related() from + * pptp_timeout_related() to destroy expectations in case + * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen + * (Philip Craig ) + * - Add Version information at module loadtime + * 2002-02-10 - Version 1.6 + * - move to C99 style initializers + * - remove second expectation if first arrives + * */ #include @@ -35,13 +47,21 @@ #include #include +#define IP_CT_PPTP_VERSION "1.9" + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); DECLARE_LOCK(ip_pptp_lock); +#if 0 +#include "ip_conntrack_pptp_priv.h" +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \ + ": " format, ## args) +#else #define DEBUGP(format, args...) +#endif #define SECS *HZ #define MINS * 60 SECS @@ -53,8 +73,8 @@ DECLARE_LOCK(ip_pptp_lock); static int pptp_expectfn(struct ip_conntrack *ct) { - struct ip_conntrack_expect *exp, *other_exp; struct ip_conntrack *master; + struct ip_conntrack_expect *exp; DEBUGP("increasing timeouts\n"); /* increase timeout of GRE data channel conntrack entry */ @@ -67,6 +87,12 @@ static int pptp_expectfn(struct ip_conntrack *ct) return 0; } + exp = ct->master; + if (!exp) { + DEBUGP("no expectation!!\n"); + return 0; + } + DEBUGP("completing tuples with ct info\n"); /* we can do this, since we're unconfirmed */ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == @@ -83,6 +109,26 @@ static int pptp_expectfn(struct ip_conntrack *ct) ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key = htonl(master->help.ct_pptp_info.pac_call_id); } + + /* delete other expectation */ + if (exp->expected_list.next != &exp->expected_list) { + struct ip_conntrack_expect *other_exp; + struct list_head *cur_item, *next; + + for (cur_item = master->sibling_list.next; + cur_item != &master->sibling_list; cur_item = next) { + next = cur_item->next; + other_exp = list_entry(cur_item, + struct ip_conntrack_expect, + expected_list); + /* remove only if occurred at same sequence number */ + if (other_exp != exp && other_exp->seq == exp->seq) { + DEBUGP("unexpecting other direction\n"); + ip_ct_gre_keymap_destroy(other_exp); + ip_conntrack_unexpect_related(other_exp); + } + } + } return 0; } @@ -90,15 +136,21 @@ static int pptp_expectfn(struct ip_conntrack *ct) /* timeout GRE data connections */ static int pptp_timeout_related(struct ip_conntrack *ct) { - struct list_head *cur_item; + struct list_head *cur_item, *next; struct ip_conntrack_expect *exp; - list_for_each(cur_item, &ct->sibling_list) { + /* FIXME: do we have to lock something ? */ + for (cur_item = ct->sibling_list.next; + cur_item != &ct->sibling_list; cur_item = next) { + next = cur_item->next; exp = list_entry(cur_item, struct ip_conntrack_expect, expected_list); - if (!exp->sibling) + ip_ct_gre_keymap_destroy(exp); + if (!exp->sibling) { + ip_conntrack_unexpect_related(exp); continue; + } DEBUGP("setting timeout of conntrack %p to 0\n", exp->sibling); @@ -110,7 +162,7 @@ static int pptp_timeout_related(struct ip_conntrack *ct) return 0; } -/* expect GRE connection in PNS->PAC direction */ +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */ static inline int exp_gre(struct ip_conntrack *master, u_int32_t seq, @@ -121,7 +173,7 @@ exp_gre(struct ip_conntrack *master, struct ip_conntrack_tuple inv_tuple; memset(&exp, 0, sizeof(exp)); - /* tuple in original direction, PAC->PNS */ + /* tuple in original direction, PNS->PAC */ exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid)); exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; @@ -148,12 +200,44 @@ exp_gre(struct ip_conntrack *master, DEBUGP("calling expect_related "); DUMP_TUPLE_RAW(&exp.tuple); + /* Add GRE keymap entries */ + if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0) + return 1; + + invert_tuplepr(&inv_tuple, &exp.tuple); + if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) { + ip_ct_gre_keymap_destroy(&exp); + return 1; + } + + if (ip_conntrack_expect_related(master, &exp) != 0) { + ip_ct_gre_keymap_destroy(&exp); + DEBUGP("cannot expect_related()\n"); + return 1; + } + + /* tuple in reply direction, PAC->PNS */ + exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; + exp.tuple.src.u.gre.key = htonl(ntohs(callid)); + exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; + exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid)); + + DEBUGP("calling expect_related "); + DUMP_TUPLE_RAW(&exp.tuple); + /* Add GRE keymap entries */ ip_ct_gre_keymap_add(&exp, &exp.tuple, 0); invert_tuplepr(&inv_tuple, &exp.tuple); ip_ct_gre_keymap_add(&exp, &inv_tuple, 1); + /* FIXME: cannot handle error correctly, since we need to free + * the above keymap :( */ - ip_conntrack_expect_related(master, &exp); + if (ip_conntrack_expect_related(master, &exp) != 0) { + /* free the second pair of keypmaps */ + ip_ct_gre_keymap_destroy(&exp); + DEBUGP("cannot expect_related():\n"); + return 1; + } return 0; } @@ -240,7 +324,8 @@ pptp_inbound_pkt(struct tcphdr *tcph, info->cstate = PPTP_CALL_OUT_CONF; seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph); - exp_gre(ct, seq, *cid, *pcid); + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); break; case PPTP_IN_CALL_REQUEST: @@ -282,7 +367,8 @@ pptp_inbound_pkt(struct tcphdr *tcph, /* we expect a GRE connection from PAC to PNS */ seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph); - exp_gre(ct, seq, *cid, *pcid); + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); break; @@ -294,7 +380,6 @@ pptp_inbound_pkt(struct tcphdr *tcph, /* untrack this call id, unexpect GRE packets */ pptp_timeout_related(ct); - /* NEWNAT: look up exp for call id and unexpct_related */ break; case PPTP_WAN_ERROR_NOTIFY: @@ -446,7 +531,8 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len, if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, csum_partial((char *) tcph, tcplen, 0))) { printk(KERN_NOTICE __FILE__ ": bad csum\n"); -// return NF_ACCEPT; + /* W2K PPTP server sends TCP packets with wrong checksum :(( */ + //return NF_ACCEPT; } if (tcph->fin || tcph->rst) { @@ -456,8 +542,6 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len, /* untrack this call id, unexpect GRE packets */ pptp_timeout_related(ct); - /* no need to call unexpect_related since master conn - * dies anyway */ } @@ -482,6 +566,8 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len, LOCK_BH(&ip_pptp_lock); + /* FIXME: We just blindly assume that the control connection is always + * established from PNS->PAC. However, RFC makes no guarantee */ if (dir == IP_CT_DIR_ORIGINAL) /* client -> server (PNS -> PAC) */ ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo); @@ -497,13 +583,31 @@ conntrack_pptp_help(const struct iphdr *iph, size_t len, /* control protocol helper */ static struct ip_conntrack_helper pptp = { - { NULL, NULL }, - "pptp", IP_CT_HELPER_F_REUSE_EXPECT, THIS_MODULE, 2, 0, - { { 0, { tcp: { port: __constant_htons(PPTP_CONTROL_PORT) } } }, - { 0, { 0 }, IPPROTO_TCP } }, - { { 0, { tcp: { port: 0xffff } } }, - { 0, { 0 }, 0xffff } }, - conntrack_pptp_help }; + .list = { NULL, NULL }, + .name = "pptp", + .flags = IP_CT_HELPER_F_REUSE_EXPECT, + .me = THIS_MODULE, + .max_expected = 2, + .timeout = 0, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(PPTP_CONTROL_PORT) } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = IPPROTO_TCP + } + }, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = 0xffff } } + }, + .dst = { .ip = 0, + .u = { .all = 0 }, + .protonum = 0xffff + } + }, + .help = conntrack_pptp_help +}; /* ip_conntrack_pptp initialization */ static int __init init(void) @@ -517,12 +621,14 @@ static int __init init(void) return -EIO; } + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION); return 0; } static void __exit fini(void) { ip_conntrack_helper_unregister(&pptp); + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION); } module_init(init); -- cgit v1.2.3-54-g00ecf