pespin has uploaded this change for review.

View Change

Depend on libosmo-netif for icmpv6 APIs

Most of icmpv6.* and checksum.* was moved to libosmo-netif from this
same repository so it can be reused. Link to libosmo-netif and adapt
code to new public symbol naming.

Depends: libosmo-netif.git Change-Id I78ec7270c717af0a1b8ffd9398cd69ea7a0dbee2
Change-Id: I8d8fae362f302d48afaed28a9c664f76ca4a2739
---
M TODO-RELEASE
M configure.ac
M contrib/jenkins.sh
M debian/control
M ggsn/Makefile.am
M ggsn/ggsn.c
M lib/Makefile.am
D lib/checksum.c
D lib/checksum.h
M lib/icmpv6.c
M lib/icmpv6.h
M sgsnemu/Makefile.am
M sgsnemu/sgsnemu.c
13 files changed, 50 insertions(+), 533 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/65/42465/1
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 0ed7189..aab5c0a 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -7,3 +7,4 @@
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
+libosmo-netif >1.7.0 osmo_icmpv6_*()
diff --git a/configure.ac b/configure.ac
index ade3ae9..2fd4d36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,6 +158,7 @@
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.12.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.12.0)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 1.12.0)
+PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 1.7.0)

AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index 4404cfa..1473418 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -28,6 +28,7 @@
osmo-build-dep.sh libgtpnl
fi
osmo-build-dep.sh libosmocore "" --disable-doxygen
+osmo-build-dep.sh libosmo-netif "" --disable-doxygen

verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")

diff --git a/debian/control b/debian/control
index 8c9237d..0bd4694 100644
--- a/debian/control
+++ b/debian/control
@@ -8,6 +8,7 @@
libdpkg-perl, git,
dh-autoreconf,
libosmocore-dev (>= 1.12.0),
+ libosmo-netif-dev (>= 1.7.0),
osmo-gsm-manuals-dev (>= 1.7.0),
libgtpnl-dev (>= 1.3.0)
Standards-Version: 3.9.6
diff --git a/ggsn/Makefile.am b/ggsn/Makefile.am
index ad6b2b2..c82f458 100644
--- a/ggsn/Makefile.am
+++ b/ggsn/Makefile.am
@@ -11,9 +11,17 @@
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOCTRL_CFLAGS) \
$(LIBOSMOVTY_CFLAGS) \
+ $(LIBOSMONETIF_CFLAGS) \
$(NULL)

-osmo_ggsn_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS) $(LIBOSMOCTRL_LIBS) $(LIBOSMOVTY_LIBS)
+osmo_ggsn_LDADD = \
+ @EXEC_LDADD@ \
+ -lgtp -L../gtp ../lib/libmisc.a \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOCTRL_LIBS) \
+ $(LIBOSMOVTY_LIBS) \
+ $(LIBOSMONETIF_LIBS) \
+ $(NULL)

if ENABLE_GTP_KERNEL
AM_CFLAGS += -DGTP_KERNEL $(LIBGTPNL_CFLAGS)
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 329b15f..3177713 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -46,6 +46,8 @@
#include <osmocom/ctrl/control_if.h>
#include <osmocom/gsm/apn.h>

+#include <osmocom/netif/icmpv6.h>
+
#include <osmocom/gtp/pdp.h>
#include <osmocom/gtp/gtp.h>

@@ -789,11 +791,13 @@

if (IN6_IS_ADDR_MULTICAST(&ip6h->ip6_dst)) {
/* daddr: all-routers multicast addr */
- if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &all_router_mcast_addr))
+ if (IN6_ARE_ADDR_EQUAL(&ip6h->ip6_dst, &osmo_icmpv6_all_router_mcast_addr))
return handle_router_mcast(pdp->gsn, pdp, &peer->addr.v6,
&apn->v6_lladdr, apn->cfg.mtu, pack, len);
/* daddr: solicited-node multicast addr */
- if (memcmp(&ip6h->ip6_dst.s6_addr, solicited_node_mcast_addr_prefix, sizeof(solicited_node_mcast_addr_prefix)) == 0)
+ if (memcmp(&ip6h->ip6_dst.s6_addr,
+ osmo_icmpv6_solicited_node_mcast_addr_prefix,
+ sizeof(osmo_icmpv6_solicited_node_mcast_addr_prefix)) == 0)
return handle_solicited_node_mcast(pack, len);
}
break;
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 1fdc93f..7f0f14f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,7 +1,6 @@
noinst_LIBRARIES = libmisc.a

