Subject: Re: Host IDs
To: Al B. Snell <alaric@alaric-snell.com>
From: None <itojun@iijlab.net>
List: tech-kern
Date: 01/03/2001 12:50:01
>>Therefore, since nobody has yet said it would be a bad idea, I'll start
>>munging ifconfig and rtsold to use this 64 bit value...
> hint:
> link-local address gets assigned by the kernel, not by ifconfig,
> when interface brought up (!IFF_UP -> IFF_UP). you just need to
> tweak sys/netinet6/in6_ifattach.c.
this should do what you wanted.
itojun
Index: in6_ifattach.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_ifattach.c,v
retrieving revision 1.32
diff -u -r1.32 in6_ifattach.c
--- in6_ifattach.c 2000/11/05 17:17:16 1.32
+++ in6_ifattach.c 2001/01/03 03:49:24
@@ -60,6 +60,7 @@
size_t icmp6_ifstatmax = 0;
unsigned long in6_maxmtu = 0;
+static int get_hostid_ifid __P((struct ifnet *, struct in6_addr *));
static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
@@ -79,6 +80,43 @@
#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
/*
+ * Generate a last-resort interface identifier from hostid.
+ */
+static int
+get_hostid_ifid(ifp, in6)
+ struct ifnet *ifp;
+ struct in6_addr *in6; /*upper 64bits are preserved */
+{
+ int off, len;
+ static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ static u_int8_t allone[8] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ if (!hostid)
+ return -1;
+
+ /* get up to 8 bytes from the hostid field - should we get */
+ len = (sizeof(hostid) > 8) ? 8 : sizeof(hostid);
+ off = sizeof(*in6) - len;
+ bcopy(&hostid, &in6->s6_addr[off], len);
+
+ /* make sure we do not return anything bogus */
+ if (bcmp(&in6->s6_addr[8], allzero, sizeof(allzero)))
+ return -1;
+ if (bcmp(&in6->s6_addr[8], allone, sizeof(allone)))
+ return -1;
+
+ /* make sure to set "u" bit to local, and "g" bit to individual. */
+ in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
+ in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
+
+ /* convert EUI64 into IPv6 interface identifier */
+ EUI64_TO_IFID(in6);
+
+ return 0;
+}
+
+/*
* Generate a last-resort interface identifier, when the machine has no
* IEEE802/EUI64 address sources.
* The goal here is to get an interface identifier that is
@@ -260,6 +298,10 @@
{
struct ifnet *ifp;
+#if 1
+ goto hostid;
+#endif
+
/* first, try to get it from the interface itself */
if (get_hw_ifid(ifp0, in6) == 0) {
#ifdef ND6_DEBUG
@@ -298,6 +340,16 @@
#endif
goto success;
}
+ }
+
+hostid:
+ /* get from hostid - only for certain architectures */
+ if (get_hostid_ifid(ifp, in6) == 0) {
+#ifdef ND6_DEBUG
+ printf("%s: interface identifier generated by hostid\n",
+ if_name(ifp0));
+#endif
+ goto success;
}
/* last resort: get from random number source */