aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/gprs/gprs_gsup_messages.c21
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c15
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c23
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c41
-rw-r--r--openbsc/src/gprs/sgsn_vty.c8
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);
}