noinst_HEADERS = \
- checksum.h \
gnugetopt.h \
gtp-kernel.h \
icmpv6.h \
@@ -21,10 +20,10 @@
-DSBINDIR='"$(sbindir)"' \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
+ $(LIBOSMONETIF_CFLAGS) \
$(NULL)

libmisc_a_SOURCES = \
- checksum.c \
debug.c \
getopt.c \
getopt1.c \
diff --git a/lib/checksum.c b/lib/checksum.c
deleted file mode 100644
index 4b23897..0000000
--- a/lib/checksum.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * IP/TCP/UDP checksumming routines
- *
- * Authors: Jorge Cwik, <jorge@laser.satlink.net>
- * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
- * Tom May, <ftom@netcom.com>
- * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
- * Lots of code moved from tcp.c and ip.c; see those files
- * for more names.
- *
- * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
- * Fixed some nasty bugs, causing some horrible crashes.
- * A: At some points, the sum (%0) was used as
- * length-counter instead of the length counter
- * (%1). Thanks to Roman Hodek for pointing this out.
- * B: GCC seems to mess up if one uses too many
- * data-registers to hold input values and one tries to
- * specify d0 and d1 as scratch registers. Letting gcc
- * choose these registers itself solves the problem.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
- kills, so most of the assembly has to go. */
-
-#if defined(__FreeBSD__)
-#define _KERNEL /* needed on FreeBSD 10.x for s6_addr32 */
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/endian.h>
-#endif
-
-#include "checksum.h"
-#include <arpa/inet.h>
-
-static inline unsigned short from32to16(unsigned int x)
-{
- /* add up 16-bit and 16-bit for 16+c bit */
- x = (x & 0xffff) + (x >> 16);
- /* add up carry.. */
- x = (x & 0xffff) + (x >> 16);
- return x;
-}
-
-static unsigned int do_csum(const unsigned char *buff, int len)
-{
- int odd;
- unsigned int result = 0;
-
- if (len <= 0)
- goto out;
- odd = 1 & (unsigned long) buff;
- if (odd) {
-#if BYTE_ORDER == LITTLE_ENDIAN
- result += (*buff << 8);
-#else
- result = *buff;
-#endif
- len--;
- buff++;
- }
- if (len >= 2) {
- if (2 & (unsigned long) buff) {
- result += *(unsigned short *) buff;
- len -= 2;
- buff += 2;
- }
- if (len >= 4) {
- const unsigned char *end = buff + ((unsigned)len & ~3);
- unsigned int carry = 0;
- do {
- unsigned int w = *(unsigned int *) buff;
- buff += 4;
- result += carry;
- result += w;
- carry = (w > result);
- } while (buff < end);
- result += carry;
- result = (result & 0xffff) + (result >> 16);
- }
- if (len & 2) {
- result += *(unsigned short *) buff;
- buff += 2;
- }
- }
- if (len & 1)
-#if BYTE_ORDER == LITTLE_ENDIAN
- result += *buff;
-#else
- result += (*buff << 8);
-#endif
- result = from32to16(result);
- if (odd)
- result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
- return result;
-}
-
-/*
- * This is a version of ip_compute_csum() optimized for IP headers,
- * which always checksum on 4 octet boundaries.
- */
-uint16_t ip_fast_csum(const void *iph, unsigned int ihl)
-{
- return (uint16_t)~do_csum(iph, ihl*4);
-}
-
-/*
- * computes the checksum of a memory block at buff, length len,
- * and adds in "sum" (32-bit)
- *
- * returns a 32-bit number suitable for feeding into itself
- * or csum_tcpudp_magic
- *
- * this function must be called with even lengths, except
- * for the last fragment, which may be odd
- *
- * it's best to have buff aligned on a 32-bit boundary
- */
-uint32_t csum_partial(const void *buff, int len, uint32_t wsum)
-{
- unsigned int sum = (unsigned int)wsum;
- unsigned int result = do_csum(buff, len);
-
- /* add in old sum, and carry.. */
- result += sum;
- if (sum > result)
- result += 1;
- return (uint32_t)result;
-}
-
-/*
- * this routine is used for miscellaneous IP-like checksums, mainly
- * in icmp.c
- */
-uint16_t ip_compute_csum(const void *buff, int len)
-{
- return (uint16_t)~do_csum(buff, len);
-}
-
-uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- uint32_t len, uint8_t proto, uint32_t csum)
-{
- int carry;
- uint32_t ulen;
- uint32_t uproto;
- uint32_t sum = (uint32_t)csum;
-
- sum += (uint32_t)saddr->s6_addr32[0];
- carry = (sum < (uint32_t)saddr->s6_addr32[0]);
- sum += carry;
-
- sum += (uint32_t)saddr->s6_addr32[1];
- carry = (sum < (uint32_t)saddr->s6_addr32[1]);
- sum += carry;
-
- sum += (uint32_t)saddr->s6_addr32[2];
- carry = (sum < (uint32_t)saddr->s6_addr32[2]);
- sum += carry;
-
- sum += (uint32_t)saddr->s6_addr32[3];
- carry = (sum < (uint32_t)saddr->s6_addr32[3]);
- sum += carry;
-
- sum += (uint32_t)daddr->s6_addr32[0];
- carry = (sum < (uint32_t)daddr->s6_addr32[0]);
- sum += carry;
-
- sum += (uint32_t)daddr->s6_addr32[1];
- carry = (sum < (uint32_t)daddr->s6_addr32[1]);
- sum += carry;
-
- sum += (uint32_t)daddr->s6_addr32[2];
- carry = (sum < (uint32_t)daddr->s6_addr32[2]);
- sum += carry;
-
- sum += (uint32_t)daddr->s6_addr32[3];
- carry = (sum < (uint32_t)daddr->s6_addr32[3]);
- sum += carry;
-
- ulen = (uint32_t)htonl((uint32_t) len);
- sum += ulen;
- carry = (sum < ulen);
- sum += carry;
-
- uproto = (uint32_t)htonl(proto);
- sum += uproto;
- carry = (sum < uproto);
- sum += carry;
-
- return csum_fold((uint32_t)sum);
-}
-
-/* fold a partial checksum */
-uint16_t csum_fold(uint32_t csum)
-{
- uint32_t sum = (uint32_t)csum;
- sum = (sum & 0xffff) + (sum >> 16);
- sum = (sum & 0xffff) + (sum >> 16);
- return (uint16_t)~sum;
-}
diff --git a/lib/checksum.h b/lib/checksum.h
deleted file mode 100644
index 4b22431..0000000
--- a/lib/checksum.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include <stdint.h>
-#include <netinet/in.h>
-
-uint16_t ip_fast_csum(const void *iph, unsigned int ihl);
-uint32_t csum_partial(const void *buff, int len, uint32_t wsum);
-uint16_t ip_compute_csum(const void *buff, int len);
-
-uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- uint32_t len, uint8_t proto, uint32_t csum);
-
-uint16_t csum_fold(uint32_t csum);
diff --git a/lib/icmpv6.c b/lib/icmpv6.c
index 4226fc0..51a2b81 100644
--- a/lib/icmpv6.c
+++ b/lib/icmpv6.c
@@ -22,172 +22,16 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>

