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 */