diff options
| -rw-r--r-- | include/linux/netfilter/nfnetlink.h | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 83 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_icmp.c | 15 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 11 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ip_nat_helper_pptp.c | 28 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 3 | ||||
| -rw-r--r-- | net/ipv6/ip6_tunnel.c | 1 | ||||
| -rw-r--r-- | net/netfilter/nfnetlink.c | 21 |
8 files changed, 92 insertions, 72 deletions
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index f08e870100f4..72975fa8795d 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
| @@ -146,7 +146,7 @@ extern void nfnl_unlock(void); | |||
| 146 | extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); | 146 | extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); |
| 147 | extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); | 147 | extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); |
| 148 | 148 | ||
| 149 | extern int nfattr_parse(struct nfattr *tb[], int maxattr, | 149 | extern void nfattr_parse(struct nfattr *tb[], int maxattr, |
| 150 | struct nfattr *nfa, int len); | 150 | struct nfattr *nfa, int len); |
| 151 | 151 | ||
| 152 | #define nfattr_parse_nested(tb, max, nfa) \ | 152 | #define nfattr_parse_nested(tb, max, nfa) \ |
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 82a65043a8ef..5c1c0a3d1c4b 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; |
| @@ -827,7 +802,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 827 | free: | 802 | free: |
| 828 | kfree_skb(skb2); | 803 | kfree_skb(skb2); |
| 829 | out: | 804 | out: |
| 830 | return -1; | 805 | return err; |
| 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) |
| @@ -1554,6 +1543,8 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { | |||
| 1554 | .cb = ctnl_exp_cb, | 1543 | .cb = ctnl_exp_cb, |
| 1555 | }; | 1544 | }; |
| 1556 | 1545 | ||
| 1546 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); | ||
| 1547 | |||
| 1557 | static int __init ctnetlink_init(void) | 1548 | static int __init ctnetlink_init(void) |
| 1558 | { | 1549 | { |
| 1559 | 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_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index ee6ab74ad3a9..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,7 +237,7 @@ 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); |
| 219 | expect_orig->dir = IP_CT_DIR_ORIGINAL; | 243 | expect_orig->dir = IP_CT_DIR_ORIGINAL; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b7a5f51238b3..ddcf7754eec2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1022,6 +1022,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 1022 | continue; | 1022 | continue; |
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | #ifdef CONFIG_IPV6_PRIVACY | ||
| 1025 | /* Rule 7: Prefer public address | 1026 | /* Rule 7: Prefer public address |
| 1026 | * Note: prefer temprary address if use_tempaddr >= 2 | 1027 | * Note: prefer temprary address if use_tempaddr >= 2 |
| 1027 | */ | 1028 | */ |
| @@ -1042,7 +1043,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, | |||
| 1042 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) | 1043 | if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY) |
| 1043 | continue; | 1044 | continue; |
| 1044 | } | 1045 | } |
| 1045 | 1046 | #endif | |
| 1046 | /* Rule 8: Use longest matching prefix */ | 1047 | /* Rule 8: Use longest matching prefix */ |
| 1047 | if (hiscore.rule < 8) | 1048 | if (hiscore.rule < 8) |
| 1048 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); | 1049 | hiscore.matchlen = ipv6_addr_diff(&ifa_result->addr, daddr); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e6b0e3954c02..e315d0f80af1 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -525,6 +525,7 @@ ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
| 525 | 525 | ||
| 526 | if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { | 526 | if ((t = ip6ip6_tnl_lookup(&ipv6h->saddr, &ipv6h->daddr)) != NULL) { |
| 527 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 527 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 528 | read_unlock(&ip6ip6_lock); | ||
| 528 | kfree_skb(skb); | 529 | kfree_skb(skb); |
| 529 | return 0; | 530 | return 0; |
| 530 | } | 531 | } |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4bc27a6334c1..83f4c53030fc 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
| @@ -128,7 +128,7 @@ void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen, | |||
| 128 | memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size); | 128 | memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) | 131 | void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) |
| 132 | { | 132 | { |
| 133 | memset(tb, 0, sizeof(struct nfattr *) * maxattr); | 133 | memset(tb, 0, sizeof(struct nfattr *) * maxattr); |
| 134 | 134 | ||
| @@ -138,8 +138,6 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) | |||
| 138 | tb[flavor-1] = nfa; | 138 | tb[flavor-1] = nfa; |
| 139 | nfa = NFA_NEXT(nfa, len); | 139 | nfa = NFA_NEXT(nfa, len); |
| 140 | } | 140 | } |
| 141 | |||
| 142 | return 0; | ||
| 143 | } | 141 | } |
| 144 | 142 | ||
| 145 | /** | 143 | /** |
| @@ -242,15 +240,18 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, | |||
| 242 | ss = nfnetlink_get_subsys(type); | 240 | ss = nfnetlink_get_subsys(type); |
| 243 | if (!ss) { | 241 | if (!ss) { |
| 244 | #ifdef CONFIG_KMOD | 242 | #ifdef CONFIG_KMOD |
| 245 | /* don't call nfnl_shunlock, since it would reenter | 243 | if (cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { |
| 246 | * with further packet processing */ | 244 | /* don't call nfnl_shunlock, since it would reenter |
| 247 | up(&nfnl_sem); | 245 | * with further packet processing */ |
| 248 | request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); | 246 | up(&nfnl_sem); |
| 249 | nfnl_shlock(); | 247 | request_module("nfnetlink-subsys-%d", |
| 250 | ss = nfnetlink_get_subsys(type); | 248 | NFNL_SUBSYS_ID(type)); |
| 249 | nfnl_shlock(); | ||
| 250 | ss = nfnetlink_get_subsys(type); | ||
| 251 | } | ||
| 251 | if (!ss) | 252 | if (!ss) |
| 252 | #endif | 253 | #endif |
| 253 | goto err_inval; | 254 | goto err_inval; |
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | nc = nfnetlink_find_client(type, ss); | 257 | nc = nfnetlink_find_client(type, ss); |
