static unsigned int ipv4_conntrack_help(unsigned int hooknum,
				      struct sk_buff **pskb,
				      const struct net_device *in,
				      const struct net_device *out,
				      int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	struct nf_conn_help *help;

	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(*pskb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
		return NF_ACCEPT;

	help = nfct_help(ct);
	if (!help || !help->helper)
		return NF_ACCEPT;

#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE)
            if( (skb_headroom(*pskb) >=4)  &&
                    ((FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_PCI) ||
                     (FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_WLAN) ||
                     (FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_GE))){
                    FOE_ALG_RXIF(*pskb)=1;
            }
#endif

	return help->helper->help(pskb,
			       (*pskb)->nh.raw - (*pskb)->data
					       + (*pskb)->nh.iph->ihl*4,
			       ct, ctinfo);
}
Exemple #2
0
/* timeout GRE data connections */
static void pptp_destroy_siblings(struct nf_conn *ct)
{
	struct net *net = nf_ct_net(ct);
	const struct nf_conn_help *help = nfct_help(ct);
	struct nf_conntrack_tuple t;

#ifdef CONFIG_HTC_NET_MODIFY
    if (help == NULL)
        printk("[NET] help = NULL in %s\n", __func__);
#endif

	nf_ct_gre_keymap_destroy(ct);

	/* try original (pns->pac) tuple */
	memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t));
	t.dst.protonum = IPPROTO_GRE;
	t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
	t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
	if (!destroy_sibling_or_exp(net, ct, &t))
		pr_debug("failed to timeout original pns->pac ct/exp\n");

	/* try reply (pac->pns) tuple */
	memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t));
	t.dst.protonum = IPPROTO_GRE;
	t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
	t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
	if (!destroy_sibling_or_exp(net, ct, &t))
		pr_debug("failed to timeout reply pac->pns ct/exp\n");
}
static unsigned int ipv4_helper(unsigned int hooknum,
				struct sk_buff *skb,
				const struct net_device *in,
				const struct net_device *out,
				int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	const struct nf_conn_help *help;
	const struct nf_conntrack_helper *helper;

	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
		return NF_ACCEPT;

	help = nfct_help(ct);
	if (!help)
		return NF_ACCEPT;

	/* rcu_read_lock()ed by nf_hook_slow */
	helper = rcu_dereference(help->helper);
	if (!helper)
		return NF_ACCEPT;

	return helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
			    ct, ctinfo);
}
Exemple #4
0
static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data, UnregistrationRequest *urq)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int ret;
	typeof(set_sig_addr_hook) set_sig_addr;

	pr_debug("nf_ct_ras: URQ\n");

	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
				   urq->callSignalAddress.item,
				   urq->callSignalAddress.count);
		if (ret < 0)
			return -1;
	}

	
	nf_ct_remove_expectations(ct);
	info->sig_port[dir] = 0;
	info->sig_port[!dir] = 0;

	
	nf_ct_refresh(ct, skb, 30 * HZ);

	return 0;
}
static bool
helper_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct xt_helper_info *info = par->matchinfo;
	const struct nf_conn *ct;
	const struct nf_conn_help *master_help;
	const struct nf_conntrack_helper *helper;
	enum ip_conntrack_info ctinfo;
	bool ret = info->invert;

	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || !ct->master)
		return ret;

	master_help = nfct_help(ct->master);
	if (!master_help)
		return ret;

	/*                                   */
	helper = rcu_dereference(master_help->helper);
	if (!helper)
		return ret;

	if (info->name[0] == '\0')
		ret = !ret;
	else
		ret ^= !strncmp(helper->name, info->name,
				strlen(helper->name));
	return ret;
}
Exemple #6
0
static int map_addr(struct sk_buff *skb, unsigned int dataoff,
		    const char **dptr, unsigned int *datalen,
		    unsigned int matchoff, unsigned int matchlen,
		    union nf_inet_addr *addr, __be16 port)
{
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
#if defined(CONFIG_SYNO_COMCERTO)
	struct nf_conn_help *help = nfct_help(ct);
#endif
	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
	unsigned int buflen;
	__be32 newaddr;
	__be16 newport;

