diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-12-02 11:00:03 +0000 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-12-02 11:00:03 +0000 |
commit | c969404724b19204bc1ef1634800f2b70572a297 (patch) | |
tree | 8dd14a96e9f4296a39a7ecb93b17f87c9beb82e7 /gweb | |
parent | 64533ee069c306bd9caf642fe218e9137a3b1572 (diff) | |
download | connman-c969404724b19204bc1ef1634800f2b70572a297.tar.gz connman-c969404724b19204bc1ef1634800f2b70572a297.tar.bz2 connman-c969404724b19204bc1ef1634800f2b70572a297.zip |
gresolv: Implement RFC3484 rule 9 (prefer longest matching prefix)
Diffstat (limited to 'gweb')
-rw-r--r-- | gweb/gresolv.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/gweb/gresolv.c b/gweb/gresolv.c index ed1ccab3..0c7613db 100644 --- a/gweb/gresolv.c +++ b/gweb/gresolv.c @@ -920,6 +920,41 @@ static int rfc3484_compare(const void *__one, const void *__two) return one->dst_scope - two->dst_scope; /* Rule 9: Use longest matching prefix */ + if (one->dst.sa.sa_family == AF_INET) { + /* Rule 9 is meaningless and counterproductive for Legacy IP + unless perhaps we can tell that it's actually on the local + subnet. But we don't (yet) have local interface config + information, so do nothing here for Legacy IP for now. */ + } else { + int i; + + for (i = 0; i < 4; i++) { + guint32 cmp_one, cmp_two; + + cmp_one = one->src.sin6.sin6_addr.s6_addr32[i] ^ + one->dst.sin6.sin6_addr.s6_addr32[i]; + cmp_two = two->src.sin6.sin6_addr.s6_addr32[i] ^ + two->dst.sin6.sin6_addr.s6_addr32[i]; + + if (!cmp_two && !cmp_one) + continue; + + if (cmp_one && !cmp_two) + return 1; + if (cmp_two && !cmp_one) + return -1; + + /* g_bit_storage() is effectively fls() */ + cmp_one = g_bit_storage(ntohl(cmp_one)); + cmp_two = g_bit_storage(ntohl(cmp_two)); + + if (cmp_one == cmp_two) + break; + + return cmp_one - cmp_two; + } + } + /* Rule 10: Otherwise, leave the order unchanged */ if (one < two) |