+#include <osmocom/netif/icmpv6.h>
+
#include <osmocom/gtp/gtp.h>
#include <osmocom/gtp/pdp.h>

-#include "checksum.h"
#include "ippool.h"
#include "syserr.h"
#include "icmpv6.h"
#include "config.h"

-/* 29.061 11.2.1.3.4 IPv6 Router Configuration Variables in GGSN */
-#define GGSN_MaxRtrAdvInterval 21600 /* 6 hours */
-#define GGSN_MinRtrAdvInterval 16200 /* 4.5 hours */
-#define GGSN_AdvValidLifetime 0xffffffff /* infinite */
-#define GGSN_AdvPreferredLifetime 0xffffffff /* infinite */
-
-/* RFC3307 link-local scope multicast address */
-const struct in6_addr all_router_mcast_addr = {
- .s6_addr = { 0xff,0x02,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,2 }
-};
-
-/* RFC4291 link-local solicited-node multicast address, FF02:0:0:0:0:1:FF, 104 bits = 13 bytes */
-const uint8_t solicited_node_mcast_addr_prefix[13] = {
- 0xff, 0x02, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- 0xFF
-};
-
-/* Prepends the ipv6 header and returns checksum content */
-uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,
- const struct in6_addr *daddr)
-{
- uint32_t len;
- uint16_t skb_csum;
- struct ip6_hdr *i6h;
-
- /* checksum */
- skb_csum = csum_partial(msgb_data(msg), msgb_length(msg), 0);
- len = msgb_length(msg);
- skb_csum = csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, skb_csum);
-
- /* Push IPv6 header in front of ICMPv6 packet */
- i6h = (struct ip6_hdr *) msgb_push(msg, sizeof(*i6h));
- /* 4 bits version, 8 bits TC, 20 bits flow-ID */
- i6h->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
- i6h->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len);
- i6h->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_ICMPV6;
- i6h->ip6_ctlun.ip6_un1.ip6_un1_hlim = 255;
- i6h->ip6_src = *saddr;
- i6h->ip6_dst = *daddr;
- return skb_csum;
-}
-
-/*! construct a RFC4861 compliant ICMPv6 router soliciation
- * \param[in] saddr Source IPv6 address for router advertisement
- * \param[in] daddr Destination IPv6 address for router advertisement IPv6 header
- * \param[in] prefix The single prefix to be advertised (/64 implied!)
- * \returns callee-allocated message buffer containing router advertisement */
-struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr)
-{
- struct msgb *msg = msgb_alloc_headroom(512,128, "IPv6 RS");
- struct icmpv6_rsol_hdr *rs;
- OSMO_ASSERT(msg);
- rs = (struct icmpv6_rsol_hdr *) msgb_put(msg, sizeof(*rs));
- rs->hdr.type = 133; /* see RFC4861 4.1 */
- rs->hdr.code = 0; /* see RFC4861 4.1 */
- rs->hdr.csum = 0; /* updated below */
- rs->reserved = 0; /* see RFC4861 4.1 */
-
- rs->hdr.csum = icmpv6_prepend_ip6hdr(msg, saddr, &all_router_mcast_addr);
-
- return msg;
-}
-/*! construct a 3GPP 29.061 compliant router advertisement for a given prefix
- * \param[in] saddr Source IPv6 address for router advertisement
- * \param[in] daddr Destination IPv6 address for router advertisement IPv6 header
- * \param[in] prefix The single prefix to be advertised (/64 implied!)
- * \returns callee-allocated message buffer containing router advertisement */
-static struct msgb *icmpv6_construct_ra(const struct in6_addr *saddr,
- const struct in6_addr *daddr,
- const struct in6_addr *prefix,
- uint32_t mtu)
-{
- struct msgb *msg = msgb_alloc_headroom(512,128, "IPv6 RA");
- struct icmpv6_radv_hdr *ra;
- struct icmpv6_opt_prefix *ra_opt_pref;
- struct icmpv6_opt_mtu *ra_opt_mtu;
-
- OSMO_ASSERT(msg);
-
- ra = (struct icmpv6_radv_hdr *) msgb_put(msg, sizeof(*ra));
- ra->hdr.type = 134; /* see RFC4861 4.2 */
- ra->hdr.code = 0; /* see RFC4861 4.2 */
- ra->hdr.csum = 0; /* updated below */
- ra->cur_ho_limit = 64; /* seems reasonable? */
- /* the GGSN shall leave the M-flag cleared in the Router
- * Advertisement messages */
- ra->m = 0;
- /* The GGSN may set the O-flag if there are additional
- * configuration parameters that need to be fetched by the MS */
- ra->o = 0; /* no DHCPv6 */
- ra->res = 0;
- /* RFC4861 Default: 3 * MaxRtrAdvInterval */
- ra->router_lifetime = htons(3*GGSN_MaxRtrAdvInterval);
- ra->reachable_time = 0; /* Unspecified */
-
- /* RFC4861 Section 4.6.2 */
- ra_opt_pref = (struct icmpv6_opt_prefix *) msgb_put(msg, sizeof(*ra_opt_pref));
- ra_opt_pref->hdr.type = 3; /* RFC4861 4.6.2 */
- ra_opt_pref->hdr.len = 4; /* RFC4861 4.6.2 */
- ra_opt_pref->prefix_len = 64; /* only prefix length as per 3GPP */
- /* The Prefix is contained in the Prefix Information Option of
- * the Router Advertisements and shall have the A-flag set
- * and the L-flag cleared */
- ra_opt_pref->a = 1;
- ra_opt_pref->l = 0;
- ra_opt_pref->res = 0;
- /* The lifetime of the prefix shall be set to infinity */
- ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime);
- ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime);
- ra_opt_pref->res2 = 0;
- memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
-
- /* RFC4861 Section 4.6.4, MTU */
- ra_opt_mtu = (struct icmpv6_opt_mtu *) msgb_put(msg, sizeof(*ra_opt_mtu));
- ra_opt_mtu->hdr.type = 5; /* RFC4861 4.6.4 */
- ra_opt_mtu->hdr.len = 1; /* RFC4861 4.6.4 */
- ra_opt_mtu->reserved = 0;
- ra_opt_mtu->mtu = htonl(mtu);
-
- /* The Prefix is contained in the Prefix Information Option of
- * the Router Advertisements and shall have the A-flag set
- * and the L-flag cleared */
- ra_opt_pref->a = 1;
- ra_opt_pref->l = 0;
- ra_opt_pref->res = 0;
- /* The lifetime of the prefix shall be set to infinity */
- ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime);
- ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime);
- ra_opt_pref->res2 = 0;
- memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
-
- /* checksum */
- ra->hdr.csum = icmpv6_prepend_ip6hdr(msg, saddr, daddr);
-
- return msg;
-}
-
-/* Validate an ICMPv6 router solicitation according to RFC4861 6.1.1 */
-static bool icmpv6_validate_router_solicit(const uint8_t *pack, unsigned len)
-{
- const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
- //const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
-
- /* Hop limit field must have 255 */
- if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
- return false;
- /* FIXME: ICMP checksum is valid */
- /* ICMP length (derived from IP length) is 8 or more octets */
- if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 8)
- return false;
- /* FIXME: All included options have a length > 0 */
- /* FIXME: If IP source is unspecified, no source link-layer addr option */
- return true;
-}
-
/* Validate an ICMPv6 neighbor solicitation according to RFC4861 7.1.1 */
static bool icmpv6_validate_neigh_solicit(const uint8_t *pack, unsigned len)
{
@@ -207,37 +51,6 @@
return true;
}

