This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Harald Welte gerrit-no-reply at lists.osmocom.orgReview at https://gerrit.osmocom.org/4044 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 --- M ggsn/ggsn.c M ggsn/ggsn.h M ggsn/icmpv6.c M ggsn/icmpv6.h M lib/tun.c M lib/tun.h 6 files changed, 59 insertions(+), 10 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/44/4044/1 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 @@ 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 @@ { 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 @@ 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 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 @@ 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 @@ 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); diff --git a/lib/tun.c b/lib/tun.c index 76ac379..32a8d2d 100644 --- a/lib/tun.c +++ b/lib/tun.c @@ -748,3 +748,35 @@ } return 0; } + +#include <ifaddrs.h> + +/* obtain the link-local address of the tun device */ +int tun_ipv6_linklocal_get(const struct tun_t *tun, struct in6_addr *ia) +{ + struct ifaddrs *ifaddr, *ifa; + static const uint8_t ll_prefix[] = { 0xfe,0x80, 0,0, 0,0, 0,0 }; + + if (getifaddrs(&ifaddr) == -1) { + return -1; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; + if (ifa->ifa_addr == NULL) + continue; + + if (ifa->ifa_addr->sa_family != AF_INET6) + continue; + + if (strcmp(ifa->ifa_name, tun->devname)) + continue; + + if (memcmp(sin6->sin6_addr.s6_addr, ll_prefix, sizeof(ll_prefix))) + continue; + + *ia = sin6->sin6_addr; + return 0; + } + return -1; +} diff --git a/lib/tun.h b/lib/tun.h index 50ac806..95fff26 100644 --- a/lib/tun.h +++ b/lib/tun.h @@ -85,4 +85,6 @@ extern int tun_runscript(struct tun_t *tun, char *script); +int tun_ipv6_linklocal_get(const struct tun_t *tun, struct in6_addr *ia); + #endif /* !_TUN_H */ -- To view, visit https://gerrit.osmocom.org/4044 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ib444af70fc8f0b433d371281601fd5a37b29039e Gerrit-PatchSet: 1 Gerrit-Project: osmo-ggsn Gerrit-Branch: master Gerrit-Owner: Harald Welte <laforge at gnumonks.org>