summaryrefslogtreecommitdiff
path: root/gweb
diff options
context:
space:
mode:
Diffstat (limited to 'gweb')
-rw-r--r--gweb/gresolv.c35
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)