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; #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } extern const struct in6_addr in6addr_loopback; #define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } +#ifdef __KERNEL__ +extern const struct in6_addr in6addr_linklocal_allnodes; +#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \ + { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } +extern const struct in6_addr in6addr_linklocal_allrouters; +#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \ + { { { 0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2 } } } +#endif struct sockaddr_in6 { 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, struct net_device *dev); extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, - struct in6_addr *addr, + const struct in6_addr *addr, struct net_device *dev, int strict); extern int ipv6_dev_get_saddr(struct net_device *dev, - struct in6_addr *daddr, + const struct in6_addr *daddr, unsigned int srcprefs, struct in6_addr *saddr); extern int ipv6_get_lladdr(struct net_device *dev, @@ -105,25 +105,27 @@ extern u32 ipv6_addr_label(const struct in6_addr *addr, /* * multicast prototypes (mcast.c) */ -extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, - struct in6_addr *addr); -extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, - struct in6_addr *addr); +extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, + const struct in6_addr *addr); +extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, + const struct in6_addr *addr); extern void ipv6_sock_mc_close(struct sock *sk); -extern int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, - struct in6_addr *src_addr); +extern int inet6_mc_check(struct sock *sk, + const struct in6_addr *mc_addr, + const struct in6_addr *src_addr); -extern int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr); -extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); -extern int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr); +extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr); +extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr); +extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr); extern void ipv6_mc_up(struct inet6_dev *idev); extern void ipv6_mc_down(struct inet6_dev *idev); extern void ipv6_mc_init_dev(struct inet6_dev *idev); extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); -extern int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, - struct in6_addr *src_addr); +extern int ipv6_chk_mcast_addr(struct net_device *dev, + const struct in6_addr *group, + const struct in6_addr *src_addr); extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr); 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) #define in6_ifa_hold(ifp) atomic_inc(&(ifp)->refcnt) -/* - * Hash function taken from net_alias.c - */ - -static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr) -{ - __u32 word; - - /* - * We perform the hash function over the last 64 bits of the address - * This will include the IEEE address token on links that support it. - */ - - word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); - word ^= (word >> 16); - word ^= (word >> 8); - - return ((word ^ (word >> 4)) & 0x0f); -} /* * compute link-local solicited-node multicast address @@ -222,17 +205,6 @@ static inline void addrconf_addr_solict_mult(const struct in6_addr *addr, htonl(0xFF000000) | addr->s6_addr32[3]); } - -static inline void ipv6_addr_all_nodes(struct in6_addr *addr) -{ - ipv6_addr_set(addr, htonl(0xFF020000), 0, 0, htonl(0x1)); -} - -static inline void ipv6_addr_all_routers(struct in6_addr *addr) -{ - ipv6_addr_set(addr, htonl(0xFF020000), 0, 0, htonl(0x2)); -} - static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) { 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) static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr) { - return (addr->s6_addr32[0] == htonl(0xff020000) && - addr->s6_addr32[1] == 0 && - addr->s6_addr32[2] == 0 && - addr->s6_addr32[3] == htonl(0x00000001)); + return (((addr->s6_addr32[0] ^ htonl(0xff020000)) | + addr->s6_addr32[1] | addr->s6_addr32[2] | + (addr->s6_addr32[3] ^ htonl(0x00000001))) == 0); } static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr) { - return (addr->s6_addr32[0] == htonl(0xff020000) && - addr->s6_addr32[1] == 0 && - addr->s6_addr32[2] == 0 && - addr->s6_addr32[3] == htonl(0x00000002)); + return (((addr->s6_addr32[0] ^ htonl(0xff020000)) | + addr->s6_addr32[1] | addr->s6_addr32[2] | + (addr->s6_addr32[3] ^ htonl(0x00000002))) == 0); } -static inline int ipv6_isatap_eui64(u8 *eui, __be32 addr) -{ - eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || - ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || - ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || - ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) || - ipv4_is_test_198(addr) || ipv4_is_multicast(addr) || - ipv4_is_lbcast(addr)) ? 0x00 : 0x02; - eui[1] = 0; - eui[2] = 0x5E; - eui[3] = 0xFE; - memcpy (eui+4, &addr, 4); - return 0; -} +extern int __ipv6_isatap_ifid(u8 *eui, __be32 addr); static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) { 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 *); extern int ip6_del_rt(struct rt6_info *); extern struct rt6_info *rt6_lookup(struct net *net, - struct in6_addr *daddr, - struct in6_addr *saddr, + const struct in6_addr *daddr, + const struct in6_addr *saddr, int oif, int flags); extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *addr); + const struct in6_addr *addr); extern int icmp6_dst_gc(int *more); 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 ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, const struct in6_addr *a2) { - unsigned int i; - - for (i = 0; i < 4; i++) - if ((a1->s6_addr32[i] ^ a2->s6_addr32[i]) & m->s6_addr32[i]) - return 1; - return 0; + return (!!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) | + ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) | + ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) | + ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]))); } 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, static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2) { - return (a1->s6_addr32[0] == a2->s6_addr32[0] && - a1->s6_addr32[1] == a2->s6_addr32[1] && - a1->s6_addr32[2] == a2->s6_addr32[2] && - a1->s6_addr32[3] == a2->s6_addr32[3]); + return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | + (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | + (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | + (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0); } 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) static inline int ipv6_addr_v4mapped(const struct in6_addr *a) { - return ((a->s6_addr32[0] | a->s6_addr32[1]) == 0 && - a->s6_addr32[2] == htonl(0x0000ffff)); + return ((a->s6_addr32[0] | a->s6_addr32[1] | + (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0); } /* @@ -453,8 +451,8 @@ extern int ip6_xmit(struct sock *sk, extern int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, - struct in6_addr *saddr, - struct in6_addr *daddr, + const struct in6_addr *saddr, + const struct in6_addr *daddr, int proto, int len); 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 @@ #include #include -#define MIP6_OPT_PAD_1 0 -#define MIP6_OPT_PAD_N 1 - /* * Mobility Header */ 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); extern void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *solicit, - struct in6_addr *daddr, - struct in6_addr *saddr); + const struct in6_addr *solicit, + const struct in6_addr *daddr, + const struct in6_addr *saddr); extern void ndisc_send_rs(struct net_device *dev, - struct in6_addr *saddr, - struct in6_addr *daddr); + const struct in6_addr *saddr, + const struct in6_addr *daddr); extern void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, - struct in6_addr *target); + const struct in6_addr *target); extern int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir); @@ -134,7 +134,7 @@ extern int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, extern void inet6_ifinfo_notify(int event, struct inet6_dev *idev); -static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr) +static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr) { 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 = { /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; +const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT; +const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT; /* Check if a valid qdisc is available */ static inline int addrconf_qdisc_ok(struct net_device *dev) @@ -321,7 +323,6 @@ EXPORT_SYMBOL(in6_dev_finish_destroy); static struct inet6_dev * ipv6_add_dev(struct net_device *dev) { struct inet6_dev *ndev; - struct in6_addr maddr; ASSERT_RTNL(); @@ -406,8 +407,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) rcu_assign_pointer(dev->ip6_ptr, ndev); /* Join all-node multicast group */ - ipv6_addr_all_nodes(&maddr); - ipv6_dev_mc_inc(dev, &maddr); + ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); return ndev; } @@ -433,18 +433,15 @@ static void dev_forward_change(struct inet6_dev *idev) { struct net_device *dev; struct inet6_ifaddr *ifa; - struct in6_addr addr; if (!idev) return; dev = idev->dev; if (dev && (dev->flags & IFF_MULTICAST)) { - ipv6_addr_all_routers(&addr); - if (idev->cnf.forwarding) - ipv6_dev_mc_inc(dev, &addr); + ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); else - ipv6_dev_mc_dec(dev, &addr); + ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); } for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { if (ifa->flags&IFA_F_TENTATIVE) @@ -541,6 +538,25 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) *ifap = ifp; } +/* + * Hash function taken from net_alias.c + */ +static u8 ipv6_addr_hash(const struct in6_addr *addr) +{ + __u32 word; + + /* + * We perform the hash function over the last 64 bits of the address + * This will include the IEEE address token on links that support it. + */ + + word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); + word ^= (word >> 16); + word ^= (word >> 8); + + return ((word ^ (word >> 4)) & 0x0f); +} + /* On success it returns ifp with increased reference count */ static struct inet6_ifaddr * @@ -921,7 +937,7 @@ struct ipv6_saddr_score { }; struct ipv6_saddr_dst { - struct in6_addr *addr; + const struct in6_addr *addr; int ifindex; int scope; int label; @@ -1055,7 +1071,7 @@ out: } int ipv6_dev_get_saddr(struct net_device *dst_dev, - struct in6_addr *daddr, unsigned int prefs, + const struct in6_addr *daddr, unsigned int prefs, struct in6_addr *saddr) { struct ipv6_saddr_score scores[2], @@ -1290,7 +1306,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) EXPORT_SYMBOL(ipv6_chk_prefix); -struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr, +struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, struct net_device *dev, int strict) { struct inet6_ifaddr * ifp; @@ -1475,6 +1491,29 @@ static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev) return 0; } +int __ipv6_isatap_ifid(u8 *eui, __be32 addr) +{ + eui[0] = (ipv4_is_zeronet(addr) || ipv4_is_private_10(addr) || + ipv4_is_loopback(addr) || ipv4_is_linklocal_169(addr) || + ipv4_is_private_172(addr) || ipv4_is_test_192(addr) || + ipv4_is_anycast_6to4(addr) || ipv4_is_private_192(addr) || + ipv4_is_test_198(addr) || ipv4_is_multicast(addr) || + ipv4_is_lbcast(addr)) ? 0x00 : 0x02; + eui[1] = 0; + eui[2] = 0x5E; + eui[3] = 0xFE; + memcpy(eui + 4, &addr, 4); + return 0; +} +EXPORT_SYMBOL(__ipv6_isatap_ifid); + +static int addrconf_ifid_sit(u8 *eui, struct net_device *dev) +{ + if (dev->priv_flags & IFF_ISATAP) + return __ipv6_isatap_ifid(eui, *(__be32 *)dev->dev_addr); + return -1; +} + static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) { switch (dev->type) { @@ -1487,8 +1526,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) case ARPHRD_INFINIBAND: return addrconf_ifid_infiniband(eui, dev); case ARPHRD_SIT: - if (dev->priv_flags & IFF_ISATAP) - return ipv6_isatap_eui64(eui, *(__be32 *)dev->dev_addr); + return addrconf_ifid_sit(eui, dev); } return -1; } @@ -2613,8 +2651,6 @@ static void addrconf_rs_timer(unsigned long data) spin_lock(&ifp->lock); if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { - struct in6_addr all_routers; - /* The wait after the last probe can be shorter */ addrconf_mod_timer(ifp, AC_RS, (ifp->probes == ifp->idev->cnf.rtr_solicits) ? @@ -2622,9 +2658,7 @@ static void addrconf_rs_timer(unsigned long data) ifp->idev->cnf.rtr_solicit_interval); spin_unlock(&ifp->lock); - ipv6_addr_all_routers(&all_routers); - - ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); + ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); } else { spin_unlock(&ifp->lock); /* @@ -2711,7 +2745,6 @@ static void addrconf_dad_timer(unsigned long data) { struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; struct inet6_dev *idev = ifp->idev; - struct in6_addr unspec; struct in6_addr mcaddr; read_lock_bh(&idev->lock); @@ -2740,9 +2773,8 @@ static void addrconf_dad_timer(unsigned long data) read_unlock_bh(&idev->lock); /* send a neighbour solicitation for our addr */ - memset(&unspec, 0, sizeof(unspec)); addrconf_addr_solict_mult(&ifp->addr, &mcaddr); - ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec); + ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &in6addr_any); out: in6_ifa_put(ifp); } @@ -2765,16 +2797,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) ifp->idev->cnf.rtr_solicits > 0 && (dev->flags&IFF_LOOPBACK) == 0 && (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { - struct in6_addr all_routers; - - ipv6_addr_all_routers(&all_routers); - /* * If a host as already performed a random delay * [...] as part of DAD [...] there is no need * to delay again before sending the first RS */ - ndisc_send_rs(ifp->idev->dev, &ifp->addr, &all_routers); + ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); spin_lock_bh(&ifp->lock); ifp->probes = 1; @@ -2951,7 +2979,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { if (!net_eq(dev_net(ifp->idev->dev), net)) continue; - if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && + if (ipv6_addr_equal(&ifp->addr, addr) && (ifp->flags & IFA_F_HOMEADDRESS)) { ret = 1; 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) void fib6_rules_cleanup(void) { - return unregister_pernet_subsys(&fib6_rules_net_ops); + unregister_pernet_subsys(&fib6_rules_net_ops); } 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) * is for MLD (0x0000). */ if ((ptr[2] | ptr[3]) == 0) { + deliver = 0; + if (!ipv6_ext_hdr(nexthdr)) { /* BUG */ - goto discard; + goto out; } offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); if (offset < 0) - goto discard; + goto out; if (nexthdr != IPPROTO_ICMPV6) - goto discard; + goto out; if (!pskb_may_pull(skb, (skb_network_header(skb) + offset + 1 - skb->data))) - goto discard; + goto out; icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset); @@ -285,12 +287,9 @@ int ip6_mc_input(struct sk_buff *skb) case ICMPV6_MGM_REPORT: case ICMPV6_MGM_REDUCTION: case ICMPV6_MLD2_REPORT: + deliver = 1; break; - default: - /* Bogus */ - goto discard; } - deliver = 1; goto out; } /* unknown RA - process it normally */ @@ -308,15 +307,14 @@ int ip6_mc_input(struct sk_buff *skb) ip6_mr_input(skb2); } } -#endif out: - if (likely(deliver)) { +#endif + if (likely(deliver)) ip6_input(skb); - return 0; + else { + /* discard */ + kfree_skb(skb); } -discard: - /* discard */ - kfree_skb(skb); return 0; } 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); */ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, - struct in6_addr *saddr, struct in6_addr *daddr, + const struct in6_addr *saddr, const struct in6_addr *daddr, int proto, int len) { 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 @@ #include #include #include -#include #include #include #include -#include #include #include -#include #include -#include #include #include #include -#include -#include #include -#include #include #include -#include -#include #include #include @@ -83,7 +74,7 @@ static int mroute_do_pim; #define mroute_do_pim 0 #endif -static struct mfc6_cache *mfc6_cache_array[MFC_LINES]; /* Forwarding cache */ +static struct mfc6_cache *mfc6_cache_array[MFC6_LINES]; /* Forwarding cache */ static struct mfc6_cache *mfc_unres_queue; /* Queue of unresolved entries */ static atomic_t cache_resolve_queue_len; /* Size of unresolved */ @@ -102,7 +93,7 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static int ip6_mr_forward(struct sk_buff *skb, struct mfc6_cache *cache); -static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert); +static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert); static int ip6mr_fill_mroute(struct sk_buff *skb, struct mfc6_cache *c, struct rtmsg *rtm); #ifdef CONFIG_IPV6_PIMSM_V2 @@ -597,9 +588,9 @@ static void ip6mr_update_thresholds(struct mfc6_cache *cache, unsigned char *ttl { int vifi; - cache->mfc_un.res.minvif = MAXVIFS; + cache->mfc_un.res.minvif = MAXMIFS; cache->mfc_un.res.maxvif = 0; - memset(cache->mfc_un.res.ttls, 255, MAXVIFS); + memset(cache->mfc_un.res.ttls, 255, MAXMIFS); for (vifi = 0; vifi < maxvif; vifi++) { if (MIF_EXISTS(vifi) && ttls[vifi] && ttls[vifi] < 255) { @@ -700,7 +691,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void) if (c == NULL) return NULL; memset(c, 0, sizeof(*c)); - c->mfc_un.res.minvif = MAXVIFS; + c->mfc_un.res.minvif = MAXMIFS; return c; } @@ -753,7 +744,7 @@ static void ip6mr_cache_resolve(struct mfc6_cache *uc, struct mfc6_cache *c) * Called under mrt_lock. */ -static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) +static int ip6mr_cache_report(struct sk_buff *pkt, mifi_t mifi, int assert) { struct sk_buff *skb; struct mrt6msg *msg; @@ -815,7 +806,7 @@ static int ip6mr_cache_report(struct sk_buff *pkt, vifi_t vifi, int assert) msg->im6_mbz = 0; msg->im6_msgtype = assert; - msg->im6_mif = vifi; + msg->im6_mif = mifi; msg->im6_pad = 0; ipv6_addr_copy(&msg->im6_src, &ipv6_hdr(pkt)->saddr); 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) */ static int -ip6mr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) +ip6mr_cache_unresolved(mifi_t mifi, struct sk_buff *skb) { int err; struct mfc6_cache *c; @@ -883,7 +874,7 @@ ip6mr_cache_unresolved(vifi_t vifi, struct sk_buff *skb) /* * Reflect first query at pim6sd */ - if ((err = ip6mr_cache_report(skb, vifi, MRT6MSG_NOCACHE)) < 0) { + if ((err = ip6mr_cache_report(skb, mifi, MRT6MSG_NOCACHE)) < 0) { /* If the report failed throw the cache entry out - Brad Parker */ @@ -992,11 +983,11 @@ static int ip6mr_mfc_add(struct mf6cctl *mfc, int mrtsock) { int line; struct mfc6_cache *uc, *c, **cp; - unsigned char ttls[MAXVIFS]; + unsigned char ttls[MAXMIFS]; int i; - memset(ttls, 255, MAXVIFS); - for (i = 0; i < MAXVIFS; i++) { + memset(ttls, 255, MAXMIFS); + for (i = 0; i < MAXMIFS; i++) { if (IF_ISSET(i, &mfc->mf6cc_ifset)) ttls[i] = 1; @@ -1188,7 +1179,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int return -EINVAL; if (copy_from_user(&vif, optval, sizeof(vif))) return -EFAULT; - if (vif.mif6c_mifi >= MAXVIFS) + if (vif.mif6c_mifi >= MAXMIFS) return -ENFILE; rtnl_lock(); ret = mif6_add(&vif, sk == mroute6_socket); @@ -1238,7 +1229,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, int #ifdef CONFIG_IPV6_PIMSM_V2 case MRT6_PIM: { - int v, ret; + int v; if (get_user(v, (int __user *)optval)) return -EFAULT; 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 @@ * * FIXME: Make the setsockopt code POSIX compliant: That is * - * o Return -EINVAL for setsockopt of short lengths * o Truncate getsockopt returns * o Return an optlen of the truncated length if need be * @@ -114,8 +113,13 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (optval == NULL) val=0; - else if (get_user(val, (int __user *) optval)) - return -EFAULT; + else { + if (optlen >= sizeof(int)) { + if (get_user(val, (int __user *) optval)) + return -EFAULT; + } else + val = 0; + } valbool = (val!=0); @@ -127,6 +131,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, switch (optname) { case IPV6_ADDRFORM: + if (optlen < sizeof(int)) + goto e_inval; if (val == PF_INET) { struct ipv6_txoptions *opt; struct sk_buff *pktopt; @@ -159,8 +165,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (sk->sk_protocol == IPPROTO_TCP) { struct inet_connection_sock *icsk = inet_csk(sk); - struct net *net = sock_net(sk); - local_bh_disable(); sock_prot_inuse_add(net, sk->sk_prot, -1); sock_prot_inuse_add(net, &tcp_prot, 1); @@ -172,7 +176,6 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); } else { struct proto *prot = &udp_prot; - struct net *net = sock_net(sk); if (sk->sk_protocol == IPPROTO_UDPLITE) prot = &udplite_prot; @@ -204,63 +207,86 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, goto e_inval; case IPV6_V6ONLY: - if (inet_sk(sk)->num) + if (optlen < sizeof(int) || + inet_sk(sk)->num) goto e_inval; np->ipv6only = valbool; retv = 0; break; case IPV6_RECVPKTINFO: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxinfo = valbool; retv = 0; break; case IPV6_2292PKTINFO: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxoinfo = valbool; retv = 0; break; case IPV6_RECVHOPLIMIT: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxhlim = valbool; retv = 0; break; case IPV6_2292HOPLIMIT: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxohlim = valbool; retv = 0; break; case IPV6_RECVRTHDR: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.srcrt = valbool; retv = 0; break; case IPV6_2292RTHDR: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.osrcrt = valbool; retv = 0; break; case IPV6_RECVHOPOPTS: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.hopopts = valbool; retv = 0; break; case IPV6_2292HOPOPTS: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.ohopopts = valbool; retv = 0; break; case IPV6_RECVDSTOPTS: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.dstopts = valbool; retv = 0; break; case IPV6_2292DSTOPTS: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.odstopts = valbool; retv = 0; break; case IPV6_TCLASS: + if (optlen < sizeof(int)) + goto e_inval; if (val < -1 || val > 0xff) goto e_inval; np->tclass = val; @@ -268,11 +294,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, break; case IPV6_RECVTCLASS: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxtclass = valbool; retv = 0; break; case IPV6_FLOWINFO: + if (optlen < sizeof(int)) + goto e_inval; np->rxopt.bits.rxflow = valbool; retv = 0; break; @@ -291,9 +321,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) break; - retv = -EINVAL; - if (optlen & 0x7 || optlen > 8 * 255) - break; + if (optlen < sizeof(struct ipv6_opt_hdr) || + optlen & 0x7 || optlen > 8 * 255) + goto e_inval; opt = ipv6_renew_options(sk, np->opt, optname, (struct ipv6_opt_hdr __user *)optval, @@ -411,6 +441,8 @@ done: break; } case IPV6_UNICAST_HOPS: + if (optlen < sizeof(int)) + goto e_inval; if (val > 255 || val < -1) goto e_inval; np->hop_limit = val; @@ -420,6 +452,8 @@ done: case IPV6_MULTICAST_HOPS: if (sk->sk_type == SOCK_STREAM) goto e_inval; + if (optlen < sizeof(int)) + goto e_inval; if (val > 255 || val < -1) goto e_inval; np->mcast_hops = val; @@ -427,6 +461,8 @@ done: break; case IPV6_MULTICAST_LOOP: + if (optlen < sizeof(int)) + goto e_inval; np->mc_loop = valbool; retv = 0; break; @@ -434,6 +470,8 @@ done: case IPV6_MULTICAST_IF: if (sk->sk_type == SOCK_STREAM) goto e_inval; + if (optlen < sizeof(int)) + goto e_inval; if (val) { if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != val) @@ -452,6 +490,9 @@ done: { struct ipv6_mreq mreq; + if (optlen < sizeof(struct ipv6_mreq)) + goto e_inval; + retv = -EPROTO; if (inet_sk(sk)->is_icsk) break; @@ -471,7 +512,7 @@ done: { struct ipv6_mreq mreq; - if (optlen != sizeof(struct ipv6_mreq)) + if (optlen < sizeof(struct ipv6_mreq)) goto e_inval; retv = -EFAULT; @@ -490,6 +531,9 @@ done: struct group_req greq; struct sockaddr_in6 *psin6; + if (optlen < sizeof(struct group_req)) + goto e_inval; + retv = -EFAULT; if (copy_from_user(&greq, optval, sizeof(struct group_req))) break; @@ -514,7 +558,7 @@ done: struct group_source_req greqs; int omode, add; - if (optlen != sizeof(struct group_source_req)) + if (optlen < sizeof(struct group_source_req)) goto e_inval; if (copy_from_user(&greqs, optval, sizeof(greqs))) { retv = -EFAULT; @@ -588,27 +632,37 @@ done: break; } case IPV6_ROUTER_ALERT: + if (optlen < sizeof(int)) + goto e_inval; retv = ip6_ra_control(sk, val, NULL); break; case IPV6_MTU_DISCOVER: + if (optlen < sizeof(int)) + goto e_inval; if (val<0 || val>3) goto e_inval; np->pmtudisc = val; retv = 0; break; case IPV6_MTU: + if (optlen < sizeof(int)) + goto e_inval; if (val && val < IPV6_MIN_MTU) goto e_inval; np->frag_size = val; retv = 0; break; case IPV6_RECVERR: + if (optlen < sizeof(int)) + goto e_inval; np->recverr = valbool; if (!val) skb_queue_purge(&sk->sk_error_queue); retv = 0; break; case IPV6_FLOWINFO_SEND: + if (optlen < sizeof(int)) + goto e_inval; np->sndflow = valbool; retv = 0; break; @@ -628,6 +682,9 @@ done: unsigned int pref = 0; unsigned int prefmask = ~0; + if (optlen < sizeof(int)) + goto e_inval; + retv = -EINVAL; /* 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; /* Big mc list lock for all the sockets */ static DEFINE_RWLOCK(ipv6_sk_mc_lock); -int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr); - static void igmp6_join_group(struct ifmcaddr6 *ma); static void igmp6_leave_group(struct ifmcaddr6 *ma); static void igmp6_timer_handler(unsigned long data); @@ -177,7 +175,7 @@ int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; * socket join on multicast group */ -int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) +int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct net_device *dev = NULL; struct ipv6_mc_socklist *mc_lst; @@ -252,7 +250,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) /* * socket leave on multicast group */ -int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) +int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) { struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_mc_socklist *mc_lst, **lnk; @@ -664,8 +662,8 @@ done: return err; } -int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr, - struct in6_addr *src_addr) +int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr, + const struct in6_addr *src_addr) { struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_mc_socklist *mc; @@ -871,7 +869,7 @@ static void mld_clear_delrec(struct inet6_dev *idev) /* * device multicast group inc (add if not found) */ -int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) +int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) { struct ifmcaddr6 *mc; struct inet6_dev *idev; @@ -942,7 +940,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr) /* * device multicast group del */ -int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) +int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) { struct ifmcaddr6 *ma, **map; @@ -967,7 +965,7 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr) return -ENOENT; } -int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr) +int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr) { struct inet6_dev *idev = in6_dev_get(dev); int err; @@ -1012,8 +1010,8 @@ int ipv6_is_mld(struct sk_buff *skb, int nexthdr) /* * check if the interface/address pair is valid */ -int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group, - struct in6_addr *src_addr) +int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group, + const struct in6_addr *src_addr) { struct inet6_dev *idev; struct ifmcaddr6 *mc; @@ -1406,6 +1404,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) struct sk_buff *skb; struct mld2_report *pmr; struct in6_addr addr_buf; + const struct in6_addr *saddr; int err; u8 ra[8] = { IPPROTO_ICMPV6, 0, IPV6_TLV_ROUTERALERT, 2, 0, 0, @@ -1424,10 +1423,11 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) * use unspecified address as the source address * when a valid link-local address is not available. */ - memset(&addr_buf, 0, sizeof(addr_buf)); - } + saddr = &in6addr_any; + } else + saddr = &addr_buf; - ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0); + ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0); memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); @@ -1768,10 +1768,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) struct inet6_dev *idev; struct sk_buff *skb; struct icmp6hdr *hdr; - struct in6_addr *snd_addr; + const struct in6_addr *snd_addr, *saddr; struct in6_addr *addrp; struct in6_addr addr_buf; - struct in6_addr all_routers; int err, len, payload_len, full_len; u8 ra[8] = { IPPROTO_ICMPV6, 0, IPV6_TLV_ROUTERALERT, 2, 0, 0, @@ -1782,11 +1781,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) IP6_INC_STATS(__in6_dev_get(dev), IPSTATS_MIB_OUTREQUESTS); rcu_read_unlock(); - snd_addr = addr; - if (type == ICMPV6_MGM_REDUCTION) { - snd_addr = &all_routers; - ipv6_addr_all_routers(&all_routers); - } + if (type == ICMPV6_MGM_REDUCTION) + snd_addr = &in6addr_linklocal_allrouters; + else + snd_addr = addr; len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); payload_len = len + sizeof(ra); @@ -1809,10 +1807,11 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) * use unspecified address as the source address * when a valid link-local address is not available. */ - memset(&addr_buf, 0, sizeof(addr_buf)); - } + saddr = &in6addr_any; + } else + saddr = &addr_buf; - ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len); + ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len); memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra)); @@ -1823,7 +1822,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr)); ipv6_addr_copy(addrp, addr); - hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len, + hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len, IPPROTO_ICMPV6, csum_partial((__u8 *) hdr, len, 0)); @@ -2311,24 +2310,19 @@ void ipv6_mc_init_dev(struct inet6_dev *idev) void ipv6_mc_destroy_dev(struct inet6_dev *idev) { struct ifmcaddr6 *i; - struct in6_addr maddr; /* Deactivate timers */ ipv6_mc_down(idev); /* Delete all-nodes address. */ - ipv6_addr_all_nodes(&maddr); - /* We cannot call ipv6_dev_mc_dec() directly, our caller in * addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will * fail. */ - __ipv6_dev_mc_dec(idev, &maddr); + __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes); - if (idev->cnf.forwarding) { - ipv6_addr_all_routers(&maddr); - __ipv6_dev_mc_dec(idev, &maddr); - } + if (idev->cnf.forwarding) + __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters); write_lock_bh(&idev->lock); 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) if (!data) return NULL; if (padlen == 1) { - data[0] = MIP6_OPT_PAD_1; + data[0] = IPV6_TLV_PAD0; } else if (padlen > 1) { - data[0] = MIP6_OPT_PAD_N; + data[0] = IPV6_TLV_PADN; data[1] = padlen - 2; if (padlen > 2) 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) */ static void __ndisc_send(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *daddr, struct in6_addr *saddr, - struct icmp6hdr *icmp6h, struct in6_addr *target, + const struct in6_addr *daddr, + const struct in6_addr *saddr, + struct icmp6hdr *icmp6h, const struct in6_addr *target, int llinfo) { struct flowi fl; @@ -529,12 +530,13 @@ static void __ndisc_send(struct net_device *dev, } static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *daddr, struct in6_addr *solicited_addr, - int router, int solicited, int override, int inc_opt) + const struct in6_addr *daddr, + const struct in6_addr *solicited_addr, + int router, int solicited, int override, int inc_opt) { struct in6_addr tmpaddr; struct inet6_ifaddr *ifp; - struct in6_addr *src_addr; + const struct in6_addr *src_addr; struct icmp6hdr icmp6h = { .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT, }; @@ -564,8 +566,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, } void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *solicit, - struct in6_addr *daddr, struct in6_addr *saddr) + const struct in6_addr *solicit, + const struct in6_addr *daddr, const struct in6_addr *saddr) { struct in6_addr addr_buf; struct icmp6hdr icmp6h = { @@ -584,8 +586,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, !ipv6_addr_any(saddr) ? ND_OPT_SOURCE_LL_ADDR : 0); } -void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, - struct in6_addr *daddr) +void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr, + const struct in6_addr *daddr) { struct icmp6hdr icmp6h = { .icmp6_type = NDISC_ROUTER_SOLICITATION, @@ -816,10 +818,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) is_router = !!idev->cnf.forwarding; if (dad) { - struct in6_addr maddr; - - ipv6_addr_all_nodes(&maddr); - ndisc_send_na(dev, NULL, &maddr, &msg->target, + ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &msg->target, is_router, 0, (ifp != NULL), 1); goto out; } @@ -1447,7 +1446,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) } void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, - struct in6_addr *target) + const struct in6_addr *target) { struct net_device *dev = skb->dev; 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, read_lock(&raw_v6_hashinfo.lock); sk = sk_head(&raw_v6_hashinfo.ht[hash]); if (sk != NULL) { - saddr = &ipv6_hdr(skb)->saddr; - daddr = &ipv6_hdr(skb)->daddr; + /* Note: ipv6_hdr(skb) != skb->data */ + struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data; + saddr = &ip6h->saddr; + daddr = &ip6h->daddr; net = dev_net(skb->dev); while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, @@ -805,15 +807,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, fl.fl6_flowlabel = np->flow_label; } - if (ipv6_addr_any(daddr)) { - /* - * unspecified destination address - * treated as error... is this correct ? - */ - fl6_sock_release(flowlabel); - return(-EINVAL); - } - if (fl.oif == 0) fl.oif = sk->sk_bound_dev_if; @@ -846,7 +839,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, if (err) goto out; - ipv6_addr_copy(&fl.fl6_dst, daddr); + if (!ipv6_addr_any(daddr)) + ipv6_addr_copy(&fl.fl6_dst, daddr); + else + fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) ipv6_addr_copy(&fl.fl6_src, &np->saddr); 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: } -struct rt6_info *rt6_lookup(struct net *net, struct in6_addr *daddr, - struct in6_addr *saddr, int oif, int strict) +struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, + const struct in6_addr *saddr, int oif, int strict) { struct flowi fl = { .oif = oif, @@ -925,7 +925,7 @@ static DEFINE_SPINLOCK(icmp6_dst_lock); struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct neighbour *neigh, - struct in6_addr *addr) + const struct in6_addr *addr) { struct rt6_info *rt; 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) dev_put(dev); } else { ipip6_tunnel_unlink(netdev_priv(dev)); - ipip6_tunnel_del_prl(netdev_priv(dev), 0); + ipip6_tunnel_del_prl(netdev_priv(dev), NULL); dev_put(dev); } } 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, return NULL; for (i = 0; i < tp->md5sig_info->entries6; i++) { - if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) + if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr)) return &tp->md5sig_info->keys6[i].base; } return NULL; @@ -632,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) int i; for (i = 0; i < tp->md5sig_info->entries6; i++) { - if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { + if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) { /* Free the key */ kfree(tp->md5sig_info->keys6[i].base.key); 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: opt = ipv6_fixup_options(&opt_space, opt); fl.proto = sk->sk_protocol; - ipv6_addr_copy(&fl.fl6_dst, daddr); + if (!ipv6_addr_any(daddr)) + ipv6_addr_copy(&fl.fl6_dst, daddr); + else + fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) ipv6_addr_copy(&fl.fl6_src, &np->saddr); fl.fl_ip_sport = inet->sport;