-/* Validate an ICMPv6 router advertisement according to RFC4861 6.1.2.
- Returns pointer packet header on success, NULL otherwise. */
-struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len)
-{
- const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
- const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
-
- /* ICMP length (derived from IP length) is 16 or more octets */
- if (len < sizeof(*ip6h) + 16)
- return NULL;
-
- if (ic6h->type != 134) /* router advertismenet type */
- return NULL;
-
- /*Routers must use their link-local address */
- if (!IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))
- return NULL;
- /* Hop limit field must have 255 */
- if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
- return NULL;
- /* ICMP Code is 0 */
- if (ic6h->code != 0)
- return NULL;
- /* ICMP length (derived from IP length) is 16 or more octets */
- if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 16)
- return NULL;
- /* FIXME: All included options have a length > 0 */
- /* FIXME: If IP source is unspecified, no source link-layer addr option */
- return (struct icmpv6_radv_hdr *)ic6h;
-}
-
/* 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 *pdp_prefix,
@@ -246,7 +59,7 @@
const uint8_t *pack, unsigned len)
{
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
- const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
+ const struct osmo_icmpv6_hdr *ic6h = (struct osmo_icmpv6_hdr *) (pack + sizeof(*ip6h));
struct msgb *msg;

if (len < sizeof(*ip6h)) {
@@ -271,7 +84,7 @@
LOGP(DICMP6, LOGL_NOTICE, "ICMPv6 type 133 but code %d\n", ic6h->code);
return -1;
}
- if (!icmpv6_validate_router_solicit(pack, len)) {
+ if (!osmo_icmpv6_validate_router_solicit(pack, len)) {
LOGP(DICMP6, LOGL_NOTICE, "Invalid Router Solicitation: %s\n",
osmo_hexdump(pack, len));
return -1;
@@ -279,7 +92,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, pdp_prefix, mtu);
+ msg = osmo_icmpv6_construct_ra(own_ll_addr, &ip6h->ip6_src, pdp_prefix, mtu);
/* Send the constructed RA to the MS */
gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
msgb_free(msg);
@@ -295,7 +108,7 @@
int handle_solicited_node_mcast(const uint8_t *pack, unsigned len)
{
const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
- const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + sizeof(*ip6h));
+ const struct osmo_icmpv6_hdr *ic6h = (struct osmo_icmpv6_hdr *) (pack + sizeof(*ip6h));

