]> err.no Git - linux-2.6/blobdiff - net/ipv6/addrconf.c
[IPV6] address: Convert address deletion to new netlink api
[linux-2.6] / net / ipv6 / addrconf.c
index f1ede90048870b6992abaf10d92ed6e62fef2763..61627036eb2bf2fdca5eed28911451633db0ef1a 100644 (file)
@@ -736,7 +736,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 
                if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
                        if (onlink == 0) {
-                               ip6_del_rt(rt, NULL, NULL, NULL);
+                               ip6_del_rt(rt);
                                rt = NULL;
                        } else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
                                rt->rt6i_expires = expires;
@@ -1509,59 +1509,56 @@ static void
 addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
                      unsigned long expires, u32 flags)
 {
-       struct in6_rtmsg rtmsg;
+       struct fib6_config cfg = {
+               .fc_table = RT6_TABLE_PREFIX,
+               .fc_metric = IP6_RT_PRIO_ADDRCONF,
+               .fc_ifindex = dev->ifindex,
+               .fc_expires = expires,
+               .fc_dst_len = plen,
+               .fc_flags = RTF_UP | flags,
+       };
 
-       memset(&rtmsg, 0, sizeof(rtmsg));
-       ipv6_addr_copy(&rtmsg.rtmsg_dst, pfx);
-       rtmsg.rtmsg_dst_len = plen;
-       rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
-       rtmsg.rtmsg_ifindex = dev->ifindex;
-       rtmsg.rtmsg_info = expires;
-       rtmsg.rtmsg_flags = RTF_UP|flags;
-       rtmsg.rtmsg_type = RTMSG_NEWROUTE;
+       ipv6_addr_copy(&cfg.fc_dst, pfx);
 
        /* Prevent useless cloning on PtP SIT.
           This thing is done here expecting that the whole
           class of non-broadcast devices need not cloning.
         */
-       if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
-               rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
+       if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
+               cfg.fc_flags |= RTF_NONEXTHOP;
 
-       ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_PREFIX);
+       ip6_route_add(&cfg);
 }
 
 /* Create "default" multicast route to the interface */
 
 static void addrconf_add_mroute(struct net_device *dev)
 {
-       struct in6_rtmsg rtmsg;
-
-       memset(&rtmsg, 0, sizeof(rtmsg));
-       ipv6_addr_set(&rtmsg.rtmsg_dst,
-                     htonl(0xFF000000), 0, 0, 0);
-       rtmsg.rtmsg_dst_len = 8;
-       rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
-       rtmsg.rtmsg_ifindex = dev->ifindex;
-       rtmsg.rtmsg_flags = RTF_UP;
-       rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-       ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_LOCAL);
+       struct fib6_config cfg = {
+               .fc_table = RT6_TABLE_LOCAL,
+               .fc_metric = IP6_RT_PRIO_ADDRCONF,
+               .fc_ifindex = dev->ifindex,
+               .fc_dst_len = 8,
+               .fc_flags = RTF_UP,
+       };
+
+       ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0);
+
+       ip6_route_add(&cfg);
 }
 
 static void sit_route_add(struct net_device *dev)
 {
-       struct in6_rtmsg rtmsg;
-
-       memset(&rtmsg, 0, sizeof(rtmsg));
-
-       rtmsg.rtmsg_type        = RTMSG_NEWROUTE;
-       rtmsg.rtmsg_metric      = IP6_RT_PRIO_ADDRCONF;
+       struct fib6_config cfg = {
+               .fc_table = RT6_TABLE_MAIN,
+               .fc_metric = IP6_RT_PRIO_ADDRCONF,
+               .fc_ifindex = dev->ifindex,
+               .fc_dst_len = 96,
+               .fc_flags = RTF_UP | RTF_NONEXTHOP,
+       };
 
        /* prefix length - 96 bits "::d.d.d.d" */
-       rtmsg.rtmsg_dst_len     = 96;
-       rtmsg.rtmsg_flags       = RTF_UP|RTF_NONEXTHOP;
-       rtmsg.rtmsg_ifindex     = dev->ifindex;
-
-       ip6_route_add(&rtmsg, NULL, NULL, NULL, RT6_TABLE_MAIN);
+       ip6_route_add(&cfg);
 }
 
 static void addrconf_add_lroute(struct net_device *dev)
