mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 13:03:33 +00:00
gprs: Store gbproxy patching state per peer
Currently, all patching state is stored globally in the gbproxy. Thus the feature cannot be used safely with a concentrating gbproxy (NAT). This patch moves the state and relevant counters to the gbprox_peer structure. It adds code to resolve the corresponding peer when packets are received by looking at BVCI, NSEI, and BSSGP IEs (BVCI, RAI/LAI/LAC) when the peer is not passed to the gbprox_patch_bssgp_message() function. Test cases are also added for the SGSN->BSS case including test cases with invalid identifiers. Note that this patch should make it possible to use RAI patching at a NAT gbproxy as long as the messages are not encrypted. Ticket: OW#1185 Sponsored-by: On-Waves ehf
This commit is contained in:
committed by
Holger Hans Peter Freyther
parent
cf02eb1b20
commit
006c038212
@@ -59,11 +59,7 @@ enum gbprox_global_ctr {
|
||||
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
|
||||
GBPROX_GLOB_CTR_TX_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_OTHER_ERR,
|
||||
GBPROX_GLOB_CTR_RAID_PATCHED_BSS,
|
||||
GBPROX_GLOB_CTR_RAID_PATCHED_SGSN,
|
||||
GBPROX_GLOB_CTR_APN_PATCHED,
|
||||
GBPROX_GLOB_CTR_PATCH_CRYPT_ERR,
|
||||
GBPROX_GLOB_CTR_PATCH_ERR,
|
||||
GBPROX_GLOB_CTR_PATCH_PEER_ERR,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc global_ctr_description[] = {
|
||||
@@ -78,11 +74,7 @@ static const struct rate_ctr_desc global_ctr_description[] = {
|
||||
{ "restart.sgsn", "Restarted RESET procedure (SGSN)" },
|
||||
{ "tx-err.sgsn", "NS Transmission error (SGSN)" },
|
||||
{ "error", "Other error " },
|
||||
{ "raid-mod.bss", "RAID patched (BSS )" },
|
||||
{ "raid-mod.sgsn", "RAID patched (SGSN)" },
|
||||
{ "apn-mod.sgsn", "APN patched " },
|
||||
{ "mod-crypt-err", "Patch error: encrypted " },
|
||||
{ "mod-err", "Patch error: other " },
|
||||
{ "mod-peer-err", "Patch error: no peer " },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc global_ctrg_desc = {
|
||||
@@ -109,14 +101,24 @@ enum gbprox_peer_ctr {
|
||||
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_PATCH_CRYPT_ERR,
|
||||
GBPROX_PEER_CTR_PATCH_ERR,
|
||||
};
|
||||
|
||||
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 " },
|
||||
{ "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 " },
|
||||
{ "mod-crypt-err", "Patch error: encrypted " },
|
||||
{ "mod-err", "Patch error: other " },
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc peer_ctrg_desc = {
|
||||
@@ -126,10 +128,10 @@ static const struct rate_ctr_group_desc peer_ctrg_desc = {
|
||||
.ctr_desc = peer_ctr_description,
|
||||
};
|
||||
|
||||
static struct gbprox_patch_state {
|
||||
struct gbprox_patch_state {
|
||||
int local_mnc;
|
||||
int local_mcc;
|
||||
} gbprox_patch_state = {0};
|
||||
};
|
||||
|
||||
struct gbprox_peer {
|
||||
struct llist_head list;
|
||||
@@ -146,6 +148,8 @@ struct gbprox_peer {
|
||||
|
||||
/* Counter */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
struct gbprox_patch_state patch_state;
|
||||
};
|
||||
|
||||
/* Linked list of all Gb peers (except SGSN) */
|
||||
@@ -195,6 +199,18 @@ static struct gbprox_peer *peer_by_lai(const uint8_t *la)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* look-up a peer by its Location Area Code (LAC) */
|
||||
static struct gbprox_peer *peer_by_lac(const uint8_t *la)
|
||||
{
|
||||
struct gbprox_peer *peer;
|
||||
llist_for_each_entry(peer, &gbprox_bts_peers, list) {
|
||||
if (!memcmp(peer->ra + 3, la + 3, 2))
|
||||
return peer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int check_peer_nsei(struct gbprox_peer *peer, uint16_t nsei)
|
||||
{
|
||||
if (peer->nsei != nsei) {
|
||||
@@ -379,9 +395,10 @@ static int patching_is_required(enum gbproxy_patch_mode need_at_least)
|
||||
}
|
||||
|
||||
/* patch RA identifier in place, update peer accordingly */
|
||||
static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *state,
|
||||
static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_peer *peer,
|
||||
int to_bss, const char *log_text)
|
||||
{
|
||||
struct gbprox_patch_state *state = &peer->patch_state;
|
||||
const int old_local_mcc = state->local_mcc;
|
||||
const int old_local_mnc = state->local_mnc;
|
||||
int old_mcc;
|
||||
@@ -431,10 +448,10 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *stat
|
||||
to_bss ? "BSS" : "SGSN");
|
||||
|
||||
if (state->local_mcc || state->local_mnc) {
|
||||
enum gbprox_global_ctr counter =
|
||||
enum gbprox_peer_ctr counter =
|
||||
to_bss ?
|
||||
GBPROX_GLOB_CTR_RAID_PATCHED_SGSN :
|
||||
GBPROX_GLOB_CTR_RAID_PATCHED_BSS;
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS;
|
||||
|
||||
LOGP(DGPRS, LOGL_DEBUG,
|
||||
"Patching %s to %s: "
|
||||
@@ -445,12 +462,13 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *stat
|
||||
raid.mcc, raid.mnc, raid.lac, raid.rac);
|
||||
|
||||
gsm48_construct_ra(raid_enc, &raid);
|
||||
rate_ctr_inc(&get_global_ctrg()->ctr[counter]);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[counter]);
|
||||
}
|
||||
}
|
||||
|
||||
static void gbprox_patch_apn_ie(struct msgb *msg,
|
||||
uint8_t *apn_ie, size_t apn_ie_len,
|
||||
struct gbprox_peer *peer,
|
||||
size_t *new_apn_ie_len, const char *log_text)
|
||||
{
|
||||
struct apn_ie_hdr {
|
||||
@@ -496,12 +514,12 @@ static void gbprox_patch_apn_ie(struct msgb *msg,
|
||||
hdr->apn_len = gbcfg.core_apn_size;
|
||||
}
|
||||
|
||||
rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_APN_PATCHED]);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
|
||||
}
|
||||
|
||||
static int gbprox_patch_gmm_attach_req(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
/* Check minimum length, always includes the RAI */
|
||||
@@ -528,14 +546,14 @@ static int gbprox_patch_gmm_attach_req(struct msgb *msg,
|
||||
data_len -= data[0] + 1;
|
||||
data += data[0] + 1;
|
||||
|
||||
gbprox_patch_raid(data, state, to_bss, "LLC/ATTACH_REQ");
|
||||
gbprox_patch_raid(data, peer, to_bss, "LLC/ATTACH_REQ");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbprox_patch_gmm_attach_ack(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
/* Check minimum length, always includes the RAI */
|
||||
@@ -550,14 +568,14 @@ static int gbprox_patch_gmm_attach_ack(struct msgb *msg,
|
||||
data_len -= 3;
|
||||
data += 3;
|
||||
|
||||
gbprox_patch_raid(data, state, to_bss, "LLC/ATTACH_ACK");
|
||||
gbprox_patch_raid(data, peer, to_bss, "LLC/ATTACH_ACK");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbprox_patch_gmm_ra_upd_req(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
/* Check minimum length, always includes the RAI */
|
||||
@@ -569,14 +587,14 @@ static int gbprox_patch_gmm_ra_upd_req(struct msgb *msg,
|
||||
data_len -= 1;
|
||||
data += 1;
|
||||
|
||||
gbprox_patch_raid(data, state, to_bss, "LLC/RA_UPD_REQ");
|
||||
gbprox_patch_raid(data, peer, to_bss, "LLC/RA_UPD_REQ");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbprox_patch_gmm_ra_upd_ack(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
/* Check minimum length, always includes the RAI */
|
||||
@@ -589,14 +607,14 @@ static int gbprox_patch_gmm_ra_upd_ack(struct msgb *msg,
|
||||
data_len -= 2;
|
||||
data += 2;
|
||||
|
||||
gbprox_patch_raid(data, state, to_bss, "LLC/RA_UPD_ACK");
|
||||
gbprox_patch_raid(data, peer, to_bss, "LLC/RA_UPD_ACK");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbprox_patch_gmm_ptmsi_reall_cmd(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
/* Check minimum length, always includes the RAI */
|
||||
@@ -610,14 +628,14 @@ static int gbprox_patch_gmm_ptmsi_reall_cmd(struct msgb *msg,
|
||||
data_len -= 6;
|
||||
data += 6;
|
||||
|
||||
gbprox_patch_raid(data, state, to_bss, "LLC/PTMSI_REALL_CMD");
|
||||
gbprox_patch_raid(data, peer, to_bss, "LLC/PTMSI_REALL_CMD");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int gbprox_patch_gsm_act_pdp_req(struct msgb *msg,
|
||||
uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state,
|
||||
struct gbprox_peer *peer,
|
||||
int to_bss, int *len_change)
|
||||
{
|
||||
size_t new_len, old_len;
|
||||
@@ -660,7 +678,7 @@ static int gbprox_patch_gsm_act_pdp_req(struct msgb *msg,
|
||||
|
||||
old_len = data[1] + 2;
|
||||
|
||||
gbprox_patch_apn_ie(msg, data, old_len, &new_len, "LLC/ACT_PDP_REQ");
|
||||
gbprox_patch_apn_ie(msg, data, old_len, peer, &new_len, "LLC/ACT_PDP_REQ");
|
||||
|
||||
*len_change += (int)new_len - (int)old_len;
|
||||
data_len -= old_len;
|
||||
@@ -669,8 +687,34 @@ static int gbprox_patch_gsm_act_pdp_req(struct msgb *msg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct gbprox_peer *peer_by_bssgp_tlv(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 peer_by_bvci(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 peer_by_lac(rai);
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {
|
||||
uint8_t *lai = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA);
|
||||
return peer_by_lac(lai);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len,
|
||||
struct gbprox_patch_state *state, int to_bss,
|
||||
struct gbprox_peer *peer, int to_bss,
|
||||
int *len_change)
|
||||
{
|
||||
struct gsm48_hdr *g48h;
|
||||
@@ -692,31 +736,31 @@ static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len,
|
||||
switch (g48h->msg_type) {
|
||||
case GSM48_MT_GMM_ATTACH_REQ:
|
||||
return gbprox_patch_gmm_attach_req(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
|
||||
case GSM48_MT_GMM_ATTACH_ACK:
|
||||
if (!patching_is_enabled(GBPROX_PATCH_LLC_ATTACH))
|
||||
break;
|
||||
return gbprox_patch_gmm_attach_ack(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
|
||||
case GSM48_MT_GMM_RA_UPD_REQ:
|
||||
if (!patching_is_enabled(GBPROX_PATCH_LLC_GMM))
|
||||
break;
|
||||
return gbprox_patch_gmm_ra_upd_req(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
|
||||
case GSM48_MT_GMM_RA_UPD_ACK:
|
||||
if (!patching_is_enabled(GBPROX_PATCH_LLC_GMM))
|
||||
break;
|
||||
return gbprox_patch_gmm_ra_upd_ack(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
|
||||
case GSM48_MT_GMM_PTMSI_REALL_CMD:
|
||||
if (!patching_is_enabled(GBPROX_PATCH_LLC_GMM))
|
||||
break;
|
||||
return gbprox_patch_gmm_ptmsi_reall_cmd(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
|
||||
case GSM48_MT_GSM_ACT_PDP_REQ:
|
||||
if (!patching_is_enabled(GBPROX_PATCH_LLC_GSM))
|
||||
@@ -724,7 +768,7 @@ static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len,
|
||||
if (gbcfg.core_apn == NULL)
|
||||
break;
|
||||
return gbprox_patch_gsm_act_pdp_req(msg, data, data_len,
|
||||
state, to_bss, len_change);
|
||||
peer, to_bss, len_change);
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@@ -733,7 +777,7 @@ static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len,
|
||||
}
|
||||
|
||||
static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbprox_patch_state *state, int to_bss)
|
||||
struct gbprox_peer *peer, int to_bss)
|
||||
{
|
||||
struct gprs_llc_hdr_parsed ghp = {0};
|
||||
int rc;
|
||||
@@ -773,7 +817,7 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
* message. */
|
||||
|
||||
err_info = "GMM message is encrypted";
|
||||
err_ctr = GBPROX_GLOB_CTR_PATCH_CRYPT_ERR;
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
|
||||
goto patch_error;
|
||||
}
|
||||
|
||||
@@ -784,7 +828,8 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
data = ghp.data;
|
||||
data_len = ghp.data_len;
|
||||
|
||||
rc = gbprox_patch_dtap(msg, data, data_len, state, to_bss, &len_change);
|
||||
rc = gbprox_patch_dtap(msg, data, data_len, peer, to_bss,
|
||||
&len_change);
|
||||
|
||||
if (rc > 0) {
|
||||
llc_len += len_change;
|
||||
@@ -795,7 +840,7 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
/* most probably a one byte length */
|
||||
if (llc_len > 127) {
|
||||
err_info = "Cannot increase size";
|
||||
err_ctr = GBPROX_GLOB_CTR_PATCH_ERR;
|
||||
err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
|
||||
goto patch_error;
|
||||
}
|
||||
llc[-1] = llc_len | 0x80;
|
||||
@@ -818,7 +863,7 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
|
||||
patch_error:
|
||||
OSMO_ASSERT(err_ctr >= 0);
|
||||
rate_ctr_inc(&get_global_ctrg()->ctr[err_ctr]);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
|
||||
LOGP(DGPRS, LOGL_ERROR,
|
||||
"Failed to patch BSSGP/GMM message as requested: %s.\n", err_info);
|
||||
|
||||
@@ -826,13 +871,14 @@ patch_error:
|
||||
}
|
||||
|
||||
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
|
||||
static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss)
|
||||
static void gbprox_patch_bssgp_message(struct msgb *msg,
|
||||
struct gbprox_peer *peer, int to_bss)
|
||||
{
|
||||
struct bssgp_normal_hdr *bgph;
|
||||
struct bssgp_ud_hdr *budh;
|
||||
struct tlv_parsed tp;
|
||||
uint8_t pdu_type;
|
||||
struct gbprox_patch_state *state = &gbprox_patch_state;
|
||||
struct gbprox_patch_state *state = NULL;
|
||||
uint8_t *data;
|
||||
size_t data_len;
|
||||
|
||||
@@ -843,9 +889,6 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss)
|
||||
budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg);
|
||||
pdu_type = bgph->pdu_type;
|
||||
|
||||
if (to_bss && !state->local_mcc && !state->local_mnc)
|
||||
return;
|
||||
|
||||
if (pdu_type == BSSGP_PDUT_UL_UNITDATA ||
|
||||
pdu_type == BSSGP_PDUT_DL_UNITDATA) {
|
||||
data = budh->data;
|
||||
@@ -857,32 +900,60 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss)
|
||||
|
||||
bssgp_tlv_parse(&tp, data, data_len);
|
||||
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA))
|
||||
if (!peer && msgb_bvci(msg) >= 2)
|
||||
peer = peer_by_bvci(msgb_bvci(msg));
|
||||
|
||||
if (!peer && !to_bss)
|
||||
peer = peer_by_nsei(msgb_nsei(msg));
|
||||
|
||||
if (!peer)
|
||||
peer = peer_by_bssgp_tlv(&tp);
|
||||
|
||||
if (!peer) {
|
||||
LOGP(DLLC, LOGL_INFO,
|
||||
"NSEI=%d(%s) patching: didn't find peer for message, "
|
||||
"PDU %d\n",
|
||||
msgb_nsei(msg), to_bss ? "SGSN" : "BSS", pdu_type);
|
||||
/* Increment counter */
|
||||
rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
|
||||
return;
|
||||
}
|
||||
|
||||
state = &peer->patch_state;
|
||||
|
||||
if (to_bss && !state->local_mcc && !state->local_mnc)
|
||||
return;
|
||||
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA)) {
|
||||
gbprox_patch_raid((uint8_t *)TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA),
|
||||
state, to_bss, "ROUTING_AREA");
|
||||
peer, to_bss, "ROUTING_AREA");
|
||||
}
|
||||
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID))
|
||||
gbprox_patch_raid((uint8_t *)TLVP_VAL(&tp, BSSGP_IE_CELL_ID),
|
||||
state, to_bss, "CELL_ID");
|
||||
peer, to_bss, "CELL_ID");
|
||||
|
||||
if (TLVP_PRESENT(&tp, BSSGP_IE_LLC_PDU) &&
|
||||
patching_is_enabled(GBPROX_PATCH_LLC_ATTACH_REQ)) {
|
||||
uint8_t *llc = (uint8_t *)TLVP_VAL(&tp, BSSGP_IE_LLC_PDU);
|
||||
size_t llc_len = TLVP_LEN(&tp, BSSGP_IE_LLC_PDU);
|
||||
gbprox_patch_llc(msg, llc, llc_len, state, to_bss);
|
||||
gbprox_patch_llc(msg, llc, llc_len, peer, to_bss);
|
||||
/* Note that the tp struct might contain invalid pointers here
|
||||
* if the LLC field has changed its size */
|
||||
}
|
||||
}
|
||||
|
||||
/* feed a message down the NS-VC associated with the specified peer */
|
||||
static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
|
||||
static int gbprox_relay2sgsn(struct msgb *old_msg,
|
||||
struct gbprox_peer *peer, uint16_t ns_bvci)
|
||||
{
|
||||
/* create a copy of the message so the old one can
|
||||
* be free()d safely when we return from gbprox_rcvmsg() */
|
||||
struct msgb *msg = msgb_copy(old_msg, "msgb_relay2sgsn");
|
||||
int rc;
|
||||
|
||||
gbprox_patch_bssgp_message(msg, peer, 0);
|
||||
|
||||
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
|
||||
msgb_nsei(msg), ns_bvci, gbcfg.nsip_sgsn_nsei);
|
||||
|
||||
@@ -891,8 +962,6 @@ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci)
|
||||
|
||||
strip_ns_hdr(msg);
|
||||
|
||||
gbprox_patch_bssgp_message(msg, 0);
|
||||
|
||||
rc = gprs_ns_sendmsg(bssgp_nsi, msg);
|
||||
if (rc < 0)
|
||||
rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]);
|
||||
@@ -983,7 +1052,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei,
|
||||
struct tlv_parsed tp;
|
||||
uint8_t pdu_type = bgph->pdu_type;
|
||||
int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
|
||||
struct gbprox_peer *from_peer;
|
||||
struct gbprox_peer *from_peer = NULL;
|
||||
struct gprs_ra_id raid;
|
||||
|
||||
if (ns_bvci != 0 && ns_bvci != 1) {
|
||||
@@ -1074,7 +1143,7 @@ static int gbprox_rx_sig_from_bss(struct msgb *msg, uint16_t nsei,
|
||||
|
||||
/* Normally, we can simply pass on all signalling messages from BSS to
|
||||
* SGSN */
|
||||
return gbprox_relay2sgsn(msg, ns_bvci);
|
||||
return gbprox_relay2sgsn(msg, from_peer, ns_bvci);
|
||||
err_no_peer:
|
||||
LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(BSS) cannot find peer based on NSEI\n",
|
||||
nsei);
|
||||
@@ -1297,7 +1366,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns
|
||||
int remote_end_is_sgsn = nsei == gbcfg.nsip_sgsn_nsei;
|
||||
|
||||
if (remote_end_is_sgsn)
|
||||
gbprox_patch_bssgp_message(msg, 1);
|
||||
gbprox_patch_bssgp_message(msg, NULL, 1);
|
||||
|
||||
/* Only BVCI=0 messages need special treatment */
|
||||
if (ns_bvci == 0 || ns_bvci == 1) {
|
||||
@@ -1312,7 +1381,7 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns
|
||||
if (!remote_end_is_sgsn) {
|
||||
if (peer)
|
||||
check_peer_nsei(peer, nsei);
|
||||
return gbprox_relay2sgsn(msg, ns_bvci);
|
||||
return gbprox_relay2sgsn(msg, peer, ns_bvci);
|
||||
}
|
||||
|
||||
/* else: SGSN -> BSS direction */
|
||||
|
||||
@@ -917,11 +917,11 @@ static void test_gbproxy_ra_patching()
|
||||
|
||||
printf("--- Bad cases ---\n\n");
|
||||
|
||||
printf("TLLI is already detached, shouldn't patch (expected failure)\n");
|
||||
printf("Invalid BVCI, shouldn't patch\n");
|
||||
send_ns_unitdata(nsi, "ACT PDP CTX REQ", &bss_peer[0], 0x1002,
|
||||
bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
|
||||
|
||||
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1eee);
|
||||
printf("Invalid RAI, shouldn't patch\n");
|
||||
send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown);
|
||||
|
||||
gbprox_dump_global(stdout, 0);
|
||||
|
||||
@@ -1520,6 +1520,7 @@ Current NS-VCIs:
|
||||
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 1
|
||||
PROCESSING BVC_RESET_ACK from 0x05060708:32000
|
||||
00 00 00 00 23 04 82 10 02
|
||||
|
||||
@@ -1557,10 +1558,10 @@ MESSAGE to BSS at 0x01020304:1111, msg length 22
|
||||
result (BVC_SUSPEND_ACK) = 22
|
||||
|
||||
Gbproxy global:
|
||||
RAID patched (BSS ): 2
|
||||
RAID patched (SGSN): 1
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 2
|
||||
RAID patched (SGSN): 1
|
||||
--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---
|
||||
|
||||
PROCESSING ATTACH REQUEST from 0x01020304:1111
|
||||
@@ -1672,14 +1673,14 @@ MESSAGE to BSS at 0x01020304:1111, msg length 71
|
||||
result (DETACH ACC) = 71
|
||||
|
||||
Gbproxy global:
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 9
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 2
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
--- Bad cases ---
|
||||
|
||||
TLLI is already detached, shouldn't patch (expected failure)
|
||||
Invalid BVCI, shouldn't patch
|
||||
PROCESSING ACT PDP CTX 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 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
|
||||
|
||||
@@ -1692,14 +1693,7 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 75
|
||||
|
||||
result (ACT PDP CTX REQ) = 75
|
||||
|
||||
PROCESSING BVC_RESET_ACK from 0x05060708:32000
|
||||
00 00 00 00 23 04 82 1e ee
|
||||
|
||||
CALLBACK, event 0, msg length 5, bvci 0x0000
|
||||
00 00 00 00 23 04 82 1e ee
|
||||
|
||||
result (BVC_RESET_ACK) = -2
|
||||
|
||||
Invalid RAI, shouldn't patch
|
||||
PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000
|
||||
00 00 00 00 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01
|
||||
|
||||
@@ -1708,17 +1702,17 @@ CALLBACK, event 0, msg length 18, bvci 0x0000
|
||||
|
||||
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 (gprs_ns_sendmsg)
|
||||
MESSAGE to SGSN at 0x05060708:32000, msg length 28
|
||||
00 00 00 00 41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 11 22 33 00 63 60 1d 81 01
|
||||
00 00 00 00 41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01
|
||||
|
||||
result (BVC_SUSPEND_ACK) = 28
|
||||
|
||||
Gbproxy global:
|
||||
Invalid BVC Identifier : 1
|
||||
Invalid Routing Area Identifier : 1
|
||||
RAID patched (BSS ): 10
|
||||
RAID patched (SGSN): 4
|
||||
APN patched : 3
|
||||
Patch error: no peer : 1
|
||||
Peers:
|
||||
NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96
|
||||
RAID patched (BSS ): 10
|
||||
RAID patched (SGSN): 3
|
||||
APN patched : 3
|
||||
===== GbProxy test END
|
||||
|
||||
|
||||
Reference in New Issue
Block a user