	if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
	    ct->tuplehash[dir].tuple.src.u.udp.port == port) {
		newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
		newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
		newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
#if defined(CONFIG_SYNO_COMCERTO)
		newport = help->help.ct_sip_info.forced_dport ? :
			  ct->tuplehash[!dir].tuple.src.u.udp.port;
#else
		newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
#endif
	} else
Exemple #7
0
static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data, UnregistrationRequest *urq)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int ret;
	typeof(set_sig_addr_hook) set_sig_addr;

	pr_debug("nf_ct_ras: URQ\n");

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(info) || (!info))
		printk(KERN_ERR "[NET] info is NULL in %s!\n", __func__);
#endif

	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
				   urq->callSignalAddress.item,
				   urq->callSignalAddress.count);
		if (ret < 0)
			return -1;
	}

	
	nf_ct_remove_expectations(ct);
	info->sig_port[dir] = 0;
	info->sig_port[!dir] = 0;

	
	nf_ct_refresh(ct, skb, 30 * HZ);

	return 0;
}
static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
{
	struct xt_ct_target_info_v1 *info = par->targinfo;
	struct nf_conn *ct = info->ct;
	struct nf_conn_help *help;
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
	struct nf_conn_timeout *timeout_ext;
	typeof(nf_ct_timeout_put_hook) timeout_put;
#endif
	if (!nf_ct_is_untracked(ct)) {
		help = nfct_help(ct);
		if (help)
			module_put(help->helper->me);

		nf_ct_l3proto_module_put(par->family);

#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
		rcu_read_lock();
		timeout_put = rcu_dereference(nf_ct_timeout_put_hook);

		if (timeout_put) {
			timeout_ext = nf_ct_timeout_find(ct);
			if (timeout_ext)
				timeout_put(timeout_ext->timeout);
		}
		rcu_read_unlock();
#endif
	}
	nf_ct_put(info->ct);
}
static void
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_ct_pptp_master *ct_pptp_info;
	struct nf_nat_pptp *nat_pptp_info;

	ct_pptp_info  = &nfct_help(ct)->help.ct_pptp_info;
	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;

	/* alter expectation for PNS->PAC direction */
	expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
	expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
	expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
	expect_orig->dir = IP_CT_DIR_ORIGINAL;

	/* alter expectation for PAC->PNS direction */
	expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
	expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
	expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
	expect_reply->dir = IP_CT_DIR_REPLY;
}
static unsigned int ipv4_helper(unsigned int hooknum,
				struct sk_buff *skb,
				const struct net_device *in,
				const struct net_device *out,
				int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	const struct nf_conn_help *help;
	const struct nf_conntrack_helper *helper;
	unsigned int ret;

	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
		return NF_ACCEPT;

	help = nfct_help(ct);
	if (!help)
		return NF_ACCEPT;

	/* rcu_read_lock()ed by nf_hook_slow */
	helper = rcu_dereference(help->helper);
	if (!helper)
		return NF_ACCEPT;

	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
			   ct, ctinfo);
	if (ret != NF_ACCEPT && (ret & NF_VERDICT_MASK) != NF_QUEUE) {
		nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
			      "nf_ct_%s: dropping packet", helper->name);
	}
	return ret;
}
static void
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_ct_pptp_master *ct_pptp_info;
	struct nf_nat_pptp *nat_pptp_info;

	ct_pptp_info  = &nfct_help(ct)->help.ct_pptp_info;
	nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;

	
	nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;

	
	expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
	expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
	expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
	expect_orig->dir = IP_CT_DIR_ORIGINAL;

	
	expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
	expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
	expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
	expect_reply->dir = IP_CT_DIR_REPLY;
}
static inline int
ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
	struct nfattr *nest_helper;
	const struct nf_conn_help *help = nfct_help(ct);
	struct nf_conntrack_helper *helper;

	if (!help)
		return 0;

	rcu_read_lock();
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

	nest_helper = NFA_NEST(skb, CTA_HELP);
	NFA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);

	if (helper->to_nfattr)
		helper->to_nfattr(skb, ct);

	NFA_NEST_END(skb, nest_helper);
out:
	rcu_read_unlock();
	return 0;

