1/* This is a module which is used for setting the NFMARK field of an skb. */ 2 3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> 4 * 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. 8 */ 9 10#include <linux/module.h> 11#include <linux/skbuff.h> 12#include <linux/ip.h> 13#include <net/checksum.h> 14 15#include <linux/netfilter/x_tables.h> 16#include <linux/netfilter/xt_MARK.h> 17#ifdef HNDCTF 18#include <net/netfilter/nf_conntrack.h> 19#endif 20 21MODULE_LICENSE("GPL"); 22MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 23MODULE_DESCRIPTION("ip[6]tables MARK modification module"); 24MODULE_ALIAS("ipt_MARK"); 25MODULE_ALIAS("ip6t_MARK"); 26 27static unsigned int 28target_v0(struct sk_buff **pskb, 29 const struct net_device *in, 30 const struct net_device *out, 31 unsigned int hooknum, 32 const struct xt_target *target, 33 const void *targinfo) 34{ 35 const struct xt_mark_target_info *markinfo = targinfo; 36 37 (*pskb)->mark = markinfo->mark; 38 return XT_CONTINUE; 39} 40 41static unsigned int 42target_v1(struct sk_buff **pskb, 43 const struct net_device *in, 44 const struct net_device *out, 45 unsigned int hooknum, 46 const struct xt_target *target, 47 const void *targinfo) 48{ 49 const struct xt_mark_target_info_v1 *markinfo = targinfo; 50 int mark = 0; 51 52 switch (markinfo->mode) { 53 case XT_MARK_SET: 54 mark = markinfo->mark; 55#ifdef HNDCTF 56 { 57 enum ip_conntrack_info ctinfo; 58 struct nf_conn *ct = nf_ct_get(*pskb, &ctinfo); 59 ct->ctf_flags |= CTF_FLAGS_EXCLUDED; 60 } 61#endif /* HNDCTF */ 62 break; 63 64 case XT_MARK_AND: 65 mark = (*pskb)->mark & markinfo->mark; 66 break; 67 68 case XT_MARK_OR: 69 mark = (*pskb)->mark | markinfo->mark; 70 break; 71 } 72 73 (*pskb)->mark = mark; 74 return XT_CONTINUE; 75} 76 77 78static int 79checkentry_v0(const char *tablename, 80 const void *entry, 81 const struct xt_target *target, 82 void *targinfo, 83 unsigned int hook_mask) 84{ 85 struct xt_mark_target_info *markinfo = targinfo; 86 87 if (markinfo->mark > 0xffffffff) { 88 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 89 return 0; 90 } 91 return 1; 92} 93 94static int 95checkentry_v1(const char *tablename, 96 const void *entry, 97 const struct xt_target *target, 98 void *targinfo, 99 unsigned int hook_mask) 100{ 101 struct xt_mark_target_info_v1 *markinfo = targinfo; 102 103 if (markinfo->mode != XT_MARK_SET 104 && markinfo->mode != XT_MARK_AND 105 && markinfo->mode != XT_MARK_OR) { 106 printk(KERN_WARNING "MARK: unknown mode %u\n", 107 markinfo->mode); 108 return 0; 109 } 110 if (markinfo->mark > 0xffffffff) { 111 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n"); 112 return 0; 113 } 114 return 1; 115} 116 117#ifdef CONFIG_COMPAT 118struct compat_xt_mark_target_info_v1 { 119 compat_ulong_t mark; 120 u_int8_t mode; 121 u_int8_t __pad1; 122 u_int16_t __pad2; 123}; 124 125static void compat_from_user_v1(void *dst, void *src) 126{ 127 struct compat_xt_mark_target_info_v1 *cm = src; 128 struct xt_mark_target_info_v1 m = { 129 .mark = cm->mark, 130 .mode = cm->mode, 131 }; 132 memcpy(dst, &m, sizeof(m)); 133} 134 135static int compat_to_user_v1(void __user *dst, void *src) 136{ 137 struct xt_mark_target_info_v1 *m = src; 138 struct compat_xt_mark_target_info_v1 cm = { 139 .mark = m->mark, 140 .mode = m->mode, 141 }; 142 return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; 143} 144#endif /* CONFIG_COMPAT */ 145 146static struct xt_target xt_mark_target[] = { 147 { 148 .name = "MARK", 149 .family = AF_INET, 150 .revision = 0, 151 .checkentry = checkentry_v0, 152 .target = target_v0, 153 .targetsize = sizeof(struct xt_mark_target_info), 154 .table = "mangle", 155 .me = THIS_MODULE, 156 }, 157 { 158 .name = "MARK", 159 .family = AF_INET, 160 .revision = 1, 161 .checkentry = checkentry_v1, 162 .target = target_v1, 163 .targetsize = sizeof(struct xt_mark_target_info_v1), 164#ifdef CONFIG_COMPAT 165 .compatsize = sizeof(struct compat_xt_mark_target_info_v1), 166 .compat_from_user = compat_from_user_v1, 167 .compat_to_user = compat_to_user_v1, 168#endif 169 .table = "mangle", 170 .me = THIS_MODULE, 171 }, 172 { 173 .name = "MARK", 174 .family = AF_INET6, 175 .revision = 0, 176 .checkentry = checkentry_v0, 177 .target = target_v0, 178 .targetsize = sizeof(struct xt_mark_target_info), 179 .table = "mangle", 180 .me = THIS_MODULE, 181 }, 182}; 183 184static int __init xt_mark_init(void) 185{ 186 return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target)); 187} 188 189static void __exit xt_mark_fini(void) 190{ 191 xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target)); 192} 193 194module_init(xt_mark_init); 195module_exit(xt_mark_fini); 196