gbproxy: Track SGSN and BSS TLLI/PTMSI separately
This patch separates BSS side from SGSN side TLLI/PTMSI tracking. When TLLI/PTMSI patching is not enabled, the corresponding states shall be identical. The TLLI/PTMSI state has been moved into the struct gbproxy_tlli_state and is used twice in gbproxy_tlli_info. Since the state handling for uplink and downlink messages is diverging, gbprox_update_state() is replaced by two functions gbprox_update_state_dl/gbprox_update_state_ul and gbprox_process_bssgp_message() is replaced by gbprox_process_bssgp_dl/gbprox_process_bssgp_ul. Sponsored-by: On-Waves ehf
This commit is contained in:
parent
c53f2a6961
commit
9057bc3c72
|
@ -44,6 +44,7 @@ struct gbproxy_config {
|
|||
enum gbproxy_patch_mode patch_mode;
|
||||
int tlli_max_age;
|
||||
int tlli_max_len;
|
||||
int patch_ptmsi;
|
||||
|
||||
/* IMSI checking/matching */
|
||||
int check_imsi;
|
||||
|
@ -81,17 +82,26 @@ struct gbproxy_peer {
|
|||
struct gbproxy_patch_state patch_state;
|
||||
};
|
||||
|
||||
struct gbproxy_tlli_state {
|
||||
uint32_t current;
|
||||
uint32_t assigned;
|
||||
int bss_validated;
|
||||
int net_validated;
|
||||
|
||||
uint32_t ptmsi;
|
||||
};
|
||||
|
||||
struct gbproxy_tlli_info {
|
||||
struct llist_head list;
|
||||
|
||||
uint32_t tlli;
|
||||
uint32_t assigned_tlli;
|
||||
int bss_validated;
|
||||
int net_validated;
|
||||
struct gbproxy_tlli_state tlli;
|
||||
struct gbproxy_tlli_state sgsn_tlli;
|
||||
|
||||
time_t timestamp;
|
||||
uint8_t *mi_data;
|
||||
size_t mi_data_len;
|
||||
|
||||
|
||||
int enable_patching;
|
||||
};
|
||||
|
||||
|
@ -132,6 +142,9 @@ struct gbproxy_tlli_info *gbprox_find_tlli(struct gbproxy_peer *peer,
|
|||
struct gbproxy_tlli_info *gbprox_find_tlli_by_mi(struct gbproxy_peer *peer,
|
||||
const uint8_t *mi_data,
|
||||
size_t mi_data_len);
|
||||
struct gbproxy_tlli_info *gbprox_find_tlli_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli);
|
||||
struct gbproxy_tlli_info *gbprox_register_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli,
|
||||
const uint8_t *imsi, size_t imsi_len, time_t now);
|
||||
|
|
|
@ -427,7 +427,23 @@ struct gbproxy_tlli_info *gbprox_find_tlli(struct gbproxy_peer *peer,
|
|||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
|
||||
if (tlli_info->tlli == tlli || tlli_info->assigned_tlli == tlli)
|
||||
if (tlli_info->tlli.current == tlli ||
|
||||
tlli_info->tlli.assigned == tlli)
|
||||
return tlli_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbprox_find_tlli_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
|
||||
if (tlli_info->sgsn_tlli.current == tlli ||
|
||||
tlli_info->sgsn_tlli.assigned == tlli)
|
||||
return tlli_info;
|
||||
|
||||
return NULL;
|
||||
|
@ -583,7 +599,7 @@ int gbprox_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
|
|||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, length %d, max_len exceeded)\n",
|
||||
tlli_info->tlli, state->enabled_tllis_count);
|
||||
tlli_info->tlli.current, state->enabled_tllis_count);
|
||||
|
||||
gbprox_delete_tlli(peer, tlli_info);
|
||||
deleted_count += 1;
|
||||
|
@ -605,7 +621,7 @@ int gbprox_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
|
|||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, age %d, max_age exceeded)\n",
|
||||
tlli_info->tlli, (int)age);
|
||||
tlli_info->tlli.current, (int)age);
|
||||
|
||||
gbprox_delete_tlli(peer, tlli_info);
|
||||
deleted_count += 1;
|
||||
|
@ -622,8 +638,9 @@ static struct gbproxy_tlli_info *gbprox_get_detached_tlli_info(
|
|||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!tlli_info) {
|
||||
/* move this into an tlli_alloc function */
|
||||
tlli_info = talloc_zero(peer, struct gbproxy_tlli_info);
|
||||
tlli_info->tlli = tlli;
|
||||
tlli_info->tlli.current = tlli;
|
||||
} else {
|
||||
llist_del(&tlli_info->list);
|
||||
OSMO_ASSERT(state->enabled_tllis_count > 0);
|
||||
|
@ -649,57 +666,58 @@ static void gbprox_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
|
|||
memcpy(tlli_info->mi_data, imsi, imsi_len);
|
||||
}
|
||||
|
||||
void gbprox_reassign_tlli(struct gbproxy_tlli_info *tlli_info,
|
||||
void gbprox_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
struct gbproxy_peer *peer, uint32_t new_tlli)
|
||||
{
|
||||
if (new_tlli == tlli_info->tlli)
|
||||
if (new_tlli == tlli_state->current)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI has been reassigned from %08x to %08x\n",
|
||||
tlli_info->tlli, new_tlli);
|
||||
tlli_state->current, new_tlli);
|
||||
|
||||
/* Remember assigned TLLI */
|
||||
tlli_info->assigned_tlli = new_tlli;
|
||||
tlli_info->bss_validated = 0;
|
||||
tlli_info->net_validated = 0;
|
||||
tlli_state->assigned = new_tlli;
|
||||
tlli_state->bss_validated = 0;
|
||||
tlli_state->net_validated = 0;
|
||||
}
|
||||
|
||||
static void gbprox_validate_tlli(struct gbproxy_tlli_info *tlli_info,
|
||||
static void gbprox_validate_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
uint32_t tlli, int to_bss)
|
||||
{
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"%s({tlli = %08x, assigned_tlli = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
|
||||
__func__, tlli_info->tlli, tlli_info->assigned_tlli,
|
||||
tlli_info->net_validated, tlli_info->bss_validated, tlli);
|
||||
"%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
|
||||
__func__, tlli_state->current, tlli_state->assigned,
|
||||
tlli_state->net_validated, tlli_state->bss_validated, tlli);
|
||||
|
||||
if (!tlli_info->assigned_tlli || tlli_info->assigned_tlli != tlli)
|
||||
if (!tlli_state->assigned || tlli_state->assigned != tlli)
|
||||
return;
|
||||
|
||||
/* TODO: Is this ok? Check spec */
|
||||
if (gprs_tlli_type(tlli) != TLLI_LOCAL)
|
||||
return;
|
||||
|
||||
/* See GSM 04.08, 4.7.1.5 */
|
||||
if (to_bss)
|
||||
tlli_info->net_validated = 1;
|
||||
tlli_state->net_validated = 1;
|
||||
else
|
||||
tlli_info->bss_validated = 1;
|
||||
tlli_state->bss_validated = 1;
|
||||
|
||||
if (!tlli_info->bss_validated || !tlli_info->net_validated)
|
||||
if (!tlli_state->bss_validated || !tlli_state->net_validated)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI %08x has been validated (was %08x)\n",
|
||||
tlli_info->assigned_tlli, tlli_info->tlli);
|
||||
tlli_state->assigned, tlli_state->current);
|
||||
|
||||
tlli_info->tlli = tlli;
|
||||
tlli_info->assigned_tlli = 0;
|
||||
tlli_state->current = tlli;
|
||||
tlli_state->assigned = 0;
|
||||
}
|
||||
|
||||
void gbprox_touch_tlli(struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info, time_t now)
|
||||
{
|
||||
gbprox_get_detached_tlli_info(peer, tlli_info, tlli_info->tlli);
|
||||
gbprox_get_detached_tlli_info(peer, tlli_info, 0);
|
||||
gbprox_attach_tlli_info(peer, now, tlli_info);
|
||||
}
|
||||
|
||||
|
@ -727,8 +745,8 @@ struct gbproxy_tlli_info *gbprox_register_tlli(
|
|||
/* TLLI has changed somehow, adjust it */
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI has changed from %08x to %08x\n",
|
||||
tlli_info->tlli, tlli);
|
||||
tlli_info->tlli = tlli;
|
||||
tlli_info->tlli.current, tlli);
|
||||
tlli_info->tlli.current = tlli;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1313,6 +1331,9 @@ 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;
|
||||
|
@ -1406,15 +1427,25 @@ static void gbprox_log_parse_context(struct gbproxy_parse_context *parse_ctx,
|
|||
LOGP(DGPRS, LOGL_DEBUG, "\n");
|
||||
}
|
||||
|
||||
static struct gbproxy_tlli_info *gbprox_update_state(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
static uint32_t gbprox_make_bss_ptmsi(struct gbproxy_peer *peer,
|
||||
uint32_t sgsn_ptmsi)
|
||||
{
|
||||
return sgsn_ptmsi;
|
||||
}
|
||||
|
||||
static uint32_t gbprox_make_sgsn_tlli(struct gbproxy_peer *peer,
|
||||
uint32_t bss_tlli)
|
||||
{
|
||||
return bss_tlli;
|
||||
}
|
||||
|
||||
static struct gbproxy_tlli_info *gbprox_update_state_ul(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gbproxy_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
if (!peer->cfg->check_imsi)
|
||||
return NULL;
|
||||
|
||||
if (parse_ctx->tlli_enc)
|
||||
tlli_info = gbprox_find_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
|
@ -1424,6 +1455,69 @@ static struct gbproxy_tlli_info *gbprox_update_state(
|
|||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REQS]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gbprox_log_parse_context(parse_ctx, "BSSGP");
|
||||
|
||||
if (parse_ctx->tlli_enc && parse_ctx->llc) {
|
||||
uint32_t sgsn_tlli;
|
||||
if (!tlli_info) {
|
||||
tlli_info =
|
||||
gbprox_register_tlli(peer, parse_ctx->tlli,
|
||||
parse_ctx->imsi,
|
||||
parse_ctx->imsi_len, now);
|
||||
/* Setup TLLIs */
|
||||
sgsn_tlli = gbprox_make_sgsn_tlli(peer, parse_ctx->tlli);
|
||||
tlli_info->sgsn_tlli.current = sgsn_tlli;
|
||||
} else {
|
||||
sgsn_tlli = tlli_info->sgsn_tlli.assigned;
|
||||
if (!sgsn_tlli)
|
||||
sgsn_tlli = tlli_info->sgsn_tlli.current;
|
||||
if (!sgsn_tlli) {
|
||||
sgsn_tlli = gbprox_make_sgsn_tlli(peer,
|
||||
parse_ctx->tlli);
|
||||
}
|
||||
|
||||
gbprox_validate_tlli(&tlli_info->tlli,
|
||||
parse_ctx->tlli, 0);
|
||||
gbprox_validate_tlli(&tlli_info->sgsn_tlli,
|
||||
sgsn_tlli, 0);
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
} else if (tlli_info) {
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi && tlli_info && tlli_info->mi_data_len == 0) {
|
||||
int enable_patching;
|
||||
gbprox_update_tlli_info(tlli_info,
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
/* Check, whether the IMSI matches */
|
||||
enable_patching = gbprox_check_imsi(peer, parse_ctx->imsi,
|
||||
parse_ctx->imsi_len);
|
||||
if (enable_patching >= 0)
|
||||
tlli_info->enable_patching = enable_patching;
|
||||
}
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
static struct gbproxy_tlli_info *gbprox_update_state_dl(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gbproxy_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
if (parse_ctx->tlli_enc)
|
||||
tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
if (parse_ctx->g48_hdr) {
|
||||
switch (parse_ctx->g48_hdr->msg_type) {
|
||||
case GSM48_MT_GMM_ATTACH_REJ:
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REJS]);
|
||||
break;
|
||||
|
@ -1435,43 +1529,69 @@ static struct gbproxy_tlli_info *gbprox_update_state(
|
|||
|
||||
gbprox_log_parse_context(parse_ctx, "BSSGP");
|
||||
|
||||
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc &&
|
||||
parse_ctx->to_bss) {
|
||||
if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc) {
|
||||
/* A new PTMSI has been signaled in the message,
|
||||
* register new TLLI */
|
||||
uint32_t new_ptmsi;
|
||||
uint32_t new_tlli;
|
||||
uint32_t new_sgsn_ptmsi;
|
||||
uint32_t new_sgsn_tlli;
|
||||
uint32_t new_bss_ptmsi;
|
||||
uint32_t new_bss_tlli = 0;
|
||||
if (!parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
|
||||
&new_ptmsi)) {
|
||||
&new_sgsn_ptmsi)) {
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"Failed to parse new TLLI/PTMSI (current is %08x)\n",
|
||||
parse_ctx->tlli);
|
||||
return tlli_info;
|
||||
}
|
||||
new_tlli = gprs_tmsi2tlli(new_ptmsi, TLLI_LOCAL);
|
||||
new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
|
||||
new_bss_ptmsi = gbprox_make_bss_ptmsi(peer, new_sgsn_ptmsi);
|
||||
if (new_bss_ptmsi != GSM_RESERVED_TMSI)
|
||||
new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Got new TLLI/PTMSI %08x/%08x (current is %08x)\n",
|
||||
new_tlli, new_ptmsi, parse_ctx->tlli);
|
||||
"Got new TLLI(PTMSI) %08x(%08x) from SGSN, using %08x(%08x)\n",
|
||||
new_sgsn_tlli, new_sgsn_ptmsi, new_bss_tlli, new_bss_ptmsi);
|
||||
if (tlli_info) {
|
||||
gbprox_reassign_tlli(tlli_info, peer, new_tlli);
|
||||
gbprox_reassign_tlli(&tlli_info->sgsn_tlli,
|
||||
peer, new_sgsn_tlli);
|
||||
gbprox_reassign_tlli(&tlli_info->tlli,
|
||||
peer, new_bss_tlli);
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
} else {
|
||||
tlli_info =
|
||||
gbprox_register_tlli(peer, new_tlli,
|
||||
gbprox_register_tlli(peer, new_bss_tlli,
|
||||
parse_ctx->imsi,
|
||||
parse_ctx->imsi_len, now);
|
||||
/* Setup TLLIs */
|
||||
tlli_info->sgsn_tlli.current = new_sgsn_tlli;
|
||||
}
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc) {
|
||||
if (!tlli_info) {
|
||||
tlli_info =
|
||||
gbprox_register_tlli(peer, parse_ctx->tlli,
|
||||
parse_ctx->imsi,
|
||||
parse_ctx->imsi_len, now);
|
||||
} else {
|
||||
gbprox_validate_tlli(tlli_info, parse_ctx->tlli,
|
||||
parse_ctx->to_bss);
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
/* Setup PTMSIs */
|
||||
tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
|
||||
tlli_info->tlli.ptmsi = new_bss_ptmsi;
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info) {
|
||||
/* Unknown SGSN TLLI */
|
||||
tlli_info =
|
||||
gbprox_register_tlli(peer, parse_ctx->tlli,
|
||||
parse_ctx->imsi,
|
||||
parse_ctx->imsi_len, now);
|
||||
|
||||
/* Setup TLLIs */
|
||||
tlli_info->sgsn_tlli.current = tlli_info->tlli.current;
|
||||
if (peer->cfg->patch_ptmsi) {
|
||||
/* TODO: We don't know the local TLLI here, perhaps add
|
||||
* a workaround that derives a PTMSI from the SGSN TLLI
|
||||
* and use that to get the missing values. This may
|
||||
* only happen when the gbproxy has been restarted or a
|
||||
* tlli_info has been discarded due to age or queue
|
||||
* length.
|
||||
*/
|
||||
tlli_info->tlli.current = 0;
|
||||
}
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
|
||||
gbprox_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
|
||||
if (!peer->cfg->patch_ptmsi)
|
||||
gbprox_validate_tlli(&tlli_info->tlli,
|
||||
parse_ctx->tlli, 1);
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
} else if (tlli_info) {
|
||||
gbprox_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
|
@ -1662,21 +1782,78 @@ patch_error:
|
|||
"Failed to patch BSSGP message as requested: %s.\n", err_info);
|
||||
}
|
||||
|
||||
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
|
||||
static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
|
||||
struct msgb *msg,
|
||||
struct gbproxy_peer *peer, int to_bss)
|
||||
/* patch BSSGP message */
|
||||
static void gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
|
||||
struct msgb *msg,
|
||||
struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_parse_context parse_ctx = {0};
|
||||
int rc;
|
||||
int len_change = 0;
|
||||
time_t now;
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn)
|
||||
return;
|
||||
|
||||
parse_ctx.to_bss = to_bss;
|
||||
parse_ctx.to_bss = 0;
|
||||
|
||||
/* Parse BSSGP/LLC */
|
||||
rc = gbprox_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
|
||||
&parse_ctx);
|
||||
|
||||
if (!rc) {
|
||||
if (!parse_ctx.need_decryption) {
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"Failed to parse BSSGP/GMM message\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get peer */
|
||||
if (!peer && msgb_bvci(msg) >= 2)
|
||||
peer = peer_by_bvci(cfg, msgb_bvci(msg));
|
||||
|
||||
if (!peer)
|
||||
peer = gbprox_peer_by_nsei(cfg, msgb_nsei(msg));
|
||||
|
||||
if (!peer)
|
||||
peer = peer_by_bssgp_tlv(cfg, &parse_ctx.bssgp_tp);
|
||||
|
||||
if (!peer) {
|
||||
LOGP(DLLC, LOGL_INFO,
|
||||
"NSEI=%d(BSS) patching: didn't find peer for message, "
|
||||
"PDU %d\n",
|
||||
msgb_nsei(msg), parse_ctx.pdu_type);
|
||||
/* Increment counter */
|
||||
rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
|
||||
return;
|
||||
}
|
||||
|
||||
now = time(NULL);
|
||||
|
||||
tlli_info = gbprox_update_state_ul(peer, now, &parse_ctx);
|
||||
|
||||
gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
|
||||
peer, tlli_info, &len_change, &parse_ctx);
|
||||
|
||||
gbprox_update_state_after(peer, tlli_info, now, &parse_ctx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
|
||||
static void gbprox_process_bssgp_dl(struct gbproxy_config *cfg,
|
||||
struct msgb *msg,
|
||||
struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_parse_context parse_ctx = {0};
|
||||
int rc;
|
||||
int len_change = 0;
|
||||
time_t now;
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
parse_ctx.to_bss = 1;
|
||||
|
||||
rc = gbprox_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
|
||||
&parse_ctx);
|
||||
|
@ -1692,17 +1869,14 @@ static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
|
|||
if (!peer && msgb_bvci(msg) >= 2)
|
||||
peer = peer_by_bvci(cfg, msgb_bvci(msg));
|
||||
|
||||
if (!peer && !to_bss)
|
||||
peer = gbprox_peer_by_nsei(cfg, msgb_nsei(msg));
|
||||
|
||||
if (!peer)
|
||||
peer = peer_by_bssgp_tlv(cfg, &parse_ctx.bssgp_tp);
|
||||
|
||||
if (!peer) {
|
||||
LOGP(DLLC, LOGL_INFO,
|
||||
"NSEI=%d(%s) patching: didn't find peer for message, "
|
||||
"NSEI=%d(SGSN) patching: didn't find peer for message, "
|
||||
"PDU %d\n",
|
||||
msgb_nsei(msg), to_bss ? "SGSN" : "BSS", parse_ctx.pdu_type);
|
||||
msgb_nsei(msg), parse_ctx.pdu_type);
|
||||
/* Increment counter */
|
||||
rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
|
||||
return;
|
||||
|
@ -1710,7 +1884,7 @@ static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
|
|||
|
||||
now = time(NULL);
|
||||
|
||||
tlli_info = gbprox_update_state(peer, now, &parse_ctx);
|
||||
tlli_info = gbprox_update_state_dl(peer, now, &parse_ctx);
|
||||
|
||||
gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
|
||||
peer, tlli_info, &len_change, &parse_ctx);
|
||||
|
@ -1729,7 +1903,7 @@ static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
|
|||
struct msgb *msg = gprs_msgb_copy(old_msg, "msgb_relay2sgsn");
|
||||
int rc;
|
||||
|
||||
gbprox_process_bssgp_message(cfg, msg, peer, 0);
|
||||
gbprox_process_bssgp_ul(cfg, msg, peer);
|
||||
|
||||
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
|
||||
msgb_nsei(msg), ns_bvci, cfg->nsip_sgsn_nsei);
|
||||
|
@ -2147,7 +2321,7 @@ int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei,
|
|||
int remote_end_is_sgsn = nsei == cfg->nsip_sgsn_nsei;
|
||||
|
||||
if (remote_end_is_sgsn)
|
||||
gbprox_process_bssgp_message(cfg, msg, NULL, 1);
|
||||
gbprox_process_bssgp_dl(cfg, msg, NULL);
|
||||
|
||||
/* Only BVCI=0 messages need special treatment */
|
||||
if (ns_bvci == 0 || ns_bvci == 1) {
|
||||
|
|
|
@ -377,7 +377,7 @@ DEFUN(show_gbproxy_tllis, show_gbproxy_tllis_cmd, "show gbproxy tllis",
|
|||
snprintf(mi_buf, sizeof(mi_buf), "(none)");
|
||||
}
|
||||
vty_out(vty, " TLLI %08x, IMSI %s, AGE %d%s",
|
||||
tlli_info->tlli, mi_buf, (int)age,
|
||||
tlli_info->tlli.current, mi_buf, (int)age,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
|
|||
}
|
||||
|
||||
llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list) {
|
||||
if (match == MATCH_TLLI && tlli_info->tlli != tlli)
|
||||
if (match == MATCH_TLLI && tlli_info->tlli.current != tlli)
|
||||
continue;
|
||||
|
||||
if (match == MATCH_IMSI) {
|
||||
|
@ -544,7 +544,8 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
|
|||
if (strcmp(mi_buf, imsi) != 0)
|
||||
continue;
|
||||
}
|
||||
vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli, VTY_NEWLINE);
|
||||
vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli.current,
|
||||
VTY_NEWLINE);
|
||||
gbprox_delete_tlli(peer, tlli_info);
|
||||
found += 1;
|
||||
}
|
||||
|
|
|
@ -127,9 +127,16 @@ static int dump_peers(FILE *stream, int indent, time_t now,
|
|||
snprintf(mi_buf, sizeof(mi_buf), "(none)");
|
||||
}
|
||||
fprintf(stream, "%*s TLLI %08x",
|
||||
indent, "", tlli_info->tlli);
|
||||
if (tlli_info->assigned_tlli)
|
||||
fprintf(stream, "/%08x", tlli_info->assigned_tlli);
|
||||
indent, "", tlli_info->tlli.current);
|
||||
if (tlli_info->tlli.assigned)
|
||||
fprintf(stream, "/%08x", tlli_info->tlli.assigned);
|
||||
if (tlli_info->sgsn_tlli.current) {
|
||||
fprintf(stream, " -> %08x",
|
||||
tlli_info->sgsn_tlli.current);
|
||||
if (tlli_info->sgsn_tlli.assigned)
|
||||
fprintf(stream, "/%08x",
|
||||
tlli_info->sgsn_tlli.assigned);
|
||||
}
|
||||
rc = fprintf(stream, ", IMSI %s, AGE %d\n",
|
||||
mi_buf, (int)age);
|
||||
if (rc < 0)
|
||||
|
@ -1115,6 +1122,7 @@ static void test_gbproxy_ra_patching()
|
|||
gbcfg.core_mnc = 456;
|
||||
gbcfg.core_apn = talloc_zero_size(NULL, 100);
|
||||
gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar");
|
||||
gbcfg.patch_ptmsi = 0;
|
||||
|
||||
configure_sgsn_peer(&sgsn_peer);
|
||||
configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer));
|
||||
|
@ -1173,24 +1181,32 @@ static void test_gbproxy_ra_patching()
|
|||
GPRS_SAPI_GMM, 1,
|
||||
dtap_attach_acc, sizeof(dtap_attach_acc));
|
||||
|
||||
tlli_info = gbprox_find_tlli(peer, local_tlli);
|
||||
tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli != local_tlli);
|
||||
OSMO_ASSERT(!tlli_info->bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->net_validated);
|
||||
OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
|
||||
OSMO_ASSERT(!tlli_info->tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->tlli.net_validated);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
|
||||
OSMO_ASSERT(!tlli_info->sgsn_tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
|
||||
|
||||
send_llc_ul_ui(nsi, "ATTACH COMPLETE", &bss_peer[0], 0x1002,
|
||||
local_tlli, &rai_bss, cell_id,
|
||||
GPRS_SAPI_GMM, 4,
|
||||
dtap_attach_complete, sizeof(dtap_attach_complete));
|
||||
|
||||
tlli_info = gbprox_find_tlli(peer, local_tlli);
|
||||
tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->net_validated);
|
||||
OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->tlli.net_validated);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
|
||||
|
||||
/* Replace APN (1) */
|
||||
send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
|
||||
|
@ -1198,22 +1214,28 @@ static void test_gbproxy_ra_patching()
|
|||
GPRS_SAPI_GMM, 3,
|
||||
dtap_act_pdp_ctx_req, sizeof(dtap_act_pdp_ctx_req));
|
||||
|
||||
tlli_info = gbprox_find_tlli(peer, local_tlli);
|
||||
tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->assigned_tlli == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->net_validated);
|
||||
OSMO_ASSERT(tlli_info->tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.current != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->tlli.net_validated);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.current != local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.bss_validated);
|
||||
OSMO_ASSERT(!tlli_info->sgsn_tlli.net_validated);
|
||||
|
||||
send_llc_dl_ui(nsi, "GMM INFO", &sgsn_peer, 0x1002,
|
||||
local_tlli, 1, imsi, sizeof(imsi),
|
||||
GPRS_SAPI_GMM, 2,
|
||||
dtap_gmm_information, sizeof(dtap_gmm_information));
|
||||
|
||||
tlli_info = gbprox_find_tlli(peer, local_tlli);
|
||||
tlli_info = gbprox_find_tlli_by_sgsn_tlli(peer, local_tlli);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->assigned_tlli == 0);
|
||||
OSMO_ASSERT(tlli_info->tlli == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->tlli.assigned == 0);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == local_tlli);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.assigned == 0);
|
||||
OSMO_ASSERT(tlli_info->sgsn_tlli.current == local_tlli);
|
||||
|
||||
/* Replace APN (2) */
|
||||
send_llc_ul_ui(nsi, "ACT PDP CTX REQ (REPLACE APN)", &bss_peer[0], 0x1002,
|
||||
|
@ -1566,7 +1588,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
tlli_info = gbprox_register_tlli(peer, tlli1,
|
||||
imsi1, ARRAY_SIZE(imsi1), now);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli1);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli1);
|
||||
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
|
||||
|
||||
/* replace the old entry */
|
||||
|
@ -1574,7 +1596,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
tlli_info = gbprox_register_tlli(peer, tlli2,
|
||||
imsi1, ARRAY_SIZE(imsi1), now);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli2);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli2);
|
||||
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
|
||||
|
||||
dump_peers(stdout, 2, now, &cfg);
|
||||
|
@ -1582,7 +1604,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
/* verify that 5678 has survived */
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli2);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli2);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
|
||||
OSMO_ASSERT(!tlli_info);
|
||||
|
||||
|
@ -1605,7 +1627,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
tlli_info = gbprox_register_tlli(peer, tlli1,
|
||||
imsi1, ARRAY_SIZE(imsi1), now);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli1);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli1);
|
||||
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
|
||||
|
||||
/* try to replace the old entry */
|
||||
|
@ -1613,7 +1635,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
tlli_info = gbprox_register_tlli(peer, tlli1,
|
||||
imsi2, ARRAY_SIZE(imsi2), now);
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli1);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli1);
|
||||
OSMO_ASSERT(peer->patch_state.enabled_tllis_count == 1);
|
||||
|
||||
dump_peers(stdout, 2, now, &cfg);
|
||||
|
@ -1623,7 +1645,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
OSMO_ASSERT(!tlli_info);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli1);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli1);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
@ -1661,7 +1683,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
OSMO_ASSERT(!tlli_info);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli == tlli2);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli2);
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
@ -1669,6 +1691,7 @@ static void test_gbproxy_tlli_expire(void)
|
|||
}
|
||||
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
int num_removed;
|
||||
|
||||
printf("Test TLLI expiry, max_age == 1:\n");
|
||||
|
@ -1693,12 +1716,20 @@ static void test_gbproxy_tlli_expire(void)
|
|||
|
||||
dump_peers(stdout, 2, now + 2, &cfg);
|
||||
|
||||
/* verify that 5678 has survived */
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
|
||||
OSMO_ASSERT(!tlli_info);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli2);
|
||||
|
||||
printf("\n");
|
||||
|
||||
gbproxy_peer_free(peer);
|
||||
}
|
||||
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
int num_removed;
|
||||
|
||||
printf("Test TLLI expiry, max_len == 2, max_age == 1:\n");
|
||||
|
@ -1731,6 +1762,15 @@ static void test_gbproxy_tlli_expire(void)
|
|||
|
||||
dump_peers(stdout, 2, now + 2, &cfg);
|
||||
|
||||
/* verify that tlli3 has survived */
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi1, ARRAY_SIZE(imsi1));
|
||||
OSMO_ASSERT(!tlli_info);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi2, ARRAY_SIZE(imsi2));
|
||||
OSMO_ASSERT(!tlli_info);
|
||||
tlli_info = gbprox_find_tlli_by_mi(peer, imsi3, ARRAY_SIZE(imsi3));
|
||||
OSMO_ASSERT(tlli_info);
|
||||
OSMO_ASSERT(tlli_info->tlli.current == tlli3);
|
||||
|
||||
printf("\n");
|
||||
|
||||
gbproxy_peer_free(peer);
|
||||
|
|
|
@ -1745,7 +1745,7 @@ Peers:
|
|||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI efe2b700, IMSI 12131415161718, AGE 0
|
||||
TLLI efe2b700 -> efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING DETACH REQ from 0x01020304:1111
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 7e e1 41
|
||||
|
||||
|
@ -1823,7 +1823,7 @@ Peers:
|
|||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI bbc54679/efe2b700, IMSI 12131415161718, AGE 0
|
||||
TLLI bbc54679/efe2b700 -> bbc54679/efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING DETACH REQ (PWR OFF) from 0x01020304:1111
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 11 22 33 40 50 60 75 30 00 80 0e 00 15 01 c0 19 08 05 09 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 84 0c eb
|
||||
|
||||
|
@ -1883,7 +1883,7 @@ Peers:
|
|||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI efe2b700, IMSI (none), AGE 0
|
||||
TLLI efe2b700 -> efe2b700, IMSI (none), AGE 0
|
||||
Test TLLI info expiry
|
||||
|
||||
Test TLLI replacement:
|
||||
|
|
Loading…
Reference in New Issue