pespin has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-ggsn/+/42465?usp=email )

Change subject: Depend on libosmo-netif for icmpv6 APIs
......................................................................

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, 55 insertions(+), 538 deletions(-)

Approvals:
  pespin: Looks good to me, approved
  fixeria: Looks good to me, but someone else must approve
  osmith: Looks good to me, but someone else must approve
  Jenkins Builder: Verified




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..9f643da 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -24,17 +24,18 @@

 mkdir "$deps" || true

-if [ "x$GTP" == "x--enable-gtp-linux" ]; then
-       osmo-build-dep.sh libgtpnl
-fi
-osmo-build-dep.sh libosmocore "" --disable-doxygen
-
 verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")

 export PKG_CONFIG_PATH="$inst/lib/pkgconfig:$PKG_CONFIG_PATH"
 export LD_LIBRARY_PATH="$inst/lib"
 export PATH="$inst/bin:$PATH"

+if [ "x$GTP" == "x--enable-gtp-linux" ]; then
+       osmo-build-dep.sh libgtpnl
+fi
+osmo-build-dep.sh libosmocore "" --disable-doxygen
+osmo-build-dep.sh libosmo-netif "" --disable-doxygen
+
 # Additional configure options and depends
 CONFIG=""
 if [ "$WITH_MANUALS" = "1" ]; then
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, <[email protected]>
- *             Arnt Gulbrandsen, <[email protected]>
- *             Tom May, <[email protected]>
- *             Andreas Schwab, <[email protected]>
- *             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 https://gerrit.osmocom.org/c/osmo-ggsn/+/42465?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: I8d8fae362f302d48afaed28a9c664f76ca4a2739
Gerrit-Change-Number: 42465
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: osmith <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to