aboutsummaryrefslogtreecommitdiffstats
path: root/gtp/gtp.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-08-12 23:58:29 +0200
committerHarald Welte <laforge@gnumonks.org>2017-08-13 00:01:35 +0200
commit37d5b1557b4c15b59ab3fe432faa5b7bf7c5a2a3 (patch)
treed7c3b0c178e6b52614cb028361b274f001f0d6b3 /gtp/gtp.c
parent54d082e5e8a3bd45a46dde1162015954b9047f69 (diff)
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
Diffstat (limited to 'gtp/gtp.c')
-rw-r--r--gtp/gtp.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/gtp/gtp.c b/gtp/gtp.c
index a4e8e2b..012aa79 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -2581,17 +2581,44 @@ int gtp_error_ind_resp(struct gsn_t *gsn, int version,
int gtp_error_ind_conf(struct gsn_t *gsn, int version,
struct sockaddr_in *peer, void *pack, unsigned len)
{
+ union gtpie_member *ie[GTPIE_SIZE];
struct pdp_t *pdp;
/* Find the context in question */
- if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
- gsn->err_unknownpdp++;
- GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
- "Unknown PDP context\n");
- return EOF;
+ if (version == 0) {
+ if (pdp_tidget(&pdp, be64toh(((union gtp_packet *)pack)->gtp0.h.tid))) {
+ gsn->err_unknownpdp++;
+ GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
+ "Unknown PDP context\n");
+ return EOF;
+ }
+ } else if (version == 1) {
+ /* we have to look-up based on the *peer* TEID */
+ int hlen = get_hlen(pack);
+ uint32_t teid_gn;
+
+ /* Decode information elements */
+ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
+ gsn->invalid++;
+ GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
+ "Invalid message format\n");
+ return EOF;
+ }
+
+ if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &teid_gn)) {
+ gsn->missing++;
+ GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
+ "Missing mandatory information field\n");
+ return EOF;
+ }
+
+ if (pdp_getgtp1_peer_d(&pdp, peer, teid_gn)) {
+ gsn->err_unknownpdp++;
+ GTP_LOGPKG(LOGL_ERROR, peer, pack, len, "Unknown PDP context\n");
+ return EOF;
+ }
}
- gsn->err_unknownpdp++; /* TODO: Change counter */
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Received Error Indication\n");