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

Commit 8c6b0865 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'master' of git://1984.lsi.us.es/net

parents 8a783354 60b5f8f7
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -118,6 +118,10 @@ extern struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
extern struct nf_conntrack_l4proto *
extern struct nf_conntrack_l4proto *
__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);
__nf_ct_l4proto_find(u_int16_t l3proto, u_int8_t l4proto);


extern struct nf_conntrack_l4proto *
nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto);
extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p);

/* Protocol registration. */
/* Protocol registration. */
extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto);
extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto);
+1 −1
Original line number Original line Diff line number Diff line
@@ -15,7 +15,7 @@ struct ctnl_timeout {
	atomic_t		refcnt;
	atomic_t		refcnt;
	char			name[CTNL_TIMEOUT_NAME_MAX];
	char			name[CTNL_TIMEOUT_NAME_MAX];
	__u16			l3num;
	__u16			l3num;
	__u8			l4num;
	struct nf_conntrack_l4proto *l4proto;
	char			data[0];
	char			data[0];
};
};


+22 −17
Original line number Original line Diff line number Diff line
@@ -768,8 +768,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
	       struct nf_conntrack_l3proto *l3proto,
	       struct nf_conntrack_l3proto *l3proto,
	       struct nf_conntrack_l4proto *l4proto,
	       struct nf_conntrack_l4proto *l4proto,
	       struct sk_buff *skb,
	       struct sk_buff *skb,
	       unsigned int dataoff, u32 hash,
	       unsigned int dataoff, u32 hash)
	       unsigned int *timeouts)
{
{
	struct nf_conn *ct;
	struct nf_conn *ct;
	struct nf_conn_help *help;
	struct nf_conn_help *help;
@@ -777,6 +776,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
	struct nf_conntrack_ecache *ecache;
	struct nf_conntrack_ecache *ecache;
	struct nf_conntrack_expect *exp;
	struct nf_conntrack_expect *exp;
	u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
	u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
	struct nf_conn_timeout *timeout_ext;
	unsigned int *timeouts;


	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
	if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
		pr_debug("Can't invert tuple.\n");
		pr_debug("Can't invert tuple.\n");
@@ -788,12 +789,21 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
	if (IS_ERR(ct))
	if (IS_ERR(ct))
		return (struct nf_conntrack_tuple_hash *)ct;
		return (struct nf_conntrack_tuple_hash *)ct;


	timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL;
	if (timeout_ext)
		timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
	else
		timeouts = l4proto->get_timeouts(net);

	if (!l4proto->new(ct, skb, dataoff, timeouts)) {
	if (!l4proto->new(ct, skb, dataoff, timeouts)) {
		nf_conntrack_free(ct);
		nf_conntrack_free(ct);
		pr_debug("init conntrack: can't track with proto module\n");
		pr_debug("init conntrack: can't track with proto module\n");
		return NULL;
		return NULL;
	}
	}


	if (timeout_ext)
		nf_ct_timeout_ext_add(ct, timeout_ext->timeout, GFP_ATOMIC);

	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);


@@ -854,8 +864,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
		  struct nf_conntrack_l3proto *l3proto,
		  struct nf_conntrack_l3proto *l3proto,
		  struct nf_conntrack_l4proto *l4proto,
		  struct nf_conntrack_l4proto *l4proto,
		  int *set_reply,
		  int *set_reply,
		  enum ip_conntrack_info *ctinfo,
		  enum ip_conntrack_info *ctinfo)
		  unsigned int *timeouts)
{
{
	struct nf_conntrack_tuple tuple;
	struct nf_conntrack_tuple tuple;
	struct nf_conntrack_tuple_hash *h;
	struct nf_conntrack_tuple_hash *h;
@@ -875,7 +884,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
	h = __nf_conntrack_find_get(net, zone, &tuple, hash);
	h = __nf_conntrack_find_get(net, zone, &tuple, hash);
	if (!h) {
	if (!h) {
		h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
		h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
				   skb, dataoff, hash, timeouts);
				   skb, dataoff, hash);
		if (!h)
		if (!h)
			return NULL;
			return NULL;
		if (IS_ERR(h))
		if (IS_ERR(h))
@@ -964,19 +973,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
			goto out;
			goto out;
	}
	}


	/* Decide what timeout policy we want to apply to this flow. */
	if (tmpl) {
	        timeout_ext = nf_ct_timeout_find(tmpl);
		if (timeout_ext)
			timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
		else
			timeouts = l4proto->get_timeouts(net);
	} else
		timeouts = l4proto->get_timeouts(net);

	ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
	ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
			       l3proto, l4proto, &set_reply, &ctinfo,
			       l3proto, l4proto, &set_reply, &ctinfo);
			       timeouts);
	if (!ct) {
	if (!ct) {
		/* Not valid part of a connection */
		/* Not valid part of a connection */
		NF_CT_STAT_INC_ATOMIC(net, invalid);
		NF_CT_STAT_INC_ATOMIC(net, invalid);
@@ -993,6 +991,13 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,


	NF_CT_ASSERT(skb->nfct);
	NF_CT_ASSERT(skb->nfct);


	/* Decide what timeout policy we want to apply to this flow. */
	timeout_ext = nf_ct_timeout_find(ct);
	if (timeout_ext)
		timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
	else
		timeouts = l4proto->get_timeouts(net);

	ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts);
	ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts);
	if (ret <= 0) {
	if (ret <= 0) {
		/* Invalid: inverse of the return code tells
		/* Invalid: inverse of the return code tells
+21 −0
Original line number Original line Diff line number Diff line
@@ -127,6 +127,27 @@ void nf_ct_l3proto_module_put(unsigned short l3proto)
}
}
EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);


struct nf_conntrack_l4proto *
nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num)
{
	struct nf_conntrack_l4proto *p;

	rcu_read_lock();
	p = __nf_ct_l4proto_find(l3num, l4num);
	if (!try_module_get(p->me))
		p = &nf_conntrack_l4proto_generic;
	rcu_read_unlock();

	return p;
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get);

void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p)
{
	module_put(p->me);
}
EXPORT_SYMBOL_GPL(nf_ct_l4proto_put);

static int kill_l3proto(struct nf_conn *i, void *data)
static int kill_l3proto(struct nf_conn *i, void *data)
{
{
	return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
	return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
+23 −22
Original line number Original line Diff line number Diff line
@@ -98,11 +98,13 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
		break;
		break;
	}
	}


	l4proto = __nf_ct_l4proto_find(l3num, l4num);
	l4proto = nf_ct_l4proto_find_get(l3num, l4num);


	/* This protocol is not supportted, skip. */
	/* This protocol is not supportted, skip. */
	if (l4proto->l4proto != l4num)
	if (l4proto->l4proto != l4num) {
		return -EOPNOTSUPP;
		ret = -EOPNOTSUPP;
		goto err_proto_put;
	}


	if (matching) {
	if (matching) {
		if (nlh->nlmsg_flags & NLM_F_REPLACE) {
		if (nlh->nlmsg_flags & NLM_F_REPLACE) {
@@ -110,20 +112,25 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
			 * different kind, sorry.
			 * different kind, sorry.
			 */
			 */
			if (matching->l3num != l3num ||
			if (matching->l3num != l3num ||
			    matching->l4num != l4num)
			    matching->l4proto->l4proto != l4num) {
				return -EINVAL;
				ret = -EINVAL;
				goto err_proto_put;
			}


			ret = ctnl_timeout_parse_policy(matching, l4proto,
			ret = ctnl_timeout_parse_policy(matching, l4proto,
							cda[CTA_TIMEOUT_DATA]);
							cda[CTA_TIMEOUT_DATA]);
			return ret;
			return ret;
		}
		}
		return -EBUSY;
		ret = -EBUSY;
		goto err_proto_put;
	}
	}


	timeout = kzalloc(sizeof(struct ctnl_timeout) +
	timeout = kzalloc(sizeof(struct ctnl_timeout) +
			  l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
			  l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
	if (timeout == NULL)
	if (timeout == NULL) {
		return -ENOMEM;
		ret = -ENOMEM;
		goto err_proto_put;
	}


	ret = ctnl_timeout_parse_policy(timeout, l4proto,
	ret = ctnl_timeout_parse_policy(timeout, l4proto,
					cda[CTA_TIMEOUT_DATA]);
					cda[CTA_TIMEOUT_DATA]);
@@ -132,13 +139,15 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,


	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
	strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
	timeout->l3num = l3num;
	timeout->l3num = l3num;
	timeout->l4num = l4num;
	timeout->l4proto = l4proto;
	atomic_set(&timeout->refcnt, 1);
	atomic_set(&timeout->refcnt, 1);
	list_add_tail_rcu(&timeout->head, &cttimeout_list);
	list_add_tail_rcu(&timeout->head, &cttimeout_list);


	return 0;
	return 0;
err:
err:
	kfree(timeout);
	kfree(timeout);
err_proto_put:
	nf_ct_l4proto_put(l4proto);
	return ret;
	return ret;
}
}


@@ -149,7 +158,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
	struct nlmsghdr *nlh;
	struct nlmsghdr *nlh;
	struct nfgenmsg *nfmsg;
	struct nfgenmsg *nfmsg;
	unsigned int flags = pid ? NLM_F_MULTI : 0;
	unsigned int flags = pid ? NLM_F_MULTI : 0;
	struct nf_conntrack_l4proto *l4proto;
	struct nf_conntrack_l4proto *l4proto = timeout->l4proto;


	event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
	event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
	nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
@@ -163,20 +172,10 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,


	NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name);
	NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name);
	NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num));
	NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num));
	NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num);
	NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto);
	NLA_PUT_BE32(skb, CTA_TIMEOUT_USE,
	NLA_PUT_BE32(skb, CTA_TIMEOUT_USE,
			htonl(atomic_read(&timeout->refcnt)));
			htonl(atomic_read(&timeout->refcnt)));


	l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num);

	/* If the timeout object does not match the layer 4 protocol tracker,
	 * then skip dumping the data part since we don't know how to
	 * interpret it. This may happen for UPDlite, SCTP and DCCP since
	 * you can unload the module.
	 */
	if (timeout->l4num != l4proto->l4proto)
		goto out;

	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
	if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
		struct nlattr *nest_parms;
		struct nlattr *nest_parms;
		int ret;
		int ret;
