diff options
author | Harald Welte <laforge@gnumonks.org> | 2016-04-25 19:07:34 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-04-29 13:10:37 +0200 |
commit | 23d77d56ea47bbb971bf2fc5d93d6ae2d7d30f03 (patch) | |
tree | 3b8eabec7b1cbc05ba86e1ba265c005f3bc87be4 /openbsc/src | |
parent | 50f1c0af567423b6ade9a84aaa5197ecf6237819 (diff) |
Move osmo_gsup_messages.[ch] to libosmocore
This requires the corresponding commit in libosmocore.
Diffstat (limited to 'openbsc/src')
-rw-r--r-- | openbsc/src/gprs/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/gprs/gprs_subscriber.c | 2 | ||||
-rw-r--r-- | openbsc/src/gprs/osmo_gsup_messages.c | 472 |
3 files changed, 2 insertions, 474 deletions
diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 7889d5fd9..6dc7e1634 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -26,7 +26,7 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ - osmo_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ + gprs_utils.c gprs_gsup_client.c \ sgsn_cdr.c sgsn_ares.c \ oap.c oap_messages.c osmo_sgsn_LDADD = \ diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index d9bc10a18..f5a5937a0 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -21,13 +21,13 @@ */ #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> +#include <osmocom/gsm/gsup.h> #include <openbsc/gsm_subscriber.h> #include <openbsc/gprs_gsup_client.h> #include <openbsc/sgsn.h> #include <openbsc/gprs_sgsn.h> #include <openbsc/gprs_gmm.h> -#include <openbsc/osmo_gsup_messages.h> #include <openbsc/gprs_utils.h> #include <openbsc/debug.h> diff --git a/openbsc/src/gprs/osmo_gsup_messages.c b/openbsc/src/gprs/osmo_gsup_messages.c deleted file mode 100644 index 430cba750..000000000 --- a/openbsc/src/gprs/osmo_gsup_messages.c +++ /dev/null @@ -1,472 +0,0 @@ -/* Osmocom Subscriber Update Protocol message encoder/decoder */ - -/* - * (C) 2014 by Sysmocom s.f.m.c. GmbH - * (C) 2015 by Holger Hans Peter Freyther - * (C) 2016 by Harald Welte <laforge@gnumonks.org> - * All Rights Reserved - * - * Author: Jacob Erlbeck - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#include <openbsc/osmo_gsup_messages.h> - -#include <openbsc/debug.h> -#include <openbsc/utils.h> - -#include <osmocom/gsm/tlv.h> -#include <osmocom/core/msgb.h> -#include <osmocom/gsm/gsm48_ie.h> - -#include <stdint.h> - -static int decode_pdp_info(uint8_t *data, size_t data_len, - struct osmo_gsup_pdp_info *pdp_info) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - - /* specific parts */ - while (data_len > 0) { - enum osmo_gsup_iei iei; - - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_PDP_CONTEXT_ID_IE: - pdp_info->context_id = decode_big_endian(value, value_len); - break; - - case OSMO_GSUP_PDP_TYPE_IE: - pdp_info->pdp_type = - decode_big_endian(value, value_len) & 0x0fff; - break; - - case OSMO_GSUP_ACCESS_POINT_NAME_IE: - pdp_info->apn_enc = value; - pdp_info->apn_enc_len = value_len; - break; - - case OSMO_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); - continue; - } - } - - return 0; -} - -static int decode_auth_info(uint8_t *data, size_t data_len, - struct osmo_auth_vector *auth_vector) -{ - int rc; - uint8_t tag; - uint8_t *value; - size_t value_len; - enum osmo_gsup_iei iei; - uint8_t presence = 0; - - /* specific parts */ - while (data_len > 0) { - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_RAND_IE: - if (value_len != sizeof(auth_vector->rand)) - goto parse_error; - - memcpy(auth_vector->rand, value, value_len); - presence |= (1 << 0); - break; - - case OSMO_GSUP_SRES_IE: - if (value_len != sizeof(auth_vector->sres)) - goto parse_error; - - memcpy(auth_vector->sres, value, value_len); - presence |= (1 << 1); - break; - - case OSMO_GSUP_KC_IE: - if (value_len != sizeof(auth_vector->kc)) - goto parse_error; - - memcpy(auth_vector->kc, value, value_len); - presence |= (1 << 2); - break; - - case OSMO_GSUP_IK_IE: - if (value_len != sizeof(auth_vector->ik)) - goto parse_error; - memcpy(auth_vector->ik, value, value_len); - presence |= (1 << 4); - break; - - case OSMO_GSUP_CK_IE: - if (value_len != sizeof(auth_vector->ck)) - goto parse_error; - memcpy(auth_vector->ck, value, value_len); - presence |= (1 << 5); - break; - - case OSMO_GSUP_AUTN_IE: - if (value_len != sizeof(auth_vector->autn)) - goto parse_error; - memcpy(auth_vector->autn, value, value_len); - presence |= (1 << 6); - break; - case OSMO_GSUP_RES_IE: - if (value_len > sizeof(auth_vector->res)) - goto parse_error; - memcpy(auth_vector->res, value, value_len); - auth_vector->res_len = value_len; - presence |= (1 << 7); - break; - - default: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d not expected in PDP info\n", iei); - continue; - } - } - - if (presence & 0x07) - auth_vector->auth_types |= OSMO_AUTH_TYPE_GSM; - if (presence & 0xf0) - auth_vector->auth_types |= OSMO_AUTH_TYPE_UMTS; - - return 0; - -parse_error: - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len); - - return -1; -} - -/*! Decode (parse) a GSUP message - * \param[in] const_data input data to be parsed - * \param[in] data_len length of input (\a const_data) - * \param[out] gsup_msg callee-allocated output data structure - * \returns 0 on success; negative otherwise - */ -int osmo_gsup_decode(const uint8_t *const_data, size_t data_len, - struct osmo_gsup_message *gsup_msg) -{ - int rc; - uint8_t tag; - /* the shift/match functions expect non-const pointers, but we'll - * either copy the data or cast pointers back to const before returning - * them - */ - uint8_t *data = (uint8_t *)const_data; - uint8_t *value; - size_t value_len; - static const struct osmo_gsup_pdp_info empty_pdp_info = {0}; - static const struct osmo_auth_vector empty_auth_info = {0}; - static const struct osmo_gsup_message empty_gsup_message = {0}; - - *gsup_msg = empty_gsup_message; - - /* generic part */ - rc = osmo_shift_v_fixed(&data, &data_len, 1, &value); - if (rc < 0) - return -GMM_CAUSE_INV_MAND_INFO; - - gsup_msg->message_type = decode_big_endian(value, 1); - - rc = osmo_match_shift_tlv(&data, &data_len, OSMO_GSUP_IMSI_IE, - &value, &value_len); - - if (rc <= 0) - return -GMM_CAUSE_INV_MAND_INFO; - - if (value_len * 2 + 1 > sizeof(gsup_msg->imsi)) - return -GMM_CAUSE_INV_MAND_INFO; - - /* Note that gsm48_decode_bcd_number expects the number of encoded IMSI - * octets in the first octet. By coincidence (the TLV encoding) the byte - * before the value part already contains this length so we can use it - * here. - */ - OSMO_ASSERT(value[-1] == value_len); - gsm48_decode_bcd_number(gsup_msg->imsi, sizeof(gsup_msg->imsi), - value - 1, 0); - - /* specific parts */ - while (data_len > 0) { - enum osmo_gsup_iei iei; - struct osmo_gsup_pdp_info pdp_info; - struct osmo_auth_vector auth_info; - - rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len); - if (rc < 0) - return -GMM_CAUSE_PROTO_ERR_UNSPEC; - - iei = tag; - - switch (iei) { - case OSMO_GSUP_IMSI_IE: - case OSMO_GSUP_PDP_TYPE_IE: - case OSMO_GSUP_ACCESS_POINT_NAME_IE: - case OSMO_GSUP_RAND_IE: - case OSMO_GSUP_SRES_IE: - case OSMO_GSUP_KC_IE: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d not expected (ignored)\n", iei); - continue; - - case OSMO_GSUP_CAUSE_IE: - gsup_msg->cause = decode_big_endian(value, value_len); - break; - - case OSMO_GSUP_CANCEL_TYPE_IE: - gsup_msg->cancel_type = - decode_big_endian(value, value_len) + 1; - break; - - case OSMO_GSUP_PDP_INFO_COMPL_IE: - gsup_msg->pdp_info_compl = 1; - break; - - case OSMO_GSUP_FREEZE_PTMSI_IE: - gsup_msg->freeze_ptmsi = 1; - break; - - case OSMO_GSUP_PDP_CONTEXT_ID_IE: - /* When these IE appear in the top-level part of the - * message, they are used by Delete Subscr Info to delete - * single entries. We don't have an extra list for - * these but use the PDP info list instead */ - - /* fall through */ - - case OSMO_GSUP_PDP_INFO_IE: - if (gsup_msg->num_pdp_infos >= OSMO_GSUP_MAX_NUM_PDP_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (PDP_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_COND_IE_ERR; - } - - pdp_info = empty_pdp_info; - - if (iei == OSMO_GSUP_PDP_INFO_IE) { - rc = decode_pdp_info(value, value_len, &pdp_info); - if (rc < 0) - return rc; - pdp_info.have_info = 1; - } else { - pdp_info.context_id = - decode_big_endian(value, value_len); - } - - gsup_msg->pdp_infos[gsup_msg->num_pdp_infos++] = - pdp_info; - break; - - case OSMO_GSUP_AUTH_TUPLE_IE: - if (gsup_msg->num_auth_vectors >= OSMO_GSUP_MAX_NUM_AUTH_INFO) { - LOGP(DGPRS, LOGL_ERROR, - "GSUP IE type %d (AUTH_INFO) max exceeded\n", - iei); - return -GMM_CAUSE_INV_MAND_INFO; - } - - auth_info = empty_auth_info; - - rc = decode_auth_info(value, value_len, &auth_info); - if (rc < 0) - return rc; - - gsup_msg->auth_vectors[gsup_msg->num_auth_vectors++] = - auth_info; - break; - - case OSMO_GSUP_AUTS_IE: - if (value_len != 16) { - LOGP(DGPRS, LOGL_ERROR, - "AUTS length != 16 received\n"); - return -GMM_CAUSE_COND_IE_ERR; - } - gsup_msg->auts = value; - break; - - case OSMO_GSUP_MSISDN_IE: - gsup_msg->msisdn_enc = value; - gsup_msg->msisdn_enc_len = value_len; - break; - - case OSMO_GSUP_HLR_NUMBER_IE: - gsup_msg->hlr_enc = value; - gsup_msg->hlr_enc_len = value_len; - break; - - default: - LOGP(DGPRS, LOGL_NOTICE, - "GSUP IE type %d unknown\n", iei); - continue; - } - } - - return 0; -} - -static void encode_pdp_info(struct msgb *msg, enum osmo_gsup_iei iei, - const struct osmo_gsup_pdp_info *pdp_info) -{ - uint8_t *len_field; - size_t old_len; - uint8_t u8; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - u8 = pdp_info->context_id; - msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8); - - if (pdp_info->pdp_type) { - msgb_tlv_put(msg, OSMO_GSUP_PDP_TYPE_IE, - OSMO_GSUP_PDP_TYPE_SIZE, - encode_big_endian(pdp_info->pdp_type | 0xf000, - OSMO_GSUP_PDP_TYPE_SIZE)); - } - - if (pdp_info->apn_enc) { - msgb_tlv_put(msg, OSMO_GSUP_ACCESS_POINT_NAME_IE, - pdp_info->apn_enc_len, pdp_info->apn_enc); - } - - if (pdp_info->qos_enc) { - msgb_tlv_put(msg, OSMO_GSUP_PDP_QOS_IE, - pdp_info->qos_enc_len, pdp_info->qos_enc); - } - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -static void encode_auth_info(struct msgb *msg, enum osmo_gsup_iei iei, - const struct osmo_auth_vector *auth_vector) -{ - uint8_t *len_field; - size_t old_len; - - len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1; - old_len = msgb_length(msg); - - msgb_tlv_put(msg, OSMO_GSUP_RAND_IE, - sizeof(auth_vector->rand), auth_vector->rand); - - msgb_tlv_put(msg, OSMO_GSUP_SRES_IE, - sizeof(auth_vector->sres), auth_vector->sres); - - msgb_tlv_put(msg, OSMO_GSUP_KC_IE, - sizeof(auth_vector->kc), auth_vector->kc); - - /* Update length field */ - *len_field = msgb_length(msg) - old_len; -} - -/*! Encode a GSUP message - * \param[out] msg message buffer to which encoded message is written - * \param[in] gsup_msg \ref osmo_gsup_message data to be encoded - */ -void osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) -{ - uint8_t u8; - int idx; - uint8_t bcd_buf[GSM48_MI_SIZE] = {0}; - size_t bcd_len; - - /* generic part */ - OSMO_ASSERT(gsup_msg->message_type); - msgb_v_put(msg, gsup_msg->message_type); - - bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0, - gsup_msg->imsi); - - OSMO_ASSERT(bcd_len > 1); - - /* Note that gsm48_encode_bcd_number puts the length into the first - * octet. Since msgb_tlv_put will add this length byte, we'll have to - * skip it */ - msgb_tlv_put(msg, OSMO_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]); - - /* specific parts */ - if (gsup_msg->msisdn_enc) - msgb_tlv_put(msg, OSMO_GSUP_MSISDN_IE, - gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc); - if (gsup_msg->hlr_enc) - msgb_tlv_put(msg, OSMO_GSUP_HLR_NUMBER_IE, - gsup_msg->hlr_enc_len, gsup_msg->hlr_enc); - - if ((u8 = gsup_msg->cause)) - msgb_tlv_put(msg, OSMO_GSUP_CAUSE_IE, sizeof(u8), &u8); - - if ((u8 = gsup_msg->cancel_type)) { - u8 -= 1; - msgb_tlv_put(msg, OSMO_GSUP_CANCEL_TYPE_IE, sizeof(u8), &u8); - } - - if (gsup_msg->pdp_info_compl) - msgb_tlv_put(msg, OSMO_GSUP_PDP_INFO_COMPL_IE, 0, &u8); - - if (gsup_msg->freeze_ptmsi) - msgb_tlv_put(msg, OSMO_GSUP_FREEZE_PTMSI_IE, 0, &u8); - - for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) { - const struct osmo_gsup_pdp_info *pdp_info; - - pdp_info = &gsup_msg->pdp_infos[idx]; - - if (pdp_info->context_id == 0) - continue; - - if (pdp_info->have_info) { - encode_pdp_info(msg, OSMO_GSUP_PDP_INFO_IE, pdp_info); - } else { - u8 = pdp_info->context_id; - msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, - sizeof(u8), &u8); - } - } - - for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) { - const struct osmo_auth_vector *auth_vector; - - auth_vector = &gsup_msg->auth_vectors[idx]; - - encode_auth_info(msg, OSMO_GSUP_AUTH_TUPLE_IE, auth_vector); - } -} |