コード例 #1
0
static int pptp_expectfn(struct ip_conntrack *ct)
{
	struct ip_conntrack_expect *exp, *other_exp;
	struct ip_conntrack *master;

	DEBUGP("increasing timeouts\n");
	/* increase timeout of GRE data channel conntrack entry */
	ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
	ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;

	master = master_ct(ct);
	if (!master) {
		DEBUGP(" no master!!!\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 == 
		htonl(master->help.ct_pptp_info.pac_call_id)) {	
		/* assume PNS->PAC */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
			htonl(master->help.ct_pptp_info.pns_call_id);
		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
			htonl(master->help.ct_pptp_info.pns_call_id);
	} else {
		/* assume PAC->PNS */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
			htonl(master->help.ct_pptp_info.pac_call_id);
		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
			htonl(master->help.ct_pptp_info.pac_call_id);
	}

	return 0;
}
コード例 #2
0
static unsigned int
amanda_nat_expected(struct sk_buff **pskb,
                    unsigned int hooknum,
                    struct ip_conntrack *ct,
                    struct ip_nat_info *info)
{
	struct ip_conntrack *master = master_ct(ct);
	struct ip_ct_amanda_expect *exp_amanda_info;
	struct ip_nat_multi_range mr;
	u_int32_t newip;

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);
	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
	else
		newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs. */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		exp_amanda_info = &ct->master->help.exp_amanda_info;
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ .udp = { htons(exp_amanda_info->port) } });
コード例 #3
0
ファイル: ip_nat_pptp.c プロジェクト: JBTech/ralink_rt5350
static unsigned int
pptp_nat_expected(struct sk_buff **pskb,
		  unsigned int hooknum,
		  struct ip_conntrack *ct,
		  struct ip_nat_info *info)
{
	struct ip_conntrack *master = master_ct(ct);
	struct ip_nat_multi_range mr;
	struct ip_ct_pptp_master *ct_pptp_info;
	struct ip_nat_pptp *nat_pptp_info;
	u_int32_t newsrcip, newdstip, newcid;
	int ret;

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);
	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));

	DEBUGP("we have a connection!\n");

	LOCK_BH(&ip_pptp_lock);
	ct_pptp_info = &master->help.ct_pptp_info;
	nat_pptp_info = &master->nat.help.nat_pptp_info;

	/* need to alter GRE tuple because conntrack expectfn() used 'wrong'
	 * (unmanipulated) values */
	if (hooknum == NF_IP_PRE_ROUTING) {
		DEBUGP("completing tuples with NAT info \n");
		/* we can do this, since we're unconfirmed */
		if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
			htonl(ct_pptp_info->pac_call_id)) {	
			/* assume PNS->PAC */
			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
				htonl(nat_pptp_info->pns_call_id);
//			ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.gre.key =
//				htonl(nat_pptp_info->pac_call_id);
			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
				htonl(nat_pptp_info->pns_call_id);
		} else {
			/* assume PAC->PNS */
			DEBUGP("WRONG DIRECTION\n");
			ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
				htonl(nat_pptp_info->pac_call_id);
			ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
				htonl(nat_pptp_info->pns_call_id);
		}
	}

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		//OsborneModify Start on August 3, 2006.
		//newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
		newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
		//OsborneModify End.
		newcid = htonl(master->nat.help.nat_pptp_info.pac_call_id);

		mr.rangesize = 1;
		mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min_ip = mr.range[0].max_ip = newdstip;
		mr.range[0].min = mr.range[0].max = 
			((union ip_conntrack_manip_proto ) { newcid }); 
