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 | 120 +++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 63 insertions(+), 57 deletions(-)

diff --git a/gtp/gtp.c b/gtp/gtp.c
index 2a6ecd7..12cb492 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -2187,9 +2187,8 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
                gsn->err_unknownpdp++;
                GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
                            "Unknown PDP context: %u\n", get_tei(pack));
-               if (gsn->cb_conf)
-                       gsn->cb_conf(type, EOF, NULL, cbp);
-               return EOF;
+               pdp = NULL;
+               goto err_out;
        }

        /* Register that we have received a valid teic from GGSN */
@@ -2200,23 +2199,12 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version,
                gsn->invalid++;
                GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
                            "Invalid message format\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;
+               goto err_out;
        }

        /* Extract cause value (mandatory) */
        if (gtpie_gettv1(ie, GTPIE_CAUSE, 0, &cause)) {
-               gsn->missing++;
-               GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
-                           "Missing mandatory 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;
+               goto err_missing;
        }

        /* Extract recovery (optional) */
@@ -2226,51 +2214,69 @@ 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))) {
-                       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;
+       /* 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))) {
+                               goto err_missing;
+                       }
+
+                       if (gtpie_gettv2(ie, GTPIE_FL_DI, 0, &pdp->flru)) {
+                               goto err_missing;
+                       }
+
+                       if (gtpie_gettv2(ie, GTPIE_FL_C, 0, &pdp->flrc)) {
+                               goto err_missing;
+                       }
                }

-               /* 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 (version == 1) {
+                       if (gtpie_gettv4(ie, GTPIE_TEI_DI, 0, &pdp->teid_gn)) {
+                               goto err_missing;
+                       }

-               if (gsn->cb_conf)
-                       gsn->cb_conf(type, cause, pdp, cbp);
-               return 0;       /* Succes */
+                       if (gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn)) {
+                               goto err_missing;
+                       }
+               }
+
+               if (gtpie_gettv4(ie, GTPIE_CHARGING_ID, 0, &pdp->cid)) {
+                       goto err_missing;
+               }
+
+               if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 0, &pdp->gsnrc.l,
+                                &pdp->gsnrc.v, sizeof(pdp->gsnrc.v))) {
+                       goto err_missing;
+               }
+
+               if (gtpie_gettlv(ie, GTPIE_GSN_ADDR, 1, &pdp->gsnru.l,
+                                &pdp->gsnru.v, sizeof(pdp->gsnru.v))) {
+                       goto err_missing;
+               }
+
+               if (version == 1) {
+                       if (gtpie_gettlv
+                           (ie, GTPIE_QOS_PROFILE, 0, &pdp->qos_neg.l,
+                            &pdp->qos_neg.v, sizeof(pdp->qos_neg.v))) {
+                               goto err_missing;
+                       }
+               }
        }
+
+       if (gsn->cb_conf)
+               gsn->cb_conf(type, cause, pdp, cbp);
+       return 0;       /* Succes */
+
+err_missing:
+       gsn->missing++;
+       GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
+                   "Missing information field\n");
+err_out:
+       if (gsn->cb_conf)
+               gsn->cb_conf(type, EOF, pdp, cbp);
+       return EOF;
 }

 /* API: Send Delete PDP Context Request */
-- 
2.1.4

Reply via email to