Commit 6fb9114e authored by David S. Miller's avatar David S. Miller

Merge branch 'net-2.6.26-misc-20080412b' of git://git.linux-ipv6.org/gitroot/yoshfuji/linux-2.6-dev

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