www.usr.com/support/gpl/USR9107_release.1.4.tar.gz
[bcm963xx.git] / kernel / linux / net / ipv4 / netfilter / ip_conntrack_pptp.c
index aafc2fe..0afe69f 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * ip_conntrack_pptp.c - Version 1.9
+ * ip_conntrack_pptp.c - Version 2.0
  *
  * 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-2003 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
  *
  * Development of this code funded by Astaro AG (http://www.astaro.com/)
  *
  *     2002-02-10 - Version 1.6
  *       - move to C99 style initializers
  *       - remove second expectation if first arrives
+ *     2004-10-22 - Version 2.0
+ *       - merge Mandrake's 2.6.x port with recent 2.6.x API changes
+ *       - fix lots of linear skb assumptions from Mandrake's port
+ *     2005-06-10 - Version 2.1
+ *       - use ip_conntrack_expect_free() instead of kfree() on the
+ *         expect's (which are from the slab for quite some time)
  *
  */
 
@@ -47,7 +53,7 @@
 #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
 
-#define IP_CT_PPTP_VERSION "1.9"
+#define IP_CT_PPTP_VERSION "2.1"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
@@ -57,8 +63,7 @@ DECLARE_LOCK(ip_pptp_lock);
 
 #if 0
 #include "ip_conntrack_pptp_priv.h"
-#define DEBUGP(format, args...)        printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
-                                       ": " format, ## args)
+#define DEBUGP(format, args...)        printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
 #else
 #define DEBUGP(format, args...)
 #endif
@@ -156,6 +161,8 @@ static int pptp_timeout_related(struct ip_conntrack *ct)
                        exp->sibling);
                exp->sibling->proto.gre.timeout = 0;
                exp->sibling->proto.gre.stream_timeout = 0;
+               /* refresh_acct will not modify counters if skb == NULL */
+               //ip_ct_refresh_acct(exp->sibling, 0, NULL, 0);
                ip_ct_refresh(exp->sibling, 0);
        }
 
@@ -169,129 +176,154 @@ exp_gre(struct ip_conntrack *master,
        u_int16_t callid,
        u_int16_t peer_callid)
 {
-       struct ip_conntrack_expect exp;
        struct ip_conntrack_tuple inv_tuple;
-
-       memset(&exp, 0, sizeof(exp));
-       /* 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;
-       exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
-       exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
-       exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
-       exp.tuple.dst.protonum = IPPROTO_GRE;
-
-       exp.mask.src.ip = 0xffffffff;
-       exp.mask.src.u.all = 0;
-       exp.mask.dst.u.all = 0;
-       exp.mask.dst.u.gre.key = 0xffffffff;
-       exp.mask.dst.u.gre.version = 0xff;
-       exp.mask.dst.u.gre.protocol = 0xffff;
-       exp.mask.dst.ip = 0xffffffff;
-       exp.mask.dst.protonum = 0xffff;
+       struct ip_conntrack_tuple exp_tuples[] = {
+               /* tuple in original direction, PNS->PAC */
+               { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
+                          .u = { .gre = { .key = htonl(ntohs(peer_callid)) } }
+                        },
+                 .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
+                          .u = { .gre = { .key = htonl(ntohs(callid)) } },
+                          .protonum = IPPROTO_GRE
+                        },
+                },
+               /* tuple in reply direction, PAC->PNS */
+               { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
+                          .u = { .gre = { .key = htonl(ntohs(callid)) } }
+                        },
+                 .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
+                          .u = { .gre = { .key = htonl(ntohs(peer_callid)) } },
+                          .protonum = IPPROTO_GRE
+                        },
+                }
+       }, *exp_tuple;
+
+       for (exp_tuple = exp_tuples; exp_tuple < &exp_tuples[2]; exp_tuple++) {
+               struct ip_conntrack_expect *exp;
+
+               exp = ip_conntrack_expect_alloc();
+               if (exp == NULL)
+                       return 1;
+
+               memcpy(&exp->tuple, exp_tuple, sizeof(exp->tuple));
+
+               exp->mask.src.ip = 0xffffffff;
+               exp->mask.src.u.all = 0;
+               exp->mask.dst.u.all = 0;
+               exp->mask.dst.u.gre.key = 0xffffffff;
+               exp->mask.dst.ip = 0xffffffff;
+               exp->mask.dst.protonum = 0xffff;
                        
-       exp.seq = seq;
-       exp.expectfn = pptp_expectfn;
+               exp->seq = seq;
+               exp->expectfn = pptp_expectfn;
 
-       exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
-       exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
+               exp->help.exp_pptp_info.pac_call_id = ntohs(callid);
+               exp->help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
 
-       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;
-       }
+               DEBUGP("calling expect_related ");
+               DUMP_TUPLE_RAW(&exp->tuple);
        