if (len < sizeof(*ip6h)) {
LOGP(DICMP6, LOGL_NOTICE, "Packet too short: %u bytes\n", len);
diff --git a/lib/icmpv6.h b/lib/icmpv6.h
index 2469ed0..08bb506 100644
--- a/lib/icmpv6.h
+++ b/lib/icmpv6.h
@@ -1,109 +1,13 @@
#pragma once

-#include <stdbool.h>
-
-#include <osmocom/core/msgb.h>
-#include <osmocom/core/endian.h>
+#include <stdint.h>

#include <osmocom/gtp/gtp.h>
#include <osmocom/gtp/pdp.h>

-#define ICMPv6_OPT_TYPE_PREFIX_INFO 0x03
-
-#define foreach_icmpv6_opt(icmpv6_pkt, icmpv6_len, opt_hdr) \
- for (opt_hdr = (struct icmpv6_opt_hdr *)(icmpv6_pkt)->options; \
- (uint8_t*)(opt_hdr) + sizeof(struct icmpv6_opt_hdr) <= (((uint8_t*)(icmpv6_pkt)) + (icmpv6_len)); \
- opt_hdr = (struct icmpv6_opt_hdr*)((uint8_t*)(opt_hdr) + (opt_hdr)->len) \
- )
-
-struct icmpv6_hdr {
- uint8_t type;
- uint8_t code;
- uint16_t csum;
-} __attribute__ ((packed));
-
-struct icmpv6_echo_hdr {
- struct icmpv6_hdr hdr;
- uint16_t ident; /* Identifier */
- uint16_t seq; /* Sequence number */
- uint8_t data[0]; /* Data */
-} __attribute__ ((packed));
-
-/* RFC4861 Section 4.1 */
-struct icmpv6_rsol_hdr {
- struct icmpv6_hdr hdr;
- uint32_t reserved;
- uint8_t options[0];
-} __attribute__ ((packed));
-
-/* RFC4861 Section 4.2 */
-struct icmpv6_radv_hdr {
- struct icmpv6_hdr hdr;
- uint8_t cur_ho_limit;
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t res:6,
- m:1,
- o:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
- uint8_t o:1, m:1, res:6;
-#endif
- uint16_t router_lifetime;
- uint32_t reachable_time;
- uint32_t retrans_timer;
- uint8_t options[0];
-} __attribute__ ((packed));
-
-
-/* RFC4861 Section 4.6 */
-struct icmpv6_opt_hdr {
- uint8_t type;
- /* length in units of 8 octets, including type+len! */
- uint8_t len;
- uint8_t data[0];
-} __attribute__ ((packed));
-
-/* RFC4861 Section 4.6.2 */
-struct icmpv6_opt_prefix {
- struct icmpv6_opt_hdr hdr;
- uint8_t prefix_len;
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t res:6,
- a:1,
- l:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
- uint8_t l:1, a:1, res:6;
-#endif
- uint32_t valid_lifetime;
- uint32_t preferred_lifetime;
- uint32_t res2;
- uint8_t prefix[16];
-} __attribute__ ((packed));
-
-/* RFC4861 Section 4.6.4 */
-struct icmpv6_opt_mtu {
- struct icmpv6_opt_hdr hdr;
- uint16_t reserved;
- uint32_t mtu;
-} __attribute__ ((packed));
-
-uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,
- const struct in6_addr *daddr);
-
-struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr);
-
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,
uint32_t mtu,
const uint8_t *pack, unsigned len);
int handle_solicited_node_mcast(const uint8_t *pack, unsigned len);
-
-struct icmpv6_radv_hdr *icmpv6_validate_router_adv(const uint8_t *pack, unsigned len);
-
-
-/* RFC3307 link-local scope multicast address */
-extern const struct in6_addr all_router_mcast_addr;
-
-extern const uint8_t solicited_node_mcast_addr_prefix[13];
diff --git a/sgsnemu/Makefile.am b/sgsnemu/Makefile.am
index 5d88c7f..d28673f 100644
--- a/sgsnemu/Makefile.am
+++ b/sgsnemu/Makefile.am
@@ -9,9 +9,15 @@
-DSBINDIR='"$(sbindir)"' \
-I$(top_srcdir)/include \
$(LIBOSMOCORE_CFLAGS) \
+ $(LIBOSMONETIF_CFLAGS) \
$(NULL)