@@ -1662,7 +1659,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
                if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
                        if (rt->rt6i_flags&RTF_EXPIRES) {
                                if (valid_lft == 0) {
-                                       ip6_del_rt(rt, NULL, NULL, NULL);
+                                       ip6_del_rt(rt);
                                        rt = NULL;
                                } else {
                                        rt->rt6i_expires = jiffies + rt_expires;
@@ -2871,25 +2868,43 @@ restart:
        spin_unlock_bh(&addrconf_verify_lock);
 }
 
+static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
+{
+       struct in6_addr *pfx = NULL;
+
+       if (addr)
+               pfx = nla_data(addr);
+
+       if (local) {
+               if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
+                       pfx = NULL;
+               else
+                       pfx = nla_data(local);
+       }
+
+       return pfx;
+}
+
+static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = {
+       [IFA_ADDRESS]           = { .len = sizeof(struct in6_addr) },
+       [IFA_LOCAL]             = { .len = sizeof(struct in6_addr) },
+       [IFA_CACHEINFO]         = { .len = sizeof(struct ifa_cacheinfo) },
+};
+
 static int
 inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct rtattr **rta = arg;
-       struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+       struct ifaddrmsg *ifm;
+       struct nlattr *tb[IFA_MAX+1];
        struct in6_addr *pfx;
+       int err;
 
-       pfx = NULL;
-       if (rta[IFA_ADDRESS-1]) {
-               if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))
-                       return -EINVAL;
-               pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
-       }
-       if (rta[IFA_LOCAL-1]) {
-               if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
-                   (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
-                       return -EINVAL;
-               pfx = RTA_DATA(rta[IFA_LOCAL-1]);
-       }
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+       if (err < 0)
+               return err;
+
+       ifm = nlmsg_data(nlh);
+       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
        if (pfx == NULL)
                return -EINVAL;
 
@@ -2948,46 +2963,41 @@ inet6_addr_modify(int ifindex, struct in6_addr *pfx,
 static int
 inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct rtattr  **rta = arg;
-       struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+       struct ifaddrmsg *ifm;
+       struct nlattr *tb[IFA_MAX+1];
        struct in6_addr *pfx;
-       __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME;
+       u32 valid_lft, preferred_lft;
+       int err;
 
-       pfx = NULL;
-       if (rta[IFA_ADDRESS-1]) {
-               if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx))
-                       return -EINVAL;
-               pfx = RTA_DATA(rta[IFA_ADDRESS-1]);
-       }
-       if (rta[IFA_LOCAL-1]) {
-               if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) ||
-                   (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))))
-                       return -EINVAL;
-               pfx = RTA_DATA(rta[IFA_LOCAL-1]);
-       }
+       err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
+       if (err < 0)
+               return err;
+
+       ifm = nlmsg_data(nlh);
+       pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
        if (pfx == NULL)
                return -EINVAL;
 
-       if (rta[IFA_CACHEINFO-1]) {
+       if (tb[IFA_CACHEINFO]) {
                struct ifa_cacheinfo *ci;
-               if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci))
-                       return -EINVAL;
-               ci = RTA_DATA(rta[IFA_CACHEINFO-1]);
+
+               ci = nla_data(tb[IFA_CACHEINFO]);
                valid_lft = ci->ifa_valid;
-               prefered_lft = ci->ifa_prefered;
+               preferred_lft = ci->ifa_prefered;
+       } else {
+               preferred_lft = INFINITY_LIFE_TIME;
+               valid_lft = INFINITY_LIFE_TIME;
        }
 
        if (nlh->nlmsg_flags & NLM_F_REPLACE) {
-               int ret;
-               ret = inet6_addr_modify(ifm->ifa_index, pfx,
-                                       prefered_lft, valid_lft);
-               if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
-                       return ret;
+               err = inet6_addr_modify(ifm->ifa_index, pfx,
+                                       preferred_lft, valid_lft);
+               if (err == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE))
+                       return err;
        }
 
        return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
-                             prefered_lft, valid_lft);
-
+                             preferred_lft, valid_lft);
 }
 
 /* Maximum length of ifa_cacheinfo attributes */
@@ -3548,7 +3558,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
 
        switch (event) {
        case RTM_NEWADDR:
-               ip6_ins_rt(ifp->rt, NULL, NULL, NULL);
+               ip6_ins_rt(ifp->rt);
                if (ifp->idev->cnf.forwarding)
                        addrconf_join_anycast(ifp);
                break;
@@ -3557,7 +3567,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                        addrconf_leave_anycast(ifp);
                addrconf_leave_solict(ifp->idev, &ifp->addr);
                dst_hold(&ifp->rt->u.dst);
-               if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
+               if (ip6_del_rt(ifp->rt))
                        dst_free(&ifp->rt->u.dst);
                break;
        }