Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 811927cc authored by Patrick McHardy's avatar Patrick McHardy Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_conntrack: restrict NAT helper invocation to IPv4



The NAT helpers currently only handle IPv4 packets correctly. Restrict
invocation of the helpers to IPv4 in preparation of IPv6 NAT.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 2b60af01
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -154,7 +154,8 @@ static int amanda_help(struct sk_buff *skb,
				  IPPROTO_TCP, NULL, &port);
				  IPPROTO_TCP, NULL, &port);


		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
		nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
		if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
		if (nf_nat_amanda && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
		    ct->status & IPS_NAT_MASK)
			ret = nf_nat_amanda(skb, ctinfo, off - dataoff,
			ret = nf_nat_amanda(skb, ctinfo, off - dataoff,
					    len, exp);
					    len, exp);
		else if (nf_ct_expect_related(exp) != 0)
		else if (nf_ct_expect_related(exp) != 0)
+2 −1
Original line number Original line Diff line number Diff line
@@ -487,7 +487,8 @@ static int help(struct sk_buff *skb,
	/* Now, NAT might want to mangle the packet, and register the
	/* Now, NAT might want to mangle the packet, and register the
	 * (possibly changed) expectation itself. */
	 * (possibly changed) expectation itself. */
	nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
	nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
	if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
	if (nf_nat_ftp && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK)
		ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
		ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
				 matchoff, matchlen, exp);
				 matchoff, matchlen, exp);
	else {
	else {
+29 −12
Original line number Original line Diff line number Diff line
@@ -295,6 +295,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
		   (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
		   (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
		   nf_ct_l3num(ct) == NFPROTO_IPV4 &&
		   ct->status & IPS_NAT_MASK) {
		   ct->status & IPS_NAT_MASK) {
		/* NAT needed */
		/* NAT needed */
		ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
		ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
@@ -353,6 +354,7 @@ static int expect_t120(struct sk_buff *skb,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
	    (nat_t120 = rcu_dereference(nat_t120_hook)) &&
	    (nat_t120 = rcu_dereference(nat_t120_hook)) &&
	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
	    ct->status & IPS_NAT_MASK) {
		/* NAT needed */
		/* NAT needed */
		ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr,
		ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr,
@@ -688,6 +690,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
	    (nat_h245 = rcu_dereference(nat_h245_hook)) &&
	    (nat_h245 = rcu_dereference(nat_h245_hook)) &&
	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
	    ct->status & IPS_NAT_MASK) {
		/* NAT needed */
		/* NAT needed */
		ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr,
		ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr,
@@ -811,6 +814,7 @@ static int expect_callforwarding(struct sk_buff *skb,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   &ct->tuplehash[!dir].tuple.dst.u3,
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
		   sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
	    (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
	    ct->status & IPS_NAT_MASK) {
		/* Need NAT */
		/* Need NAT */
		ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff,
		ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff,
@@ -852,7 +856,8 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,


	set_h225_addr = rcu_dereference(set_h225_addr_hook);
	set_h225_addr = rcu_dereference(set_h225_addr_hook);
	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
	if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
	    (set_h225_addr) && ct->status & IPS_NAT_MASK &&
	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK &&
	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
	    get_h225_addr(ct, *data, &setup->destCallSignalAddress,
			  &addr, &port) &&
			  &addr, &port) &&
	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
	    memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
@@ -868,7 +873,8 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
	}
	}


	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
	if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
	    (set_h225_addr) && ct->status & IPS_NAT_MASK &&
	    (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK &&
	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
	    get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
			  &addr, &port) &&
			  &addr, &port) &&
	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
	    memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
@@ -1278,7 +1284,8 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */
	exp->flags = NF_CT_EXPECT_PERMANENT;	/* Accept multiple calls */


	nat_q931 = rcu_dereference(nat_q931_hook);
	nat_q931 = rcu_dereference(nat_q931_hook);
	if (nat_q931 && ct->status & IPS_NAT_MASK) {	/* Need NAT */
	if (nat_q931 && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {	/* Need NAT */
		ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
		ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
	} else {		/* Conntrack only */
	} else {		/* Conntrack only */
		if (nf_ct_expect_related(exp) == 0) {
		if (nf_ct_expect_related(exp) == 0) {
@@ -1306,7 +1313,8 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
	pr_debug("nf_ct_ras: GRQ\n");
	pr_debug("nf_ct_ras: GRQ\n");


	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	if (set_ras_addr && ct->status & IPS_NAT_MASK)	/* NATed */
	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK)	/* NATed */
		return set_ras_addr(skb, ct, ctinfo, data,
		return set_ras_addr(skb, ct, ctinfo, data,
				    &grq->rasAddress, 1);
				    &grq->rasAddress, 1);
	return 0;
	return 0;
@@ -1374,7 +1382,8 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
		return -1;
		return -1;


	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		ret = set_ras_addr(skb, ct, ctinfo, data,
		ret = set_ras_addr(skb, ct, ctinfo, data,
				   rrq->rasAddress.item,
				   rrq->rasAddress.item,
				   rrq->rasAddress.count);
				   rrq->rasAddress.count);
@@ -1405,7 +1414,8 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
	pr_debug("nf_ct_ras: RCF\n");
	pr_debug("nf_ct_ras: RCF\n");


	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
		ret = set_sig_addr(skb, ct, ctinfo, data,
					rcf->callSignalAddress.item,
					rcf->callSignalAddress.item,
					rcf->callSignalAddress.count);
					rcf->callSignalAddress.count);
@@ -1453,7 +1463,8 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
	pr_debug("nf_ct_ras: URQ\n");
	pr_debug("nf_ct_ras: URQ\n");


	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
		ret = set_sig_addr(skb, ct, ctinfo, data,
				   urq->callSignalAddress.item,
				   urq->callSignalAddress.item,
				   urq->callSignalAddress.count);
				   urq->callSignalAddress.count);
@@ -1491,6 +1502,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
			  &addr, &port) &&
			  &addr, &port) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    port == info->sig_port[dir] &&
	    port == info->sig_port[dir] &&
	    nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    set_h225_addr && ct->status & IPS_NAT_MASK) {
	    set_h225_addr && ct->status & IPS_NAT_MASK) {
		/* Answering ARQ */
		/* Answering ARQ */
		return set_h225_addr(skb, data, 0,
		return set_h225_addr(skb, data, 0,
@@ -1503,7 +1515,8 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
	    get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
	    get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
			  &addr, &port) &&
			  &addr, &port) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    set_h225_addr && ct->status & IPS_NAT_MASK) {
	    set_h225_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		/* Calling ARQ */
		/* Calling ARQ */
		return set_h225_addr(skb, data, 0,
		return set_h225_addr(skb, data, 0,
				     &arq->srcCallSignalAddress,
				     &arq->srcCallSignalAddress,
@@ -1535,7 +1548,8 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
	if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
	if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
		/* Answering ACF */
		/* Answering ACF */
		set_sig_addr = rcu_dereference(set_sig_addr_hook);
		set_sig_addr = rcu_dereference(set_sig_addr_hook);
		if (set_sig_addr && ct->status & IPS_NAT_MASK)
		if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
		    ct->status & IPS_NAT_MASK)
			return set_sig_addr(skb, ct, ctinfo, data,
			return set_sig_addr(skb, ct, ctinfo, data,
					    &acf->destCallSignalAddress, 1);
					    &acf->destCallSignalAddress, 1);
		return 0;
		return 0;
@@ -1571,7 +1585,8 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
	pr_debug("nf_ct_ras: LRQ\n");
	pr_debug("nf_ct_ras: LRQ\n");


	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	if (set_ras_addr && ct->status & IPS_NAT_MASK)
	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK)
		return set_ras_addr(skb, ct, ctinfo, data,
		return set_ras_addr(skb, ct, ctinfo, data,
				    &lrq->replyAddress, 1);
				    &lrq->replyAddress, 1);
	return 0;
	return 0;
@@ -1628,7 +1643,8 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
	pr_debug("nf_ct_ras: IRR\n");
	pr_debug("nf_ct_ras: IRR\n");


	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
	if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		ret = set_ras_addr(skb, ct, ctinfo, data,
		ret = set_ras_addr(skb, ct, ctinfo, data,
				   &irr->rasAddress, 1);
				   &irr->rasAddress, 1);
		if (ret < 0)
		if (ret < 0)
@@ -1636,7 +1652,8 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
	}
	}


	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
	if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
		ret = set_sig_addr(skb, ct, ctinfo, data,
					irr->callSignalAddress.item,
					irr->callSignalAddress.item,
					irr->callSignalAddress.count);
					irr->callSignalAddress.count);
