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
This commit is contained in:
Jacob Erlbeck 2014-08-18 15:41:41 +02:00 committed by Holger Hans Peter Freyther
parent 311592fc39
commit 12496dd7db
1 changed files with 85 additions and 31 deletions

View File

@ -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),