-sgsnemu_LDADD = @EXEC_LDADD@ -lgtp -L../gtp ../lib/libmisc.a $(LIBOSMOCORE_LIBS)
+sgsnemu_LDADD = \
+ @EXEC_LDADD@ \
+ -lgtp -L../gtp ../lib/libmisc.a \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMONETIF_LIBS) \
+ $(NULL)

if ENABLE_GTP_KERNEL
AM_CFLAGS += \
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index ee74def..ff2cfc7 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -25,6 +25,8 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>

+#include <osmocom/netif/icmpv6.h>
+
#include <ctype.h>
#include <netdb.h>
#include <signal.h>
@@ -178,7 +180,7 @@
} __attribute__ ((packed));

struct ip6_ping {
- struct icmpv6_echo_hdr hdr;
+ struct osmo_icmpv6_echo_hdr hdr;
uint8_t data[CREATEPING_MAX]; /* Data */
} __attribute__ ((packed));

@@ -1265,7 +1267,7 @@

static int cb_gtpu_data_ind_ping6(struct pdp_t *pdp, struct ip6_hdr *ip6h, unsigned len)
{
- const struct icmpv6_echo_hdr *ic6h = (struct icmpv6_echo_hdr *) ((uint8_t*)ip6h + sizeof(*ip6h));
+ const struct osmo_icmpv6_echo_hdr *ic6h = (struct osmo_icmpv6_echo_hdr *) ((uint8_t *)ip6h + sizeof(*ip6h));
struct timeval tv;
struct timeval tp;
int triptime;
@@ -1285,7 +1287,7 @@
return 0;
}