@@ -192,7 +191,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,


		nla_nest_end(skb, nest_parms);
		nla_nest_end(skb, nest_parms);
	}
	}
out:

	nlmsg_end(skb, nlh);
	nlmsg_end(skb, nlh);
	return skb->len;
	return skb->len;


@@ -293,6 +292,7 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout)
	if (atomic_dec_and_test(&timeout->refcnt)) {
	if (atomic_dec_and_test(&timeout->refcnt)) {
		/* We are protected by nfnl mutex. */
		/* We are protected by nfnl mutex. */
		list_del_rcu(&timeout->head);
		list_del_rcu(&timeout->head);
		nf_ct_l4proto_put(timeout->l4proto);
		kfree_rcu(timeout, rcu_head);
		kfree_rcu(timeout, rcu_head);
	} else {
	} else {
		/* still in use, restore reference counter. */
		/* still in use, restore reference counter. */
@@ -417,6 +417,7 @@ static void __exit cttimeout_exit(void)
		/* We are sure that our objects have no clients at this point,
		/* We are sure that our objects have no clients at this point,
		 * it's safe to release them all without checking refcnt.
		 * it's safe to release them all without checking refcnt.
		 */
		 */
		nf_ct_l4proto_put(cur->l4proto);
		kfree_rcu(cur, rcu_head);
		kfree_rcu(cur, rcu_head);
	}
	}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
Loading