<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>