- if (len < sizeof(struct ip6_hdr) + sizeof(struct icmpv6_echo_hdr)) {
+ if (len < sizeof(struct ip6_hdr) + sizeof(struct osmo_icmpv6_echo_hdr)) {
LOGP(DSGSN, LOGL_ERROR, "Packet len too small to contain ICMPv6 echo header (%d)\n", len);
return 0;
}
@@ -1305,7 +1307,7 @@
inet_ntop(AF_INET6, &ip6h->ip6_src, straddr, sizeof(straddr)),
ntohs(ic6h->seq));

- if (len >= sizeof(struct ip6_hdr) + sizeof(struct icmpv6_echo_hdr) + sizeof(struct timeval)) {
+ if (len >= sizeof(struct ip6_hdr) + sizeof(struct osmo_icmpv6_echo_hdr) + sizeof(struct timeval)) {
gettimeofday(&tv, NULL);
memcpy(&tp, ic6h->data, sizeof(struct timeval));
if ((tv.tv_usec -= tp.tv_usec) < 0) {
@@ -1441,7 +1443,7 @@

struct msgb *msg = msgb_alloc_headroom(sizeof(struct ip6_ping) + 128,128, "ICMPv6 echo");
OSMO_ASSERT(msg);
- pack = (struct ip6_ping *) msgb_put(msg, sizeof(struct icmpv6_echo_hdr) + datasize);
+ pack = (struct ip6_ping *) msgb_put(msg, sizeof(struct osmo_icmpv6_echo_hdr) + datasize);
pack->hdr.hdr.type = 128;
pack->hdr.hdr.code = 0;
pack->hdr.hdr.csum = 0; /* updated below */
@@ -1457,7 +1459,7 @@
gettimeofday(tp, &tz);
}

- pack->hdr.hdr.csum = icmpv6_prepend_ip6hdr(msg, &src->v6, &dst->v6);
+ pack->hdr.hdr.csum = osmo_icmpv6_prepend_ip6hdr(msg, &src->v6, &dst->v6);

ntransmitted++;
return gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));
@@ -1682,7 +1684,7 @@
return EOF; /* Not a valid IP address */
}
SYS_ERR(DSGSN, LOGL_INFO, 0, "Sending ICMPv6 Router Soliciation to GGSN...");
- msg = icmpv6_construct_rs(saddr6);
+ msg = osmo_icmpv6_construct_rs(saddr6);
gtp_data_req(gsn, ctx->pdp, msgb_data(msg), msgb_length(msg));
msgb_free(msg);
}
@@ -1748,11 +1750,12 @@
}
}

