diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/inet6_connection_sock.c | 23 | ||||
| -rw-r--r-- | net/ipv6/ip6_fib.c | 4 | ||||
| -rw-r--r-- | net/ipv6/mip6.c | 20 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 21 | ||||
| -rw-r--r-- | net/ipv6/route.c | 19 |
5 files changed, 38 insertions, 49 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 0251a6005be8..c4f934176cab 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
| @@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst, | |||
| 175 | const struct in6_addr *saddr) | 175 | const struct in6_addr *saddr) |
| 176 | { | 176 | { |
| 177 | __ip6_dst_store(sk, dst, daddr, saddr); | 177 | __ip6_dst_store(sk, dst, daddr, saddr); |
| 178 | |||
| 179 | #ifdef CONFIG_XFRM | ||
| 180 | { | ||
| 181 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
| 182 | rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); | ||
| 183 | } | ||
| 184 | #endif | ||
| 185 | } | 178 | } |
| 186 | 179 | ||
| 187 | static inline | 180 | static inline |
| 188 | struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | 181 | struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) |
| 189 | { | 182 | { |
| 190 | struct dst_entry *dst; | 183 | return __sk_dst_check(sk, cookie); |
| 191 | |||
| 192 | dst = __sk_dst_check(sk, cookie); | ||
| 193 | |||
| 194 | #ifdef CONFIG_XFRM | ||
| 195 | if (dst) { | ||
| 196 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
| 197 | if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) { | ||
| 198 | __sk_dst_reset(sk); | ||
| 199 | dst = NULL; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | #endif | ||
| 203 | |||
| 204 | return dst; | ||
| 205 | } | 184 | } |
| 206 | 185 | ||
| 207 | static struct dst_entry *inet6_csk_route_socket(struct sock *sk, | 186 | static struct dst_entry *inet6_csk_route_socket(struct sock *sk, |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 13690d650c3e..286acfc21250 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -819,6 +819,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
| 819 | offsetof(struct rt6_info, rt6i_src), | 819 | offsetof(struct rt6_info, rt6i_src), |
| 820 | allow_create, replace_required); | 820 | allow_create, replace_required); |
| 821 | 821 | ||
| 822 | if (IS_ERR(sn)) { | ||
| 823 | err = PTR_ERR(sn); | ||
| 824 | sn = NULL; | ||
| 825 | } | ||
| 822 | if (!sn) { | 826 | if (!sn) { |
| 823 | /* If it is failed, discard just allocated | 827 | /* If it is failed, discard just allocated |
| 824 | root, and then (in st_failure) stale node | 828 | root, and then (in st_failure) stale node |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 5b087c31d87b..0f9bdc5ee9f3 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
| @@ -86,28 +86,30 @@ static int mip6_mh_len(int type) | |||
| 86 | 86 | ||
| 87 | static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) | 87 | static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) |
| 88 | { | 88 | { |
| 89 | struct ip6_mh *mh; | 89 | struct ip6_mh _hdr; |
| 90 | const struct ip6_mh *mh; | ||
| 90 | 91 | ||
| 91 | if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || | 92 | mh = skb_header_pointer(skb, skb_transport_offset(skb), |
| 92 | !pskb_may_pull(skb, (skb_transport_offset(skb) + | 93 | sizeof(_hdr), &_hdr); |
| 93 | ((skb_transport_header(skb)[1] + 1) << 3)))) | 94 | if (!mh) |
| 94 | return -1; | 95 | return -1; |
| 95 | 96 | ||
| 96 | mh = (struct ip6_mh *)skb_transport_header(skb); | 97 | if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) |
| 98 | return -1; | ||
| 97 | 99 | ||
| 98 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { | 100 | if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { |
| 99 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", | 101 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", |
| 100 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); | 102 | mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); |
| 101 | mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - | 103 | mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + |
| 102 | skb_network_header(skb))); | 104 | skb_network_header_len(skb)); |
| 103 | return -1; | 105 | return -1; |
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | if (mh->ip6mh_proto != IPPROTO_NONE) { | 108 | if (mh->ip6mh_proto != IPPROTO_NONE) { |
| 107 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", | 109 | LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", |
| 108 | mh->ip6mh_proto); | 110 | mh->ip6mh_proto); |
| 109 | mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - | 111 | mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + |
| 110 | skb_network_header(skb))); | 112 | skb_network_header_len(skb)); |
| 111 | return -1; | 113 | return -1; |
| 112 | } | 114 | } |
| 113 | 115 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ef0579d5bca6..4a5f78b50495 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -107,21 +107,20 @@ found: | |||
| 107 | * 0 - deliver | 107 | * 0 - deliver |
| 108 | * 1 - block | 108 | * 1 - block |
| 109 | */ | 109 | */ |
| 110 | static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) | 110 | static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) |
| 111 | { | 111 | { |
| 112 | struct icmp6hdr *icmph; | 112 | struct icmp6hdr *_hdr; |
| 113 | struct raw6_sock *rp = raw6_sk(sk); | 113 | const struct icmp6hdr *hdr; |
| 114 | |||
| 115 | if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { | ||
| 116 | __u32 *data = &rp->filter.data[0]; | ||
| 117 | int bit_nr; | ||
| 118 | 114 | ||
| 119 | icmph = (struct icmp6hdr *) skb->data; | 115 | hdr = skb_header_pointer(skb, skb_transport_offset(skb), |
| 120 | bit_nr = icmph->icmp6_type; | 116 | sizeof(_hdr), &_hdr); |
| 117 | if (hdr) { | ||
| 118 | const __u32 *data = &raw6_sk(sk)->filter.data[0]; | ||
| 119 | unsigned int type = hdr->icmp6_type; | ||
| 121 | 120 | ||
| 122 | return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; | 121 | return (data[type >> 5] & (1U << (type & 31))) != 0; |
| 123 | } | 122 | } |
| 124 | return 0; | 123 | return 1; |
| 125 | } | 124 | } |
| 126 | 125 | ||
| 127 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 126 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8e80fd279100..854e4018d205 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = { | |||
| 226 | .dst = { | 226 | .dst = { |
| 227 | .__refcnt = ATOMIC_INIT(1), | 227 | .__refcnt = ATOMIC_INIT(1), |
| 228 | .__use = 1, | 228 | .__use = 1, |
| 229 | .obsolete = -1, | 229 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
| 230 | .error = -ENETUNREACH, | 230 | .error = -ENETUNREACH, |
| 231 | .input = ip6_pkt_discard, | 231 | .input = ip6_pkt_discard, |
| 232 | .output = ip6_pkt_discard_out, | 232 | .output = ip6_pkt_discard_out, |
| @@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
| 246 | .dst = { | 246 | .dst = { |
| 247 | .__refcnt = ATOMIC_INIT(1), | 247 | .__refcnt = ATOMIC_INIT(1), |
| 248 | .__use = 1, | 248 | .__use = 1, |
| 249 | .obsolete = -1, | 249 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
| 250 | .error = -EACCES, | 250 | .error = -EACCES, |
| 251 | .input = ip6_pkt_prohibit, | 251 | .input = ip6_pkt_prohibit, |
| 252 | .output = ip6_pkt_prohibit_out, | 252 | .output = ip6_pkt_prohibit_out, |
| @@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
| 261 | .dst = { | 261 | .dst = { |
| 262 | .__refcnt = ATOMIC_INIT(1), | 262 | .__refcnt = ATOMIC_INIT(1), |
| 263 | .__use = 1, | 263 | .__use = 1, |
| 264 | .obsolete = -1, | 264 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
| 265 | .error = -EINVAL, | 265 | .error = -EINVAL, |
| 266 | .input = dst_discard, | 266 | .input = dst_discard, |
| 267 | .output = dst_discard, | 267 | .output = dst_discard, |
| @@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, | |||
| 281 | struct fib6_table *table) | 281 | struct fib6_table *table) |
| 282 | { | 282 | { |
| 283 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, | 283 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, |
| 284 | 0, DST_OBSOLETE_NONE, flags); | 284 | 0, DST_OBSOLETE_FORCE_CHK, flags); |
| 285 | 285 | ||
| 286 | if (rt) { | 286 | if (rt) { |
| 287 | struct dst_entry *dst = &rt->dst; | 287 | struct dst_entry *dst = &rt->dst; |
| 288 | 288 | ||
| 289 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); | 289 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); |
| 290 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); | 290 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); |
| 291 | rt->rt6i_genid = rt_genid(net); | ||
| 291 | } | 292 | } |
| 292 | return rt; | 293 | return rt; |
| 293 | } | 294 | } |
| @@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
| 1031 | 1032 | ||
| 1032 | rt = (struct rt6_info *) dst; | 1033 | rt = (struct rt6_info *) dst; |
| 1033 | 1034 | ||
| 1035 | /* All IPV6 dsts are created with ->obsolete set to the value | ||
| 1036 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | ||
| 1037 | * into this function always. | ||
| 1038 | */ | ||
| 1039 | if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) | ||
| 1040 | return NULL; | ||
| 1041 | |||
| 1034 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { | 1042 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { |
| 1035 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { | 1043 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { |
| 1036 | if (!rt6_has_peer(rt)) | 1044 | if (!rt6_has_peer(rt)) |
| @@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1397 | goto out; | 1405 | goto out; |
| 1398 | } | 1406 | } |
| 1399 | 1407 | ||
| 1400 | rt->dst.obsolete = -1; | ||
| 1401 | |||
| 1402 | if (cfg->fc_flags & RTF_EXPIRES) | 1408 | if (cfg->fc_flags & RTF_EXPIRES) |
| 1403 | rt6_set_expires(rt, jiffies + | 1409 | rt6_set_expires(rt, jiffies + |
| 1404 | clock_t_to_jiffies(cfg->fc_expires)); | 1410 | clock_t_to_jiffies(cfg->fc_expires)); |
| @@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
| 2080 | rt->dst.input = ip6_input; | 2086 | rt->dst.input = ip6_input; |
| 2081 | rt->dst.output = ip6_output; | 2087 | rt->dst.output = ip6_output; |
| 2082 | rt->rt6i_idev = idev; | 2088 | rt->rt6i_idev = idev; |
| 2083 | rt->dst.obsolete = -1; | ||
| 2084 | 2089 | ||
| 2085 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 2090 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
| 2086 | if (anycast) | 2091 | if (anycast) |
