Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * net/sched/act_ipt.c		iptables target interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *TODO: Add other tables. For now we only support the ipv4 table targets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Copyright:	Jamal Hadi Salim (2002-13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <net/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <net/pkt_sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/tc_act/tc_ipt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <net/tc_act/tc_ipt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/netfilter_ipv4/ip_tables.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static unsigned int ipt_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static struct tc_action_ops act_ipt_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) static unsigned int xt_net_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static struct tc_action_ops act_xt_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static int ipt_init_target(struct net *net, struct xt_entry_target *t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 			   char *table, unsigned int hook)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct xt_tgchk_param par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct xt_target *target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	struct ipt_entry e = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	target = xt_request_find_target(AF_INET, t->u.user.name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 					t->u.user.revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	if (IS_ERR(target))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		return PTR_ERR(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	t->u.kernel.target = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	memset(&par, 0, sizeof(par));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	par.net       = net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	par.table     = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	par.entryinfo = &e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	par.target    = target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	par.targinfo  = t->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	par.hook_mask = hook;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	par.family    = NFPROTO_IPV4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		module_put(t->u.kernel.target->me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) static void ipt_destroy_target(struct xt_entry_target *t, struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	struct xt_tgdtor_param par = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 		.target   = t->u.kernel.target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		.targinfo = t->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		.family   = NFPROTO_IPV4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		.net      = net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (par.target->destroy != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		par.target->destroy(&par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	module_put(par.target->me);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) static void tcf_ipt_release(struct tc_action *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct tcf_ipt *ipt = to_ipt(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	if (ipt->tcfi_t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		kfree(ipt->tcfi_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	kfree(ipt->tcfi_tname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	[TCA_IPT_TABLE]	= { .type = NLA_STRING, .len = IFNAMSIZ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	[TCA_IPT_HOOK]	= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	[TCA_IPT_INDEX]	= { .type = NLA_U32 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	[TCA_IPT_TARG]	= { .len = sizeof(struct xt_entry_target) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 			  struct nlattr *est, struct tc_action **a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 			  const struct tc_action_ops *ops, int ovr, int bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			  struct tcf_proto *tp, u32 flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	struct tc_action_net *tn = net_generic(net, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	struct nlattr *tb[TCA_IPT_MAX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	struct tcf_ipt *ipt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	struct xt_entry_target *td, *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	char *tname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	bool exists = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	int ret = 0, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	u32 hook = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	u32 index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	if (nla == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	err = nla_parse_nested_deprecated(tb, TCA_IPT_MAX, nla, ipt_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 					  NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	if (tb[TCA_IPT_INDEX] != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		index = nla_get_u32(tb[TCA_IPT_INDEX]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	err = tcf_idr_check_alloc(tn, &index, a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	exists = err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	if (exists && bind)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	if (nla_len(tb[TCA_IPT_TARG]) != td->u.target_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		if (exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	if (!exists) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		ret = tcf_idr_create(tn, index, est, a, ops, bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 				     false, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 			tcf_idr_cleanup(tn, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		ret = ACT_P_CREATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		if (bind)/* dont override defaults */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (!ovr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	hook = nla_get_u32(tb[TCA_IPT_HOOK]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	if (unlikely(!tname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	if (tb[TCA_IPT_TABLE] == NULL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	    nla_strlcpy(tname, tb[TCA_IPT_TABLE], IFNAMSIZ) >= IFNAMSIZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		strcpy(tname, "mangle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	t = kmemdup(td, td->u.target_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (unlikely(!t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		goto err2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	err = ipt_init_target(net, t, tname, hook);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	ipt = to_ipt(*a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	spin_lock_bh(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (ret != ACT_P_CREATED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		ipt_destroy_target(ipt->tcfi_t, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		kfree(ipt->tcfi_tname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		kfree(ipt->tcfi_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	ipt->tcfi_tname = tname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	ipt->tcfi_t     = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	ipt->tcfi_hook  = hook;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	spin_unlock_bh(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	kfree(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) err2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	kfree(tname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	tcf_idr_release(*a, bind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static int tcf_ipt_init(struct net *net, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			struct nlattr *est, struct tc_action **a, int ovr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 			int bind, bool rtnl_held, struct tcf_proto *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 			u32 flags, struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return __tcf_ipt_init(net, ipt_net_id, nla, est, a, &act_ipt_ops, ovr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			      bind, tp, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int tcf_xt_init(struct net *net, struct nlattr *nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		       struct nlattr *est, struct tc_action **a, int ovr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		       int bind, bool unlocked, struct tcf_proto *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		       u32 flags, struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	return __tcf_ipt_init(net, xt_net_id, nla, est, a, &act_xt_ops, ovr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			      bind, tp, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static int tcf_ipt_act(struct sk_buff *skb, const struct tc_action *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		       struct tcf_result *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	int ret = 0, result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	struct tcf_ipt *ipt = to_ipt(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	struct xt_action_param par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	struct nf_hook_state state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		.net	= dev_net(skb->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		.in	= skb->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		.hook	= ipt->tcfi_hook,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		.pf	= NFPROTO_IPV4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	if (skb_unclone(skb, GFP_ATOMIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		return TC_ACT_UNSPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	spin_lock(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	tcf_lastuse_update(&ipt->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	bstats_update(&ipt->tcf_bstats, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	/* yes, we have to worry about both in and out dev
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	 * worry later - danger - this API seems to have changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	 * from earlier kernels
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	par.state    = &state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	par.target   = ipt->tcfi_t->u.kernel.target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	par.targinfo = ipt->tcfi_t->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	ret = par.target->target(skb, &par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	case NF_ACCEPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		result = TC_ACT_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	case NF_DROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		result = TC_ACT_SHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		ipt->tcf_qstats.drops++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	case XT_CONTINUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		result = TC_ACT_PIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		net_notice_ratelimited("tc filter: Bogus netfilter code %d assume ACCEPT\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 				       ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		result = TC_ACT_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	spin_unlock(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			int ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	unsigned char *b = skb_tail_pointer(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	struct tcf_ipt *ipt = to_ipt(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	struct xt_entry_target *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	struct tcf_t tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	struct tc_cnt c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	/* for simple targets kernel size == user size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	 * user name = target name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	 * for foolproof you need to not assume this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	spin_lock_bh(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (unlikely(!t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	c.bindcnt = atomic_read(&ipt->tcf_bindcnt) - bind;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	c.refcnt = refcount_read(&ipt->tcf_refcnt) - ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	if (nla_put(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	    nla_put_u32(skb, TCA_IPT_INDEX, ipt->tcf_index) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	    nla_put_u32(skb, TCA_IPT_HOOK, ipt->tcfi_hook) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	    nla_put(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	    nla_put_string(skb, TCA_IPT_TABLE, ipt->tcfi_tname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	tcf_tm_dump(&tm, &ipt->tcf_tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	if (nla_put_64bit(skb, TCA_IPT_TM, sizeof(tm), &tm, TCA_IPT_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		goto nla_put_failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	spin_unlock_bh(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	kfree(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	return skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) nla_put_failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	spin_unlock_bh(&ipt->tcf_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	nlmsg_trim(skb, b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	kfree(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			  struct netlink_callback *cb, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 			  const struct tc_action_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			  struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	struct tc_action_net *tn = net_generic(net, ipt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	struct tc_action_net *tn = net_generic(net, ipt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	return tcf_idr_search(tn, a, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static struct tc_action_ops act_ipt_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	.kind		=	"ipt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	.id		=	TCA_ID_IPT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	.owner		=	THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	.act		=	tcf_ipt_act,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	.dump		=	tcf_ipt_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	.cleanup	=	tcf_ipt_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	.init		=	tcf_ipt_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	.walk		=	tcf_ipt_walker,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	.lookup		=	tcf_ipt_search,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	.size		=	sizeof(struct tcf_ipt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static __net_init int ipt_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	struct tc_action_net *tn = net_generic(net, ipt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	return tc_action_net_init(net, tn, &act_ipt_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void __net_exit ipt_exit_net(struct list_head *net_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	tc_action_net_exit(net_list, ipt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static struct pernet_operations ipt_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	.init = ipt_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	.exit_batch = ipt_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	.id   = &ipt_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	.size = sizeof(struct tc_action_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			 struct netlink_callback *cb, int type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			 const struct tc_action_ops *ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			 struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	struct tc_action_net *tn = net_generic(net, xt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	struct tc_action_net *tn = net_generic(net, xt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	return tcf_idr_search(tn, a, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static struct tc_action_ops act_xt_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	.kind		=	"xt",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	.id		=	TCA_ID_XT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	.owner		=	THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	.act		=	tcf_ipt_act,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	.dump		=	tcf_ipt_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	.cleanup	=	tcf_ipt_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	.init		=	tcf_xt_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	.walk		=	tcf_xt_walker,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	.lookup		=	tcf_xt_search,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	.size		=	sizeof(struct tcf_ipt),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static __net_init int xt_init_net(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct tc_action_net *tn = net_generic(net, xt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	return tc_action_net_init(net, tn, &act_xt_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static void __net_exit xt_exit_net(struct list_head *net_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	tc_action_net_exit(net_list, xt_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static struct pernet_operations xt_net_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	.init = xt_init_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	.exit_batch = xt_exit_net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 	.id   = &xt_net_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	.size = sizeof(struct tc_action_net),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) MODULE_AUTHOR("Jamal Hadi Salim(2002-13)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) MODULE_DESCRIPTION("Iptables target actions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) MODULE_ALIAS("act_xt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static int __init ipt_init_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	int ret1, ret2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	ret1 = tcf_register_action(&act_xt_ops, &xt_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	if (ret1 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		pr_err("Failed to load xt action\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	ret2 = tcf_register_action(&act_ipt_ops, &ipt_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	if (ret2 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		pr_err("Failed to load ipt action\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	if (ret1 < 0 && ret2 < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		return ret1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) static void __exit ipt_cleanup_module(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	tcf_unregister_action(&act_ipt_ops, &ipt_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	tcf_unregister_action(&act_xt_ops, &xt_net_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) module_init(ipt_init_module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) module_exit(ipt_cleanup_module);