<p>keith has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/24237">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Implement ICMP response for inactive IP address.<br><br>Send ICMP Host Unreachable packets back on the tun device<br>in reponse to a packet received for an IP address that is<br>not active in our pool (No active pdp context)<br><br>Only IPv4 implemented.<br><br>Change-Id: Ia2c708feab14bb4cada00b0a90e0cb56d680d1aa<br>---<br>M ggsn/ggsn.c<br>1 file changed, 63 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/37/24237/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c</span><br><span>index 0cde543..a0479a1 100644</span><br><span>--- a/ggsn/ggsn.c</span><br><span>+++ b/ggsn/ggsn.c</span><br><span>@@ -40,6 +40,7 @@</span><br><span> #include <arpa/inet.h></span><br><span> #include <netinet/in.h></span><br><span> #include <netinet/ip.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <netinet/ip_icmp.h></span><br><span> #include <netinet/ip6.h></span><br><span> </span><br><span> #include <osmocom/core/timer.h></span><br><span>@@ -584,6 +585,64 @@</span><br><span>         return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static uint16_t inet_checksum(void *data, int len) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    int nleft = len;</span><br><span style="color: hsl(120, 100%, 40%);">+      int sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned short *w = data;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned short checksum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        while (nleft > 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                sum += *w++;</span><br><span style="color: hsl(120, 100%, 40%);">+          nleft -= 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nleft == 1){</span><br><span style="color: hsl(120, 100%, 40%);">+              *(unsigned char *)(&checksum) = *(unsigned char *)w;</span><br><span style="color: hsl(120, 100%, 40%);">+              sum += checksum;</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%);">+   sum = (sum >> 16) + (sum & 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+ sum += (sum >> 16);</span><br><span style="color: hsl(120, 100%, 40%);">+     checksum = ~sum;</span><br><span style="color: hsl(120, 100%, 40%);">+      return (checksum);</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%);">+/* Generate and send an ICMP HOST UNREACHABLE Packet */</span><br><span style="color: hsl(120, 100%, 40%);">+static void ipv4_host_unreach(struct tun_t *tun, void *pack, unsigned len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char send_buf[sizeof(struct ip) + sizeof(struct icmp) + len];</span><br><span style="color: hsl(120, 100%, 40%);">+ len = len - 20;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct iphdr *iph = (struct iphdr *)pack;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(send_buf, 0, sizeof(send_buf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ip *ip = (struct ip *)send_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+        struct icmp *icmp = (struct icmp *)(ip + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        ip->ip_v = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+      ip->ip_hl = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+     ip->ip_tos = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    ip->ip_len = htons(sizeof(send_buf));</span><br><span style="color: hsl(120, 100%, 40%);">+      ip->ip_id = rand();</span><br><span style="color: hsl(120, 100%, 40%);">+        ip->ip_off = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    ip->ip_ttl = 64;</span><br><span style="color: hsl(120, 100%, 40%);">+   ip->ip_sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    ip->ip_p = IPPROTO_ICMP;</span><br><span style="color: hsl(120, 100%, 40%);">+   ip->ip_src.s_addr = iph->daddr;</span><br><span style="color: hsl(120, 100%, 40%);">+ ip->ip_dst.s_addr = iph->saddr;</span><br><span style="color: hsl(120, 100%, 40%);">+ ip->ip_sum = inet_checksum(ip, sizeof(send_buf));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        icmp->icmp_type = ICMP_DEST_UNREACH;</span><br><span style="color: hsl(120, 100%, 40%);">+       icmp->icmp_code = ICMP_HOST_UNREACH;</span><br><span style="color: hsl(120, 100%, 40%);">+       icmp->icmp_id = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ icmp->icmp_seq = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        icmp->icmp_cksum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(send_buf + sizeof(ip) + sizeof(icmp) + 12, pack, len);</span><br><span style="color: hsl(120, 100%, 40%);">+ icmp->icmp_cksum = inet_checksum(icmp, sizeof(icmp) + 12 + len);</span><br><span style="color: hsl(120, 100%, 40%);">+   tun_encaps(tun, send_buf, sizeof(send_buf));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Internet-originated IP packet, needs to be sent via GTP towards MS */</span><br><span> static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)</span><br><span> {</span><br><span>@@ -660,6 +719,10 @@</span><br><span>                     iph->version == 4 ?</span><br><span>                         inet_ntop(AF_INET, &iph->saddr, straddr[1], sizeof(straddr[1])) :</span><br><span>                     inet_ntop(AF_INET6, &ip6h->ip6_src, straddr[1], sizeof(straddr[1])));</span><br><span style="color: hsl(120, 100%, 40%);">+         /* TODO: Implement ipv6 */</span><br><span style="color: hsl(120, 100%, 40%);">+            if (iph->version != 4)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             ipv4_host_unreach(tun, pack, len);</span><br><span>   }</span><br><span>    return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-ggsn/+/24237">change 24237</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/+/24237"/><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: Ia2c708feab14bb4cada00b0a90e0cb56d680d1aa </div>
<div style="display:none"> Gerrit-Change-Number: 24237 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: keith <keith@rhizomatica.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>