aboutsummaryrefslogtreecommitdiffstats
path: root/ggsn
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-09-24 20:00:34 +0800
committerHarald Welte <laforge@gnumonks.org>2017-09-24 20:51:47 +0800
commitf85fe9720be14acc1038ed400654d8ce336274a7 (patch)
treee12f5279f153547a1d5b433bfbd62c9ef7868831 /ggsn
parentfed598f41d85cef578925a4be6ce96a2c6afd3b3 (diff)
ICMPv6: Send router advertisement from own link-local address
I'm not quite sure how I ended up doing this, but for some strange reason the code before this commit is sending the ICMPv6 Router Advertisements from some weird non-standard source address. This is a violation of RFC4861 which clearly states that the source address of router advertisements "MUST be the link-local address assigned to the interface from which this message is sent." Change-Id: Ib444af70fc8f0b433d371281601fd5a37b29039e
Diffstat (limited to 'ggsn')
-rw-r--r--ggsn/ggsn.c17
-rw-r--r--ggsn/ggsn.h3
-rw-r--r--ggsn/icmpv6.c12
-rw-r--r--ggsn/icmpv6.h3
4 files changed, 25 insertions, 10 deletions
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 46850a6..d521e57 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -202,6 +202,16 @@ int apn_start(struct apn_ctx *apn)
apn->tun.cfg.ipup_script);
tun_runscript(apn->tun.tun, apn->tun.cfg.ipup_script);
}
+
+ if (apn->cfg.apn_type_mask & (APN_TYPE_IPv6|APN_TYPE_IPv4v6)) {
+ if (tun_ipv6_linklocal_get(apn->tun.tun, &apn->v6_lladdr) < 0) {
+ LOGPAPN(LOGL_ERROR, apn, "Cannot obtain IPv6 link-local address of "
+ "interface: %s\n", strerror(errno));
+ apn_stop(apn, false);
+ return -1;
+ }
+ }
+
/* set back-pointer from TUN device to APN */
apn->tun.tun->priv = apn;
break;
@@ -573,6 +583,11 @@ static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
{
struct iphdr *iph = (struct iphdr *)pack;
struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+ struct tun_t *tun = (struct tun_t *)pdp->ipif;
+ struct apn_ctx *apn = tun->priv;
+
+ OSMO_ASSERT(tun);
+ OSMO_ASSERT(apn);
LOGPPDP(LOGL_DEBUG, pdp, "Packet received: forwarding to tun\n");
@@ -580,7 +595,7 @@ static int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
case 6:
/* daddr: all-routers multicast addr */
if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr))
- return handle_router_mcast(pdp->gsn, pdp, pack, len);
+ return handle_router_mcast(pdp->gsn, pdp, &apn->v6_lladdr, pack, len);
break;
case 4:
break;
diff --git a/ggsn/ggsn.h b/ggsn/ggsn.h
index 2dd963c..42f8e1c 100644
--- a/ggsn/ggsn.h
+++ b/ggsn/ggsn.h
@@ -78,6 +78,9 @@ struct apn_ctx {
struct osmo_fd fd;
} tun;
+ /* ipv6 link-local address */
+ struct in6_addr v6_lladdr;
+
struct apn_ctx_ip v4;
struct apn_ctx_ip v6;
};
diff --git a/ggsn/icmpv6.c b/ggsn/icmpv6.c
index ac51bb1..11ced24 100644
--- a/ggsn/icmpv6.c
+++ b/ggsn/icmpv6.c
@@ -179,13 +179,9 @@ static bool icmpv6_validate_router_solicit(const uint8_t *pack, unsigned len)
return true;
}
-/* RFC3307 link-local scope multicast address */
-static const struct in6_addr my_local_addr = {
- .s6_addr = { 0x01,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0xff }
-};
-
/* handle incoming packets to the all-routers multicast address */
-int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const uint8_t *pack, unsigned len)
+int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *own_ll_addr,
+ const uint8_t *pack, unsigned len)
{
struct ippoolm_t *member = pdp->peer;
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
@@ -222,10 +218,10 @@ int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const uint8_t *pac
osmo_hexdump(pack, len));
return -1;
}
- /* FIXME: Send router advertisement from GGSN link-local
+ /* Send router advertisement from GGSN link-local
* address to MS link-local address, including prefix
* allocated to this PDP context */
- msg = icmpv6_construct_ra(&my_local_addr, &ip6h->ip6_src, &member->addr.v6);
+ msg = icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, &member->addr.v6);
/* Send the constructed RA to the MS */
gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
msgb_free(msg);
diff --git a/ggsn/icmpv6.h b/ggsn/icmpv6.h
index ebff04e..b6eec63 100644
--- a/ggsn/icmpv6.h
+++ b/ggsn/icmpv6.h
@@ -3,4 +3,5 @@
#include "../gtp/gtp.h"
#include "../gtp/pdp.h"
-int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const uint8_t *pack, unsigned len);
+int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp, const struct in6_addr *own_ll_addr,
+ const uint8_t *pack, unsigned len);