nfattr_failure:
	rcu_read_unlock();
	return -1;
}
Exemple #13
0
static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data, RegistrationRequest *rrq)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int ret;
	typeof(set_ras_addr_hook) set_ras_addr;

	pr_debug("nf_ct_ras: RRQ\n");

	ret = expect_q931(skb, ct, ctinfo, data,
			  rrq->callSignalAddress.item,
			  rrq->callSignalAddress.count);
	if (ret < 0)
		return -1;

	set_ras_addr = rcu_dereference(set_ras_addr_hook);
	if (set_ras_addr && ct->status & IPS_NAT_MASK) {
		ret = set_ras_addr(skb, ct, ctinfo, data,
				   rrq->rasAddress.item,
				   rrq->rasAddress.count);
		if (ret < 0)
			return -1;
	}

	if (rrq->options & eRegistrationRequest_timeToLive) {
		pr_debug("nf_ct_ras: RRQ TTL = %u seconds\n", rrq->timeToLive);
		info->timeout = rrq->timeToLive;
	} else
		info->timeout = default_rrq_ttl;

	return 0;
}
Exemple #14
0
static void
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_ct_pptp_master *ct_pptp_info;
    struct nf_nat_pptp *nat_pptp_info;

    ct_pptp_info  = &nfct_help(ct)->help.ct_pptp_info;
    nat_pptp_info = &nfct_nat(ct)->help.nat_pptp_info;

#ifdef CONFIG_HTC_NETWORK_MODIFY
    if (IS_ERR(ct_pptp_info) || (!ct_pptp_info))
        printk(KERN_ERR "[NET] ct_pptp_info is NULL in %s!\n", __func__);

    if (IS_ERR(nat_pptp_info) || (!nat_pptp_info))
        printk(KERN_ERR "[NET] nat_pptp_info is NULL in %s!\n", __func__);
#endif

    /* save original PAC call ID in nat_info */
    nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;

    /* alter expectation for PNS->PAC direction */
    expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id;
    expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id;
    expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id;
    expect_orig->dir = IP_CT_DIR_ORIGINAL;

    /* alter expectation for PAC->PNS direction */
    expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id;
    expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id;
    expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id;
    expect_reply->dir = IP_CT_DIR_REPLY;
}
static inline int
ctnetlink_dump_helpinfo(struct sk_buff *skb, const struct nf_conn *ct)
{
	struct nlattr *nest_helper;
	const struct nf_conn_help *help = nfct_help(ct);
	struct nf_conntrack_helper *helper;

	if (!help)
		return 0;

	rcu_read_lock();
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

	nest_helper = nla_nest_start(skb, CTA_HELP | NLA_F_NESTED);
	if (!nest_helper)
		goto nla_put_failure;
	NLA_PUT(skb, CTA_HELP_NAME, strlen(helper->name), helper->name);

	if (helper->to_nlattr)
		helper->to_nlattr(skb, ct);

	nla_nest_end(skb, nest_helper);
out:
	rcu_read_unlock();
	return 0;

nla_put_failure:
	rcu_read_unlock();
	return -1;
}
Exemple #16
0
static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data,
		       TransportAddress *taddr, int count)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int ret = 0;
	int i;
	__be16 port;
	union nf_inet_addr addr;
	struct nf_conntrack_expect *exp;
	typeof(nat_q931_hook) nat_q931;

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(info) || (!info))
		printk(KERN_ERR "[NET] info is NULL in %s!\n", __func__);
