diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2022-12-22 19:49:37 +0100 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2022-12-22 19:49:39 +0100 |
commit | 749ca7c850adcb4ae8cc2dfbac8d95e12773769d (patch) | |
tree | 18238c44384b9f21179902075d0e819555ae60d5 /tests | |
parent | e7ccfdb4aaa44675ee00f6e82b34dabb22bf34b9 (diff) |
Move gprs_gb_parse.[c,h] to tests/sgsn/
That big file is really only used by tests/sgsn/sgsn_test nowadays, so
let's keep it out of osmo-sgsn app code base.
Change-Id: Ia5a639832f52b2f015a2800bd0d94a28d7bc689b
Diffstat (limited to 'tests')
-rw-r--r-- | tests/sgsn/Makefile.am | 6 | ||||
-rw-r--r-- | tests/sgsn/gprs_gb_parse.c | 686 | ||||
-rw-r--r-- | tests/sgsn/gprs_gb_parse.h | 61 | ||||
-rw-r--r-- | tests/sgsn/sgsn_test.c | 3 |
4 files changed, 754 insertions, 2 deletions
diff --git a/tests/sgsn/Makefile.am b/tests/sgsn/Makefile.am index 72a771442..bd8e19c57 100644 --- a/tests/sgsn/Makefile.am +++ b/tests/sgsn/Makefile.am @@ -29,8 +29,13 @@ check_PROGRAMS = \ sgsn_test \ $(NULL) +noinst_HEADERS = \ + gprs_gb_parse.h \ + $(NULL) + sgsn_test_SOURCES = \ sgsn_test.c \ + gprs_gb_parse.c \ $(NULL) sgsn_test_LDFLAGS = \ @@ -66,7 +71,6 @@ sgsn_test_LDADD = \ $(top_builddir)/src/sgsn/sgsn_rim.o \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_llc_parse.o \ - $(top_builddir)/src/gprs/gprs_gb_parse.o \ $(top_builddir)/src/gprs/crc24.o \ $(top_builddir)/src/gprs/sgsn_ares.o \ $(LIBOSMOABIS_LIBS) \ diff --git a/tests/sgsn/gprs_gb_parse.c b/tests/sgsn/gprs_gb_parse.c new file mode 100644 index 000000000..3338911db --- /dev/null +++ b/tests/sgsn/gprs_gb_parse.c @@ -0,0 +1,686 @@ +/* GPRS Gb message parser */ + +/* (C) 2014 by On-Waves + * All Rights Reserved + * + * 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 <osmocom/gsm/gsm48.h> +#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> + +#include "gprs_gb_parse.h" + +#include <osmocom/sgsn/gprs_utils.h> + +#include <osmocom/sgsn/debug.h> + +#include <osmocom/gprs/gprs_bssgp.h> + +static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "ATTACH_REQ"; + + /* Skip MS network capability */ + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + value_len < 1 || value_len > 8) + /* invalid */ + return 0; + + /* Skip Attach type */ + /* Skip Ciphering key sequence number */ + /* Skip DRX parameter */ + if (osmo_shift_v_fixed(&data, &data_len, 3, NULL) < 3) + return 0; + + /* Get Mobile identity */ + if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 || + value_len < 5 || value_len > 8) + /* invalid */ + return 0; + + if (gprs_is_mi_tmsi(value, value_len)) { + parse_ctx->ptmsi_enc = value + 1; + } else if (gprs_is_mi_imsi(value, value_len)) { + parse_ctx->imsi = value; + parse_ctx->imsi_len = value_len; + } + + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + return 0; + + parse_ctx->old_raid_enc = value; + + return 1; +} + +static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "ATTACH_ACK"; + + /* Skip Attach result */ + /* Skip Force to standby */ + /* Skip Periodic RA update timer */ + /* Skip Radio priority for SMS */ + /* Skip Spare half octet */ + if (osmo_shift_v_fixed(&data, &data_len, 3, NULL) < 3) + return 0; + + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + return 0; + + parse_ctx->raid_enc = value; + + /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */ + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); + + /* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */ + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL); + + /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */ + if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, + &value, &value_len) > 0 && + gprs_is_mi_tmsi(value, value_len)) + parse_ctx->new_ptmsi_enc = value + 1; + return 1; +} + +static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + + parse_ctx->llc_msg_name = "ATTACH_REJ"; + + /* GMM cause */ + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + return 0; + + parse_ctx->invalidate_tlli = 1; + + return 1; +} + + +static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + int detach_type; + int power_off; + + parse_ctx->llc_msg_name = "DETACH_REQ"; + + /* Skip spare half octet */ + /* Get Detach type */ + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + /* invalid */ + return 0; + + detach_type = *value & 0x07; + power_off = *value & 0x08 ? 1 : 0; + + if (parse_ctx->to_bss) { + /* Network originated */ + if (detach_type == GPRS_DET_T_MT_REATT_REQ) + parse_ctx->await_reattach = 1; + } else { + /* Mobile originated */ + + if (power_off) + parse_ctx->invalidate_tlli = 1; + + /* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */ + if (osmo_match_shift_tlv(&data, &data_len, + GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0) + { + if (gprs_is_mi_tmsi(value, value_len)) + parse_ctx->ptmsi_enc = value + 1; + } + } + + return 1; +} + +static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + + parse_ctx->llc_msg_name = "RA_UPD_REQ"; + + /* Skip Update type */ + /* Skip GPRS ciphering key sequence number */ + if (osmo_shift_v_fixed(&data, &data_len, 1, NULL) < 1) + return 0; + + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + return 0; + + parse_ctx->old_raid_enc = value; + + return 1; +} + +static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + uint8_t cause; + int force_standby; + + parse_ctx->llc_msg_name = "RA_UPD_REJ"; + + /* GMM cause */ + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + return 0; + + cause = value[0]; + + /* Force to standby, 1/2 */ + /* spare bits, 1/2 */ + if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0) + return 0; + + force_standby = (value[0] & 0x07) == 0x01; + + if (cause == GMM_CAUSE_IMPL_DETACHED && !force_standby) + parse_ctx->await_reattach = 1; + + parse_ctx->invalidate_tlli = 1; + + return 1; +} + +static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "RA_UPD_ACK"; + + /* Skip Force to standby */ + /* Skip Update result */ + /* Skip Periodic RA update timer */ + if (osmo_shift_v_fixed(&data, &data_len, 2, NULL) < 2) + return 0; + + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + return 0; + + parse_ctx->raid_enc = value; + + /* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */ + osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL); + + /* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */ + if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI, + &value, &value_len) > 0 && + gprs_is_mi_tmsi(value, value_len)) + parse_ctx->new_ptmsi_enc = value + 1; + + return 1; +} + +static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "PTMSI_REALL_CMD"; + + LOGP(DLLC, LOGL_NOTICE, + "Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n"); + + /* Allocated P-TMSI */ + if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 && + gprs_is_mi_tmsi(value, value_len)) + parse_ctx->new_ptmsi_enc = value + 1; + + if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0) + return 0; + + parse_ctx->raid_enc = value; + + return 1; +} + +static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "ID_RESP"; + + /* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */ + if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 || + value_len < 1 || value_len > 9) + /* invalid */ + return 0; + + if (gprs_is_mi_tmsi(value, value_len)) { + parse_ctx->ptmsi_enc = value + 1; + } else if (gprs_is_mi_imsi(value, value_len)) { + parse_ctx->imsi = value; + parse_ctx->imsi_len = value_len; + } + + return 1; +} + +static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + ssize_t old_len; + uint8_t *value; + size_t value_len; + + parse_ctx->llc_msg_name = "ACT_PDP_REQ"; + + /* Skip Requested NSAPI */ + /* Skip Requested LLC SAPI */ + if (osmo_shift_v_fixed(&data, &data_len, 2, NULL) < 2) + return 0; + + /* Skip Requested QoS (support 04.08 and 24.008) */ + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + value_len < 4 || value_len > 14) + /* invalid */ + return 0; + + /* Skip Requested PDP address */ + if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 || + value_len < 2 || value_len > 18) + /* invalid */ + return 0; + + /* Access point name */ + old_len = osmo_match_shift_tlv(&data, &data_len, + GSM48_IE_GSM_APN, &value, &value_len); + + if (old_len > 0 && value_len >=1 && value_len <= 100) { + parse_ctx->apn_ie = data - old_len; + parse_ctx->apn_ie_len = old_len; + } + + return 1; +} + +int gprs_gb_parse_dtap(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx) +{ + struct gsm48_hdr *g48h; + uint8_t pdisc; + uint8_t msg_type; + + if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0) + return 0; + + parse_ctx->g48_hdr = g48h; + + pdisc = gsm48_hdr_pdisc(g48h); + if (pdisc != GSM48_PDISC_MM_GPRS && pdisc != GSM48_PDISC_SM_GPRS) + return 1; + + msg_type = gsm48_hdr_msg_type(g48h); + switch (msg_type) { + case GSM48_MT_GMM_ATTACH_REQ: + return gprs_gb_parse_gmm_attach_req(data, data_len, parse_ctx); + + case GSM48_MT_GMM_ATTACH_REJ: + return gprs_gb_parse_gmm_attach_rej(data, data_len, parse_ctx); + + case GSM48_MT_GMM_ATTACH_ACK: + return gprs_gb_parse_gmm_attach_ack(data, data_len, parse_ctx); + + case GSM48_MT_GMM_RA_UPD_REQ: + return gprs_gb_parse_gmm_ra_upd_req(data, data_len, parse_ctx); + + case GSM48_MT_GMM_RA_UPD_REJ: + return gprs_gb_parse_gmm_ra_upd_rej(data, data_len, parse_ctx); + + case GSM48_MT_GMM_RA_UPD_ACK: + return gprs_gb_parse_gmm_ra_upd_ack(data, data_len, parse_ctx); + + case GSM48_MT_GMM_PTMSI_REALL_CMD: + return gprs_gb_parse_gmm_ptmsi_reall_cmd(data, data_len, parse_ctx); + + case GSM48_MT_GSM_ACT_PDP_REQ: + return gprs_gb_parse_gsm_act_pdp_req(data, data_len, parse_ctx); + + case GSM48_MT_GMM_ID_RESP: + return gprs_gb_parse_gmm_id_resp(data, data_len, parse_ctx); + + case GSM48_MT_GMM_DETACH_REQ: + return gprs_gb_parse_gmm_detach_req(data, data_len, parse_ctx); + + case GSM48_MT_GMM_DETACH_ACK: + parse_ctx->llc_msg_name = "DETACH_ACK"; + parse_ctx->invalidate_tlli = 1; + break; + + case GSM48_MT_GSM_DEACT_PDP_REQ: + parse_ctx->llc_msg_name = "DEACT_PDP_REQ"; + break; + + case GSM48_MT_GSM_DEACT_PDP_ACK: + parse_ctx->llc_msg_name = "DEACT_PDP_ACK"; + break; + + default: + LOGP(DLLC, LOGL_NOTICE, + "Unhandled GSM 04.08 message type %s for protocol discriminator %s.\n", + get_value_string(gprs_msgt_gmm_names, msg_type), get_value_string(gsm48_pdisc_names, pdisc)); + break; + }; + + return 1; +} + +int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len, + struct gprs_gb_parse_context *parse_ctx) +{ + struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed; + int rc; + int fcs; + + /* parse LLC */ + rc = gprs_llc_hdr_parse(ghp, llc, llc_len); + gprs_llc_hdr_dump(ghp, NULL); + if (rc != 0) { + LOGP(DLLC, LOGL_NOTICE, "Error during LLC header parsing\n"); + return 0; + } + + fcs = gprs_llc_fcs(llc, ghp->crc_length); + LOGP(DLLC, LOGL_DEBUG, "Got LLC message, CRC: %06x (computed %06x)\n", + ghp->fcs, fcs); + + if (!ghp->data) + return 0; + + if (ghp->sapi != GPRS_SAPI_GMM) + return 1; + + if (ghp->cmd != GPRS_LLC_UI) + return 1; + + if (ghp->is_encrypted) { + parse_ctx->need_decryption = 1; + return 0; + } + + return gprs_gb_parse_dtap(ghp->data, ghp->data_len, parse_ctx); +} + +/*! Determine the TLLI from the given BSSGP message. + * \param[in] bssgp pointer to start of BSSGP header + * \param[in] bssgp_len length of BSSGP message in octets + * \param[out] tlli TLLI (if any) in host byte order + * \returns 1 if TLLI found; 0 if none found; negative on parse error */ +int gprs_gb_parse_tlli(const uint8_t *bssgp, size_t bssgp_len, uint32_t *tlli) +{ + const struct bssgp_normal_hdr *bgph; + uint8_t pdu_type; + + if (bssgp_len < sizeof(struct bssgp_normal_hdr)) + return -EINVAL; + + bgph = (struct bssgp_normal_hdr *)bssgp; + pdu_type = bgph->pdu_type; + + if (pdu_type == BSSGP_PDUT_UL_UNITDATA || + pdu_type == BSSGP_PDUT_DL_UNITDATA) { + const struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *)bssgp; + if (bssgp_len < sizeof(struct bssgp_ud_hdr)) + return -EINVAL; + *tlli = osmo_load32be((const uint8_t *)&budh->tlli); + return 1; + } else { + const uint8_t *data = bgph->data; + size_t data_len = bssgp_len - sizeof(*bgph); + struct tlv_parsed tp; + + if (bssgp_tlv_parse(&tp, data, data_len) < 0) + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_TLLI)) { + *tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI)); + return 1; + } + } + + /* No TLLI present in message */ + return 0; +} + +int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len, + struct gprs_gb_parse_context *parse_ctx) +{ + struct bssgp_normal_hdr *bgph; + struct bssgp_ud_hdr *budh = NULL; + struct tlv_parsed *tp = &parse_ctx->bssgp_tp; + uint8_t pdu_type; + uint8_t *data; + size_t data_len; + int rc; + + if (bssgp_len < sizeof(struct bssgp_normal_hdr)) + return 0; + + bgph = (struct bssgp_normal_hdr *)bssgp; + pdu_type = bgph->pdu_type; + + if (pdu_type == BSSGP_PDUT_UL_UNITDATA || + pdu_type == BSSGP_PDUT_DL_UNITDATA) { + if (bssgp_len < sizeof(struct bssgp_ud_hdr)) + return 0; + budh = (struct bssgp_ud_hdr *)bssgp; + bgph = NULL; + data = budh->data; + data_len = bssgp_len - sizeof(*budh); + } else { + data = bgph->data; + data_len = bssgp_len - sizeof(*bgph); + } + + parse_ctx->pdu_type = pdu_type; + parse_ctx->bud_hdr = budh; + parse_ctx->bgp_hdr = bgph; + parse_ctx->bssgp_data = data; + parse_ctx->bssgp_data_len = data_len; + + if (bssgp_tlv_parse(tp, data, data_len) < 0) + return 0; + + if (budh) + parse_ctx->tlli_enc = (uint8_t *)&budh->tlli; + + if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) + parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA); + + if (TLVP_PRESENT(tp, BSSGP_IE_CELL_ID)) + parse_ctx->bssgp_raid_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_CELL_ID); + + if (TLVP_PRESENT(tp, BSSGP_IE_IMSI)) { + parse_ctx->imsi = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_IMSI); + parse_ctx->imsi_len = TLVP_LEN(tp, BSSGP_IE_IMSI); + } + + if (TLVP_PRESENT(tp, BSSGP_IE_TLLI)) { + if (parse_ctx->tlli_enc) + /* This is TLLI old, don't confuse it with TLLI current */ + parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI); + else + parse_ctx->tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI); + } + + if (TLVP_PRESENT(tp, BSSGP_IE_TMSI) && pdu_type == BSSGP_PDUT_PAGING_PS) + parse_ctx->bssgp_ptmsi_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TMSI); + + if (TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) { + uint8_t *llc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LLC_PDU); + size_t llc_len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU); + + rc = gprs_gb_parse_llc(llc, llc_len, parse_ctx); + if (!rc) + return 0; + + parse_ctx->llc = llc; + parse_ctx->llc_len = llc_len; + } + + if (parse_ctx->tlli_enc) { + uint32_t tmp_tlli; + memcpy(&tmp_tlli, parse_ctx->tlli_enc, sizeof(tmp_tlli)); + parse_ctx->tlli = ntohl(tmp_tlli); + } + + if (parse_ctx->bssgp_raid_enc && parse_ctx->old_raid_enc && + memcmp(parse_ctx->bssgp_raid_enc, parse_ctx->old_raid_enc, 6) != 0) + parse_ctx->old_raid_is_foreign = 1; + + return 1; +} + +void gprs_gb_log_parse_context(int log_level, + struct gprs_gb_parse_context *parse_ctx, + const char *default_msg_name) +{ + const char *msg_name; + const char *sep = ""; + + if (!parse_ctx->tlli_enc && + !parse_ctx->ptmsi_enc && + !parse_ctx->new_ptmsi_enc && + !parse_ctx->bssgp_ptmsi_enc && + !parse_ctx->imsi) + return; + + msg_name = gprs_gb_message_name(parse_ctx, default_msg_name); + + if (parse_ctx->llc_msg_name) + msg_name = parse_ctx->llc_msg_name; + + LOGP(DGPRS, log_level, "%s: Got", msg_name); + + if (parse_ctx->tlli_enc) { + LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli); + sep = ","; + } + + if (parse_ctx->old_tlli_enc) { + LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep, + parse_ctx->old_tlli_enc[0], + parse_ctx->old_tlli_enc[1], + parse_ctx->old_tlli_enc[2], + parse_ctx->old_tlli_enc[3]); + sep = ","; + } + + if (parse_ctx->bssgp_raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc); + LOGPC(DGPRS, log_level, "%s BSSGP RAID %s", sep, osmo_rai_name(&raid)); + sep = ","; + } + + if (parse_ctx->raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->raid_enc); + LOGPC(DGPRS, log_level, "%s RAID %s", sep, osmo_rai_name(&raid)); + sep = ","; + } + + if (parse_ctx->old_raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->old_raid_enc); + LOGPC(DGPRS, log_level, "%s old RAID %s", sep, osmo_rai_name(&raid)); + sep = ","; + } + + if (parse_ctx->bssgp_ptmsi_enc) { + uint32_t ptmsi = GSM_RESERVED_TMSI; + gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi); + LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi); + sep = ","; + } + + if (parse_ctx->ptmsi_enc) { + uint32_t ptmsi = GSM_RESERVED_TMSI; + gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi); + LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi); + sep = ","; + } + + if (parse_ctx->new_ptmsi_enc) { + uint32_t new_ptmsi = GSM_RESERVED_TMSI; + gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi); + LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi); + sep = ","; + } + + if (parse_ctx->imsi) { + struct osmo_mobile_identity mi; + if (osmo_mobile_identity_decode(&mi, parse_ctx->imsi, parse_ctx->imsi_len, false) == 0 + && mi.type == GSM_MI_TYPE_IMSI) { + LOGPC(DGPRS, log_level, "%s IMSI %s", sep, mi.imsi); + sep = ","; + } + } + if (parse_ctx->invalidate_tlli) { + LOGPC(DGPRS, log_level, "%s invalidate", sep); + sep = ","; + } + if (parse_ctx->await_reattach) { + LOGPC(DGPRS, log_level, "%s re-attach", sep); + sep = ","; + } + + LOGPC(DGPRS, log_level, "\n"); +} + +const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx, + const char *default_msg_name) +{ + if (parse_ctx->llc_msg_name) + return parse_ctx->llc_msg_name; + + if (parse_ctx->g48_hdr) + return "GMM"; + + if (parse_ctx->llc) + return "LLC"; + + if (parse_ctx->bud_hdr) + return "BSSGP-UNITDATA"; + + if (parse_ctx->bgp_hdr) + return "BSSGP"; + + return "unknown"; +} diff --git a/tests/sgsn/gprs_gb_parse.h b/tests/sgsn/gprs_gb_parse.h new file mode 100644 index 000000000..58de17f81 --- /dev/null +++ b/tests/sgsn/gprs_gb_parse.h @@ -0,0 +1,61 @@ +#pragma once + +#include <osmocom/sgsn/gprs_llc.h> + +#include <sys/types.h> + +struct gprs_gb_parse_context { + /* Pointer to protocol specific parts */ + struct gsm48_hdr *g48_hdr; + struct bssgp_normal_hdr *bgp_hdr; + struct bssgp_ud_hdr *bud_hdr; + uint8_t *bssgp_data; + size_t bssgp_data_len; + uint8_t *llc; + size_t llc_len; + + /* Extracted information */ + struct gprs_llc_hdr_parsed llc_hdr_parsed; + struct tlv_parsed bssgp_tp; + int to_bss; + uint8_t *tlli_enc; + uint8_t *old_tlli_enc; + uint8_t *imsi; + size_t imsi_len; + uint8_t *apn_ie; + size_t apn_ie_len; + uint8_t *ptmsi_enc; + uint8_t *new_ptmsi_enc; + uint8_t *raid_enc; + uint8_t *old_raid_enc; + uint8_t *bssgp_raid_enc; + uint8_t *bssgp_ptmsi_enc; + + /* General info */ + const char *llc_msg_name; + int invalidate_tlli; + int await_reattach; + int need_decryption; + uint32_t tlli; + int pdu_type; + int old_raid_is_foreign; + int peer_nsei; +}; + +int gprs_gb_parse_dtap(uint8_t *data, size_t data_len, + struct gprs_gb_parse_context *parse_ctx); + +int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len, + struct gprs_gb_parse_context *parse_ctx); + +int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len, + struct gprs_gb_parse_context *parse_ctx); + +int gprs_gb_parse_tlli(const uint8_t *bssgp, size_t bssgp_len, uint32_t *tlli); + +const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx, + const char *default_msg_name); + +void gprs_gb_log_parse_context(int log_level, + struct gprs_gb_parse_context *parse_ctx, + const char *default_msg_name); diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c index 2c41e8ea3..a09f1a5b6 100644 --- a/tests/sgsn/sgsn_test.c +++ b/tests/sgsn/sgsn_test.c @@ -27,7 +27,6 @@ #include <osmocom/gsm/gsup.h> #include <osmocom/gsupclient/gsup_client.h> #include <osmocom/sgsn/gprs_utils.h> -#include <osmocom/sgsn/gprs_gb_parse.h> #include <osmocom/sgsn/gprs_gmm_fsm.h> #include <osmocom/gprs/gprs_bssgp.h> @@ -42,6 +41,8 @@ #include <stdio.h> +#include "gprs_gb_parse.h" + void *tall_sgsn_ctx; static struct sgsn_instance sgsn_inst = { .config_file = "osmo_sgsn.cfg", |