From 12496dd7db41b3de8a9fe71b843c9378360b33d3 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Mon, 18 Aug 2014 15:41:41 +0200 Subject: gbproxy: Refactor gbprox_patch_raid(), use different RAI types properly Currently gbprox_patch_raid() updates the local MCC/MNC with every BSS originated message, even if the RAI is an 'old' one. This patch separates state updating and patching into 2 functions gbprox_update_current_raid and gbprox_patch_raid. In addition, a field named old_raid_enc is added to gbproxy_parse_context, which is used for 'old RAI' IEs in Attach Requests and RA Update Requests. Only the bssg_raid_enc in BSS originated message is used to update the BSS side 'local' MCC/MNC. Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gb_proxy.c | 116 ++++++++++++++++++++++++++++++++------------ 1 file changed, 85 insertions(+), 31 deletions(-) (limited to 'openbsc/src/gprs/gb_proxy.c') diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 0d738aa38..eb1a699e4 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -409,6 +409,7 @@ struct gbproxy_parse_context { 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_ptimsi; @@ -418,6 +419,7 @@ struct gbproxy_parse_context { int need_decryption; uint32_t tlli; int pdu_type; + int old_raid_matches; }; struct gbproxy_tlli_info *gbprox_find_tlli(struct gbproxy_peer *peer, @@ -821,13 +823,51 @@ static int patching_is_required(struct gbproxy_peer *peer, return need_at_least <= peer->cfg->patch_mode; } -/* patch RA identifier in place, update peer accordingly */ -static void gbprox_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer, - int to_bss, const char *log_text) +/* update peer according to the BSS message */ +static void gbprox_update_current_raid(uint8_t *raid_enc, + struct gbproxy_peer *peer, + const char *log_text) { struct gbproxy_patch_state *state = &peer->patch_state; const int old_local_mcc = state->local_mcc; const int old_local_mnc = state->local_mnc; + struct gprs_ra_id raid; + + if (!raid_enc) + return; + + gsm48_parse_ra(&raid, raid_enc); + + /* save source side MCC/MNC */ + if (!peer->cfg->core_mcc || raid.mcc == peer->cfg->core_mcc) { + state->local_mcc = 0; + } else { + state->local_mcc = raid.mcc; + } + + if (!peer->cfg->core_mnc || raid.mnc == peer->cfg->core_mnc) { + state->local_mnc = 0; + } else { + state->local_mnc = raid.mnc; + } + + if (old_local_mcc != state->local_mcc || + old_local_mnc != state->local_mnc) + LOGP(DGPRS, LOGL_NOTICE, + "Patching RAID %sactivated, msg: %s, " + "local: %d-%d, core: %d-%d\n", + state->local_mcc || state->local_mnc ? + "" : "de", + log_text, + state->local_mcc, state->local_mnc, + peer->cfg->core_mcc, peer->cfg->core_mnc); +} + +/* patch RA identifier in place */ +static void gbprox_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer, + int to_bss, const char *log_text) +{ + struct gbproxy_patch_state *state = &peer->patch_state; int old_mcc; int old_mnc; struct gprs_ra_id raid; @@ -839,20 +879,11 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer, if (!to_bss) { /* BSS -> SGSN */ - /* save BSS side MCC/MNC */ - if (!peer->cfg->core_mcc || raid.mcc == peer->cfg->core_mcc) { - state->local_mcc = 0; - } else { - state->local_mcc = raid.mcc; + if (state->local_mcc) raid.mcc = peer->cfg->core_mcc; - } - if (!peer->cfg->core_mnc || raid.mnc == peer->cfg->core_mnc) { - state->local_mnc = 0; - } else { - state->local_mnc = raid.mnc; + if (state->local_mnc) raid.mnc = peer->cfg->core_mnc; - } } else { /* SGSN -> BSS */ if (state->local_mcc) @@ -862,18 +893,6 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer, raid.mnc = state->local_mnc; } - if (old_local_mcc != state->local_mcc || - old_local_mnc != state->local_mnc) - LOGP(DGPRS, LOGL_NOTICE, - "Patching RAID %sactivated, msg: %s, " - "local: %d-%d, core: %d-%d, to %s\n", - state->local_mcc || state->local_mnc ? - "" : "de", - log_text, - state->local_mcc, state->local_mnc, - peer->cfg->core_mcc, peer->cfg->core_mnc, - to_bss ? "BSS" : "SGSN"); - if (state->local_mcc || state->local_mnc) { enum gbprox_peer_ctr counter = to_bss ? @@ -979,7 +998,7 @@ static int gbprox_parse_gmm_attach_req(uint8_t *data, size_t data_len, if (v_fixed_shift(&data, &data_len, 6, &value) <= 0) return 0; - parse_ctx->raid_enc = value; + parse_ctx->old_raid_enc = value; return 1; } @@ -1069,7 +1088,7 @@ static int gbprox_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len, if (v_fixed_shift(&data, &data_len, 6, &value) <= 0) return 0; - parse_ctx->raid_enc = value; + parse_ctx->old_raid_enc = value; return 1; } @@ -1339,14 +1358,18 @@ static int gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len, return have_patched; if (parse_ctx->raid_enc) { - /* TODO: BSS->SGSN: Only patch if matches original BSSGP, - * don't update internal mapping, patch to invalid if P-TMSI - * unknown. */ gbprox_patch_raid(parse_ctx->raid_enc, peer, parse_ctx->to_bss, parse_ctx->llc_msg_name); have_patched = 1; } + if (parse_ctx->old_raid_enc && parse_ctx->old_raid_matches) { + /* TODO: Patch to invalid if P-TMSI unknown. */ + gbprox_patch_raid(parse_ctx->old_raid_enc, peer, parse_ctx->to_bss, + parse_ctx->llc_msg_name); + have_patched = 1; + } + if (parse_ctx->apn_ie && peer->cfg->core_apn && !parse_ctx->to_bss && @@ -1399,6 +1422,30 @@ static void gbprox_log_parse_context(struct gbproxy_parse_context *parse_ctx, sep = ","; } + if (parse_ctx->bssgp_raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc); + LOGP(DGPRS, LOGL_DEBUG, "%s BSSGP RAID %u-%u-%u-%u", sep, + raid.mcc, raid.mnc, raid.lac, raid.rac); + sep = ","; + } + + if (parse_ctx->raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->raid_enc); + LOGP(DGPRS, LOGL_DEBUG, "%s RAID %u-%u-%u-%u", sep, + raid.mcc, raid.mnc, raid.lac, raid.rac); + sep = ","; + } + + if (parse_ctx->old_raid_enc) { + struct gprs_ra_id raid; + gsm48_parse_ra(&raid, parse_ctx->old_raid_enc); + LOGP(DGPRS, LOGL_DEBUG, "%s old RAID %u-%u-%u-%u", sep, + raid.mcc, raid.mnc, raid.lac, raid.rac); + sep = ","; + } + if (parse_ctx->ptmsi_enc) { uint32_t ptmsi = GSM_RESERVED_TMSI; int ok; @@ -1840,6 +1887,13 @@ static void gbprox_process_bssgp_ul(struct gbproxy_config *cfg, now = time(NULL); + 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_matches = 1; + + gbprox_update_current_raid(parse_ctx.bssgp_raid_enc, peer, + parse_ctx.llc_msg_name); + tlli_info = gbprox_update_state_ul(peer, now, &parse_ctx); gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg), -- cgit v1.2.3