#endif

	
	for (i = 0; i < count; i++) {
		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port) &&
		    memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3,
			   sizeof(addr)) == 0 && port != 0)
			break;
	}

	if (i >= count)		
		return 0;

	
	if ((exp = nf_ct_expect_alloc(ct)) == NULL)
		return -1;
	nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
			  gkrouted_only ? 
				&ct->tuplehash[!dir].tuple.src.u3 : NULL,
			  &ct->tuplehash[!dir].tuple.dst.u3,
			  IPPROTO_TCP, NULL, &port);
	exp->helper = nf_conntrack_helper_q931;
	exp->flags = NF_CT_EXPECT_PERMANENT;	

	nat_q931 = rcu_dereference(nat_q931_hook);
	if (nat_q931 && ct->status & IPS_NAT_MASK) {	
		ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
	} else {		
		if (nf_ct_expect_related(exp) == 0) {
			pr_debug("nf_ct_ras: expect Q.931 ");
			nf_ct_dump_tuple(&exp->tuple);

			
			info->sig_port[dir] = port;
		} else
			ret = -1;
	}

	nf_ct_expect_put(exp);

	return ret;
}
Exemple #17
0
static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
		    enum ip_conntrack_info ctinfo,
		    unsigned char **data, int dataoff,
		    TransportAddress *taddr, __be16 port,
		    struct nf_conntrack_expect *exp)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	u_int16_t nated_port = ntohs(port);

	/* Set expectations for NAT */
	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
	exp->expectfn = nf_nat_follow_master;
	exp->dir = !dir;

	/* Check existing expects */
	if (info->sig_port[dir] == port)
		nated_port = ntohs(info->sig_port[!dir]);

	/* Try to get same port: if not, try to change it. */
	for (; nated_port != 0; nated_port++) {
		int ret;

		exp->tuple.dst.u.tcp.port = htons(nated_port);
		ret = nf_ct_expect_related(exp);
		if (ret == 0)
			break;
		else if (ret != -EBUSY) {
			nated_port = 0;
			break;
		}
	}

	if (nated_port == 0) {	/* No port available */
		if (net_ratelimit())
			pr_notice("nf_nat_q931: out of TCP ports\n");
		return 0;
	}

	/* Modify signal */
	if (set_h225_addr(skb, data, dataoff, taddr,
			  &ct->tuplehash[!dir].tuple.dst.u3,
			  htons(nated_port)) == 0) {
		/* Save ports */
		info->sig_port[dir] = port;
		info->sig_port[!dir] = htons(nated_port);
	} else {
		nf_ct_unexpect_related(exp);
		return -1;
	}

	pr_debug("nf_nat_q931: expect H.245 %pI4:%hu->%pI4:%hu\n",
		 &exp->tuple.src.u3.ip,
		 ntohs(exp->tuple.src.u.tcp.port),
		 &exp->tuple.dst.u3.ip,
		 ntohs(exp->tuple.dst.u.tcp.port));

	return 0;
}
Exemple #18
0
static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
			enum ip_conntrack_info ctinfo,
			unsigned char **data,
			TransportAddress *taddr, int count)
{
	const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int i;
	__be16 port;
	union nf_inet_addr addr;

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(info) || (!info))
		printk(KERN_ERR "[NET] info is NULL in %s!\n", __func__);
#endif

	for (i = 0; i < count; i++) {
		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
			if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
			    port == info->sig_port[dir]) {
				/* GW->GK */

				/* Fix for Gnomemeeting */
				if (i > 0 &&
				    get_h225_addr(ct, *data, &taddr[0],
						  &addr, &port) &&
				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
					i = 0;

				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
					 &addr.ip, port,
					 &ct->tuplehash[!dir].tuple.dst.u3.ip,
					 info->sig_port[!dir]);
				return set_h225_addr(skb, data, 0, &taddr[i],
						     &ct->tuplehash[!dir].
						     tuple.dst.u3,
						     info->sig_port[!dir]);
			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
				   port == info->sig_port[dir]) {
				/* GK->GW */
				pr_debug("nf_nat_ras: set signal address %pI4:%hu->%pI4:%hu\n",
					 &addr.ip, port,
					 &ct->tuplehash[!dir].tuple.src.u3.ip,
					 info->sig_port[!dir]);
				return set_h225_addr(skb, data, 0, &taddr[i],
						     &ct->tuplehash[!dir].
						     tuple.src.u3,
						     info->sig_port[!dir]);
			}
		}
	}

	return 0;
}
static unsigned int ipv4_confirm(unsigned int hooknum,
				 struct sk_buff *skb,
				 const struct net_device *in,
				 const struct net_device *out,
				 int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	const struct nf_conn_help *help;
	const struct nf_conntrack_helper *helper;
	unsigned int ret;

	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
		goto out;

	help = nfct_help(ct);
	if (!help)
		goto out;

	/* rcu_read_lock()ed by nf_hook_slow */
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE)
	if (IS_SPACE_AVAILABLED(skb) && IS_MAGIC_TAG_VALID(skb)) {
		FOE_ALG(skb)=1;
	}
#endif
	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
			   ct, ctinfo);
	if (ret != NF_ACCEPT) {
		nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
			      "nf_ct_%s: dropping packet", helper->name);
		return ret;
	}

	/* adjust seqs for loopback traffic only in outgoing direction */
	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
	    !nf_is_loopback_packet(skb)) {
		typeof(nf_nat_seq_adjust_hook) seq_adjust;

		seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
		if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) {
			NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
			return NF_DROP;
		}
	}
