1/* (C) 1999-2001 Paul `Rusty' Russell 2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 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 9#include <linux/types.h> 10#include <linux/ip.h> 11#include <linux/netfilter.h> 12#include <linux/module.h> 13#include <linux/skbuff.h> 14#include <linux/icmp.h> 15#include <linux/sysctl.h> 16#include <net/route.h> 17#include <net/ip.h> 18 19#include <linux/netfilter_ipv4.h> 20#include <net/netfilter/nf_conntrack.h> 21#include <net/netfilter/nf_conntrack_helper.h> 22#include <net/netfilter/nf_conntrack_l4proto.h> 23#include <net/netfilter/nf_conntrack_l3proto.h> 24#include <net/netfilter/nf_conntrack_core.h> 25#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 26 27#define DEBUGP(format, args...) 28 29static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, 30 struct nf_conntrack_tuple *tuple) 31{ 32 __be32 _addrs[2], *ap; 33 ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), 34 sizeof(u_int32_t) * 2, _addrs); 35 if (ap == NULL) 36 return 0; 37 38 tuple->src.u3.ip = ap[0]; 39 tuple->dst.u3.ip = ap[1]; 40 41 return 1; 42} 43 44static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple, 45 const struct nf_conntrack_tuple *orig) 46{ 47 tuple->src.u3.ip = orig->dst.u3.ip; 48 tuple->dst.u3.ip = orig->src.u3.ip; 49 50 return 1; 51} 52 53static int ipv4_print_tuple(struct seq_file *s, 54 const struct nf_conntrack_tuple *tuple) 55{ 56 return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", 57 NIPQUAD(tuple->src.u3.ip), 58 NIPQUAD(tuple->dst.u3.ip)); 59} 60 61static int ipv4_print_conntrack(struct seq_file *s, 62 const struct nf_conn *conntrack) 63{ 64 return 0; 65} 66 67/* Returns new sk_buff, or NULL */ 68static struct sk_buff * 69nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) 70{ 71 skb_orphan(skb); 72 73 local_bh_disable(); 74 skb = ip_defrag(skb, user); 75 local_bh_enable(); 76 77 if (skb) 78 ip_send_check(ip_hdr(skb)); 79 80 return skb; 81} 82 83static int 84ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, 85 u_int8_t *protonum) 86{ 87 /* Never happen */ 88 if (ip_hdr(*pskb)->frag_off & htons(IP_OFFSET)) { 89 if (net_ratelimit()) { 90 printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", 91 ip_hdr(*pskb)->protocol, hooknum); 92 } 93 return -NF_DROP; 94 } 95 96 *dataoff = skb_network_offset(*pskb) + ip_hdrlen(*pskb); 97 *protonum = ip_hdr(*pskb)->protocol; 98 99 return NF_ACCEPT; 100} 101 102int nf_nat_module_is_loaded = 0; 103EXPORT_SYMBOL_GPL(nf_nat_module_is_loaded); 104 105static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) 106{ 107 if (nf_nat_module_is_loaded) 108 return NF_CT_F_NAT; 109 110 return NF_CT_F_BASIC; 111} 112 113static unsigned int ipv4_confirm(unsigned int hooknum, 114 struct sk_buff **pskb, 115 const struct net_device *in, 116 const struct net_device *out, 117 int (*okfn)(struct sk_buff *)) 118{ 119 /* We've seen it coming out the other side: confirm it */ 120 return nf_conntrack_confirm(pskb); 121} 122 123static unsigned int ipv4_conntrack_help(unsigned int hooknum, 124 struct sk_buff **pskb, 125 const struct net_device *in, 126 const struct net_device *out, 127 int (*okfn)(struct sk_buff *)) 128{ 129 struct nf_conn *ct; 130 enum ip_conntrack_info ctinfo; 131 struct nf_conn_help *help; 132 struct nf_conntrack_helper *helper; 133 134 /* This is where we call the helper: as the packet goes out. */ 135 ct = nf_ct_get(*pskb, &ctinfo); 136 if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY) 137 return NF_ACCEPT; 138 139 help = nfct_help(ct); 140 if (!help) 141 return NF_ACCEPT; 142 /* rcu_read_lock()ed by nf_hook_slow */ 143 helper = rcu_dereference(help->helper); 144 if (!helper) 145 return NF_ACCEPT; 146 return helper->help(pskb, skb_network_offset(*pskb) + ip_hdrlen(*pskb), 147 ct, ctinfo); 148} 149 150static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 151 struct sk_buff **pskb, 152 const struct net_device *in, 153 const struct net_device *out, 154 int (*okfn)(struct sk_buff *)) 155{ 156 /* Previously seen (loopback)? Ignore. Do this before 157 fragment check. */ 158 if ((*pskb)->nfct) 159 return NF_ACCEPT; 160 161 /* Gather fragments. */ 162 if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { 163 *pskb = nf_ct_ipv4_gather_frags(*pskb, 164 hooknum == NF_IP_PRE_ROUTING ? 165 IP_DEFRAG_CONNTRACK_IN : 166 IP_DEFRAG_CONNTRACK_OUT); 167 if (!*pskb) 168 return NF_STOLEN; 169 } 170 return NF_ACCEPT; 171} 172 173static unsigned int ipv4_conntrack_in(unsigned int hooknum, 174 struct sk_buff **pskb, 175 const struct net_device *in, 176 const struct net_device *out, 177 int (*okfn)(struct sk_buff *)) 178{ 179 return nf_conntrack_in(PF_INET, hooknum, pskb); 180} 181 182static unsigned int ipv4_conntrack_local(unsigned int hooknum, 183 struct sk_buff **pskb, 184 const struct net_device *in, 185 const struct net_device *out, 186 int (*okfn)(struct sk_buff *)) 187{ 188 /* root is playing with raw sockets. */ 189 if ((*pskb)->len < sizeof(struct iphdr) 190 || ip_hdrlen(*pskb) < sizeof(struct iphdr)) { 191 if (net_ratelimit()) 192 printk("ipt_hook: happy cracking.\n"); 193 return NF_ACCEPT; 194 } 195 return nf_conntrack_in(PF_INET, hooknum, pskb); 196} 197 198/* Connection tracking may drop packets, but never alters them, so 199 make it the first hook. */ 200static struct nf_hook_ops ipv4_conntrack_ops[] = { 201 { 202 .hook = ipv4_conntrack_defrag, 203 .owner = THIS_MODULE, 204 .pf = PF_INET, 205 .hooknum = NF_IP_PRE_ROUTING, 206 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 207 }, 208 { 209 .hook = ipv4_conntrack_in, 210 .owner = THIS_MODULE, 211 .pf = PF_INET, 212 .hooknum = NF_IP_PRE_ROUTING, 213 .priority = NF_IP_PRI_CONNTRACK, 214 }, 215 { 216 .hook = ipv4_conntrack_defrag, 217 .owner = THIS_MODULE, 218 .pf = PF_INET, 219 .hooknum = NF_IP_LOCAL_OUT, 220 .priority = NF_IP_PRI_CONNTRACK_DEFRAG, 221 }, 222 { 223 .hook = ipv4_conntrack_local, 224 .owner = THIS_MODULE, 225 .pf = PF_INET, 226 .hooknum = NF_IP_LOCAL_OUT, 227 .priority = NF_IP_PRI_CONNTRACK, 228 }, 229 { 230 .hook = ipv4_conntrack_help, 231 .owner = THIS_MODULE, 232 .pf = PF_INET, 233 .hooknum = NF_IP_POST_ROUTING, 234 .priority = NF_IP_PRI_CONNTRACK_HELPER, 235 }, 236 { 237 .hook = ipv4_conntrack_help, 238 .owner = THIS_MODULE, 239 .pf = PF_INET, 240 .hooknum = NF_IP_LOCAL_IN, 241 .priority = NF_IP_PRI_CONNTRACK_HELPER, 242 }, 243 { 244 .hook = ipv4_confirm, 245 .owner = THIS_MODULE, 246 .pf = PF_INET, 247 .hooknum = NF_IP_POST_ROUTING, 248 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 249 }, 250 { 251 .hook = ipv4_confirm, 252 .owner = THIS_MODULE, 253 .pf = PF_INET, 254 .hooknum = NF_IP_LOCAL_IN, 255 .priority = NF_IP_PRI_CONNTRACK_CONFIRM, 256 }, 257}; 258 259#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) 260static int log_invalid_proto_min = 0; 261static int log_invalid_proto_max = 255; 262 263static ctl_table ip_ct_sysctl_table[] = { 264 { 265 .ctl_name = NET_IPV4_NF_CONNTRACK_MAX, 266 .procname = "ip_conntrack_max", 267 .data = &nf_conntrack_max, 268 .maxlen = sizeof(int), 269 .mode = 0644, 270 .proc_handler = &proc_dointvec, 271 }, 272 { 273 .ctl_name = NET_IPV4_NF_CONNTRACK_COUNT, 274 .procname = "ip_conntrack_count", 275 .data = &nf_conntrack_count, 276 .maxlen = sizeof(int), 277 .mode = 0444, 278 .proc_handler = &proc_dointvec, 279 }, 280 { 281 .ctl_name = NET_IPV4_NF_CONNTRACK_BUCKETS, 282 .procname = "ip_conntrack_buckets", 283 .data = &nf_conntrack_htable_size, 284 .maxlen = sizeof(unsigned int), 285 .mode = 0444, 286 .proc_handler = &proc_dointvec, 287 }, 288 { 289 .ctl_name = NET_IPV4_NF_CONNTRACK_CHECKSUM, 290 .procname = "ip_conntrack_checksum", 291 .data = &nf_conntrack_checksum, 292 .maxlen = sizeof(int), 293 .mode = 0644, 294 .proc_handler = &proc_dointvec, 295 }, 296 { 297 .ctl_name = NET_IPV4_NF_CONNTRACK_LOG_INVALID, 298 .procname = "ip_conntrack_log_invalid", 299 .data = &nf_ct_log_invalid, 300 .maxlen = sizeof(unsigned int), 301 .mode = 0644, 302 .proc_handler = &proc_dointvec_minmax, 303 .strategy = &sysctl_intvec, 304 .extra1 = &log_invalid_proto_min, 305 .extra2 = &log_invalid_proto_max, 306 }, 307 { 308 .ctl_name = 0 309 } 310}; 311#endif /* CONFIG_SYSCTL && CONFIG_NF_CONNTRACK_PROC_COMPAT */ 312 313/* Fast function for those who don't want to parse /proc (and I don't 314 blame them). */ 315/* Reversing the socket's dst/src point of view gives us the reply 316 mapping. */ 317static int 318getorigdst(struct sock *sk, int optval, void __user *user, int *len) 319{ 320 struct inet_sock *inet = inet_sk(sk); 321 struct nf_conntrack_tuple_hash *h; 322 struct nf_conntrack_tuple tuple; 323 324 NF_CT_TUPLE_U_BLANK(&tuple); 325 tuple.src.u3.ip = inet->rcv_saddr; 326 tuple.src.u.tcp.port = inet->sport; 327 tuple.dst.u3.ip = inet->daddr; 328 tuple.dst.u.tcp.port = inet->dport; 329 tuple.src.l3num = PF_INET; 330 tuple.dst.protonum = IPPROTO_TCP; 331 332 /* We only do TCP at the moment: is there a better way? */ 333 if (strcmp(sk->sk_prot->name, "TCP")) { 334 DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n"); 335 return -ENOPROTOOPT; 336 } 337 338 if ((unsigned int) *len < sizeof(struct sockaddr_in)) { 339 DEBUGP("SO_ORIGINAL_DST: len %u not %u\n", 340 *len, sizeof(struct sockaddr_in)); 341 return -EINVAL; 342 } 343 344 h = nf_conntrack_find_get(&tuple, NULL); 345 if (h) { 346 struct sockaddr_in sin; 347 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 348 349 sin.sin_family = AF_INET; 350 sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL] 351 .tuple.dst.u.tcp.port; 352 sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL] 353 .tuple.dst.u3.ip; 354 memset(sin.sin_zero, 0, sizeof(sin.sin_zero)); 355 356 DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", 357 NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); 358 nf_ct_put(ct); 359 if (copy_to_user(user, &sin, sizeof(sin)) != 0) 360 return -EFAULT; 361 else 362 return 0; 363 } 364 DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", 365 NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), 366 NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); 367 return -ENOENT; 368} 369 370#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 371 372#include <linux/netfilter/nfnetlink.h> 373#include <linux/netfilter/nfnetlink_conntrack.h> 374 375static int ipv4_tuple_to_nfattr(struct sk_buff *skb, 376 const struct nf_conntrack_tuple *tuple) 377{ 378 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), 379 &tuple->src.u3.ip); 380 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), 381 &tuple->dst.u3.ip); 382 return 0; 383 384nfattr_failure: 385 return -1; 386} 387 388static const size_t cta_min_ip[CTA_IP_MAX] = { 389 [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), 390 [CTA_IP_V4_DST-1] = sizeof(u_int32_t), 391}; 392 393static int ipv4_nfattr_to_tuple(struct nfattr *tb[], 394 struct nf_conntrack_tuple *t) 395{ 396 if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1]) 397 return -EINVAL; 398 399 if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) 400 return -EINVAL; 401 402 t->src.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); 403 t->dst.u3.ip = *(__be32 *)NFA_DATA(tb[CTA_IP_V4_DST-1]); 404 405 return 0; 406} 407#endif 408 409static struct nf_sockopt_ops so_getorigdst = { 410 .pf = PF_INET, 411 .get_optmin = SO_ORIGINAL_DST, 412 .get_optmax = SO_ORIGINAL_DST+1, 413 .get = &getorigdst, 414}; 415 416struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { 417 .l3proto = PF_INET, 418 .name = "ipv4", 419 .pkt_to_tuple = ipv4_pkt_to_tuple, 420 .invert_tuple = ipv4_invert_tuple, 421 .print_tuple = ipv4_print_tuple, 422 .print_conntrack = ipv4_print_conntrack, 423 .prepare = ipv4_prepare, 424 .get_features = ipv4_get_features, 425#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 426 .tuple_to_nfattr = ipv4_tuple_to_nfattr, 427 .nfattr_to_tuple = ipv4_nfattr_to_tuple, 428#endif 429#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) 430 .ctl_table_path = nf_net_ipv4_netfilter_sysctl_path, 431 .ctl_table = ip_ct_sysctl_table, 432#endif 433 .me = THIS_MODULE, 434}; 435 436MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); 437MODULE_ALIAS("ip_conntrack"); 438MODULE_LICENSE("GPL"); 439 440static int __init nf_conntrack_l3proto_ipv4_init(void) 441{ 442 int ret = 0; 443 444 need_conntrack(); 445 446 ret = nf_register_sockopt(&so_getorigdst); 447 if (ret < 0) { 448 printk(KERN_ERR "Unable to register netfilter socket option\n"); 449 return ret; 450 } 451 452 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp4); 453 if (ret < 0) { 454 printk("nf_conntrack_ipv4: can't register tcp.\n"); 455 goto cleanup_sockopt; 456 } 457 458 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp4); 459 if (ret < 0) { 460 printk("nf_conntrack_ipv4: can't register udp.\n"); 461 goto cleanup_tcp; 462 } 463 464 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmp); 465 if (ret < 0) { 466 printk("nf_conntrack_ipv4: can't register icmp.\n"); 467 goto cleanup_udp; 468 } 469 470 ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4); 471 if (ret < 0) { 472 printk("nf_conntrack_ipv4: can't register ipv4\n"); 473 goto cleanup_icmp; 474 } 475 476 ret = nf_register_hooks(ipv4_conntrack_ops, 477 ARRAY_SIZE(ipv4_conntrack_ops)); 478 if (ret < 0) { 479 printk("nf_conntrack_ipv4: can't register hooks.\n"); 480 goto cleanup_ipv4; 481 } 482#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) 483 ret = nf_conntrack_ipv4_compat_init(); 484 if (ret < 0) 485 goto cleanup_hooks; 486#endif 487 return ret; 488#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) 489 cleanup_hooks: 490 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 491#endif 492 cleanup_ipv4: 493 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 494 cleanup_icmp: 495 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); 496 cleanup_udp: 497 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); 498 cleanup_tcp: 499 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); 500 cleanup_sockopt: 501 nf_unregister_sockopt(&so_getorigdst); 502 return ret; 503} 504 505static void __exit nf_conntrack_l3proto_ipv4_fini(void) 506{ 507 synchronize_net(); 508#if defined(CONFIG_PROC_FS) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) 509 nf_conntrack_ipv4_compat_fini(); 510#endif 511 nf_unregister_hooks(ipv4_conntrack_ops, ARRAY_SIZE(ipv4_conntrack_ops)); 512 nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); 513 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmp); 514 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp4); 515 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp4); 516 nf_unregister_sockopt(&so_getorigdst); 517} 518 519module_init(nf_conntrack_l3proto_ipv4_init); 520module_exit(nf_conntrack_l3proto_ipv4_fini); 521