From: Daniel Willmann <dwillmann(a)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