コード例 #4
0
ファイル: ip_nat_ftp.c プロジェクト: nhanh0/hah
 static unsigned int
  ftp_nat_expected(struct sk_buff **pskb,
                 unsigned int hooknum,
                 struct ip_conntrack *ct,
                 struct ip_nat_info *info)
  {
        struct ip_nat_multi_range mr;
        u_int32_t newdstip, newsrcip, newip;
        struct ip_ct_ftp_expect *exp_ftp_info;

        struct ip_conntrack *master = master_ct(ct);

        IP_NF_ASSERT(info);
        IP_NF_ASSERT(master);

        IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));

        DEBUGP("nat_expected: We have a connection!\n");
        exp_ftp_info = &ct->master->help.exp_ftp_info;

        LOCK_BH(&ip_ftp_lock);

        if (exp_ftp_info->ftptype == IP_CT_FTP_PORT
            || exp_ftp_info->ftptype == IP_CT_FTP_EPRT) {

		/* PORT command: make connection go to the client. */
		newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
		DEBUGP("nat_expected: PORT cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	} else {
		/* PASV command: make the connection go to the server */
		newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
		DEBUGP("nat_expected: PASV cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	}
	UNLOCK_BH(&ip_ftp_lock);

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else
		newip = newdstip;

	DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs... */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	/* ... unless we're doing a MANIP_DST, in which case, make
	   sure we map to the correct port */
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ htons(exp_ftp_info->port) });
コード例 #5
0
ファイル: ip_autofw.c プロジェクト: cilynx/dd-wrt
static unsigned int
autofw_nat_expected(struct sk_buff **pskb,
		 unsigned int hooknum,
		 struct ip_conntrack *ct,
		 struct ip_nat_info *info)
{
	struct ip_nat_multi_range mr;
	u_int32_t newdstip, newsrcip, newip;
	u_int16_t port;
	struct ip_conntrack *master = master_ct(ct);

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);

	IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));

	DEBUGP("autofw_nat_expected: got ");
	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);

	LOCK_BH(&ip_autofw_lock);

	port = ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.all);
	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
#ifdef NEW_PORT_TRIG
	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
#else
	newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
#endif

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else {
		if (port < ntohs(ct->master->help.exp_autofw_info.dport[0]) ||
		    port > ntohs(ct->master->help.exp_autofw_info.dport[1])) {
			UNLOCK_BH(&ip_autofw_lock);
			return NF_DROP;
		}
		newip = newdstip;
	}

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs... */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	/* ... unless we're doing a MANIP_DST, in which case, make
	   sure we map to the correct port */
	port -= ntohs(ct->master->help.exp_autofw_info.dport[0]);
	port += ntohs(ct->master->help.exp_autofw_info.to[0]);
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ htons(port) });
コード例 #6
0
static unsigned int
amanda_nat_expected(struct sk_buff **pskb,
		 unsigned int hooknum,
		 struct ip_conntrack *ct,
		 struct ip_nat_info *info)
{
	struct ip_nat_multi_range mr;
	u_int32_t newdstip, newsrcip, newip;
	u_int16_t port;
	struct ip_ct_amanda_expect *exp_info;
	struct ip_conntrack *master = master_ct(ct);

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);

	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));

	DEBUGP("nat_expected: We have a connection!\n");
	exp_info = &ct->master->help.exp_amanda_info;

	newdstip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
	newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	DEBUGP("nat_expected: %u.%u.%u.%u->%u.%u.%u.%u\n",
	       NIPQUAD(newsrcip), NIPQUAD(newdstip));

	port = exp_info->port;

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else
		newip = newdstip;

	DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs. */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ .udp = { htons(port) } });
コード例 #7
0
ファイル: ip_nat_mms.c プロジェクト: nakedible/vpnease-l2tp
static unsigned int
mms_nat_expected(struct sk_buff **pskb,
                 unsigned int hooknum,
                 struct ip_conntrack *ct,
                 struct ip_nat_info *info)
{
	struct ip_nat_multi_range mr;
	u_int32_t newdstip, newsrcip, newip;

