Subject: Re: [PATCH] IPv6 IPsec support

From: Kunihiro Ishiguro <[email-masked]>
Date: Wed, 19 Feb 2003 01:13:51 -0800

>I would ask that Alexey and myself stay on the CC: list.
>
>It would not hurt to keep netdev as well, perhaps we can
>breed some new experts in our ipsec code :-)

I believe many ipsec experts on this list ;-).

>@@ -428,20 +455,79 @@
> static inline int
> xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
> {
>-      return  !memcmp(fl->fl6_dst, sel->daddr.a6, sizeof(struct in6_addr)) &&
>-              !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
>-              !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
>-              (fl->proto == sel->proto || !sel->proto) &&
>-              (fl->oif == sel->ifindex || !sel->ifindex) &&
>-              !memcmp(fl->fl6_src, sel->saddr.a6, sizeof(struct in6_addr));
>+	return  !memcmp(fl->fl6_dst, &sel->daddr, (sel->prefixlen_d)/8) &&
>+		!memcmp(fl->fl6_src, &sel->saddr, (sel->prefixlen_s)/8) &&
>+		!((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
>+		!((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
>+		(fl->proto == sel->proto || !sel->proto) &&
>+		(fl->oif == sel->ifindex || !sel->ifindex);
> }

memcmp with prefixlen/8 is too generous.  Orignal non mask comparison
is much worser (maybe my code...).  We need bit comparison here.

Poor xfrm6_selector_match()... I only have below idea... addr_match()
is taken from ip6_fib.c...

static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
{
        __u32 *a1 = token1;
        __u32 *a2 = token2;
        int pdw;
        int pbi;

        pdw = prefixlen >> 5;     /* num of whole __u32 in prefix */
        pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */

        if (pdw)
                if (memcmp(a1, a2, pdw << 2))
                        return 0;

        if (pbi) {
                __u32 mask;

                mask = htonl((0xffffffff) << (32 - pbi));

                if ((a1[pdw] ^ a2[pdw]) & mask)
                        return 0;
        }

        return 1;
}

static inline int
xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
{
        return  addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
                addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
                !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) &&
                !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) &&
                (fl->proto == sel->proto || !sel->proto) &&
                (fl->oif == sel->ifindex || !sel->ifindex);
}