1 /* 2 * Copyright (c) 2010 Patrick McHardy <kaber@trash.net> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 */ 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 #include <linux/module.h> 10 #include <linux/gfp.h> 11 #include <linux/skbuff.h> 12 #include <linux/netfilter_ipv4/ip_tables.h> 13 #include <linux/netfilter_ipv6/ip6_tables.h> 14 #include <linux/netfilter/x_tables.h> 15 #include <linux/netfilter/xt_CT.h> 16 #include <net/netfilter/nf_conntrack.h> 17 #include <net/netfilter/nf_conntrack_l4proto.h> 18 #include <net/netfilter/nf_conntrack_helper.h> 19 #include <net/netfilter/nf_conntrack_ecache.h> 20 #include <net/netfilter/nf_conntrack_timeout.h> 21 #include <net/netfilter/nf_conntrack_zones.h> 22 23 static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) 24 { 25 /* Previously seen (loopback)? Ignore. */ 26 if (skb->_nfct != 0) 27 return XT_CONTINUE; 28 29 /* special case the untracked ct : we want the percpu object */ 30 if (!ct) 31 ct = nf_ct_untracked_get(); 32 atomic_inc(&ct->ct_general.use); 33 nf_ct_set(skb, ct, IP_CT_NEW); 34 35 return XT_CONTINUE; 36 } 37 38 static unsigned int xt_ct_target_v0(struct sk_buff *skb, 39 const struct xt_action_param *par) 40 { 41 const struct xt_ct_target_info *info = par->targinfo; 42 struct nf_conn *ct = info->ct; 43 44 return xt_ct_target(skb, ct); 45 } 46 47 static unsigned int xt_ct_target_v1(struct sk_buff *skb, 48 const struct xt_action_param *par) 49 { 50 const struct xt_ct_target_info_v1 *info = par->targinfo; 51 struct nf_conn *ct = info->ct; 52 53 return xt_ct_target(skb, ct); 54 } 55 56 static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) 57 { 58 if (par->family == NFPROTO_IPV4) { 59 const struct ipt_entry *e = par->entryinfo; 60 61 if (e->ip.invflags & IPT_INV_PROTO) 62 return 0; 63 return e->ip.proto; 64 } else if (par->family == NFPROTO_IPV6) { 65 const struct ip6t_entry *e = par->entryinfo; 66 67 if (e->ipv6.invflags & IP6T_INV_PROTO) 68 return 0; 69 return e->ipv6.proto; 70 } else 71 return 0; 72 } 73 74 static int 75 xt_ct_set_helper(struct nf_conn *ct, const char *helper_name, 76 const struct xt_tgchk_param *par) 77 { 78 struct nf_conntrack_helper *helper; 79 struct nf_conn_help *help; 80 u8 proto; 81 82 proto = xt_ct_find_proto(par); 83 if (!proto) { 84 pr_info("You must specify a L4 protocol, and not use " 85 "inversions on it.\n"); 86 return -ENOENT; 87 } 88 89 helper = nf_conntrack_helper_try_module_get(helper_name, par->family, 90 proto); 91 if (helper == NULL) { 92 pr_info("No such helper \"%s\"\n", helper_name); 93 return -ENOENT; 94 } 95 96 help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); 97 if (help == NULL) { 98 module_put(helper->me); 99 return -ENOMEM; 100 } 101 102 help->helper = helper; 103 return 0; 104 } 105 106 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 107 static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) 108 { 109 typeof(nf_ct_timeout_put_hook) timeout_put; 110 111 timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 112 if (timeout_put) 113 timeout_put(timeout); 114 } 115 #endif 116 117 static int 118 xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, 119 const char *timeout_name) 120 { 121 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 122 typeof(nf_ct_timeout_find_get_hook) timeout_find_get; 123 struct ctnl_timeout *timeout; 124 struct nf_conn_timeout *timeout_ext; 125 struct nf_conntrack_l4proto *l4proto; 126 int ret = 0; 127 u8 proto; 128 129 rcu_read_lock(); 130 timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); 131 if (timeout_find_get == NULL) { 132 ret = -ENOENT; 133 pr_info("Timeout policy base is empty\n"); 134 goto out; 135 } 136 137 proto = xt_ct_find_proto(par); 138 if (!proto) { 139 ret = -EINVAL; 140 pr_info("You must specify a L4 protocol, and not use " 141 "inversions on it.\n"); 142 goto out; 143 } 144 145 timeout = timeout_find_get(par->net, timeout_name); 146 if (timeout == NULL) { 147 ret = -ENOENT; 148 pr_info("No such timeout policy \"%s\"\n", timeout_name); 149 goto out; 150 } 151 152 if (timeout->l3num != par->family) { 153 ret = -EINVAL; 154 pr_info("Timeout policy `%s' can only be used by L3 protocol " 155 "number %d\n", timeout_name, timeout->l3num); 156 goto err_put_timeout; 157 } 158 /* Make sure the timeout policy matches any existing protocol tracker, 159 * otherwise default to generic. 160 */ 161 l4proto = __nf_ct_l4proto_find(par->family, proto); 162 if (timeout->l4proto->l4proto != l4proto->l4proto) { 163 ret = -EINVAL; 164 pr_info("Timeout policy `%s' can only be used by L4 protocol " 165 "number %d\n", 166 timeout_name, timeout->l4proto->l4proto); 167 goto err_put_timeout; 168 } 169 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); 170 if (timeout_ext == NULL) 171 ret = -ENOMEM; 172 173 rcu_read_unlock(); 174 return ret; 175 176 err_put_timeout: 177 __xt_ct_tg_timeout_put(timeout); 178 out: 179 rcu_read_unlock(); 180 return ret; 181 #else 182 return -EOPNOTSUPP; 183 #endif 184 } 185 186 static u16 xt_ct_flags_to_dir(const struct xt_ct_target_info_v1 *info) 187 { 188 switch (info->flags & (XT_CT_ZONE_DIR_ORIG | 189 XT_CT_ZONE_DIR_REPL)) { 190 case XT_CT_ZONE_DIR_ORIG: 191 return NF_CT_ZONE_DIR_ORIG; 192 case XT_CT_ZONE_DIR_REPL: 193 return NF_CT_ZONE_DIR_REPL; 194 default: 195 return NF_CT_DEFAULT_ZONE_DIR; 196 } 197 } 198 199 static int xt_ct_tg_check(const struct xt_tgchk_param *par, 200 struct xt_ct_target_info_v1 *info) 201 { 202 struct nf_conntrack_zone zone; 203 struct nf_conn *ct; 204 int ret = -EOPNOTSUPP; 205 206 if (info->flags & XT_CT_NOTRACK) { 207 ct = NULL; 208 goto out; 209 } 210 211 #ifndef CONFIG_NF_CONNTRACK_ZONES 212 if (info->zone || info->flags & (XT_CT_ZONE_DIR_ORIG | 213 XT_CT_ZONE_DIR_REPL | 214 XT_CT_ZONE_MARK)) 215 goto err1; 216 #endif 217 218 ret = nf_ct_netns_get(par->net, par->family); 219 if (ret < 0) 220 goto err1; 221 222 memset(&zone, 0, sizeof(zone)); 223 zone.id = info->zone; 224 zone.dir = xt_ct_flags_to_dir(info); 225 if (info->flags & XT_CT_ZONE_MARK) 226 zone.flags |= NF_CT_FLAG_MARK; 227 228 ct = nf_ct_tmpl_alloc(par->net, &zone, GFP_KERNEL); 229 if (!ct) { 230 ret = -ENOMEM; 231 goto err2; 232 } 233 234 ret = 0; 235 if ((info->ct_events || info->exp_events) && 236 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events, 237 GFP_KERNEL)) { 238 ret = -EINVAL; 239 goto err3; 240 } 241 242 if (info->helper[0]) { 243 ret = xt_ct_set_helper(ct, info->helper, par); 244 if (ret < 0) 245 goto err3; 246 } 247 248 if (info->timeout[0]) { 249 ret = xt_ct_set_timeout(ct, par, info->timeout); 250 if (ret < 0) 251 goto err3; 252 } 253 __set_bit(IPS_CONFIRMED_BIT, &ct->status); 254 nf_conntrack_get(&ct->ct_general); 255 out: 256 info->ct = ct; 257 return 0; 258 259 err3: 260 nf_ct_tmpl_free(ct); 261 err2: 262 nf_ct_netns_put(par->net, par->family); 263 err1: 264 return ret; 265 } 266 267 static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) 268 { 269 struct xt_ct_target_info *info = par->targinfo; 270 struct xt_ct_target_info_v1 info_v1 = { 271 .flags = info->flags, 272 .zone = info->zone, 273 .ct_events = info->ct_events, 274 .exp_events = info->exp_events, 275 }; 276 int ret; 277 278 if (info->flags & ~XT_CT_NOTRACK) 279 return -EINVAL; 280 281 memcpy(info_v1.helper, info->helper, sizeof(info->helper)); 282 283 ret = xt_ct_tg_check(par, &info_v1); 284 if (ret < 0) 285 return ret; 286 287 info->ct = info_v1.ct; 288 289 return ret; 290 } 291 292 static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) 293 { 294 struct xt_ct_target_info_v1 *info = par->targinfo; 295 296 if (info->flags & ~XT_CT_NOTRACK) 297 return -EINVAL; 298 299 return xt_ct_tg_check(par, par->targinfo); 300 } 301 302 static int xt_ct_tg_check_v2(const struct xt_tgchk_param *par) 303 { 304 struct xt_ct_target_info_v1 *info = par->targinfo; 305 306 if (info->flags & ~XT_CT_MASK) 307 return -EINVAL; 308 309 return xt_ct_tg_check(par, par->targinfo); 310 } 311 312 static void xt_ct_destroy_timeout(struct nf_conn *ct) 313 { 314 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 315 struct nf_conn_timeout *timeout_ext; 316 typeof(nf_ct_timeout_put_hook) timeout_put; 317 318 rcu_read_lock(); 319 timeout_put = rcu_dereference(nf_ct_timeout_put_hook); 320 321 if (timeout_put) { 322 timeout_ext = nf_ct_timeout_find(ct); 323 if (timeout_ext) { 324 timeout_put(timeout_ext->timeout); 325 RCU_INIT_POINTER(timeout_ext->timeout, NULL); 326 } 327 } 328 rcu_read_unlock(); 329 #endif 330 } 331 332 static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, 333 struct xt_ct_target_info_v1 *info) 334 { 335 struct nf_conn *ct = info->ct; 336 struct nf_conn_help *help; 337 338 if (ct && !nf_ct_is_untracked(ct)) { 339 help = nfct_help(ct); 340 if (help) 341 module_put(help->helper->me); 342 343 nf_ct_netns_put(par->net, par->family); 344 345 xt_ct_destroy_timeout(ct); 346 nf_ct_put(info->ct); 347 } 348 } 349 350 static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 351 { 352 struct xt_ct_target_info *info = par->targinfo; 353 struct xt_ct_target_info_v1 info_v1 = { 354 .flags = info->flags, 355 .zone = info->zone, 356 .ct_events = info->ct_events, 357 .exp_events = info->exp_events, 358 .ct = info->ct, 359 }; 360 memcpy(info_v1.helper, info->helper, sizeof(info->helper)); 361 362 xt_ct_tg_destroy(par, &info_v1); 363 } 364 365 static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) 366 { 367 xt_ct_tg_destroy(par, par->targinfo); 368 } 369 370 static struct xt_target xt_ct_tg_reg[] __read_mostly = { 371 { 372 .name = "CT", 373 .family = NFPROTO_UNSPEC, 374 .targetsize = sizeof(struct xt_ct_target_info), 375 .usersize = offsetof(struct xt_ct_target_info, ct), 376 .checkentry = xt_ct_tg_check_v0, 377 .destroy = xt_ct_tg_destroy_v0, 378 .target = xt_ct_target_v0, 379 .table = "raw", 380 .me = THIS_MODULE, 381 }, 382 { 383 .name = "CT", 384 .family = NFPROTO_UNSPEC, 385 .revision = 1, 386 .targetsize = sizeof(struct xt_ct_target_info_v1), 387 .usersize = offsetof(struct xt_ct_target_info, ct), 388 .checkentry = xt_ct_tg_check_v1, 389 .destroy = xt_ct_tg_destroy_v1, 390 .target = xt_ct_target_v1, 391 .table = "raw", 392 .me = THIS_MODULE, 393 }, 394 { 395 .name = "CT", 396 .family = NFPROTO_UNSPEC, 397 .revision = 2, 398 .targetsize = sizeof(struct xt_ct_target_info_v1), 399 .usersize = offsetof(struct xt_ct_target_info, ct), 400 .checkentry = xt_ct_tg_check_v2, 401 .destroy = xt_ct_tg_destroy_v1, 402 .target = xt_ct_target_v1, 403 .table = "raw", 404 .me = THIS_MODULE, 405 }, 406 }; 407 408 static unsigned int 409 notrack_tg(struct sk_buff *skb, const struct xt_action_param *par) 410 { 411 /* Previously seen (loopback)? Ignore. */ 412 if (skb->_nfct != 0) 413 return XT_CONTINUE; 414 415 nf_ct_set(skb, nf_ct_untracked_get(), IP_CT_NEW); 416 nf_conntrack_get(skb_nfct(skb)); 417 418 return XT_CONTINUE; 419 } 420 421 static int notrack_chk(const struct xt_tgchk_param *par) 422 { 423 if (!par->net->xt.notrack_deprecated_warning) { 424 pr_info("netfilter: NOTRACK target is deprecated, " 425 "use CT instead or upgrade iptables\n"); 426 par->net->xt.notrack_deprecated_warning = true; 427 } 428 return 0; 429 } 430 431 static struct xt_target notrack_tg_reg __read_mostly = { 432 .name = "NOTRACK", 433 .revision = 0, 434 .family = NFPROTO_UNSPEC, 435 .checkentry = notrack_chk, 436 .target = notrack_tg, 437 .table = "raw", 438 .me = THIS_MODULE, 439 }; 440 441 static int __init xt_ct_tg_init(void) 442 { 443 int ret; 444 445 ret = xt_register_target(¬rack_tg_reg); 446 if (ret < 0) 447 return ret; 448 449 ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 450 if (ret < 0) { 451 xt_unregister_target(¬rack_tg_reg); 452 return ret; 453 } 454 return 0; 455 } 456 457 static void __exit xt_ct_tg_exit(void) 458 { 459 xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); 460 xt_unregister_target(¬rack_tg_reg); 461 } 462 463 module_init(xt_ct_tg_init); 464 module_exit(xt_ct_tg_exit); 465 466 MODULE_LICENSE("GPL"); 467 MODULE_DESCRIPTION("Xtables: connection tracking target"); 468 MODULE_ALIAS("ipt_CT"); 469 MODULE_ALIAS("ip6t_CT"); 470 MODULE_ALIAS("ipt_NOTRACK"); 471 MODULE_ALIAS("ip6t_NOTRACK"); 472