ggsn: encaps_tun: Avoid forwarding packet if EUA is unassigned, fix crash

Check (before forwarding received GTP packets into the tun) if the pdp ctx
associated with the packet requested was assigned an EUA of the given IP version.
This way we avoid for instance forwarding an IPv6 packet (or sending
back a response to a Router Solicitation packet) in case the APN was
configured without IPv6 support or if the MS/SGSN didn't ask for an IPv6
while requesting an EUA.

As a side effect, this commit fixes an OSMO_ASSERT hit introduced in handle_router_mcast
in 2d6a69e69a4b4cb2b8cc63c4810dae44e5a4d8f6 due to a deffective MS
sending an icmpv6 Router Solicitation over IPv6 after having been
requesting and assigned an IPv4 EUA (so no IPv6 packets expected).
Before that commit, there was no crash but the message was being wrongly
answered and used an uninitialized .v6 addr field from the peer struct.

Fixes: OS#2843

Change-Id: Ib6d18a64c2b71f3bcf6cb7e3a978d2d3f9c7a79b
diff --git a/ggsn/icmpv6.c b/ggsn/icmpv6.c
index 6564a54..b7b97eb 100644
--- a/ggsn/icmpv6.c
+++ b/ggsn/icmpv6.c
@@ -180,22 +180,15 @@
 }
 
 /* handle incoming packets to the all-routers multicast address */
-int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *own_ll_addr,
+int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp,
+			const struct in6_addr *pdp_prefix,
+			const struct in6_addr *own_ll_addr,
 			const uint8_t *pack, unsigned len)
 {
-	struct ippoolm_t *member;
 	const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
 	const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
 	struct msgb *msg;
 
-	OSMO_ASSERT(pdp);
-
-	member = pdp->peer[0];
-	OSMO_ASSERT(member);
-	if (member->addr.len == sizeof(struct in_addr)) /* ipv4v6 context */
-		member = pdp->peer[1];
-	OSMO_ASSERT(member);
-
 	if (len < sizeof(*ip6h)) {
 		LOGP(DICMP6, LOGL_NOTICE, "Packet too short: %u bytes\n", len);
 		return -1;
@@ -226,7 +219,7 @@
 		/* Send router advertisement from GGSN link-local
 		 * address to MS link-local address, including prefix
 		 * allocated to this PDP context */
-		msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, &member->addr.v6);
+		msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, pdp_prefix);
 		/* Send the constructed RA to the MS */
 		gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
 		msgb_free(msg);