#ifndef IN6_IS_ADDR_MULTICAST
#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
#endif
+/*
+ * Unicast link / site local.
+ */
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0xc0))
+#endif
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
*/
for (i= nwilds; i < ninterfaces; i++)
{
+ /*
+ * Skip the loopback. It can't act as an outgoing interface
+ */
+ if (inter_list[i].flags & INT_LOOPBACK)
+ continue;
/*
* For IPv4 we can check the network mask to see if
* we have a match on the outgoing interface
if (amask == imask)
return (&inter_list[i]);
}
+
+ /*
+ * See if the IPv6 address is Link-Local or Site Local
+ */
+ if (addr->ss_family == AF_INET6) {
+ if (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)addr)->sin6_addr) &&
+ IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6*)&inter_list[i].sin)->sin6_addr))
+ return (&inter_list[i]);
+
+ if (IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6*)addr)->sin6_addr) &&
+ IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6*)&inter_list[i].sin)->sin6_addr))
+ return (&inter_list[i]);
+ }
}
saddrlen = SOCKLEN(addr);