diff options
| author | David S. Miller <davem@davemloft.net> | 2009-06-29 22:22:31 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-06-29 22:22:31 -0400 |
| commit | 53bd9728bf9be7fc3b3147e821dbeb71d767c354 (patch) | |
| tree | 3e4dcda28ef94b6d67d24d22b4e1ec76f6fcd968 | |
| parent | bd46cb6cf11867130a41ea9546dd65688b71f3c2 (diff) | |
| parent | d6d3f08b0fd998b647a05540cedd11a067b72867 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-2.6
| -rw-r--r-- | include/linux/netfilter/xt_conntrack.h | 13 | ||||
| -rw-r--r-- | include/linux/netfilter/xt_osf.h | 2 | ||||
| -rw-r--r-- | include/net/netfilter/nf_conntrack.h | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nf_nat_helper.c | 17 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 4 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_extend.c | 2 | ||||
| -rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 6 | ||||
| -rw-r--r-- | net/netfilter/xt_conntrack.c | 66 |
8 files changed, 95 insertions, 19 deletions
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h index 3430c7751948..7ae05338e94c 100644 --- a/include/linux/netfilter/xt_conntrack.h +++ b/include/linux/netfilter/xt_conntrack.h | |||
| @@ -81,4 +81,17 @@ struct xt_conntrack_mtinfo1 { | |||
| 81 | __u8 state_mask, status_mask; | 81 | __u8 state_mask, status_mask; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | struct xt_conntrack_mtinfo2 { | ||
| 85 | union nf_inet_addr origsrc_addr, origsrc_mask; | ||
| 86 | union nf_inet_addr origdst_addr, origdst_mask; | ||
| 87 | union nf_inet_addr replsrc_addr, replsrc_mask; | ||
| 88 | union nf_inet_addr repldst_addr, repldst_mask; | ||
| 89 | __u32 expires_min, expires_max; | ||
| 90 | __u16 l4proto; | ||
| 91 | __be16 origsrc_port, origdst_port; | ||
| 92 | __be16 replsrc_port, repldst_port; | ||
| 93 | __u16 match_flags, invert_flags; | ||
| 94 | __u16 state_mask, status_mask; | ||
| 95 | }; | ||
| 96 | |||
| 84 | #endif /*_XT_CONNTRACK_H*/ | 97 | #endif /*_XT_CONNTRACK_H*/ |
diff --git a/include/linux/netfilter/xt_osf.h b/include/linux/netfilter/xt_osf.h index fd2272e0959a..18afa495f973 100644 --- a/include/linux/netfilter/xt_osf.h +++ b/include/linux/netfilter/xt_osf.h | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #ifndef _XT_OSF_H | 20 | #ifndef _XT_OSF_H |
| 21 | #define _XT_OSF_H | 21 | #define _XT_OSF_H |
| 22 | 22 | ||
| 23 | #include <linux/types.h> | ||
| 24 | |||
| 23 | #define MAXGENRELEN 32 | 25 | #define MAXGENRELEN 32 |
| 24 | 26 | ||
| 25 | #define XT_OSF_GENRE (1<<0) | 27 | #define XT_OSF_GENRE (1<<0) |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index a632689b61b4..cbdd6284996d 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
| @@ -258,8 +258,8 @@ static inline bool nf_ct_kill(struct nf_conn *ct) | |||
| 258 | /* Update TCP window tracking data when NAT mangles the packet */ | 258 | /* Update TCP window tracking data when NAT mangles the packet */ |
| 259 | extern void nf_conntrack_tcp_update(const struct sk_buff *skb, | 259 | extern void nf_conntrack_tcp_update(const struct sk_buff *skb, |
| 260 | unsigned int dataoff, | 260 | unsigned int dataoff, |
| 261 | struct nf_conn *ct, | 261 | struct nf_conn *ct, int dir, |
| 262 | int dir); | 262 | s16 offset); |
| 263 | 263 | ||
| 264 | /* Fake conntrack entry for untracked connections */ | 264 | /* Fake conntrack entry for untracked connections */ |
| 265 | extern struct nf_conn nf_conntrack_untracked; | 265 | extern struct nf_conn nf_conntrack_untracked; |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 155c008626c8..09172a65d9b6 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
| @@ -191,7 +191,8 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
| 191 | ct, ctinfo); | 191 | ct, ctinfo); |
| 192 | /* Tell TCP window tracking about seq change */ | 192 | /* Tell TCP window tracking about seq change */ |
| 193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), | 193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), |
| 194 | ct, CTINFO2DIR(ctinfo)); | 194 | ct, CTINFO2DIR(ctinfo), |
| 195 | (int)rep_len - (int)match_len); | ||
| 195 | 196 | ||
| 196 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | 197 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); |
| 197 | } | 198 | } |
| @@ -377,6 +378,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
| 377 | struct tcphdr *tcph; | 378 | struct tcphdr *tcph; |
| 378 | int dir; | 379 | int dir; |
| 379 | __be32 newseq, newack; | 380 | __be32 newseq, newack; |
| 381 | s16 seqoff, ackoff; | ||
| 380 | struct nf_conn_nat *nat = nfct_nat(ct); | 382 | struct nf_conn_nat *nat = nfct_nat(ct); |
| 381 | struct nf_nat_seq *this_way, *other_way; | 383 | struct nf_nat_seq *this_way, *other_way; |
| 382 | 384 | ||
| @@ -390,15 +392,18 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
| 390 | 392 | ||
| 391 | tcph = (void *)skb->data + ip_hdrlen(skb); | 393 | tcph = (void *)skb->data + ip_hdrlen(skb); |
| 392 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 394 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
| 393 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); | 395 | seqoff = this_way->offset_after; |
| 394 | else | 396 | else |
| 395 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); | 397 | seqoff = this_way->offset_before; |
| 396 | 398 | ||
| 397 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, | 399 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, |
| 398 | other_way->correction_pos)) | 400 | other_way->correction_pos)) |
| 399 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); | 401 | ackoff = other_way->offset_after; |
| 400 | else | 402 | else |
| 401 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 403 | ackoff = other_way->offset_before; |
| 404 | |||
| 405 | newseq = htonl(ntohl(tcph->seq) + seqoff); | ||
| 406 | newack = htonl(ntohl(tcph->ack_seq) - ackoff); | ||
| 402 | 407 | ||
| 403 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); | 408 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); |
| 404 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); | 409 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); |
| @@ -413,7 +418,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
| 413 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) | 418 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) |
| 414 | return 0; | 419 | return 0; |
| 415 | 420 | ||
| 416 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); | 421 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); |
| 417 | 422 | ||
| 418 | return 1; | 423 | return 1; |
| 419 | } | 424 | } |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index afde8f991646..2032dfe25ca8 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -617,8 +617,10 @@ err1: | |||
| 617 | void nf_conntrack_expect_fini(struct net *net) | 617 | void nf_conntrack_expect_fini(struct net *net) |
| 618 | { | 618 | { |
| 619 | exp_proc_remove(net); | 619 | exp_proc_remove(net); |
| 620 | if (net_eq(net, &init_net)) | 620 | if (net_eq(net, &init_net)) { |
| 621 | rcu_barrier(); /* Wait for call_rcu() before destroy */ | ||
| 621 | kmem_cache_destroy(nf_ct_expect_cachep); | 622 | kmem_cache_destroy(nf_ct_expect_cachep); |
| 623 | } | ||
| 622 | nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, | 624 | nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, |
| 623 | nf_ct_expect_hsize); | 625 | nf_ct_expect_hsize); |
| 624 | } | 626 | } |
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 4b2c769d555f..fef95be334bd 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c | |||
| @@ -186,6 +186,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) | |||
| 186 | rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); | 186 | rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); |
| 187 | update_alloc_size(type); | 187 | update_alloc_size(type); |
| 188 | mutex_unlock(&nf_ct_ext_type_mutex); | 188 | mutex_unlock(&nf_ct_ext_type_mutex); |
| 189 | synchronize_rcu(); | 189 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
| 190 | } | 190 | } |
| 191 | EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); | 191 | EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 33fc0a443f3d..97a82ba75376 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
| @@ -720,8 +720,8 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
| 720 | /* Caller must linearize skb at tcp header. */ | 720 | /* Caller must linearize skb at tcp header. */ |
| 721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, | 721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, |
| 722 | unsigned int dataoff, | 722 | unsigned int dataoff, |
| 723 | struct nf_conn *ct, | 723 | struct nf_conn *ct, int dir, |
| 724 | int dir) | 724 | s16 offset) |
| 725 | { | 725 | { |
| 726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; | 726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; |
| 727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; | 727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; |
| @@ -734,7 +734,7 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb, | |||
| 734 | /* | 734 | /* |
| 735 | * We have to worry for the ack in the reply packet only... | 735 | * We have to worry for the ack in the reply packet only... |
| 736 | */ | 736 | */ |
| 737 | if (after(end, ct->proto.tcp.seen[dir].td_end)) | 737 | if (ct->proto.tcp.seen[dir].td_end + offset == end) |
| 738 | ct->proto.tcp.seen[dir].td_end = end; | 738 | ct->proto.tcp.seen[dir].td_end = end; |
| 739 | ct->proto.tcp.last_end = end; | 739 | ct->proto.tcp.last_end = end; |
| 740 | spin_unlock_bh(&ct->lock); | 740 | spin_unlock_bh(&ct->lock); |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 0b7139f3dd78..fc581800698e 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
| @@ -129,7 +129,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr, | |||
| 129 | 129 | ||
| 130 | static inline bool | 130 | static inline bool |
| 131 | conntrack_mt_origsrc(const struct nf_conn *ct, | 131 | conntrack_mt_origsrc(const struct nf_conn *ct, |
| 132 | const struct xt_conntrack_mtinfo1 *info, | 132 | const struct xt_conntrack_mtinfo2 *info, |
| 133 | u_int8_t family) | 133 | u_int8_t family) |
| 134 | { | 134 | { |
| 135 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, | 135 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, |
| @@ -138,7 +138,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct, | |||
| 138 | 138 | ||
| 139 | static inline bool | 139 | static inline bool |
| 140 | conntrack_mt_origdst(const struct nf_conn *ct, | 140 | conntrack_mt_origdst(const struct nf_conn *ct, |
| 141 | const struct xt_conntrack_mtinfo1 *info, | 141 | const struct xt_conntrack_mtinfo2 *info, |
| 142 | u_int8_t family) | 142 | u_int8_t family) |
| 143 | { | 143 | { |
| 144 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, | 144 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, |
| @@ -147,7 +147,7 @@ conntrack_mt_origdst(const struct nf_conn *ct, | |||
| 147 | 147 | ||
| 148 | static inline bool | 148 | static inline bool |
| 149 | conntrack_mt_replsrc(const struct nf_conn *ct, | 149 | conntrack_mt_replsrc(const struct nf_conn *ct, |
| 150 | const struct xt_conntrack_mtinfo1 *info, | 150 | const struct xt_conntrack_mtinfo2 *info, |
| 151 | u_int8_t family) | 151 | u_int8_t family) |
| 152 | { | 152 | { |
| 153 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, | 153 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, |
| @@ -156,7 +156,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct, | |||
| 156 | 156 | ||
| 157 | static inline bool | 157 | static inline bool |
| 158 | conntrack_mt_repldst(const struct nf_conn *ct, | 158 | conntrack_mt_repldst(const struct nf_conn *ct, |
| 159 | const struct xt_conntrack_mtinfo1 *info, | 159 | const struct xt_conntrack_mtinfo2 *info, |
| 160 | u_int8_t family) | 160 | u_int8_t family) |
| 161 | { | 161 | { |
| 162 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, | 162 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, |
| @@ -164,7 +164,7 @@ conntrack_mt_repldst(const struct nf_conn *ct, | |||
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | static inline bool | 166 | static inline bool |
| 167 | ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, | 167 | ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, |
| 168 | const struct nf_conn *ct) | 168 | const struct nf_conn *ct) |
| 169 | { | 169 | { |
| 170 | const struct nf_conntrack_tuple *tuple; | 170 | const struct nf_conntrack_tuple *tuple; |
| @@ -204,7 +204,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, | |||
| 204 | static bool | 204 | static bool |
| 205 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 205 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) |
| 206 | { | 206 | { |
| 207 | const struct xt_conntrack_mtinfo1 *info = par->matchinfo; | 207 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; |
| 208 | enum ip_conntrack_info ctinfo; | 208 | enum ip_conntrack_info ctinfo; |
| 209 | const struct nf_conn *ct; | 209 | const struct nf_conn *ct; |
| 210 | unsigned int statebit; | 210 | unsigned int statebit; |
| @@ -278,6 +278,16 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
| 278 | return true; | 278 | return true; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static bool | ||
| 282 | conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | ||
| 283 | { | ||
| 284 | const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; | ||
| 285 | struct xt_match_param newpar = *par; | ||
| 286 | |||
| 287 | newpar.matchinfo = *info; | ||
| 288 | return conntrack_mt(skb, &newpar); | ||
| 289 | } | ||
| 290 | |||
| 281 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) | 291 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) |
| 282 | { | 292 | { |
| 283 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 293 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { |
| @@ -288,11 +298,45 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par) | |||
| 288 | return true; | 298 | return true; |
| 289 | } | 299 | } |
| 290 | 300 | ||
| 301 | static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) | ||
| 302 | { | ||
| 303 | struct xt_conntrack_mtinfo1 *info = par->matchinfo; | ||
| 304 | struct xt_conntrack_mtinfo2 *up; | ||
| 305 | int ret = conntrack_mt_check(par); | ||
| 306 | |||
| 307 | if (ret < 0) | ||
| 308 | return ret; | ||
| 309 | |||
| 310 | up = kmalloc(sizeof(*up), GFP_KERNEL); | ||
| 311 | if (up == NULL) { | ||
| 312 | nf_ct_l3proto_module_put(par->family); | ||
| 313 | return -ENOMEM; | ||
| 314 | } | ||
| 315 | |||
| 316 | /* | ||
| 317 | * The strategy here is to minimize the overhead of v1 matching, | ||
| 318 | * by prebuilding a v2 struct and putting the pointer into the | ||
| 319 | * v1 dataspace. | ||
| 320 | */ | ||
| 321 | memcpy(up, info, offsetof(typeof(*info), state_mask)); | ||
| 322 | up->state_mask = info->state_mask; | ||
| 323 | up->status_mask = info->status_mask; | ||
| 324 | *(void **)info = up; | ||
| 325 | return true; | ||
| 326 | } | ||
| 327 | |||
| 291 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) | 328 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) |
| 292 | { | 329 | { |
| 293 | nf_ct_l3proto_module_put(par->family); | 330 | nf_ct_l3proto_module_put(par->family); |
| 294 | } | 331 | } |
| 295 | 332 | ||
| 333 | static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) | ||
| 334 | { | ||
| 335 | struct xt_conntrack_mtinfo2 **info = par->matchinfo; | ||
| 336 | kfree(*info); | ||
| 337 | conntrack_mt_destroy(par); | ||
| 338 | } | ||
| 339 | |||
| 296 | #ifdef CONFIG_COMPAT | 340 | #ifdef CONFIG_COMPAT |
| 297 | struct compat_xt_conntrack_info | 341 | struct compat_xt_conntrack_info |
| 298 | { | 342 | { |
| @@ -363,6 +407,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { | |||
| 363 | .revision = 1, | 407 | .revision = 1, |
| 364 | .family = NFPROTO_UNSPEC, | 408 | .family = NFPROTO_UNSPEC, |
| 365 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), | 409 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), |
| 410 | .match = conntrack_mt_v1, | ||
| 411 | .checkentry = conntrack_mt_check_v1, | ||
| 412 | .destroy = conntrack_mt_destroy_v1, | ||
| 413 | .me = THIS_MODULE, | ||
| 414 | }, | ||
| 415 | { | ||
| 416 | .name = "conntrack", | ||
| 417 | .revision = 2, | ||
| 418 | .family = NFPROTO_UNSPEC, | ||
| 419 | .matchsize = sizeof(struct xt_conntrack_mtinfo2), | ||
| 366 | .match = conntrack_mt, | 420 | .match = conntrack_mt, |
| 367 | .checkentry = conntrack_mt_check, | 421 | .checkentry = conntrack_mt_check, |
| 368 | .destroy = conntrack_mt_destroy, | 422 | .destroy = conntrack_mt_destroy, |
