1 /* This is a module which is used for setting the NFMARK field of an skb. */
3 /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
11 #include <linux/module.h>
12 #include <linux/version.h>
13 #include <linux/skbuff.h>
15 #include <net/checksum.h>
16 #include <net/route.h>
17 #include <net/inet_hashtables.h>
19 #include <linux/netfilter_ipv4/ip_conntrack.h>
20 #include <linux/netfilter/x_tables.h>
21 #include <linux/netfilter/xt_MARK.h>
23 MODULE_LICENSE("GPL");
24 MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
25 MODULE_DESCRIPTION("ip[6]tables MARK modification module");
26 MODULE_ALIAS("ipt_MARK");
27 MODULE_ALIAS("ip6t_MARK");
29 static inline u_int16_t
30 get_dst_port(struct ip_conntrack_tuple *tuple)
32 switch (tuple->dst.protonum) {
34 /* XXX Truncate 32-bit GRE key to 16 bits */
35 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
36 return tuple->dst.u.gre.key;
38 return htons(ntohl(tuple->dst.u.gre.key));
41 /* Bind on ICMP echo ID */
42 return tuple->src.u.icmp.id;
44 return tuple->dst.u.tcp.port;
46 return tuple->dst.u.udp.port;
48 return tuple->dst.u.all;
52 static inline u_int16_t
53 get_src_port(struct ip_conntrack_tuple *tuple)
55 switch (tuple->dst.protonum) {
57 /* XXX Truncate 32-bit GRE key to 16 bits */
58 return htons(ntohl(tuple->src.u.gre.key));
60 /* Bind on ICMP echo ID */
61 return tuple->src.u.icmp.id;
63 return tuple->src.u.tcp.port;
65 return tuple->src.u.udp.port;
67 return tuple->src.u.all;
72 target_v0(struct sk_buff **pskb,
73 const struct net_device *in,
74 const struct net_device *out,
76 const struct xt_target *target,
79 const struct xt_mark_target_info *markinfo = targinfo;
81 if((*pskb)->mark != markinfo->mark)
82 (*pskb)->mark = markinfo->mark;
88 target_v1(struct sk_buff **pskb,
89 const struct net_device *in,
90 const struct net_device *out,
92 const struct xt_target *target,
95 const struct xt_mark_target_info_v1 *markinfo = targinfo;
98 switch (markinfo->mode) {
100 mark = markinfo->mark;
104 mark = (*pskb)->mark & markinfo->mark;
108 mark = (*pskb)->mark | markinfo->mark;
111 case XT_MARK_COPYXID:
113 enum ip_conntrack_info ctinfo;
114 struct sock *connection_sk;
117 struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
118 extern struct inet_hashinfo tcp_hashinfo;
119 enum ip_conntrack_dir dir;
123 dir= CTINFO2DIR(ctinfo);
124 u_int32_t src_ip = ct->tuplehash[dir].tuple.src.ip;
125 u_int16_t src_port = get_src_port(&ct->tuplehash[dir].tuple);
130 dif = ((struct rtable *)(*pskb)->dst)->rt_iif;
131 ip = ct->tuplehash[dir].tuple.dst.ip;
132 port = get_dst_port(&ct->tuplehash[dir].tuple);
135 connection_sk = (*pskb)->sk;
137 connection_sk = inet_lookup(&tcp_hashinfo, src_ip, src_port, ip, port, dif);
142 connection_sk->sk_peercred.gid = connection_sk->sk_peercred.uid = ct->xid[dir];
143 ct->xid[!dir]=connection_sk->sk_xid;
145 connection_sk->sk_peercred.gid = connection_sk->sk_peercred.uid = connection_sk->sk_xid;
146 if (connection_sk->sk_xid != 0)
147 mark = connection_sk->sk_xid;
148 if (connection_sk != (*pskb)->sk)
149 sock_put(connection_sk);
155 if((*pskb)->mark != mark && mark != -1)
156 (*pskb)->mark = mark;
163 checkentry_v0(const char *tablename,
165 const struct xt_target *target,
167 unsigned int hook_mask)
169 struct xt_mark_target_info *markinfo = targinfo;
171 if (markinfo->mark > 0xffffffff) {
172 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
179 checkentry_v1(const char *tablename,
181 const struct xt_target *target,
183 unsigned int hook_mask)
185 struct xt_mark_target_info_v1 *markinfo = targinfo;
187 if (markinfo->mode != XT_MARK_SET
188 && markinfo->mode != XT_MARK_AND
189 && markinfo->mode != XT_MARK_OR
190 && markinfo->mode != XT_MARK_COPYXID) {
191 printk(KERN_WARNING "MARK: unknown mode %u\n",
195 if (markinfo->mark > 0xffffffff) {
196 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
203 struct compat_xt_mark_target_info_v1 {
210 static void compat_from_user_v1(void *dst, void *src)
212 struct compat_xt_mark_target_info_v1 *cm = src;
213 struct xt_mark_target_info_v1 m = {
217 memcpy(dst, &m, sizeof(m));
220 static int compat_to_user_v1(void __user *dst, void *src)
222 struct xt_mark_target_info_v1 *m = src;
223 struct compat_xt_mark_target_info_v1 cm = {
227 return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
229 #endif /* CONFIG_COMPAT */
231 static struct xt_target xt_mark_target[] = {
236 .checkentry = checkentry_v0,
238 .targetsize = sizeof(struct xt_mark_target_info),
246 .checkentry = checkentry_v1,
248 .targetsize = sizeof(struct xt_mark_target_info_v1),
250 .compatsize = sizeof(struct compat_xt_mark_target_info_v1),
251 .compat_from_user = compat_from_user_v1,
252 .compat_to_user = compat_to_user_v1,
261 .checkentry = checkentry_v0,
263 .targetsize = sizeof(struct xt_mark_target_info),
269 static int __init xt_mark_init(void)
271 return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
274 static void __exit xt_mark_fini(void)
276 xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target));
279 module_init(xt_mark_init);
280 module_exit(xt_mark_fini);