+ canon[l] = 0;
+ return name_from_dns(buf, canon, name, family, &conf);
+}
+
+static const struct policy {
+ unsigned char addr[16];
+ unsigned char len, mask;
+ unsigned char prec, label;
+} defpolicy[] = {
+ { "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 15, 0xff, 50, 0 },
+ { "\0\0\0\0\0\0\0\0\0\0\xff\xff", 11, 0xff, 35, 4 },
+ { "\x20\2", 1, 0xff, 30, 2 },
+ { "\x20\1", 3, 0xff, 5, 5 },
+ { "\xfc", 0, 0xfe, 3, 13 },
+#if 0
+ /* These are deprecated and/or returned to the address
+ * pool, so despite the RFC, treating them as special
+ * is probably wrong. */
+ { "", 11, 0xff, 1, 3 },
+ { "\xfe\xc0", 1, 0xc0, 1, 11 },
+ { "\x3f\xfe", 1, 0xff, 1, 12 },
+#endif
+ /* Last rule must match all addresses to stop loop. */
+ { "", 0, 0, 40, 1 },
+};
+
+static const struct policy *policyof(const struct in6_addr *a)
+{
+ int i;
+ for (i=0; ; i++) {
+ if (memcmp(a->s6_addr, defpolicy[i].addr, defpolicy[i].len))
+ continue;
+ if ((a->s6_addr[defpolicy[i].len] & defpolicy[i].mask)
+ != defpolicy[i].addr[defpolicy[i].len])
+ continue;
+ return defpolicy+i;
+ }
+}
+
+static int labelof(const struct in6_addr *a)
+{
+ return policyof(a)->label;
+}
+
+static int scopeof(const struct in6_addr *a)
+{
+ if (IN6_IS_ADDR_MULTICAST(a)) return a->s6_addr[1] & 15;
+ if (IN6_IS_ADDR_LINKLOCAL(a)) return 2;
+ if (IN6_IS_ADDR_LOOPBACK(a)) return 2;
+ if (IN6_IS_ADDR_SITELOCAL(a)) return 5;
+ return 14;
+}
+
+static int prefixmatch(const struct in6_addr *s, const struct in6_addr *d)
+{
+ /* FIXME: The common prefix length should be limited to no greater
+ * than the nominal length of the prefix portion of the source
+ * address. However the definition of the source prefix length is
+ * not clear and thus this limiting is not yet implemented. */
+ unsigned i;
+ for (i=0; i<128 && !((s->s6_addr[i/8]^d->s6_addr[i/8])&(128>>(i%8))); i++);
+ return i;
+}
+
+#define DAS_USABLE 0x40000000
+#define DAS_MATCHINGSCOPE 0x20000000
+#define DAS_MATCHINGLABEL 0x10000000
+#define DAS_PREC_SHIFT 20
+#define DAS_SCOPE_SHIFT 16
+#define DAS_PREFIX_SHIFT 8
+#define DAS_ORDER_SHIFT 0
+
+static int addrcmp(const void *_a, const void *_b)
+{
+ const struct address *a = _a, *b = _b;
+ return b->sortkey - a->sortkey;