-       if (ip_conntrack_expect_related(&exp, master) != 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));
+               /* Add GRE keymap entries */
+               if (ip_ct_gre_keymap_add(exp, &exp->tuple, 0) != 0) {
+                       //ip_conntrack_expect_free(exp);
+                       ip_conntrack_expect_put(exp);
+                       return 1;
+               }
 
-       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 :( */
+               invert_tuplepr(&inv_tuple, &exp->tuple);
+               if (ip_ct_gre_keymap_add(exp, &inv_tuple, 1) != 0) {
+                       ip_ct_gre_keymap_destroy(exp);
+                       //ip_conntrack_expect_free(exp);
+                       ip_conntrack_expect_put(exp);
+                       return 1;
+               }
        
-       if (ip_conntrack_expect_related(&exp, master) != 0) {
-               /* free the second pair of keypmaps */
-               ip_ct_gre_keymap_destroy(&exp);
-               DEBUGP("cannot expect_related():\n");
-               return 1;
+               if (ip_conntrack_expect_related(exp, master) != 0) {
+                       ip_ct_gre_keymap_destroy(exp);
+                       //ip_conntrack_expect_free(exp);
+                       ip_conntrack_expect_put(exp);
+                       DEBUGP("cannot expect_related()\n");
+                       return 1;
+               }
        }
 
        return 0;
 }
 
 static inline int 
