<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17826">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">sgsnemu: Implement ping on IPv6 APNs<br><br>Related: OS#4434<br>Change-Id: If9ca7c37a1a397bbc3f8912d67bccdabc4968e0c<br>---<br>M lib/icmpv6.c<br>M lib/icmpv6.h<br>M sgsnemu/sgsnemu.c<br>3 files changed, 234 insertions(+), 51 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/lib/icmpv6.c b/lib/icmpv6.c</span><br><span>index 1bddf65..ac1474d 100644</span><br><span>--- a/lib/icmpv6.c</span><br><span>+++ b/lib/icmpv6.c</span><br><span>@@ -42,7 +42,7 @@</span><br><span> };</span><br><span> </span><br><span> /* Prepends the ipv6 header and returns checksum content */</span><br><span style="color: hsl(0, 100%, 40%);">-static uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,</span><br><span style="color: hsl(120, 100%, 40%);">+uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,</span><br><span>                                  const struct in6_addr *daddr)</span><br><span> {</span><br><span>         uint32_t len;</span><br><span>diff --git a/lib/icmpv6.h b/lib/icmpv6.h</span><br><span>index 44b9b73..4b4dc37 100644</span><br><span>--- a/lib/icmpv6.h</span><br><span>+++ b/lib/icmpv6.h</span><br><span>@@ -22,6 +22,13 @@</span><br><span>      uint16_t csum;</span><br><span> } __attribute__ ((packed));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct icmpv6_echo_hdr {</span><br><span style="color: hsl(120, 100%, 40%);">+   struct icmpv6_hdr hdr;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint16_t ident;         /* Identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+      uint16_t seq;           /* Sequence number */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t data[0];        /* Data */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* RFC4861 Section 4.1 */</span><br><span> struct icmpv6_rsol_hdr {</span><br><span>   struct icmpv6_hdr hdr;</span><br><span>@@ -76,6 +83,9 @@</span><br><span>   uint8_t prefix[16];</span><br><span> } __attribute__ ((packed));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+uint16_t icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr *saddr,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  const struct in6_addr *daddr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct msgb *icmpv6_construct_rs(const struct in6_addr *saddr);</span><br><span> </span><br><span> int handle_router_mcast(struct gsn_t *gsn, struct pdp_t *pdp,</span><br><span>diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c</span><br><span>index 69879dd..7d60c31 100644</span><br><span>--- a/sgsnemu/sgsnemu.c</span><br><span>+++ b/sgsnemu/sgsnemu.c</span><br><span>@@ -104,7 +104,7 @@</span><br><span>    size_t prefixlen;</span><br><span>    char *ipup, *ipdown;    /* Filename of scripts */</span><br><span>    int defaultroute;       /* Set up default route */</span><br><span style="color: hsl(0, 100%, 40%);">-      struct in_addr pinghost;        /* Remote ping host    */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct in46_addr pinghost;      /* Remote ping host    */</span><br><span>    int pingrate;</span><br><span>        int pingsize;</span><br><span>        int pingcount;</span><br><span>@@ -166,6 +166,11 @@</span><br><span>        uint8_t data[CREATEPING_MAX];   /* Data */</span><br><span> } __attribute__ ((packed));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ip6_ping {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct icmpv6_echo_hdr hdr;</span><br><span style="color: hsl(120, 100%, 40%);">+   uint8_t data[CREATEPING_MAX];   /* Data */</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__ ((packed));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Statistical values for ping */</span><br><span> int nreceived = 0;</span><br><span> int ntreceived = 0;</span><br><span>@@ -916,20 +921,61 @@</span><br><span>  /* defaultroute */</span><br><span>   options.defaultroute = args_info.defaultroute_flag;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       /* PDP Type */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!strcmp(args_info.pdp_type_arg, "v6"))</span><br><span style="color: hsl(120, 100%, 40%);">+          options.pdp_type = PDP_EUA_TYPE_v6;</span><br><span style="color: hsl(120, 100%, 40%);">+   else if (!strcmp(args_info.pdp_type_arg, "v4"))</span><br><span style="color: hsl(120, 100%, 40%);">+             options.pdp_type = PDP_EUA_TYPE_v4;</span><br><span style="color: hsl(120, 100%, 40%);">+   else {</span><br><span style="color: hsl(120, 100%, 40%);">+                SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unsupported/unknown PDP Type '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        args_info.pdp_type_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* pinghost                                                     */</span><br><span>   /* Store ping host as in_addr                                   */</span><br><span>   if (args_info.pinghost_arg) {</span><br><span style="color: hsl(0, 100%, 40%);">-           if (!(host = gethostbyname(args_info.pinghost_arg))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                struct addrinfo hints;</span><br><span style="color: hsl(120, 100%, 40%);">+                struct addrinfo *result;</span><br><span style="color: hsl(120, 100%, 40%);">+              memset(&hints, 0, sizeof(struct addrinfo));</span><br><span style="color: hsl(120, 100%, 40%);">+               switch (options.pdp_type) {</span><br><span style="color: hsl(120, 100%, 40%);">+           case PDP_EUA_TYPE_v4:</span><br><span style="color: hsl(120, 100%, 40%);">+                 hints.ai_family = AF_INET;</span><br><span style="color: hsl(120, 100%, 40%);">+                    break;</span><br><span style="color: hsl(120, 100%, 40%);">+                case PDP_EUA_TYPE_v6:</span><br><span style="color: hsl(120, 100%, 40%);">+                 hints.ai_family = AF_INET6;</span><br><span style="color: hsl(120, 100%, 40%);">+                   break;</span><br><span style="color: hsl(120, 100%, 40%);">+                default:</span><br><span style="color: hsl(120, 100%, 40%);">+                      SYS_ERR(DSGSN, LOGL_ERROR, 0, "lookup(AF_UNSPEC) %d", options.pdp_type);</span><br><span style="color: hsl(120, 100%, 40%);">+                    hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+             hints.ai_socktype = SOCK_DGRAM;</span><br><span style="color: hsl(120, 100%, 40%);">+               hints.ai_flags = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+           hints.ai_protocol = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                hints.ai_canonname = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+            hints.ai_addr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+         hints.ai_next = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+         if ((i = getaddrinfo(args_info.pinghost_arg, NULL, &hints, &result)) != 0) {</span><br><span>                         SYS_ERR(DSGSN, LOGL_ERROR, 0,</span><br><span style="color: hsl(0, 100%, 40%);">-                           "Invalid ping host: %s!",</span><br><span style="color: hsl(0, 100%, 40%);">-                             args_info.pinghost_arg);</span><br><span style="color: hsl(120, 100%, 40%);">+                              "Invalid ping host '%s': %s",</span><br><span style="color: hsl(120, 100%, 40%);">+                               args_info.pinghost_arg, gai_strerror(i));</span><br><span>                    return -1;</span><br><span>           } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        memcpy(&options.pinghost.s_addr, host->h_addr,</span><br><span style="color: hsl(0, 100%, 40%);">-                          host->h_length);</span><br><span style="color: hsl(120, 100%, 40%);">+                    switch (result->ai_family) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       case AF_INET:</span><br><span style="color: hsl(120, 100%, 40%);">+                         options.pinghost.len = sizeof(struct in_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+                                options.pinghost.v4 = ((struct sockaddr_in*)result->ai_addr)->sin_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                         SYS_ERR(DSGSN, LOGL_ERROR, 0,   "AF_INET %d", options.pinghost.len);</span><br><span style="color: hsl(120, 100%, 40%);">+                                break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        case AF_INET6:</span><br><span style="color: hsl(120, 100%, 40%);">+                                options.pinghost.len = sizeof(struct in6_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+                               options.pinghost.v6 = ((struct sockaddr_in6*)result->ai_addr)->sin6_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                               break;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span>                    printf("Using ping host:       %s (%s)\n",</span><br><span>                                args_info.pinghost_arg,</span><br><span style="color: hsl(0, 100%, 40%);">-                         inet_ntoa(options.pinghost));</span><br><span style="color: hsl(120, 100%, 40%);">+                         in46a_ntoa(&options.pinghost));</span><br><span style="color: hsl(120, 100%, 40%);">+                    freeaddrinfo(result);</span><br><span>                }</span><br><span>    }</span><br><span> </span><br><span>@@ -947,22 +993,6 @@</span><br><span>         else</span><br><span>                 options.tx_gpdu_seq = 1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    /* PDP Type */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (!strcmp(args_info.pdp_type_arg, "v6"))</span><br><span style="color: hsl(0, 100%, 40%);">-            options.pdp_type = PDP_EUA_TYPE_v6;</span><br><span style="color: hsl(0, 100%, 40%);">-     else if (!strcmp(args_info.pdp_type_arg, "v4"))</span><br><span style="color: hsl(0, 100%, 40%);">-               options.pdp_type = PDP_EUA_TYPE_v4;</span><br><span style="color: hsl(0, 100%, 40%);">-     else {</span><br><span style="color: hsl(0, 100%, 40%);">-          SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unsupported/unknown PDP Type '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  args_info.pdp_type_arg);</span><br><span style="color: hsl(0, 100%, 40%);">-                return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (options.pingcount && options.pdp_type != PDP_EUA_TYPE_v4) {</span><br><span style="color: hsl(0, 100%, 40%);">-         SYS_ERR(DSGSN, LOGL_ERROR, 0, "built-in ping only works with IPv4, use tun-device");</span><br><span style="color: hsl(0, 100%, 40%);">-          return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>    return 0;</span><br><span> </span><br><span> }</span><br><span>@@ -1118,7 +1148,7 @@</span><br><span>   struct timezone tz;</span><br><span>  struct timeval tv;</span><br><span>   int diff;</span><br><span style="color: hsl(0, 100%, 40%);">-       if ((options.pinghost.s_addr) && (2 == state) &&</span><br><span style="color: hsl(120, 100%, 40%);">+      if ((options.pinghost.len) && (2 == state) &&</span><br><span>            ((pingseq < options.pingcount) || (options.pingcount == 0))) {</span><br><span>                gettimeofday(&tv, &tz);</span><br><span>              diff = 1000000 / options.pingrate * pingseq - 1000000 * (tv.tv_sec - firstping.tv_sec) - (tv.tv_usec - firstping.tv_usec);      /* Microseconds safe up to 500 sec */</span><br><span>@@ -1143,7 +1173,7 @@</span><br><span>        gettimeofday(&tv, &tz);</span><br><span>      elapsed = 1000000 * (tv.tv_sec - firstping.tv_sec) + (tv.tv_usec - firstping.tv_usec);  /* Microseconds */</span><br><span>   printf("\n");</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\n----%s PING Statistics----\n", inet_ntoa(options.pinghost));</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("\n----%s PING Statistics----\n", in46a_ntoa(&options.pinghost));</span><br><span>       printf("%d packets transmitted in %.3f seconds, ", ntransmitted,</span><br><span>          elapsed / 1000000.0);</span><br><span>         printf("%d packets received, ", nreceived);</span><br><span>@@ -1167,10 +1197,8 @@</span><br><span>       return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Handle a received ping packet. Print out line and update statistics. */</span><br><span style="color: hsl(0, 100%, 40%);">-static int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len)</span><br><span style="color: hsl(120, 100%, 40%);">+static int encaps_ping4(struct pdp_t *pdp, void *pack, unsigned len)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct timezone tz;</span><br><span>  struct timeval tv;</span><br><span>   struct timeval *tp;</span><br><span>  struct ip_ping *pingpack = pack;</span><br><span>@@ -1179,17 +1207,12 @@</span><br><span> </span><br><span>       src.s_addr = pingpack->src;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      gettimeofday(&tv, &tz);</span><br><span style="color: hsl(0, 100%, 40%);">- if (options.debug)</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("%d.%6d ", (int)tv.tv_sec, (int)tv.tv_usec);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>        if (len < CREATEPING_IP + CREATEPING_ICMP) {</span><br><span>              printf("packet too short (%d bytes) from %s\n", len,</span><br><span>                      inet_ntoa(src));</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ntreceived++;</span><br><span>        if (pingpack->protocol != 1) {</span><br><span>            if (!options.pingquiet)</span><br><span>                      printf("%d bytes from %s: ip_protocol=%d (%s)\n",</span><br><span>@@ -1213,7 +1236,7 @@</span><br><span>                 inet_ntoa(src), ntohs(pingpack->seq));</span><br><span> </span><br><span>         if (len >= sizeof(struct timeval) + CREATEPING_IP + CREATEPING_ICMP) {</span><br><span style="color: hsl(0, 100%, 40%);">-               gettimeofday(&tv, &tz);</span><br><span style="color: hsl(120, 100%, 40%);">+               gettimeofday(&tv, NULL);</span><br><span>                 tp = (struct timeval *)pingpack->data;</span><br><span>            if ((tv.tv_usec -= tp->tv_usec) < 0) {</span><br><span>                         tv.tv_sec--;</span><br><span>@@ -1236,15 +1259,106 @@</span><br><span>      return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Create a new ping packet and send it off to peer. */</span><br><span style="color: hsl(0, 100%, 40%);">-static int create_ping(void *gsn, struct pdp_t *pdp,</span><br><span style="color: hsl(0, 100%, 40%);">-                   struct in_addr *dst, int seq, unsigned int datasize)</span><br><span style="color: hsl(120, 100%, 40%);">+static int encaps_ping6(struct pdp_t *pdp, struct ip6_hdr *ip6h, unsigned len)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct icmpv6_echo_hdr *ic6h = (struct icmpv6_echo_hdr *) ((uint8_t*)ip6h + sizeof(*ip6h));</span><br><span style="color: hsl(120, 100%, 40%);">+     struct timeval tv;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct timeval tp;</span><br><span style="color: hsl(120, 100%, 40%);">+    int triptime;</span><br><span style="color: hsl(120, 100%, 40%);">+ char straddr[128];</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+        if (len < sizeof(struct ip6_hdr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                SYS_ERR(DSGSN, LOGL_ERROR, 0, "Packet len too small to contain IPv6 header (%d)", len);</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_ICMPV6) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!options.pingquiet)</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf("%d bytes from %s: ip6_protocol=%d (%s)\n", len,</span><br><span style="color: hsl(120, 100%, 40%);">+                            inet_ntop(AF_INET6, &ip6h->ip6_src, straddr, sizeof(straddr)),</span><br><span style="color: hsl(120, 100%, 40%);">+                         ip6h->ip6_ctlun.ip6_un1.ip6_un1_nxt,</span><br><span style="color: hsl(120, 100%, 40%);">+                               print_ipprot(ip6h->ip6_ctlun.ip6_un1.ip6_un1_nxt));</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (len < sizeof(struct ip6_hdr) + sizeof(struct icmpv6_echo_hdr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DSGSN, LOGL_ERROR, "Packet len too small to contain ICMPv6 echo header (%d)\n", len);</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ic6h->hdr.type != 129 || ic6h->hdr.code != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!options.pingquiet)</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf</span><br><span style="color: hsl(120, 100%, 40%);">+                            ("%d bytes from %s: icmp_type=%d icmp_code=%d\n", len,</span><br><span style="color: hsl(120, 100%, 40%);">+                      inet_ntop(AF_INET6, &ip6h->ip6_src, straddr, sizeof(straddr)),</span><br><span style="color: hsl(120, 100%, 40%);">+                         ic6h->hdr.type, ic6h->hdr.code);</span><br><span style="color: hsl(120, 100%, 40%);">+            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   nreceived++;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!options.pingquiet)</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("%d bytes from %s: icmp_seq=%d", len,</span><br><span style="color: hsl(120, 100%, 40%);">+                       inet_ntop(AF_INET6, &ip6h->ip6_src, straddr, sizeof(straddr)),</span><br><span style="color: hsl(120, 100%, 40%);">+                 ntohs(ic6h->seq));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (len >= sizeof(struct ip6_hdr) + sizeof(struct icmpv6_echo_hdr) + sizeof(struct timeval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             gettimeofday(&tv, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(&tp, ic6h->data, sizeof(struct timeval));</span><br><span style="color: hsl(120, 100%, 40%);">+               if ((tv.tv_usec -= tp.tv_usec) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      tv.tv_sec--;</span><br><span style="color: hsl(120, 100%, 40%);">+                  tv.tv_usec += 1000000;</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             tv.tv_sec -= tp.tv_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             triptime = tv.tv_sec * 1000000 + (tv.tv_usec);</span><br><span style="color: hsl(120, 100%, 40%);">+                tsum += triptime;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (triptime < tmin)</span><br><span style="color: hsl(120, 100%, 40%);">+                       tmin = triptime;</span><br><span style="color: hsl(120, 100%, 40%);">+              if (triptime > tmax)</span><br><span style="color: hsl(120, 100%, 40%);">+                       tmax = triptime;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!options.pingquiet)</span><br><span style="color: hsl(120, 100%, 40%);">+                       printf(" time=%.3f ms\n", triptime / 1000.0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (!options.pingquiet)</span><br><span style="color: hsl(120, 100%, 40%);">+                printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Handle a received ping packet. Print out line and update statistics. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encaps_ping(struct pdp_t *pdp, void *pack, unsigned len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct iphdr *iph = (struct iphdr *)pack;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct timeval tv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        gettimeofday(&tv, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (options.debug)</span><br><span style="color: hsl(120, 100%, 40%);">+            printf("%d.%6d ", (int)tv.tv_sec, (int)tv.tv_usec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ntreceived++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (len < sizeof(struct iphdr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          SYS_ERR(DSGSN, LOGL_ERROR, 0, "Packet len too small to contain ip header (%d)", len);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     switch(iph->version) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+               return encaps_ping4(pdp, pack, len);</span><br><span style="color: hsl(120, 100%, 40%);">+  case 6:</span><br><span style="color: hsl(120, 100%, 40%);">+               return encaps_ping6(pdp, (struct ip6_hdr *)pack, len);</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              SYS_ERR(DSGSN, LOGL_ERROR, 0, "Unknown ip header version %d", iph->version);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int create_ping4(void *gsn, struct pdp_t *pdp, struct in46_addr *src,</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct in46_addr *dst, int seq, unsigned int datasize)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span>    struct ip_ping pack;</span><br><span>         uint16_t v16;</span><br><span>        uint8_t *p8 = (uint8_t *) & pack;</span><br><span style="color: hsl(0, 100%, 40%);">-   struct in_addr src;</span><br><span>  unsigned int n;</span><br><span>      long int sum = 0;</span><br><span>    int count = 0;</span><br><span>@@ -1253,14 +1367,6 @@</span><br><span>      struct timeval *tp =</span><br><span>             (struct timeval *)&p8[CREATEPING_IP + CREATEPING_ICMP];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (datasize > CREATEPING_MAX) {</span><br><span style="color: hsl(0, 100%, 40%);">-             SYS_ERR(DSGSN, LOGL_ERROR, 0,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "Ping size to large: %d!", datasize);</span><br><span style="color: hsl(0, 100%, 40%);">-         return -1;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       memcpy(&src, &(pdp->eua.v[2]), 4);   /* Copy a 4 byte address */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>  pack.ipver = 0x45;</span><br><span>   pack.tos = 0x00;</span><br><span>     pack.length = htons(CREATEPING_IP + CREATEPING_ICMP + datasize);</span><br><span>@@ -1269,8 +1375,8 @@</span><br><span>     pack.ttl = 0x40;</span><br><span>     pack.protocol = 0x01;</span><br><span>        pack.ipcheck = 0x0000;</span><br><span style="color: hsl(0, 100%, 40%);">-  pack.src = src.s_addr;</span><br><span style="color: hsl(0, 100%, 40%);">-  pack.dst = dst->s_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+    pack.src = src->v4.s_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ pack.dst = dst->v4.s_addr;</span><br><span>        pack.type = 0x08;</span><br><span>    pack.code = 0x00;</span><br><span>    pack.checksum = 0x0000;</span><br><span>@@ -1320,6 +1426,73 @@</span><br><span>     return gtp_data_req(gsn, pdp, &pack, 28 + datasize);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int create_ping6(void *gsn, struct pdp_t *pdp, struct in46_addr *src,</span><br><span style="color: hsl(120, 100%, 40%);">+                       struct in46_addr *dst, int seq, unsigned int datasize)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ip6_ping *pack;</span><br><span style="color: hsl(120, 100%, 40%);">+        uint8_t *p8;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int n;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct timezone tz;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct timeval *tp;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct msgb *msg = msgb_alloc_headroom(sizeof(struct ip6_ping) + 128,128, "ICMPv6 echo");</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+     pack = (struct ip6_ping *) msgb_put(msg, sizeof(struct icmpv6_echo_hdr) + datasize);</span><br><span style="color: hsl(120, 100%, 40%);">+  pack->hdr.hdr.type = 128;</span><br><span style="color: hsl(120, 100%, 40%);">+  pack->hdr.hdr.code = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    pack->hdr.hdr.csum = 0;  /* updated below */</span><br><span style="color: hsl(120, 100%, 40%);">+       pack->hdr.ident = 0x0000;</span><br><span style="color: hsl(120, 100%, 40%);">+  pack->hdr.seq = htons(seq);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      p8 = pack->data;</span><br><span style="color: hsl(120, 100%, 40%);">+   for (n = 0; n < (datasize); n++)</span><br><span style="color: hsl(120, 100%, 40%);">+           p8[n] = n;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (datasize >= sizeof(struct timeval)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          tp = (struct timeval *)pack->data;</span><br><span style="color: hsl(120, 100%, 40%);">+         gettimeofday(tp, &tz);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   pack->hdr.hdr.csum = icmpv6_prepend_ip6hdr(msg, &src->v6, &dst->v6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ntransmitted++;</span><br><span style="color: hsl(120, 100%, 40%);">+       return gtp_data_req(gsn, pdp, msgb_data(msg), msgb_length(msg));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Create a new ping packet and send it off to peer. */</span><br><span style="color: hsl(120, 100%, 40%);">+static int create_ping(void *gsn, struct pdp_t *pdp,</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct in46_addr *dst, int seq, unsigned int datasize)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int num_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct in46_addr addr[2];</span><br><span style="color: hsl(120, 100%, 40%);">+     struct in46_addr *src;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (datasize > CREATEPING_MAX) {</span><br><span style="color: hsl(120, 100%, 40%);">+           SYS_ERR(DSGSN, LOGL_ERROR, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Ping size to large: %d!", datasize);</span><br><span style="color: hsl(120, 100%, 40%);">+               return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((num_addr = in46a_from_eua(&pdp->eua, addr)) < 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             SYS_ERR(DSGSN, LOGL_ERROR, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "in46a_from_eua() failed! %d", num_addr);</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (dst->len == addr[0].len) {</span><br><span style="color: hsl(120, 100%, 40%);">+             src = &addr[0];</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (num_addr > 1 && dst->len == addr[1].len) {</span><br><span style="color: hsl(120, 100%, 40%);">+           src = &addr[1];</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              SYS_ERR(DSGSN, LOGL_ERROR, 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "Mismaching source and destination IP addr types (%d vs %d)", dst->len, addr[0].len);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (in46a_is_v4(dst))</span><br><span style="color: hsl(120, 100%, 40%);">+         return create_ping4(gsn, pdp, src, dst, seq, datasize);</span><br><span style="color: hsl(120, 100%, 40%);">+       else</span><br><span style="color: hsl(120, 100%, 40%);">+          return create_ping6(gsn, pdp, src, dst, seq, datasize);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int delete_context(struct pdp_t *pdp)</span><br><span> {</span><br><span>    int rc;</span><br><span>@@ -1955,7 +2128,7 @@</span><br><span>                              /* Delete context */</span><br><span>                                 printf("Disconnecting PDP context #%d\n", n);</span><br><span>                              gtp_delete_context_req2(gsn, iparr[n].pdp, NULL, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-                            if ((options.pinghost.s_addr != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                            if ((options.pinghost.len)</span><br><span>                               && ntransmitted)</span><br><span>                                         ping_finish();</span><br><span>                       }</span><br><span>@@ -1965,7 +2138,7 @@</span><br><span>            diff = 0;</span><br><span>            while ((diff <= 0) &&</span><br><span>                    /* Send off an ICMP ping packet */</span><br><span style="color: hsl(0, 100%, 40%);">-                      /*if ( */ (options.pinghost.s_addr) && (2 == state) &&</span><br><span style="color: hsl(120, 100%, 40%);">+                /*if ( */ (options.pinghost.len) && (2 == state) &&</span><br><span>                  ((pingseq < options.pingcount)</span><br><span>                     || (options.pingcount == 0))) {</span><br><span>                      if (!pingseq)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17826">change 17826</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-ggsn/+/17826"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ggsn </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If9ca7c37a1a397bbc3f8912d67bccdabc4968e0c </div>
<div style="display:none"> Gerrit-Change-Number: 17826 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: daniel <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>