11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  ebt_mark
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Authors:
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Bart De Schuymer <bdschuym@pandora.be>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  July, 2002
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The mark target can be used in any chain,
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * I believe adding a mangle table just for marking is total overkill.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Marking a frame doesn't really change anything in the frame anyway.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1618219d3f7d6a5bc43825a41e0763158efbdb80d3Jan Engelhardt#include <linux/module.h>
1718219d3f7d6a5bc43825a41e0763158efbdb80d3Jan Engelhardt#include <linux/netfilter/x_tables.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_bridge/ebtables.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_bridge/ebt_mark_t.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
212d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardtstatic unsigned int
224b560b447df83368df44bd3712c0c39b1d79ba04Jan Engelhardtebt_mark_tg(struct sk_buff *skb, const struct xt_action_param *par)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
247eb3558655aaa87a3e71a0c065dfaddda521fa6dJan Engelhardt	const struct ebt_mark_t_info *info = par->targinfo;
25b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	int action = info->target & -16;
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	if (action == MARK_SET_VALUE)
283db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xu		skb->mark = info->mark;
29b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	else if (action == MARK_OR_VALUE)
303db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xu		skb->mark |= info->mark;
31b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	else if (action == MARK_AND_VALUE)
323db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xu		skb->mark &= info->mark;
33b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	else
343db05fea51cdb162cfa8f69e9cfb9e228919d2a9Herbert Xu		skb->mark ^= info->mark;
356869c4d8e066e21623c812c448a05f1ed931c9c6Harald Welte
36d12cdc3ccf140bd2febef1c1be92284571da983fBart De Schuymer	return info->target | ~EBT_VERDICT_BITS;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39135367b8f6a18507af6b9a6910a14b5699415309Jan Engelhardtstatic int ebt_mark_tg_check(const struct xt_tgchk_param *par)
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
41af5d6dc200eb0fcc6fbd3df1ab4d8969004cb37fJan Engelhardt	const struct ebt_mark_t_info *info = par->targinfo;
42b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	int tmp;
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44d12cdc3ccf140bd2febef1c1be92284571da983fBart De Schuymer	tmp = info->target | ~EBT_VERDICT_BITS;
45b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	if (BASE_CHAIN && tmp == EBT_RETURN)
46d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
47b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
48d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
49d12cdc3ccf140bd2febef1c1be92284571da983fBart De Schuymer	tmp = info->target & ~EBT_VERDICT_BITS;
50b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
51b18dfa90c008850e0f3bfd63638dd8fbe8e08701Bart De Schuymer	    tmp != MARK_AND_VALUE && tmp != MARK_XOR_VALUE)
52d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt		return -EINVAL;
53d6b00a5345ce4e86e8b00a88bb84a2c0c1f69ddcJan Engelhardt	return 0;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
556e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal#ifdef CONFIG_COMPAT
566e705f56a181118f6fbd35e6b443eab33df07290Florian Westphalstruct compat_ebt_mark_t_info {
576e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	compat_ulong_t mark;
586e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	compat_uint_t target;
596e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal};
606e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal
616e705f56a181118f6fbd35e6b443eab33df07290Florian Westphalstatic void mark_tg_compat_from_user(void *dst, const void *src)
626e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal{
636e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	const struct compat_ebt_mark_t_info *user = src;
646e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	struct ebt_mark_t_info *kern = dst;
656e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal
666e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	kern->mark = user->mark;
676e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	kern->target = user->target;
686e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal}
696e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal
706e705f56a181118f6fbd35e6b443eab33df07290Florian Westphalstatic int mark_tg_compat_to_user(void __user *dst, const void *src)
716e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal{
726e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	struct compat_ebt_mark_t_info __user *user = dst;
736e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	const struct ebt_mark_t_info *kern = src;
746e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal
756e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	if (put_user(kern->mark, &user->mark) ||
766e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	    put_user(kern->target, &user->target))
776e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal		return -EFAULT;
786e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	return 0;
796e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal}
806e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal#endif
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
82043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardtstatic struct xt_target ebt_mark_tg_reg __read_mostly = {
83043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	.name		= "mark",
84001a18d369f4813ed792629ff4a9a6ade2a4a031Jan Engelhardt	.revision	= 0,
85001a18d369f4813ed792629ff4a9a6ade2a4a031Jan Engelhardt	.family		= NFPROTO_BRIDGE,
862d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardt	.target		= ebt_mark_tg,
872d06d4a5cc107046508d860a0b47dbc43b829b79Jan Engelhardt	.checkentry	= ebt_mark_tg_check,
88fc0e3df4f00a5f62c2f2fce84bf496136b58c474Florian Westphal	.targetsize	= sizeof(struct ebt_mark_t_info),
896e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal#ifdef CONFIG_COMPAT
906e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	.compatsize	= sizeof(struct compat_ebt_mark_t_info),
916e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	.compat_from_user = mark_tg_compat_from_user,
926e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal	.compat_to_user	= mark_tg_compat_to_user,
936e705f56a181118f6fbd35e6b443eab33df07290Florian Westphal#endif
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.me		= THIS_MODULE,
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9765b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic int __init ebt_mark_init(void)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
99043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	return xt_register_target(&ebt_mark_tg_reg);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10265b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonstatic void __exit ebt_mark_fini(void)
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
104043ef46c7690bfdbd5b012e15812a14a19ca5604Jan Engelhardt	xt_unregister_target(&ebt_mark_tg_reg);
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10765b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_init(ebt_mark_init);
10865b4b4e81a5094d52cbe372b887b1779abe53f9bAndrew Mortonmodule_exit(ebt_mark_fini);
109f776c4cda449bab463f5388eb07bd63dc52e2b13Jan EngelhardtMODULE_DESCRIPTION("Ebtables: Packet mark modification");
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
111