+2 −1
Original line number Original line Diff line number Diff line
@@ -204,7 +204,8 @@ static int help(struct sk_buff *skb, unsigned int protoff,
					  IPPROTO_TCP, NULL, &port);
					  IPPROTO_TCP, NULL, &port);


			nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
			nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
			if (nf_nat_irc && ct->status & IPS_NAT_MASK)
			if (nf_nat_irc && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
			    ct->status & IPS_NAT_MASK)
				ret = nf_nat_irc(skb, ctinfo,
				ret = nf_nat_irc(skb, ctinfo,
						 addr_beg_p - ib_ptr,
						 addr_beg_p - ib_ptr,
						 addr_end_p - addr_beg_p,
						 addr_end_p - addr_beg_p,
+12 −6
Original line number Original line Diff line number Diff line
@@ -981,7 +981,8 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff,
			  IPPROTO_UDP, NULL, &rtcp_port);
			  IPPROTO_UDP, NULL, &rtcp_port);


	nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
	nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
	if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
	if (nf_nat_sdp_media && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK && !direct_rtp)
		ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen,
		ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen,
				       rtp_exp, rtcp_exp,
				       rtp_exp, rtcp_exp,
				       mediaoff, medialen, daddr);
				       mediaoff, medialen, daddr);
@@ -1104,7 +1105,8 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff,
			return ret;
			return ret;


		/* Update media connection address if present */
		/* Update media connection address if present */
		if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
		if (maddr_len && nf_nat_sdp_addr &&
		    nf_ct_l3num(ct) == NFPROTO_IPV4 && ct->status & IPS_NAT_MASK) {
			ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen,
			ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen,
					      mediaoff, c_hdr, SDP_HDR_MEDIA,
					      mediaoff, c_hdr, SDP_HDR_MEDIA,
					      &rtp_addr);
					      &rtp_addr);