out:
	/* We've seen it coming out the other side: confirm it */
	return nf_conntrack_confirm(skb);
}
Exemple #20
0
static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
			enum ip_conntrack_info ctinfo,
			unsigned char **data,
			TransportAddress *taddr, int count)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int i;
	__be16 port;
	union nf_inet_addr addr;

	for (i = 0; i < count; i++) {
		if (get_h225_addr(ct, *data, &taddr[i], &addr, &port)) {
			if (addr.ip == ct->tuplehash[dir].tuple.src.u3.ip &&
			    port == info->sig_port[dir]) {
				/* GW->GK */

				/* Fix for Gnomemeeting */
				if (i > 0 &&
				    get_h225_addr(ct, *data, &taddr[0],
						  &addr, &port) &&
				    (ntohl(addr.ip) & 0xff000000) == 0x7f000000)
					i = 0;

				DEBUGP
				    ("nf_nat_ras: set signal address "
				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
				     NIPQUAD(ip), port,
				     NIPQUAD(ct->tuplehash[!dir].tuple.dst.
					     ip), info->sig_port[!dir]);
				return set_h225_addr(skb, data, 0, &taddr[i],
						     &ct->tuplehash[!dir].
						     tuple.dst.u3,
						     info->sig_port[!dir]);
			} else if (addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip &&
				   port == info->sig_port[dir]) {
				/* GK->GW */
				DEBUGP
				    ("nf_nat_ras: set signal address "
				     "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
				     NIPQUAD(ip), port,
				     NIPQUAD(ct->tuplehash[!dir].tuple.src.
					     ip), info->sig_port[!dir]);
				return set_h225_addr(skb, data, 0, &taddr[i],
						     &ct->tuplehash[!dir].
						     tuple.src.u3,
						     info->sig_port[!dir]);
			}
		}
	}

	return 0;
}
static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
			enum ip_conntrack_info ctinfo,
			unsigned char **data,
			TransportAddress *taddr, int count)
{
	const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int i;
	__be16 port;
	union nf_inet_addr addr;

<<<<<<< HEAD
Exemple #22
0
static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data, RegistrationConfirm *rcf)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	int ret;
	struct nf_conntrack_expect *exp;
	typeof(set_sig_addr_hook) set_sig_addr;

	pr_debug("nf_ct_ras: RCF\n");

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(info) || (!info))
		printk(KERN_ERR "[NET] info is NULL in %s!\n", __func__);
#endif

	set_sig_addr = rcu_dereference(set_sig_addr_hook);
	if (set_sig_addr && ct->status & IPS_NAT_MASK) {
		ret = set_sig_addr(skb, ct, ctinfo, data,
					rcf->callSignalAddress.item,
					rcf->callSignalAddress.count);
		if (ret < 0)
			return -1;
	}

	if (rcf->options & eRegistrationConfirm_timeToLive) {
		pr_debug("nf_ct_ras: RCF TTL = %u seconds\n", rcf->timeToLive);
		info->timeout = rcf->timeToLive;
	}

	if (info->timeout > 0) {
		pr_debug("nf_ct_ras: set RAS connection timeout to "
			 "%u seconds\n", info->timeout);
		nf_ct_refresh(ct, skb, info->timeout * HZ);

		
		spin_lock_bh(&nf_conntrack_lock);
		exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3,
				  info->sig_port[!dir]);
		if (exp) {
			pr_debug("nf_ct_ras: set Q.931 expect "
				 "timeout to %u seconds for",
				 info->timeout);
			nf_ct_dump_tuple(&exp->tuple);
			set_expect_timeout(exp, info->timeout);
		}
		spin_unlock_bh(&nf_conntrack_lock);
	}

	return 0;
}
static unsigned int ipv4_confirm(unsigned int hooknum,
				 struct sk_buff *skb,
				 const struct net_device *in,
				 const struct net_device *out,
				 int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	const struct nf_conn_help *help;
	const struct nf_conntrack_helper *helper;
	unsigned int ret;

	
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
		goto out;

	help = nfct_help(ct);
	if (!help)
		goto out;

	
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
			   ct, ctinfo);
	if (ret != NF_ACCEPT) {
		nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
			      "nf_ct_%s: dropping packet", helper->name);
		return ret;
	}

	
	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
	    !nf_is_loopback_packet(skb)) {
		typeof(nf_nat_seq_adjust_hook) seq_adjust;

		seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
		if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) {
			NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
			return NF_DROP;
		}
	}
