lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAAedzxpD7EEV-3BXdGA72wqwxM1b0tge0iqBKehfZG4KvRjYrQ@mail.gmail.com>
Date:	Fri, 10 Jul 2015 16:19:24 +0900
From:	Erik Kline <ek@...gle.com>
To:	YOSHIFUJI Hideaki/吉藤英明 
	<hideaki.yoshifuji@...aclelinux.com>
Cc:	David Miller <davem@...emloft.net>,
	netdev <netdev@...r.kernel.org>,
	Hannes Frederic Sowa <hannes@...essinduktion.org>,
	Lorenzo Colitti <lorenzo@...gle.com>
Subject: Re: [PATCH net-next] ipv6: Do not iterate over all interfaces when
 finding source address on specific interface.

On 10 July 2015 at 15:50, YOSHIFUJI Hideaki/吉藤英明
<hideaki.yoshifuji@...aclelinux.com> wrote:
> If outgoing interface is specified and the candidate addresses
> are restricted to the outgoing interface, it is enough to iterate
> over that given interface only.
>
> Signed-off-by: YOSHIFUJI Hideaki <hideaki.yoshifuji@...aclelinux.com>
> ---
>  net/ipv6/addrconf.c | 201 +++++++++++++++++++++++++++++-----------------------
>  1 file changed, 111 insertions(+), 90 deletions(-)
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 21c2c81..b4c82d8 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1358,15 +1358,94 @@ out:
>         return ret;
>  }
>
> +static void __ipv6_dev_get_saddr(struct net *net,
> +                                struct ipv6_saddr_dst *dst,
> +                                unsigned int prefs,
> +                                const struct in6_addr *saddr,
> +                                struct inet6_dev *idev,
> +                                struct ipv6_saddr_score *scores)
> +{
> +       struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1];
> +
> +       read_lock_bh(&idev->lock);
> +       list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
> +               int i;
> +
> +               /*
> +                * - Tentative Address (RFC2462 section 5.4)
> +                *  - A tentative address is not considered
> +                *    "assigned to an interface" in the traditional
> +                *    sense, unless it is also flagged as optimistic.
> +                * - Candidate Source Address (section 4)
> +                *  - In any case, anycast addresses, multicast
> +                *    addresses, and the unspecified address MUST
> +                *    NOT be included in a candidate set.
> +                */
> +               if ((score->ifa->flags & IFA_F_TENTATIVE) &&
> +                   (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
> +                       continue;
> +
> +               score->addr_type = __ipv6_addr_type(&score->ifa->addr);
> +
> +               if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
> +                            score->addr_type & IPV6_ADDR_MULTICAST)) {
> +                       net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
> +                                           idev->dev->name);
> +                       continue;
> +               }
> +
> +               score->rule = -1;
> +               bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
> +
> +               for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
> +                       int minihiscore, miniscore;
> +
> +                       minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i);
> +                       miniscore = ipv6_get_saddr_eval(net, score, dst, i);
> +
> +                       if (minihiscore > miniscore) {
> +                               if (i == IPV6_SADDR_RULE_SCOPE &&
> +                                   score->scopedist > 0) {
> +                                       /*
> +                                        * special case:
> +                                        * each remaining entry
> +                                        * has too small (not enough)
> +                                        * scope, because ifa entries
> +                                        * are sorted by their scope
> +                                        * values.
> +                                        */
> +                                       goto out;
> +                               }
> +                               break;
> +                       } else if (minihiscore < miniscore) {
> +                               if (hiscore->ifa)
> +                                       in6_ifa_put(hiscore->ifa);
> +
> +                               in6_ifa_hold(score->ifa);
> +
> +                               swap(hiscore, score);
> +
> +                               /* restore our iterator */
> +                               score->ifa = hiscore->ifa;
> +
> +                               break;
> +                       }
> +               }
> +       }
> +out:
> +       read_unlock_bh(&idev->lock);
> +}
> +
>  int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
>                        const struct in6_addr *daddr, unsigned int prefs,
>                        struct in6_addr *saddr)
>  {
> -       struct ipv6_saddr_score scores[2],
> -                               *score = &scores[0], *hiscore = &scores[1];
> +       struct ipv6_saddr_score scores[2], *hiscore = &scores[1];
>         struct ipv6_saddr_dst dst;
> +       struct inet6_dev *idev;
>         struct net_device *dev;
>         int dst_type;
> +       bool use_oif_addr = false;
>
>         dst_type = __ipv6_addr_type(daddr);
>         dst.addr = daddr;
> @@ -1380,97 +1459,39 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
>
>         rcu_read_lock();
>
> -       for_each_netdev_rcu(net, dev) {
> -               struct inet6_dev *idev;
> -
> -               /* Candidate Source Address (section 4)
> -                *  - multicast and link-local destination address,
> -                *    the set of candidate source address MUST only
> -                *    include addresses assigned to interfaces
> -                *    belonging to the same link as the outgoing
> -                *    interface.
> -                * (- For site-local destination addresses, the
> -                *    set of candidate source addresses MUST only
> -                *    include addresses assigned to interfaces
> -                *    belonging to the same site as the outgoing
> -                *    interface.)
> -                */
> -               if (((dst_type & IPV6_ADDR_MULTICAST) ||
> -                    dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) &&
> -                   dst.ifindex && dev->ifindex != dst.ifindex)
> -                       continue;
> -
> -               idev = __in6_dev_get(dev);
> -               if (!idev)
> -                       continue;
> -
> -               read_lock_bh(&idev->lock);
> -               list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
> -                       int i;
> -
> -                       /*
> -                        * - Tentative Address (RFC2462 section 5.4)
> -                        *  - A tentative address is not considered
> -                        *    "assigned to an interface" in the traditional
> -                        *    sense, unless it is also flagged as optimistic.
> -                        * - Candidate Source Address (section 4)
> -                        *  - In any case, anycast addresses, multicast
> -                        *    addresses, and the unspecified address MUST
> -                        *    NOT be included in a candidate set.
> -                        */
> -                       if ((score->ifa->flags & IFA_F_TENTATIVE) &&
> -                           (!(score->ifa->flags & IFA_F_OPTIMISTIC)))
> -                               continue;
> -
> -                       score->addr_type = __ipv6_addr_type(&score->ifa->addr);
> +       /* Candidate Source Address (section 4)
> +        *  - multicast and link-local destination address,
> +        *    the set of candidate source address MUST only
> +        *    include addresses assigned to interfaces
> +        *    belonging to the same link as the outgoing
> +        *    interface.
> +        * (- For site-local destination addresses, the
> +        *    set of candidate source addresses MUST only
> +        *    include addresses assigned to interfaces
> +        *    belonging to the same site as the outgoing
> +        *    interface.)
> +        *  - "It is RECOMMENDED that the candidate source addresses
> +        *    be the set of unicast addresses assigned to the
> +        *    interface that will be used to send to the destination
> +        *    (the 'outgoing' interface)." (RFC 6724)
> +        */
> +       if (dst_dev) {
> +               if ((dst_type & IPV6_ADDR_MULTICAST) ||
> +                   dst.scope <= IPV6_ADDR_SCOPE_LINKLOCAL) {
> +                       idev = __in6_dev_get(dst_dev);
> +                       use_oif_addr = true;
> +               }
> +       }
>
> -                       if (unlikely(score->addr_type == IPV6_ADDR_ANY ||
> -                                    score->addr_type & IPV6_ADDR_MULTICAST)) {
> -                               net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s",
> -                                                   dev->name);
> +       if (use_oif_addr) {
> +               __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
> +       } else {
> +               for_each_netdev_rcu(net, dev) {
> +                       idev = __in6_dev_get(dev);
> +                       if (!idev)
>                                 continue;
> -                       }
> -
> -                       score->rule = -1;
> -                       bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX);
> -
> -                       for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) {
> -                               int minihiscore, miniscore;
> -
> -                               minihiscore = ipv6_get_saddr_eval(net, hiscore, &dst, i);
> -                               miniscore = ipv6_get_saddr_eval(net, score, &dst, i);
> -
> -                               if (minihiscore > miniscore) {
> -                                       if (i == IPV6_SADDR_RULE_SCOPE &&
> -                                           score->scopedist > 0) {
> -                                               /*
> -                                                * special case:
> -                                                * each remaining entry
> -                                                * has too small (not enough)
> -                                                * scope, because ifa entries
> -                                                * are sorted by their scope
> -                                                * values.
> -                                                */
> -                                               goto try_nextdev;
> -                                       }
> -                                       break;
> -                               } else if (minihiscore < miniscore) {
> -                                       if (hiscore->ifa)
> -                                               in6_ifa_put(hiscore->ifa);
> -
> -                                       in6_ifa_hold(score->ifa);
> -
> -                                       swap(hiscore, score);
> -
> -                                       /* restore our iterator */
> -                                       score->ifa = hiscore->ifa;
> -
> -                                       break;
> -                               }
> -                       }
> +                       __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores);
>                 }
> -try_nextdev:
> -               read_unlock_bh(&idev->lock);
>         }
>         rcu_read_unlock();
>
> --
> 1.9.1
>

LGTM, and thanks again.

Acked-by: Erik Kline <ek@...gle.com>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