Merge Jacob's GPRS GB Proxy related configs
All review feedback will be addressed _after_ the split of the files. This is the only reasonable approach to get the split of files merged. I didn't have the time to review all of the code before the point of splitting.
This commit is contained in:
commit
ddbbe695b3
|
@ -11,6 +11,8 @@
|
|||
#include <regex.h>
|
||||
|
||||
struct rate_ctr_group;
|
||||
struct gprs_gb_parse_context;
|
||||
struct tlv_parsed;
|
||||
|
||||
enum gbproxy_patch_mode {
|
||||
GBPROX_PATCH_DEFAULT,
|
||||
|
@ -22,6 +24,42 @@ enum gbproxy_patch_mode {
|
|||
GBPROX_PATCH_LLC, /*!< BSSGP and all supported LLC msgs */
|
||||
};
|
||||
|
||||
enum gbproxy_global_ctr {
|
||||
GBPROX_GLOB_CTR_INV_BVCI,
|
||||
GBPROX_GLOB_CTR_INV_LAI,
|
||||
GBPROX_GLOB_CTR_INV_RAI,
|
||||
GBPROX_GLOB_CTR_INV_NSEI,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_BSS,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
|
||||
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
|
||||
GBPROX_GLOB_CTR_TX_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_OTHER_ERR,
|
||||
GBPROX_GLOB_CTR_PATCH_PEER_ERR,
|
||||
};
|
||||
|
||||
enum gbproxy_peer_ctr {
|
||||
GBPROX_PEER_CTR_BLOCKED,
|
||||
GBPROX_PEER_CTR_UNBLOCKED,
|
||||
GBPROX_PEER_CTR_DROPPED,
|
||||
GBPROX_PEER_CTR_INV_NSEI,
|
||||
GBPROX_PEER_CTR_TX_ERR,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_APN_PATCHED,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
|
||||
GBPROX_PEER_CTR_PATCH_ERR,
|
||||
GBPROX_PEER_CTR_ATTACH_REQS,
|
||||
GBPROX_PEER_CTR_ATTACH_REJS,
|
||||
GBPROX_PEER_CTR_TLLI_UNKNOWN,
|
||||
GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
|
||||
};
|
||||
|
||||
struct gbproxy_config {
|
||||
/* parsed from config file */
|
||||
uint16_t nsip_sgsn_nsei;
|
||||
|
@ -44,10 +82,15 @@ 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;
|
||||
regex_t imsi_re_comp;
|
||||
|
||||
/* Used to generate identifiers */
|
||||
unsigned bss_ptmsi_state;
|
||||
unsigned sgsn_tlli_state;
|
||||
};
|
||||
|
||||
struct gbproxy_patch_state {
|
||||
|
@ -81,14 +124,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;
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -113,26 +168,85 @@ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
|
|||
|
||||
void gbprox_reset(struct gbproxy_config *cfg);
|
||||
|
||||
int gbprox_set_patch_filter(struct gbproxy_config *cfg, const char *filter,
|
||||
const char **err_msg);
|
||||
void gbprox_clear_patch_filter(struct gbproxy_config *cfg);
|
||||
/* TLLI state handling */
|
||||
void gbproxy_delete_tllis(struct gbproxy_peer *peer);
|
||||
int gbproxy_check_tlli(struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_tlli_info *gbprox_find_tlli_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi);
|
||||
uint32_t gbproxy_map_tlli(
|
||||
uint32_t other_tlli, struct gbproxy_tlli_info *tlli_info, int to_bss);
|
||||
struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
void gbproxy_update_tlli_state_after(
|
||||
struct gbproxy_peer *peer, struct gbproxy_tlli_info *tlli_info,
|
||||
time_t now, struct gprs_gb_parse_context *parse_ctx);
|
||||
int gbproxy_remove_stale_tllis(struct gbproxy_peer *peer, time_t now);
|
||||
void gbproxy_delete_tlli(struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info);
|
||||
|
||||
void gbprox_delete_tlli(struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info);
|
||||
int gbprox_remove_stale_tllis(struct gbproxy_peer *peer, time_t now);
|
||||
int gbprox_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);
|
||||
|
||||
struct gbproxy_peer *gbprox_peer_by_nsei(struct gbproxy_config *cfg, uint16_t nsei);
|
||||
|
||||
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_register_tlli(
|
||||
struct gbproxy_tlli_info *gbproxy_register_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli,
|
||||
const uint8_t *imsi, size_t imsi_len, time_t now);
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer);
|
||||
|
||||
int gbprox_check_imsi(struct gbproxy_peer *peer,
|
||||
const uint8_t *imsi, size_t imsi_len);
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli_by_mi(
|
||||
struct gbproxy_peer *peer, const uint8_t *mi_data, size_t mi_data_len);
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli);
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi);
|
||||
|
||||
/* needed by gb_proxy_tlli.h */
|
||||
uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, uint32_t sgsn_ptmsi);
|
||||
uint32_t gbproxy_make_sgsn_tlli(
|
||||
struct gbproxy_peer *peer, struct gbproxy_tlli_info *tlli_info,
|
||||
uint32_t bss_tlli);
|
||||
int gbproxy_check_imsi(
|
||||
struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
|
||||
|
||||
/* Message patching */
|
||||
void gbproxy_patch_bssgp(
|
||||
struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_tlli_info *tlli_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx)
|
||||
__attribute__((nonnull));
|
||||
|
||||
int gbproxy_patch_llc(
|
||||
struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_tlli_info *tlli_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx)
|
||||
__attribute__((nonnull));
|
||||
|
||||
int gbproxy_set_patch_filter(
|
||||
struct gbproxy_config *cfg, const char *filter, const char **err_msg);
|
||||
void gbproxy_clear_patch_filter(struct gbproxy_config *cfg);
|
||||
int gbproxy_check_imsi(
|
||||
struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
|
||||
|
||||
/* Peer handling */
|
||||
struct gbproxy_peer *gbproxy_peer_by_bvci(
|
||||
struct gbproxy_config *cfg, uint16_t bvci) __attribute__((nonnull));
|
||||
struct gbproxy_peer *gbproxy_peer_by_nsei(
|
||||
struct gbproxy_config *cfg, uint16_t nsei) __attribute__((nonnull));
|
||||
struct gbproxy_peer *gbproxy_peer_by_rai(
|
||||
struct gbproxy_config *cfg, const uint8_t *ra) __attribute__((nonnull));
|
||||
struct gbproxy_peer *gbproxy_peer_by_lai(
|
||||
struct gbproxy_config *cfg, const uint8_t *la) __attribute__((nonnull));
|
||||
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(
|
||||
struct gbproxy_config *cfg, struct tlv_parsed *tp)
|
||||
__attribute__((nonnull));
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
|
||||
__attribute__((nonnull));
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer) __attribute__((nonnull));
|
||||
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
|
||||
__attribute__((nonnull));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include <openbsc/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 *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_ptimsi;
|
||||
|
||||
/* General info */
|
||||
const char *llc_msg_name;
|
||||
int invalidate_tlli;
|
||||
int need_decryption;
|
||||
uint32_t tlli;
|
||||
int pdu_type;
|
||||
int old_raid_matches;
|
||||
};
|
||||
|
||||
int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
|
||||
struct gprs_gb_parse_context *parse_ctx) __attribute__((nonnull));
|
||||
|
||||
int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
|
||||
struct gprs_gb_parse_context *parse_ctx) __attribute__((nonnull));
|
||||
|
||||
int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gprs_gb_parse_context *parse_ctx) __attribute__((nonnull));
|
||||
|
||||
void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx,
|
||||
const char *default_msg_name) __attribute__((nonnull(1)));
|
|
@ -31,3 +31,6 @@ int gprs_msgb_resize_area(struct msgb *msg, uint8_t *area,
|
|||
size_t old_size, size_t new_size);
|
||||
char *gprs_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t rest_chars);
|
||||
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
|
||||
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
|
||||
|
|
|
@ -14,7 +14,8 @@ bin_PROGRAMS = osmo-gbproxy
|
|||
endif
|
||||
|
||||
osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \
|
||||
gprs_llc_parse.c crc24.c gprs_utils.c
|
||||
gb_proxy_patch.c gb_proxy_tlli.c gb_proxy_peer.c \
|
||||
gprs_gb_parse.c gprs_llc_parse.c crc24.c gprs_utils.c
|
||||
osmo_gbproxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(OSMO_LIBS)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,475 @@
|
|||
/* Gb-proxy message patching */
|
||||
|
||||
/* (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 <openbsc/gb_proxy.h>
|
||||
|
||||
#include <openbsc/gprs_utils.h>
|
||||
#include <openbsc/gprs_gb_parse.h>
|
||||
|
||||
#include <openbsc/gsm_data_shared.h>
|
||||
#include <openbsc/gsm_04_08_gprs.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocom/gprs/protocol/gsm_08_18.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
/* check whether patching is enabled at this level */
|
||||
static int patching_is_enabled(struct gbproxy_peer *peer,
|
||||
enum gbproxy_patch_mode need_at_least)
|
||||
{
|
||||
enum gbproxy_patch_mode patch_mode = peer->cfg->patch_mode;
|
||||
if (patch_mode == GBPROX_PATCH_DEFAULT)
|
||||
patch_mode = GBPROX_PATCH_LLC;
|
||||
|
||||
return need_at_least <= patch_mode;
|
||||
}
|
||||
|
||||
/* check whether patching is enabled at this level */
|
||||
static int patching_is_required(struct gbproxy_peer *peer,
|
||||
enum gbproxy_patch_mode need_at_least)
|
||||
{
|
||||
return need_at_least <= peer->cfg->patch_mode;
|
||||
}
|
||||
|
||||
static int allow_message_patching(struct gbproxy_peer *peer, int msg_type)
|
||||
{
|
||||
if (msg_type >= GSM48_MT_GSM_ACT_PDP_REQ) {
|
||||
return patching_is_enabled(peer, GBPROX_PATCH_LLC_GSM);
|
||||
} else if (msg_type > GSM48_MT_GMM_ATTACH_REJ) {
|
||||
return patching_is_enabled(peer, GBPROX_PATCH_LLC);
|
||||
} else if (msg_type > GSM48_MT_GMM_ATTACH_REQ) {
|
||||
return patching_is_enabled(peer, GBPROX_PATCH_LLC_ATTACH);
|
||||
} else {
|
||||
return patching_is_enabled(peer, GBPROX_PATCH_LLC_ATTACH_REQ);
|
||||
}
|
||||
}
|
||||
|
||||
/* patch RA identifier in place */
|
||||
static void gbproxy_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;
|
||||
|
||||
gsm48_parse_ra(&raid, raid_enc);
|
||||
|
||||
old_mcc = raid.mcc;
|
||||
old_mnc = raid.mnc;
|
||||
|
||||
if (!to_bss) {
|
||||
/* BSS -> SGSN */
|
||||
if (state->local_mcc)
|
||||
raid.mcc = peer->cfg->core_mcc;
|
||||
|
||||
if (state->local_mnc)
|
||||
raid.mnc = peer->cfg->core_mnc;
|
||||
} else {
|
||||
/* SGSN -> BSS */
|
||||
if (state->local_mcc)
|
||||
raid.mcc = state->local_mcc;
|
||||
|
||||
if (state->local_mnc)
|
||||
raid.mnc = state->local_mnc;
|
||||
}
|
||||
|
||||
if (state->local_mcc || state->local_mnc) {
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to %s: "
|
||||
"%d-%d-%d-%d -> %d-%d-%d-%d\n",
|
||||
log_text,
|
||||
to_bss ? "BSS" : "SGSN",
|
||||
old_mcc, old_mnc, raid.lac, raid.rac,
|
||||
raid.mcc, raid.mnc, raid.lac, raid.rac);
|
||||
|
||||
gsm48_construct_ra(raid_enc, &raid);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
}
|
||||
}
|
||||
|
||||
static void gbproxy_patch_apn_ie(struct msgb *msg,
|
||||
uint8_t *apn_ie, size_t apn_ie_len,
|
||||
struct gbproxy_peer *peer,
|
||||
size_t *new_apn_ie_len, const char *log_text)
|
||||
{
|
||||
struct apn_ie_hdr {
|
||||
uint8_t iei;
|
||||
uint8_t apn_len;
|
||||
uint8_t apn[0];
|
||||
} *hdr = (void *)apn_ie;
|
||||
|
||||
size_t apn_len = hdr->apn_len;
|
||||
uint8_t *apn = hdr->apn;
|
||||
|
||||
OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));
|
||||
OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);
|
||||
|
||||
if (peer->cfg->core_apn_size == 0) {
|
||||
char str1[110];
|
||||
/* Remove the IE */
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to SGSN: Removing APN '%s'\n",
|
||||
log_text,
|
||||
gprs_apn_to_str(str1, apn, apn_len));
|
||||
|
||||
*new_apn_ie_len = 0;
|
||||
gprs_msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
|
||||
} else {
|
||||
/* Resize the IE */
|
||||
char str1[110];
|
||||
char str2[110];
|
||||
|
||||
OSMO_ASSERT(peer->cfg->core_apn_size <= 100);
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to SGSN: "
|
||||
"Replacing APN '%s' -> '%s'\n",
|
||||
log_text,
|
||||
gprs_apn_to_str(str1, apn, apn_len),
|
||||
gprs_apn_to_str(str2, peer->cfg->core_apn,
|
||||
peer->cfg->core_apn_size));
|
||||
|
||||
*new_apn_ie_len = peer->cfg->core_apn_size + 2;
|
||||
gprs_msgb_resize_area(msg, apn, apn_len, peer->cfg->core_apn_size);
|
||||
memcpy(apn, peer->cfg->core_apn, peer->cfg->core_apn_size);
|
||||
hdr->apn_len = peer->cfg->core_apn_size;
|
||||
}
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
|
||||
}
|
||||
|
||||
static int gbproxy_patch_tlli(uint8_t *tlli_enc,
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t new_tlli,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
uint32_t tlli_be;
|
||||
uint32_t tlli;
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
|
||||
|
||||
memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
|
||||
tlli = ntohl(tlli_be);
|
||||
|
||||
if (tlli == new_tlli)
|
||||
return 0;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %ss: "
|
||||
"Replacing %08x -> %08x\n",
|
||||
log_text, tlli, new_tlli);
|
||||
|
||||
tlli_be = htonl(new_tlli);
|
||||
memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbproxy_patch_ptmsi(uint8_t *ptmsi_enc,
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t new_ptmsi,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
uint32_t ptmsi_be;
|
||||
uint32_t ptmsi;
|
||||
enum gbproxy_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
|
||||
memcpy(&ptmsi_be, ptmsi_enc + 1, sizeof(ptmsi_be));
|
||||
ptmsi = ntohl(ptmsi_be);
|
||||
|
||||
if (ptmsi == new_ptmsi)
|
||||
return 0;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %ss: "
|
||||
"Replacing %08x -> %08x\n",
|
||||
log_text, ptmsi, new_ptmsi);
|
||||
|
||||
ptmsi_be = htonl(new_ptmsi);
|
||||
memcpy(ptmsi_enc + 1, &ptmsi_be, sizeof(ptmsi_be));
|
||||
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gbproxy_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info, int *len_change,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
|
||||
int have_patched = 0;
|
||||
int fcs;
|
||||
|
||||
if (parse_ctx->g48_hdr && !allow_message_patching(peer, parse_ctx->g48_hdr->msg_type))
|
||||
return have_patched;
|
||||
|
||||
if (parse_ctx->ptmsi_enc && tlli_info) {
|
||||
uint32_t ptmsi;
|
||||
if (parse_ctx->to_bss)
|
||||
ptmsi = tlli_info->tlli.ptmsi;
|
||||
else
|
||||
ptmsi = tlli_info->sgsn_tlli.ptmsi;
|
||||
|
||||
if (ptmsi != GSM_RESERVED_TMSI) {
|
||||
if (gbproxy_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
|
||||
ptmsi, parse_ctx->to_bss, "P-TMSI"))
|
||||
have_patched = 1;
|
||||
} else {
|
||||
/* TODO: invalidate old RAI if present (see below) */
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_ctx->new_ptmsi_enc && tlli_info) {
|
||||
uint32_t ptmsi;
|
||||
if (parse_ctx->to_bss)
|
||||
ptmsi = tlli_info->tlli.ptmsi;
|
||||
else
|
||||
ptmsi = tlli_info->sgsn_tlli.ptmsi;
|
||||
|
||||
OSMO_ASSERT(ptmsi);
|
||||
if (gbproxy_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
|
||||
ptmsi, parse_ctx->to_bss, "new P-TMSI"))
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (parse_ctx->raid_enc) {
|
||||
gbproxy_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. */
|
||||
gbproxy_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 &&
|
||||
gbproxy_check_tlli(peer, parse_ctx->tlli)) {
|
||||
size_t new_len;
|
||||
gbproxy_patch_apn_ie(msg,
|
||||
parse_ctx->apn_ie, parse_ctx->apn_ie_len,
|
||||
peer, &new_len, parse_ctx->llc_msg_name);
|
||||
*len_change += (int)new_len - (int)parse_ctx->apn_ie_len;
|
||||
|
||||
have_patched = 1;
|
||||
}
|
||||
|
||||
if (have_patched) {
|
||||
llc_len += *len_change;
|
||||
ghp->crc_length += *len_change;
|
||||
|
||||
/* Fix FCS */
|
||||
fcs = gprs_llc_fcs(llc, ghp->crc_length);
|
||||
LOGP(DLLC, LOGL_DEBUG, "Updated LLC message, CRC: %06x -> %06x\n",
|
||||
ghp->fcs, fcs);
|
||||
|
||||
llc[llc_len - 3] = fcs & 0xff;
|
||||
llc[llc_len - 2] = (fcs >> 8) & 0xff;
|
||||
llc[llc_len - 1] = (fcs >> 16) & 0xff;
|
||||
}
|
||||
|
||||
return have_patched;
|
||||
}
|
||||
|
||||
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
|
||||
void gbproxy_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info, int *len_change,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
const char *err_info = NULL;
|
||||
int err_ctr = -1;
|
||||
|
||||
if (!patching_is_enabled(peer, GBPROX_PATCH_BSSGP))
|
||||
return;
|
||||
|
||||
if (parse_ctx->bssgp_raid_enc)
|
||||
gbproxy_patch_raid(parse_ctx->bssgp_raid_enc, peer,
|
||||
parse_ctx->to_bss, "BSSGP");
|
||||
|
||||
if (!patching_is_enabled(peer, GBPROX_PATCH_LLC_ATTACH_REQ))
|
||||
return;
|
||||
|
||||
if (parse_ctx->need_decryption &&
|
||||
patching_is_required(peer, GBPROX_PATCH_LLC_ATTACH)) {
|
||||
/* Patching LLC messages has been requested
|
||||
* explicitly, but the message (including the
|
||||
* type) is encrypted, so we possibly fail to
|
||||
* patch the LLC part of the message. */
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
|
||||
err_info = "GMM message is encrypted";
|
||||
goto patch_error;
|
||||
}
|
||||
|
||||
if (parse_ctx->tlli_enc && tlli_info) {
|
||||
uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,
|
||||
tlli_info, parse_ctx->to_bss);
|
||||
|
||||
if (tlli) {
|
||||
gbproxy_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
|
||||
parse_ctx->to_bss, "TLLI");
|
||||
parse_ctx->tlli = tlli;
|
||||
} else if (parse_ctx->to_bss) {
|
||||
/* Happens with unknown (not cached) TLLI coming from
|
||||
* the SGSN */
|
||||
/* TODO: What shall be done with the message in this case? */
|
||||
err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
|
||||
err_info = "TLLI sent by the SGSN is unknown";
|
||||
goto patch_error;
|
||||
} else {
|
||||
/* Internal error */
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
|
||||
err_info = "Replacement TLLI is 0";
|
||||
goto patch_error;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_ctx->llc) {
|
||||
uint8_t *llc = parse_ctx->llc;
|
||||
size_t llc_len = parse_ctx->llc_len;
|
||||
int llc_len_change = 0;
|
||||
|
||||
gbproxy_patch_llc(msg, llc, llc_len, peer, tlli_info,
|
||||
&llc_len_change, parse_ctx);
|
||||
/* Note that the APN might have been resized here, but no
|
||||
* pointer int the parse_ctx will refer to an adress after the
|
||||
* APN. So it's possible to patch first and do the TLLI
|
||||
* handling afterwards. */
|
||||
|
||||
if (llc_len_change) {
|
||||
llc_len += llc_len_change;
|
||||
|
||||
/* Fix LLC IE len */
|
||||
/* TODO: This is a kludge, but the a pointer to the
|
||||
* start of the IE is not available here */
|
||||
if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
|
||||
/* most probably a one byte length */
|
||||
if (llc_len > 127) {
|
||||
err_info = "Cannot increase size";
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
|
||||
goto patch_error;
|
||||
}
|
||||
llc[-1] = llc_len | 0x80;
|
||||
} else {
|
||||
llc[-2] = (llc_len >> 8) & 0x7f;
|
||||
llc[-1] = llc_len & 0xff;
|
||||
}
|
||||
*len_change += llc_len_change;
|
||||
}
|
||||
/* Note that the tp struct might contain invalid pointers here
|
||||
* if the LLC field has changed its size */
|
||||
parse_ctx->llc_len = llc_len;
|
||||
}
|
||||
return;
|
||||
|
||||
patch_error:
|
||||
OSMO_ASSERT(err_ctr >= 0);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"NSEI=%u(%s) failed to patch BSSGP message as requested: %s.\n",
|
||||
msgb_nsei(msg), parse_ctx->to_bss ? "SGSN" : "BSS",
|
||||
err_info);
|
||||
}
|
||||
|
||||
void gbproxy_clear_patch_filter(struct gbproxy_config *cfg)
|
||||
{
|
||||
if (cfg->check_imsi) {
|
||||
regfree(&cfg->imsi_re_comp);
|
||||
cfg->check_imsi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int gbproxy_set_patch_filter(struct gbproxy_config *cfg, const char *filter,
|
||||
const char **err_msg)
|
||||
{
|
||||
static char err_buf[300];
|
||||
int rc;
|
||||
|
||||
gbproxy_clear_patch_filter(cfg);
|
||||
|
||||
if (!filter)
|
||||
return 0;
|
||||
|
||||
rc = regcomp(&cfg->imsi_re_comp, filter,
|
||||
REG_EXTENDED | REG_NOSUB | REG_ICASE);
|
||||
|
||||
if (rc == 0) {
|
||||
cfg->check_imsi = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err_msg) {
|
||||
regerror(rc, &cfg->imsi_re_comp,
|
||||
err_buf, sizeof(err_buf));
|
||||
*err_msg = err_buf;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gbproxy_check_imsi(struct gbproxy_peer *peer,
|
||||
const uint8_t *imsi, size_t imsi_len)
|
||||
{
|
||||
char mi_buf[200];
|
||||
int rc;
|
||||
|
||||
if (!peer->cfg->check_imsi)
|
||||
return 1;
|
||||
|
||||
rc = gprs_is_mi_imsi(imsi, imsi_len);
|
||||
if (rc > 0)
|
||||
rc = gsm48_mi_to_string(mi_buf, sizeof(mi_buf), imsi, imsi_len);
|
||||
if (rc <= 0) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
|
||||
osmo_hexdump(imsi, imsi_len));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG, "Checking IMSI '%s' (%d)\n", mi_buf, rc);
|
||||
|
||||
rc = regexec(&peer->cfg->imsi_re_comp, mi_buf, 0, NULL, 0);
|
||||
if (rc == REG_NOMATCH) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"IMSI '%s' doesn't match pattern '%s'\n",
|
||||
mi_buf, peer->cfg->match_re);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/* Gb proxy peer handling */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010-2013 by On-Waves
|
||||
* (C) 2013 by Holger Hans Peter Freyther
|
||||
* 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 <openbsc/gb_proxy.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_data_shared.h>
|
||||
#include <openbsc/gsm_04_08_gprs.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocom/gprs/protocol/gsm_08_18.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const struct rate_ctr_desc peer_ctr_description[] = {
|
||||
{ "blocked", "BVC Block " },
|
||||
{ "unblocked", "BVC Unblock " },
|
||||
{ "dropped", "BVC blocked, dropped packet " },
|
||||
{ "inv-nsei", "NSEI mismatch " },
|
||||
{ "tx-err", "NS Transmission error " },
|
||||
{ "raid-mod.bss", "RAID patched (BSS )" },
|
||||
{ "raid-mod.sgsn", "RAID patched (SGSN)" },
|
||||
{ "apn-mod.sgsn", "APN patched " },
|
||||
{ "tlli-mod.bss", "TLLI patched (BSS )" },
|
||||
{ "tlli-mod.sgsn", "TLLI patched (SGSN)" },
|
||||
{ "ptmsi-mod.bss", "P-TMSI patched (BSS )" },
|
||||
{ "ptmsi-mod.sgsn","P-TMSI patched (SGSN)" },
|
||||
{ "mod-crypt-err", "Patch error: encrypted " },
|
||||
{ "mod-err", "Patch error: other " },
|
||||
{ "attach-reqs", "Attach Request count " },
|
||||
{ "attach-rejs", "Attach Reject count " },
|
||||
{ "tlli-unknown", "TLLI from SGSN unknown " },
|
||||
{ "tlli-cache", "TLLI cache size " },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc peer_ctrg_desc = {
|
||||
.group_name_prefix = "gbproxy.peer",
|
||||
.group_description = "GBProxy Peer Statistics",
|
||||
.num_ctr = ARRAY_SIZE(peer_ctr_description),
|
||||
.ctr_desc = peer_ctr_description,
|
||||
};
|
||||
|
||||
|
||||
/* Find the gbprox_peer by its BVCI */
|
||||
struct gbproxy_peer *gbproxy_peer_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (peer->bvci == bvci)
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the gbprox_peer by its NSEI */
|
||||
struct gbproxy_peer *gbproxy_peer_by_nsei(struct gbproxy_config *cfg,
|
||||
uint16_t nsei)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (peer->nsei == nsei)
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Routeing Area Identification (RAI) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_rai(struct gbproxy_config *cfg,
|
||||
const uint8_t *ra)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra, ra, 6))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Location Area Identification (LAI) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_lai(struct gbproxy_config *cfg,
|
||||
const uint8_t *la)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra, la, 5))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Location Area Code (LAC) */
|
||||
struct gbproxy_peer *gbproxy_peer_by_lac(struct gbproxy_config *cfg,
|
||||
const uint8_t *la)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
if (!memcmp(peer->ra + 3, la + 3, 2))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(struct gbproxy_config *cfg,
|
||||
struct tlv_parsed *tp)
|
||||
{
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {
|
||||
uint16_t bvci;
|
||||
|
||||
bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI));
|
||||
if (bvci >= 2)
|
||||
return gbproxy_peer_by_bvci(cfg, bvci);
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {
|
||||
uint8_t *rai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA);
|
||||
/* Only compare LAC part, since MCC/MNC are possibly patched.
|
||||
* Since the LAC of different BSS must be different when
|
||||
* MCC/MNC are patched, collisions shouldn't happen. */
|
||||
return gbproxy_peer_by_lac(cfg, rai);
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
|
||||
uint8_t *lai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA);
|
||||
return gbproxy_peer_by_lac(cfg, lai);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
|
||||
peer = talloc_zero(tall_bsc_ctx, struct gbproxy_peer);
|
||||
if (!peer)
|
||||
return NULL;
|
||||
|
||||
peer->bvci = bvci;
|
||||
peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci);
|
||||
peer->cfg = cfg;
|
||||
|
||||
llist_add(&peer->list, &cfg->bts_peers);
|
||||
|
||||
INIT_LLIST_HEAD(&peer->patch_state.enabled_tllis);
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer)
|
||||
{
|
||||
llist_del(&peer->list);
|
||||
|
||||
gbproxy_delete_tllis(peer);
|
||||
|
||||
rate_ctr_group_free(peer->ctrg);
|
||||
peer->ctrg = NULL;
|
||||
|
||||
talloc_free(peer);
|
||||
}
|
||||
|
||||
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)
|
||||
{
|
||||
int counter = 0;
|
||||
struct gbproxy_peer *peer, *tmp;
|
||||
|
||||
llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list) {
|
||||
if (peer->nsei != nsei)
|
||||
continue;
|
||||
if (bvci && peer->bvci != bvci)
|
||||
continue;
|
||||
|
||||
gbproxy_peer_free(peer);
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
|
@ -0,0 +1,544 @@
|
|||
/* Gb-proxy TLLI state handling */
|
||||
|
||||
/* (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 <openbsc/gb_proxy.h>
|
||||
|
||||
#include <openbsc/gprs_utils.h>
|
||||
#include <openbsc/gprs_gb_parse.h>
|
||||
|
||||
#include <openbsc/gsm_data_shared.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_find_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->tlli.current == tlli ||
|
||||
tlli_info->tlli.assigned == tlli)
|
||||
return tlli_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi)
|
||||
{
|
||||
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->tlli.ptmsi == ptmsi)
|
||||
return tlli_info;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_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;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_find_tlli_by_mi(
|
||||
struct gbproxy_peer *peer,
|
||||
const uint8_t *mi_data,
|
||||
size_t mi_data_len)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
if (!gprs_is_mi_imsi(mi_data, mi_data_len))
|
||||
return NULL;
|
||||
|
||||
llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
|
||||
if (tlli_info->mi_data_len != mi_data_len)
|
||||
continue;
|
||||
if (memcmp(tlli_info->mi_data, mi_data, mi_data_len) != 0)
|
||||
continue;
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gbproxy_delete_tlli(struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_del(&tlli_info->list);
|
||||
talloc_free(tlli_info);
|
||||
state->enabled_tllis_count -= 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->enabled_tllis_count;
|
||||
}
|
||||
|
||||
void gbproxy_delete_tllis(struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info, *nxt;
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list)
|
||||
gbproxy_delete_tlli(peer, tlli_info);
|
||||
|
||||
OSMO_ASSERT(state->enabled_tllis_count == 0);
|
||||
OSMO_ASSERT(llist_empty(&state->enabled_tllis));
|
||||
}
|
||||
|
||||
static void gbproxy_attach_tlli_info(struct gbproxy_peer *peer, time_t now,
|
||||
struct gbproxy_tlli_info *tlli_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
tlli_info->timestamp = now;
|
||||
llist_add(&tlli_info->list, &state->enabled_tllis);
|
||||
state->enabled_tllis_count += 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->enabled_tllis_count;
|
||||
}
|
||||
|
||||
int gbproxy_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
int exceeded_max_len = 0;
|
||||
int deleted_count = 0;
|
||||
int check_for_age;
|
||||
|
||||
if (peer->cfg->tlli_max_len > 0)
|
||||
exceeded_max_len =
|
||||
state->enabled_tllis_count - peer->cfg->tlli_max_len;
|
||||
|
||||
check_for_age = peer->cfg->tlli_max_age > 0;
|
||||
|
||||
for (; exceeded_max_len > 0; exceeded_max_len--) {
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
OSMO_ASSERT(!llist_empty(&state->enabled_tllis));
|
||||
tlli_info = llist_entry(state->enabled_tllis.prev,
|
||||
struct gbproxy_tlli_info,
|
||||
list);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, length %d, max_len exceeded)\n",
|
||||
tlli_info->tlli.current, state->enabled_tllis_count);
|
||||
|
||||
gbproxy_delete_tlli(peer, tlli_info);
|
||||
deleted_count += 1;
|
||||
}
|
||||
|
||||
while (check_for_age && !llist_empty(&state->enabled_tllis)) {
|
||||
time_t age;
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
tlli_info = llist_entry(state->enabled_tllis.prev,
|
||||
struct gbproxy_tlli_info,
|
||||
list);
|
||||
age = now - tlli_info->timestamp;
|
||||
/* age < 0 only happens after system time jumps, discard entry */
|
||||
if (age <= peer->cfg->tlli_max_age && age >= 0) {
|
||||
check_for_age = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list "
|
||||
"(stale, age %d, max_age exceeded)\n",
|
||||
tlli_info->tlli.current, (int)age);
|
||||
|
||||
gbproxy_delete_tlli(peer, tlli_info);
|
||||
deleted_count += 1;
|
||||
}
|
||||
|
||||
return deleted_count;
|
||||
}
|
||||
|
||||
static struct gbproxy_tlli_info *gbproxy_tlli_info_alloc(
|
||||
struct gbproxy_peer *peer)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
|
||||
tlli_info = talloc_zero(peer, struct gbproxy_tlli_info);
|
||||
tlli_info->tlli.ptmsi = GSM_RESERVED_TMSI;
|
||||
tlli_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
static void gbproxy_detach_tlli_info(
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info)
|
||||
{
|
||||
struct gbproxy_patch_state *state = &peer->patch_state;
|
||||
|
||||
llist_del(&tlli_info->list);
|
||||
OSMO_ASSERT(state->enabled_tllis_count > 0);
|
||||
state->enabled_tllis_count -= 1;
|
||||
|
||||
peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
|
||||
state->enabled_tllis_count;
|
||||
}
|
||||
|
||||
static void gbproxy_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
|
||||
const uint8_t *imsi, size_t imsi_len)
|
||||
{
|
||||
if (!gprs_is_mi_imsi(imsi, imsi_len))
|
||||
return;
|
||||
|
||||
tlli_info->mi_data_len = imsi_len;
|
||||
tlli_info->mi_data =
|
||||
talloc_realloc_size(tlli_info, tlli_info->mi_data, imsi_len);
|
||||
OSMO_ASSERT(tlli_info->mi_data != NULL);
|
||||
memcpy(tlli_info->mi_data, imsi, imsi_len);
|
||||
}
|
||||
|
||||
void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
struct gbproxy_peer *peer, uint32_t new_tlli)
|
||||
{
|
||||
if (new_tlli == tlli_state->current)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI has been reassigned from %08x to %08x\n",
|
||||
tlli_state->current, new_tlli);
|
||||
|
||||
/* Remember assigned TLLI */
|
||||
tlli_state->assigned = new_tlli;
|
||||
tlli_state->bss_validated = 0;
|
||||
tlli_state->net_validated = 0;
|
||||
}
|
||||
|
||||
uint32_t gbproxy_map_tlli(uint32_t other_tlli,
|
||||
struct gbproxy_tlli_info *tlli_info, int to_bss)
|
||||
{
|
||||
uint32_t tlli = 0;
|
||||
struct gbproxy_tlli_state *src, *dst;
|
||||
if (to_bss) {
|
||||
src = &tlli_info->sgsn_tlli;
|
||||
dst = &tlli_info->tlli;
|
||||
} else {
|
||||
src = &tlli_info->tlli;
|
||||
dst = &tlli_info->sgsn_tlli;
|
||||
}
|
||||
if (src->current == other_tlli)
|
||||
tlli = dst->current;
|
||||
else if (src->assigned == other_tlli)
|
||||
tlli = dst->assigned;
|
||||
|
||||
return tlli;
|
||||
}
|
||||
|
||||
static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
|
||||
uint32_t tlli, int to_bss)
|
||||
{
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"%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_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_state->net_validated = 1;
|
||||
else
|
||||
tlli_state->bss_validated = 1;
|
||||
|
||||
if (!tlli_state->bss_validated || !tlli_state->net_validated)
|
||||
return;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI %08x has been validated (was %08x)\n",
|
||||
tlli_state->assigned, tlli_state->current);
|
||||
|
||||
tlli_state->current = tlli;
|
||||
tlli_state->assigned = 0;
|
||||
}
|
||||
|
||||
void gbproxy_touch_tlli(struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info, time_t now)
|
||||
{
|
||||
gbproxy_detach_tlli_info(peer, tlli_info);
|
||||
gbproxy_attach_tlli_info(peer, now, tlli_info);
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_register_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli,
|
||||
const uint8_t *imsi, size_t imsi_len, time_t now)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
int enable_patching = -1;
|
||||
int tlli_already_known;
|
||||
|
||||
/* Check, whether the IMSI matches */
|
||||
if (gprs_is_mi_imsi(imsi, imsi_len)) {
|
||||
enable_patching = gbproxy_check_imsi(peer, imsi, imsi_len);
|
||||
if (enable_patching < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tlli_info = gbproxy_find_tlli(peer, tlli);
|
||||
|
||||
if (!tlli_info) {
|
||||
tlli_info = gbproxy_find_tlli_by_mi(peer, imsi, imsi_len);
|
||||
|
||||
if (tlli_info) {
|
||||
/* TLLI has changed somehow, adjust it */
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"The TLLI has changed from %08x to %08x\n",
|
||||
tlli_info->tlli.current, tlli);
|
||||
tlli_info->tlli.current = tlli;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tlli_info) {
|
||||
tlli_info = gbproxy_tlli_info_alloc(peer);
|
||||
tlli_info->tlli.current = tlli;
|
||||
} else {
|
||||
gbproxy_detach_tlli_info(peer, tlli_info);
|
||||
tlli_already_known = 1;
|
||||
}
|
||||
|
||||
OSMO_ASSERT(tlli_info != NULL);
|
||||
|
||||
if (!tlli_already_known)
|
||||
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n", tlli);
|
||||
|
||||
gbproxy_attach_tlli_info(peer, now, tlli_info);
|
||||
gbproxy_update_tlli_info(tlli_info, imsi, imsi_len);
|
||||
|
||||
if (enable_patching >= 0)
|
||||
tlli_info->enable_patching = enable_patching;
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
static void gbproxy_unregister_tlli(struct gbproxy_peer *peer, uint32_t tlli)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
|
||||
tlli_info = gbproxy_find_tlli(peer, tlli);
|
||||
if (tlli_info) {
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Removing TLLI %08x from list\n",
|
||||
tlli);
|
||||
gbproxy_delete_tlli(peer, tlli_info);
|
||||
}
|
||||
}
|
||||
|
||||
int gbproxy_check_tlli(struct gbproxy_peer *peer, uint32_t tlli)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info;
|
||||
|
||||
LOGP(DGPRS, LOGL_INFO, "Checking TLLI %08x, class: %d\n",
|
||||
tlli, gprs_tlli_type(tlli));
|
||||
|
||||
if (!peer->cfg->check_imsi)
|
||||
return 1;
|
||||
|
||||
tlli_info = gbproxy_find_tlli(peer, tlli);
|
||||
|
||||
return tlli_info != NULL && tlli_info->enable_patching;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
if (parse_ctx->tlli_enc)
|
||||
tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
if (parse_ctx->tlli_enc && parse_ctx->llc) {
|
||||
uint32_t sgsn_tlli;
|
||||
if (!tlli_info) {
|
||||
tlli_info =
|
||||
gbproxy_register_tlli(peer, parse_ctx->tlli,
|
||||
parse_ctx->imsi,
|
||||
parse_ctx->imsi_len, now);
|
||||
/* Setup TLLIs */
|
||||
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
|
||||
parse_ctx->tlli);
|
||||
tlli_info->sgsn_tlli.current = sgsn_tlli;
|
||||
} else {
|
||||
sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
|
||||
if (!sgsn_tlli)
|
||||
sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
|
||||
parse_ctx->tlli);
|
||||
|
||||
gbproxy_validate_tlli(&tlli_info->tlli,
|
||||
parse_ctx->tlli, 0);
|
||||
gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
|
||||
sgsn_tlli, 0);
|
||||
gbproxy_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
} else if (tlli_info) {
|
||||
gbproxy_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi && tlli_info && tlli_info->mi_data_len == 0) {
|
||||
int enable_patching;
|
||||
gbproxy_update_tlli_info(tlli_info,
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
/* Check, whether the IMSI matches */
|
||||
enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
|
||||
parse_ctx->imsi_len);
|
||||
if (enable_patching >= 0)
|
||||
tlli_info->enable_patching = enable_patching;
|
||||
}
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
|
||||
struct gbproxy_peer *peer,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
struct gbproxy_tlli_info *tlli_info = NULL;
|
||||
|
||||
if (parse_ctx->tlli_enc)
|
||||
tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
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_sgsn_ptmsi;
|
||||
uint32_t new_sgsn_tlli;
|
||||
uint32_t new_bss_ptmsi;
|
||||
uint32_t new_bss_tlli = 0;
|
||||
if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
|
||||
&new_sgsn_ptmsi)) {
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"Failed to parse new TLLI/PTMSI (current is %08x)\n",
|
||||
parse_ctx->tlli);
|
||||
return tlli_info;
|
||||
}
|
||||
new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
|
||||
new_bss_ptmsi = gbproxy_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) from SGSN, using %08x(%08x)\n",
|
||||
new_sgsn_tlli, new_sgsn_ptmsi, new_bss_tlli, new_bss_ptmsi);
|
||||
if (tlli_info) {
|
||||
gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
|
||||
peer, new_sgsn_tlli);
|
||||
gbproxy_reassign_tlli(&tlli_info->tlli,
|
||||
peer, new_bss_tlli);
|
||||
gbproxy_touch_tlli(peer, tlli_info, now);
|
||||
} else {
|
||||
tlli_info = gbproxy_tlli_info_alloc(peer);
|
||||
LOGP(DGPRS, LOGL_INFO,
|
||||
"Adding TLLI %08x to list (SGSN, new P-TMSI)\n",
|
||||
new_sgsn_tlli);
|
||||
|
||||
gbproxy_attach_tlli_info(peer, now, tlli_info);
|
||||
/* Setup TLLIs */
|
||||
tlli_info->sgsn_tlli.current = new_sgsn_tlli;
|
||||
}
|
||||
/* 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 = gbproxy_tlli_info_alloc(peer);
|
||||
LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
|
||||
parse_ctx->tlli);
|
||||
|
||||
gbproxy_attach_tlli_info(peer, now, tlli_info);
|
||||
/* Setup TLLIs */
|
||||
tlli_info->sgsn_tlli.current = parse_ctx->tlli;
|
||||
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 {
|
||||
tlli_info->tlli.current = tlli_info->sgsn_tlli.current;
|
||||
}
|
||||
} else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
|
||||
uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
|
||||
tlli_info, 1);
|
||||
gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
|
||||
gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
|
||||
gbproxy_touch_tlli(peer, tlli_info, now);
|
||||
} else if (tlli_info) {
|
||||
gbproxy_touch_tlli(peer, tlli_info, now);
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi && tlli_info && tlli_info->mi_data_len == 0) {
|
||||
int enable_patching;
|
||||
gbproxy_update_tlli_info(tlli_info,
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
|
||||
/* Check, whether the IMSI matches */
|
||||
enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
|
||||
parse_ctx->imsi_len);
|
||||
if (enable_patching >= 0)
|
||||
tlli_info->enable_patching = enable_patching;
|
||||
}
|
||||
|
||||
return tlli_info;
|
||||
}
|
||||
|
||||
void gbproxy_update_tlli_state_after(
|
||||
struct gbproxy_peer *peer,
|
||||
struct gbproxy_tlli_info *tlli_info,
|
||||
time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx)
|
||||
{
|
||||
if (parse_ctx->invalidate_tlli)
|
||||
gbproxy_unregister_tlli(peer, parse_ctx->tlli);
|
||||
|
||||
gbproxy_remove_stale_tllis(peer, now);
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +104,11 @@ static int config_write_gbproxy(struct vty *vty)
|
|||
else
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
if (g_cfg->patch_ptmsi > 0)
|
||||
vty_out(vty, " patch-ptmsi%s",
|
||||
VTY_NEWLINE);
|
||||
|
||||
if (g_cfg->tlli_max_age > 0)
|
||||
vty_out(vty, " tlli-list max-age %d%s",
|
||||
g_cfg->tlli_max_age, VTY_NEWLINE);
|
||||
|
@ -193,7 +198,7 @@ static int set_core_apn(struct vty *vty, const char *apn, const char *filter)
|
|||
talloc_free(g_cfg->core_apn);
|
||||
g_cfg->core_apn = NULL;
|
||||
g_cfg->core_apn_size = 0;
|
||||
gbprox_clear_patch_filter(g_cfg);
|
||||
gbproxy_clear_patch_filter(g_cfg);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -206,8 +211,8 @@ static int set_core_apn(struct vty *vty, const char *apn, const char *filter)
|
|||
}
|
||||
|
||||
if (!filter) {
|
||||
gbprox_clear_patch_filter(g_cfg);
|
||||
} else if (gbprox_set_patch_filter(g_cfg, filter, &err_msg) != 0) {
|
||||
gbproxy_clear_patch_filter(g_cfg);
|
||||
} else if (gbproxy_set_patch_filter(g_cfg, filter, &err_msg) != 0) {
|
||||
vty_out(vty, "Match expression invalid: %s%s",
|
||||
err_msg, VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
|
@ -268,6 +273,28 @@ DEFUN(cfg_gbproxy_no_core_apn,
|
|||
return set_core_apn(vty, NULL, NULL);
|
||||
}
|
||||
|
||||
#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
|
||||
|
||||
DEFUN(cfg_gbproxy_patch_ptmsi,
|
||||
cfg_gbproxy_patch_ptmsi_cmd,
|
||||
"patch-ptmsi",
|
||||
GBPROXY_PATCH_PTMSI_STR)
|
||||
{
|
||||
g_cfg->patch_ptmsi = 1;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_gbproxy_no_patch_ptmsi,
|
||||
cfg_gbproxy_no_patch_ptmsi_cmd,
|
||||
"no patch-ptmsi",
|
||||
NO_STR GBPROXY_PATCH_PTMSI_STR)
|
||||
{
|
||||
g_cfg->patch_ptmsi = 0;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
|
||||
#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
|
||||
|
||||
|
@ -377,7 +404,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);
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +422,7 @@ DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
|
|||
const uint16_t bvci = atoi(argv[1]);
|
||||
int counter;
|
||||
|
||||
counter = gbprox_cleanup_peers(g_cfg, nsei, bvci);
|
||||
counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
|
||||
|
||||
if (counter == 0) {
|
||||
vty_out(vty, "BVC not found%s", VTY_NEWLINE);
|
||||
|
@ -431,7 +458,7 @@ DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
|
|||
|
||||
if (delete_bvc) {
|
||||
if (!dry_run)
|
||||
counter = gbprox_cleanup_peers(g_cfg, nsei, 0);
|
||||
counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
|
||||
else {
|
||||
struct gbproxy_peer *peer;
|
||||
counter = 0;
|
||||
|
@ -514,7 +541,7 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
|
|||
break;
|
||||
}
|
||||
|
||||
peer = gbprox_peer_by_nsei(g_cfg, nsei);
|
||||
peer = gbproxy_peer_by_nsei(g_cfg, nsei);
|
||||
if (!peer) {
|
||||
vty_out(vty, "Didn't find peer with NSEI %d%s",
|
||||
nsei, VTY_NEWLINE);
|
||||
|
@ -524,7 +551,7 @@ DEFUN(delete_gb_tlli, delete_gb_tlli_cmd,
|
|||
state = &peer->patch_state;
|
||||
|
||||
if (match == MATCH_STALE) {
|
||||
found = gbprox_remove_stale_tllis(peer, time(NULL));
|
||||
found = gbproxy_remove_stale_tllis(peer, time(NULL));
|
||||
if (found)
|
||||
vty_out(vty, "Deleted %d stale TLLI%s%s",
|
||||
found, found == 1 ? "" : "s", VTY_NEWLINE);
|
||||
|
@ -532,7 +559,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,8 +571,9 @@ 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);
|
||||
gbprox_delete_tlli(peer, tlli_info);
|
||||
vty_out(vty, "Deleting TLLI %08x%s", tlli_info->tlli.current,
|
||||
VTY_NEWLINE);
|
||||
gbproxy_delete_tlli(peer, tlli_info);
|
||||
found += 1;
|
||||
}
|
||||
|
||||
|
@ -574,11 +602,13 @@ int gbproxy_vty_init(void)
|
|||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_match_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_age_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_len_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_no_max_age_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_no_max_len_cmd);
|
||||
install_element(GBPROXY_NODE, &cfg_gbproxy_patch_mode_cmd);
|
||||
|
|
|
@ -0,0 +1,642 @@
|
|||
/* 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 <openbsc/gprs_gb_parse.h>
|
||||
|
||||
#include <openbsc/gprs_utils.h>
|
||||
|
||||
#include <openbsc/gsm_04_08_gprs.h>
|
||||
#include <openbsc/gsm_data_shared.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
/* TODO: Move shift functions to libosmocore */
|
||||
|
||||
int v_fixed_shift(uint8_t **data, size_t *data_len,
|
||||
size_t len, uint8_t **value)
|
||||
{
|
||||
if (len > *data_len)
|
||||
goto fail;
|
||||
|
||||
if (value)
|
||||
*value = *data;
|
||||
|
||||
*data += len;
|
||||
*data_len -= len;
|
||||
|
||||
return len;
|
||||
|
||||
fail:
|
||||
*data += *data_len;
|
||||
*data_len = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tv_fixed_match(uint8_t **data, size_t *data_len,
|
||||
uint8_t tag, size_t len,
|
||||
uint8_t **value)
|
||||
{
|
||||
size_t ie_len;
|
||||
|
||||
if (*data_len == 0)
|
||||
goto fail;
|
||||
|
||||
if ((*data)[0] != tag)
|
||||
return 0;
|
||||
|
||||
if (len > *data_len - 1)
|
||||
goto fail;
|
||||
|
||||
if (value)
|
||||
*value = *data + 1;
|
||||
|
||||
ie_len = len + 1;
|
||||
*data += ie_len;
|
||||
*data_len -= ie_len;
|
||||
|
||||
return ie_len;
|
||||
|
||||
fail:
|
||||
*data += *data_len;
|
||||
*data_len = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tlv_match(uint8_t **data, size_t *data_len,
|
||||
uint8_t tag, uint8_t **value, size_t *value_len)
|
||||
{
|
||||
size_t len;
|
||||
size_t ie_len;
|
||||
|
||||
if (*data_len < 2)
|
||||
goto fail;
|
||||
|
||||
if ((*data)[0] != tag)
|
||||
return 0;
|
||||
|
||||
len = (*data)[1];
|
||||
if (len > *data_len - 2)
|
||||
goto fail;
|
||||
|
||||
if (value)
|
||||
*value = *data + 2;
|
||||
if (value_len)
|
||||
*value_len = len;
|
||||
|
||||
ie_len = len + 2;
|
||||
|
||||
*data += ie_len;
|
||||
*data_len -= ie_len;
|
||||
|
||||
return ie_len;
|
||||
|
||||
fail:
|
||||
*data += *data_len;
|
||||
*data_len = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lv_shift(uint8_t **data, size_t *data_len,
|
||||
uint8_t **value, size_t *value_len)
|
||||
{
|
||||
size_t len;
|
||||
size_t ie_len;
|
||||
|
||||
if (*data_len < 1)
|
||||
goto fail;
|
||||
|
||||
len = (*data)[0];
|
||||
if (len > *data_len - 1)
|
||||
goto fail;
|
||||
|
||||
if (value)
|
||||
*value = *data + 1;
|
||||
if (value_len)
|
||||
*value_len = len;
|
||||
|
||||
ie_len = len + 1;
|
||||
*data += ie_len;
|
||||
*data_len -= ie_len;
|
||||
|
||||
return ie_len;
|
||||
|
||||
fail:
|
||||
*data += *data_len;
|
||||
*data_len = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
|
||||
value_len < 1 || value_len > 2)
|
||||
/* invalid */
|
||||
return 0;;
|
||||
|
||||
/* Skip Attach type */
|
||||
/* Skip Ciphering key sequence number */
|
||||
/* Skip DRX parameter */
|
||||
v_fixed_shift(&data, &data_len, 3, NULL);
|
||||
|
||||
/* Get Mobile identity */
|
||||
if (lv_shift(&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;
|
||||
} else if (gprs_is_mi_imsi(value, value_len)) {
|
||||
parse_ctx->imsi = value;
|
||||
parse_ctx->imsi_len = value_len;
|
||||
}
|
||||
|
||||
if (v_fixed_shift(&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 */
|
||||
v_fixed_shift(&data, &data_len, 3, NULL);
|
||||
|
||||
if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
|
||||
return 0;
|
||||
|
||||
parse_ctx->raid_enc = value;
|
||||
|
||||
/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
|
||||
tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
|
||||
|
||||
/* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
|
||||
tv_fixed_match(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
|
||||
|
||||
/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
|
||||
if (tlv_match(&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;
|
||||
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 (v_fixed_shift(&data, &data_len, 1, &value) <= 0)
|
||||
/* invalid */
|
||||
return 0;
|
||||
|
||||
detach_type = *value & 0x07;
|
||||
power_off = *value & 0x08 ? 1 : 0;
|
||||
|
||||
if (!parse_ctx->to_bss) {
|
||||
/* Mobile originated */
|
||||
|
||||
if (power_off)
|
||||
parse_ctx->invalidate_tlli = 1;
|
||||
|
||||
/* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
|
||||
if (tlv_match(&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;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
v_fixed_shift(&data, &data_len, 1, NULL);
|
||||
|
||||
if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
|
||||
return 0;
|
||||
|
||||
parse_ctx->old_raid_enc = value;
|
||||
|
||||
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 */
|
||||
v_fixed_shift(&data, &data_len, 2, NULL);
|
||||
|
||||
if (v_fixed_shift(&data, &data_len, 6, &value) <= 0)
|
||||
return 0;
|
||||
|
||||
parse_ctx->raid_enc = value;
|
||||
|
||||
/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
|
||||
tv_fixed_match(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
|
||||
|
||||
/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
|
||||
if (tlv_match(&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;
|
||||
|
||||
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 (lv_shift(&data, &data_len, &value, &value_len) > 0 &&
|
||||
gprs_is_mi_tmsi(value, value_len))
|
||||
parse_ctx->new_ptmsi_enc = value;
|
||||
|
||||
if (v_fixed_shift(&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 (lv_shift(&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;
|
||||
} 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 */
|
||||
v_fixed_shift(&data, &data_len, 2, NULL);
|
||||
|
||||
/* Skip Requested QoS (support 04.08 and 24.008) */
|
||||
if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
|
||||
value_len < 4 || value_len > 14)
|
||||
/* invalid */
|
||||
return 0;;
|
||||
|
||||
/* Skip Requested PDP address */
|
||||
if (lv_shift(&data, &data_len, NULL, &value_len) <= 0 ||
|
||||
value_len < 2 || value_len > 18)
|
||||
/* invalid */
|
||||
return 0;
|
||||
|
||||
/* Access point name */
|
||||
old_len = tlv_match(&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;
|
||||
|
||||
if (v_fixed_shift(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
|
||||
return 0;
|
||||
|
||||
parse_ctx->g48_hdr = g48h;
|
||||
|
||||
if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS &&
|
||||
(g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS)
|
||||
return 1;
|
||||
|
||||
switch (g48h->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_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_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;
|
||||
|
||||
default:
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (bssgp_tlv_parse(tp, data, data_len) < 0)
|
||||
return 0;
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
/* TODO: This is TLLI old, don't confuse with TLLI current, add
|
||||
* and use tlli_old_enc instead */
|
||||
if (0 && TLVP_PRESENT(tp, BSSGP_IE_TLLI))
|
||||
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->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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx,
|
||||
const char *default_msg_name)
|
||||
{
|
||||
const char *msg_name = default_msg_name;
|
||||
const char *sep = "";
|
||||
|
||||
if (!parse_ctx->tlli_enc &&
|
||||
!parse_ctx->ptmsi_enc &&
|
||||
!parse_ctx->new_ptmsi_enc &&
|
||||
!parse_ctx->imsi)
|
||||
return;
|
||||
|
||||
if (parse_ctx->llc_msg_name)
|
||||
msg_name = parse_ctx->llc_msg_name;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s: Got", msg_name);
|
||||
|
||||
if (parse_ctx->tlli_enc) {
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s TLLI %08x", sep, parse_ctx->tlli);
|
||||
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;
|
||||
ok = gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN, &ptmsi);
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s PTMSI %08x%s",
|
||||
sep, ptmsi, ok ? "" : " (parse error)");
|
||||
sep = ",";
|
||||
}
|
||||
|
||||
if (parse_ctx->new_ptmsi_enc) {
|
||||
uint32_t new_ptmsi = GSM_RESERVED_TMSI;
|
||||
int ok;
|
||||
ok = gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
|
||||
&new_ptmsi);
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s new PTMSI %08x%s",
|
||||
sep, new_ptmsi, ok ? "" : " (parse error)");
|
||||
sep = ",";
|
||||
}
|
||||
|
||||
if (parse_ctx->imsi) {
|
||||
char mi_buf[200];
|
||||
mi_buf[0] = '\0';
|
||||
gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
|
||||
parse_ctx->imsi, parse_ctx->imsi_len);
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s IMSI %s",
|
||||
sep, mi_buf);
|
||||
sep = ",";
|
||||
}
|
||||
if (parse_ctx->invalidate_tlli) {
|
||||
LOGP(DGPRS, LOGL_DEBUG, "%s invalidate", sep);
|
||||
sep = ",";
|
||||
}
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG, "\n");
|
||||
}
|
||||
|
|
@ -24,6 +24,8 @@
|
|||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* FIXME: this needs to go to libosmocore/msgb.c */
|
||||
|
@ -162,3 +164,40 @@ int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
|
|||
return len;
|
||||
}
|
||||
|
||||
/* GSM 04.08, 10.5.1.4 */
|
||||
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len)
|
||||
{
|
||||
if (value_len != GSM48_TMSI_LEN)
|
||||
return 0;
|
||||
|
||||
if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_TMSI)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* GSM 04.08, 10.5.1.4 */
|
||||
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len)
|
||||
{
|
||||
if (value_len == 0)
|
||||
return 0;
|
||||
|
||||
if (!value || (value[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi)
|
||||
{
|
||||
uint32_t tmsi_be;
|
||||
|
||||
if (!gprs_is_mi_tmsi(value, value_len))
|
||||
return 0;
|
||||
|
||||
memcpy(&tmsi_be, value + 1, sizeof(tmsi_be));
|
||||
|
||||
*tmsi = ntohl(tmsi_be);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ noinst_PROGRAMS = gbproxy_test
|
|||
gbproxy_test_SOURCES = gbproxy_test.c
|
||||
gbproxy_test_LDADD = \
|
||||
$(top_builddir)/src/gprs/gb_proxy.o \
|
||||
$(top_builddir)/src/gprs/gb_proxy_patch.o \
|
||||
$(top_builddir)/src/gprs/gb_proxy_peer.o \
|
||||
$(top_builddir)/src/gprs/gb_proxy_tlli.o \
|
||||
$(top_builddir)/src/gprs/gprs_gb_parse.o \
|
||||
$(top_builddir)/src/gprs/gprs_llc_parse.o \
|
||||
$(top_builddir)/src/gprs/crc24.o \
|
||||
$(top_builddir)/src/gprs/gprs_utils.o \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1666,10 +1666,10 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 44
|
|||
result (IDENT RESPONSE) = 44
|
||||
|
||||
PROCESSING ATTACH ACCEPT from 0x05060708:32000
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 42 67 9a
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1
|
||||
|
||||
CALLBACK, event 0, msg length 88, bvci 0x1002
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 42 67 9a
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 92
|
||||
|
@ -1677,6 +1677,18 @@ MESSAGE to BSS at 0x01020304:1111, msg length 92
|
|||
|
||||
result (ATTACH ACCEPT) = 92
|
||||
|
||||
PROCESSING ATTACH COMPLETE 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 08 01 c0 11 08 03 ea 67 11
|
||||
|
||||
CALLBACK, event 0, msg length 31, bvci 0x1002
|
||||
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 08 01 c0 11 08 03 ea 67 11
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 35
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 08 01 c0 11 08 03 ea 67 11
|
||||
|
||||
result (ATTACH COMPLETE) = 35
|
||||
|
||||
PROCESSING ACT PDP CTX REQ (REPLACE APN) 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 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02
|
||||
|
||||
|
@ -1727,13 +1739,13 @@ result (ACT PDP CTX REQ (REMOVE APN)) = 75
|
|||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 8
|
||||
RAID patched (BSS ): 9
|
||||
RAID patched (SGSN): 2
|
||||
APN patched : 3
|
||||
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
|
||||
|
||||
|
@ -1760,7 +1772,7 @@ result (DETACH ACC) = 71
|
|||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 9
|
||||
RAID patched (BSS ): 10
|
||||
RAID patched (SGSN): 2
|
||||
APN patched : 3
|
||||
Attach Request count : 1
|
||||
|
@ -1780,16 +1792,16 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 89
|
|||
result (RA UPD REQ) = 89
|
||||
|
||||
PROCESSING RA UPD ACC from 0x05060708:32000
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 9d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 0a 82 07 04 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 81 17 17 16 c3 bf cc
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 d7 59 65
|
||||
|
||||
CALLBACK, event 0, msg length 91, bvci 0x1002
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 9d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 0a 82 07 04 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 81 17 17 16 c3 bf cc
|
||||
CALLBACK, event 0, msg length 87, bvci 0x1002
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 d7 59 65
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 91 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 95
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 9d 19 13 42 33 57 2b f7 c8 48 02 13 48 50 c8 48 02 14 48 50 c8 48 02 17 49 10 c8 48 02 00 0a 82 07 04 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 ef e2 81 17 17 16 2e e5 fd
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 91
|
||||
00 00 10 02 00 bb c5 46 79 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9d 41 c0 19 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 3a 03 54
|
||||
|
||||
result (RA UPD ACC) = 95
|
||||
result (RA UPD ACC) = 91
|
||||
|
||||
PROCESSING ACT PDP CTX REQ (REMOVE APN) 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 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02
|
||||
|
@ -1797,56 +1809,41 @@ PROCESSING ACT PDP CTX REQ (REMOVE APN) from 0x01020304:1111
|
|||
CALLBACK, event 0, msg length 76, bvci 0x1002
|
||||
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 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 76 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 80
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 35 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 03 02 61 62 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 5a ff 02
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 71 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 75
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 30 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 85 fa 60
|
||||
|
||||
result (ACT PDP CTX REQ (REMOVE APN)) = 80
|
||||
result (ACT PDP CTX REQ (REMOVE APN)) = 75
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 12
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 3
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 2
|
||||
TLLI-Cache: 2
|
||||
TLLI efe2b700, IMSI (none), AGE 0
|
||||
TLLI efe28117, 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
|
||||
|
||||
CALLBACK, event 0, msg length 44, bvci 0x1002
|
||||
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
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 48
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 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
|
||||
|
||||
result (DETACH REQ) = 48
|
||||
|
||||
PROCESSING DETACH ACC from 0x05060708:32000
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0
|
||||
|
||||
CALLBACK, event 0, msg length 67, bvci 0x1002
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 71
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 15 08 06 00 f7 35 f0
|
||||
|
||||
result (DETACH ACC) = 71
|
||||
|
||||
Gbproxy global:
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 13
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 3
|
||||
APN patched : 4
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI efe28117, 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
|
||||
|
||||
CALLBACK, event 0, msg length 44, bvci 0x1002
|
||||
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
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 48
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 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
|
||||
|
||||
result (DETACH REQ (PWR OFF)) = 48
|
||||
|
||||
Gbproxy global:
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 14
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 4
|
||||
Attach Request count : 1
|
||||
TLLI-Cache: 0
|
||||
--- Bad cases ---
|
||||
|
||||
TLLI is already detached, shouldn't patch
|
||||
|
@ -1880,14 +1877,391 @@ Gbproxy global:
|
|||
Patch error: no peer : 1
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 14
|
||||
RAID patched (BSS ): 15
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 3
|
||||
APN patched : 4
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 2
|
||||
TLLI-Cache: 2
|
||||
TLLI efe2b700, IMSI (none), AGE 0
|
||||
TLLI efe28117, IMSI 12131415161718, AGE 0
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI efe2b700 -> efe2b700, IMSI (none), AGE 0
|
||||
=== test_gbproxy_ptmsi_patching ===
|
||||
--- Initialise SGSN ---
|
||||
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 12
|
||||
02 00 81 01 01 82 01 01 04 82 01 00
|
||||
|
||||
PROCESSING RESET_ACK from 0x05060708:32000
|
||||
03 01 82 01 01 04 82 01 00
|
||||
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 1
|
||||
0a
|
||||
|
||||
result (RESET_ACK) = 1
|
||||
|
||||
PROCESSING ALIVE_ACK from 0x05060708:32000
|
||||
0b
|
||||
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 1
|
||||
06
|
||||
|
||||
result (ALIVE_ACK) = 1
|
||||
|
||||
PROCESSING UNBLOCK_ACK from 0x05060708:32000
|
||||
07
|
||||
|
||||
==> got signal NS_UNBLOCK, NS-VC 0x0101/5.6.7.8:32000
|
||||
|
||||
result (UNBLOCK_ACK) = 0
|
||||
|
||||
PROCESSING ALIVE from 0x05060708:32000
|
||||
0a
|
||||
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 1
|
||||
0b
|
||||
|
||||
result (ALIVE) = 1
|
||||
|
||||
--- Initialise BSS 1 ---
|
||||
|
||||
Setup NS-VC: remote 0x01020304:1111, NSVCI 0x1001(4097), NSEI 0x1000(4096)
|
||||
|
||||
PROCESSING RESET from 0x01020304:1111
|
||||
02 00 81 01 01 82 10 01 04 82 10 00
|
||||
|
||||
==> got signal NS_RESET, NS-VC 0x1001/1.2.3.4:1111
|
||||
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 9
|
||||
03 01 82 10 01 04 82 10 00
|
||||
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 1
|
||||
0a
|
||||
|
||||
result (RESET) = 9
|
||||
|
||||
PROCESSING ALIVE from 0x01020304:1111
|
||||
0a
|
||||
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 1
|
||||
0b
|
||||
|
||||
result (ALIVE) = 1
|
||||
|
||||
PROCESSING UNBLOCK from 0x01020304:1111
|
||||
06
|
||||
|
||||
==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111
|
||||
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 1
|
||||
07
|
||||
|
||||
result (UNBLOCK) = 1
|
||||
|
||||
PROCESSING ALIVE_ACK from 0x01020304:1111
|
||||
0b
|
||||
|
||||
result (ALIVE_ACK) = 0
|
||||
|
||||
Setup BSSGP: remote 0x01020304:1111, BVCI 0x1002(4098)
|
||||
|
||||
PROCESSING BVC_RESET from 0x01020304:1111
|
||||
00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00
|
||||
|
||||
CALLBACK, event 0, msg length 18, bvci 0x0000
|
||||
00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 22
|
||||
00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00
|
||||
|
||||
result (BVC_RESET) = 22
|
||||
|
||||
PROCESSING BVC_RESET_ACK from 0x05060708:32000
|
||||
00 00 00 00 23 04 82 10 02
|
||||
|
||||
CALLBACK, event 0, msg length 5, bvci 0x0000
|
||||
00 00 00 00 23 04 82 10 02
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 9
|
||||
00 00 00 00 23 04 82 10 02
|
||||
|
||||
result (BVC_RESET_ACK) = 9
|
||||
|
||||
PROCESSING BVC_SUSPEND from 0x01020304:1111
|
||||
00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60
|
||||
|
||||
CALLBACK, event 0, msg length 15, bvci 0x0000
|
||||
00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 19
|
||||
00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60
|
||||
|
||||
result (BVC_SUSPEND) = 19
|
||||
|
||||
PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
|
||||
00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01
|
||||
|
||||
CALLBACK, event 0, msg length 18, bvci 0x0000
|
||||
00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 22
|
||||
00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 1d 81 01
|
||||
|
||||
result (BVC_SUSPEND_ACK) = 22
|
||||
|
||||
Current NS-VCIs:
|
||||
VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111
|
||||
VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000
|
||||
NS-VC Block count : 1
|
||||
|
||||
Gbproxy global:
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 2
|
||||
RAID patched (SGSN): 1
|
||||
TLLI-Cache: 0
|
||||
--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
|
||||
|
||||
PROCESSING ATTACH REQUEST from 0x01020304:1111
|
||||
00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01
|
||||
|
||||
CALLBACK, event 0, msg length 75, bvci 0x1002
|
||||
00 00 10 02 01 80 00 de ad 00 00 04 08 88 00 f1 99 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 79
|
||||
00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 11 22 33 40 50 60 19 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 16 6d 01
|
||||
|
||||
result (ATTACH REQUEST) = 79
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 3
|
||||
RAID patched (SGSN): 1
|
||||
TLLI patched (BSS ): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0
|
||||
PROCESSING IDENT REQUEST from 0x05060708:32000
|
||||
00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
|
||||
|
||||
CALLBACK, event 0, msg length 23, bvci 0x1002
|
||||
00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 27
|
||||
00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba
|
||||
|
||||
result (IDENT REQUEST) = 27
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 3
|
||||
RAID patched (SGSN): 1
|
||||
TLLI patched (BSS ): 1
|
||||
TLLI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0
|
||||
PROCESSING IDENT RESPONSE from 0x01020304:1111
|
||||
00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28
|
||||
|
||||
CALLBACK, event 0, msg length 40, bvci 0x1002
|
||||
00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 44
|
||||
00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28
|
||||
|
||||
result (IDENT RESPONSE) = 44
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 4
|
||||
RAID patched (SGSN): 1
|
||||
TLLI patched (BSS ): 2
|
||||
TLLI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0
|
||||
PROCESSING ATTACH ACCEPT from 0x05060708:32000
|
||||
00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1
|
||||
|
||||
CALLBACK, event 0, msg length 88, bvci 0x1002
|
||||
00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 53 62 f1
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 92
|
||||
00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 9e 41 c0 05 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 0f 73 04 50 22 97
|
||||
|
||||
result (ATTACH ACCEPT) = 92
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 4
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 2
|
||||
TLLI patched (SGSN): 2
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING ATTACH COMPLETE from 0x01020304:1111
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc
|
||||
|
||||
CALLBACK, event 0, msg length 31, bvci 0x1002
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 35
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc
|
||||
|
||||
result (ATTACH COMPLETE) = 35
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 5
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 3
|
||||
TLLI patched (SGSN): 2
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING GMM INFO from 0x05060708:32000
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d
|
||||
|
||||
CALLBACK, event 0, msg length 66, bvci 0x1002
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 70
|
||||
00 00 10 02 00 c0 0f 73 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 88 41 c0 09 08 21 04 ba 3d
|
||||
|
||||
result (GMM INFO) = 70
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 5
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 3
|
||||
TLLI patched (SGSN): 3
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING XID (UL) from 0x01020304:1111
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28
|
||||
|
||||
CALLBACK, event 0, msg length 38, bvci 0x1002
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 42
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28
|
||||
|
||||
result (XID (UL)) = 42
|
||||
|
||||
PROCESSING XID (DL) from 0x05060708:32000
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e
|
||||
|
||||
CALLBACK, event 0, msg length 70, bvci 0x1002
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 74
|
||||
00 00 10 02 00 c0 0f 73 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e
|
||||
|
||||
result (XID (DL)) = 74
|
||||
|
||||
PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07
|
||||
|
||||
CALLBACK, event 0, msg length 89, bvci 0x1002
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 93
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07
|
||||
|
||||
result (LL11 DNS QUERY (UL)) = 93
|
||||
|
||||
PROCESSING LL11 DNS RESP (DL) from 0x05060708:32000
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31
|
||||
|
||||
CALLBACK, event 0, msg length 267, bvci 0x1002
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 271
|
||||
00 00 10 02 00 c0 0f 73 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31
|
||||
|
||||
result (LL11 DNS RESP (DL)) = 271
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 7
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 5
|
||||
TLLI patched (SGSN): 5
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING DETACH REQ from 0x01020304:1111
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6
|
||||
|
||||
CALLBACK, event 0, msg length 44, bvci 0x1002
|
||||
00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 48
|
||||
00 00 10 02 01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6
|
||||
|
||||
result (DETACH REQ) = 48
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 8
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 6
|
||||
TLLI patched (SGSN): 5
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI cache size : 1
|
||||
TLLI-Cache: 1
|
||||
TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0
|
||||
PROCESSING DETACH ACC from 0x05060708:32000
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee
|
||||
|
||||
CALLBACK, event 0, msg length 67, bvci 0x1002
|
||||
00 00 10 02 00 ef e2 b7 00 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee
|
||||
|
||||
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg)
|
||||
MESSAGE to BSS at 0x01020304:1111, msg length 71
|
||||
00 00 10 02 00 c0 0f 73 04 00 50 20 16 82 02 58 13 99 18 b3 43 2b 25 96 62 00 60 80 9a c2 c6 62 00 60 80 ba c8 c6 62 00 60 80 00 0a 82 08 02 0d 88 11 12 13 14 15 16 17 18 00 81 00 0e 89 41 c0 0d 08 06 00 aa ab ee
|
||||
|
||||
result (DETACH ACC) = 71
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 8
|
||||
RAID patched (SGSN): 2
|
||||
TLLI patched (BSS ): 6
|
||||
TLLI patched (SGSN): 6
|
||||
P-TMSI patched (SGSN): 1
|
||||
Attach Request count : 1
|
||||
TLLI-Cache: 0
|
||||
Gbproxy global:
|
||||
Test TLLI info expiry
|
||||
|
||||
Test TLLI replacement:
|
||||
|
|
Loading…
Reference in New Issue