- ifl = 1; /* parse flags */
- if (!(iflags & RTF_UP))
- continue;
- if (iflags & RTF_GATEWAY)
- flags[ifl++] = 'G';
- if (iflags & RTF_HOST)
- flags[ifl++] = 'H';
- if (iflags & RTF_DEFAULT)
- flags[ifl++] = 'D';
- if (iflags & RTF_ADDRCONF)
- flags[ifl++] = 'A';
- if (iflags & RTF_CACHE)
- flags[ifl++] = 'C';
- flags[ifl] = 0;
-
- /* Fetch and resolve the target address. */
- snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
- addr6p[0], addr6p[1], addr6p[2], addr6p[3],
- addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
- inet_pton(AF_INET6, addr6, (struct sockaddr *) &saddr6.sin6_addr);
- saddr6.sin6_family = AF_INET6;
-
- INET6_rresolve(addr6, sizeof(addr6), (struct sockaddr_in6 *) &saddr6,
- numeric);
- snprintf(addr6, sizeof(addr6), "%s/%d", addr6, prefix_len);
-
- /* Fetch and resolve the nexthop address. */
- snprintf(naddr6, sizeof(naddr6), "%s:%s:%s:%s:%s:%s:%s:%s",
- naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3],
- naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7]);
- inet_pton(AF_INET6, naddr6, (struct sockaddr *) &snaddr6.sin6_addr);
- snaddr6.sin6_family = AF_INET6;
-
- INET6_rresolve(naddr6, sizeof(naddr6),
- (struct sockaddr_in6 *) &snaddr6, numeric);
-
- /* Print the info. */
- printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n",
- addr6, naddr6, flags, metric, refcnt, use, iface);
+ /* Do the addr6x shift-and-insert changes to ':'-delimit addresses.
+ * For now, always do this to validate the proc route format, even
+ * if the interface is down. */
+ {
+ int i = 0;
+ char *p = addr6x+14;
+
+ do {
+ if (!*p) {
+ if (i == 40) { /* nul terminator for 1st address? */
+ addr6x[39] = 0; /* Fixup... need 0 instead of ':'. */
+ ++p; /* Skip and continue. */
+ continue;
+ }
+ goto ERROR;
+ }
+ addr6x[i++] = *p++;
+ if (!((i+1) % 5)) {
+ addr6x[i++] = ':';
+ }
+ } while (i < 40+28+7);
+ }
+
+ set_flags(flags, (iflags & IPV6_MASK));
+
+ r = 0;
+ while (1) {
+ inet_pton(AF_INET6, addr6x + r,
+ (struct sockaddr *) &snaddr6.sin6_addr);
+ snaddr6.sin6_family = AF_INET6;
+ naddr6 = INET6_rresolve((struct sockaddr_in6 *) &snaddr6,
+ 0x0fff /* Apparently, upstream never resolves. */
+ );
+
+ if (!r) { /* 1st pass */
+ snprintf(addr6, sizeof(addr6), "%s/%d", naddr6, prefix_len);
+ r += 40;
+ free(naddr6);
+ } else { /* 2nd pass */
+ /* Print the info. */
+ printf("%-43s %-39s %-5s %-6d %-2d %7d %-8s\n",
+ addr6, naddr6, flags, metric, refcnt, use, iface);
+ free(naddr6);
+ break;
+ }
+ }