ipv6: Factor out global cache of mac/ip addresses.

Since there may be multiple connections which use different network devices,
there can't be a universal cache of the mac and ips derived from it.

Change-Id: Ibfae6804643ee491bfe0f23e9f38816af7a2f067
diff --git a/src/net/ipv6/inet6.c b/src/net/ipv6/inet6.c
index ca2f546..0fbee3c 100644
--- a/src/net/ipv6/inet6.c
+++ b/src/net/ipv6/inet6.c
@@ -19,7 +19,7 @@
 // Convert MAC Address to IPv6 Link Local Address.
 // aa:bb:cc:dd:ee:ff => FF80::aabb:ccFF:FEdd:eeff
 // Bit 2 (U/L) of the mac is inverted.
-static void inet6_ll6addr_from_mac(Ipv6Address *_ip, const MacAddress *_mac)
+static void inet6_lladdr_from_mac(Ipv6Address *_ip, const MacAddress *_mac)
 {
 	uint8_t *ip = _ip->x;
 	const uint8_t *mac = _mac->octet;
@@ -70,12 +70,6 @@
 	mac[5] = ip[15];
 }
 
-// Ip6 stack configuration.
-static MacAddress inet6_ll_mac_addr;
-static Ipv6Address inet6_ll_ip_addr;
-static MacAddress inet6_snm_mac_addr;
-static Ipv6Address inet6_snm_ip_addr;
-
 // Cache for the last source addresses we've seen.
 static MacAddress inet6_rx_mac_addr;
 static Ipv6Address inet6_rx_ip_addr;
@@ -134,28 +128,31 @@
 	return;
 }
 
-void ipv6_init(const void *macaddr)
+void ipv6_init(NetDevice *dev)
 {
-	// Save our ethernet MAC and synthesize link layer addresses.
-	memcpy(&inet6_ll_mac_addr, macaddr, sizeof(inet6_ll_mac_addr));
-	inet6_ll6addr_from_mac(&inet6_ll_ip_addr, &inet6_ll_mac_addr);
-	inet6_snmaddr_from_mac(&inet6_snm_ip_addr, &inet6_ll_mac_addr);
-	inet6_multicast_from_ipv6(&inet6_snm_mac_addr, &inet6_snm_ip_addr);
+	const MacAddress *mac = dev->get_mac(dev);
 
-	eth_add_mcast_filter(&inet6_snm_mac_addr);
+	// Save our ethernet MAC and synthesize link layer addresses.
+	Ipv6Address ip;
+	inet6_lladdr_from_mac(&ip, mac);
+	Ipv6Address snm_ip;
+	inet6_snmaddr_from_mac(&snm_ip, mac);
+	MacAddress snm_mac;
+	inet6_multicast_from_ipv6(&snm_mac, &snm_ip);
+
+	eth_add_mcast_filter(dev, &snm_mac);
 
 	MacAddress all;
 	inet6_multicast_from_ipv6(&all, &Ipv6LlAllNodes);
-	eth_add_mcast_filter(&all);
+	eth_add_mcast_filter(dev, &all);
 
 	printf("macaddr: %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       inet6_ll_mac_addr.octet[0], inet6_ll_mac_addr.octet[1],
-	       inet6_ll_mac_addr.octet[2], inet6_ll_mac_addr.octet[3],
-	       inet6_ll_mac_addr.octet[4], inet6_ll_mac_addr.octet[5]);
+	       mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3],
+	       mac->octet[4], mac->octet[5]);
 	printf("ipv6addr: ");
-	ipv6_print_addr(&inet6_ll_ip_addr);
+	ipv6_print_addr(&ip);
 	printf("\nsnmaddr: ");
-	ipv6_print_addr(&inet6_snm_ip_addr);
+	ipv6_print_addr(&snm_ip);
 	printf("\n");
 }
 
@@ -238,7 +235,7 @@
 	return sum == 0xffff ? sum : ~sum;
 }
 