out:
	
	return nf_conntrack_confirm(skb);
}
Exemple #24
0
static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
{
    struct xt_ct_target_info *info = par->targinfo;
    struct nf_conn *ct = info->ct;
    struct nf_conn_help *help;

    if (!nf_ct_is_untracked(ct)) {
        help = nfct_help(ct);
        if (help)
            module_put(help->helper->me);

        nf_ct_l3proto_module_put(par->family);
    }
    nf_ct_put(info->ct);
}
static unsigned int ipv4_confirm(unsigned int hooknum,
				 struct sk_buff *skb,
				 const struct net_device *in,
				 const struct net_device *out,
				 int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	enum ip_conntrack_info ctinfo;
	const struct nf_conn_help *help;
	const struct nf_conntrack_helper *helper;
	unsigned int ret;

	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
		goto out;

	help = nfct_help(ct);
	if (!help)
		goto out;

	/* rcu_read_lock()ed by nf_hook_slow */
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

	ret = helper->help(skb, skb_network_offset(skb) + ip_hdrlen(skb),
			   ct, ctinfo);
//Alpha
	if (ret != NF_ACCEPT) {
		nf_log_packet(NFPROTO_IPV4, hooknum, skb, in, out, NULL,
			      "nf_ct_%s: dropping packet", helper->name);
		return ret;
	}

	if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
		typeof(nf_nat_seq_adjust_hook) seq_adjust;

		seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
		if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) {
			NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
			return NF_DROP;
		}
	}