@@ -1116,7 +1118,8 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff,


	/* Update session connection and owner addresses */
	/* Update session connection and owner addresses */
	nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
	nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
	if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
	if (nf_nat_sdp_session && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK)
		ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff,
		ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff,
					 &rtp_addr);
					 &rtp_addr);


@@ -1275,7 +1278,8 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
	exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
	exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;


	nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
	nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
	if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
	if (nf_nat_sip_expect && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK)
		ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp,
		ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp,
					matchoff, matchlen);
					matchoff, matchlen);
	else {
	else {
@@ -1453,7 +1457,8 @@ static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct,
	else
	else
		ret = process_sip_response(skb, dataoff, dptr, datalen);
		ret = process_sip_response(skb, dataoff, dptr, datalen);


	if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
	if (ret == NF_ACCEPT && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
		nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
		if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen))
		if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen))
			ret = NF_DROP;
			ret = NF_DROP;
@@ -1534,7 +1539,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
		datalen  = datalen + diff - msglen;
		datalen  = datalen + diff - msglen;
	}
	}


	if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
	if (ret == NF_ACCEPT && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
	    ct->status & IPS_NAT_MASK) {
		nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook);
		nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook);
		if (nf_nat_sip_seq_adjust)
		if (nf_nat_sip_seq_adjust)
			nf_nat_sip_seq_adjust(skb, tdiff);
			nf_nat_sip_seq_adjust(skb, tdiff);
Loading