diff options
Diffstat (limited to 'net/ipv4')
33 files changed, 1225 insertions, 205 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index a9d84f93442c..eaa150c33b04 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -147,8 +147,7 @@ void inet_sock_destruct(struct sock *sk) | |||
| 147 | BUG_TRAP(!sk->sk_wmem_queued); | 147 | BUG_TRAP(!sk->sk_wmem_queued); |
| 148 | BUG_TRAP(!sk->sk_forward_alloc); | 148 | BUG_TRAP(!sk->sk_forward_alloc); |
| 149 | 149 | ||
| 150 | if (inet->opt) | 150 | kfree(inet->opt); |
| 151 | kfree(inet->opt); | ||
| 152 | dst_release(sk->sk_dst_cache); | 151 | dst_release(sk->sk_dst_cache); |
| 153 | sk_refcnt_debug_dec(sk); | 152 | sk_refcnt_debug_dec(sk); |
| 154 | } | 153 | } |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 990633c09dfe..2267c1fad879 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -266,8 +266,7 @@ int ip_rt_ioctl(unsigned int cmd, void __user *arg) | |||
| 266 | if (tb) | 266 | if (tb) |
| 267 | err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); | 267 | err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); |
| 268 | } | 268 | } |
| 269 | if (rta.rta_mx) | 269 | kfree(rta.rta_mx); |
| 270 | kfree(rta.rta_mx); | ||
| 271 | } | 270 | } |
| 272 | rtnl_unlock(); | 271 | rtnl_unlock(); |
| 273 | return err; | 272 | return err; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 94468a76c5b4..3fe021f1a566 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
| @@ -78,17 +78,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, | |||
| 78 | int low = sysctl_local_port_range[0]; | 78 | int low = sysctl_local_port_range[0]; |
| 79 | int high = sysctl_local_port_range[1]; | 79 | int high = sysctl_local_port_range[1]; |
| 80 | int remaining = (high - low) + 1; | 80 | int remaining = (high - low) + 1; |
| 81 | int rover; | 81 | int rover = net_random() % (high - low) + low; |
| 82 | 82 | ||
| 83 | spin_lock(&hashinfo->portalloc_lock); | ||
| 84 | if (hashinfo->port_rover < low) | ||
| 85 | rover = low; | ||
| 86 | else | ||
| 87 | rover = hashinfo->port_rover; | ||
| 88 | do { | 83 | do { |
| 89 | rover++; | ||
| 90 | if (rover > high) | ||
| 91 | rover = low; | ||
| 92 | head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; | 84 | head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)]; |
| 93 | spin_lock(&head->lock); | 85 | spin_lock(&head->lock); |
| 94 | inet_bind_bucket_for_each(tb, node, &head->chain) | 86 | inet_bind_bucket_for_each(tb, node, &head->chain) |
| @@ -97,9 +89,9 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo, | |||
| 97 | break; | 89 | break; |
| 98 | next: | 90 | next: |
| 99 | spin_unlock(&head->lock); | 91 | spin_unlock(&head->lock); |
| 92 | if (++rover > high) | ||
| 93 | rover = low; | ||
| 100 | } while (--remaining > 0); | 94 | } while (--remaining > 0); |
| 101 | hashinfo->port_rover = rover; | ||
| 102 | spin_unlock(&hashinfo->portalloc_lock); | ||
| 103 | 95 | ||
| 104 | /* Exhausted local port range during search? It is not | 96 | /* Exhausted local port range during search? It is not |
| 105 | * possible for us to be holding one of the bind hash | 97 | * possible for us to be holding one of the bind hash |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 71f3c7350c6e..39061ed53cfd 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -724,12 +724,6 @@ done: | |||
| 724 | return skb->len; | 724 | return skb->len; |
| 725 | } | 725 | } |
| 726 | 726 | ||
| 727 | static int inet_diag_dump_done(struct netlink_callback *cb) | ||
| 728 | { | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | |||
| 733 | static __inline__ int | 727 | static __inline__ int |
| 734 | inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 728 | inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 735 | { | 729 | { |
| @@ -760,8 +754,7 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 760 | goto err_inval; | 754 | goto err_inval; |
| 761 | } | 755 | } |
| 762 | return netlink_dump_start(idiagnl, skb, nlh, | 756 | return netlink_dump_start(idiagnl, skb, nlh, |
| 763 | inet_diag_dump, | 757 | inet_diag_dump, NULL); |
| 764 | inet_diag_dump_done); | ||
| 765 | } else { | 758 | } else { |
| 766 | return inet_diag_get_exact(skb, nlh); | 759 | return inet_diag_get_exact(skb, nlh); |
| 767 | } | 760 | } |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index bce4e875193b..dbe12da8d8b3 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
| @@ -510,8 +510,7 @@ static int ip_options_get_finish(struct ip_options **optp, | |||
| 510 | kfree(opt); | 510 | kfree(opt); |
| 511 | return -EINVAL; | 511 | return -EINVAL; |
| 512 | } | 512 | } |
| 513 | if (*optp) | 513 | kfree(*optp); |
| 514 | kfree(*optp); | ||
| 515 | *optp = opt; | 514 | *optp = opt; |
| 516 | return 0; | 515 | return 0; |
| 517 | } | 516 | } |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 17758234a3e3..11c2f68254f0 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -353,7 +353,8 @@ packet_routed: | |||
| 353 | ip_options_build(skb, opt, inet->daddr, rt, 0); | 353 | ip_options_build(skb, opt, inet->daddr, rt, 0); |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | ip_select_ident_more(iph, &rt->u.dst, sk, skb_shinfo(skb)->tso_segs); | 356 | ip_select_ident_more(iph, &rt->u.dst, sk, |
| 357 | (skb_shinfo(skb)->tso_segs ?: 1) - 1); | ||
| 357 | 358 | ||
| 358 | /* Add an IP checksum. */ | 359 | /* Add an IP checksum. */ |
| 359 | ip_send_check(iph); | 360 | ip_send_check(iph); |
| @@ -1262,10 +1263,8 @@ int ip_push_pending_frames(struct sock *sk) | |||
| 1262 | 1263 | ||
| 1263 | out: | 1264 | out: |
| 1264 | inet->cork.flags &= ~IPCORK_OPT; | 1265 | inet->cork.flags &= ~IPCORK_OPT; |
| 1265 | if (inet->cork.opt) { | 1266 | kfree(inet->cork.opt); |
| 1266 | kfree(inet->cork.opt); | 1267 | inet->cork.opt = NULL; |
| 1267 | inet->cork.opt = NULL; | ||
| 1268 | } | ||
| 1269 | if (inet->cork.rt) { | 1268 | if (inet->cork.rt) { |
| 1270 | ip_rt_put(inet->cork.rt); | 1269 | ip_rt_put(inet->cork.rt); |
| 1271 | inet->cork.rt = NULL; | 1270 | inet->cork.rt = NULL; |
| @@ -1289,10 +1288,8 @@ void ip_flush_pending_frames(struct sock *sk) | |||
| 1289 | kfree_skb(skb); | 1288 | kfree_skb(skb); |
| 1290 | 1289 | ||
| 1291 | inet->cork.flags &= ~IPCORK_OPT; | 1290 | inet->cork.flags &= ~IPCORK_OPT; |
| 1292 | if (inet->cork.opt) { | 1291 | kfree(inet->cork.opt); |
| 1293 | kfree(inet->cork.opt); | 1292 | inet->cork.opt = NULL; |
| 1294 | inet->cork.opt = NULL; | ||
| 1295 | } | ||
| 1296 | if (inet->cork.rt) { | 1293 | if (inet->cork.rt) { |
| 1297 | ip_rt_put(inet->cork.rt); | 1294 | ip_rt_put(inet->cork.rt); |
| 1298 | inet->cork.rt = NULL; | 1295 | inet->cork.rt = NULL; |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2f0b47da5b37..4f2d87257309 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -202,8 +202,7 @@ int ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct s | |||
| 202 | if (ra->sk == sk) { | 202 | if (ra->sk == sk) { |
| 203 | if (on) { | 203 | if (on) { |
| 204 | write_unlock_bh(&ip_ra_lock); | 204 | write_unlock_bh(&ip_ra_lock); |
| 205 | if (new_ra) | 205 | kfree(new_ra); |
| 206 | kfree(new_ra); | ||
| 207 | return -EADDRINUSE; | 206 | return -EADDRINUSE; |
| 208 | } | 207 | } |
| 209 | *rap = ra->next; | 208 | *rap = ra->next; |
| @@ -446,8 +445,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
| 446 | #endif | 445 | #endif |
| 447 | } | 446 | } |
| 448 | opt = xchg(&inet->opt, opt); | 447 | opt = xchg(&inet->opt, opt); |
| 449 | if (opt) | 448 | kfree(opt); |
| 450 | kfree(opt); | ||
| 451 | break; | 449 | break; |
| 452 | } | 450 | } |
| 453 | case IP_PKTINFO: | 451 | case IP_PKTINFO: |
| @@ -828,10 +826,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, | |||
| 828 | 826 | ||
| 829 | err = ip_mc_msfilter(sk, msf, ifindex); | 827 | err = ip_mc_msfilter(sk, msf, ifindex); |
| 830 | mc_msf_out: | 828 | mc_msf_out: |
| 831 | if (msf) | 829 | kfree(msf); |
| 832 | kfree(msf); | 830 | kfree(gsf); |
| 833 | if (gsf) | ||
| 834 | kfree(gsf); | ||
| 835 | break; | 831 | break; |
| 836 | } | 832 | } |
| 837 | case IP_ROUTER_ALERT: | 833 | case IP_ROUTER_ALERT: |
diff --git a/net/ipv4/ipvs/ip_vs_app.c b/net/ipv4/ipvs/ip_vs_app.c index fc6f95aaa969..d7eb680101c2 100644 --- a/net/ipv4/ipvs/ip_vs_app.c +++ b/net/ipv4/ipvs/ip_vs_app.c | |||
| @@ -110,8 +110,7 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port) | |||
| 110 | return 0; | 110 | return 0; |
| 111 | 111 | ||
| 112 | out: | 112 | out: |
| 113 | if (inc->timeout_table) | 113 | kfree(inc->timeout_table); |
| 114 | kfree(inc->timeout_table); | ||
| 115 | kfree(inc); | 114 | kfree(inc); |
| 116 | return ret; | 115 | return ret; |
| 117 | } | 116 | } |
| @@ -136,8 +135,7 @@ ip_vs_app_inc_release(struct ip_vs_app *inc) | |||
| 136 | 135 | ||
| 137 | list_del(&inc->a_list); | 136 | list_del(&inc->a_list); |
| 138 | 137 | ||
| 139 | if (inc->timeout_table != NULL) | 138 | kfree(inc->timeout_table); |
| 140 | kfree(inc->timeout_table); | ||
| 141 | kfree(inc); | 139 | kfree(inc); |
| 142 | } | 140 | } |
| 143 | 141 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 981cc3244ef2..1a0843cd58a9 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
| @@ -1009,11 +1009,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff **pskb, | |||
| 1009 | if (sysctl_ip_vs_expire_nodest_conn) { | 1009 | if (sysctl_ip_vs_expire_nodest_conn) { |
| 1010 | /* try to expire the connection immediately */ | 1010 | /* try to expire the connection immediately */ |
| 1011 | ip_vs_conn_expire_now(cp); | 1011 | ip_vs_conn_expire_now(cp); |
| 1012 | } else { | ||
| 1013 | /* don't restart its timer, and silently | ||
| 1014 | drop the packet. */ | ||
| 1015 | __ip_vs_conn_put(cp); | ||
| 1016 | } | 1012 | } |
| 1013 | /* don't restart its timer, and silently | ||
| 1014 | drop the packet. */ | ||
| 1015 | __ip_vs_conn_put(cp); | ||
| 1017 | return NF_DROP; | 1016 | return NF_DROP; |
| 1018 | } | 1017 | } |
| 1019 | 1018 | ||
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index bd7d75b6abe0..d34a9fa608e0 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c | |||
| @@ -207,16 +207,12 @@ static void wrandom_select_route(const struct flowi *flp, | |||
| 207 | decision = mpc->rt; | 207 | decision = mpc->rt; |
| 208 | 208 | ||
| 209 | last_power = mpc->power; | 209 | last_power = mpc->power; |
| 210 | if (last_mpc) | 210 | kfree(last_mpc); |
| 211 | kfree(last_mpc); | ||
| 212 | |||
| 213 | last_mpc = mpc; | 211 | last_mpc = mpc; |
| 214 | } | 212 | } |
| 215 | 213 | ||
| 216 | if (last_mpc) { | 214 | /* concurrent __multipath_flush may lead to !last_mpc */ |
| 217 | /* concurrent __multipath_flush may lead to !last_mpc */ | 215 | kfree(last_mpc); |
| 218 | kfree(last_mpc); | ||
| 219 | } | ||
| 220 | 216 | ||
| 221 | decision->u.dst.__use++; | 217 | decision->u.dst.__use++; |
| 222 | *rp = decision; | 218 | *rp = decision; |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 7d917e4ce1d9..9d3c8b5f327e 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
| @@ -5,6 +5,20 @@ | |||
| 5 | menu "IP: Netfilter Configuration" | 5 | menu "IP: Netfilter Configuration" |
| 6 | depends on INET && NETFILTER | 6 | depends on INET && NETFILTER |
| 7 | 7 | ||
| 8 | config NF_CONNTRACK_IPV4 | ||
| 9 | tristate "IPv4 support for new connection tracking (EXPERIMENTAL)" | ||
| 10 | depends on EXPERIMENTAL && NF_CONNTRACK | ||
| 11 | ---help--- | ||
| 12 | Connection tracking keeps a record of what packets have passed | ||
| 13 | through your machine, in order to figure out how they are related | ||
| 14 | into connections. | ||
| 15 | |||
| 16 | This is IPv4 support on Layer 3 independent connection tracking. | ||
| 17 | Layer 3 independent connection tracking is experimental scheme | ||
| 18 | which generalize ip_conntrack to support other layer 3 protocols. | ||
| 19 | |||
| 20 | To compile it as a module, choose M here. If unsure, say N. | ||
| 21 | |||
| 8 | # connection tracking, helpers and protocols | 22 | # connection tracking, helpers and protocols |
| 9 | config IP_NF_CONNTRACK | 23 | config IP_NF_CONNTRACK |
| 10 | tristate "Connection tracking (required for masq/NAT)" | 24 | tristate "Connection tracking (required for masq/NAT)" |
| @@ -209,8 +223,8 @@ config IP_NF_MATCH_PKTTYPE | |||
| 209 | tristate "Packet type match support" | 223 | tristate "Packet type match support" |
| 210 | depends on IP_NF_IPTABLES | 224 | depends on IP_NF_IPTABLES |
| 211 | help | 225 | help |
| 212 | Packet type matching allows you to match a packet by | 226 | Packet type matching allows you to match a packet by |
| 213 | its "class", eg. BROADCAST, MULTICAST, ... | 227 | its "class", eg. BROADCAST, MULTICAST, ... |
| 214 | 228 | ||
| 215 | Typical usage: | 229 | Typical usage: |
| 216 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG | 230 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG |
| @@ -317,7 +331,8 @@ config IP_NF_MATCH_TCPMSS | |||
| 317 | 331 | ||
| 318 | config IP_NF_MATCH_HELPER | 332 | config IP_NF_MATCH_HELPER |
| 319 | tristate "Helper match support" | 333 | tristate "Helper match support" |
| 320 | depends on IP_NF_CONNTRACK && IP_NF_IPTABLES | 334 | depends on IP_NF_IPTABLES |
| 335 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
| 321 | help | 336 | help |
| 322 | Helper matching allows you to match packets in dynamic connections | 337 | Helper matching allows you to match packets in dynamic connections |
| 323 | tracked by a conntrack-helper, ie. ip_conntrack_ftp | 338 | tracked by a conntrack-helper, ie. ip_conntrack_ftp |
| @@ -326,7 +341,8 @@ config IP_NF_MATCH_HELPER | |||
| 326 | 341 | ||
| 327 | config IP_NF_MATCH_STATE | 342 | config IP_NF_MATCH_STATE |
| 328 | tristate "Connection state match support" | 343 | tristate "Connection state match support" |
| 329 | depends on IP_NF_CONNTRACK && IP_NF_IPTABLES | 344 | depends on IP_NF_IPTABLES |
| 345 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
| 330 | help | 346 | help |
| 331 | Connection state matching allows you to match packets based on their | 347 | Connection state matching allows you to match packets based on their |
| 332 | relationship to a tracked connection (ie. previous packets). This | 348 | relationship to a tracked connection (ie. previous packets). This |
| @@ -336,7 +352,8 @@ config IP_NF_MATCH_STATE | |||
| 336 | 352 | ||
| 337 | config IP_NF_MATCH_CONNTRACK | 353 | config IP_NF_MATCH_CONNTRACK |
| 338 | tristate "Connection tracking match support" | 354 | tristate "Connection tracking match support" |
| 339 | depends on IP_NF_CONNTRACK && IP_NF_IPTABLES | 355 | depends on IP_NF_IPTABLES |
| 356 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
| 340 | help | 357 | help |
| 341 | This is a general conntrack match module, a superset of the state match. | 358 | This is a general conntrack match module, a superset of the state match. |
| 342 | 359 | ||
| @@ -422,7 +439,8 @@ config IP_NF_MATCH_COMMENT | |||
| 422 | 439 | ||
| 423 | config IP_NF_MATCH_CONNMARK | 440 | config IP_NF_MATCH_CONNMARK |
| 424 | tristate 'Connection mark match support' | 441 | tristate 'Connection mark match support' |
| 425 | depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES | 442 | depends on IP_NF_IPTABLES |
| 443 | depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
| 426 | help | 444 | help |
| 427 | This option adds a `connmark' match, which allows you to match the | 445 | This option adds a `connmark' match, which allows you to match the |
| 428 | connection mark value previously set for the session by `CONNMARK'. | 446 | connection mark value previously set for the session by `CONNMARK'. |
| @@ -433,7 +451,8 @@ config IP_NF_MATCH_CONNMARK | |||
| 433 | 451 | ||
| 434 | config IP_NF_MATCH_CONNBYTES | 452 | config IP_NF_MATCH_CONNBYTES |
| 435 | tristate 'Connection byte/packet counter match support' | 453 | tristate 'Connection byte/packet counter match support' |
| 436 | depends on IP_NF_CT_ACCT && IP_NF_IPTABLES | 454 | depends on IP_NF_IPTABLES |
| 455 | depends on IP_NF_CT_ACCT || (NF_CT_ACCT && NF_CONNTRACK_IPV4) | ||
| 437 | help | 456 | help |
| 438 | This option adds a `connbytes' match, which allows you to match the | 457 | This option adds a `connbytes' match, which allows you to match the |
| 439 | number of bytes and/or packets for each direction within a connection. | 458 | number of bytes and/or packets for each direction within a connection. |
| @@ -747,7 +766,8 @@ config IP_NF_TARGET_TTL | |||
| 747 | 766 | ||
| 748 | config IP_NF_TARGET_CONNMARK | 767 | config IP_NF_TARGET_CONNMARK |
| 749 | tristate 'CONNMARK target support' | 768 | tristate 'CONNMARK target support' |
| 750 | depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE | 769 | depends on IP_NF_MANGLE |
| 770 | depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
| 751 | help | 771 | help |
| 752 | This option adds a `CONNMARK' target, which allows one to manipulate | 772 | This option adds a `CONNMARK' target, which allows one to manipulate |
| 753 | the connection mark value. Similar to the MARK target, but | 773 | the connection mark value. Similar to the MARK target, but |
| @@ -759,7 +779,8 @@ config IP_NF_TARGET_CONNMARK | |||
| 759 | 779 | ||
| 760 | config IP_NF_TARGET_CLUSTERIP | 780 | config IP_NF_TARGET_CLUSTERIP |
| 761 | tristate "CLUSTERIP target support (EXPERIMENTAL)" | 781 | tristate "CLUSTERIP target support (EXPERIMENTAL)" |
| 762 | depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES && EXPERIMENTAL | 782 | depends on IP_NF_IPTABLES && EXPERIMENTAL |
| 783 | depends on IP_NF_CONNTRACK_MARK || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
| 763 | help | 784 | help |
| 764 | The CLUSTERIP target allows you to build load-balancing clusters of | 785 | The CLUSTERIP target allows you to build load-balancing clusters of |
| 765 | network servers without having a dedicated load-balancing | 786 | network servers without having a dedicated load-balancing |
| @@ -782,7 +803,7 @@ config IP_NF_RAW | |||
| 782 | config IP_NF_TARGET_NOTRACK | 803 | config IP_NF_TARGET_NOTRACK |
| 783 | tristate 'NOTRACK target support' | 804 | tristate 'NOTRACK target support' |
| 784 | depends on IP_NF_RAW | 805 | depends on IP_NF_RAW |
| 785 | depends on IP_NF_CONNTRACK | 806 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 |
| 786 | help | 807 | help |
| 787 | The NOTRACK target allows a select rule to specify | 808 | The NOTRACK target allows a select rule to specify |
| 788 | which packets *not* to enter the conntrack/NAT | 809 | which packets *not* to enter the conntrack/NAT |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index dab4b58dd31e..058c48e258fc 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
| @@ -103,3 +103,9 @@ obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o | |||
| 103 | obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o | 103 | obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o |
| 104 | 104 | ||
| 105 | obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o | 105 | obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o |
| 106 | |||
| 107 | # objects for l3 independent conntrack | ||
| 108 | nf_conntrack_ipv4-objs := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o | ||
| 109 | |||
| 110 | # l3 independent conntrack | ||
| 111 | obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index 926a6684643d..4108a5e12b3c 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c | |||
| @@ -270,14 +270,10 @@ exp_gre(struct ip_conntrack *master, | |||
| 270 | exp_orig->expectfn = pptp_expectfn; | 270 | exp_orig->expectfn = pptp_expectfn; |
| 271 | exp_orig->flags = 0; | 271 | exp_orig->flags = 0; |
| 272 | 272 | ||
| 273 | exp_orig->dir = IP_CT_DIR_ORIGINAL; | ||
| 274 | |||
| 275 | /* both expectations are identical apart from tuple */ | 273 | /* both expectations are identical apart from tuple */ |
| 276 | memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); | 274 | memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); |
| 277 | memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); | 275 | memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); |
| 278 | 276 | ||
| 279 | exp_reply->dir = !exp_orig->dir; | ||
| 280 | |||
| 281 | if (ip_nat_pptp_hook_exp_gre) | 277 | if (ip_nat_pptp_hook_exp_gre) |
| 282 | ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); | 278 | ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); |
| 283 | else { | 279 | else { |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 166e6069f121..d2a4fec22862 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
| @@ -28,11 +28,8 @@ | |||
| 28 | #include <linux/netlink.h> | 28 | #include <linux/netlink.h> |
| 29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
| 30 | #include <linux/notifier.h> | 30 | #include <linux/notifier.h> |
| 31 | #include <linux/rtnetlink.h> | ||
| 32 | 31 | ||
| 33 | #include <linux/netfilter.h> | 32 | #include <linux/netfilter.h> |
| 34 | #include <linux/netfilter_ipv4.h> | ||
| 35 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
| 36 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 33 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
| 37 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | 34 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> |
| 38 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | 35 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> |
| @@ -58,14 +55,17 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, | |||
| 58 | const struct ip_conntrack_tuple *tuple) | 55 | const struct ip_conntrack_tuple *tuple) |
| 59 | { | 56 | { |
| 60 | struct ip_conntrack_protocol *proto; | 57 | struct ip_conntrack_protocol *proto; |
| 58 | int ret = 0; | ||
| 61 | 59 | ||
| 62 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); | 60 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); |
| 63 | 61 | ||
| 64 | proto = ip_conntrack_proto_find_get(tuple->dst.protonum); | 62 | proto = ip_conntrack_proto_find_get(tuple->dst.protonum); |
| 65 | if (proto && proto->tuple_to_nfattr) | 63 | if (likely(proto && proto->tuple_to_nfattr)) { |
| 66 | return proto->tuple_to_nfattr(skb, tuple); | 64 | ret = proto->tuple_to_nfattr(skb, tuple); |
| 65 | ip_conntrack_proto_put(proto); | ||
| 66 | } | ||
| 67 | 67 | ||
| 68 | return 0; | 68 | return ret; |
| 69 | 69 | ||
| 70 | nfattr_failure: | 70 | nfattr_failure: |
| 71 | return -1; | 71 | return -1; |
| @@ -175,7 +175,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct, | |||
| 175 | { | 175 | { |
| 176 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; | 176 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; |
| 177 | struct nfattr *nest_count = NFA_NEST(skb, type); | 177 | struct nfattr *nest_count = NFA_NEST(skb, type); |
| 178 | u_int64_t tmp; | 178 | u_int32_t tmp; |
| 179 | 179 | ||
| 180 | tmp = htonl(ct->counters[dir].packets); | 180 | tmp = htonl(ct->counters[dir].packets); |
| 181 | NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); | 181 | NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); |
| @@ -479,9 +479,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) | |||
| 479 | 479 | ||
| 480 | DEBUGP("entered %s\n", __FUNCTION__); | 480 | DEBUGP("entered %s\n", __FUNCTION__); |
| 481 | 481 | ||
| 482 | 482 | nfattr_parse_nested(tb, CTA_IP_MAX, attr); | |
| 483 | if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0) | ||
| 484 | goto nfattr_failure; | ||
| 485 | 483 | ||
| 486 | if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) | 484 | if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) |
| 487 | return -EINVAL; | 485 | return -EINVAL; |
| @@ -497,9 +495,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) | |||
| 497 | DEBUGP("leaving\n"); | 495 | DEBUGP("leaving\n"); |
| 498 | 496 | ||
| 499 | return 0; | 497 | return 0; |
| 500 | |||
| 501 | nfattr_failure: | ||
| 502 | return -1; | ||
| 503 | } | 498 | } |
| 504 | 499 | ||
| 505 | static const int cta_min_proto[CTA_PROTO_MAX] = { | 500 | static const int cta_min_proto[CTA_PROTO_MAX] = { |
| @@ -521,8 +516,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, | |||
| 521 | 516 | ||
| 522 | DEBUGP("entered %s\n", __FUNCTION__); | 517 | DEBUGP("entered %s\n", __FUNCTION__); |
| 523 | 518 | ||
| 524 | if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0) | 519 | nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); |
| 525 | goto nfattr_failure; | ||
| 526 | 520 | ||
| 527 | if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) | 521 | if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) |
| 528 | return -EINVAL; | 522 | return -EINVAL; |
| @@ -539,9 +533,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, | |||
| 539 | } | 533 | } |
| 540 | 534 | ||
| 541 | return ret; | 535 | return ret; |
| 542 | |||
| 543 | nfattr_failure: | ||
| 544 | return -1; | ||
| 545 | } | 536 | } |
| 546 | 537 | ||
| 547 | static inline int | 538 | static inline int |
| @@ -555,8 +546,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, | |||
| 555 | 546 | ||
| 556 | memset(tuple, 0, sizeof(*tuple)); | 547 | memset(tuple, 0, sizeof(*tuple)); |
| 557 | 548 | ||
| 558 | if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0) | 549 | nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); |
| 559 | goto nfattr_failure; | ||
| 560 | 550 | ||
| 561 | if (!tb[CTA_TUPLE_IP-1]) | 551 | if (!tb[CTA_TUPLE_IP-1]) |
| 562 | return -EINVAL; | 552 | return -EINVAL; |
| @@ -583,9 +573,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, | |||
| 583 | DEBUGP("leaving\n"); | 573 | DEBUGP("leaving\n"); |
| 584 | 574 | ||
| 585 | return 0; | 575 | return 0; |
| 586 | |||
| 587 | nfattr_failure: | ||
| 588 | return -1; | ||
| 589 | } | 576 | } |
| 590 | 577 | ||
| 591 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 578 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
| @@ -603,11 +590,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, | |||
| 603 | 590 | ||
| 604 | DEBUGP("entered %s\n", __FUNCTION__); | 591 | DEBUGP("entered %s\n", __FUNCTION__); |
| 605 | 592 | ||
| 606 | if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0) | 593 | nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); |
| 607 | goto nfattr_failure; | ||
| 608 | 594 | ||
| 609 | if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) | 595 | if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) |
| 610 | goto nfattr_failure; | 596 | return -EINVAL; |
| 611 | 597 | ||
| 612 | npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); | 598 | npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); |
| 613 | if (!npt) | 599 | if (!npt) |
| @@ -626,9 +612,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, | |||
| 626 | 612 | ||
| 627 | DEBUGP("leaving\n"); | 613 | DEBUGP("leaving\n"); |
| 628 | return 0; | 614 | return 0; |
| 629 | |||
| 630 | nfattr_failure: | ||
| 631 | return -1; | ||
| 632 | } | 615 | } |
| 633 | 616 | ||
| 634 | static inline int | 617 | static inline int |
| @@ -642,8 +625,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], | |||
| 642 | 625 | ||
| 643 | memset(range, 0, sizeof(*range)); | 626 | memset(range, 0, sizeof(*range)); |
| 644 | 627 | ||
| 645 | if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0) | 628 | nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); |
| 646 | goto nfattr_failure; | ||
| 647 | 629 | ||
| 648 | if (tb[CTA_NAT_MINIP-1]) | 630 | if (tb[CTA_NAT_MINIP-1]) |
| 649 | range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); | 631 | range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); |
| @@ -665,9 +647,6 @@ ctnetlink_parse_nat(struct nfattr *cda[], | |||
| 665 | 647 | ||
| 666 | DEBUGP("leaving\n"); | 648 | DEBUGP("leaving\n"); |
| 667 | return 0; | 649 | return 0; |
| 668 | |||
| 669 | nfattr_failure: | ||
| 670 | return -1; | ||
| 671 | } | 650 | } |
| 672 | #endif | 651 | #endif |
| 673 | 652 | ||
| @@ -678,8 +657,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) | |||
| 678 | 657 | ||
| 679 | DEBUGP("entered %s\n", __FUNCTION__); | 658 | DEBUGP("entered %s\n", __FUNCTION__); |
| 680 | 659 | ||
| 681 | if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0) | 660 | nfattr_parse_nested(tb, CTA_HELP_MAX, attr); |
| 682 | goto nfattr_failure; | ||
| 683 | 661 | ||
| 684 | if (!tb[CTA_HELP_NAME-1]) | 662 | if (!tb[CTA_HELP_NAME-1]) |
| 685 | return -EINVAL; | 663 | return -EINVAL; |
| @@ -687,9 +665,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) | |||
| 687 | *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); | 665 | *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); |
| 688 | 666 | ||
| 689 | return 0; | 667 | return 0; |
| 690 | |||
| 691 | nfattr_failure: | ||
| 692 | return -1; | ||
| 693 | } | 668 | } |
| 694 | 669 | ||
| 695 | static int | 670 | static int |
| @@ -804,7 +779,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 804 | ct = tuplehash_to_ctrack(h); | 779 | ct = tuplehash_to_ctrack(h); |
| 805 | 780 | ||
| 806 | err = -ENOMEM; | 781 | err = -ENOMEM; |
| 807 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); | 782 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 808 | if (!skb2) { | 783 | if (!skb2) { |
| 809 | ip_conntrack_put(ct); | 784 | ip_conntrack_put(ct); |
| 810 | return -ENOMEM; | 785 | return -ENOMEM; |
| @@ -815,7 +790,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 815 | IPCTNL_MSG_CT_NEW, 1, ct); | 790 | IPCTNL_MSG_CT_NEW, 1, ct); |
| 816 | ip_conntrack_put(ct); | 791 | ip_conntrack_put(ct); |
| 817 | if (err <= 0) | 792 | if (err <= 0) |
| 818 | goto out; | 793 | goto free; |
| 819 | 794 | ||
| 820 | err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); | 795 | err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); |
| 821 | if (err < 0) | 796 | if (err < 0) |
| @@ -824,10 +799,10 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 824 | DEBUGP("leaving\n"); | 799 | DEBUGP("leaving\n"); |
| 825 | return 0; | 800 | return 0; |
| 826 | 801 | ||
| 802 | free: | ||
| 803 | kfree_skb(skb2); | ||
| 827 | out: | 804 | out: |
| 828 | if (skb2) | 805 | return err; |
| 829 | kfree_skb(skb2); | ||
| 830 | return -1; | ||
| 831 | } | 806 | } |
| 832 | 807 | ||
| 833 | static inline int | 808 | static inline int |
| @@ -957,8 +932,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) | |||
| 957 | u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; | 932 | u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; |
| 958 | int err = 0; | 933 | int err = 0; |
| 959 | 934 | ||
| 960 | if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) | 935 | nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); |
| 961 | goto nfattr_failure; | ||
| 962 | 936 | ||
| 963 | proto = ip_conntrack_proto_find_get(npt); | 937 | proto = ip_conntrack_proto_find_get(npt); |
| 964 | if (!proto) | 938 | if (!proto) |
| @@ -969,9 +943,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) | |||
| 969 | ip_conntrack_proto_put(proto); | 943 | ip_conntrack_proto_put(proto); |
| 970 | 944 | ||
| 971 | return err; | 945 | return err; |
| 972 | |||
| 973 | nfattr_failure: | ||
| 974 | return -ENOMEM; | ||
| 975 | } | 946 | } |
| 976 | 947 | ||
| 977 | static int | 948 | static int |
| @@ -1005,6 +976,11 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) | |||
| 1005 | return err; | 976 | return err; |
| 1006 | } | 977 | } |
| 1007 | 978 | ||
| 979 | #if defined(CONFIG_IP_NF_CONNTRACK_MARK) | ||
| 980 | if (cda[CTA_MARK-1]) | ||
| 981 | ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); | ||
| 982 | #endif | ||
| 983 | |||
| 1008 | DEBUGP("all done\n"); | 984 | DEBUGP("all done\n"); |
| 1009 | return 0; | 985 | return 0; |
| 1010 | } | 986 | } |
| @@ -1048,6 +1024,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[], | |||
| 1048 | if (ct->helper) | 1024 | if (ct->helper) |
| 1049 | ip_conntrack_helper_put(ct->helper); | 1025 | ip_conntrack_helper_put(ct->helper); |
| 1050 | 1026 | ||
| 1027 | #if defined(CONFIG_IP_NF_CONNTRACK_MARK) | ||
| 1028 | if (cda[CTA_MARK-1]) | ||
| 1029 | ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); | ||
| 1030 | #endif | ||
| 1031 | |||
| 1051 | DEBUGP("conntrack with id %u inserted\n", ct->id); | 1032 | DEBUGP("conntrack with id %u inserted\n", ct->id); |
| 1052 | return 0; | 1033 | return 0; |
| 1053 | 1034 | ||
| @@ -1312,6 +1293,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1312 | if (!exp) | 1293 | if (!exp) |
| 1313 | return -ENOENT; | 1294 | return -ENOENT; |
| 1314 | 1295 | ||
| 1296 | if (cda[CTA_EXPECT_ID-1]) { | ||
| 1297 | u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); | ||
| 1298 | if (exp->id != ntohl(id)) { | ||
| 1299 | ip_conntrack_expect_put(exp); | ||
| 1300 | return -ENOENT; | ||
| 1301 | } | ||
| 1302 | } | ||
| 1303 | |||
| 1315 | err = -ENOMEM; | 1304 | err = -ENOMEM; |
| 1316 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 1305 | skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 1317 | if (!skb2) | 1306 | if (!skb2) |
| @@ -1322,21 +1311,16 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1322 | nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, | 1311 | nlh->nlmsg_seq, IPCTNL_MSG_EXP_NEW, |
| 1323 | 1, exp); | 1312 | 1, exp); |
| 1324 | if (err <= 0) | 1313 | if (err <= 0) |
| 1325 | goto out; | 1314 | goto free; |
| 1326 | 1315 | ||
| 1327 | ip_conntrack_expect_put(exp); | 1316 | ip_conntrack_expect_put(exp); |
| 1328 | 1317 | ||
| 1329 | err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); | 1318 | return netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); |
| 1330 | if (err < 0) | ||
| 1331 | goto free; | ||
| 1332 | |||
| 1333 | return err; | ||
| 1334 | 1319 | ||
| 1320 | free: | ||
| 1321 | kfree_skb(skb2); | ||
| 1335 | out: | 1322 | out: |
| 1336 | ip_conntrack_expect_put(exp); | 1323 | ip_conntrack_expect_put(exp); |
| 1337 | free: | ||
| 1338 | if (skb2) | ||
| 1339 | kfree_skb(skb2); | ||
| 1340 | return err; | 1324 | return err; |
| 1341 | } | 1325 | } |
| 1342 | 1326 | ||
| @@ -1392,7 +1376,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1392 | ip_conntrack_expect_put(exp); | 1376 | ip_conntrack_expect_put(exp); |
| 1393 | } | 1377 | } |
| 1394 | } | 1378 | } |
| 1395 | write_unlock(&ip_conntrack_lock); | 1379 | write_unlock_bh(&ip_conntrack_lock); |
| 1396 | } else { | 1380 | } else { |
| 1397 | /* This basically means we have to flush everything*/ | 1381 | /* This basically means we have to flush everything*/ |
| 1398 | write_lock_bh(&ip_conntrack_lock); | 1382 | write_lock_bh(&ip_conntrack_lock); |
| @@ -1559,6 +1543,8 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { | |||
| 1559 | .cb = ctnl_exp_cb, | 1543 | .cb = ctnl_exp_cb, |
| 1560 | }; | 1544 | }; |
| 1561 | 1545 | ||
| 1546 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); | ||
| 1547 | |||
| 1562 | static int __init ctnetlink_init(void) | 1548 | static int __init ctnetlink_init(void) |
| 1563 | { | 1549 | { |
| 1564 | int ret; | 1550 | int ret; |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 98f0015dd255..5198f3a1e2cd 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c | |||
| @@ -151,13 +151,13 @@ icmp_error_message(struct sk_buff *skb, | |||
| 151 | /* Not enough header? */ | 151 | /* Not enough header? */ |
| 152 | inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); | 152 | inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); |
| 153 | if (inside == NULL) | 153 | if (inside == NULL) |
| 154 | return NF_ACCEPT; | 154 | return -NF_ACCEPT; |
| 155 | 155 | ||
| 156 | /* Ignore ICMP's containing fragments (shouldn't happen) */ | 156 | /* Ignore ICMP's containing fragments (shouldn't happen) */ |
| 157 | if (inside->ip.frag_off & htons(IP_OFFSET)) { | 157 | if (inside->ip.frag_off & htons(IP_OFFSET)) { |
| 158 | DEBUGP("icmp_error_track: fragment of proto %u\n", | 158 | DEBUGP("icmp_error_track: fragment of proto %u\n", |
| 159 | inside->ip.protocol); | 159 | inside->ip.protocol); |
| 160 | return NF_ACCEPT; | 160 | return -NF_ACCEPT; |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); | 163 | innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); |
| @@ -166,7 +166,7 @@ icmp_error_message(struct sk_buff *skb, | |||
| 166 | if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { | 166 | if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { |
| 167 | DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); | 167 | DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); |
| 168 | ip_conntrack_proto_put(innerproto); | 168 | ip_conntrack_proto_put(innerproto); |
| 169 | return NF_ACCEPT; | 169 | return -NF_ACCEPT; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | 172 | /* Ordinarily, we'd expect the inverted tupleproto, but it's |
| @@ -174,7 +174,7 @@ icmp_error_message(struct sk_buff *skb, | |||
| 174 | if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { | 174 | if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { |
| 175 | DEBUGP("icmp_error_track: Can't invert tuple\n"); | 175 | DEBUGP("icmp_error_track: Can't invert tuple\n"); |
| 176 | ip_conntrack_proto_put(innerproto); | 176 | ip_conntrack_proto_put(innerproto); |
| 177 | return NF_ACCEPT; | 177 | return -NF_ACCEPT; |
| 178 | } | 178 | } |
| 179 | ip_conntrack_proto_put(innerproto); | 179 | ip_conntrack_proto_put(innerproto); |
| 180 | 180 | ||
| @@ -190,7 +190,7 @@ icmp_error_message(struct sk_buff *skb, | |||
| 190 | 190 | ||
| 191 | if (!h) { | 191 | if (!h) { |
| 192 | DEBUGP("icmp_error_track: no match\n"); | 192 | DEBUGP("icmp_error_track: no match\n"); |
| 193 | return NF_ACCEPT; | 193 | return -NF_ACCEPT; |
| 194 | } | 194 | } |
| 195 | /* Reverse direction from that found */ | 195 | /* Reverse direction from that found */ |
| 196 | if (DIRECTION(h) != IP_CT_DIR_REPLY) | 196 | if (DIRECTION(h) != IP_CT_DIR_REPLY) |
| @@ -296,7 +296,8 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], | |||
| 296 | struct ip_conntrack_tuple *tuple) | 296 | struct ip_conntrack_tuple *tuple) |
| 297 | { | 297 | { |
| 298 | if (!tb[CTA_PROTO_ICMP_TYPE-1] | 298 | if (!tb[CTA_PROTO_ICMP_TYPE-1] |
| 299 | || !tb[CTA_PROTO_ICMP_CODE-1]) | 299 | || !tb[CTA_PROTO_ICMP_CODE-1] |
| 300 | || !tb[CTA_PROTO_ICMP_ID-1]) | ||
| 300 | return -1; | 301 | return -1; |
| 301 | 302 | ||
| 302 | tuple->dst.u.icmp.type = | 303 | tuple->dst.u.icmp.type = |
| @@ -304,7 +305,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], | |||
| 304 | tuple->dst.u.icmp.code = | 305 | tuple->dst.u.icmp.code = |
| 305 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); | 306 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); |
| 306 | tuple->src.u.icmp.id = | 307 | tuple->src.u.icmp.id = |
| 307 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); | 308 | *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); |
| 308 | 309 | ||
| 309 | return 0; | 310 | return 0; |
| 310 | } | 311 | } |
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index d6701cafbcc2..468c6003b4c7 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c | |||
| @@ -362,8 +362,12 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) | |||
| 362 | struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; | 362 | struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; |
| 363 | struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; | 363 | struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; |
| 364 | 364 | ||
| 365 | if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) | 365 | /* updates could not contain anything about the private |
| 366 | goto nfattr_failure; | 366 | * protocol info, in that case skip the parsing */ |
| 367 | if (!attr) | ||
| 368 | return 0; | ||
| 369 | |||
| 370 | nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); | ||
| 367 | 371 | ||
| 368 | if (!tb[CTA_PROTOINFO_TCP_STATE-1]) | 372 | if (!tb[CTA_PROTOINFO_TCP_STATE-1]) |
| 369 | return -EINVAL; | 373 | return -EINVAL; |
| @@ -374,9 +378,6 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) | |||
| 374 | write_unlock_bh(&tcp_lock); | 378 | write_unlock_bh(&tcp_lock); |
| 375 | 379 | ||
| 376 | return 0; | 380 | return 0; |
| 377 | |||
| 378 | nfattr_failure: | ||
| 379 | return -1; | ||
| 380 | } | 381 | } |
| 381 | #endif | 382 | #endif |
| 382 | 383 | ||
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c5e3abd24672..762f4d93936b 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c | |||
| @@ -66,10 +66,8 @@ ip_nat_proto_find_get(u_int8_t protonum) | |||
| 66 | * removed until we've grabbed the reference */ | 66 | * removed until we've grabbed the reference */ |
| 67 | preempt_disable(); | 67 | preempt_disable(); |
| 68 | p = __ip_nat_proto_find(protonum); | 68 | p = __ip_nat_proto_find(protonum); |
| 69 | if (p) { | 69 | if (!try_module_get(p->me)) |
| 70 | if (!try_module_get(p->me)) | 70 | p = &ip_nat_unknown_protocol; |
| 71 | p = &ip_nat_unknown_protocol; | ||
| 72 | } | ||
| 73 | preempt_enable(); | 71 | preempt_enable(); |
| 74 | 72 | ||
| 75 | return p; | 73 | return p; |
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index 3cdd0684d30d..e546203f5662 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c | |||
| @@ -73,6 +73,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct, | |||
| 73 | struct ip_conntrack_tuple t; | 73 | struct ip_conntrack_tuple t; |
| 74 | struct ip_ct_pptp_master *ct_pptp_info; | 74 | struct ip_ct_pptp_master *ct_pptp_info; |
| 75 | struct ip_nat_pptp *nat_pptp_info; | 75 | struct ip_nat_pptp *nat_pptp_info; |
| 76 | struct ip_nat_range range; | ||
| 76 | 77 | ||
| 77 | ct_pptp_info = &master->help.ct_pptp_info; | 78 | ct_pptp_info = &master->help.ct_pptp_info; |
| 78 | nat_pptp_info = &master->nat.help.nat_pptp_info; | 79 | nat_pptp_info = &master->nat.help.nat_pptp_info; |
| @@ -110,7 +111,30 @@ static void pptp_nat_expected(struct ip_conntrack *ct, | |||
| 110 | DEBUGP("not found!\n"); | 111 | DEBUGP("not found!\n"); |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | ip_nat_follow_master(ct, exp); | 114 | /* This must be a fresh one. */ |
| 115 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | ||
| 116 | |||
| 117 | /* Change src to where master sends to */ | ||
| 118 | range.flags = IP_NAT_RANGE_MAP_IPS; | ||
| 119 | range.min_ip = range.max_ip | ||
| 120 | = ct->master->tuplehash[!exp->dir].tuple.dst.ip; | ||
| 121 | if (exp->dir == IP_CT_DIR_ORIGINAL) { | ||
| 122 | range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | ||
| 123 | range.min = range.max = exp->saved_proto; | ||
| 124 | } | ||
| 125 | /* hook doesn't matter, but it has to do source manip */ | ||
| 126 | ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); | ||
| 127 | |||
| 128 | /* For DST manip, map port here to where it's expected. */ | ||
| 129 | range.flags = IP_NAT_RANGE_MAP_IPS; | ||
| 130 | range.min_ip = range.max_ip | ||
| 131 | = ct->master->tuplehash[!exp->dir].tuple.src.ip; | ||
| 132 | if (exp->dir == IP_CT_DIR_REPLY) { | ||
| 133 | range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | ||
| 134 | range.min = range.max = exp->saved_proto; | ||
| 135 | } | ||
| 136 | /* hook doesn't matter, but it has to do destination manip */ | ||
| 137 | ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); | ||
| 114 | } | 138 | } |
| 115 | 139 | ||
| 116 | /* outbound packets == from PNS to PAC */ | 140 | /* outbound packets == from PNS to PAC */ |
| @@ -213,9 +237,10 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, | |||
| 213 | 237 | ||
| 214 | /* alter expectation for PNS->PAC direction */ | 238 | /* alter expectation for PNS->PAC direction */ |
| 215 | invert_tuplepr(&inv_t, &expect_orig->tuple); | 239 | invert_tuplepr(&inv_t, &expect_orig->tuple); |
| 216 | expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); | 240 | expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id); |
| 217 | expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); | 241 | expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); |
| 218 | expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); | 242 | expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); |
| 243 | expect_orig->dir = IP_CT_DIR_ORIGINAL; | ||
| 219 | inv_t.src.ip = reply_t->src.ip; | 244 | inv_t.src.ip = reply_t->src.ip; |
| 220 | inv_t.dst.ip = reply_t->dst.ip; | 245 | inv_t.dst.ip = reply_t->dst.ip; |
| 221 | inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); | 246 | inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); |
| @@ -233,6 +258,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, | |||
| 233 | expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); | 258 | expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); |
| 234 | expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); | 259 | expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); |
| 235 | expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); | 260 | expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); |
| 261 | expect_reply->dir = IP_CT_DIR_REPLY; | ||
| 236 | inv_t.src.ip = orig_t->src.ip; | 262 | inv_t.src.ip = orig_t->src.ip; |
| 237 | inv_t.dst.ip = orig_t->dst.ip; | 263 | inv_t.dst.ip = orig_t->dst.ip; |
| 238 | inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); | 264 | inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); |
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c index 7c1285401672..f7cad7cf1aec 100644 --- a/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c | |||
| @@ -139,8 +139,8 @@ gre_manip_pkt(struct sk_buff **pskb, | |||
| 139 | break; | 139 | break; |
| 140 | case GRE_VERSION_PPTP: | 140 | case GRE_VERSION_PPTP: |
| 141 | DEBUGP("call_id -> 0x%04x\n", | 141 | DEBUGP("call_id -> 0x%04x\n", |
| 142 | ntohl(tuple->dst.u.gre.key)); | 142 | ntohs(tuple->dst.u.gre.key)); |
| 143 | pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key)); | 143 | pgreh->call_id = tuple->dst.u.gre.key; |
| 144 | break; | 144 | break; |
| 145 | default: | 145 | default: |
| 146 | DEBUGP("can't nat unknown GRE version\n"); | 146 | DEBUGP("can't nat unknown GRE version\n"); |
diff --git a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c index 99bbef56f84e..f0099a646a0b 100644 --- a/net/ipv4/netfilter/ip_nat_proto_unknown.c +++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c | |||
| @@ -62,7 +62,7 @@ unknown_print_range(char *buffer, const struct ip_nat_range *range) | |||
| 62 | 62 | ||
| 63 | struct ip_nat_protocol ip_nat_unknown_protocol = { | 63 | struct ip_nat_protocol ip_nat_unknown_protocol = { |
| 64 | .name = "unknown", | 64 | .name = "unknown", |
| 65 | .me = THIS_MODULE, | 65 | /* .me isn't set: getting a ref to this cannot fail. */ |
| 66 | .manip_pkt = unknown_manip_pkt, | 66 | .manip_pkt = unknown_manip_pkt, |
| 67 | .in_range = unknown_in_range, | 67 | .in_range = unknown_in_range, |
| 68 | .unique_tuple = unknown_unique_tuple, | 68 | .unique_tuple = unknown_unique_tuple, |
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index 93b2c5111bb2..8acb7ed40b47 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c | |||
| @@ -1161,8 +1161,7 @@ static int snmp_parse_mangle(unsigned char *msg, | |||
| 1161 | 1161 | ||
| 1162 | if (!snmp_object_decode(&ctx, obj)) { | 1162 | if (!snmp_object_decode(&ctx, obj)) { |
| 1163 | if (*obj) { | 1163 | if (*obj) { |
| 1164 | if ((*obj)->id) | 1164 | kfree((*obj)->id); |
| 1165 | kfree((*obj)->id); | ||
| 1166 | kfree(*obj); | 1165 | kfree(*obj); |
| 1167 | } | 1166 | } |
| 1168 | kfree(obj); | 1167 | kfree(obj); |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 9bcb398fbc1f..45c52d8f4d99 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | #include <linux/netfilter_ipv4/ip_tables.h> | 30 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 31 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> | 31 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> |
| 32 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 32 | #include <net/netfilter/nf_conntrack_compat.h> |
| 33 | 33 | ||
| 34 | #define CLUSTERIP_VERSION "0.8" | 34 | #define CLUSTERIP_VERSION "0.8" |
| 35 | 35 | ||
| @@ -316,14 +316,14 @@ target(struct sk_buff **pskb, | |||
| 316 | { | 316 | { |
| 317 | const struct ipt_clusterip_tgt_info *cipinfo = targinfo; | 317 | const struct ipt_clusterip_tgt_info *cipinfo = targinfo; |
| 318 | enum ip_conntrack_info ctinfo; | 318 | enum ip_conntrack_info ctinfo; |
| 319 | struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); | 319 | u_int32_t *mark, hash; |
| 320 | u_int32_t hash; | ||
| 321 | 320 | ||
| 322 | /* don't need to clusterip_config_get() here, since refcount | 321 | /* don't need to clusterip_config_get() here, since refcount |
| 323 | * is only decremented by destroy() - and ip_tables guarantees | 322 | * is only decremented by destroy() - and ip_tables guarantees |
| 324 | * that the ->target() function isn't called after ->destroy() */ | 323 | * that the ->target() function isn't called after ->destroy() */ |
| 325 | 324 | ||
| 326 | if (!ct) { | 325 | mark = nf_ct_get_mark((*pskb), &ctinfo); |
| 326 | if (mark == NULL) { | ||
| 327 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); | 327 | printk(KERN_ERR "CLUSTERIP: no conntrack!\n"); |
| 328 | /* FIXME: need to drop invalid ones, since replies | 328 | /* FIXME: need to drop invalid ones, since replies |
| 329 | * to outgoing connections of other nodes will be | 329 | * to outgoing connections of other nodes will be |
| @@ -346,7 +346,7 @@ target(struct sk_buff **pskb, | |||
| 346 | 346 | ||
| 347 | switch (ctinfo) { | 347 | switch (ctinfo) { |
| 348 | case IP_CT_NEW: | 348 | case IP_CT_NEW: |
| 349 | ct->mark = hash; | 349 | *mark = hash; |
| 350 | break; | 350 | break; |
| 351 | case IP_CT_RELATED: | 351 | case IP_CT_RELATED: |
| 352 | case IP_CT_RELATED+IP_CT_IS_REPLY: | 352 | case IP_CT_RELATED+IP_CT_IS_REPLY: |
| @@ -363,7 +363,7 @@ target(struct sk_buff **pskb, | |||
| 363 | #ifdef DEBUG_CLUSTERP | 363 | #ifdef DEBUG_CLUSTERP |
| 364 | DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 364 | DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
| 365 | #endif | 365 | #endif |
| 366 | DEBUGP("hash=%u ct_hash=%u ", hash, ct->mark); | 366 | DEBUGP("hash=%u ct_hash=%u ", hash, *mark); |
| 367 | if (!clusterip_responsible(cipinfo->config, hash)) { | 367 | if (!clusterip_responsible(cipinfo->config, hash)) { |
| 368 | DEBUGP("not responsible\n"); | 368 | DEBUGP("not responsible\n"); |
| 369 | return NF_DROP; | 369 | return NF_DROP; |
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c index 134638021339..8acac5a40a92 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/ipv4/netfilter/ipt_CONNMARK.c | |||
| @@ -29,7 +29,7 @@ MODULE_LICENSE("GPL"); | |||
| 29 | 29 | ||
| 30 | #include <linux/netfilter_ipv4/ip_tables.h> | 30 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 31 | #include <linux/netfilter_ipv4/ipt_CONNMARK.h> | 31 | #include <linux/netfilter_ipv4/ipt_CONNMARK.h> |
| 32 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 32 | #include <net/netfilter/nf_conntrack_compat.h> |
| 33 | 33 | ||
| 34 | static unsigned int | 34 | static unsigned int |
| 35 | target(struct sk_buff **pskb, | 35 | target(struct sk_buff **pskb, |
| @@ -43,24 +43,24 @@ target(struct sk_buff **pskb, | |||
| 43 | u_int32_t diff; | 43 | u_int32_t diff; |
| 44 | u_int32_t nfmark; | 44 | u_int32_t nfmark; |
| 45 | u_int32_t newmark; | 45 | u_int32_t newmark; |
| 46 | u_int32_t ctinfo; | ||
| 47 | u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); | ||
| 46 | 48 | ||
| 47 | enum ip_conntrack_info ctinfo; | 49 | if (ctmark) { |
| 48 | struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo); | ||
| 49 | if (ct) { | ||
| 50 | switch(markinfo->mode) { | 50 | switch(markinfo->mode) { |
| 51 | case IPT_CONNMARK_SET: | 51 | case IPT_CONNMARK_SET: |
| 52 | newmark = (ct->mark & ~markinfo->mask) | markinfo->mark; | 52 | newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; |
| 53 | if (newmark != ct->mark) | 53 | if (newmark != *ctmark) |
| 54 | ct->mark = newmark; | 54 | *ctmark = newmark; |
| 55 | break; | 55 | break; |
| 56 | case IPT_CONNMARK_SAVE: | 56 | case IPT_CONNMARK_SAVE: |
| 57 | newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); | 57 | newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); |
| 58 | if (ct->mark != newmark) | 58 | if (*ctmark != newmark) |
| 59 | ct->mark = newmark; | 59 | *ctmark = newmark; |
| 60 | break; | 60 | break; |
| 61 | case IPT_CONNMARK_RESTORE: | 61 | case IPT_CONNMARK_RESTORE: |
| 62 | nfmark = (*pskb)->nfmark; | 62 | nfmark = (*pskb)->nfmark; |
| 63 | diff = (ct->mark ^ nfmark) & markinfo->mask; | 63 | diff = (*ctmark ^ nfmark) & markinfo->mask; |
| 64 | if (diff != 0) | 64 | if (diff != 0) |
| 65 | (*pskb)->nfmark = nfmark ^ diff; | 65 | (*pskb)->nfmark = nfmark ^ diff; |
| 66 | break; | 66 | break; |
| @@ -109,6 +109,7 @@ static struct ipt_target ipt_connmark_reg = { | |||
| 109 | 109 | ||
| 110 | static int __init init(void) | 110 | static int __init init(void) |
| 111 | { | 111 | { |
| 112 | need_ip_conntrack(); | ||
| 112 | return ipt_register_target(&ipt_connmark_reg); | 113 | return ipt_register_target(&ipt_connmark_reg); |
| 113 | } | 114 | } |
| 114 | 115 | ||
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/ipv4/netfilter/ipt_NOTRACK.c index a4bb9b3bc292..e3c69d072c6e 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/ipv4/netfilter/ipt_NOTRACK.c | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
| 6 | 6 | ||
| 7 | #include <linux/netfilter_ipv4/ip_tables.h> | 7 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 8 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 8 | #include <net/netfilter/nf_conntrack_compat.h> |
| 9 | 9 | ||
| 10 | static unsigned int | 10 | static unsigned int |
| 11 | target(struct sk_buff **pskb, | 11 | target(struct sk_buff **pskb, |
| @@ -23,7 +23,7 @@ target(struct sk_buff **pskb, | |||
| 23 | If there is a real ct entry correspondig to this packet, | 23 | If there is a real ct entry correspondig to this packet, |
| 24 | it'll hang aroun till timing out. We don't deal with it | 24 | it'll hang aroun till timing out. We don't deal with it |
| 25 | for performance reasons. JK */ | 25 | for performance reasons. JK */ |
| 26 | (*pskb)->nfct = &ip_conntrack_untracked.ct_general; | 26 | nf_ct_untrack(*pskb); |
| 27 | (*pskb)->nfctinfo = IP_CT_NEW; | 27 | (*pskb)->nfctinfo = IP_CT_NEW; |
| 28 | nf_conntrack_get((*pskb)->nfct); | 28 | nf_conntrack_get((*pskb)->nfct); |
| 29 | 29 | ||
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/ipv4/netfilter/ipt_connbytes.c index df4a42c6da22..d68a048b7176 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/ipv4/netfilter/ipt_connbytes.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
| 13 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 13 | #include <net/netfilter/nf_conntrack_compat.h> |
| 14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 15 | #include <linux/netfilter_ipv4/ipt_connbytes.h> | 15 | #include <linux/netfilter_ipv4/ipt_connbytes.h> |
| 16 | 16 | ||
| @@ -46,60 +46,59 @@ match(const struct sk_buff *skb, | |||
| 46 | int *hotdrop) | 46 | int *hotdrop) |
| 47 | { | 47 | { |
| 48 | const struct ipt_connbytes_info *sinfo = matchinfo; | 48 | const struct ipt_connbytes_info *sinfo = matchinfo; |
| 49 | enum ip_conntrack_info ctinfo; | ||
| 50 | struct ip_conntrack *ct; | ||
| 51 | u_int64_t what = 0; /* initialize to make gcc happy */ | 49 | u_int64_t what = 0; /* initialize to make gcc happy */ |
| 50 | const struct ip_conntrack_counter *counters; | ||
| 52 | 51 | ||
| 53 | if (!(ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo))) | 52 | if (!(counters = nf_ct_get_counters(skb))) |
| 54 | return 0; /* no match */ | 53 | return 0; /* no match */ |
| 55 | 54 | ||
| 56 | switch (sinfo->what) { | 55 | switch (sinfo->what) { |
| 57 | case IPT_CONNBYTES_PKTS: | 56 | case IPT_CONNBYTES_PKTS: |
| 58 | switch (sinfo->direction) { | 57 | switch (sinfo->direction) { |
| 59 | case IPT_CONNBYTES_DIR_ORIGINAL: | 58 | case IPT_CONNBYTES_DIR_ORIGINAL: |
| 60 | what = ct->counters[IP_CT_DIR_ORIGINAL].packets; | 59 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
| 61 | break; | 60 | break; |
| 62 | case IPT_CONNBYTES_DIR_REPLY: | 61 | case IPT_CONNBYTES_DIR_REPLY: |
| 63 | what = ct->counters[IP_CT_DIR_REPLY].packets; | 62 | what = counters[IP_CT_DIR_REPLY].packets; |
| 64 | break; | 63 | break; |
| 65 | case IPT_CONNBYTES_DIR_BOTH: | 64 | case IPT_CONNBYTES_DIR_BOTH: |
| 66 | what = ct->counters[IP_CT_DIR_ORIGINAL].packets; | 65 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
| 67 | what += ct->counters[IP_CT_DIR_REPLY].packets; | 66 | what += counters[IP_CT_DIR_REPLY].packets; |
| 68 | break; | 67 | break; |
| 69 | } | 68 | } |
| 70 | break; | 69 | break; |
| 71 | case IPT_CONNBYTES_BYTES: | 70 | case IPT_CONNBYTES_BYTES: |
| 72 | switch (sinfo->direction) { | 71 | switch (sinfo->direction) { |
| 73 | case IPT_CONNBYTES_DIR_ORIGINAL: | 72 | case IPT_CONNBYTES_DIR_ORIGINAL: |
| 74 | what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; | 73 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
| 75 | break; | 74 | break; |
| 76 | case IPT_CONNBYTES_DIR_REPLY: | 75 | case IPT_CONNBYTES_DIR_REPLY: |
| 77 | what = ct->counters[IP_CT_DIR_REPLY].bytes; | 76 | what = counters[IP_CT_DIR_REPLY].bytes; |
| 78 | break; | 77 | break; |
| 79 | case IPT_CONNBYTES_DIR_BOTH: | 78 | case IPT_CONNBYTES_DIR_BOTH: |
| 80 | what = ct->counters[IP_CT_DIR_ORIGINAL].bytes; | 79 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
| 81 | what += ct->counters[IP_CT_DIR_REPLY].bytes; | 80 | what += counters[IP_CT_DIR_REPLY].bytes; |
| 82 | break; | 81 | break; |
| 83 | } | 82 | } |
| 84 | break; | 83 | break; |
| 85 | case IPT_CONNBYTES_AVGPKT: | 84 | case IPT_CONNBYTES_AVGPKT: |
| 86 | switch (sinfo->direction) { | 85 | switch (sinfo->direction) { |
| 87 | case IPT_CONNBYTES_DIR_ORIGINAL: | 86 | case IPT_CONNBYTES_DIR_ORIGINAL: |
| 88 | what = div64_64(ct->counters[IP_CT_DIR_ORIGINAL].bytes, | 87 | what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, |
| 89 | ct->counters[IP_CT_DIR_ORIGINAL].packets); | 88 | counters[IP_CT_DIR_ORIGINAL].packets); |
| 90 | break; | 89 | break; |
| 91 | case IPT_CONNBYTES_DIR_REPLY: | 90 | case IPT_CONNBYTES_DIR_REPLY: |
| 92 | what = div64_64(ct->counters[IP_CT_DIR_REPLY].bytes, | 91 | what = div64_64(counters[IP_CT_DIR_REPLY].bytes, |
| 93 | ct->counters[IP_CT_DIR_REPLY].packets); | 92 | counters[IP_CT_DIR_REPLY].packets); |
| 94 | break; | 93 | break; |
| 95 | case IPT_CONNBYTES_DIR_BOTH: | 94 | case IPT_CONNBYTES_DIR_BOTH: |
| 96 | { | 95 | { |
| 97 | u_int64_t bytes; | 96 | u_int64_t bytes; |
| 98 | u_int64_t pkts; | 97 | u_int64_t pkts; |
| 99 | bytes = ct->counters[IP_CT_DIR_ORIGINAL].bytes + | 98 | bytes = counters[IP_CT_DIR_ORIGINAL].bytes + |
| 100 | ct->counters[IP_CT_DIR_REPLY].bytes; | 99 | counters[IP_CT_DIR_REPLY].bytes; |
| 101 | pkts = ct->counters[IP_CT_DIR_ORIGINAL].packets+ | 100 | pkts = counters[IP_CT_DIR_ORIGINAL].packets+ |
| 102 | ct->counters[IP_CT_DIR_REPLY].packets; | 101 | counters[IP_CT_DIR_REPLY].packets; |
| 103 | 102 | ||
| 104 | /* FIXME_THEORETICAL: what to do if sum | 103 | /* FIXME_THEORETICAL: what to do if sum |
| 105 | * overflows ? */ | 104 | * overflows ? */ |
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/ipv4/netfilter/ipt_connmark.c index bf8de47ce004..5306ef293b92 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/ipv4/netfilter/ipt_connmark.c | |||
| @@ -28,7 +28,7 @@ MODULE_LICENSE("GPL"); | |||
| 28 | 28 | ||
| 29 | #include <linux/netfilter_ipv4/ip_tables.h> | 29 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 30 | #include <linux/netfilter_ipv4/ipt_connmark.h> | 30 | #include <linux/netfilter_ipv4/ipt_connmark.h> |
| 31 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 31 | #include <net/netfilter/nf_conntrack_compat.h> |
| 32 | 32 | ||
| 33 | static int | 33 | static int |
| 34 | match(const struct sk_buff *skb, | 34 | match(const struct sk_buff *skb, |
| @@ -39,12 +39,12 @@ match(const struct sk_buff *skb, | |||
| 39 | int *hotdrop) | 39 | int *hotdrop) |
| 40 | { | 40 | { |
| 41 | const struct ipt_connmark_info *info = matchinfo; | 41 | const struct ipt_connmark_info *info = matchinfo; |
| 42 | enum ip_conntrack_info ctinfo; | 42 | u_int32_t ctinfo; |
| 43 | struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); | 43 | const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); |
| 44 | if (!ct) | 44 | if (!ctmark) |
| 45 | return 0; | 45 | return 0; |
| 46 | 46 | ||
| 47 | return ((ct->mark & info->mask) == info->mark) ^ info->invert; | 47 | return (((*ctmark) & info->mask) == info->mark) ^ info->invert; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | static int | 50 | static int |
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/ipv4/netfilter/ipt_conntrack.c index c1d22801b7cf..c8d18705469b 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/ipv4/netfilter/ipt_conntrack.c | |||
| @@ -10,7 +10,14 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
| 13 | |||
| 14 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | ||
| 13 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 15 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
| 16 | #include <linux/netfilter_ipv4/ip_conntrack_tuple.h> | ||
| 17 | #else | ||
| 18 | #include <net/netfilter/nf_conntrack.h> | ||
| 19 | #endif | ||
| 20 | |||
| 14 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 15 | #include <linux/netfilter_ipv4/ipt_conntrack.h> | 22 | #include <linux/netfilter_ipv4/ipt_conntrack.h> |
| 16 | 23 | ||
| @@ -18,6 +25,8 @@ MODULE_LICENSE("GPL"); | |||
| 18 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 25 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
| 19 | MODULE_DESCRIPTION("iptables connection tracking match module"); | 26 | MODULE_DESCRIPTION("iptables connection tracking match module"); |
| 20 | 27 | ||
| 28 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | ||
| 29 | |||
| 21 | static int | 30 | static int |
| 22 | match(const struct sk_buff *skb, | 31 | match(const struct sk_buff *skb, |
| 23 | const struct net_device *in, | 32 | const struct net_device *in, |
| @@ -102,6 +111,93 @@ match(const struct sk_buff *skb, | |||
| 102 | return 1; | 111 | return 1; |
| 103 | } | 112 | } |
| 104 | 113 | ||
| 114 | #else /* CONFIG_IP_NF_CONNTRACK */ | ||
| 115 | static int | ||
| 116 | match(const struct sk_buff *skb, | ||
| 117 | const struct net_device *in, | ||
| 118 | const struct net_device *out, | ||
| 119 | const void *matchinfo, | ||
| 120 | int offset, | ||
| 121 | int *hotdrop) | ||
| 122 | { | ||
| 123 | const struct ipt_conntrack_info *sinfo = matchinfo; | ||
| 124 | struct nf_conn *ct; | ||
| 125 | enum ip_conntrack_info ctinfo; | ||
| 126 | unsigned int statebit; | ||
| 127 | |||
| 128 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | ||
| 129 | |||
| 130 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | ||
| 131 | |||
| 132 | if (ct == &nf_conntrack_untracked) | ||
| 133 | statebit = IPT_CONNTRACK_STATE_UNTRACKED; | ||
| 134 | else if (ct) | ||
| 135 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | ||
| 136 | else | ||
| 137 | statebit = IPT_CONNTRACK_STATE_INVALID; | ||
| 138 | |||
| 139 | if(sinfo->flags & IPT_CONNTRACK_STATE) { | ||
| 140 | if (ct) { | ||
| 141 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != | ||
| 142 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) | ||
| 143 | statebit |= IPT_CONNTRACK_STATE_SNAT; | ||
| 144 | |||
| 145 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != | ||
| 146 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) | ||
| 147 | statebit |= IPT_CONNTRACK_STATE_DNAT; | ||
| 148 | } | ||
| 149 | |||
| 150 | if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | if(sinfo->flags & IPT_CONNTRACK_PROTO) { | ||
| 155 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { | ||
| 160 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) | ||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { | ||
| 165 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { | ||
| 170 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | if(sinfo->flags & IPT_CONNTRACK_REPLDST) { | ||
| 175 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) | ||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | if(sinfo->flags & IPT_CONNTRACK_STATUS) { | ||
| 180 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { | ||
| 185 | unsigned long expires; | ||
| 186 | |||
| 187 | if(!ct) | ||
| 188 | return 0; | ||
| 189 | |||
| 190 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; | ||
| 191 | |||
| 192 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | return 1; | ||
| 197 | } | ||
| 198 | |||
| 199 | #endif /* CONFIG_NF_IP_CONNTRACK */ | ||
| 200 | |||
| 105 | static int check(const char *tablename, | 201 | static int check(const char *tablename, |
| 106 | const struct ipt_ip *ip, | 202 | const struct ipt_ip *ip, |
| 107 | void *matchinfo, | 203 | void *matchinfo, |
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c index 3e7dd014de43..bf14e1c7798a 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/ipv4/netfilter/ipt_helper.c | |||
| @@ -13,9 +13,15 @@ | |||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
| 15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
| 16 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | ||
| 16 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 17 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
| 17 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | 18 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> |
| 18 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | 19 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> |
| 20 | #else | ||
| 21 | #include <net/netfilter/nf_conntrack.h> | ||
| 22 | #include <net/netfilter/nf_conntrack_core.h> | ||
| 23 | #include <net/netfilter/nf_conntrack_helper.h> | ||
| 24 | #endif | ||
| 19 | #include <linux/netfilter_ipv4/ip_tables.h> | 25 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 20 | #include <linux/netfilter_ipv4/ipt_helper.h> | 26 | #include <linux/netfilter_ipv4/ipt_helper.h> |
| 21 | 27 | ||
| @@ -29,6 +35,7 @@ MODULE_DESCRIPTION("iptables helper match module"); | |||
| 29 | #define DEBUGP(format, args...) | 35 | #define DEBUGP(format, args...) |
| 30 | #endif | 36 | #endif |
| 31 | 37 | ||
| 38 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | ||
| 32 | static int | 39 | static int |
| 33 | match(const struct sk_buff *skb, | 40 | match(const struct sk_buff *skb, |
| 34 | const struct net_device *in, | 41 | const struct net_device *in, |
| @@ -73,6 +80,53 @@ out_unlock: | |||
| 73 | return ret; | 80 | return ret; |
| 74 | } | 81 | } |
| 75 | 82 | ||
| 83 | #else /* CONFIG_IP_NF_CONNTRACK */ | ||
| 84 | |||
| 85 | static int | ||
| 86 | match(const struct sk_buff *skb, | ||
| 87 | const struct net_device *in, | ||
| 88 | const struct net_device *out, | ||
| 89 | const void *matchinfo, | ||
| 90 | int offset, | ||
| 91 | int *hotdrop) | ||
| 92 | { | ||
| 93 | const struct ipt_helper_info *info = matchinfo; | ||
| 94 | struct nf_conn *ct; | ||
| 95 | enum ip_conntrack_info ctinfo; | ||
| 96 | int ret = info->invert; | ||
| 97 | |||
| 98 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | ||
| 99 | if (!ct) { | ||
| 100 | DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (!ct->master) { | ||
| 105 | DEBUGP("ipt_helper: conntrack %p has no master\n", ct); | ||
| 106 | return ret; | ||
| 107 | } | ||
| 108 | |||
| 109 | read_lock_bh(&nf_conntrack_lock); | ||
| 110 | if (!ct->master->helper) { | ||
| 111 | DEBUGP("ipt_helper: master ct %p has no helper\n", | ||
| 112 | exp->expectant); | ||
| 113 | goto out_unlock; | ||
| 114 | } | ||
| 115 | |||
| 116 | DEBUGP("master's name = %s , info->name = %s\n", | ||
| 117 | ct->master->helper->name, info->name); | ||
| 118 | |||
| 119 | if (info->name[0] == '\0') | ||
| 120 | ret ^= 1; | ||
| 121 | else | ||
| 122 | ret ^= !strncmp(ct->master->helper->name, info->name, | ||
| 123 | strlen(ct->master->helper->name)); | ||
| 124 | out_unlock: | ||
| 125 | read_unlock_bh(&nf_conntrack_lock); | ||
| 126 | return ret; | ||
| 127 | } | ||
| 128 | #endif | ||
| 129 | |||
| 76 | static int check(const char *tablename, | 130 | static int check(const char *tablename, |
| 77 | const struct ipt_ip *ip, | 131 | const struct ipt_ip *ip, |
| 78 | void *matchinfo, | 132 | void *matchinfo, |
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/ipv4/netfilter/ipt_state.c index b1511b97ea5f..4d7f16b70cec 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/ipv4/netfilter/ipt_state.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
| 12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
| 13 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 13 | #include <net/netfilter/nf_conntrack_compat.h> |
| 14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter_ipv4/ip_tables.h> |
| 15 | #include <linux/netfilter_ipv4/ipt_state.h> | 15 | #include <linux/netfilter_ipv4/ipt_state.h> |
| 16 | 16 | ||
| @@ -30,9 +30,9 @@ match(const struct sk_buff *skb, | |||
| 30 | enum ip_conntrack_info ctinfo; | 30 | enum ip_conntrack_info ctinfo; |
| 31 | unsigned int statebit; | 31 | unsigned int statebit; |
| 32 | 32 | ||
| 33 | if (skb->nfct == &ip_conntrack_untracked.ct_general) | 33 | if (nf_ct_is_untracked(skb)) |
| 34 | statebit = IPT_STATE_UNTRACKED; | 34 | statebit = IPT_STATE_UNTRACKED; |
| 35 | else if (!ip_conntrack_get(skb, &ctinfo)) | 35 | else if (!nf_ct_get_ctinfo(skb, &ctinfo)) |
| 36 | statebit = IPT_STATE_INVALID; | 36 | statebit = IPT_STATE_INVALID; |
| 37 | else | 37 | else |
| 38 | statebit = IPT_STATE_BIT(ctinfo); | 38 | statebit = IPT_STATE_BIT(ctinfo); |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c new file mode 100644 index 000000000000..8202c1c0afad --- /dev/null +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
| @@ -0,0 +1,571 @@ | |||
| 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 | * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
| 9 | * - move L3 protocol dependent part to this file. | ||
| 10 | * 23 Mar 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
| 11 | * - add get_features() to support various size of conntrack | ||
| 12 | * structures. | ||
| 13 | * | ||
| 14 | * Derived from net/ipv4/netfilter/ip_conntrack_standalone.c | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <linux/types.h> | ||
| 19 | #include <linux/ip.h> | ||
| 20 | #include <linux/netfilter.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/skbuff.h> | ||
| 23 | #include <linux/icmp.h> | ||
| 24 | #include <linux/sysctl.h> | ||
| 25 | #include <net/ip.h> | ||
| 26 | |||
| 27 | #include <linux/netfilter_ipv4.h> | ||
| 28 | #include <net/netfilter/nf_conntrack.h> | ||
| 29 | #include <net/netfilter/nf_conntrack_helper.h> | ||
| 30 | #include <net/netfilter/nf_conntrack_protocol.h> | ||
| 31 | #include <net/netfilter/nf_conntrack_l3proto.h> | ||
| 32 | #include <net/netfilter/nf_conntrack_core.h> | ||
| 33 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | ||
| 34 | |||
| 35 | #if 0 | ||
| 36 | #define DEBUGP printk | ||
| 37 | #else | ||
| 38 | #define DEBUGP(format, args...) | ||
| 39 | #endif | ||
| 40 | |||
| 41 | DECLARE_PER_CPU(struct nf_conntrack_stat, nf_conntrack_stat); | ||
| 42 | |||
| 43 | static int ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | ||
| 44 | struct nf_conntrack_tuple *tuple) | ||
| 45 | { | ||
| 46 | u_int32_t _addrs[2], *ap; | ||
| 47 | ap = skb_header_pointer(skb, nhoff + offsetof(struct iphdr, saddr), | ||
| 48 | sizeof(u_int32_t) * 2, _addrs); | ||
| 49 | if (ap == NULL) | ||
| 50 | return 0; | ||
| 51 | |||
| 52 | tuple->src.u3.ip = ap[0]; | ||
| 53 | tuple->dst.u3.ip = ap[1]; | ||
| 54 | |||
| 55 | return 1; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int ipv4_invert_tuple(struct nf_conntrack_tuple *tuple, | ||
| 59 | const struct nf_conntrack_tuple *orig) | ||
| 60 | { | ||
| 61 | tuple->src.u3.ip = orig->dst.u3.ip; | ||
| 62 | tuple->dst.u3.ip = orig->src.u3.ip; | ||
| 63 | |||
| 64 | return 1; | ||
| 65 | } | ||
| 66 | |||
| 67 | static int ipv4_print_tuple(struct seq_file *s, | ||
| 68 | const struct nf_conntrack_tuple *tuple) | ||
| 69 | { | ||
| 70 | return seq_printf(s, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ", | ||
| 71 | NIPQUAD(tuple->src.u3.ip), | ||
| 72 | NIPQUAD(tuple->dst.u3.ip)); | ||
| 73 | } | ||
| 74 | |||
| 75 | static int ipv4_print_conntrack(struct seq_file *s, | ||
| 76 | const struct nf_conn *conntrack) | ||
| 77 | { | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | /* Returns new sk_buff, or NULL */ | ||
| 82 | static struct sk_buff * | ||
| 83 | nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) | ||
| 84 | { | ||
| 85 | skb_orphan(skb); | ||
| 86 | |||
| 87 | local_bh_disable(); | ||
| 88 | skb = ip_defrag(skb, user); | ||
| 89 | local_bh_enable(); | ||
| 90 | |||
| 91 | if (skb) | ||
| 92 | ip_send_check(skb->nh.iph); | ||
| 93 | |||
| 94 | return skb; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int | ||
| 98 | ipv4_prepare(struct sk_buff **pskb, unsigned int hooknum, unsigned int *dataoff, | ||
| 99 | u_int8_t *protonum) | ||
| 100 | { | ||
| 101 | /* Never happen */ | ||
| 102 | if ((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) { | ||
| 103 | if (net_ratelimit()) { | ||
| 104 | printk(KERN_ERR "ipv4_prepare: Frag of proto %u (hook=%u)\n", | ||
| 105 | (*pskb)->nh.iph->protocol, hooknum); | ||
| 106 | } | ||
| 107 | return -NF_DROP; | ||
| 108 | } | ||
| 109 | |||
| 110 | *dataoff = (*pskb)->nh.raw - (*pskb)->data + (*pskb)->nh.iph->ihl*4; | ||
| 111 | *protonum = (*pskb)->nh.iph->protocol; | ||
| 112 | |||
| 113 | return NF_ACCEPT; | ||
| 114 | } | ||
| 115 | |||
| 116 | int nat_module_is_loaded = 0; | ||
| 117 | static u_int32_t ipv4_get_features(const struct nf_conntrack_tuple *tuple) | ||
| 118 | { | ||
| 119 | if (nat_module_is_loaded) | ||
| 120 | return NF_CT_F_NAT; | ||
| 121 | |||
| 122 | return NF_CT_F_BASIC; | ||
| 123 | } | ||
| 124 | |||
| 125 | static unsigned int ipv4_confirm(unsigned int hooknum, | ||
| 126 | struct sk_buff **pskb, | ||
| 127 | const struct net_device *in, | ||
| 128 | const struct net_device *out, | ||
| 129 | int (*okfn)(struct sk_buff *)) | ||
| 130 | { | ||
| 131 | /* We've seen it coming out the other side: confirm it */ | ||
| 132 | return nf_conntrack_confirm(pskb); | ||
| 133 | } | ||
| 134 | |||
| 135 | static unsigned int ipv4_conntrack_help(unsigned int hooknum, | ||
| 136 | struct sk_buff **pskb, | ||
| 137 | const struct net_device *in, | ||
| 138 | const struct net_device *out, | ||
| 139 | int (*okfn)(struct sk_buff *)) | ||
| 140 | { | ||
| 141 | struct nf_conn *ct; | ||
| 142 | enum ip_conntrack_info ctinfo; | ||
| 143 | |||
| 144 | /* This is where we call the helper: as the packet goes out. */ | ||
| 145 | ct = nf_ct_get(*pskb, &ctinfo); | ||
| 146 | if (ct && ct->helper) { | ||
| 147 | unsigned int ret; | ||
| 148 | ret = ct->helper->help(pskb, | ||
| 149 | (*pskb)->nh.raw - (*pskb)->data | ||
| 150 | + (*pskb)->nh.iph->ihl*4, | ||
| 151 | ct, ctinfo); | ||
| 152 | if (ret != NF_ACCEPT) | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | return NF_ACCEPT; | ||
| 156 | } | ||
| 157 | |||
| 158 | static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, | ||
| 159 | struct sk_buff **pskb, | ||
| 160 | const struct net_device *in, | ||
| 161 | const struct net_device *out, | ||
| 162 | int (*okfn)(struct sk_buff *)) | ||
| 163 | { | ||
| 164 | #if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE) | ||
| 165 | /* Previously seen (loopback)? Ignore. Do this before | ||
| 166 | fragment check. */ | ||
| 167 | if ((*pskb)->nfct) | ||
| 168 | return NF_ACCEPT; | ||
| 169 | #endif | ||
| 170 | |||
| 171 | /* Gather fragments. */ | ||
| 172 | if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { | ||
| 173 | *pskb = nf_ct_ipv4_gather_frags(*pskb, | ||
| 174 | hooknum == NF_IP_PRE_ROUTING ? | ||
| 175 | IP_DEFRAG_CONNTRACK_IN : | ||
| 176 | IP_DEFRAG_CONNTRACK_OUT); | ||
| 177 | if (!*pskb) | ||
| 178 | return NF_STOLEN; | ||
| 179 | } | ||
| 180 | return NF_ACCEPT; | ||
| 181 | } | ||
| 182 | |||
| 183 | static unsigned int ipv4_refrag(unsigned int hooknum, | ||
| 184 | struct sk_buff **pskb, | ||
| 185 | const struct net_device *in, | ||
| 186 | const struct net_device *out, | ||
| 187 | int (*okfn)(struct sk_buff *)) | ||
| 188 | { | ||
| 189 | struct rtable *rt = (struct rtable *)(*pskb)->dst; | ||
| 190 | |||
| 191 | /* We've seen it coming out the other side: confirm */ | ||
| 192 | if (ipv4_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT) | ||
| 193 | return NF_DROP; | ||
| 194 | |||
| 195 | /* Local packets are never produced too large for their | ||
| 196 | interface. We degfragment them at LOCAL_OUT, however, | ||
| 197 | so we have to refragment them here. */ | ||
| 198 | if ((*pskb)->len > dst_mtu(&rt->u.dst) && | ||
| 199 | !skb_shinfo(*pskb)->tso_size) { | ||
| 200 | /* No hook can be after us, so this should be OK. */ | ||
| 201 | ip_fragment(*pskb, okfn); | ||
| 202 | return NF_STOLEN; | ||
| 203 | } | ||
| 204 | return NF_ACCEPT; | ||
| 205 | } | ||
| 206 | |||
| 207 | static unsigned int ipv4_conntrack_in(unsigned int hooknum, | ||
| 208 | struct sk_buff **pskb, | ||
| 209 | const struct net_device *in, | ||
| 210 | const struct net_device *out, | ||
| 211 | int (*okfn)(struct sk_buff *)) | ||
| 212 | { | ||
| 213 | return nf_conntrack_in(PF_INET, hooknum, pskb); | ||
| 214 | } | ||
| 215 | |||
| 216 | static unsigned int ipv4_conntrack_local(unsigned int hooknum, | ||
| 217 | struct sk_buff **pskb, | ||
| 218 | const struct net_device *in, | ||
| 219 | const struct net_device *out, | ||
| 220 | int (*okfn)(struct sk_buff *)) | ||
| 221 | { | ||
| 222 | /* root is playing with raw sockets. */ | ||
| 223 | if ((*pskb)->len < sizeof(struct iphdr) | ||
| 224 | || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { | ||
| 225 | if (net_ratelimit()) | ||
| 226 | printk("ipt_hook: happy cracking.\n"); | ||
| 227 | return NF_ACCEPT; | ||
| 228 | } | ||
| 229 | return nf_conntrack_in(PF_INET, hooknum, pskb); | ||
| 230 | } | ||
| 231 | |||
| 232 | /* Connection tracking may drop packets, but never alters them, so | ||
| 233 | make it the first hook. */ | ||
| 234 | static struct nf_hook_ops ipv4_conntrack_defrag_ops = { | ||
| 235 | .hook = ipv4_conntrack_defrag, | ||
| 236 | .owner = THIS_MODULE, | ||
| 237 | .pf = PF_INET, | ||
| 238 | .hooknum = NF_IP_PRE_ROUTING, | ||
| 239 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static struct nf_hook_ops ipv4_conntrack_in_ops = { | ||
| 243 | .hook = ipv4_conntrack_in, | ||
| 244 | .owner = THIS_MODULE, | ||
| 245 | .pf = PF_INET, | ||
| 246 | .hooknum = NF_IP_PRE_ROUTING, | ||
| 247 | .priority = NF_IP_PRI_CONNTRACK, | ||
| 248 | }; | ||
| 249 | |||
| 250 | static struct nf_hook_ops ipv4_conntrack_defrag_local_out_ops = { | ||
| 251 | .hook = ipv4_conntrack_defrag, | ||
| 252 | .owner = THIS_MODULE, | ||
| 253 | .pf = PF_INET, | ||
| 254 | .hooknum = NF_IP_LOCAL_OUT, | ||
| 255 | .priority = NF_IP_PRI_CONNTRACK_DEFRAG, | ||
| 256 | }; | ||
| 257 | |||
| 258 | static struct nf_hook_ops ipv4_conntrack_local_out_ops = { | ||
| 259 | .hook = ipv4_conntrack_local, | ||
| 260 | .owner = THIS_MODULE, | ||
| 261 | .pf = PF_INET, | ||
| 262 | .hooknum = NF_IP_LOCAL_OUT, | ||
| 263 | .priority = NF_IP_PRI_CONNTRACK, | ||
| 264 | }; | ||
| 265 | |||
| 266 | /* helpers */ | ||
| 267 | static struct nf_hook_ops ipv4_conntrack_helper_out_ops = { | ||
| 268 | .hook = ipv4_conntrack_help, | ||
| 269 | .owner = THIS_MODULE, | ||
| 270 | .pf = PF_INET, | ||
| 271 | .hooknum = NF_IP_POST_ROUTING, | ||
| 272 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | ||
| 273 | }; | ||
| 274 | |||
| 275 | static struct nf_hook_ops ipv4_conntrack_helper_in_ops = { | ||
| 276 | .hook = ipv4_conntrack_help, | ||
| 277 | .owner = THIS_MODULE, | ||
| 278 | .pf = PF_INET, | ||
| 279 | .hooknum = NF_IP_LOCAL_IN, | ||
| 280 | .priority = NF_IP_PRI_CONNTRACK_HELPER, | ||
| 281 | }; | ||
| 282 | |||
| 283 | |||
| 284 | /* Refragmenter; last chance. */ | ||
| 285 | static struct nf_hook_ops ipv4_conntrack_out_ops = { | ||
| 286 | .hook = ipv4_refrag, | ||
| 287 | .owner = THIS_MODULE, | ||
| 288 | .pf = PF_INET, | ||
| 289 | .hooknum = NF_IP_POST_ROUTING, | ||
| 290 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | ||
| 291 | }; | ||
| 292 | |||
| 293 | static struct nf_hook_ops ipv4_conntrack_local_in_ops = { | ||
| 294 | .hook = ipv4_confirm, | ||
| 295 | .owner = THIS_MODULE, | ||
| 296 | .pf = PF_INET, | ||
| 297 | .hooknum = NF_IP_LOCAL_IN, | ||
| 298 | .priority = NF_IP_PRI_CONNTRACK_CONFIRM, | ||
| 299 | }; | ||
| 300 | |||
| 301 | #ifdef CONFIG_SYSCTL | ||
| 302 | /* From nf_conntrack_proto_icmp.c */ | ||
| 303 | extern unsigned long nf_ct_icmp_timeout; | ||
| 304 | static struct ctl_table_header *nf_ct_ipv4_sysctl_header; | ||
| 305 | |||
| 306 | static ctl_table nf_ct_sysctl_table[] = { | ||
| 307 | { | ||
| 308 | .ctl_name = NET_NF_CONNTRACK_ICMP_TIMEOUT, | ||
| 309 | .procname = "nf_conntrack_icmp_timeout", | ||
| 310 | .data = &nf_ct_icmp_timeout, | ||
| 311 | .maxlen = sizeof(unsigned int), | ||
| 312 | .mode = 0644, | ||
| 313 | .proc_handler = &proc_dointvec_jiffies, | ||
| 314 | }, | ||
| 315 | { .ctl_name = 0 } | ||
| 316 | }; | ||
| 317 | |||
| 318 | static ctl_table nf_ct_netfilter_table[] = { | ||
| 319 | { | ||
| 320 | .ctl_name = NET_NETFILTER, | ||
| 321 | .procname = "netfilter", | ||
| 322 | .mode = 0555, | ||
| 323 | .child = nf_ct_sysctl_table, | ||
| 324 | }, | ||
| 325 | { .ctl_name = 0 } | ||
| 326 | }; | ||
| 327 | |||
| 328 | static ctl_table nf_ct_net_table[] = { | ||
| 329 | { | ||
| 330 | .ctl_name = CTL_NET, | ||
| 331 | .procname = "net", | ||
| 332 | .mode = 0555, | ||
| 333 | .child = nf_ct_netfilter_table, | ||
| 334 | }, | ||
| 335 | { .ctl_name = 0 } | ||
| 336 | }; | ||
| 337 | #endif | ||
| 338 | |||
| 339 | /* Fast function for those who don't want to parse /proc (and I don't | ||
| 340 | blame them). */ | ||
| 341 | /* Reversing the socket's dst/src point of view gives us the reply | ||
| 342 | mapping. */ | ||
| 343 | static int | ||
| 344 | getorigdst(struct sock *sk, int optval, void __user *user, int *len) | ||
| 345 | { | ||
| 346 | struct inet_sock *inet = inet_sk(sk); | ||
| 347 | struct nf_conntrack_tuple_hash *h; | ||
| 348 | struct nf_conntrack_tuple tuple; | ||
| 349 | |||
| 350 | NF_CT_TUPLE_U_BLANK(&tuple); | ||
| 351 | tuple.src.u3.ip = inet->rcv_saddr; | ||
| 352 | tuple.src.u.tcp.port = inet->sport; | ||
| 353 | tuple.dst.u3.ip = inet->daddr; | ||
| 354 | tuple.dst.u.tcp.port = inet->dport; | ||
| 355 | tuple.src.l3num = PF_INET; | ||
| 356 | tuple.dst.protonum = IPPROTO_TCP; | ||
| 357 | |||
| 358 | /* We only do TCP at the moment: is there a better way? */ | ||
| 359 | if (strcmp(sk->sk_prot->name, "TCP")) { | ||
| 360 | DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n"); | ||
| 361 | return -ENOPROTOOPT; | ||
| 362 | } | ||
| 363 | |||
| 364 | if ((unsigned int) *len < sizeof(struct sockaddr_in)) { | ||
| 365 | DEBUGP("SO_ORIGINAL_DST: len %u not %u\n", | ||
| 366 | *len, sizeof(struct sockaddr_in)); | ||
| 367 | return -EINVAL; | ||
| 368 | } | ||
| 369 | |||
| 370 | h = nf_conntrack_find_get(&tuple, NULL); | ||
| 371 | if (h) { | ||
| 372 | struct sockaddr_in sin; | ||
| 373 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 374 | |||
| 375 | sin.sin_family = AF_INET; | ||
| 376 | sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL] | ||
| 377 | .tuple.dst.u.tcp.port; | ||
| 378 | sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL] | ||
| 379 | .tuple.dst.u3.ip; | ||
| 380 | |||
| 381 | DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", | ||
| 382 | NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); | ||
| 383 | nf_ct_put(ct); | ||
| 384 | if (copy_to_user(user, &sin, sizeof(sin)) != 0) | ||
| 385 | return -EFAULT; | ||
| 386 | else | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", | ||
| 390 | NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), | ||
| 391 | NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); | ||
| 392 | return -ENOENT; | ||
| 393 | } | ||
| 394 | |||
| 395 | static struct nf_sockopt_ops so_getorigdst = { | ||
| 396 | .pf = PF_INET, | ||
| 397 | .get_optmin = SO_ORIGINAL_DST, | ||
| 398 | .get_optmax = SO_ORIGINAL_DST+1, | ||
| 399 | .get = &getorigdst, | ||
| 400 | }; | ||
| 401 | |||
| 402 | struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { | ||
| 403 | .l3proto = PF_INET, | ||
| 404 | .name = "ipv4", | ||
| 405 | .pkt_to_tuple = ipv4_pkt_to_tuple, | ||
| 406 | .invert_tuple = ipv4_invert_tuple, | ||
| 407 | .print_tuple = ipv4_print_tuple, | ||
| 408 | .print_conntrack = ipv4_print_conntrack, | ||
| 409 | .prepare = ipv4_prepare, | ||
| 410 | .get_features = ipv4_get_features, | ||
| 411 | .me = THIS_MODULE, | ||
| 412 | }; | ||
| 413 | |||
| 414 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4; | ||
| 415 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4; | ||
| 416 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp; | ||
| 417 | static int init_or_cleanup(int init) | ||
| 418 | { | ||
| 419 | int ret = 0; | ||
| 420 | |||
| 421 | if (!init) goto cleanup; | ||
| 422 | |||
| 423 | ret = nf_register_sockopt(&so_getorigdst); | ||
| 424 | if (ret < 0) { | ||
| 425 | printk(KERN_ERR "Unable to register netfilter socket option\n"); | ||
| 426 | goto cleanup_nothing; | ||
| 427 | } | ||
| 428 | |||
| 429 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); | ||
| 430 | if (ret < 0) { | ||
| 431 | printk("nf_conntrack_ipv4: can't register tcp.\n"); | ||
| 432 | goto cleanup_sockopt; | ||
| 433 | } | ||
| 434 | |||
| 435 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4); | ||
| 436 | if (ret < 0) { | ||
| 437 | printk("nf_conntrack_ipv4: can't register udp.\n"); | ||
| 438 | goto cleanup_tcp; | ||
| 439 | } | ||
| 440 | |||
| 441 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp); | ||
| 442 | if (ret < 0) { | ||
| 443 | printk("nf_conntrack_ipv4: can't register icmp.\n"); | ||
| 444 | goto cleanup_udp; | ||
| 445 | } | ||
| 446 | |||
| 447 | ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4); | ||
| 448 | if (ret < 0) { | ||
| 449 | printk("nf_conntrack_ipv4: can't register ipv4\n"); | ||
| 450 | goto cleanup_icmp; | ||
| 451 | } | ||
| 452 | |||
| 453 | ret = nf_register_hook(&ipv4_conntrack_defrag_ops); | ||
| 454 | if (ret < 0) { | ||
| 455 | printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); | ||
| 456 | goto cleanup_ipv4; | ||
| 457 | } | ||
| 458 | ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops); | ||
| 459 | if (ret < 0) { | ||
| 460 | printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n"); | ||
| 461 | goto cleanup_defragops; | ||
| 462 | } | ||
| 463 | |||
| 464 | ret = nf_register_hook(&ipv4_conntrack_in_ops); | ||
| 465 | if (ret < 0) { | ||
| 466 | printk("nf_conntrack_ipv4: can't register pre-routing hook.\n"); | ||
| 467 | goto cleanup_defraglocalops; | ||
| 468 | } | ||
| 469 | |||
| 470 | ret = nf_register_hook(&ipv4_conntrack_local_out_ops); | ||
| 471 | if (ret < 0) { | ||
| 472 | printk("nf_conntrack_ipv4: can't register local out hook.\n"); | ||
| 473 | goto cleanup_inops; | ||
| 474 | } | ||
| 475 | |||
| 476 | ret = nf_register_hook(&ipv4_conntrack_helper_in_ops); | ||
| 477 | if (ret < 0) { | ||
| 478 | printk("nf_conntrack_ipv4: can't register local helper hook.\n"); | ||
| 479 | goto cleanup_inandlocalops; | ||
| 480 | } | ||
| 481 | |||
| 482 | ret = nf_register_hook(&ipv4_conntrack_helper_out_ops); | ||
| 483 | if (ret < 0) { | ||
| 484 | printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n"); | ||
| 485 | goto cleanup_helperinops; | ||
| 486 | } | ||
| 487 | |||
| 488 | ret = nf_register_hook(&ipv4_conntrack_out_ops); | ||
| 489 | if (ret < 0) { | ||
| 490 | printk("nf_conntrack_ipv4: can't register post-routing hook.\n"); | ||
| 491 | goto cleanup_helperoutops; | ||
| 492 | } | ||
| 493 | |||
| 494 | ret = nf_register_hook(&ipv4_conntrack_local_in_ops); | ||
| 495 | if (ret < 0) { | ||
| 496 | printk("nf_conntrack_ipv4: can't register local in hook.\n"); | ||
| 497 | goto cleanup_inoutandlocalops; | ||
| 498 | } | ||
| 499 | |||
| 500 | #ifdef CONFIG_SYSCTL | ||
| 501 | nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | ||
| 502 | if (nf_ct_ipv4_sysctl_header == NULL) { | ||
| 503 | printk("nf_conntrack: can't register to sysctl.\n"); | ||
| 504 | ret = -ENOMEM; | ||
| 505 | goto cleanup_localinops; | ||
| 506 | } | ||
| 507 | #endif | ||
| 508 | |||
| 509 | /* For use by REJECT target */ | ||
| 510 | ip_ct_attach = __nf_conntrack_attach; | ||
| 511 | |||
| 512 | return ret; | ||
| 513 | |||
| 514 | cleanup: | ||
| 515 | synchronize_net(); | ||
| 516 | ip_ct_attach = NULL; | ||
| 517 | #ifdef CONFIG_SYSCTL | ||
| 518 | unregister_sysctl_table(nf_ct_ipv4_sysctl_header); | ||
| 519 | cleanup_localinops: | ||
| 520 | #endif | ||
| 521 | nf_unregister_hook(&ipv4_conntrack_local_in_ops); | ||
| 522 | cleanup_inoutandlocalops: | ||
| 523 | nf_unregister_hook(&ipv4_conntrack_out_ops); | ||
| 524 | cleanup_helperoutops: | ||
| 525 | nf_unregister_hook(&ipv4_conntrack_helper_out_ops); | ||
| 526 | cleanup_helperinops: | ||
| 527 | nf_unregister_hook(&ipv4_conntrack_helper_in_ops); | ||
| 528 | cleanup_inandlocalops: | ||
| 529 | nf_unregister_hook(&ipv4_conntrack_local_out_ops); | ||
| 530 | cleanup_inops: | ||
| 531 | nf_unregister_hook(&ipv4_conntrack_in_ops); | ||
| 532 | cleanup_defraglocalops: | ||
| 533 | nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops); | ||
| 534 | cleanup_defragops: | ||
| 535 | nf_unregister_hook(&ipv4_conntrack_defrag_ops); | ||
| 536 | cleanup_ipv4: | ||
| 537 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); | ||
| 538 | cleanup_icmp: | ||
| 539 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); | ||
| 540 | cleanup_udp: | ||
| 541 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); | ||
| 542 | cleanup_tcp: | ||
| 543 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); | ||
| 544 | cleanup_sockopt: | ||
| 545 | nf_unregister_sockopt(&so_getorigdst); | ||
| 546 | cleanup_nothing: | ||
| 547 | return ret; | ||
| 548 | } | ||
| 549 | |||
| 550 | MODULE_LICENSE("GPL"); | ||
| 551 | |||
| 552 | static int __init init(void) | ||
| 553 | { | ||
| 554 | need_nf_conntrack(); | ||
| 555 | return init_or_cleanup(1); | ||
| 556 | } | ||
| 557 | |||
| 558 | static void __exit fini(void) | ||
| 559 | { | ||
| 560 | init_or_cleanup(0); | ||
| 561 | } | ||
| 562 | |||
| 563 | module_init(init); | ||
| 564 | module_exit(fini); | ||
| 565 | |||
| 566 | void need_ip_conntrack(void) | ||
| 567 | { | ||
| 568 | } | ||
| 569 | |||
| 570 | EXPORT_SYMBOL(need_ip_conntrack); | ||
| 571 | EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c new file mode 100644 index 000000000000..7ddb5c08f7b8 --- /dev/null +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
| @@ -0,0 +1,301 @@ | |||
| 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 | * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> | ||
| 9 | * - enable working with Layer 3 protocol independent connection tracking. | ||
| 10 | * | ||
| 11 | * Derived from net/ipv4/netfilter/ip_conntrack_proto_icmp.c | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/sched.h> | ||
| 16 | #include <linux/timer.h> | ||
| 17 | #include <linux/netfilter.h> | ||
| 18 | #include <linux/in.h> | ||
| 19 | #include <linux/icmp.h> | ||
| 20 | #include <linux/seq_file.h> | ||
| 21 | #include <net/ip.h> | ||
| 22 | #include <net/checksum.h> | ||
| 23 | #include <linux/netfilter_ipv4.h> | ||
| 24 | #include <net/netfilter/nf_conntrack_tuple.h> | ||
| 25 | #include <net/netfilter/nf_conntrack_protocol.h> | ||
| 26 | #include <net/netfilter/nf_conntrack_core.h> | ||
| 27 | |||
| 28 | unsigned long nf_ct_icmp_timeout = 30*HZ; | ||
| 29 | |||
| 30 | #if 0 | ||
| 31 | #define DEBUGP printk | ||
| 32 | #else | ||
| 33 | #define DEBUGP(format, args...) | ||
| 34 | #endif | ||
| 35 | |||
| 36 | static int icmp_pkt_to_tuple(const struct sk_buff *skb, | ||
| 37 | unsigned int dataoff, | ||
| 38 | struct nf_conntrack_tuple *tuple) | ||
| 39 | { | ||
| 40 | struct icmphdr _hdr, *hp; | ||
| 41 | |||
| 42 | hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); | ||
| 43 | if (hp == NULL) | ||
| 44 | return 0; | ||
| 45 | |||
| 46 | tuple->dst.u.icmp.type = hp->type; | ||
| 47 | tuple->src.u.icmp.id = hp->un.echo.id; | ||
| 48 | tuple->dst.u.icmp.code = hp->code; | ||
| 49 | |||
| 50 | return 1; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int icmp_invert_tuple(struct nf_conntrack_tuple *tuple, | ||
| 54 | const struct nf_conntrack_tuple *orig) | ||
| 55 | { | ||
| 56 | /* Add 1; spaces filled with 0. */ | ||
| 57 | static u_int8_t invmap[] | ||
| 58 | = { [ICMP_ECHO] = ICMP_ECHOREPLY + 1, | ||
| 59 | [ICMP_ECHOREPLY] = ICMP_ECHO + 1, | ||
| 60 | [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, | ||
| 61 | [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, | ||
| 62 | [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, | ||
| 63 | [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, | ||
| 64 | [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, | ||
| 65 | [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1}; | ||
| 66 | |||
| 67 | if (orig->dst.u.icmp.type >= sizeof(invmap) | ||
| 68 | || !invmap[orig->dst.u.icmp.type]) | ||
| 69 | return 0; | ||
| 70 | |||
| 71 | tuple->src.u.icmp.id = orig->src.u.icmp.id; | ||
| 72 | tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1; | ||
| 73 | tuple->dst.u.icmp.code = orig->dst.u.icmp.code; | ||
| 74 | return 1; | ||
| 75 | } | ||
| 76 | |||
| 77 | /* Print out the per-protocol part of the tuple. */ | ||
| 78 | static int icmp_print_tuple(struct seq_file *s, | ||
| 79 | const struct nf_conntrack_tuple *tuple) | ||
| 80 | { | ||
| 81 | return seq_printf(s, "type=%u code=%u id=%u ", | ||
| 82 | tuple->dst.u.icmp.type, | ||
| 83 | tuple->dst.u.icmp.code, | ||
| 84 | ntohs(tuple->src.u.icmp.id)); | ||
| 85 | } | ||
| 86 | |||
| 87 | /* Print out the private part of the conntrack. */ | ||
| 88 | static int icmp_print_conntrack(struct seq_file *s, | ||
| 89 | const struct nf_conn *conntrack) | ||
| 90 | { | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* Returns verdict for packet, or -1 for invalid. */ | ||
| 95 | static int icmp_packet(struct nf_conn *ct, | ||
| 96 | const struct sk_buff *skb, | ||
| 97 | unsigned int dataoff, | ||
| 98 | enum ip_conntrack_info ctinfo, | ||
| 99 | int pf, | ||
| 100 | unsigned int hooknum) | ||
| 101 | { | ||
| 102 | /* Try to delete connection immediately after all replies: | ||
| 103 | won't actually vanish as we still have skb, and del_timer | ||
| 104 | means this will only run once even if count hits zero twice | ||
| 105 | (theoretically possible with SMP) */ | ||
| 106 | if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { | ||
| 107 | if (atomic_dec_and_test(&ct->proto.icmp.count) | ||
| 108 | && del_timer(&ct->timeout)) | ||
| 109 | ct->timeout.function((unsigned long)ct); | ||
| 110 | } else { | ||
| 111 | atomic_inc(&ct->proto.icmp.count); | ||
| 112 | nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, skb); | ||
| 113 | nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); | ||
| 114 | } | ||
| 115 | |||
| 116 | return NF_ACCEPT; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* Called when a new connection for this protocol found. */ | ||
| 120 | static int icmp_new(struct nf_conn *conntrack, | ||
| 121 | const struct sk_buff *skb, unsigned int dataoff) | ||
| 122 | { | ||
| 123 | static u_int8_t valid_new[] | ||
| 124 | = { [ICMP_ECHO] = 1, | ||
| 125 | [ICMP_TIMESTAMP] = 1, | ||
| 126 | [ICMP_INFO_REQUEST] = 1, | ||
| 127 | [ICMP_ADDRESS] = 1 }; | ||
| 128 | |||
| 129 | if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) | ||
| 130 | || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) { | ||
| 131 | /* Can't create a new ICMP `conn' with this. */ | ||
| 132 | DEBUGP("icmp: can't create new conn with type %u\n", | ||
| 133 | conntrack->tuplehash[0].tuple.dst.u.icmp.type); | ||
| 134 | NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | atomic_set(&conntrack->proto.icmp.count, 0); | ||
| 138 | return 1; | ||
| 139 | } | ||
| 140 | |||
| 141 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4; | ||
| 142 | /* Returns conntrack if it dealt with ICMP, and filled in skb fields */ | ||
| 143 | static int | ||
| 144 | icmp_error_message(struct sk_buff *skb, | ||
| 145 | enum ip_conntrack_info *ctinfo, | ||
| 146 | unsigned int hooknum) | ||
| 147 | { | ||
| 148 | struct nf_conntrack_tuple innertuple, origtuple; | ||
| 149 | struct { | ||
| 150 | struct icmphdr icmp; | ||
| 151 | struct iphdr ip; | ||
| 152 | } _in, *inside; | ||
| 153 | struct nf_conntrack_protocol *innerproto; | ||
| 154 | struct nf_conntrack_tuple_hash *h; | ||
| 155 | int dataoff; | ||
| 156 | |||
| 157 | NF_CT_ASSERT(skb->nfct == NULL); | ||
| 158 | |||
| 159 | /* Not enough header? */ | ||
| 160 | inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); | ||
| 161 | if (inside == NULL) | ||
| 162 | return -NF_ACCEPT; | ||
| 163 | |||
| 164 | /* Ignore ICMP's containing fragments (shouldn't happen) */ | ||
| 165 | if (inside->ip.frag_off & htons(IP_OFFSET)) { | ||
| 166 | DEBUGP("icmp_error_message: fragment of proto %u\n", | ||
| 167 | inside->ip.protocol); | ||
| 168 | return -NF_ACCEPT; | ||
| 169 | } | ||
| 170 | |||
| 171 | innerproto = nf_ct_find_proto(PF_INET, inside->ip.protocol); | ||
| 172 | dataoff = skb->nh.iph->ihl*4 + sizeof(inside->icmp); | ||
| 173 | /* Are they talking about one of our connections? */ | ||
| 174 | if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET, | ||
| 175 | inside->ip.protocol, &origtuple, | ||
| 176 | &nf_conntrack_l3proto_ipv4, innerproto)) { | ||
| 177 | DEBUGP("icmp_error_message: ! get_tuple p=%u", | ||
| 178 | inside->ip.protocol); | ||
| 179 | return -NF_ACCEPT; | ||
| 180 | } | ||
| 181 | |||
| 182 | /* Ordinarily, we'd expect the inverted tupleproto, but it's | ||
| 183 | been preserved inside the ICMP. */ | ||
| 184 | if (!nf_ct_invert_tuple(&innertuple, &origtuple, | ||
| 185 | &nf_conntrack_l3proto_ipv4, innerproto)) { | ||
| 186 | DEBUGP("icmp_error_message: no match\n"); | ||
| 187 | return -NF_ACCEPT; | ||
| 188 | } | ||
| 189 | |||
| 190 | *ctinfo = IP_CT_RELATED; | ||
| 191 | |||
| 192 | h = nf_conntrack_find_get(&innertuple, NULL); | ||
| 193 | if (!h) { | ||
| 194 | /* Locally generated ICMPs will match inverted if they | ||
| 195 | haven't been SNAT'ed yet */ | ||
| 196 | /* FIXME: NAT code has to handle half-done double NAT --RR */ | ||
| 197 | if (hooknum == NF_IP_LOCAL_OUT) | ||
| 198 | h = nf_conntrack_find_get(&origtuple, NULL); | ||
| 199 | |||
| 200 | if (!h) { | ||
| 201 | DEBUGP("icmp_error_message: no match\n"); | ||
| 202 | return -NF_ACCEPT; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Reverse direction from that found */ | ||
| 206 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
| 207 | *ctinfo += IP_CT_IS_REPLY; | ||
| 208 | } else { | ||
| 209 | if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) | ||
| 210 | *ctinfo += IP_CT_IS_REPLY; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Update skb to refer to this connection */ | ||
| 214 | skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general; | ||
| 215 | skb->nfctinfo = *ctinfo; | ||
| 216 | return -NF_ACCEPT; | ||
| 217 | } | ||
| 218 | |||
| 219 | /* Small and modified version of icmp_rcv */ | ||
| 220 | static int | ||
| 221 | icmp_error(struct sk_buff *skb, unsigned int dataoff, | ||
| 222 | enum ip_conntrack_info *ctinfo, int pf, unsigned int hooknum) | ||
| 223 | { | ||
| 224 | struct icmphdr _ih, *icmph; | ||
| 225 | |||
| 226 | /* Not enough header? */ | ||
| 227 | icmph = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_ih), &_ih); | ||
| 228 | if (icmph == NULL) { | ||
| 229 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
| 230 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | ||
| 231 | "nf_ct_icmp: short packet "); | ||
| 232 | return -NF_ACCEPT; | ||
| 233 | } | ||
| 234 | |||
| 235 | /* See ip_conntrack_proto_tcp.c */ | ||
| 236 | if (hooknum != NF_IP_PRE_ROUTING) | ||
| 237 | goto checksum_skipped; | ||
| 238 | |||
| 239 | switch (skb->ip_summed) { | ||
| 240 | case CHECKSUM_HW: | ||
| 241 | if (!(u16)csum_fold(skb->csum)) | ||
| 242 | break; | ||
| 243 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
| 244 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | ||
| 245 | "nf_ct_icmp: bad HW ICMP checksum "); | ||
| 246 | return -NF_ACCEPT; | ||
| 247 | case CHECKSUM_NONE: | ||
| 248 | if ((u16)csum_fold(skb_checksum(skb, 0, skb->len, 0))) { | ||
| 249 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
| 250 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, | ||
| 251 | NULL, | ||
| 252 | "nf_ct_icmp: bad ICMP checksum "); | ||
| 253 | return -NF_ACCEPT; | ||
| 254 | } | ||
| 255 | default: | ||
| 256 | break; | ||
| 257 | } | ||
| 258 | |||
| 259 | checksum_skipped: | ||
| 260 | /* | ||
| 261 | * 18 is the highest 'known' ICMP type. Anything else is a mystery | ||
| 262 | * | ||
| 263 | * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently | ||
| 264 | * discarded. | ||
| 265 | */ | ||
| 266 | if (icmph->type > NR_ICMP_TYPES) { | ||
| 267 | if (LOG_INVALID(IPPROTO_ICMP)) | ||
| 268 | nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL, | ||
| 269 | "nf_ct_icmp: invalid ICMP type "); | ||
| 270 | return -NF_ACCEPT; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* Need to track icmp error message? */ | ||
| 274 | if (icmph->type != ICMP_DEST_UNREACH | ||
| 275 | && icmph->type != ICMP_SOURCE_QUENCH | ||
| 276 | && icmph->type != ICMP_TIME_EXCEEDED | ||
| 277 | && icmph->type != ICMP_PARAMETERPROB | ||
| 278 | && icmph->type != ICMP_REDIRECT) | ||
| 279 | return NF_ACCEPT; | ||
| 280 | |||
| 281 | return icmp_error_message(skb, ctinfo, hooknum); | ||
| 282 | } | ||
| 283 | |||
| 284 | struct nf_conntrack_protocol nf_conntrack_protocol_icmp = | ||
| 285 | { | ||
| 286 | .list = { NULL, NULL }, | ||
| 287 | .l3proto = PF_INET, | ||
| 288 | .proto = IPPROTO_ICMP, | ||
| 289 | .name = "icmp", | ||
| 290 | .pkt_to_tuple = icmp_pkt_to_tuple, | ||
| 291 | .invert_tuple = icmp_invert_tuple, | ||
| 292 | .print_tuple = icmp_print_tuple, | ||
| 293 | .print_conntrack = icmp_print_conntrack, | ||
| 294 | .packet = icmp_packet, | ||
| 295 | .new = icmp_new, | ||
| 296 | .error = icmp_error, | ||
| 297 | .destroy = NULL, | ||
| 298 | .me = NULL | ||
| 299 | }; | ||
| 300 | |||
| 301 | EXPORT_SYMBOL(nf_conntrack_protocol_icmp); | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f3f0013a9580..72b7c22e1ea5 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -2112,7 +2112,6 @@ void __init tcp_init(void) | |||
| 2112 | sysctl_tcp_max_orphans >>= (3 - order); | 2112 | sysctl_tcp_max_orphans >>= (3 - order); |
| 2113 | sysctl_max_syn_backlog = 128; | 2113 | sysctl_max_syn_backlog = 128; |
| 2114 | } | 2114 | } |
| 2115 | tcp_hashinfo.port_rover = sysctl_local_port_range[0] - 1; | ||
| 2116 | 2115 | ||
| 2117 | sysctl_tcp_mem[0] = 768 << order; | 2116 | sysctl_tcp_mem[0] = 768 << order; |
| 2118 | sysctl_tcp_mem[1] = 1024 << order; | 2117 | sysctl_tcp_mem[1] = 1024 << order; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c85819d8474b..634dabb558fd 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -93,8 +93,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { | |||
| 93 | .lhash_lock = RW_LOCK_UNLOCKED, | 93 | .lhash_lock = RW_LOCK_UNLOCKED, |
| 94 | .lhash_users = ATOMIC_INIT(0), | 94 | .lhash_users = ATOMIC_INIT(0), |
| 95 | .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), | 95 | .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait), |
| 96 | .portalloc_lock = SPIN_LOCK_UNLOCKED, | ||
| 97 | .port_rover = 1024 - 1, | ||
| 98 | }; | 96 | }; |
| 99 | 97 | ||
| 100 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) | 98 | static int tcp_v4_get_port(struct sock *sk, unsigned short snum) |
| @@ -825,8 +823,7 @@ out: | |||
| 825 | */ | 823 | */ |
| 826 | static void tcp_v4_reqsk_destructor(struct request_sock *req) | 824 | static void tcp_v4_reqsk_destructor(struct request_sock *req) |
| 827 | { | 825 | { |
| 828 | if (inet_rsk(req)->opt) | 826 | kfree(inet_rsk(req)->opt); |
| 829 | kfree(inet_rsk(req)->opt); | ||
| 830 | } | 827 | } |
| 831 | 828 | ||
| 832 | static inline void syn_flood_warning(struct sk_buff *skb) | 829 | static inline void syn_flood_warning(struct sk_buff *skb) |
