libgtp: Delete PDP context on receiving GTPv1 Error Indication

When a peer GSN receives a GPDU for an unknown PDP context, it sends
a GTP Error Indication.  This Error Indication should be used to
delete the offending PDP context locally.

In GTPv1, the Error Indication contains some mandatory IEs using
which we can look up the PDP context and delete it.

The existing code only dealt with GTPv0 Error Indications which lack
those IEs and use the TEI in the header instead.

Change-Id: I3e843f9ef1d6fd7868cc992e083c0891d16b6da9
Closes: OS#2426
diff --git a/gtp/pdp.c b/gtp/pdp.c
index f297af9..c576a4e 100644
--- a/gtp/pdp.c
+++ b/gtp/pdp.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <inttypes.h>
 #include "pdp.h"
+#include "gtp.h"
 #include "lookupa.h"
 
 /* ***********************************************************
@@ -202,6 +203,24 @@
 	}
 }
 
+/* get a PDP based on the *peer* address + TEI-Data.  Used for matching inbound Error Ind */
+int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn)
+{
+	unsigned int i;
+
+	/* this is O(n) but we don't have (nor want) another hash... */
+	for (i = 0; i < PDP_MAX; i++) {
+		struct pdp_t *candidate = &pdpa[i];
+		if (candidate->inuse && candidate->teid_gn == teid_gn &&
+		    candidate->gsnru.l == sizeof(peer->sin_addr) &&
+		    !memcmp(&peer->sin_addr, candidate->gsnru.v, sizeof(peer->sin_addr))) {
+			*pdp = &pdpa[i];
+			return 0;
+		}
+	}
+	return EOF;
+}
+
 int pdp_tidhash(uint64_t tid)
 {
 	return (lookup(&tid, sizeof(tid), 0) % PDP_MAX);