	struct ip_conntrack *master = master_ct(ct);

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);

	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));

	DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");

	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
	DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
	       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
	       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
	       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
	       NIPQUAD(newsrcip), NIPQUAD(newdstip));

	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else
		newip = newdstip;

	DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs. */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	return ip_nat_setup_info(ct, &mr, hooknum);
}
コード例 #8
0
static unsigned int
ip_nat_fn(unsigned int hooknum,
	  struct sk_buff **pskb,
	  const struct net_device *in,
	  const struct net_device *out,
	  int (*okfn)(struct sk_buff *))
{
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	struct ip_nat_info *info;
	/* maniptype == SRC for postrouting. */
	enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);

	/* We never see fragments: conntrack defrags on pre-routing
	   and local-out, and ip_nat_out protects post-routing. */
	IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
		       & htons(IP_MF|IP_OFFSET)));

	(*pskb)->nfcache |= NFC_UNKNOWN;

	/* If we had a hardware checksum before, it's now invalid */
	if ((*pskb)->ip_summed == CHECKSUM_HW)
		(*pskb)->ip_summed = CHECKSUM_NONE;

	ct = ip_conntrack_get(*pskb, &ctinfo);
	/* Can't track?  It's not due to stress, or conntrack would
	   have dropped it.  Hence it's the user's responsibilty to
	   packet filter it out, or implement conntrack/NAT for that
	   protocol. 8) --RR */
	if (!ct) {
		/* Exception: ICMP redirect to new connection (not in
                   hash table yet).  We must not let this through, in
                   case we're doing NAT to the same network. */
		struct iphdr *iph = (*pskb)->nh.iph;
		struct icmphdr *hdr = (struct icmphdr *)
			((u_int32_t *)iph + iph->ihl);
		if (iph->protocol == IPPROTO_ICMP
		    && hdr->type == ICMP_REDIRECT)
			return NF_DROP;
		return NF_ACCEPT;
	}

	switch (ctinfo) {
	case IP_CT_RELATED:
	case IP_CT_RELATED+IP_CT_IS_REPLY:
		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
			return icmp_reply_translation(*pskb, ct, hooknum,
						      CTINFO2DIR(ctinfo));
		}
		/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
	case IP_CT_NEW:
#ifdef CONFIG_IP_NF_NAT_LOCAL
		/* LOCAL_IN hook doesn't have a chain and thus doesn't care
		 * about new packets -HW */
		if (hooknum == NF_IP_LOCAL_IN)
			return NF_ACCEPT;