out:
	/* We've seen it coming out the other side: confirm it */
	return nf_conntrack_confirm(skb);
}
static unsigned int ipv6_confirm(unsigned int hooknum,
				 struct sk_buff **pskb,
				 const struct net_device *in,
				 const struct net_device *out,
				 int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	struct nf_conn_help *help;
	enum ip_conntrack_info ctinfo;
	unsigned int ret, protoff;
	unsigned int extoff = (u8*)((*pskb)->nh.ipv6h + 1)
			      - (*pskb)->data;
	unsigned char pnum = (*pskb)->nh.ipv6h->nexthdr;


	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(*pskb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
		goto out;

	help = nfct_help(ct);
	if (!help || !help->helper)
		goto out;

	protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
					 (*pskb)->len - extoff);
	if (protoff < 0 || protoff > (*pskb)->len ||
	    pnum == NEXTHDR_FRAGMENT) {
		DEBUGP("proto header not found\n");
		return NF_ACCEPT;
	}

#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE)
	if( (skb_headroom(*pskb) >=4)  &&
		((FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_PCI) ||
		 (FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_WLAN) ||
		 (FOE_MAGIC_TAG(*pskb) == FOE_MAGIC_GE))){
	    FOE_ALG_RXIF(*pskb)=1;
	}
#endif

	ret = help->helper->help(pskb, protoff, ct, ctinfo);
	if (ret != NF_ACCEPT)
		return ret;
out:
	/* We've seen it coming out the other side: confirm it */
	return nf_conntrack_confirm(pskb);
}
Exemple #27
0
/* 'skb' should already be pulled to nh_ofs. */
static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
{
	const struct nf_conntrack_helper *helper;
	const struct nf_conn_help *help;
	enum ip_conntrack_info ctinfo;
	unsigned int protoff;
	struct nf_conn *ct;

	ct = nf_ct_get(skb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
		return NF_ACCEPT;

	help = nfct_help(ct);
	if (!help)
		return NF_ACCEPT;

	helper = rcu_dereference(help->helper);
	if (!helper)
		return NF_ACCEPT;

	switch (proto) {
	case NFPROTO_IPV4:
		protoff = ip_hdrlen(skb);
		break;
	case NFPROTO_IPV6: {
		u8 nexthdr = ipv6_hdr(skb)->nexthdr;
		__be16 frag_off;
		int ofs;

		ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
				       &frag_off);
		if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
			pr_debug("proto header not found\n");
			return NF_ACCEPT;
		}
		protoff = ofs;
		break;
	}
	default:
		WARN_ONCE(1, "helper invoked on non-IP family!");
		return NF_DROP;
	}

	return helper->help(skb, protoff, ct, ctinfo);
}
Exemple #28
0
static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
		       enum ip_conntrack_info ctinfo,
		       unsigned char **data, AdmissionRequest *arq)
{
	const struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	__be16 port;
	union nf_inet_addr addr;
	typeof(set_h225_addr_hook) set_h225_addr;

	pr_debug("nf_ct_ras: ARQ\n");

#ifdef CONFIG_HTC_NETWORK_MODIFY
	if (IS_ERR(info) || (!info))
		printk(KERN_ERR "[NET] info is NULL in %s!\n", __func__);
#endif

	set_h225_addr = rcu_dereference(set_h225_addr_hook);
	if ((arq->options & eAdmissionRequest_destCallSignalAddress) &&
	    get_h225_addr(ct, *data, &arq->destCallSignalAddress,
			  &addr, &port) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    port == info->sig_port[dir] &&
	    set_h225_addr && ct->status & IPS_NAT_MASK) {
		
		return set_h225_addr(skb, data, 0,
				     &arq->destCallSignalAddress,
				     &ct->tuplehash[!dir].tuple.dst.u3,
				     info->sig_port[!dir]);
	}

	if ((arq->options & eAdmissionRequest_srcCallSignalAddress) &&
	    get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
			  &addr, &port) &&
	    !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
	    set_h225_addr && ct->status & IPS_NAT_MASK) {
		
		return set_h225_addr(skb, data, 0,
				     &arq->srcCallSignalAddress,
				     &ct->tuplehash[!dir].tuple.dst.u3,
				     port);
	}

	return 0;
}
static unsigned int ipv6_confirm(unsigned int hooknum,
				 struct sk_buff **pskb,
				 const struct net_device *in,
				 const struct net_device *out,
				 int (*okfn)(struct sk_buff *))
{
	struct nf_conn *ct;
	struct nf_conn_help *help;
	struct nf_conntrack_helper *helper;
	enum ip_conntrack_info ctinfo;
	unsigned int ret, protoff;
	unsigned int extoff = (u8 *)(ipv6_hdr(*pskb) + 1) - (*pskb)->data;
	unsigned char pnum = ipv6_hdr(*pskb)->nexthdr;


	/* This is where we call the helper: as the packet goes out. */
	ct = nf_ct_get(*pskb, &ctinfo);
	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
		goto out;

	help = nfct_help(ct);
	if (!help)
		goto out;
	/* rcu_read_lock()ed by nf_hook_slow */
	helper = rcu_dereference(help->helper);
	if (!helper)
		goto out;

	protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum,
					 (*pskb)->len - extoff);
	if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) {
		DEBUGP("proto header not found\n");
		return NF_ACCEPT;
	}

	ret = helper->help(pskb, protoff, ct, ctinfo);
	if (ret != NF_ACCEPT)
		return ret;
out:
	/* We've seen it coming out the other side: confirm it */
	return nf_conntrack_confirm(pskb);
}
Exemple #30
0
static bool
match(const struct sk_buff *skb, struct xt_action_param *par)
{
	const struct xt_helper_info *info = par->matchinfo;
	struct nf_conn *ct;
	struct nf_conn_help *master_help;
	enum ip_conntrack_info ctinfo;
	bool ret = info->invert;

	ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
	if (!ct) {
		DEBUGP("xt_helper: Eek! invalid conntrack?\n");
		return ret;
	}

	if (!ct->master) {
		DEBUGP("xt_helper: conntrack %p has no master\n", ct);
		return ret;
	}

	read_lock_bh(&nf_conntrack_lock);
	master_help = nfct_help(ct->master);
	if (!master_help || !master_help->helper) {
		DEBUGP("xt_helper: master ct %p has no helper\n",
			exp->expectant);
		goto out_unlock;
	}

	DEBUGP("master's name = %s , info->name = %s\n",
		ct->master->helper->name, info->name);

	if (info->name[0] == '\0')
		ret = !ret;
	else
		ret ^= !strncmp(master_help->helper->name, info->name,
				strlen(master_help->helper->name));
out_unlock:
	read_unlock_bh(&nf_conntrack_lock);
	return ret;
}