diff options
| -rw-r--r-- | include/linux/in6.h | 8 | ||||
| -rw-r--r-- | include/net/addrconf.h | 87 | ||||
| -rw-r--r-- | include/net/ip6_route.h | 6 | ||||
| -rw-r--r-- | include/net/ipv6.h | 26 | ||||
| -rw-r--r-- | include/net/mip6.h | 3 | ||||
| -rw-r--r-- | include/net/ndisc.h | 14 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 82 | ||||
| -rw-r--r-- | net/ipv6/fib6_rules.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 26 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 37 | ||||
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 81 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 60 | ||||
| -rw-r--r-- | net/ipv6/mip6.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 27 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 20 | ||||
| -rw-r--r-- | net/ipv6/route.c | 6 | ||||
| -rw-r--r-- | net/ipv6/sit.c | 2 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 5 |
20 files changed, 264 insertions, 238 deletions
diff --git a/include/linux/in6.h b/include/linux/in6.h index e6aa8de2b939..bc492048c349 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h | |||
| @@ -48,6 +48,14 @@ extern const struct in6_addr in6addr_any; | |||
| 48 | #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } | 48 | #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } |
| 49 | extern const struct in6_addr in6addr_loopback; | 49 | extern const struct in6_addr in6addr_loopback; |
| 50 | #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } | 50 | #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } |
| 51 | #ifdef __KERNEL__ | ||
| 52 | extern const struct in6_addr in6addr_linklocal_allnodes; | ||
| 53 | #define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ | ||
| 54 | { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } | ||
| 55 | extern const struct in6_addr in6addr_linklocal_allrouters; | ||
| 56 | #define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \ | ||
| 57 | { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2 } } } | ||
| 58 | #endif | ||
| 51 | 59 | ||
| 52 | struct sockaddr_in6 { | 60 | struct sockaddr_in6 { |
| 53 | unsigned short int sin6_family; /* AF_INET6 */ | 61 | unsigned short int sin6_family; /* AF_INET6 */ |
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index bdcc863a60a4..0a2f0372df31 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h | |||
| @@ -76,12 +76,12 @@ extern int ipv6_chk_prefix(struct in6_addr *addr, | |||
| 76 | struct net_device *dev); | 76 | struct net_device *dev); |
| 77 | 77 | ||
| 78 | extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, | 78 | extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, |
| 79 | struct in6_addr *addr, | 79 | const struct in6_addr *addr, |
| 80 | struct net_device *dev, | 80 | struct net_device *dev, |
| 81 | int strict); | 81 | int strict); |
| 82 | 82 | ||
| 83 | extern int ipv6_dev_get_saddr(struct net_device *dev, | 83 | extern int ipv6_dev_get_saddr(struct net_device *dev, |
| 84 | struct in6_addr *daddr, | 84 | const struct in6_addr *daddr, |
| 85 | unsigned int srcprefs, | 85 | unsigned int srcprefs, |
| 86 | struct in6_addr *saddr); | 86 | struct in6_addr *saddr); |
| 87 | extern int ipv6_get_lladdr(struct net_device *dev, | 87 | extern int ipv6_get_lladdr(struct net_device *dev, |
| @@ -105,25 +105,27 @@ extern u32 ipv6_addr_label(const struct in6_addr *addr, | |||
| 105 | /* | 105 | /* |
| 106 | * multicast prototypes (mcast.c) | 106 | * multicast prototypes (mcast.c) |
| 107 | */ | 107 | */ |
| 108 | extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, | 108 | extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, |
| 109 | struct in6_addr *addr); | 109 | const struct in6_addr *addr); |
| 110 | extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, | 110 | extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, |
| 111 | struct in6_addr *addr); | 111 | const struct in6_addr *addr); |
| 112 | extern void ipv6_sock_mc_close(struct sock *sk); | 112 | extern void ipv6_sock_mc_close(struct sock *sk); |
| 113 | extern int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | 113 | extern int inet6_mc_check(struct sock *sk, |
| 114 | struct in6_addr *src_addr); | 114 | const struct in6_addr *mc_addr, |
| 115 | const struct in6_addr *src_addr); | ||
| 115 | 116 | ||
| 116 | extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr); | 117 | extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr); |
| 117 | extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); | 118 | extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr); |
| 118 | extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr); | 119 | extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr); |
| 119 | extern void ipv6_mc_up(struct inet6_dev *idev); | 120 | extern void ipv6_mc_up(struct inet6_dev *idev); |
| 120 | extern void ipv6_mc_down(struct inet6_dev *idev); | 121 | extern void ipv6_mc_down(struct inet6_dev *idev); |
| 121 | extern void ipv6_mc_init_dev(struct inet6_dev *idev); | 122 | extern void ipv6_mc_init_dev(struct inet6_dev *idev); |
| 122 | extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); | 123 | extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); |
| 123 | extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); | 124 | extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); |
| 124 | 125 | ||
| 125 | extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, | 126 | extern int ipv6_chk_mcast_addr(struct net_device *dev, |
| 126 | struct in6_addr *src_addr); | 127 | const struct in6_addr *group, |
| 128 | const struct in6_addr *src_addr); | ||
| 127 | extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr); | 129 | extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr); |
| 128 | 130 | ||
| 129 | extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len); | 131 | extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len); |
| @@ -189,25 +191,6 @@ static inline void in6_ifa_put(struct inet6_ifaddr *ifp) | |||
| 189 | #define in6_ifa_hold(ifp) atomic_inc(&(ifp)->refcnt) | 191 | #define in6_ifa_hold(ifp) atomic_inc(&(ifp)->refcnt) |
| 190 | 192 | ||
| 191 | 193 | ||
| 192 | /* | ||
| 193 | * Hash function taken from net_alias.c | ||
| 194 | */ | ||
| 195 | |||
| 196 | static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
| 197 | { | ||
| 198 | __u32 word; | ||
| 199 | |||
| 200 | /* | ||
| 201 | * We perform the hash function over the last 64 bits of the address | ||
| 202 | * This will include the IEEE address token on links that support it. | ||
| 203 | */ | ||
| 204 | |||
| 205 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | ||
| 206 | word ^= (word >> 16); | ||
| 207 | word ^= (word >> 8); | ||
| 208 | |||
| 209 | return ((word ^ (word >> 4)) & 0x0f); | ||
| 210 | } | ||
| 211 | 194 | ||
| 212 | /* | 195 | /* |
| 213 | * compute link-local solicited-node multicast address | 196 | * compute link-local solicited-node multicast address |
| @@ -222,17 +205,6 @@ static inline void addrconf_addr_solict_mult(const struct in6_addr *addr, | |||
| 222 | htonl(0xFF000000) | addr->s6_addr32[3]); | 205 | htonl(0xFF000000) | addr->s6_addr32[3]); |
| 223 | } | 206 | } |
| 224 | 207 | ||
| 225 | |||
| 226 | static inline void ipv6_addr_all_nodes(struct in6_addr *addr) | ||
| 227 | { | ||
| 228 | ipv6_addr_set(addr, htonl(0xFF020000), 0, 0, htonl(0x1)); | ||
| 229 | } | ||
| 230 | |||
| 231 | static inline void ipv6_addr_all_routers(struct in6_addr *addr) | ||
| 232 | { | ||
| 233 | ipv6_addr_set(addr, htonl(0xFF020000), 0, 0, htonl(0x2)); | ||
| 234 | } | ||
| 235 | |||
| 236 | static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) | 208 | static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) |
| 237 | { | 209 | { |
| 238 | return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); | 210 | return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); |
| @@ -240,34 +212,19 @@ static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) | |||
| 240 | 212 | ||
| 241 | static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) | 213 | static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) |
| 242 | { | 214 | { |
| 243 | return (addr->s6_addr32[0] == htonl(0xff020000) && | 215 | return (((addr->s6_addr32[0] ^ htonl(0xff020000)) | |
| 244 | addr->s6_addr32[1] == 0 && | 216 | addr->s6_addr32[1] | addr->s6_addr32[2] | |
| 245 | addr->s6_addr32[2] == 0 && | 217 | (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0); |
| 246 | addr->s6_addr32[3] == htonl(0x00000001)); | ||
| 247 | } | 218 | } |
| 248 | 219 | ||
| 249 | static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) | 220 | static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) |
| 250 | { | 221 | { |
| 251 | return (addr->s6_addr32[0] == htonl(0xff020000) && | 222 | return (((addr->s6_addr32[0] ^ htonl(0xff020000)) | |
| 252 | addr->s6_addr32[1] == 0 && | 223 | addr->s6_addr32[1] | addr->s6_addr32[2] | |
| 253 | addr->s6_addr32[2] == 0 && | 224 | (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0); |
| 254 | addr->s6_addr32[3] == htonl(0x00000002)); | ||
| 255 | } | 225 | } |
| 256 | 226 | ||
| 257 | static inline int ipv6_isatap_eui64(u8 *eui, __be32 addr) | 227 | extern int __ipv6_isatap_ifid(u8 *eui, __be32 addr); |
| 258 | { | ||
| 259 | eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || | ||
| 260 | ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || | ||
| 261 | ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || | ||
| 262 | ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) || | ||
| 263 | ipv4_is_test_198(addr) || ipv4_is_multicast(addr) || | ||
| 264 | ipv4_is_lbcast(addr)) ? 0x00 : 0x02; | ||
| 265 | eui[1] = 0; | ||
| 266 | eui[2] = 0x5E; | ||
| 267 | eui[3] = 0xFE; | ||
| 268 | memcpy (eui+4, &addr, 4); | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | 228 | ||
| 272 | static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) | 229 | static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) |
| 273 | { | 230 | { |
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 9080076ce0e5..9313491e3dad 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
| @@ -61,13 +61,13 @@ extern int ip6_ins_rt(struct rt6_info *); | |||
| 61 | extern int ip6_del_rt(struct rt6_info *); | 61 | extern int ip6_del_rt(struct rt6_info *); |
| 62 | 62 | ||
| 63 | extern struct rt6_info *rt6_lookup(struct net *net, | 63 | extern struct rt6_info *rt6_lookup(struct net *net, |
| 64 | struct in6_addr *daddr, | 64 | const struct in6_addr *daddr, |
| 65 | struct in6_addr *saddr, | 65 | const struct in6_addr *saddr, |
| 66 | int oif, int flags); | 66 | int oif, int flags); |
| 67 | 67 | ||
| 68 | extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | 68 | extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
| 69 | struct neighbour *neigh, | 69 | struct neighbour *neigh, |
| 70 | struct in6_addr *addr); | 70 | const struct in6_addr *addr); |
| 71 | extern int icmp6_dst_gc(int *more); | 71 | extern int icmp6_dst_gc(int *more); |
| 72 | 72 | ||
| 73 | extern void fib6_force_start_gc(struct net *net); | 73 | extern void fib6_force_start_gc(struct net *net); |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 5738c1c73ac1..49c48983019f 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
| @@ -280,12 +280,10 @@ static inline int | |||
| 280 | ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, | 280 | ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, |
| 281 | const struct in6_addr *a2) | 281 | const struct in6_addr *a2) |
| 282 | { | 282 | { |
| 283 | unsigned int i; | 283 | return (!!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) | |
| 284 | 284 | ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) | | |
| 285 | for (i = 0; i < 4; i++) | 285 | ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) | |
| 286 | if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i]) | 286 | ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]))); |
| 287 | return 1; | ||
| 288 | return 0; | ||
| 289 | } | 287 | } |
| 290 | 288 | ||
| 291 | static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) | 289 | static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) |
| @@ -320,10 +318,10 @@ static inline void ipv6_addr_set(struct in6_addr *addr, | |||
| 320 | static inline int ipv6_addr_equal(const struct in6_addr *a1, | 318 | static inline int ipv6_addr_equal(const struct in6_addr *a1, |
| 321 | const struct in6_addr *a2) | 319 | const struct in6_addr *a2) |
| 322 | { | 320 | { |
| 323 | return (a1->s6_addr32[0] == a2->s6_addr32[0] && | 321 | return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | |
| 324 | a1->s6_addr32[1] == a2->s6_addr32[1] && | 322 | (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | |
| 325 | a1->s6_addr32[2] == a2->s6_addr32[2] && | 323 | (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | |
| 326 | a1->s6_addr32[3] == a2->s6_addr32[3]); | 324 | (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0); |
| 327 | } | 325 | } |
| 328 | 326 | ||
| 329 | static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, | 327 | static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, |
| @@ -371,8 +369,8 @@ static inline int ipv6_addr_any(const struct in6_addr *a) | |||
| 371 | 369 | ||
| 372 | static inline int ipv6_addr_v4mapped(const struct in6_addr *a) | 370 | static inline int ipv6_addr_v4mapped(const struct in6_addr *a) |
| 373 | { | 371 | { |
| 374 | return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 && | 372 | return ((a->s6_addr32[0] | a->s6_addr32[1] | |
| 375 | a->s6_addr32[2] == htonl(0x0000ffff)); | 373 | (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0); |
| 376 | } | 374 | } |
| 377 | 375 | ||
| 378 | /* | 376 | /* |
| @@ -453,8 +451,8 @@ extern int ip6_xmit(struct sock *sk, | |||
| 453 | extern int ip6_nd_hdr(struct sock *sk, | 451 | extern int ip6_nd_hdr(struct sock *sk, |
| 454 | struct sk_buff *skb, | 452 | struct sk_buff *skb, |
| 455 | struct net_device *dev, | 453 | struct net_device *dev, |
| 456 | struct in6_addr *saddr, | 454 | const struct in6_addr *saddr, |
| 457 | struct in6_addr *daddr, | 455 | const struct in6_addr *daddr, |
| 458 | int proto, int len); | 456 | int proto, int len); |
| 459 | 457 | ||
| 460 | extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); | 458 | extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); |
diff --git a/include/net/mip6.h b/include/net/mip6.h index 63272610a24a..a83ad1982a90 100644 --- a/include/net/mip6.h +++ b/include/net/mip6.h | |||
| @@ -28,9 +28,6 @@ | |||
| 28 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
| 29 | #include <net/sock.h> | 29 | #include <net/sock.h> |
| 30 | 30 | ||
| 31 | #define MIP6_OPT_PAD_1 0 | ||
| 32 | #define MIP6_OPT_PAD_N 1 | ||
| 33 | |||
| 34 | /* | 31 | /* |
| 35 | * Mobility Header | 32 | * Mobility Header |
| 36 | */ | 33 | */ |
diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 16424236fe2f..9c451ff2f4f4 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h | |||
| @@ -94,17 +94,17 @@ extern int ndisc_rcv(struct sk_buff *skb); | |||
| 94 | 94 | ||
| 95 | extern void ndisc_send_ns(struct net_device *dev, | 95 | extern void ndisc_send_ns(struct net_device *dev, |
| 96 | struct neighbour *neigh, | 96 | struct neighbour *neigh, |
| 97 | struct in6_addr *solicit, | 97 | const struct in6_addr *solicit, |
| 98 | struct in6_addr *daddr, | 98 | const struct in6_addr *daddr, |
| 99 | struct in6_addr *saddr); | 99 | const struct in6_addr *saddr); |
| 100 | 100 | ||
| 101 | extern void ndisc_send_rs(struct net_device *dev, | 101 | extern void ndisc_send_rs(struct net_device *dev, |
| 102 | struct in6_addr *saddr, | 102 | const struct in6_addr *saddr, |
| 103 | struct in6_addr *daddr); | 103 | const struct in6_addr *daddr); |
| 104 | 104 | ||
| 105 | extern void ndisc_send_redirect(struct sk_buff *skb, | 105 | extern void ndisc_send_redirect(struct sk_buff *skb, |
| 106 | struct neighbour *neigh, | 106 | struct neighbour *neigh, |
| 107 | struct in6_addr *target); | 107 | const struct in6_addr *target); |
| 108 | 108 | ||
| 109 | extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); | 109 | extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); |
| 110 | 110 | ||
| @@ -134,7 +134,7 @@ extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, | |||
| 134 | extern void inet6_ifinfo_notify(int event, | 134 | extern void inet6_ifinfo_notify(int event, |
| 135 | struct inet6_dev *idev); | 135 | struct inet6_dev *idev); |
| 136 | 136 | ||
| 137 | static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr) | 137 | static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr) |
| 138 | { | 138 | { |
| 139 | 139 | ||
| 140 | if (dev) | 140 | if (dev) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 924158393d04..e93fa62089f8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -222,6 +222,8 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
| 222 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ | 222 | /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ |
| 223 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; | 223 | const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; |
| 224 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; | 224 | const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; |
| 225 | const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; | ||
| 226 | const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; | ||
| 225 | 227 | ||
| 226 | /* Check if a valid qdisc is available */ | 228 | /* Check if a valid qdisc is available */ |
| 227 | static inline int addrconf_qdisc_ok(struct net_device *dev) | 229 | static inline int addrconf_qdisc_ok(struct net_device *dev) |
| @@ -321,7 +323,6 @@ EXPORT_SYMBOL(in6_dev_finish_destroy); | |||
| 321 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | 323 | static struct inet6_dev * ipv6_add_dev(struct net_device *dev) |
| 322 | { | 324 | { |
| 323 | struct inet6_dev *ndev; | 325 | struct inet6_dev *ndev; |
| 324 | struct in6_addr maddr; | ||
| 325 | 326 | ||
| 326 | ASSERT_RTNL(); | 327 | ASSERT_RTNL(); |
| 327 | 328 | ||
| @@ -406,8 +407,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 406 | rcu_assign_pointer(dev->ip6_ptr, ndev); | 407 | rcu_assign_pointer(dev->ip6_ptr, ndev); |
| 407 | 408 | ||
| 408 | /* Join all-node multicast group */ | 409 | /* Join all-node multicast group */ |
| 409 | ipv6_addr_all_nodes(&maddr); | 410 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); |
| 410 | ipv6_dev_mc_inc(dev, &maddr); | ||
| 411 | 411 | ||
| 412 | return ndev; | 412 | return ndev; |
| 413 | } | 413 | } |
| @@ -433,18 +433,15 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
| 433 | { | 433 | { |
| 434 | struct net_device *dev; | 434 | struct net_device *dev; |
| 435 | struct inet6_ifaddr *ifa; | 435 | struct inet6_ifaddr *ifa; |
| 436 | struct in6_addr addr; | ||
| 437 | 436 | ||
| 438 | if (!idev) | 437 | if (!idev) |
| 439 | return; | 438 | return; |
| 440 | dev = idev->dev; | 439 | dev = idev->dev; |
| 441 | if (dev && (dev->flags & IFF_MULTICAST)) { | 440 | if (dev && (dev->flags & IFF_MULTICAST)) { |
| 442 | ipv6_addr_all_routers(&addr); | ||
| 443 | |||
| 444 | if (idev->cnf.forwarding) | 441 | if (idev->cnf.forwarding) |
| 445 | ipv6_dev_mc_inc(dev, &addr); | 442 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); |
| 446 | else | 443 | else |
| 447 | ipv6_dev_mc_dec(dev, &addr); | 444 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
| 448 | } | 445 | } |
| 449 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 446 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { |
| 450 | if (ifa->flags&IFA_F_TENTATIVE) | 447 | if (ifa->flags&IFA_F_TENTATIVE) |
| @@ -541,6 +538,25 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | |||
| 541 | *ifap = ifp; | 538 | *ifap = ifp; |
| 542 | } | 539 | } |
| 543 | 540 | ||
| 541 | /* | ||
| 542 | * Hash function taken from net_alias.c | ||
| 543 | */ | ||
| 544 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
| 545 | { | ||
| 546 | __u32 word; | ||
| 547 | |||
| 548 | /* | ||
| 549 | * We perform the hash function over the last 64 bits of the address | ||
| 550 | * This will include the IEEE address token on links that support it. | ||
| 551 | */ | ||
| 552 | |||
| 553 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | ||
| 554 | word ^= (word >> 16); | ||
| 555 | word ^= (word >> 8); | ||
| 556 | |||
| 557 | return ((word ^ (word >> 4)) & 0x0f); | ||
| 558 | } | ||
| 559 | |||
| 544 | /* On success it returns ifp with increased reference count */ | 560 | /* On success it returns ifp with increased reference count */ |
| 545 | 561 | ||
| 546 | static struct inet6_ifaddr * | 562 | static struct inet6_ifaddr * |
| @@ -921,7 +937,7 @@ struct ipv6_saddr_score { | |||
| 921 | }; | 937 | }; |
| 922 | 938 | ||
| 923 | struct ipv6_saddr_dst { | 939 | struct ipv6_saddr_dst { |
| 924 | struct in6_addr *addr; | 940 | const struct in6_addr *addr; |
| 925 | int ifindex; | 941 | int ifindex; |
| 926 | int scope; | 942 | int scope; |
| 927 | int label; | 943 | int label; |
| @@ -1055,7 +1071,7 @@ out: | |||
| 1055 | } | 1071 | } |
| 1056 | 1072 | ||
| 1057 | int ipv6_dev_get_saddr(struct net_device *dst_dev, | 1073 | int ipv6_dev_get_saddr(struct net_device *dst_dev, |
| 1058 | struct in6_addr *daddr, unsigned int prefs, | 1074 | const struct in6_addr *daddr, unsigned int prefs, |
| 1059 | struct in6_addr *saddr) | 1075 | struct in6_addr *saddr) |
| 1060 | { | 1076 | { |
| 1061 | struct ipv6_saddr_score scores[2], | 1077 | struct ipv6_saddr_score scores[2], |
| @@ -1290,7 +1306,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
| 1290 | 1306 | ||
| 1291 | EXPORT_SYMBOL(ipv6_chk_prefix); | 1307 | EXPORT_SYMBOL(ipv6_chk_prefix); |
| 1292 | 1308 | ||
| 1293 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr, | 1309 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
| 1294 | struct net_device *dev, int strict) | 1310 | struct net_device *dev, int strict) |
| 1295 | { | 1311 | { |
| 1296 | struct inet6_ifaddr * ifp; | 1312 | struct inet6_ifaddr * ifp; |
| @@ -1475,6 +1491,29 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev) | |||
| 1475 | return 0; | 1491 | return 0; |
| 1476 | } | 1492 | } |
| 1477 | 1493 | ||
| 1494 | int __ipv6_isatap_ifid(u8 *eui, __be32 addr) | ||
| 1495 | { | ||
| 1496 | eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || | ||
| 1497 | ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || | ||
| 1498 | ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || | ||
| 1499 | ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) || | ||
| 1500 | ipv4_is_test_198(addr) || ipv4_is_multicast(addr) || | ||
| 1501 | ipv4_is_lbcast(addr)) ? 0x00 : 0x02; | ||
| 1502 | eui[1] = 0; | ||
| 1503 | eui[2] = 0x5E; | ||
| 1504 | eui[3] = 0xFE; | ||
| 1505 | memcpy(eui + 4, &addr, 4); | ||
| 1506 | return 0; | ||
| 1507 | } | ||
| 1508 | EXPORT_SYMBOL(__ipv6_isatap_ifid); | ||
| 1509 | |||
| 1510 | static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) | ||
| 1511 | { | ||
| 1512 | if (dev->priv_flags & IFF_ISATAP) | ||
| 1513 | return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); | ||
| 1514 | return -1; | ||
| 1515 | } | ||
| 1516 | |||
| 1478 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | 1517 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) |
| 1479 | { | 1518 | { |
| 1480 | switch (dev->type) { | 1519 | switch (dev->type) { |
| @@ -1487,8 +1526,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | |||
| 1487 | case ARPHRD_INFINIBAND: | 1526 | case ARPHRD_INFINIBAND: |
| 1488 | return addrconf_ifid_infiniband(eui, dev); | 1527 | return addrconf_ifid_infiniband(eui, dev); |
| 1489 | case ARPHRD_SIT: | 1528 | case ARPHRD_SIT: |
| 1490 | if (dev->priv_flags & IFF_ISATAP) | 1529 | return addrconf_ifid_sit(eui, dev); |
| 1491 | return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr); | ||
| 1492 | } | 1530 | } |
| 1493 | return -1; | 1531 | return -1; |
| 1494 | } | 1532 | } |
| @@ -2613,8 +2651,6 @@ static void addrconf_rs_timer(unsigned long data) | |||
| 2613 | 2651 | ||
| 2614 | spin_lock(&ifp->lock); | 2652 | spin_lock(&ifp->lock); |
| 2615 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2653 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { |
| 2616 | struct in6_addr all_routers; | ||
| 2617 | |||
| 2618 | /* The wait after the last probe can be shorter */ | 2654 | /* The wait after the last probe can be shorter */ |
| 2619 | addrconf_mod_timer(ifp, AC_RS, | 2655 | addrconf_mod_timer(ifp, AC_RS, |
| 2620 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2656 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? |
| @@ -2622,9 +2658,7 @@ static void addrconf_rs_timer(unsigned long data) | |||
| 2622 | ifp->idev->cnf.rtr_solicit_interval); | 2658 | ifp->idev->cnf.rtr_solicit_interval); |
| 2623 | spin_unlock(&ifp->lock); | 2659 | spin_unlock(&ifp->lock); |
| 2624 | 2660 | ||
| 2625 | ipv6_addr_all_routers(&all_routers); | 2661 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
| 2626 | |||
| 2627 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); | ||
| 2628 | } else { | 2662 | } else { |
| 2629 | spin_unlock(&ifp->lock); | 2663 | spin_unlock(&ifp->lock); |
| 2630 | /* | 2664 | /* |
| @@ -2711,7 +2745,6 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2711 | { | 2745 | { |
| 2712 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2746 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
| 2713 | struct inet6_dev *idev = ifp->idev; | 2747 | struct inet6_dev *idev = ifp->idev; |
| 2714 | struct in6_addr unspec; | ||
| 2715 | struct in6_addr mcaddr; | 2748 | struct in6_addr mcaddr; |
| 2716 | 2749 | ||
| 2717 | read_lock_bh(&idev->lock); | 2750 | read_lock_bh(&idev->lock); |
| @@ -2740,9 +2773,8 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2740 | read_unlock_bh(&idev->lock); | 2773 | read_unlock_bh(&idev->lock); |
| 2741 | 2774 | ||
| 2742 | /* send a neighbour solicitation for our addr */ | 2775 | /* send a neighbour solicitation for our addr */ |
| 2743 | memset(&unspec, 0, sizeof(unspec)); | ||
| 2744 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2776 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
| 2745 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec); | 2777 | ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); |
| 2746 | out: | 2778 | out: |
| 2747 | in6_ifa_put(ifp); | 2779 | in6_ifa_put(ifp); |
| 2748 | } | 2780 | } |
| @@ -2765,16 +2797,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
| 2765 | ifp->idev->cnf.rtr_solicits > 0 && | 2797 | ifp->idev->cnf.rtr_solicits > 0 && |
| 2766 | (dev->flags&IFF_LOOPBACK) == 0 && | 2798 | (dev->flags&IFF_LOOPBACK) == 0 && |
| 2767 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { | 2799 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { |
| 2768 | struct in6_addr all_routers; | ||
| 2769 | |||
| 2770 | ipv6_addr_all_routers(&all_routers); | ||
| 2771 | |||
| 2772 | /* | 2800 | /* |
| 2773 | * If a host as already performed a random delay | 2801 | * If a host as already performed a random delay |
| 2774 | * [...] as part of DAD [...] there is no need | 2802 | * [...] as part of DAD [...] there is no need |
| 2775 | * to delay again before sending the first RS | 2803 | * to delay again before sending the first RS |
| 2776 | */ | 2804 | */ |
| 2777 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); | 2805 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
| 2778 | 2806 | ||
| 2779 | spin_lock_bh(&ifp->lock); | 2807 | spin_lock_bh(&ifp->lock); |
| 2780 | ifp->probes = 1; | 2808 | ifp->probes = 1; |
| @@ -2951,7 +2979,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
| 2951 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 2979 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { |
| 2952 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 2980 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 2953 | continue; | 2981 | continue; |
| 2954 | if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && | 2982 | if (ipv6_addr_equal(&ifp->addr, addr) && |
| 2955 | (ifp->flags & IFA_F_HOMEADDRESS)) { | 2983 | (ifp->flags & IFA_F_HOMEADDRESS)) { |
| 2956 | ret = 1; | 2984 | ret = 1; |
| 2957 | break; | 2985 | break; |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index cac580749ebe..8d05527524e3 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
| @@ -316,5 +316,5 @@ int __init fib6_rules_init(void) | |||
| 316 | 316 | ||
| 317 | void fib6_rules_cleanup(void) | 317 | void fib6_rules_cleanup(void) |
| 318 | { | 318 | { |
| 319 | return unregister_pernet_subsys(&fib6_rules_net_ops); | 319 | unregister_pernet_subsys(&fib6_rules_net_ops); |
| 320 | } | 320 | } |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 09a3201e408a..4e5c8615832c 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -262,21 +262,23 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 262 | * is for MLD (0x0000). | 262 | * is for MLD (0x0000). |
| 263 | */ | 263 | */ |
| 264 | if ((ptr[2] | ptr[3]) == 0) { | 264 | if ((ptr[2] | ptr[3]) == 0) { |
| 265 | deliver = 0; | ||
| 266 | |||
| 265 | if (!ipv6_ext_hdr(nexthdr)) { | 267 | if (!ipv6_ext_hdr(nexthdr)) { |
| 266 | /* BUG */ | 268 | /* BUG */ |
| 267 | goto discard; | 269 | goto out; |
| 268 | } | 270 | } |
| 269 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), | 271 | offset = ipv6_skip_exthdr(skb, sizeof(*hdr), |
| 270 | &nexthdr); | 272 | &nexthdr); |
| 271 | if (offset < 0) | 273 | if (offset < 0) |
| 272 | goto discard; | 274 | goto out; |
| 273 | 275 | ||
| 274 | if (nexthdr != IPPROTO_ICMPV6) | 276 | if (nexthdr != IPPROTO_ICMPV6) |
| 275 | goto discard; | 277 | goto out; |
| 276 | 278 | ||
| 277 | if (!pskb_may_pull(skb, (skb_network_header(skb) + | 279 | if (!pskb_may_pull(skb, (skb_network_header(skb) + |
| 278 | offset + 1 - skb->data))) | 280 | offset + 1 - skb->data))) |
| 279 | goto discard; | 281 | goto out; |
| 280 | 282 | ||
| 281 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); | 283 | icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); |
| 282 | 284 | ||
| @@ -285,12 +287,9 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 285 | case ICMPV6_MGM_REPORT: | 287 | case ICMPV6_MGM_REPORT: |
| 286 | case ICMPV6_MGM_REDUCTION: | 288 | case ICMPV6_MGM_REDUCTION: |
| 287 | case ICMPV6_MLD2_REPORT: | 289 | case ICMPV6_MLD2_REPORT: |
| 290 | deliver = 1; | ||
| 288 | break; | 291 | break; |
| 289 | default: | ||
| 290 | /* Bogus */ | ||
| 291 | goto discard; | ||
| 292 | } | 292 | } |
| 293 | deliver = 1; | ||
| 294 | goto out; | 293 | goto out; |
| 295 | } | 294 | } |
| 296 | /* unknown RA - process it normally */ | 295 | /* unknown RA - process it normally */ |
| @@ -308,15 +307,14 @@ int ip6_mc_input(struct sk_buff *skb) | |||
| 308 | ip6_mr_input(skb2); | 307 | ip6_mr_input(skb2); |
| 309 | } | 308 | } |
| 310 | } | 309 | } |
| 311 | #endif | ||
| 312 | out: | 310 | out: |
| 313 | if (likely(deliver)) { | 311 | #endif |
| 312 | if (likely(deliver)) | ||
| 314 | ip6_input(skb); | 313 | ip6_input(skb); |
| 315 | return 0; | 314 | else { |
| 315 | /* discard */ | ||
| 316 | kfree_skb(skb); | ||
| 316 | } | 317 | } |
| 317 | discard: | ||
| 318 | /* discard */ | ||
| 319 | kfree_skb(skb); | ||
| 320 | 318 | ||
| 321 | return 0; | 319 | return 0; |
| 322 | } | 320 | } |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index c0dbe549cc42..0af2e055f883 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -286,7 +286,7 @@ EXPORT_SYMBOL(ip6_xmit); | |||
| 286 | */ | 286 | */ |
| 287 | 287 | ||
| 288 | int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | 288 | int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, |
| 289 | struct in6_addr *saddr, struct in6_addr *daddr, | 289 | const struct in6_addr *saddr, const struct in6_addr *daddr, |
| 290 | int proto, int len) | 290 | int proto, int len) |
| 291 | { | 291 | { |
| 292 | struct ipv6_pinfo *np = inet6_sk(sk); | 292 | struct ipv6_pinfo *np = inet6_sk(sk); |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index da673ef75e12..94ede696da2a 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -27,27 +27,18 @@ | |||
| 27 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
| 28 | #include <linux/stat.h> | 28 | #include <linux/stat.h> |
| 29 | #include <linux/socket.h> | 29 | #include <linux/socket.h> |
| 30 | #include <linux/in.h> | ||
| 31 | #include <linux/inet.h> | 30 | #include <linux/inet.h> |
| 32 | #include <linux/netdevice.h> | 31 | #include <linux/netdevice.h> |
| 33 | #include <linux/inetdevice.h> | 32 | #include <linux/inetdevice.h> |
| 34 | #include <linux/igmp.h> | ||
| 35 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
| 36 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
| 37 | #include <linux/mroute.h> | ||
| 38 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 39 | #include <net/ip.h> | ||
| 40 | #include <net/protocol.h> | 36 | #include <net/protocol.h> |
| 41 | #include <linux/skbuff.h> | 37 | #include <linux/skbuff.h> |
| 42 | #include <net/sock.h> | 38 | #include <net/sock.h> |
| 43 | #include <net/icmp.h> | ||
| 44 | #include <net/udp.h> | ||
| 45 | #include <net/raw.h> | 39 | #include <net/raw.h> |
| 46 | #include <net/route.h> | ||
| 47 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
| 48 | #include <linux/if_arp.h> | 41 | #include <linux/if_arp.h> |
| 49 | #include <linux/netfilter_ipv4.h> | ||
| 50 | #include <net/ipip.h> | ||
| 51 | #include <net/checksum.h> | 42 | #include <net/checksum.h> |
| 52 | #include <net/netlink.h> | 43 | #include <net/netlink.h> |
| 53 | 44 | ||
| @@ -83,7 +74,7 @@ static int mroute_do_pim; | |||
| 83 | #define mroute_do_pim 0 | 74 | #define mroute_do_pim 0 |
| 84 | #endif | 75 | #endif |
| 85 | 76 | ||
| 86 | static struct mfc6_cache *mfc6_cache_array[MFC_LINES]; /* Forwarding cache */ | 77 | static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */ |
| 87 | 78 | ||
| 88 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ | 79 | static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ |
| 89 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ | 80 | static atomic_t cache_resolve_queue_len; /* Size of unresolved */ |
| @@ -102,7 +93,7 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
| 102 | static struct kmem_cache *mrt_cachep __read_mostly; | 93 | static struct kmem_cache *mrt_cachep __read_mostly; |
| 103 | 94 | ||
| 104 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); | 95 | static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); |
| 105 | static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert); | 96 | static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert); |
| 106 | static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); | 97 | static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); |
| 107 | 98 | ||
| 108 | #ifdef CONFIG_IPV6_PIMSM_V2 | 99 | #ifdef CONFIG_IPV6_PIMSM_V2 |
| @@ -597,9 +588,9 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl | |||
| 597 | { | 588 | { |
| 598 | int vifi; | 589 | int vifi; |
| 599 | 590 | ||
| 600 | cache->mfc_un.res.minvif = MAXVIFS; | 591 | cache->mfc_un.res.minvif = MAXMIFS; |
| 601 | cache->mfc_un.res.maxvif = 0; | 592 | cache->mfc_un.res.maxvif = 0; |
| 602 | memset(cache->mfc_un.res.ttls, 255, MAXVIFS); | 593 | memset(cache->mfc_un.res.ttls, 255, MAXMIFS); |
| 603 | 594 | ||
| 604 | for (vifi = 0; vifi < maxvif; vifi++) { | 595 | for (vifi = 0; vifi < maxvif; vifi++) { |
| 605 | if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { | 596 | if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { |
| @@ -700,7 +691,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) | |||
| 700 | if (c == NULL) | 691 | if (c == NULL) |
| 701 | return NULL; | 692 | return NULL; |
| 702 | memset(c, 0, sizeof(*c)); | 693 | memset(c, 0, sizeof(*c)); |
| 703 | c->mfc_un.res.minvif = MAXVIFS; | 694 | c->mfc_un.res.minvif = MAXMIFS; |
| 704 | return c; | 695 | return c; |
| 705 | } | 696 | } |
| 706 | 697 | ||
| @@ -753,7 +744,7 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) | |||
| 753 | * Called under mrt_lock. | 744 | * Called under mrt_lock. |
| 754 | */ | 745 | */ |
| 755 | 746 | ||
| 756 | static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | 747 | static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert) |
| 757 | { | 748 | { |
| 758 | struct sk_buff *skb; | 749 | struct sk_buff *skb; |
| 759 | struct mrt6msg *msg; | 750 | struct mrt6msg *msg; |
| @@ -815,7 +806,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
| 815 | 806 | ||
| 816 | msg->im6_mbz = 0; | 807 | msg->im6_mbz = 0; |
| 817 | msg->im6_msgtype = assert; | 808 | msg->im6_msgtype = assert; |
| 818 | msg->im6_mif = vifi; | 809 | msg->im6_mif = mifi; |
| 819 | msg->im6_pad = 0; | 810 | msg->im6_pad = 0; |
| 820 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); | 811 | ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); |
| 821 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); | 812 | ipv6_addr_copy(&msg->im6_dst, &ipv6_hdr(pkt)->daddr); |
| @@ -848,7 +839,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) | |||
| 848 | */ | 839 | */ |
| 849 | 840 | ||
| 850 | static int | 841 | static int |
| 851 | ip6mr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | 842 | ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb) |
| 852 | { | 843 | { |
| 853 | int err; | 844 | int err; |
| 854 | struct mfc6_cache *c; | 845 | struct mfc6_cache *c; |
| @@ -883,7 +874,7 @@ ip6mr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) | |||
| 883 | /* | 874 | /* |
| 884 | * Reflect first query at pim6sd | 875 | * Reflect first query at pim6sd |
| 885 | */ | 876 | */ |
| 886 | if ((err = ip6mr_cache_report(skb, vifi, MRT6MSG_NOCACHE)) < 0) { | 877 | if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) { |
| 887 | /* If the report failed throw the cache entry | 878 | /* If the report failed throw the cache entry |
| 888 | out - Brad Parker | 879 | out - Brad Parker |
| 889 | */ | 880 | */ |
| @@ -992,11 +983,11 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) | |||
| 992 | { | 983 | { |
| 993 | int line; | 984 | int line; |
| 994 | struct mfc6_cache *uc, *c, **cp; | 985 | struct mfc6_cache *uc, *c, **cp; |
| 995 | unsigned char ttls[MAXVIFS]; | 986 | unsigned char ttls[MAXMIFS]; |
| 996 | int i; | 987 | int i; |
| 997 | 988 | ||
| 998 | memset(ttls, 255, MAXVIFS); | 989 | memset(ttls, 255, MAXMIFS); |
| 999 | for (i = 0; i < MAXVIFS; i++) { | 990 | for (i = 0; i < MAXMIFS; i++) { |
| 1000 | if (IF_ISSET(i, &mfc->mf6cc_ifset)) | 991 | if (IF_ISSET(i, &mfc->mf6cc_ifset)) |
| 1001 | ttls[i] = 1; | 992 | ttls[i] = 1; |
| 1002 | 993 | ||
| @@ -1188,7 +1179,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
| 1188 | return -EINVAL; | 1179 | return -EINVAL; |
| 1189 | if (copy_from_user(&vif, optval, sizeof(vif))) | 1180 | if (copy_from_user(&vif, optval, sizeof(vif))) |
| 1190 | return -EFAULT; | 1181 | return -EFAULT; |
| 1191 | if (vif.mif6c_mifi >= MAXVIFS) | 1182 | if (vif.mif6c_mifi >= MAXMIFS) |
| 1192 | return -ENFILE; | 1183 | return -ENFILE; |
| 1193 | rtnl_lock(); | 1184 | rtnl_lock(); |
| 1194 | ret = mif6_add(&vif, sk == mroute6_socket); | 1185 | ret = mif6_add(&vif, sk == mroute6_socket); |
| @@ -1238,7 +1229,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int | |||
| 1238 | #ifdef CONFIG_IPV6_PIMSM_V2 | 1229 | #ifdef CONFIG_IPV6_PIMSM_V2 |
| 1239 | case MRT6_PIM: | 1230 | case MRT6_PIM: |
| 1240 | { | 1231 | { |
| 1241 | int v, ret; | 1232 | int v; |
| 1242 | if (get_user(v, (int __user *)optval)) | 1233 | if (get_user(v, (int __user *)optval)) |
| 1243 | return -EFAULT; | 1234 | return -EFAULT; |
| 1244 | v = !!v; | 1235 | v = !!v; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 99624109c010..2f1244dc5ebf 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * | 16 | * |
| 17 | * FIXME: Make the setsockopt code POSIX compliant: That is | 17 | * FIXME: Make the setsockopt code POSIX compliant: That is |
| 18 | * | 18 | * |
| 19 | * o Return -EINVAL for setsockopt of short lengths | ||
| 20 | * o Truncate getsockopt returns | 19 | * o Truncate getsockopt returns |
| 21 | * o Return an optlen of the truncated length if need be | 20 | * o Return an optlen of the truncated length if need be |
| 22 | * | 21 | * |
| @@ -114,8 +113,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 114 | 113 | ||
| 115 | if (optval == NULL) | 114 | if (optval == NULL) |
| 116 | val=0; | 115 | val=0; |
| 117 | else if (get_user(val, (int __user *) optval)) | 116 | else { |
| 118 | return -EFAULT; | 117 | if (optlen >= sizeof(int)) { |
| 118 | if (get_user(val, (int __user *) optval)) | ||
| 119 | return -EFAULT; | ||
| 120 | } else | ||
| 121 | val = 0; | ||
| 122 | } | ||
| 119 | 123 | ||
| 120 | valbool = (val!=0); | 124 | valbool = (val!=0); |
| 121 | 125 | ||
| @@ -127,6 +131,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 127 | switch (optname) { | 131 | switch (optname) { |
| 128 | 132 | ||
| 129 | case IPV6_ADDRFORM: | 133 | case IPV6_ADDRFORM: |
| 134 | if (optlen < sizeof(int)) | ||
| 135 | goto e_inval; | ||
| 130 | if (val == PF_INET) { | 136 | if (val == PF_INET) { |
| 131 | struct ipv6_txoptions *opt; | 137 | struct ipv6_txoptions *opt; |
| 132 | struct sk_buff *pktopt; | 138 | struct sk_buff *pktopt; |
| @@ -159,8 +165,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 159 | 165 | ||
| 160 | if (sk->sk_protocol == IPPROTO_TCP) { | 166 | if (sk->sk_protocol == IPPROTO_TCP) { |
| 161 | struct inet_connection_sock *icsk = inet_csk(sk); | 167 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 162 | struct net *net = sock_net(sk); | ||
| 163 | |||
| 164 | local_bh_disable(); | 168 | local_bh_disable(); |
| 165 | sock_prot_inuse_add(net, sk->sk_prot, -1); | 169 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
| 166 | sock_prot_inuse_add(net, &tcp_prot, 1); | 170 | sock_prot_inuse_add(net, &tcp_prot, 1); |
| @@ -172,7 +176,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 172 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 176 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); |
| 173 | } else { | 177 | } else { |
| 174 | struct proto *prot = &udp_prot; | 178 | struct proto *prot = &udp_prot; |
| 175 | struct net *net = sock_net(sk); | ||
| 176 | 179 | ||
| 177 | if (sk->sk_protocol == IPPROTO_UDPLITE) | 180 | if (sk->sk_protocol == IPPROTO_UDPLITE) |
| 178 | prot = &udplite_prot; | 181 | prot = &udplite_prot; |
| @@ -204,63 +207,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 204 | goto e_inval; | 207 | goto e_inval; |
| 205 | 208 | ||
| 206 | case IPV6_V6ONLY: | 209 | case IPV6_V6ONLY: |
| 207 | if (inet_sk(sk)->num) | 210 | if (optlen < sizeof(int) || |
| 211 | inet_sk(sk)->num) | ||
| 208 | goto e_inval; | 212 | goto e_inval; |
| 209 | np->ipv6only = valbool; | 213 | np->ipv6only = valbool; |
| 210 | retv = 0; | 214 | retv = 0; |
| 211 | break; | 215 | break; |
| 212 | 216 | ||
| 213 | case IPV6_RECVPKTINFO: | 217 | case IPV6_RECVPKTINFO: |
| 218 | if (optlen < sizeof(int)) | ||
| 219 | goto e_inval; | ||
| 214 | np->rxopt.bits.rxinfo = valbool; | 220 | np->rxopt.bits.rxinfo = valbool; |
| 215 | retv = 0; | 221 | retv = 0; |
| 216 | break; | 222 | break; |
| 217 | 223 | ||
| 218 | case IPV6_2292PKTINFO: | 224 | case IPV6_2292PKTINFO: |
| 225 | if (optlen < sizeof(int)) | ||
| 226 | goto e_inval; | ||
| 219 | np->rxopt.bits.rxoinfo = valbool; | 227 | np->rxopt.bits.rxoinfo = valbool; |
| 220 | retv = 0; | 228 | retv = 0; |
| 221 | break; | 229 | break; |
| 222 | 230 | ||
| 223 | case IPV6_RECVHOPLIMIT: | 231 | case IPV6_RECVHOPLIMIT: |
| 232 | if (optlen < sizeof(int)) | ||
| 233 | goto e_inval; | ||
| 224 | np->rxopt.bits.rxhlim = valbool; | 234 | np->rxopt.bits.rxhlim = valbool; |
| 225 | retv = 0; | 235 | retv = 0; |
| 226 | break; | 236 | break; |
| 227 | 237 | ||
| 228 | case IPV6_2292HOPLIMIT: | 238 | case IPV6_2292HOPLIMIT: |
| 239 | if (optlen < sizeof(int)) | ||
| 240 | goto e_inval; | ||
| 229 | np->rxopt.bits.rxohlim = valbool; | 241 | np->rxopt.bits.rxohlim = valbool; |
| 230 | retv = 0; | 242 | retv = 0; |
| 231 | break; | 243 | break; |
| 232 | 244 | ||
| 233 | case IPV6_RECVRTHDR: | 245 | case IPV6_RECVRTHDR: |
| 246 | if (optlen < sizeof(int)) | ||
| 247 | goto e_inval; | ||
| 234 | np->rxopt.bits.srcrt = valbool; | 248 | np->rxopt.bits.srcrt = valbool; |
| 235 | retv = 0; | 249 | retv = 0; |
| 236 | break; | 250 | break; |
| 237 | 251 | ||
| 238 | case IPV6_2292RTHDR: | 252 | case IPV6_2292RTHDR: |
| 253 | if (optlen < sizeof(int)) | ||
| 254 | goto e_inval; | ||
| 239 | np->rxopt.bits.osrcrt = valbool; | 255 | np->rxopt.bits.osrcrt = valbool; |
| 240 | retv = 0; | 256 | retv = 0; |
| 241 | break; | 257 | break; |
| 242 | 258 | ||
| 243 | case IPV6_RECVHOPOPTS: | 259 | case IPV6_RECVHOPOPTS: |
| 260 | if (optlen < sizeof(int)) | ||
| 261 | goto e_inval; | ||
| 244 | np->rxopt.bits.hopopts = valbool; | 262 | np->rxopt.bits.hopopts = valbool; |
| 245 | retv = 0; | 263 | retv = 0; |
| 246 | break; | 264 | break; |
| 247 | 265 | ||
| 248 | case IPV6_2292HOPOPTS: | 266 | case IPV6_2292HOPOPTS: |
| 267 | if (optlen < sizeof(int)) | ||
| 268 | goto e_inval; | ||
| 249 | np->rxopt.bits.ohopopts = valbool; | 269 | np->rxopt.bits.ohopopts = valbool; |
| 250 | retv = 0; | 270 | retv = 0; |
| 251 | break; | 271 | break; |
| 252 | 272 | ||
| 253 | case IPV6_RECVDSTOPTS: | 273 | case IPV6_RECVDSTOPTS: |
| 274 | if (optlen < sizeof(int)) | ||
| 275 | goto e_inval; | ||
| 254 | np->rxopt.bits.dstopts = valbool; | 276 | np->rxopt.bits.dstopts = valbool; |
| 255 | retv = 0; | 277 | retv = 0; |
| 256 | break; | 278 | break; |
| 257 | 279 | ||
| 258 | case IPV6_2292DSTOPTS: | 280 | case IPV6_2292DSTOPTS: |
| 281 | if (optlen < sizeof(int)) | ||
| 282 | goto e_inval; | ||
| 259 | np->rxopt.bits.odstopts = valbool; | 283 | np->rxopt.bits.odstopts = valbool; |
| 260 | retv = 0; | 284 | retv = 0; |
| 261 | break; | 285 | break; |
| 262 | 286 | ||
| 263 | case IPV6_TCLASS: | 287 | case IPV6_TCLASS: |
| 288 | if (optlen < sizeof(int)) | ||
| 289 | goto e_inval; | ||
| 264 | if (val < -1 || val > 0xff) | 290 | if (val < -1 || val > 0xff) |
| 265 | goto e_inval; | 291 | goto e_inval; |
| 266 | np->tclass = val; | 292 | np->tclass = val; |
| @@ -268,11 +294,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 268 | break; | 294 | break; |
| 269 | 295 | ||
| 270 | case IPV6_RECVTCLASS: | 296 | case IPV6_RECVTCLASS: |
| 297 | if (optlen < sizeof(int)) | ||
| 298 | goto e_inval; | ||
| 271 | np->rxopt.bits.rxtclass = valbool; | 299 | np->rxopt.bits.rxtclass = valbool; |
| 272 | retv = 0; | 300 | retv = 0; |
| 273 | break; | 301 | break; |
| 274 | 302 | ||
| 275 | case IPV6_FLOWINFO: | 303 | case IPV6_FLOWINFO: |
| 304 | if (optlen < sizeof(int)) | ||
| 305 | goto e_inval; | ||
| 276 | np->rxopt.bits.rxflow = valbool; | 306 | np->rxopt.bits.rxflow = valbool; |
| 277 | retv = 0; | 307 | retv = 0; |
| 278 | break; | 308 | break; |
| @@ -291,9 +321,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 291 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | 321 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) |
| 292 | break; | 322 | break; |
| 293 | 323 | ||
| 294 | retv = -EINVAL; | 324 | if (optlen < sizeof(struct ipv6_opt_hdr) || |
| 295 | if (optlen & 0x7 || optlen > 8 * 255) | 325 | optlen & 0x7 || optlen > 8 * 255) |
| 296 | break; | 326 | goto e_inval; |
| 297 | 327 | ||
| 298 | opt = ipv6_renew_options(sk, np->opt, optname, | 328 | opt = ipv6_renew_options(sk, np->opt, optname, |
| 299 | (struct ipv6_opt_hdr __user *)optval, | 329 | (struct ipv6_opt_hdr __user *)optval, |
| @@ -411,6 +441,8 @@ done: | |||
| 411 | break; | 441 | break; |
| 412 | } | 442 | } |
| 413 | case IPV6_UNICAST_HOPS: | 443 | case IPV6_UNICAST_HOPS: |
| 444 | if (optlen < sizeof(int)) | ||
| 445 | goto e_inval; | ||
| 414 | if (val > 255 || val < -1) | 446 | if (val > 255 || val < -1) |
| 415 | goto e_inval; | 447 | goto e_inval; |
| 416 | np->hop_limit = val; | 448 | np->hop_limit = val; |
| @@ -420,6 +452,8 @@ done: | |||
| 420 | case IPV6_MULTICAST_HOPS: | 452 | case IPV6_MULTICAST_HOPS: |
| 421 | if (sk->sk_type == SOCK_STREAM) | 453 | if (sk->sk_type == SOCK_STREAM) |
| 422 | goto e_inval; | 454 | goto e_inval; |
| 455 | if (optlen < sizeof(int)) | ||
| 456 | goto e_inval; | ||
| 423 | if (val > 255 || val < -1) | 457 | if (val > 255 || val < -1) |
| 424 | goto e_inval; | 458 | goto e_inval; |
| 425 | np->mcast_hops = val; | 459 | np->mcast_hops = val; |
| @@ -427,6 +461,8 @@ done: | |||
| 427 | break; | 461 | break; |
| 428 | 462 | ||
| 429 | case IPV6_MULTICAST_LOOP: | 463 | case IPV6_MULTICAST_LOOP: |
| 464 | if (optlen < sizeof(int)) | ||
| 465 | goto e_inval; | ||
| 430 | np->mc_loop = valbool; | 466 | np->mc_loop = valbool; |
| 431 | retv = 0; | 467 | retv = 0; |
| 432 | break; | 468 | break; |
| @@ -434,6 +470,8 @@ done: | |||
| 434 | case IPV6_MULTICAST_IF: | 470 | case IPV6_MULTICAST_IF: |
| 435 | if (sk->sk_type == SOCK_STREAM) | 471 | if (sk->sk_type == SOCK_STREAM) |
| 436 | goto e_inval; | 472 | goto e_inval; |
| 473 | if (optlen < sizeof(int)) | ||
| 474 | goto e_inval; | ||
| 437 | 475 | ||
| 438 | if (val) { | 476 | if (val) { |
| 439 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) | 477 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) |
| @@ -452,6 +490,9 @@ done: | |||
| 452 | { | 490 | { |
| 453 | struct ipv6_mreq mreq; | 491 | struct ipv6_mreq mreq; |
| 454 | 492 | ||
| 493 | if (optlen < sizeof(struct ipv6_mreq)) | ||
| 494 | goto e_inval; | ||
| 495 | |||
| 455 | retv = -EPROTO; | 496 | retv = -EPROTO; |
| 456 | if (inet_sk(sk)->is_icsk) | 497 | if (inet_sk(sk)->is_icsk) |
| 457 | break; | 498 | break; |
| @@ -471,7 +512,7 @@ done: | |||
| 471 | { | 512 | { |
| 472 | struct ipv6_mreq mreq; | 513 | struct ipv6_mreq mreq; |
| 473 | 514 | ||
| 474 | if (optlen != sizeof(struct ipv6_mreq)) | 515 | if (optlen < sizeof(struct ipv6_mreq)) |
| 475 | goto e_inval; | 516 | goto e_inval; |
| 476 | 517 | ||
| 477 | retv = -EFAULT; | 518 | retv = -EFAULT; |
| @@ -490,6 +531,9 @@ done: | |||
| 490 | struct group_req greq; | 531 | struct group_req greq; |
| 491 | struct sockaddr_in6 *psin6; | 532 | struct sockaddr_in6 *psin6; |
| 492 | 533 | ||
| 534 | if (optlen < sizeof(struct group_req)) | ||
| 535 | goto e_inval; | ||
| 536 | |||
| 493 | retv = -EFAULT; | 537 | retv = -EFAULT; |
| 494 | if (copy_from_user(&greq, optval, sizeof(struct group_req))) | 538 | if (copy_from_user(&greq, optval, sizeof(struct group_req))) |
| 495 | break; | 539 | break; |
| @@ -514,7 +558,7 @@ done: | |||
| 514 | struct group_source_req greqs; | 558 | struct group_source_req greqs; |
| 515 | int omode, add; | 559 | int omode, add; |
| 516 | 560 | ||
| 517 | if (optlen != sizeof(struct group_source_req)) | 561 | if (optlen < sizeof(struct group_source_req)) |
| 518 | goto e_inval; | 562 | goto e_inval; |
| 519 | if (copy_from_user(&greqs, optval, sizeof(greqs))) { | 563 | if (copy_from_user(&greqs, optval, sizeof(greqs))) { |
| 520 | retv = -EFAULT; | 564 | retv = -EFAULT; |
| @@ -588,27 +632,37 @@ done: | |||
| 588 | break; | 632 | break; |
| 589 | } | 633 | } |
| 590 | case IPV6_ROUTER_ALERT: | 634 | case IPV6_ROUTER_ALERT: |
| 635 | if (optlen < sizeof(int)) | ||
| 636 | goto e_inval; | ||
| 591 | retv = ip6_ra_control(sk, val, NULL); | 637 | retv = ip6_ra_control(sk, val, NULL); |
| 592 | break; | 638 | break; |
| 593 | case IPV6_MTU_DISCOVER: | 639 | case IPV6_MTU_DISCOVER: |
| 640 | if (optlen < sizeof(int)) | ||
| 641 | goto e_inval; | ||
| 594 | if (val<0 || val>3) | 642 | if (val<0 || val>3) |
| 595 | goto e_inval; | 643 | goto e_inval; |
| 596 | np->pmtudisc = val; | 644 | np->pmtudisc = val; |
| 597 | retv = 0; | 645 | retv = 0; |
| 598 | break; | 646 | break; |
| 599 | case IPV6_MTU: | 647 | case IPV6_MTU: |
| 648 | if (optlen < sizeof(int)) | ||
| 649 | goto e_inval; | ||
| 600 | if (val && val < IPV6_MIN_MTU) | 650 | if (val && val < IPV6_MIN_MTU) |
| 601 | goto e_inval; | 651 | goto e_inval; |
| 602 | np->frag_size = val; | 652 | np->frag_size = val; |
| 603 | retv = 0; | 653 | retv = 0; |
| 604 | break; | 654 | break; |
| 605 | case IPV6_RECVERR: | 655 | case IPV6_RECVERR: |
| 656 | if (optlen < sizeof(int)) | ||
| 657 | goto e_inval; | ||
| 606 | np->recverr = valbool; | 658 | np->recverr = valbool; |
| 607 | if (!val) | 659 | if (!val) |
| 608 | skb_queue_purge(&sk->sk_error_queue); | 660 | skb_queue_purge(&sk->sk_error_queue); |
| 609 | retv = 0; | 661 | retv = 0; |
| 610 | break; | 662 | break; |
| 611 | case IPV6_FLOWINFO_SEND: | 663 | case IPV6_FLOWINFO_SEND: |
| 664 | if (optlen < sizeof(int)) | ||
| 665 | goto e_inval; | ||
| 612 | np->sndflow = valbool; | 666 | np->sndflow = valbool; |
| 613 | retv = 0; | 667 | retv = 0; |
| 614 | break; | 668 | break; |
| @@ -628,6 +682,9 @@ done: | |||
| 628 | unsigned int pref = 0; | 682 | unsigned int pref = 0; |
| 629 | unsigned int prefmask = ~0; | 683 | unsigned int prefmask = ~0; |
| 630 | 684 | ||
| 685 | if (optlen < sizeof(int)) | ||
| 686 | goto e_inval; | ||
| 687 | |||
| 631 | retv = -EINVAL; | 688 | retv = -EINVAL; |
| 632 | 689 | ||
| 633 | /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ | 690 | /* check PUBLIC/TMP/PUBTMP_DEFAULT conflicts */ |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 2e6a53f3cc38..54f91efdae58 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -127,8 +127,6 @@ static struct in6_addr mld2_all_mcr = MLD2_ALL_MCR_INIT; | |||
| 127 | /* Big mc list lock for all the sockets */ | 127 | /* Big mc list lock for all the sockets */ |
| 128 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); | 128 | static DEFINE_RWLOCK(ipv6_sk_mc_lock); |
| 129 | 129 | ||
| 130 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); | ||
| 131 | |||
| 132 | static void igmp6_join_group(struct ifmcaddr6 *ma); | 130 | static void igmp6_join_group(struct ifmcaddr6 *ma); |
| 133 | static void igmp6_leave_group(struct ifmcaddr6 *ma); | 131 | static void igmp6_leave_group(struct ifmcaddr6 *ma); |
| 134 | static void igmp6_timer_handler(unsigned long data); | 132 | static void igmp6_timer_handler(unsigned long data); |
| @@ -177,7 +175,7 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; | |||
| 177 | * socket join on multicast group | 175 | * socket join on multicast group |
| 178 | */ | 176 | */ |
| 179 | 177 | ||
| 180 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | 178 | int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) |
| 181 | { | 179 | { |
| 182 | struct net_device *dev = NULL; | 180 | struct net_device *dev = NULL; |
| 183 | struct ipv6_mc_socklist *mc_lst; | 181 | struct ipv6_mc_socklist *mc_lst; |
| @@ -252,7 +250,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) | |||
| 252 | /* | 250 | /* |
| 253 | * socket leave on multicast group | 251 | * socket leave on multicast group |
| 254 | */ | 252 | */ |
| 255 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | 253 | int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) |
| 256 | { | 254 | { |
| 257 | struct ipv6_pinfo *np = inet6_sk(sk); | 255 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 258 | struct ipv6_mc_socklist *mc_lst, **lnk; | 256 | struct ipv6_mc_socklist *mc_lst, **lnk; |
| @@ -664,8 +662,8 @@ done: | |||
| 664 | return err; | 662 | return err; |
| 665 | } | 663 | } |
| 666 | 664 | ||
| 667 | int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, | 665 | int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, |
| 668 | struct in6_addr *src_addr) | 666 | const struct in6_addr *src_addr) |
| 669 | { | 667 | { |
| 670 | struct ipv6_pinfo *np = inet6_sk(sk); | 668 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 671 | struct ipv6_mc_socklist *mc; | 669 | struct ipv6_mc_socklist *mc; |
| @@ -871,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev) | |||
| 871 | /* | 869 | /* |
| 872 | * device multicast group inc (add if not found) | 870 | * device multicast group inc (add if not found) |
| 873 | */ | 871 | */ |
| 874 | int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) | 872 | int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) |
| 875 | { | 873 | { |
| 876 | struct ifmcaddr6 *mc; | 874 | struct ifmcaddr6 *mc; |
| 877 | struct inet6_dev *idev; | 875 | struct inet6_dev *idev; |
| @@ -942,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) | |||
| 942 | /* | 940 | /* |
| 943 | * device multicast group del | 941 | * device multicast group del |
| 944 | */ | 942 | */ |
| 945 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) | 943 | int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) |
| 946 | { | 944 | { |
| 947 | struct ifmcaddr6 *ma, **map; | 945 | struct ifmcaddr6 *ma, **map; |
| 948 | 946 | ||
| @@ -967,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) | |||
| 967 | return -ENOENT; | 965 | return -ENOENT; |
| 968 | } | 966 | } |
| 969 | 967 | ||
| 970 | int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr) | 968 | int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) |
| 971 | { | 969 | { |
| 972 | struct inet6_dev *idev = in6_dev_get(dev); | 970 | struct inet6_dev *idev = in6_dev_get(dev); |
| 973 | int err; | 971 | int err; |
| @@ -1012,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr) | |||
| 1012 | /* | 1010 | /* |
| 1013 | * check if the interface/address pair is valid | 1011 | * check if the interface/address pair is valid |
| 1014 | */ | 1012 | */ |
| 1015 | int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, | 1013 | int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, |
| 1016 | struct in6_addr *src_addr) | 1014 | const struct in6_addr *src_addr) |
| 1017 | { | 1015 | { |
| 1018 | struct inet6_dev *idev; | 1016 | struct inet6_dev *idev; |
| 1019 | struct ifmcaddr6 *mc; | 1017 | struct ifmcaddr6 *mc; |
| @@ -1406,6 +1404,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
| 1406 | struct sk_buff *skb; | 1404 | struct sk_buff *skb; |
| 1407 | struct mld2_report *pmr; | 1405 | struct mld2_report *pmr; |
| 1408 | struct in6_addr addr_buf; | 1406 | struct in6_addr addr_buf; |
| 1407 | const struct in6_addr *saddr; | ||
| 1409 | int err; | 1408 | int err; |
| 1410 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1409 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
| 1411 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1410 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
| @@ -1424,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) | |||
| 1424 | * use unspecified address as the source address | 1423 | * use unspecified address as the source address |
| 1425 | * when a valid link-local address is not available. | 1424 | * when a valid link-local address is not available. |
| 1426 | */ | 1425 | */ |
| 1427 | memset(&addr_buf, 0, sizeof(addr_buf)); | 1426 | saddr = &in6addr_any; |
| 1428 | } | 1427 | } else |
| 1428 | saddr = &addr_buf; | ||
| 1429 | 1429 | ||
| 1430 | ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0); | 1430 | ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0); |
| 1431 | 1431 | ||
| 1432 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1432 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
| 1433 | 1433 | ||
| @@ -1768,10 +1768,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1768 | struct inet6_dev *idev; | 1768 | struct inet6_dev *idev; |
| 1769 | struct sk_buff *skb; | 1769 | struct sk_buff *skb; |
| 1770 | struct icmp6hdr *hdr; | 1770 | struct icmp6hdr *hdr; |
| 1771 | struct in6_addr *snd_addr; | 1771 | const struct in6_addr *snd_addr, *saddr; |
| 1772 | struct in6_addr *addrp; | 1772 | struct in6_addr *addrp; |
| 1773 | struct in6_addr addr_buf; | 1773 | struct in6_addr addr_buf; |
| 1774 | struct in6_addr all_routers; | ||
| 1775 | int err, len, payload_len, full_len; | 1774 | int err, len, payload_len, full_len; |
| 1776 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1775 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
| 1777 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1776 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
| @@ -1782,11 +1781,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1782 | IP6_INC_STATS(__in6_dev_get(dev), | 1781 | IP6_INC_STATS(__in6_dev_get(dev), |
| 1783 | IPSTATS_MIB_OUTREQUESTS); | 1782 | IPSTATS_MIB_OUTREQUESTS); |
| 1784 | rcu_read_unlock(); | 1783 | rcu_read_unlock(); |
| 1785 | snd_addr = addr; | 1784 | if (type == ICMPV6_MGM_REDUCTION) |
| 1786 | if (type == ICMPV6_MGM_REDUCTION) { | 1785 | snd_addr = &in6addr_linklocal_allrouters; |
| 1787 | snd_addr = &all_routers; | 1786 | else |
| 1788 | ipv6_addr_all_routers(&all_routers); | 1787 | snd_addr = addr; |
| 1789 | } | ||
| 1790 | 1788 | ||
| 1791 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | 1789 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); |
| 1792 | payload_len = len + sizeof(ra); | 1790 | payload_len = len + sizeof(ra); |
| @@ -1809,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1809 | * use unspecified address as the source address | 1807 | * use unspecified address as the source address |
| 1810 | * when a valid link-local address is not available. | 1808 | * when a valid link-local address is not available. |
| 1811 | */ | 1809 | */ |
| 1812 | memset(&addr_buf, 0, sizeof(addr_buf)); | 1810 | saddr = &in6addr_any; |
| 1813 | } | 1811 | } else |
| 1812 | saddr = &addr_buf; | ||
| 1814 | 1813 | ||
| 1815 | ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len); | 1814 | ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len); |
| 1816 | 1815 | ||
| 1817 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); | 1816 | memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); |
| 1818 | 1817 | ||
| @@ -1823,7 +1822,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
| 1823 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); | 1822 | addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); |
| 1824 | ipv6_addr_copy(addrp, addr); | 1823 | ipv6_addr_copy(addrp, addr); |
| 1825 | 1824 | ||
| 1826 | hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len, | 1825 | hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, |
| 1827 | IPPROTO_ICMPV6, | 1826 | IPPROTO_ICMPV6, |
| 1828 | csum_partial((__u8 *) hdr, len, 0)); | 1827 | csum_partial((__u8 *) hdr, len, 0)); |
| 1829 | 1828 | ||
| @@ -2311,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev) | |||
| 2311 | void ipv6_mc_destroy_dev(struct inet6_dev *idev) | 2310 | void ipv6_mc_destroy_dev(struct inet6_dev *idev) |
| 2312 | { | 2311 | { |
| 2313 | struct ifmcaddr6 *i; | 2312 | struct ifmcaddr6 *i; |
| 2314 | struct in6_addr maddr; | ||
| 2315 | 2313 | ||
| 2316 | /* Deactivate timers */ | 2314 | /* Deactivate timers */ |
| 2317 | ipv6_mc_down(idev); | 2315 | ipv6_mc_down(idev); |
| 2318 | 2316 | ||
| 2319 | /* Delete all-nodes address. */ | 2317 | /* Delete all-nodes address. */ |
| 2320 | ipv6_addr_all_nodes(&maddr); | ||
| 2321 | |||
| 2322 | /* We cannot call ipv6_dev_mc_dec() directly, our caller in | 2318 | /* We cannot call ipv6_dev_mc_dec() directly, our caller in |
| 2323 | * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will | 2319 | * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will |
| 2324 | * fail. | 2320 | * fail. |
| 2325 | */ | 2321 | */ |
| 2326 | __ipv6_dev_mc_dec(idev, &maddr); | 2322 | __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes); |
| 2327 | 2323 | ||
| 2328 | if (idev->cnf.forwarding) { | 2324 | if (idev->cnf.forwarding) |
| 2329 | ipv6_addr_all_routers(&maddr); | 2325 | __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters); |
| 2330 | __ipv6_dev_mc_dec(idev, &maddr); | ||
| 2331 | } | ||
| 2332 | 2326 | ||
| 2333 | write_lock_bh(&idev->lock); | 2327 | write_lock_bh(&idev->lock); |
| 2334 | while ((i = idev->mc_list) != NULL) { | 2328 | while ((i = idev->mc_list) != NULL) { |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 42403c626c27..ad1cc5bbf977 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
| @@ -44,9 +44,9 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen) | |||
| 44 | if (!data) | 44 | if (!data) |
| 45 | return NULL; | 45 | return NULL; |
| 46 | if (padlen == 1) { | 46 | if (padlen == 1) { |
| 47 | data[0] = MIP6_OPT_PAD_1; | 47 | data[0] = IPV6_TLV_PAD0; |
| 48 | } else if (padlen > 1) { | 48 | } else if (padlen > 1) { |
| 49 | data[0] = MIP6_OPT_PAD_N; | 49 | data[0] = IPV6_TLV_PADN; |
| 50 | data[1] = padlen - 2; | 50 | data[1] = padlen - 2; |
| 51 | if (padlen > 2) | 51 | if (padlen > 2) |
| 52 | memset(data+2, 0, data[1]); | 52 | memset(data+2, 0, data[1]); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index b3295d82fece..2c74885f8355 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -442,8 +442,9 @@ static void pndisc_destructor(struct pneigh_entry *n) | |||
| 442 | */ | 442 | */ |
| 443 | static void __ndisc_send(struct net_device *dev, | 443 | static void __ndisc_send(struct net_device *dev, |
| 444 | struct neighbour *neigh, | 444 | struct neighbour *neigh, |
| 445 | struct in6_addr *daddr, struct in6_addr *saddr, | 445 | const struct in6_addr *daddr, |
| 446 | struct icmp6hdr *icmp6h, struct in6_addr *target, | 446 | const struct in6_addr *saddr, |
| 447 | struct icmp6hdr *icmp6h, const struct in6_addr *target, | ||
| 447 | int llinfo) | 448 | int llinfo) |
| 448 | { | 449 | { |
| 449 | struct flowi fl; | 450 | struct flowi fl; |
| @@ -529,12 +530,13 @@ static void __ndisc_send(struct net_device *dev, | |||
| 529 | } | 530 | } |
| 530 | 531 | ||
| 531 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | 532 | static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, |
| 532 | struct in6_addr *daddr, struct in6_addr *solicited_addr, | 533 | const struct in6_addr *daddr, |
| 533 | int router, int solicited, int override, int inc_opt) | 534 | const struct in6_addr *solicited_addr, |
| 535 | int router, int solicited, int override, int inc_opt) | ||
| 534 | { | 536 | { |
| 535 | struct in6_addr tmpaddr; | 537 | struct in6_addr tmpaddr; |
| 536 | struct inet6_ifaddr *ifp; | 538 | struct inet6_ifaddr *ifp; |
| 537 | struct in6_addr *src_addr; | 539 | const struct in6_addr *src_addr; |
| 538 | struct icmp6hdr icmp6h = { | 540 | struct icmp6hdr icmp6h = { |
| 539 | .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, | 541 | .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, |
| 540 | }; | 542 | }; |
| @@ -564,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
| 564 | } | 566 | } |
| 565 | 567 | ||
| 566 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | 568 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, |
| 567 | struct in6_addr *solicit, | 569 | const struct in6_addr *solicit, |
| 568 | struct in6_addr *daddr, struct in6_addr *saddr) | 570 | const struct in6_addr *daddr, const struct in6_addr *saddr) |
| 569 | { | 571 | { |
| 570 | struct in6_addr addr_buf; | 572 | struct in6_addr addr_buf; |
| 571 | struct icmp6hdr icmp6h = { | 573 | struct icmp6hdr icmp6h = { |
| @@ -584,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
| 584 | !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); | 586 | !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); |
| 585 | } | 587 | } |
| 586 | 588 | ||
| 587 | void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | 589 | void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, |
| 588 | struct in6_addr *daddr) | 590 | const struct in6_addr *daddr) |
| 589 | { | 591 | { |
| 590 | struct icmp6hdr icmp6h = { | 592 | struct icmp6hdr icmp6h = { |
| 591 | .icmp6_type = NDISC_ROUTER_SOLICITATION, | 593 | .icmp6_type = NDISC_ROUTER_SOLICITATION, |
| @@ -816,10 +818,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) | |||
| 816 | is_router = !!idev->cnf.forwarding; | 818 | is_router = !!idev->cnf.forwarding; |
| 817 | 819 | ||
| 818 | if (dad) { | 820 | if (dad) { |
| 819 | struct in6_addr maddr; | 821 | ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target, |
| 820 | |||
| 821 | ipv6_addr_all_nodes(&maddr); | ||
| 822 | ndisc_send_na(dev, NULL, &maddr, &msg->target, | ||
| 823 | is_router, 0, (ifp != NULL), 1); | 822 | is_router, 0, (ifp != NULL), 1); |
| 824 | goto out; | 823 | goto out; |
| 825 | } | 824 | } |
| @@ -1447,7 +1446,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1447 | } | 1446 | } |
| 1448 | 1447 | ||
| 1449 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1448 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, |
| 1450 | struct in6_addr *target) | 1449 | const struct in6_addr *target) |
| 1451 | { | 1450 | { |
| 1452 | struct net_device *dev = skb->dev; | 1451 | struct net_device *dev = skb->dev; |
| 1453 | struct net *net = dev_net(dev); | 1452 | struct net *net = dev_net(dev); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 088b80b4ce74..6193b124cbc7 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -357,8 +357,10 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
| 357 | read_lock(&raw_v6_hashinfo.lock); | 357 | read_lock(&raw_v6_hashinfo.lock); |
| 358 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); | 358 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); |
| 359 | if (sk != NULL) { | 359 | if (sk != NULL) { |
| 360 | saddr = &ipv6_hdr(skb)->saddr; | 360 | /* Note: ipv6_hdr(skb) != skb->data */ |
| 361 | daddr = &ipv6_hdr(skb)->daddr; | 361 | struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data; |
| 362 | saddr = &ip6h->saddr; | ||
| 363 | daddr = &ip6h->daddr; | ||
| 362 | net = dev_net(skb->dev); | 364 | net = dev_net(skb->dev); |
| 363 | 365 | ||
| 364 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, | 366 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
| @@ -805,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 805 | fl.fl6_flowlabel = np->flow_label; | 807 | fl.fl6_flowlabel = np->flow_label; |
| 806 | } | 808 | } |
| 807 | 809 | ||
| 808 | if (ipv6_addr_any(daddr)) { | ||
| 809 | /* | ||
| 810 | * unspecified destination address | ||
| 811 | * treated as error... is this correct ? | ||
| 812 | */ | ||
| 813 | fl6_sock_release(flowlabel); | ||
| 814 | return(-EINVAL); | ||
| 815 | } | ||
| 816 | |||
| 817 | if (fl.oif == 0) | 810 | if (fl.oif == 0) |
| 818 | fl.oif = sk->sk_bound_dev_if; | 811 | fl.oif = sk->sk_bound_dev_if; |
| 819 | 812 | ||
| @@ -846,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 846 | if (err) | 839 | if (err) |
| 847 | goto out; | 840 | goto out; |
| 848 | 841 | ||
| 849 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 842 | if (!ipv6_addr_any(daddr)) |
| 843 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
| 844 | else | ||
| 845 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
| 850 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 846 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
| 851 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 847 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 852 | 848 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 269b76093288..6293cb91ed1d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -556,8 +556,8 @@ out: | |||
| 556 | 556 | ||
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | struct rt6_info *rt6_lookup(struct net *net, struct in6_addr *daddr, | 559 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
| 560 | struct in6_addr *saddr, int oif, int strict) | 560 | const struct in6_addr *saddr, int oif, int strict) |
| 561 | { | 561 | { |
| 562 | struct flowi fl = { | 562 | struct flowi fl = { |
| 563 | .oif = oif, | 563 | .oif = oif, |
| @@ -925,7 +925,7 @@ static DEFINE_SPINLOCK(icmp6_dst_lock); | |||
| 925 | 925 | ||
| 926 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | 926 | struct dst_entry *icmp6_dst_alloc(struct net_device *dev, |
| 927 | struct neighbour *neigh, | 927 | struct neighbour *neigh, |
| 928 | struct in6_addr *addr) | 928 | const struct in6_addr *addr) |
| 929 | { | 929 | { |
| 930 | struct rt6_info *rt; | 930 | struct rt6_info *rt; |
| 931 | struct inet6_dev *idev = in6_dev_get(dev); | 931 | struct inet6_dev *idev = in6_dev_get(dev); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index cc16fe07bbff..91e46fbe6ce2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -379,7 +379,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
| 379 | dev_put(dev); | 379 | dev_put(dev); |
| 380 | } else { | 380 | } else { |
| 381 | ipip6_tunnel_unlink(netdev_priv(dev)); | 381 | ipip6_tunnel_unlink(netdev_priv(dev)); |
| 382 | ipip6_tunnel_del_prl(netdev_priv(dev), 0); | 382 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); |
| 383 | dev_put(dev); | 383 | dev_put(dev); |
| 384 | } | 384 | } |
| 385 | } | 385 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8ebf6de29562..80eab71e77ff 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -543,7 +543,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
| 543 | return NULL; | 543 | return NULL; |
| 544 | 544 | ||
| 545 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 545 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
| 546 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | 546 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr)) |
| 547 | return &tp->md5sig_info->keys6[i].base; | 547 | return &tp->md5sig_info->keys6[i].base; |
| 548 | } | 548 | } |
| 549 | return NULL; | 549 | return NULL; |
| @@ -632,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | |||
| 632 | int i; | 632 | int i; |
| 633 | 633 | ||
| 634 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 634 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
| 635 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | 635 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) { |
| 636 | /* Free the key */ | 636 | /* Free the key */ |
| 637 | kfree(tp->md5sig_info->keys6[i].base.key); | 637 | kfree(tp->md5sig_info->keys6[i].base.key); |
| 638 | tp->md5sig_info->entries6--; | 638 | tp->md5sig_info->entries6--; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 30ef7dc5d403..1fd784f3e2ec 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -752,7 +752,10 @@ do_udp_sendmsg: | |||
| 752 | opt = ipv6_fixup_options(&opt_space, opt); | 752 | opt = ipv6_fixup_options(&opt_space, opt); |
| 753 | 753 | ||
| 754 | fl.proto = sk->sk_protocol; | 754 | fl.proto = sk->sk_protocol; |
| 755 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 755 | if (!ipv6_addr_any(daddr)) |
| 756 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
| 757 | else | ||
| 758 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
| 756 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 759 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
| 757 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 760 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
| 758 | fl.fl_ip_sport = inet->sport; | 761 | fl.fl_ip_sport = inet->sport; |
