netfilter: pptp: attach nat extension when needed
authorFlorian Westphal <fw@strlen.de>
Thu, 20 Apr 2017 08:11:34 +0000 (10:11 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 26 Apr 2017 07:30:22 +0000 (09:30 +0200)
make sure nat extension gets added if the master conntrack is subject to
NAT.  This will be required once the nat core stops adding it by default.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/ipv4/netfilter/nf_nat_pptp.c
net/netfilter/nf_conntrack_pptp.c

index 211fee5fe59d7f1379ae7899d94c7a750f05c7dd..8a69363b48846c628994e54c92a354ca46f71ebc 100644 (file)
@@ -49,9 +49,14 @@ static void pptp_nat_expected(struct nf_conn *ct,
        const struct nf_ct_pptp_master *ct_pptp_info;
        const struct nf_nat_pptp *nat_pptp_info;
        struct nf_nat_range range;
+       struct nf_conn_nat *nat;
 
+       nat = nf_ct_nat_ext_add(ct);
+       if (WARN_ON_ONCE(!nat))
+               return;
+
+       nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(master);
-       nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
 
        /* And here goes the grand finale of corrosion... */
        if (exp->dir == IP_CT_DIR_ORIGINAL) {
@@ -120,13 +125,17 @@ pptp_outbound_pkt(struct sk_buff *skb,
 
 {
        struct nf_ct_pptp_master *ct_pptp_info;
+       struct nf_conn_nat *nat = nfct_nat(ct);
        struct nf_nat_pptp *nat_pptp_info;
        u_int16_t msg;
        __be16 new_callid;
        unsigned int cid_off;
 
+       if (WARN_ON_ONCE(!nat))
+               return NF_DROP;
+
+       nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(ct);
-       nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
 
        new_callid = ct_pptp_info->pns_call_id;
 
@@ -191,11 +200,15 @@ pptp_exp_gre(struct nf_conntrack_expect *expect_orig,
             struct nf_conntrack_expect *expect_reply)
 {
        const struct nf_conn *ct = expect_orig->master;
+       struct nf_conn_nat *nat = nfct_nat(ct);
        struct nf_ct_pptp_master *ct_pptp_info;
        struct nf_nat_pptp *nat_pptp_info;
 
+       if (WARN_ON_ONCE(!nat))
+               return;
+
+       nat_pptp_info = &nat->help.nat_pptp_info;
        ct_pptp_info = nfct_help_data(ct);
-       nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
 
        /* save original PAC call ID in nat_info */
        nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
@@ -223,11 +236,15 @@ pptp_inbound_pkt(struct sk_buff *skb,
                 union pptp_ctrl_union *pptpReq)
 {
        const struct nf_nat_pptp *nat_pptp_info;
+       struct nf_conn_nat *nat = nfct_nat(ct);
        u_int16_t msg;
        __be16 new_pcid;
        unsigned int pcid_off;
 
-       nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;
+       if (WARN_ON_ONCE(!nat))
+               return NF_DROP;
+
+       nat_pptp_info = &nat->help.nat_pptp_info;
        new_pcid = nat_pptp_info->pns_call_id;
 
        switch (msg = ntohs(ctlh->messageType)) {
index 126031909fc7808a4c384476ddb42b8c790a3b59..6959e93063d4c957017b97e08dfca27b775461c2 100644 (file)
@@ -263,7 +263,7 @@ out_unexpect_orig:
        goto out_put_both;
 }
 
-static inline int
+static int
 pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff,
                 struct PptpControlHeader *ctlh,
                 union pptp_ctrl_union *pptpReq,
@@ -391,7 +391,7 @@ invalid:
        return NF_ACCEPT;
 }
 
-static inline int
+static int
 pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff,
                  struct PptpControlHeader *ctlh,
                  union pptp_ctrl_union *pptpReq,
@@ -523,6 +523,14 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff,
        int ret;
        u_int16_t msg;
 
+#if IS_ENABLED(CONFIG_NF_NAT)
+       if (!nf_ct_is_confirmed(ct) && (ct->status & IPS_NAT_MASK)) {
+               struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+
+               if (!nat && !nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC))
+                       return NF_DROP;
+       }
+#endif
        /* don't do any tracking before tcp handshake complete */
        if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
                return NF_ACCEPT;