143105Sdfr// SPDX-License-Identifier: GPL-2.0-only
243105Sdfr/*
343105Sdfr *  ebt_mark
443105Sdfr *
543105Sdfr *	Authors:
643105Sdfr *	Bart De Schuymer <bdschuym@pandora.be>
743105Sdfr *
843105Sdfr *  July, 2002
943105Sdfr *
1043105Sdfr */
1143105Sdfr
1243105Sdfr/* The mark target can be used in any chain,
1343105Sdfr * I believe adding a mangle table just for marking is total overkill.
1443105Sdfr * Marking a frame doesn't really change anything in the frame anyway.
1543105Sdfr */
1643105Sdfr
1743105Sdfr#include <linux/module.h>
1843105Sdfr#include <linux/netfilter/x_tables.h>
1943105Sdfr#include <linux/netfilter_bridge/ebtables.h>
2043105Sdfr#include <linux/netfilter_bridge/ebt_mark_t.h>
2143105Sdfr
2243105Sdfrstatic unsigned int
2343105Sdfrebt_mark_tg(struct sk_buff *skb, const struct xt_action_param *par)
2443105Sdfr{
2543105Sdfr	const struct ebt_mark_t_info *info = par->targinfo;
2643105Sdfr	int action = info->target & -16;
27116181Sobrien
28116181Sobrien	if (action == MARK_SET_VALUE)
29116181Sobrien		skb->mark = info->mark;
3043105Sdfr	else if (action == MARK_OR_VALUE)
3143105Sdfr		skb->mark |= info->mark;
3243105Sdfr	else if (action == MARK_AND_VALUE)
3343105Sdfr		skb->mark &= info->mark;
3443105Sdfr	else
35129880Sphk		skb->mark ^= info->mark;
3643105Sdfr
3743105Sdfr	return info->target | ~EBT_VERDICT_BITS;
3847400Sdfr}
3947400Sdfr
40159541Simpstatic int ebt_mark_tg_check(const struct xt_tgchk_param *par)
4143105Sdfr{
42147271Smarius	const struct ebt_mark_t_info *info = par->targinfo;
43147271Smarius	int tmp;
4443105Sdfr
4543105Sdfr	tmp = info->target | ~EBT_VERDICT_BITS;
4643105Sdfr	if (BASE_CHAIN && tmp == EBT_RETURN)
4743105Sdfr		return -EINVAL;
48147271Smarius	if (ebt_invalid_target(tmp))
49147271Smarius		return -EINVAL;
50212413Savg	tmp = info->target & ~EBT_VERDICT_BITS;
51188160Simp	if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
52216492Sjhb	    tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
53216492Sjhb		return -EINVAL;
54216492Sjhb	return 0;
55216492Sjhb}
56216492Sjhb#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
5743105Sdfrstruct compat_ebt_mark_t_info {
58147271Smarius	compat_ulong_t mark;
59147271Smarius	compat_uint_t target;
60147271Smarius};
6147296Syokota
6247296Syokotastatic void mark_tg_compat_from_user(void *dst, const void *src)
6343105Sdfr{
64147271Smarius	const struct compat_ebt_mark_t_info *user = src;
6543105Sdfr	struct ebt_mark_t_info *kern = dst;
6643105Sdfr
6743105Sdfr	kern->mark = user->mark;
6883147Syokota	kern->target = user->target;
69216492Sjhb}
70216492Sjhb
7143105Sdfrstatic int mark_tg_compat_to_user(void __user *dst, const void *src)
7243105Sdfr{
7383147Syokota	struct compat_ebt_mark_t_info __user *user = dst;
7483147Syokota	const struct ebt_mark_t_info *kern = src;
7583147Syokota
7643105Sdfr	if (put_user(kern->mark, &user->mark) ||
7743105Sdfr	    put_user(kern->target, &user->target))
7843105Sdfr		return -EFAULT;
7943105Sdfr	return 0;
8043105Sdfr}
8143105Sdfr#endif
82147271Smarius
8343105Sdfrstatic struct xt_target ebt_mark_tg_reg __read_mostly = {
84147271Smarius	.name		= "mark",
8543105Sdfr	.revision	= 0,
8643105Sdfr	.family		= NFPROTO_BRIDGE,
8743105Sdfr	.target		= ebt_mark_tg,
8858271Syokota	.checkentry	= ebt_mark_tg_check,
8958271Syokota	.targetsize	= sizeof(struct ebt_mark_t_info),
9058271Syokota#ifdef CONFIG_NETFILTER_XTABLES_COMPAT
9158271Syokota	.compatsize	= sizeof(struct compat_ebt_mark_t_info),
9258271Syokota	.compat_from_user = mark_tg_compat_from_user,
9343105Sdfr	.compat_to_user	= mark_tg_compat_to_user,
94147271Smarius#endif
9543105Sdfr	.me		= THIS_MODULE,
9658271Syokota};
9758271Syokota
9883147Syokotastatic int __init ebt_mark_init(void)
9983147Syokota{
10058271Syokota	return xt_register_target(&ebt_mark_tg_reg);
10158271Syokota}
102207354Ssobomax
103158041Ssobomaxstatic void __exit ebt_mark_fini(void)
104158041Ssobomax{
105158041Ssobomax	xt_unregister_target(&ebt_mark_tg_reg);
106158041Ssobomax}
107158041Ssobomax
10843105Sdfrmodule_init(ebt_mark_init);
10958271Syokotamodule_exit(ebt_mark_fini);
11058271SyokotaMODULE_DESCRIPTION("Ebtables: Packet mark modification");
11158271SyokotaMODULE_LICENSE("GPL");
11247618Sdfr