diff options
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/gprs/gprs_gsup_messages.c | 21 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_sgsn.c | 15 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_subscriber.c | 23 | ||||
-rw-r--r-- | openbsc/src/gprs/sgsn_libgtp.c | 41 | ||||
-rw-r--r-- | openbsc/src/gprs/sgsn_vty.c | 8 |
5 files changed, 99 insertions, 9 deletions
diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index 9d9b6be20..cb14fa114 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -2,6 +2,7 @@ /* * (C) 2014 by Sysmocom s.f.m.c. GmbH + * (C) 2015 by Holger Hans Peter Freyther * All Rights Reserved * * Author: Jacob Erlbeck @@ -93,6 +94,11 @@ static int decode_pdp_info(uint8_t *data, size_t data_len, pdp_info->apn_enc_len = value_len; break; + case GPRS_GSUP_PDP_QOS_IE: + pdp_info->qos_enc = value; + pdp_info->qos_enc_len = value_len; + break; + default: LOGP(DGPRS, LOGL_ERROR, "GSUP IE type %d not expected in PDP info\n", iei); @@ -291,6 +297,12 @@ int gprs_gsup_decode(const uint8_t *const_data, size_t data_len, gsup_msg->auth_tuples[gsup_msg->num_auth_tuples++] = auth_info; break; + + case GPRS_GSUP_MSISDN_IE: + gsup_msg->msisdn_enc = value; + gsup_msg->msisdn_enc_len = value_len; + break; + default: LOGP(DGPRS, LOGL_NOTICE, "GSUP IE type %d unknown\n", iei); @@ -326,6 +338,11 @@ static void encode_pdp_info(struct msgb *msg, enum gprs_gsup_iei iei, pdp_info->apn_enc_len, pdp_info->apn_enc); } + if (pdp_info->qos_enc) { + msgb_tlv_put(msg, GPRS_GSUP_PDP_QOS_IE, + pdp_info->qos_enc_len, pdp_info->qos_enc); + } + /* Update length field */ *len_field = msgb_length(msg) - old_len; } @@ -374,6 +391,10 @@ void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg msgb_tlv_put(msg, GPRS_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); /* specific parts */ + if (gsup_msg->msisdn_enc) + msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE, + gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); + if ((u8 = gsup_msg->cause)) msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8); diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index 94c2b6fbe..711540e03 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -582,6 +582,17 @@ void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx) sgsn_auth_update(mmctx); } +static void insert_qos(struct tlv_parsed *tp, struct sgsn_subscriber_pdp_data *pdp) +{ + tp->lv[OSMO_IE_GSM_SUB_QOS].len = pdp->qos_subscribed_len; + tp->lv[OSMO_IE_GSM_SUB_QOS].val = pdp->qos_subscribed; +} + +/** + * The tlv_parsed tp parameter will be modified to insert a + * OSMO_IE_GSM_SUB_QOS in case the data is available in the + * PDP context handling. + */ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, struct tlv_parsed *tp, enum gsm48_gsm_cause *gsm_cause) @@ -621,6 +632,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, { allow_any_apn = 1; selected_apn_str = ""; + insert_qos(tp, pdp); continue; } if (!llist_empty(&sgsn_apn_ctxts)) { @@ -629,6 +641,7 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, if (apn_ctx == NULL) continue; } + insert_qos(tp, pdp); selected_apn_str = pdp->apn_str; break; } @@ -636,11 +649,13 @@ struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx, /* Check whether the given APN is granted */ llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) { if (strcmp(pdp->apn_str, "*") == 0) { + insert_qos(tp, pdp); selected_apn_str = req_apn_str; allow_any_apn = 1; continue; } if (strcasecmp(pdp->apn_str, req_apn_str) == 0) { + insert_qos(tp, pdp); selected_apn_str = req_apn_str; break; } diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 60f223a0b..c2a3ae184 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -1,6 +1,7 @@ /* MS subscriber data handling */ /* (C) 2014 by sysmocom s.f.m.c. GmbH + * (C) 2015 by Holger Hans Peter Freyther * * All Rights Reserved * @@ -259,9 +260,22 @@ static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id( static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, struct gprs_gsup_message *gsup_msg) { + struct sgsn_subscriber_data *sdata = subscr->sgsn_data; unsigned idx; int rc; + if (gsup_msg->msisdn_enc) { + if (gsup_msg->msisdn_enc_len > sizeof(sdata->msisdn)) { + LOGP(DGPRS, LOGL_ERROR, "MSISDN too long (%zu)\n", + gsup_msg->msisdn_enc_len); + sdata->msisdn_len = 0; + } else { + memcpy(sdata->msisdn, gsup_msg->msisdn_enc, + gsup_msg->msisdn_enc_len); + sdata->msisdn_len = gsup_msg->msisdn_enc_len; + } + } + if (gsup_msg->pdp_info_compl) { rc = gprs_subscr_pdp_data_clear(subscr); if (rc > 0) @@ -281,6 +295,13 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, continue; } + if (pdp_info->qos_enc_len > sizeof(pdp_data->qos_subscribed)) { + LOGGSUBSCRP(LOGL_ERROR, subscr, + "QoS info too long (%zu)\n", + pdp_info->qos_enc_len); + continue; + } + LOGGSUBSCRP(LOGL_INFO, subscr, "Will set PDP info, context id = %zu, APN = %s\n", ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len)); @@ -296,6 +317,8 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr, pdp_data->pdp_type = pdp_info->pdp_type; gprs_apn_to_str(pdp_data->apn_str, pdp_info->apn_enc, pdp_info->apn_enc_len); + memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len); + pdp_data->qos_subscribed_len = pdp_info->qos_enc_len; } } diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c index 455e8af39..eee3ef21c 100644 --- a/openbsc/src/gprs/sgsn_libgtp.c +++ b/openbsc/src/gprs/sgsn_libgtp.c @@ -3,6 +3,7 @@ /* (C) 2010 by Harald Welte <laforge@gnumonks.org> * (C) 2010 by On-Waves + * (C) 2015 by Holger Hans Peter Freyther * All Rights Reserved * * This program is free software; you can redistribute it and/or modify @@ -45,6 +46,7 @@ #include <openbsc/gprs_llc.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/gprs_gmm.h> +#include <openbsc/gsm_subscriber.h> #include <gtp.h> #include <pdp.h> @@ -121,6 +123,8 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, struct sgsn_pdp_ctx *pctx; struct pdp_t *pdp; uint64_t imsi_ui64; + size_t qos_len; + const uint8_t *qos; int rc; LOGP(DGPRS, LOGL_ERROR, "Create PDP Context\n"); @@ -153,8 +157,14 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, /* IMSI, TEID/TEIC, FLLU/FLLC, TID, NSAPI set in pdp_newpdp */ - /* FIXME: MSISDN in BCD format from mmctx */ - //pdp->msisdn.l/.v + /* Put the MSISDN in case we have it */ + if (mmctx->subscr) { + pdp->msisdn.l = mmctx->subscr->sgsn_data->msisdn_len; + if (pdp->msisdn.l > sizeof(pdp->msisdn.v)) + pdp->msisdn.l = sizeof(pdp->msisdn.l); + memcpy(pdp->msisdn.v, mmctx->subscr->sgsn_data->msisdn, + pdp->msisdn.l); + } /* End User Address from GMM requested PDP address */ pdp->eua.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_PDP_ADDR); @@ -180,12 +190,27 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, memcpy(pdp->pco_req.v, TLVP_VAL(tp, GSM48_IE_GSM_PROTO_CONF_OPT), pdp->pco_req.l); - /* QoS options from GMM */ - pdp->qos_req.l = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS); - if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) - pdp->qos_req.l = sizeof(pdp->qos_req.v); - memcpy(pdp->qos_req.v, TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS), - pdp->qos_req.l); + /* QoS options from GMM or remote */ + if (TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS) > 0) { + qos_len = TLVP_LEN(tp, OSMO_IE_GSM_SUB_QOS); + qos = TLVP_VAL(tp, OSMO_IE_GSM_SUB_QOS); + } else { + qos_len = TLVP_LEN(tp, OSMO_IE_GSM_REQ_QOS); + qos = TLVP_VAL(tp, OSMO_IE_GSM_REQ_QOS); + } + + if (qos_len <= 3) { + pdp->qos_req.l = qos_len + 1; + if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) + pdp->qos_req.l = sizeof(pdp->qos_req.v); + pdp->qos_req.v[0] = 0; /* Allocation/Retention policy */ + memcpy(&pdp->qos_req.v[1], qos, pdp->qos_req.l - 1); + } else { + pdp->qos_req.l = qos_len; + if (pdp->qos_req.l > sizeof(pdp->qos_req.v)) + pdp->qos_req.l = sizeof(pdp->qos_req.v); + memcpy(pdp->qos_req.v, qos, pdp->qos_req.l); + } /* SGSN address for control plane */ pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr); diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index 684204a1f..be575d337 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -471,6 +471,11 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, if (subscr->tmsi != GSM_RESERVED_TMSI) vty_out(vty, " TMSI: %08X%s", subscr->tmsi, VTY_NEWLINE); + if (subscr->sgsn_data->msisdn_len > 0) + vty_out(vty, " MSISDN (BCD): %s%s", + osmo_hexdump(subscr->sgsn_data->msisdn, + subscr->sgsn_data->msisdn_len), + VTY_NEWLINE); if (strlen(subscr->equipment.imei) > 0) vty_out(vty, " IMEI: %s%s", subscr->equipment.imei, VTY_NEWLINE); @@ -495,8 +500,9 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr, } llist_for_each_entry(pdp, &subscr->sgsn_data->pdp_list, list) { - vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s'%s", + vty_out(vty, " PDP info: Id: %d, Type: 0x%04x, APN: '%s' QoS: %s%s", pdp->context_id, pdp->pdp_type, pdp->apn_str, + osmo_hexdump(pdp->qos_subscribed, pdp->qos_subscribed_len), VTY_NEWLINE); } |