(usagi-users 03810) [Patch][mipv6d] Autoconf home address

"Jukka Rissanen" <[email protected]> Mon, 19 Feb 2007 15:37:12 +0200
Newsgroups gmane.linux.ipv6.usagi.users
Message-ID <[email protected]>
Hi,

below is a patch for mipv6d that allows the MN to use its autoconf
address as a base for home address. This means that one can just
configure the home address prefix in mipv6d.conf instead of full home
address (this makes configuration and provisioning of several MN nodes
much easier).

Example:

MnHomeLink "eth0" {
        UseAutoconfHomeAddress enabled;
        HomeAgentAddress 2001:db8:c0a8:c8::1;
        HomeAddress 2001:db8:c0a8:c8::/64;
}

If MN MAC address is 00:04:23:97:26:1A, then its home address will be
2001:db8:c0a8:c8:204:23ff:fe97:261a
The patch requires that the prefix is set to 64.


Regards,
      Jukka




Index: mipv6-daemon/src/gram.y
===================================================================
--- mipv6-daemon.orig/src/gram.y	2007-02-14 10:31:45.000000000 +0200
+++ mipv6-daemon/src/gram.y	2007-02-19 13:48:58.000000000 +0200
@@ -110,6 +110,7 @@
 %token		DEBUGLOGFILE
 %token		DOROUTEOPTIMIZATIONCN
 %token		DOROUTEOPTIMIZATIONMN
+%token		USEAUTOCONFHOMEADDRESS
 %token		HOMEADDRESS
 %token		HOMEAGENTADDRESS
 %token		INITIALBINDACKTIMEOUTFIRSTREG
@@ -378,6 +379,38 @@
 				uerror("invalid interface");
 				return -1;
 			}
+
+			if (hai.autoconf_hoa && hai.plen!=64) {
+				uerror("For AutoconfHomeAddress the prefix len must be 64");
+				hai.autoconf_hoa=0;
+			}
+			else if (hai.autoconf_hoa) {
+				unsigned char mac[6];
+
+				if (mn_get_mac_addr(hai.name, mac)) {
+					uerror("Cannot use AutoconfHomeAddress");
+					hai.autoconf_hoa = 0;
+				} else {
+#if 0
+				  printf("The hardware address of %s is "
+					 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", hai.name,
+					 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+#endif
+				  /* Now create autoconf home address from
+				   * home address prefix + MAC address.
+				   */
+				  ipv6_addr_add_eui64(&hai.hoa.addr, mac);
+#if 0
+				  {
+				  	char buf[INET6_ADDRSTRLEN+1];
+					if (inet_ntop(AF_INET6, &hai.hoa.addr, buf, INET6_ADDRSTRLEN)) {
+						printf("Autoconf HoA = %s\n", buf);
+					}
+				  }
+#endif
+				}
+			}
+
 			nhai = malloc(sizeof(struct home_addr_info));
 			if (nhai == NULL) {
 				uerror("out of memory");
@@ -420,6 +453,10 @@
 			hai.hoa.addr = $2;
 			hai.plen = $4;
 		}
+		| USEAUTOCONFHOMEADDRESS BOOL ';'
+                {
+		        hai.autoconf_hoa = $2;
+		}
 		| USEALTCOA BOOL ';'
                 {
 		        hai.altcoa = $2;
Index: mipv6-daemon/src/mn.c
===================================================================
--- mipv6-daemon.orig/src/mn.c	2007-02-14 10:31:45.000000000 +0200
+++ mipv6-daemon/src/mn.c	2007-02-14 10:34:31.000000000 +0200
@@ -2421,3 +2421,34 @@
 	md_cleanup();
 }

+
+#include <linux/sockios.h>
+
+int mn_get_mac_addr(char *ifname, unsigned char buf[6])
+{
+	struct ifreq if_hwaddr;
+	unsigned char *hwaddr;
+	int fd;
+
+	if ((fd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
+		perror("socket");
+		return -1;
+	}
+
+	strncpy(if_hwaddr.ifr_name, ifname, IFNAMSIZ);
+	if (ioctl(fd, SIOCGIFHWADDR, &if_hwaddr) < 0) {
+		fprintf(stderr, "SIOCGIFHWADDR on %s failed: %s\n", ifname,
+			strerror(errno));
+		return -1;
+	}
+
+	hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;
+	if (if_hwaddr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
+		fprintf(stderr, "%s has no MAC address\n", ifname);
+		return -1;
+	}
+
+	memcpy(buf, hwaddr, 6);
+	return 0;
+}
+
Index: mipv6-daemon/src/mn.h
===================================================================
--- mipv6-daemon.orig/src/mn.h	2007-02-14 10:31:45.000000000 +0200
+++ mipv6-daemon/src/mn.h	2007-02-14 10:34:31.000000000 +0200
@@ -83,6 +83,7 @@
 	int if_block;
 	short hwalen;
 	uint8_t altcoa;
+	uint8_t autoconf_hoa;
 	char name[IF_NAMESIZE];
 };

Index: mipv6-daemon/src/scan.l
===================================================================
--- mipv6-daemon.orig/src/scan.l	2007-02-14 10:31:45.000000000 +0200
+++ mipv6-daemon/src/scan.l	2007-02-14 10:34:31.000000000 +0200
@@ -108,6 +108,7 @@
 IPsecPolicySet			{ return IPSECPOLICYSET; }
 IPsecPolicy			{ return IPSECPOLICY; }
 IPsecType			{ return IPSECTYPE; }
+UseAutoconfHomeAddress		{ return USEAUTOCONFHOMEADDRESS; }
 UseAltCoa			{ return USEALTCOA; }
 UseESP				{ return USEESP; }
 UseAH				{ return USEAH; }
Index: mipv6-daemon/src/util.h
===================================================================
--- mipv6-daemon.orig/src/util.h	2007-02-14 10:31:45.000000000 +0200
+++ mipv6-daemon/src/util.h	2007-02-14 10:34:31.000000000 +0200
@@ -157,6 +157,21 @@
 		      addr->s6_addr32[2], addr->s6_addr32[3]);
 }

+static inline void ipv6_addr_add_eui64(struct in6_addr *addr,
+				       unsigned char mac[6])
+{
+	/* set the last 64 bits according to EUI-64, RFC2373 */
+	/* toggle also universal/local bit */
+	addr->s6_addr[8]  = mac[0] ^ ((mac[0] & 2) == 1 ? 0 : 2);
+	addr->s6_addr[9]  = mac[1];
+	addr->s6_addr[10] = mac[2];
+	addr->s6_addr[11] = 0xff;
+	addr->s6_addr[12] = 0xfe;
+	addr->s6_addr[13] = mac[3];
+	addr->s6_addr[14] = mac[4];
+	addr->s6_addr[15] = mac[5];
+}
+
 static inline int in6_is_addr_routable_unicast(const struct in6_addr *a)
 {
 	return ((!IN6_IS_ADDR_UNSPECIFIED(a) &&