#endif
		info = &ct->nat.info;

		WRITE_LOCK(&ip_nat_lock);
		/* Seen it before?  This can happen for loopback, retrans,
		   or local packets.. */
		if (!(info->initialized & (1 << maniptype))) {
			int in_hashes = info->initialized;
			unsigned int ret;

			if (ct->master
			    && master_ct(ct)->nat.info.helper
			    && master_ct(ct)->nat.info.helper->expect) {
				ret = call_expect(master_ct(ct), pskb, 
						  hooknum, ct, info);
			} else {
				ret = ip_nat_rule_find(pskb, hooknum, in, out,
						       ct, info);
			}

			if (ret != NF_ACCEPT) {
				WRITE_UNLOCK(&ip_nat_lock);
				return ret;
			}

			if (in_hashes) {
				IP_NF_ASSERT(info->bysource.conntrack);
				replace_in_hashes(ct, info);
			} else {
				place_in_hashes(ct, info);
			}
		} else
			DEBUGP("Already setup manip %s for ct %p\n",
			       maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
			       ct);
		WRITE_UNLOCK(&ip_nat_lock);
		break;

	default:
		/* ESTABLISHED */
		IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED
			     || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
		info = &ct->nat.info;
	}

	IP_NF_ASSERT(info);
	return do_bindings(ct, ctinfo, info, hooknum, pskb);
}
コード例 #9
0
static int pptp_expectfn(struct ip_conntrack *ct)
{
	struct ip_conntrack *master;
	struct ip_conntrack_expect *exp;

	#ifdef CONFIG_IFX_ALG_QOS  // chandrav
	IFX_ALG_QOS_DBG("\nPPTP_ALG: Master conntracker ifx_alg_qos_mark is : %x \n",ct->ifx_alg_qos_mark );
	/*
	 * Mark the connection tracker with PPTP ALG Application Family type 
	 * (IFX_ALG_PROTO_DATA) and PPTP ALG Protocol Family type 
	 * (IFX_ALG_PROTO_DATA)	
	 */
	ct->ifx_alg_qos_mark = IFX_ALG_APP_PPTP | IFX_ALG_PROTO_DATA;
	IFX_ALG_QOS_DBG("\nPPTP ALG:Marked the Child conntracker with:%x \n",
					ct->ifx_alg_qos_mark );	
	#endif /* CONFIG_IFX_ALG_QOS */

	DEBUGP("increasing timeouts\n");
	/* increase timeout of GRE data channel conntrack entry */
	ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
	ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;

	master = master_ct(ct);
	if (!master) {
		DEBUGP(" no master!!!\n");
		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 == 
		htonl(master->help.ct_pptp_info.pac_call_id)) {	
		/* assume PNS->PAC */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
			htonl(master->help.ct_pptp_info.pns_call_id);
		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
			htonl(master->help.ct_pptp_info.pns_call_id);
	} else {
		/* assume PAC->PNS */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
			htonl(master->help.ct_pptp_info.pac_call_id);
		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;
}
コード例 #10
0
ファイル: ip_nat_h323.c プロジェクト: iwangv/edimax-br-6528n
static unsigned int
h225_nat_expected(struct sk_buff **pskb,
		  unsigned int hooknum,
		  struct ip_conntrack *ct,
		  struct ip_nat_info *info)
{
	struct ip_nat_multi_range mr;
	u_int32_t newdstip, newsrcip, newip;
	u_int16_t port;
	struct ip_ct_h225_expect *exp_info;
	struct ip_ct_h225_master *master_info;
	struct ip_conntrack *master = master_ct(ct);
	unsigned int is_h225, ret;
	
	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);

	IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));

	DEBUGP("h225_nat_expected: We have a connection!\n");
	master_info = &ct->master->expectant->help.ct_h225_info;
	exp_info = &ct->master->help.exp_h225_info;

	LOCK_BH(&ip_h323_lock);

	DEBUGP("master: ");
	DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
	DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
	DEBUGP("conntrack: ");
	DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
	if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
		/* Make connection go to the client. */
		newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
		DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	} else {
		/* Make the connection go to the server */
		newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
		DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	}
	port = exp_info->port;
	is_h225 = master_info->is_h225 == H225_PORT;
	UNLOCK_BH(&ip_h323_lock);
	
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else
		newip = newdstip;

	DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs... */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;

	/* ... unless we're doing a MANIP_DST, in which case, make
	   sure we map to the correct port */
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ .tcp = { port } });
コード例 #11
0
static unsigned int
ip_nat_fn(unsigned int hooknum,
	  struct sk_buff **pskb,
	  const struct net_device *in,
	  const struct net_device *out,
	  int (*okfn)(struct sk_buff *))
{
	struct ip_conntrack *ct;
	enum ip_conntrack_info ctinfo;
	struct ip_nat_info *info;
	/* maniptype == SRC for postrouting. */
	enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum);

	/* We never see fragments: conntrack defrags on pre-routing
	   and local-out, and ip_nat_out protects post-routing. */
	IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off
		       & htons(IP_MF|IP_OFFSET)));

	(*pskb)->nfcache |= NFC_UNKNOWN;

	ct = ip_conntrack_get(*pskb, &ctinfo);
	/* Can't track?  It's not due to stress, or conntrack would
	   have dropped it.  Hence it's the user's responsibilty to
	   packet filter it out, or implement conntrack/NAT for that
	   protocol. 8) --RR */
	if (!ct) {
		/* Exception: ICMP redirect to new connection (not in
                   hash table yet).  We must not let this through, in
                   case we're doing NAT to the same network. */
		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
			struct icmphdr _hdr, *hp;

			hp = skb_header_pointer(*pskb,
						(*pskb)->nh.iph->ihl*4,
						sizeof(_hdr), &_hdr);
			if (hp != NULL &&
			    hp->type == ICMP_REDIRECT)
				return NF_DROP;
		}
		return NF_ACCEPT;
	}

	/* If we had a hardware checksum before, it's now invalid */
	if ((*pskb)->ip_summed == CHECKSUM_HW)
		if (skb_checksum_help(pskb, (out == NULL)))
			return NF_DROP;

	switch (ctinfo) {
	case IP_CT_RELATED:
	case IP_CT_RELATED+IP_CT_IS_REPLY:
		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
			if (!icmp_reply_translation(pskb, ct, hooknum,
						    CTINFO2DIR(ctinfo)))
				return NF_DROP;
			else
				return NF_ACCEPT;
		}
		/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
	case IP_CT_NEW:
		info = &ct->nat.info;

		WRITE_LOCK(&ip_nat_lock);
		/* Seen it before?  This can happen for loopback, retrans,
		   or local packets.. */
		if (!(info->initialized & (1 << maniptype))
#ifndef CONFIG_IP_NF_NAT_LOCAL
		    /* If this session has already been confirmed we must not
		     * touch it again even if there is no mapping set up.
		     * Can only happen on local->local traffic with
		     * CONFIG_IP_NF_NAT_LOCAL disabled.
		     */
		    && !(ct->status & IPS_CONFIRMED)
#endif
		    ) {
			unsigned int ret;

			if (ct->master
			    && master_ct(ct)->nat.info.helper
			    && master_ct(ct)->nat.info.helper->expect) {
				ret = call_expect(master_ct(ct), pskb, 
						  hooknum, ct, info);
			} else {
#ifdef CONFIG_IP_NF_NAT_LOCAL
				/* LOCAL_IN hook doesn't have a chain!  */
				if (hooknum == NF_IP_LOCAL_IN)
					ret = alloc_null_binding(ct, info,
								 hooknum);
				else
#endif
				ret = ip_nat_rule_find(pskb, hooknum, in, out,
						       ct, info);
			}

			if (ret != NF_ACCEPT) {
				WRITE_UNLOCK(&ip_nat_lock);
				return ret;
			}
		} else
			DEBUGP("Already setup manip %s for ct %p\n",
			       maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
			       ct);
		WRITE_UNLOCK(&ip_nat_lock);
		break;

	default:
		/* ESTABLISHED */
		IP_NF_ASSERT(ctinfo == IP_CT_ESTABLISHED
			     || ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
		info = &ct->nat.info;
	}

	IP_NF_ASSERT(info);
	return do_bindings(ct, ctinfo, info, hooknum, pskb);
}
コード例 #12
0
ファイル: ip_nat_talk.c プロジェクト: nakedible/vpnease-l2tp
static unsigned int
talk_nat_expected(struct sk_buff **pskb,
		  unsigned int hooknum,
		  struct ip_conntrack *ct,
		  struct ip_nat_info *info)
{
	struct ip_nat_multi_range mr;
	u_int32_t newdstip, newsrcip, newip;
	u_int16_t port;
	unsigned int ret;
	
