]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/addrconf.c
Pull acpi_os_free into release branch
[linux-2.6-omap-h63xx.git] / net / ipv6 / addrconf.c
index 01c62a0d3742aea6c283ea7196571edbec8888a4..c250d0af10d77c3fc76f90a842da7414d1b2ed1e 100644 (file)
@@ -40,7 +40,6 @@
  *                                             status etc.
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -143,7 +142,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
                                struct prefix_info *pinfo);
 static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
 
-static struct notifier_block *inet6addr_chain;
+static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
 
 struct ipv6_devconf ipv6_devconf = {
        .forwarding             = 0,
@@ -593,7 +592,7 @@ out2:
        read_unlock_bh(&addrconf_lock);
 
        if (likely(err == 0))
-               notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+               atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
        else {
                kfree(ifa);
                ifa = ERR_PTR(err);
@@ -688,7 +687,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
        ipv6_ifa_notify(RTM_DELADDR, ifp);
 
-       notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp);
+       atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
 
        addrconf_del_timer(ifp);
 
@@ -862,6 +861,8 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type)
   *    2002::/16               2
   *    ::/96                   3
   *    ::ffff:0:0/96           4
+  *    fc00::/7                5
+  *    2001::/32               6
   */
        if (type & IPV6_ADDR_LOOPBACK)
                return 0;
@@ -869,8 +870,12 @@ static int inline ipv6_saddr_label(const struct in6_addr *addr, int type)
                return 3;
        else if (type & IPV6_ADDR_MAPPED)
                return 4;
+       else if (addr->s6_addr32[0] == htonl(0x20010000))
+               return 6;
        else if (addr->s6_addr16[0] == htons(0x2002))
                return 2;
+       else if ((addr->s6_addr[0] & 0xfe) == 0xfc)
+               return 5;
        return 1;
 }
 
@@ -1069,6 +1074,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
                                if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
                                        continue;
                        }
+#else
+                       if (hiscore.rule < 7)
+                               hiscore.rule++;
 #endif
                        /* Rule 8: Use longest matching prefix */
                        if (hiscore.rule < 8) {
@@ -2860,6 +2868,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
 
+/* Maximum length of ifa_cacheinfo attributes */
+#define INET6_IFADDR_RTA_SPACE \
+               RTA_SPACE(16) /* IFA_ADDRESS */ + \
+               RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3092,7 +3105,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 {
        struct sk_buff *skb;
-       int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
 
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
@@ -3142,6 +3155,17 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
 #endif
 }
 
+/* Maximum length of ifinfomsg attributes */
+#define INET6_IFINFO_RTA_SPACE \
+               RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
+               RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \
+               RTA_SPACE(sizeof(u32)) /* MTU */ + \
+               RTA_SPACE(sizeof(int)) /* LINK */ + \
+               RTA_SPACE(0) /* PROTINFO */ + \
+               RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
+               RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
+               RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
                             u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3235,8 +3259,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
 void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
 {
        struct sk_buff *skb;
-       /* 128 bytes ?? */
-       int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE);
        
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
@@ -3252,6 +3275,11 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
        netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
 }
 
+/* Maximum length of prefix_cacheinfo attributes */
+#define INET6_PREFIX_RTA_SPACE \
+               RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
+               RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
                        struct prefix_info *pinfo, u32 pid, u32 seq, 
                        int event, unsigned int flags)
@@ -3296,7 +3324,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
                         struct prefix_info *pinfo)
 {
        struct sk_buff *skb;
-       int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128);
+       int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE);
 
        skb = alloc_skb(size, GFP_ATOMIC);
        if (!skb) {
@@ -3767,12 +3795,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
 int register_inet6addr_notifier(struct notifier_block *nb)
 {
-        return notifier_chain_register(&inet6addr_chain, nb);
+        return atomic_notifier_chain_register(&inet6addr_chain, nb);
 }
 
 int unregister_inet6addr_notifier(struct notifier_block *nb)
 {
-        return notifier_chain_unregister(&inet6addr_chain,nb);
+        return atomic_notifier_chain_unregister(&inet6addr_chain,nb);
 }
 
 /*