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); |