-static int ipv6_setup(Ipv6Pkt *p, const Ipv6Address *daddr,
+static int ipv6_setup(Ipv6Pkt *p, NetDevice *dev, const Ipv6Address *daddr,
 		     size_t length, uint8_t type)
 {
 	MacAddress dmac;
@@ -247,8 +244,9 @@
 		return -1;
 
 	// Ethernet header.
+	const MacAddress *ll_mac = dev->get_mac(dev);
 	memcpy(p->eth + 2, &dmac, sizeof(dmac));
-	memcpy(p->eth + 8, &inet6_ll_mac_addr, sizeof(inet6_ll_mac_addr));
+	memcpy(p->eth + 8, ll_mac, sizeof(*ll_mac));
 	p->eth[14] = (EthType_Ipv6 >> 8) & 0xFF;
 	p->eth[15] = EthType_Ipv6 & 0xFF;
 
@@ -257,8 +255,10 @@
 	p->ipv6.length = htonw(length);
 	p->ipv6.next_header = type;
 	p->ipv6.hop_limit = 255;
-	memcpy(p->ipv6.src, &inet6_ll_ip_addr, sizeof(Ipv6Address));
-	memcpy(p->ipv6.dst, daddr, sizeof(Ipv6Address));
+	Ipv6Address saddr;
+	inet6_lladdr_from_mac(&saddr, ll_mac);
+	memcpy(p->ipv6.src, &saddr, sizeof(saddr));
+	memcpy(p->ipv6.dst, daddr, sizeof(*daddr));
 
 	return 0;
 }
@@ -290,7 +290,7 @@
 	UdpPkt *p = xmalloc(CONFIG_NET_LINK_MTU + 2);
 
 	size_t length = dlen + Udp_HdrLen;
-	if (ipv6_setup((void *)p, &con->dest_ip, length, HdrUdp)) {
+	if (ipv6_setup((void *)p, con->dev, &con->dest_ip, length, HdrUdp)) {
 		printf("ipv6_setup failed.\n");
 		free(p);
 		return -1;
@@ -343,7 +343,7 @@
 
 	Ipv6Pkt *p = xmalloc(CONFIG_NET_LINK_MTU + 2);
 
-	if (ipv6_setup((void *)p, dest_ip, length, HdrIcmpv6)) {
+	if (ipv6_setup((void *)p, dev, dest_ip, length, HdrIcmpv6)) {
 		free(p);
 		return -1;
 	}
@@ -428,18 +428,22 @@
 			printf("error: Bogus NDP Message\n");
 		if (ndp->code != 0)
 			printf("error: Bogus NDP Code\n");
-		if (memcmp(ndp->target, &inet6_ll_ip_addr, Ipv6_AddrLen))
+
+		const MacAddress *mac = dev->get_mac(dev);
+
+		Ipv6Address ll_ip_addr;
+		inet6_lladdr_from_mac(&ll_ip_addr, mac);
+		if (memcmp(ndp->target, &ll_ip_addr, sizeof(ll_ip_addr)))
 			printf("error: NDP Not For Me\n");
 
 		msg.hdr.type = Icmpv6_NdpNAdvertise;
 		msg.hdr.code = 0;
 		msg.hdr.checksum = 0;
 		msg.hdr.flags = 0x60; // (S)olicited and (O)verride flags.
-		memcpy(msg.hdr.target, &inet6_ll_ip_addr, Ipv6_AddrLen);
+		memcpy(msg.hdr.target, &ll_ip_addr, sizeof(ll_ip_addr));
 		msg.opt[0] = NdpNTgtLlAddr;
 		msg.opt[1] = 1;
-		memcpy(msg.opt + 2, &inet6_ll_mac_addr,
-		       sizeof(inet6_ll_mac_addr));
+		memcpy(msg.opt + 2, mac, sizeof(MacAddress));
 
 		icmpv6_send(dev, (void *)ip->src, &msg, sizeof(msg));
 		return;
@@ -479,8 +483,14 @@
 	len = n;
 
 	// Require that we are the destination.
-	if (memcmp(&inet6_ll_ip_addr, ip->dst, Ipv6_AddrLen) &&
-		memcmp(&inet6_snm_ip_addr, ip->dst, Ipv6_AddrLen)) {
+	const MacAddress *mac = dev->get_mac(dev);
+	Ipv6Address ll_ip_addr;
+	inet6_lladdr_from_mac(&ll_ip_addr, mac);
+	Ipv6Address snm_ip_addr;
+	inet6_snmaddr_from_mac(&snm_ip_addr, mac);
+
+	if (memcmp(&ll_ip_addr, ip->dst, sizeof(ll_ip_addr)) &&
+	    memcmp(&snm_ip_addr, ip->dst, sizeof(snm_ip_addr))) {
 		return 1;
 	}
 
diff --git a/src/net/ipv6/inet6.h b/src/net/ipv6/inet6.h
index d1f0579..2ee20bf 100644
--- a/src/net/ipv6/inet6.h
+++ b/src/net/ipv6/inet6.h
@@ -10,11 +10,11 @@
 #include "net/ipv6/ipv6.h"
 
 // provided by inet6.c
-void ipv6_init(const void *macaddr);
+void ipv6_init(NetDevice *dev);
 int eth_recv(NetDevice *dev, void *data, size_t len);
 
 // provided by interface driver
-int eth_add_mcast_filter(const MacAddress *addr);
+int eth_add_mcast_filter(NetDevice *dev, const MacAddress *addr);
 
 // call to transmit a UDP packet
 int udpv6_send(Ipv6UdpCon *con, const void *data, size_t len);
diff --git a/src/net/ipv6/ipv6.c b/src/net/ipv6/ipv6.c
index 8fa25ca..d3d7d4a 100644
--- a/src/net/ipv6/ipv6.c
+++ b/src/net/ipv6/ipv6.c
@@ -46,8 +46,7 @@
 static int ipv6_udp_con_init(Ipv6UdpCon *con)
 {
 	NetDevice *dev = con->dev;
-	const MacAddress *mac = dev->get_mac(dev);
-	ipv6_init(mac);
+	ipv6_init(dev);
 	list_insert_after(&con->list_node, &ipv6_udp_connections);
 	con->initialized = 1;
 	return 0;
@@ -143,7 +142,7 @@
 	return con;
 }
 
-int eth_add_mcast_filter(const MacAddress *addr)
+int eth_add_mcast_filter(NetDevice *dev, const MacAddress *addr)
 {
 	return 0;
 }