-static void handle_router_adv(struct pdp_t *pdp, struct ip6_hdr *ip6h, struct icmpv6_radv_hdr *ra, size_t ra_len)
+static void handle_router_adv(struct pdp_t *pdp, struct ip6_hdr *ip6h,
+ struct osmo_icmpv6_radv_hdr *ra, size_t ra_len)
{
struct pdp_peer_sgsnemu_ctx* ctx = (struct pdp_peer_sgsnemu_ctx*)pdp->peer[0];
- struct icmpv6_opt_hdr *opt_hdr;
- struct icmpv6_opt_prefix *opt_prefix;
+ struct osmo_icmpv6_opt_hdr *opt_hdr;
+ struct osmo_icmpv6_opt_prefix *opt_prefix;
int rc;
sigset_t oldmask;
struct in6_addr rm;
@@ -1763,7 +1766,7 @@

foreach_icmpv6_opt(ra, ra_len, opt_hdr) {
if (opt_hdr->type == ICMPv6_OPT_TYPE_PREFIX_INFO) {
- opt_prefix = (struct icmpv6_opt_prefix *)opt_hdr;
+ opt_prefix = (struct osmo_icmpv6_opt_prefix *)opt_hdr;
size_t prefix_len_bytes = (opt_prefix->prefix_len + 7)/8;
SYS_ERR(DSGSN, LOGL_INFO, 0, "Parsing OPT Prefix info (prefix_len=%u): %s",
opt_prefix->prefix_len,
@@ -1821,10 +1824,10 @@
static int cb_gtpu_data_ind(struct pdp_t *pdp, void *pack, unsigned len)
{
struct iphdr *iph = (struct iphdr *)pack;
- struct icmpv6_radv_hdr *ra;
+ struct osmo_icmpv6_radv_hdr *ra;
switch (iph->version) {
case 6:
- if ((ra = icmpv6_validate_router_adv(pack, len))) {
+ if ((ra = osmo_icmpv6_validate_router_adv(pack, len))) {
size_t ra_len = (uint8_t*)ra - (uint8_t*)pack;
handle_router_adv(pdp, (struct ip6_hdr *)pack, ra, ra_len);
return 0;

To view, visit change 42465. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I8d8fae362f302d48afaed28a9c664f76ca4a2739
Gerrit-Change-Number: 42465
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>