^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);