	struct ip_conntrack *master = master_ct(ct);

	IP_NF_ASSERT(info);
	IP_NF_ASSERT(master);

	IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));

	DEBUGP("ip_nat_talk_expected: We have a connection!\n");

	LOCK_BH(&ip_talk_lock);
	port = ct->master->help.exp_talk_info.port;
	UNLOCK_BH(&ip_talk_lock);

	DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
	       CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
	       hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
	       : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
	       : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
	       ct, master);

	if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
		/* Callee client -> caller server */
#ifdef IP_NAT_TALK_DEBUG
		struct iphdr *iph = (*pskb)->nh.iph;
		struct udphdr *udph = (void *)iph + iph->ihl * 4;

		DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
		       NIPQUAD(iph->saddr), ntohs(udph->source),
		       NIPQUAD(iph->daddr), ntohs(udph->dest));
#endif
		newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
		DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	} else {
		/* Callee client -> caller client */
#ifdef IP_NAT_TALK_DEBUG
		struct iphdr *iph = (*pskb)->nh.iph;
		struct tcphdr *tcph = (void *)iph + iph->ihl * 4;

		DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
		       NIPQUAD(iph->saddr), ntohs(tcph->source),
		       NIPQUAD(iph->daddr), ntohs(tcph->dest));
#endif
		newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
		newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
		DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
		       NIPQUAD(newsrcip), NIPQUAD(newdstip));
	}
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
		newip = newsrcip;
	else
		newip = newdstip;

	DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));

	mr.rangesize = 1;
	/* We don't want to manip the per-protocol, just the IPs... */
	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
	mr.range[0].min_ip = mr.range[0].max_ip = newip;
	
	/* ... unless we're doing a MANIP_DST, in which case, make
	   sure we map to the correct port */
	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
		mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
		mr.range[0].min = mr.range[0].max
			= ((union ip_conntrack_manip_proto)
				{ .udp = { port } });
コード例 #13
0
static int pptp_expectfn(struct ip_conntrack *ct)
{
	struct ip_conntrack *master;
	struct ip_conntrack_expect *exp;

	DEBUGP("increasing timeouts\n");
	/* increase timeout of GRE data channel conntrack entry */
	ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
	ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;

	master = master_ct(ct);
	if (!master) {
		DEBUGP(" no master!!!\n");
		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 == 
		htonl(master->help.ct_pptp_info.pac_call_id)) {	
		/* assume PNS->PAC */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
			htonl(master->help.ct_pptp_info.pns_call_id);
		ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
			htonl(master->help.ct_pptp_info.pns_call_id);
	} else {
		/* assume PAC->PNS */
		ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
			htonl(master->help.ct_pptp_info.pac_call_id);
		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;
}