0001
0002
0003
0004
0005
0006
0007 #include <linux/module.h>
0008 #include <linux/init.h>
0009 #include <linux/kernel.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/rtnetlink.h>
0012 #include <linux/pkt_cls.h>
0013 #include <linux/ip.h>
0014 #include <linux/ipv6.h>
0015 #include <net/netlink.h>
0016 #include <net/pkt_sched.h>
0017 #include <net/act_api.h>
0018 #include <net/pkt_cls.h>
0019 #include <uapi/linux/tc_act/tc_ctinfo.h>
0020 #include <net/tc_act/tc_ctinfo.h>
0021
0022 #include <net/netfilter/nf_conntrack.h>
0023 #include <net/netfilter/nf_conntrack_core.h>
0024 #include <net/netfilter/nf_conntrack_ecache.h>
0025 #include <net/netfilter/nf_conntrack_zones.h>
0026
0027 static struct tc_action_ops act_ctinfo_ops;
0028 static unsigned int ctinfo_net_id;
0029
0030 static void tcf_ctinfo_dscp_set(struct nf_conn *ct, struct tcf_ctinfo *ca,
0031 struct tcf_ctinfo_params *cp,
0032 struct sk_buff *skb, int wlen, int proto)
0033 {
0034 u8 dscp, newdscp;
0035
0036 newdscp = (((ct->mark & cp->dscpmask) >> cp->dscpmaskshift) << 2) &
0037 ~INET_ECN_MASK;
0038
0039 switch (proto) {
0040 case NFPROTO_IPV4:
0041 dscp = ipv4_get_dsfield(ip_hdr(skb)) & ~INET_ECN_MASK;
0042 if (dscp != newdscp) {
0043 if (likely(!skb_try_make_writable(skb, wlen))) {
0044 ipv4_change_dsfield(ip_hdr(skb),
0045 INET_ECN_MASK,
0046 newdscp);
0047 ca->stats_dscp_set++;
0048 } else {
0049 ca->stats_dscp_error++;
0050 }
0051 }
0052 break;
0053 case NFPROTO_IPV6:
0054 dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & ~INET_ECN_MASK;
0055 if (dscp != newdscp) {
0056 if (likely(!skb_try_make_writable(skb, wlen))) {
0057 ipv6_change_dsfield(ipv6_hdr(skb),
0058 INET_ECN_MASK,
0059 newdscp);
0060 ca->stats_dscp_set++;
0061 } else {
0062 ca->stats_dscp_error++;
0063 }
0064 }
0065 break;
0066 default:
0067 break;
0068 }
0069 }
0070
0071 static void tcf_ctinfo_cpmark_set(struct nf_conn *ct, struct tcf_ctinfo *ca,
0072 struct tcf_ctinfo_params *cp,
0073 struct sk_buff *skb)
0074 {
0075 ca->stats_cpmark_set++;
0076 skb->mark = ct->mark & cp->cpmarkmask;
0077 }
0078
0079 static int tcf_ctinfo_act(struct sk_buff *skb, const struct tc_action *a,
0080 struct tcf_result *res)
0081 {
0082 const struct nf_conntrack_tuple_hash *thash = NULL;
0083 struct tcf_ctinfo *ca = to_ctinfo(a);
0084 struct nf_conntrack_tuple tuple;
0085 struct nf_conntrack_zone zone;
0086 enum ip_conntrack_info ctinfo;
0087 struct tcf_ctinfo_params *cp;
0088 struct nf_conn *ct;
0089 int proto, wlen;
0090 int action;
0091
0092 cp = rcu_dereference_bh(ca->params);
0093
0094 tcf_lastuse_update(&ca->tcf_tm);
0095 bstats_update(&ca->tcf_bstats, skb);
0096 action = READ_ONCE(ca->tcf_action);
0097
0098 wlen = skb_network_offset(skb);
0099 switch (skb_protocol(skb, true)) {
0100 case htons(ETH_P_IP):
0101 wlen += sizeof(struct iphdr);
0102 if (!pskb_may_pull(skb, wlen))
0103 goto out;
0104
0105 proto = NFPROTO_IPV4;
0106 break;
0107 case htons(ETH_P_IPV6):
0108 wlen += sizeof(struct ipv6hdr);
0109 if (!pskb_may_pull(skb, wlen))
0110 goto out;
0111
0112 proto = NFPROTO_IPV6;
0113 break;
0114 default:
0115 goto out;
0116 }
0117
0118 ct = nf_ct_get(skb, &ctinfo);
0119 if (!ct) {
0120 if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
0121 proto, cp->net, &tuple))
0122 goto out;
0123 zone.id = cp->zone;
0124 zone.dir = NF_CT_DEFAULT_ZONE_DIR;
0125
0126 thash = nf_conntrack_find_get(cp->net, &zone, &tuple);
0127 if (!thash)
0128 goto out;
0129
0130 ct = nf_ct_tuplehash_to_ctrack(thash);
0131 }
0132
0133 if (cp->mode & CTINFO_MODE_DSCP)
0134 if (!cp->dscpstatemask || (ct->mark & cp->dscpstatemask))
0135 tcf_ctinfo_dscp_set(ct, ca, cp, skb, wlen, proto);
0136
0137 if (cp->mode & CTINFO_MODE_CPMARK)
0138 tcf_ctinfo_cpmark_set(ct, ca, cp, skb);
0139
0140 if (thash)
0141 nf_ct_put(ct);
0142 out:
0143 return action;
0144 }
0145
0146 static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX + 1] = {
0147 [TCA_CTINFO_ACT] =
0148 NLA_POLICY_EXACT_LEN(sizeof(struct tc_ctinfo)),
0149 [TCA_CTINFO_ZONE] = { .type = NLA_U16 },
0150 [TCA_CTINFO_PARMS_DSCP_MASK] = { .type = NLA_U32 },
0151 [TCA_CTINFO_PARMS_DSCP_STATEMASK] = { .type = NLA_U32 },
0152 [TCA_CTINFO_PARMS_CPMARK_MASK] = { .type = NLA_U32 },
0153 };
0154
0155 static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
0156 struct nlattr *est, struct tc_action **a,
0157 struct tcf_proto *tp, u32 flags,
0158 struct netlink_ext_ack *extack)
0159 {
0160 struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
0161 bool bind = flags & TCA_ACT_FLAGS_BIND;
0162 u32 dscpmask = 0, dscpstatemask, index;
0163 struct nlattr *tb[TCA_CTINFO_MAX + 1];
0164 struct tcf_ctinfo_params *cp_new;
0165 struct tcf_chain *goto_ch = NULL;
0166 struct tc_ctinfo *actparm;
0167 struct tcf_ctinfo *ci;
0168 u8 dscpmaskshift;
0169 int ret = 0, err;
0170
0171 if (!nla) {
0172 NL_SET_ERR_MSG_MOD(extack, "ctinfo requires attributes to be passed");
0173 return -EINVAL;
0174 }
0175
0176 err = nla_parse_nested(tb, TCA_CTINFO_MAX, nla, ctinfo_policy, extack);
0177 if (err < 0)
0178 return err;
0179
0180 if (!tb[TCA_CTINFO_ACT]) {
0181 NL_SET_ERR_MSG_MOD(extack,
0182 "Missing required TCA_CTINFO_ACT attribute");
0183 return -EINVAL;
0184 }
0185 actparm = nla_data(tb[TCA_CTINFO_ACT]);
0186
0187
0188
0189 if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) {
0190 dscpmask = nla_get_u32(tb[TCA_CTINFO_PARMS_DSCP_MASK]);
0191
0192 dscpmaskshift = dscpmask ? __ffs(dscpmask) : 0;
0193 if ((~0 & (dscpmask >> dscpmaskshift)) != 0x3f) {
0194 NL_SET_ERR_MSG_ATTR(extack,
0195 tb[TCA_CTINFO_PARMS_DSCP_MASK],
0196 "dscp mask must be 6 contiguous bits");
0197 return -EINVAL;
0198 }
0199 dscpstatemask = tb[TCA_CTINFO_PARMS_DSCP_STATEMASK] ?
0200 nla_get_u32(tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) : 0;
0201
0202 if (dscpmask & dscpstatemask) {
0203 NL_SET_ERR_MSG_ATTR(extack,
0204 tb[TCA_CTINFO_PARMS_DSCP_STATEMASK],
0205 "dscp statemask must not overlap dscp mask");
0206 return -EINVAL;
0207 }
0208 }
0209
0210
0211 index = actparm->index;
0212 err = tcf_idr_check_alloc(tn, &index, a, bind);
0213 if (!err) {
0214 ret = tcf_idr_create(tn, index, est, a,
0215 &act_ctinfo_ops, bind, false, flags);
0216 if (ret) {
0217 tcf_idr_cleanup(tn, index);
0218 return ret;
0219 }
0220 ret = ACT_P_CREATED;
0221 } else if (err > 0) {
0222 if (bind)
0223 return 0;
0224 if (!(flags & TCA_ACT_FLAGS_REPLACE)) {
0225 tcf_idr_release(*a, bind);
0226 return -EEXIST;
0227 }
0228 } else {
0229 return err;
0230 }
0231
0232 err = tcf_action_check_ctrlact(actparm->action, tp, &goto_ch, extack);
0233 if (err < 0)
0234 goto release_idr;
0235
0236 ci = to_ctinfo(*a);
0237
0238 cp_new = kzalloc(sizeof(*cp_new), GFP_KERNEL);
0239 if (unlikely(!cp_new)) {
0240 err = -ENOMEM;
0241 goto put_chain;
0242 }
0243
0244 cp_new->net = net;
0245 cp_new->zone = tb[TCA_CTINFO_ZONE] ?
0246 nla_get_u16(tb[TCA_CTINFO_ZONE]) : 0;
0247 if (dscpmask) {
0248 cp_new->dscpmask = dscpmask;
0249 cp_new->dscpmaskshift = dscpmaskshift;
0250 cp_new->dscpstatemask = dscpstatemask;
0251 cp_new->mode |= CTINFO_MODE_DSCP;
0252 }
0253
0254 if (tb[TCA_CTINFO_PARMS_CPMARK_MASK]) {
0255 cp_new->cpmarkmask =
0256 nla_get_u32(tb[TCA_CTINFO_PARMS_CPMARK_MASK]);
0257 cp_new->mode |= CTINFO_MODE_CPMARK;
0258 }
0259
0260 spin_lock_bh(&ci->tcf_lock);
0261 goto_ch = tcf_action_set_ctrlact(*a, actparm->action, goto_ch);
0262 cp_new = rcu_replace_pointer(ci->params, cp_new,
0263 lockdep_is_held(&ci->tcf_lock));
0264 spin_unlock_bh(&ci->tcf_lock);
0265
0266 if (goto_ch)
0267 tcf_chain_put_by_act(goto_ch);
0268 if (cp_new)
0269 kfree_rcu(cp_new, rcu);
0270
0271 return ret;
0272
0273 put_chain:
0274 if (goto_ch)
0275 tcf_chain_put_by_act(goto_ch);
0276 release_idr:
0277 tcf_idr_release(*a, bind);
0278 return err;
0279 }
0280
0281 static int tcf_ctinfo_dump(struct sk_buff *skb, struct tc_action *a,
0282 int bind, int ref)
0283 {
0284 struct tcf_ctinfo *ci = to_ctinfo(a);
0285 struct tc_ctinfo opt = {
0286 .index = ci->tcf_index,
0287 .refcnt = refcount_read(&ci->tcf_refcnt) - ref,
0288 .bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
0289 };
0290 unsigned char *b = skb_tail_pointer(skb);
0291 struct tcf_ctinfo_params *cp;
0292 struct tcf_t t;
0293
0294 spin_lock_bh(&ci->tcf_lock);
0295 cp = rcu_dereference_protected(ci->params,
0296 lockdep_is_held(&ci->tcf_lock));
0297
0298 tcf_tm_dump(&t, &ci->tcf_tm);
0299 if (nla_put_64bit(skb, TCA_CTINFO_TM, sizeof(t), &t, TCA_CTINFO_PAD))
0300 goto nla_put_failure;
0301
0302 opt.action = ci->tcf_action;
0303 if (nla_put(skb, TCA_CTINFO_ACT, sizeof(opt), &opt))
0304 goto nla_put_failure;
0305
0306 if (nla_put_u16(skb, TCA_CTINFO_ZONE, cp->zone))
0307 goto nla_put_failure;
0308
0309 if (cp->mode & CTINFO_MODE_DSCP) {
0310 if (nla_put_u32(skb, TCA_CTINFO_PARMS_DSCP_MASK,
0311 cp->dscpmask))
0312 goto nla_put_failure;
0313 if (nla_put_u32(skb, TCA_CTINFO_PARMS_DSCP_STATEMASK,
0314 cp->dscpstatemask))
0315 goto nla_put_failure;
0316 }
0317
0318 if (cp->mode & CTINFO_MODE_CPMARK) {
0319 if (nla_put_u32(skb, TCA_CTINFO_PARMS_CPMARK_MASK,
0320 cp->cpmarkmask))
0321 goto nla_put_failure;
0322 }
0323
0324 if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_SET,
0325 ci->stats_dscp_set, TCA_CTINFO_PAD))
0326 goto nla_put_failure;
0327
0328 if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_DSCP_ERROR,
0329 ci->stats_dscp_error, TCA_CTINFO_PAD))
0330 goto nla_put_failure;
0331
0332 if (nla_put_u64_64bit(skb, TCA_CTINFO_STATS_CPMARK_SET,
0333 ci->stats_cpmark_set, TCA_CTINFO_PAD))
0334 goto nla_put_failure;
0335
0336 spin_unlock_bh(&ci->tcf_lock);
0337 return skb->len;
0338
0339 nla_put_failure:
0340 spin_unlock_bh(&ci->tcf_lock);
0341 nlmsg_trim(skb, b);
0342 return -1;
0343 }
0344
0345 static int tcf_ctinfo_walker(struct net *net, struct sk_buff *skb,
0346 struct netlink_callback *cb, int type,
0347 const struct tc_action_ops *ops,
0348 struct netlink_ext_ack *extack)
0349 {
0350 struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
0351
0352 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
0353 }
0354
0355 static int tcf_ctinfo_search(struct net *net, struct tc_action **a, u32 index)
0356 {
0357 struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
0358
0359 return tcf_idr_search(tn, a, index);
0360 }
0361
0362 static void tcf_ctinfo_cleanup(struct tc_action *a)
0363 {
0364 struct tcf_ctinfo *ci = to_ctinfo(a);
0365 struct tcf_ctinfo_params *cp;
0366
0367 cp = rcu_dereference_protected(ci->params, 1);
0368 if (cp)
0369 kfree_rcu(cp, rcu);
0370 }
0371
0372 static struct tc_action_ops act_ctinfo_ops = {
0373 .kind = "ctinfo",
0374 .id = TCA_ID_CTINFO,
0375 .owner = THIS_MODULE,
0376 .act = tcf_ctinfo_act,
0377 .dump = tcf_ctinfo_dump,
0378 .init = tcf_ctinfo_init,
0379 .cleanup= tcf_ctinfo_cleanup,
0380 .walk = tcf_ctinfo_walker,
0381 .lookup = tcf_ctinfo_search,
0382 .size = sizeof(struct tcf_ctinfo),
0383 };
0384
0385 static __net_init int ctinfo_init_net(struct net *net)
0386 {
0387 struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
0388
0389 return tc_action_net_init(net, tn, &act_ctinfo_ops);
0390 }
0391
0392 static void __net_exit ctinfo_exit_net(struct list_head *net_list)
0393 {
0394 tc_action_net_exit(net_list, ctinfo_net_id);
0395 }
0396
0397 static struct pernet_operations ctinfo_net_ops = {
0398 .init = ctinfo_init_net,
0399 .exit_batch = ctinfo_exit_net,
0400 .id = &ctinfo_net_id,
0401 .size = sizeof(struct tc_action_net),
0402 };
0403
0404 static int __init ctinfo_init_module(void)
0405 {
0406 return tcf_register_action(&act_ctinfo_ops, &ctinfo_net_ops);
0407 }
0408
0409 static void __exit ctinfo_cleanup_module(void)
0410 {
0411 tcf_unregister_action(&act_ctinfo_ops, &ctinfo_net_ops);
0412 }
0413
0414 module_init(ctinfo_init_module);
0415 module_exit(ctinfo_cleanup_module);
0416 MODULE_AUTHOR("Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>");
0417 MODULE_DESCRIPTION("Connection tracking mark actions");
0418 MODULE_LICENSE("GPL");