diff options
Diffstat (limited to 'net/sched/act_ipt.c')
| -rw-r--r-- | net/sched/act_ipt.c | 145 | 
1 files changed, 70 insertions, 75 deletions
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 8daef963225..8a64a0734ae 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -1,5 +1,5 @@  /* - * net/sched/ipt.c	iptables target interface + * net/sched/ipt.c     iptables target interface   *   *TODO: Add other tables. For now we only support the ipv4 table targets   * @@ -8,7 +8,7 @@   *		as published by the Free Software Foundation; either version   *		2 of the License, or (at your option) any later version.   * - * Copyright:	Jamal Hadi Salim (2002-4) + * Copyright:	Jamal Hadi Salim (2002-13)   */  #include <linux/types.h> @@ -29,15 +29,6 @@  #define IPT_TAB_MASK     15 -static struct tcf_common *tcf_ipt_ht[IPT_TAB_MASK + 1]; -static u32 ipt_idx_gen; -static DEFINE_RWLOCK(ipt_lock); - -static struct tcf_hashinfo ipt_hash_info = { -	.htab	=	tcf_ipt_ht, -	.hmask	=	IPT_TAB_MASK, -	.lock	=	&ipt_lock, -};  static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook)  { @@ -77,22 +68,12 @@ static void ipt_destroy_target(struct xt_entry_target *t)  	module_put(par.target->me);  } -static int tcf_ipt_release(struct tcf_ipt *ipt, int bind) +static void tcf_ipt_release(struct tc_action *a, int bind)  { -	int ret = 0; -	if (ipt) { -		if (bind) -			ipt->tcf_bindcnt--; -		ipt->tcf_refcnt--; -		if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) { -			ipt_destroy_target(ipt->tcfi_t); -			kfree(ipt->tcfi_tname); -			kfree(ipt->tcfi_t); -			tcf_hash_destroy(&ipt->common, &ipt_hash_info); -			ret = ACT_P_DELETED; -		} -	} -	return ret; +	struct tcf_ipt *ipt = to_ipt(a); +	ipt_destroy_target(ipt->tcfi_t); +	kfree(ipt->tcfi_tname); +	kfree(ipt->tcfi_t);  }  static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { @@ -102,12 +83,11 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {  	[TCA_IPT_TARG]	= { .len = sizeof(struct xt_entry_target) },  }; -static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est, +static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,  			struct tc_action *a, int ovr, int bind)  {  	struct nlattr *tb[TCA_IPT_MAX + 1];  	struct tcf_ipt *ipt; -	struct tcf_common *pc;  	struct xt_entry_target *td, *t;  	char *tname;  	int ret = 0, err; @@ -133,20 +113,20 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,  	if (tb[TCA_IPT_INDEX] != NULL)  		index = nla_get_u32(tb[TCA_IPT_INDEX]); -	pc = tcf_hash_check(index, a, bind, &ipt_hash_info); -	if (!pc) { -		pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, -				     &ipt_idx_gen, &ipt_hash_info); -		if (IS_ERR(pc)) -		    return PTR_ERR(pc); +	if (!tcf_hash_check(index, a, bind) ) { +		ret = tcf_hash_create(index, est, a, sizeof(*ipt), bind); +		if (ret) +			return ret;  		ret = ACT_P_CREATED;  	} else { -		if (!ovr) { -			tcf_ipt_release(to_ipt(pc), bind); +		if (bind)/* dont override defaults */ +			return 0; +		tcf_hash_release(a, bind); + +		if (!ovr)  			return -EEXIST; -		}  	} -	ipt = to_ipt(pc); +	ipt = to_ipt(a);  	hook = nla_get_u32(tb[TCA_IPT_HOOK]); @@ -162,7 +142,8 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,  	if (unlikely(!t))  		goto err2; -	if ((err = ipt_init_target(t, tname, hook)) < 0) +	err = ipt_init_target(t, tname, hook); +	if (err < 0)  		goto err3;  	spin_lock_bh(&ipt->tcf_lock); @@ -176,7 +157,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,  	ipt->tcfi_hook  = hook;  	spin_unlock_bh(&ipt->tcf_lock);  	if (ret == ACT_P_CREATED) -		tcf_hash_insert(pc, &ipt_hash_info); +		tcf_hash_insert(a);  	return ret;  err3: @@ -184,37 +165,30 @@ err3:  err2:  	kfree(tname);  err1: -	kfree(pc); +	if (ret == ACT_P_CREATED) +		tcf_hash_cleanup(a, est);  	return err;  } -static int tcf_ipt_cleanup(struct tc_action *a, int bind) -{ -	struct tcf_ipt *ipt = a->priv; -	return tcf_ipt_release(ipt, bind); -} - -static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, +static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,  		   struct tcf_result *res)  {  	int ret = 0, result = 0;  	struct tcf_ipt *ipt = a->priv;  	struct xt_action_param par; -	if (skb_cloned(skb)) { -		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) -			return TC_ACT_UNSPEC; -	} +	if (skb_unclone(skb, GFP_ATOMIC)) +		return TC_ACT_UNSPEC;  	spin_lock(&ipt->tcf_lock);  	ipt->tcf_tm.lastuse = jiffies; -	ipt->tcf_bstats.bytes += qdisc_pkt_len(skb); -	ipt->tcf_bstats.packets++; +	bstats_update(&ipt->tcf_bstats, skb);  	/* yes, we have to worry about both in and out dev -	 worry later - danger - this API seems to have changed -	 from earlier kernels */ +	 * worry later - danger - this API seems to have changed +	 * from earlier kernels +	 */  	par.in       = skb->dev;  	par.out      = NULL;  	par.hooknum  = ipt->tcfi_hook; @@ -234,9 +208,8 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,  		result = TC_ACT_PIPE;  		break;  	default: -		if (net_ratelimit()) -			pr_notice("tc filter: Bogus netfilter code" -				  " %d assume ACCEPT\n", ret); +		net_notice_ratelimited("tc filter: Bogus netfilter code %d assume ACCEPT\n", +				       ret);  		result = TC_POLICE_OK;  		break;  	} @@ -254,9 +227,9 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int  	struct tc_cnt c;  	/* for simple targets kernel size == user size -	** user name = target name -	** for foolproof you need to not assume this -	*/ +	 * user name = target name +	 * for foolproof you need to not assume this +	 */  	t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);  	if (unlikely(!t)) @@ -266,15 +239,17 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int  	c.refcnt = ipt->tcf_refcnt - ref;  	strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); -	NLA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); -	NLA_PUT_U32(skb, TCA_IPT_INDEX, ipt->tcf_index); -	NLA_PUT_U32(skb, TCA_IPT_HOOK, ipt->tcfi_hook); -	NLA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); -	NLA_PUT_STRING(skb, TCA_IPT_TABLE, ipt->tcfi_tname); +	if (nla_put(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t) || +	    nla_put_u32(skb, TCA_IPT_INDEX, ipt->tcf_index) || +	    nla_put_u32(skb, TCA_IPT_HOOK, ipt->tcfi_hook) || +	    nla_put(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c) || +	    nla_put_string(skb, TCA_IPT_TABLE, ipt->tcfi_tname)) +		goto nla_put_failure;  	tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);  	tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse);  	tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires); -	NLA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); +	if (nla_put(skb, TCA_IPT_TM, sizeof (tm), &tm)) +		goto nla_put_failure;  	kfree(t);  	return skb->len; @@ -286,29 +261,49 @@ nla_put_failure:  static struct tc_action_ops act_ipt_ops = {  	.kind		=	"ipt", -	.hinfo		=	&ipt_hash_info,  	.type		=	TCA_ACT_IPT, -	.capab		=	TCA_CAP_NONE,  	.owner		=	THIS_MODULE,  	.act		=	tcf_ipt,  	.dump		=	tcf_ipt_dump, -	.cleanup	=	tcf_ipt_cleanup, -	.lookup		=	tcf_hash_search, +	.cleanup	=	tcf_ipt_release, +	.init		=	tcf_ipt_init, +}; + +static struct tc_action_ops act_xt_ops = { +	.kind		=	"xt", +	.type		=	TCA_ACT_XT, +	.owner		=	THIS_MODULE, +	.act		=	tcf_ipt, +	.dump		=	tcf_ipt_dump, +	.cleanup	=	tcf_ipt_release,  	.init		=	tcf_ipt_init, -	.walk		=	tcf_generic_walker  }; -MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");  MODULE_DESCRIPTION("Iptables target actions");  MODULE_LICENSE("GPL"); +MODULE_ALIAS("act_xt");  static int __init ipt_init_module(void)  { -	return tcf_register_action(&act_ipt_ops); +	int ret1, ret2; + +	ret1 = tcf_register_action(&act_xt_ops, IPT_TAB_MASK); +	if (ret1 < 0) +		printk("Failed to load xt action\n"); +	ret2 = tcf_register_action(&act_ipt_ops, IPT_TAB_MASK); +	if (ret2 < 0) +		printk("Failed to load ipt action\n"); + +	if (ret1 < 0 && ret2 < 0) { +		return ret1; +	} else +		return 0;  }  static void __exit ipt_cleanup_module(void)  { +	tcf_unregister_action(&act_xt_ops);  	tcf_unregister_action(&act_ipt_ops);  }  | 
