Change in osmo-ggsn[master]: Implement ICMP response for inactive IP address.

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

keith gerrit-no-reply at lists.osmocom.org
Mon May 17 00:02:07 UTC 2021


keith has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ggsn/+/24237 )


Change subject: Implement ICMP response for inactive IP address.
......................................................................

Implement ICMP response for inactive IP address.

Send ICMP Host Unreachable packets back on the tun device
in reponse to a packet received for an IP address that is
not active in our pool (No active pdp context)

Only IPv4 implemented.

Change-Id: Ia2c708feab14bb4cada00b0a90e0cb56d680d1aa
---
M ggsn/ggsn.c
1 file changed, 63 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-ggsn refs/changes/37/24237/1

diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 0cde543..a0479a1 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -40,6 +40,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
 #include <netinet/ip6.h>
 
 #include <osmocom/core/timer.h>
@@ -584,6 +585,64 @@
 	return 0;
 }
 
+static uint16_t inet_checksum(void *data, int len) {
+
+	int nleft = len;
+	int sum = 0;
+	unsigned short *w = data;
+	unsigned short checksum = 0;
+
+	while (nleft > 1) {
+		sum += *w++;
+		nleft -= 2;
+	}
+	if (nleft == 1){
+		*(unsigned char *)(&checksum) = *(unsigned char *)w;
+		sum += checksum;
+	}
+
+	sum = (sum >> 16) + (sum & 0xffff);
+	sum += (sum >> 16);
+	checksum = ~sum;
+	return (checksum);
+}
+
+/* Generate and send an ICMP HOST UNREACHABLE Packet */
+static void ipv4_host_unreach(struct tun_t *tun, void *pack, unsigned len)
+{
+	char send_buf[sizeof(struct ip) + sizeof(struct icmp) + len];
+	len = len - 20;
+	struct iphdr *iph = (struct iphdr *)pack;
+
+	memset(send_buf, 0, sizeof(send_buf));
+
+	struct ip *ip = (struct ip *)send_buf;
+	struct icmp *icmp = (struct icmp *)(ip + 1);
+
+	ip->ip_v = 4;
+	ip->ip_hl = 5;
+	ip->ip_tos = 0;
+	ip->ip_len = htons(sizeof(send_buf));
+	ip->ip_id = rand();
+	ip->ip_off = 0;
+	ip->ip_ttl = 64;
+	ip->ip_sum = 0;
+	ip->ip_p = IPPROTO_ICMP;
+	ip->ip_src.s_addr = iph->daddr;
+	ip->ip_dst.s_addr = iph->saddr;
+	ip->ip_sum = inet_checksum(ip, sizeof(send_buf));
+
+	icmp->icmp_type = ICMP_DEST_UNREACH;
+	icmp->icmp_code = ICMP_HOST_UNREACH;
+	icmp->icmp_id = 0;
+	icmp->icmp_seq = 0;
+	icmp->icmp_cksum = 0;
+
+	memcpy(send_buf + sizeof(ip) + sizeof(icmp) + 12, pack, len);
+	icmp->icmp_cksum = inet_checksum(icmp, sizeof(icmp) + 12 + len);
+	tun_encaps(tun, send_buf, sizeof(send_buf));
+}
+
 /* Internet-originated IP packet, needs to be sent via GTP towards MS */
 static int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
 {
@@ -660,6 +719,10 @@
  		       iph->version == 4 ?
  		         inet_ntop(AF_INET, &iph->saddr, straddr[1], sizeof(straddr[1])) :
  		         inet_ntop(AF_INET6, &ip6h->ip6_src, straddr[1], sizeof(straddr[1])));
+		/* TODO: Implement ipv6 */
+		if (iph->version != 4)
+			return 0;
+		ipv4_host_unreach(tun, pack, len);
 	}
 	return 0;
 }

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-ggsn/+/24237
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-Change-Id: Ia2c708feab14bb4cada00b0a90e0cb56d680d1aa
Gerrit-Change-Number: 24237
Gerrit-PatchSet: 1
Gerrit-Owner: keith <keith at rhizomatica.org>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210517/b4b2a638/attachment.htm>


More information about the gerrit-log mailing list