[PATCH 3/3] gtp: Handle gtpv1 in gtp_update_pdp_conf() correctly

Daniel Willmann dwilllmann at sysmocom.de
Wed Feb 3 17:53:31 UTC 2016


From: Daniel Willmann <dwillmann at sysmocom.de>

libgtp cannot understand its own update pdp request (in gtp v1)
Only require the conditional and mandatory fields for gtpv1 and not
others.
Refer to 3GPP TS 29.060 Ch. 7.3.4
---
 gtp/gtp.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 112 insertions(+), 32 deletions(-)

diff --git a/gtp/gtp.c b/gtp/gtp.c
index 772ab08..0ef4a54 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -2225,22 +2225,87 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
 	}
 
 	/* Check all conditional information elements */
-	if (GTPCAUSE_ACC_REQ != cause) {
-		if (gsn->cb_conf)
-			gsn->cb_conf(type, cause, pdp, cbp);
-		/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
-		   pdp_freepdp(pdp); */
-		return 0;
-	} else {
-		/* Check for missing conditionary information elements */
-		if (!(gtpie_exist(ie, GTPIE_QOS_PROFILE0, 0) &&
-		      gtpie_exist(ie, GTPIE_REORDER, 0) &&
-		      gtpie_exist(ie, GTPIE_FL_DI, 0) &&
-		      gtpie_exist(ie, GTPIE_FL_C, 0) &&
-		      gtpie_exist(ie, GTPIE_CHARGING_ID, 0) &&
-		      gtpie_exist(ie, GTPIE_EUA, 0) &&
-		      gtpie_exist(ie, GTPIE_GSN_ADDR, 0) &&
-		      gtpie_exist(ie, GTPIE_GSN_ADDR, 1))) {
+	/* TODO: This does not handle GGSN-initiated update responses */
+	if (GTPCAUSE_ACC_REQ == cause) {
+		if (version == 0) {
+			if (gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
+					 &pdp->qos_neg0,
+					 sizeof(pdp->qos_neg0))) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+
+			if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+
+			if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+		}
+
+		if (version == 1) {
+			if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+
+			if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+		}
+
+		if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
+			gsn->missing++;
+			GTP_LOGPKG(LOGL_ERROR, peer, pack,
+				    len,
+				    "Missing conditional information field\n");
+			if (gsn->cb_conf)
+				gsn->cb_conf(type, EOF, pdp, cbp);
+			/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+			   pdp_freepdp(pdp); */
+		}
+
+		if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+				 &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
 			gsn->missing++;
 			GTP_LOGPKG(LOGL_ERROR, peer, pack,
 				    len,
@@ -2252,24 +2317,39 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
 			return EOF;
 		}
 
-		/* Update pdp with new values */
-		gtpie_gettv0(ie, GTPIE_QOS_PROFILE0, 0,
-			     pdp->qos_neg0, sizeof(pdp->qos_neg0));
-		gtpie_gettv1(ie, GTPIE_REORDER, 0, &pdp->reorder);
-		gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru);
-		gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc);
-		gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid);
-		gtpie_gettlv(ie, GTPIE_EUA, 0, &pdp->eua.l,
-			     &pdp->eua.v, sizeof(pdp->eua.v));
-		gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
-			     &pdp->gsnrc.v, sizeof(pdp->gsnrc.v));
-		gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
-			     &pdp->gsnru.v, sizeof(pdp->gsnru.v));
+		if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+				 &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+			gsn->missing++;
+			GTP_LOGPKG(LOGL_ERROR, peer, pack,
+				    len,
+				    "Missing conditional information field\n");
+			if (gsn->cb_conf)
+				gsn->cb_conf(type, EOF, pdp, cbp);
+			/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+			   pdp_freepdp(pdp); */
+			return EOF;
+		}
 
-		if (gsn->cb_conf)
-			gsn->cb_conf(type, cause, pdp, cbp);
-		return 0;	/* Succes */
+		if (version == 1) {
+			if (gtpie_gettlv
+			    (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
+			     &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
+				gsn->missing++;
+				GTP_LOGPKG(LOGL_ERROR, peer,
+					    pack, len,
+					    "Missing conditional information field\n");
+				if (gsn->cb_conf)
+					gsn->cb_conf(type, EOF, pdp, cbp);
+				/*    if (gsn->cb_delete_context) gsn->cb_delete_context(pdp);
+				   pdp_freepdp(pdp); */
+				return EOF;
+			}
+		}
 	}
+
+	if (gsn->cb_conf)
+		gsn->cb_conf(type, cause, pdp, cbp);
+	return 0;	/* Succes */
 }
 
 /* API: Send Delete PDP Context Request */
-- 
2.1.4




More information about the osmocom-net-gprs mailing list