-pptp_inbound_pkt(struct tcphdr *tcph,
-                struct pptp_pkt_hdr *pptph, 
+pptp_inbound_pkt(struct sk_buff *skb,
+                struct tcphdr *tcph,
+                unsigned int ctlhoff,
                 size_t datalen,
-                struct ip_conntrack *ct,
-                enum ip_conntrack_info ctinfo)
+                struct ip_conntrack *ct)
 {
-       struct PptpControlHeader *ctlh;
-        union pptp_ctrl_union pptpReq;
-       
+       struct PptpControlHeader _ctlh, *ctlh;
+       unsigned int reqlen;
+       union pptp_ctrl_union _pptpReq, *pptpReq;
        struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
        u_int16_t msg, *cid, *pcid;
        u_int32_t seq;  
 
-       ctlh = (struct PptpControlHeader *) 
-               ((char *) pptph + sizeof(struct pptp_pkt_hdr));
-       pptpReq.rawreq = (void *) 
-               ((char *) ctlh + sizeof(struct PptpControlHeader));
+       ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh);
+       if (unlikely(!ctlh)) {
+               DEBUGP("error during skb_header_pointer\n");
+               return NF_ACCEPT;
+       }
+
+       reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh);
+       pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh),
+                                    reqlen, &_pptpReq);
+       if (unlikely(!pptpReq)) {
+               DEBUGP("error during skb_header_pointer\n");
+               return NF_ACCEPT;
+       }
 
        msg = ntohs(ctlh->messageType);
        DEBUGP("inbound control message %s\n", strMName[msg]);
 
        switch (msg) {
        case PPTP_START_SESSION_REPLY:
+               if (reqlen < sizeof(_pptpReq.srep)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server confirms new control session */
                if (info->sstate < PPTP_SESSION_REQUESTED) {
                        DEBUGP("%s without START_SESS_REQUEST\n",
                                strMName[msg]);
                        break;
                }
-               if (pptpReq.srep->resultCode == PPTP_START_OK)
+               if (pptpReq->srep.resultCode == PPTP_START_OK)
                        info->sstate = PPTP_SESSION_CONFIRMED;
                else 
                        info->sstate = PPTP_SESSION_ERROR;
                break;
 
        case PPTP_STOP_SESSION_REPLY:
+               if (reqlen < sizeof(_pptpReq.strep)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server confirms end of control session */
                if (info->sstate > PPTP_SESSION_STOPREQ) {
                        DEBUGP("%s without STOP_SESS_REQUEST\n",
                                strMName[msg]);
                        break;
                }
-               if (pptpReq.strep->resultCode == PPTP_STOP_OK)
+               if (pptpReq->strep.resultCode == PPTP_STOP_OK)
                        info->sstate = PPTP_SESSION_NONE;
                else
                        info->sstate = PPTP_SESSION_ERROR;
                break;
 
        case PPTP_OUT_CALL_REPLY:
+               if (reqlen < sizeof(_pptpReq.ocack)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server accepted call, we now expect GRE frames */
                if (info->sstate != PPTP_SESSION_CONFIRMED) {
                        DEBUGP("%s but no session\n", strMName[msg]);
@@ -302,13 +334,13 @@ pptp_inbound_pkt(struct tcphdr *tcph,
                        DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
                        break;
                }
-               if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
+               if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) {
                        info->cstate = PPTP_CALL_NONE;
                        break;
                }
 
-               cid = &pptpReq.ocack->callID;
-               pcid = &pptpReq.ocack->peersCallID;
+               cid = &pptpReq->ocack.callID;
+               pcid = &pptpReq->ocack.peersCallID;
 
                info->pac_call_id = ntohs(*cid);
                
@@ -323,24 +355,37 @@ pptp_inbound_pkt(struct tcphdr *tcph,
                
                info->cstate = PPTP_CALL_OUT_CONF;
 
-               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
+               seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+                                      + sizeof(struct PptpControlHeader)
+                                      + ((void *)pcid - (void *)pptpReq);
+                       
                if (exp_gre(ct, seq, *cid, *pcid) != 0)
                        printk("ip_conntrack_pptp: error during exp_gre\n");
                break;
 
        case PPTP_IN_CALL_REQUEST:
+               if (reqlen < sizeof(_pptpReq.icack)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server tells us about incoming call request */
                if (info->sstate != PPTP_SESSION_CONFIRMED) {
                        DEBUGP("%s but no session\n", strMName[msg]);
                        break;
                }
-               pcid = &pptpReq.icack->peersCallID;
+               pcid = &pptpReq->icack.peersCallID;
                DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
                info->cstate = PPTP_CALL_IN_REQ;
-               info->pac_call_id= ntohs(*pcid);
+               info->pac_call_id = ntohs(*pcid);
                break;
 
        case PPTP_IN_CALL_CONNECT:
+               if (reqlen < sizeof(_pptpReq.iccon)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server tells us about incoming call established */
                if (info->sstate != PPTP_SESSION_CONFIRMED) {
                        DEBUGP("%s but no session\n", strMName[msg]);
@@ -353,7 +398,7 @@ pptp_inbound_pkt(struct tcphdr *tcph,
                        break;
                }
 
-               pcid = &pptpReq.iccon->peersCallID;
+               pcid = &pptpReq->iccon.peersCallID;
                cid = &info->pac_call_id;
 
                if (info->pns_call_id != ntohs(*pcid)) {
@@ -366,15 +411,23 @@ pptp_inbound_pkt(struct tcphdr *tcph,
                info->cstate = PPTP_CALL_IN_CONF;
 
                /* we expect a GRE connection from PAC to PNS */
-               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
+               seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr)
+                                      + sizeof(struct PptpControlHeader)
+                                      + ((void *)pcid - (void *)pptpReq);
+                       
                if (exp_gre(ct, seq, *cid, *pcid) != 0)
                        printk("ip_conntrack_pptp: error during exp_gre\n");
 
                break;
 
        case PPTP_CALL_DISCONNECT_NOTIFY:
+               if (reqlen < sizeof(_pptpReq.disc)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* server confirms disconnect */
-               cid = &pptpReq.disc->callID;
+               cid = &pptpReq->disc.callID;
                DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
                info->cstate = PPTP_CALL_NONE;
 
@@ -400,19 +453,27 @@ pptp_inbound_pkt(struct tcphdr *tcph,
 }
 
 static inline int
-pptp_outbound_pkt(struct tcphdr *tcph,
-                 struct pptp_pkt_hdr *pptph,
+pptp_outbound_pkt(struct sk_buff *skb,
+                 struct tcphdr *tcph,
+                 unsigned int ctlhoff,
                  size_t datalen,
-                 struct ip_conntrack *ct,
-                 enum ip_conntrack_info ctinfo)
+                 struct ip_conntrack *ct)
 {
-       struct PptpControlHeader *ctlh;
-        union pptp_ctrl_union pptpReq;
+       struct PptpControlHeader _ctlh, *ctlh;
+       unsigned int reqlen;
+       union pptp_ctrl_union _pptpReq, *pptpReq;
        struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
        u_int16_t msg, *cid, *pcid;
 
-       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
-       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
+       ctlh = skb_header_pointer(skb, ctlhoff, sizeof(_ctlh), &_ctlh);
+       if (!ctlh)
+               return NF_ACCEPT;
+       
+       reqlen = datalen - sizeof(struct pptp_pkt_hdr) - sizeof(_ctlh);
+       pptpReq = skb_header_pointer(skb, ctlhoff+sizeof(_ctlh), reqlen, 
+                                    &_pptpReq);
+       if (!pptpReq)
+               return NF_ACCEPT;
 
        msg = ntohs(ctlh->messageType);
        DEBUGP("outbound control message %s\n", strMName[msg]);
@@ -432,6 +493,11 @@ pptp_outbound_pkt(struct tcphdr *tcph,
                break;
 
        case PPTP_OUT_CALL_REQUEST:
+               if (reqlen < sizeof(_pptpReq.ocreq)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       /* FIXME: break; */
+               }
+
                /* client initiating connection to server */
                if (info->sstate != PPTP_SESSION_CONFIRMED) {
                        DEBUGP("%s but no session\n",
@@ -440,11 +506,16 @@ pptp_outbound_pkt(struct tcphdr *tcph,
                }
                info->cstate = PPTP_CALL_OUT_REQ;
                /* track PNS call id */
-               cid = &pptpReq.ocreq->callID;
+               cid = &pptpReq->ocreq.callID;
                DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
                info->pns_call_id = ntohs(*cid);
                break;
        case PPTP_IN_CALL_REPLY:
+               if (reqlen < sizeof(_pptpReq.icack)) {
+                       DEBUGP("%s: short packet\n", strMName[msg]);
+                       break;
+               }
+
                /* client answers incoming call */
                if (info->cstate != PPTP_CALL_IN_REQ
                    && info->cstate != PPTP_CALL_IN_REP) {
@@ -452,11 +523,11 @@ pptp_outbound_pkt(struct tcphdr *tcph,
                                strMName[msg]);
                        break;
                }
-               if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
+               if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) {
                        info->cstate = PPTP_CALL_NONE;
                        break;
                }
-               pcid = &pptpReq.icack->peersCallID;
+               pcid = &pptpReq->icack.peersCallID;
                if (info->pac_call_id != ntohs(*pcid)) {
                        DEBUGP("%s for unknown call %u\n", 
                                strMName[msg], ntohs(*pcid));
@@ -465,7 +536,7 @@ pptp_outbound_pkt(struct tcphdr *tcph,
                DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
                /* part two of the three-way handshake */
                info->cstate = PPTP_CALL_IN_REP;
-               info->pns_call_id = ntohs(pptpReq.icack->callID);
+               info->pns_call_id = ntohs(pptpReq->icack.callID);
                break;
 
        case PPTP_CALL_CLEAR_REQUEST:
@@ -502,14 +573,15 @@ conntrack_pptp_help(struct sk_buff *skb,
                    struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 
 {
-       struct pptp_pkt_hdr *pptph;
+       struct pptp_pkt_hdr _pptph, *pptph;
        
-       struct tcphdr *tcph = (void *) skb->nh.iph + skb->nh.iph->ihl * 4;
+       struct tcphdr _tcph, *tcph;
        u_int32_t tcplen = skb->len - skb->nh.iph->ihl * 4;
-       u_int32_t datalen = tcplen - tcph->doff * 4;
+       u_int32_t datalen;
        void *datalimit;
        int dir = CTINFO2DIR(ctinfo);
        struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
+       unsigned int nexthdr_off;
 
        int oldsstate, oldcstate;
        int ret;
@@ -521,12 +593,21 @@ conntrack_pptp_help(struct sk_buff *skb,
                return NF_ACCEPT;
        }
        
+       nexthdr_off = skb->nh.iph->ihl*4;
+       tcph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_tcph),
+                                 &_tcph);
+       if (!tcph)
+               return NF_ACCEPT;
+
        /* not a complete TCP header? */
        if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
                DEBUGP("tcplen = %u\n", tcplen);
                return NF_ACCEPT;
        }
 
+
+       datalen = tcplen - tcph->doff * 4;
+
        /* checksum invalid? */
        if (tcp_v4_check(tcph, tcplen, skb->nh.iph->saddr, skb->nh.iph->daddr,
                        csum_partial((char *) tcph, tcplen, 0))) {
@@ -544,18 +625,18 @@ conntrack_pptp_help(struct sk_buff *skb,
                pptp_timeout_related(ct);
        }
 
-
-       pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
-       datalimit = (void *) pptph + datalen;
-
-       /* not a full pptp packet header? */
-       if ((void *) pptph+sizeof(*pptph) >= datalimit) {
+       nexthdr_off += tcph->doff*4;
+       pptph = skb_header_pointer(skb, skb->nh.iph->ihl*4 + tcph->doff*4,
+                                  sizeof(_pptph), &_pptph);
+       if (!pptph) {
                DEBUGP("no full PPTP header, can't track\n");
                return NF_ACCEPT;
        }
-       
+
+       datalimit = (void *) pptph + datalen;
+
        /* if it's not a control message we can't do anything with it */
-        if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
+       if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
            ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
                DEBUGP("not a control packet\n");
                return NF_ACCEPT;
@@ -566,14 +647,15 @@ conntrack_pptp_help(struct sk_buff *skb,
 
        LOCK_BH(&ip_pptp_lock);
 
+       nexthdr_off += sizeof(_pptph);
        /* 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);
+               ret = pptp_outbound_pkt(skb, tcph, nexthdr_off, datalen, ct);
        else
                /* server -> client (PAC -> PNS) */
-               ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
+               ret = pptp_inbound_pkt(skb, tcph, nexthdr_off, datalen, ct);
        DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
                oldsstate, info->sstate, oldcstate, info->cstate);
        UNLOCK_BH(&ip_pptp_lock);
@@ -615,9 +697,8 @@ static int __init init(void)
        int retcode;
 
        DEBUGP(__FILE__ ": registering helper\n");
-       return 0;
        if ((retcode = ip_conntrack_helper_register(&pptp))) {
-                printk(KERN_ERR "Unable to register conntrack application "
+               printk(KERN_ERR "Unable to register conntrack application "
                                "helper for pptp: %d\n", retcode);
                return -EIO;
        }
@@ -628,7 +709,6 @@ static int __init init(void)
 
 static void __exit fini(void)
 {
-       return 0;
        ip_conntrack_helper_unregister(&pptp);
        printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
 }