gbproxy: Refactor gbproxy_patch_bssgp_message

This patch refactors that function by separating the actual patch
code into a new function gbproxy_patch_bssgp(), similar to
gbproxy_patch_llc(). The remaining function is renamed to
gbproxy_process_bssgp_message. The existing function
gbproxy_parse_bssgp_message() is renamed to
gbproxy_process_bssgp_message to match gbproxy_parse_llc.

Sponsored-by: On-Waves ehf
This commit is contained in:
Jacob Erlbeck 2014-08-07 16:07:24 +02:00
parent 291f0508c5
commit c812882dbf
1 changed files with 89 additions and 64 deletions

View File

@ -1347,8 +1347,8 @@ static void gbprox_update_state_after(struct gbproxy_peer *peer,
gbprox_unregister_tlli(peer, parse_ctx->tlli);
}
static int gbprox_parse_bssgp_message(uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_parse_context *parse_ctx)
static int gbprox_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_parse_context *parse_ctx)
{
struct bssgp_normal_hdr *bgph;
struct bssgp_ud_hdr *budh = NULL;
@ -1428,21 +1428,99 @@ static int gbprox_parse_bssgp_message(uint8_t *bssgp, size_t bssgp_len,
}
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
static void gbprox_patch_bssgp_message(struct gbproxy_config *cfg, struct msgb *msg,
struct gbproxy_peer *peer, int to_bss)
static void gbprox_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_peer *peer, int *len_change,
struct gbproxy_parse_context *parse_ctx)
__attribute__((nonnull));
static void gbprox_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
struct gbproxy_peer *peer, int *len_change,
struct gbproxy_parse_context *parse_ctx)
{
struct gbproxy_parse_context parse_ctx = {0};
const char *err_info = NULL;
int err_ctr = -1;
if (!patching_is_enabled(peer, GBPROX_PATCH_BSSGP))
return;
if (parse_ctx->bssgp_raid_enc)
gbprox_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->llc) {
uint8_t *llc = parse_ctx->llc;
size_t llc_len = parse_ctx->llc_len;
int llc_len_change = 0;
gbprox_patch_llc(msg, llc, llc_len, peer, &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,
"Failed to patch BSSGP message as requested: %s.\n", err_info);
}
/* patch BSSGP message to use core_mcc/mnc on the SGSN side */
static void gbprox_process_bssgp_message(struct gbproxy_config *cfg,
struct msgb *msg,
struct gbproxy_peer *peer, int to_bss)
{
struct gbproxy_parse_context parse_ctx = {0};
int rc;
int len_change = 0;
if (!cfg->core_mcc && !cfg->core_mnc && !cfg->core_apn)
return;
parse_ctx.to_bss = to_bss;
rc = gbprox_parse_bssgp_message(msgb_bssgph(msg), msgb_bssgp_len(msg),
&parse_ctx);
rc = gbprox_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
&parse_ctx);
if (!rc) {
if (!parse_ctx.need_decryption) {
@ -1471,67 +1549,14 @@ static void gbprox_patch_bssgp_message(struct gbproxy_config *cfg, struct msgb *
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;
}
gbprox_update_state(peer, &parse_ctx);
if (parse_ctx.bssgp_raid_enc)
gbprox_patch_raid(parse_ctx.bssgp_raid_enc, peer, to_bss, "BSSGP");
if (parse_ctx.llc &&
patching_is_enabled(peer, GBPROX_PATCH_LLC_ATTACH_REQ)) {
uint8_t *llc = parse_ctx.llc;
size_t llc_len = parse_ctx.llc_len;
int len_change = 0;
gbprox_patch_llc(msg, llc, llc_len, peer, &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 (len_change) {
llc_len += 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;
}
}
/* Note that the tp struct might contain invalid pointers here
* if the LLC field has changed its size */
parse_ctx.llc_len = llc_len;
}
gbprox_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
peer, &len_change, &parse_ctx);
gbprox_update_state_after(peer, &parse_ctx);
return;
patch_error:
OSMO_ASSERT(err_ctr >= 0);
rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
LOGP(DGPRS, LOGL_ERROR,
"Failed to patch BSSGP message as requested: %s.\n", err_info);
}
/* feed a message down the NS-VC associated with the specified peer */
@ -1543,7 +1568,7 @@ static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
struct msgb *msg = gprs_msgb_copy(old_msg, "msgb_relay2sgsn");
int rc;
gbprox_patch_bssgp_message(cfg, msg, peer, 0);
gbprox_process_bssgp_message(cfg, msg, peer, 0);
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
msgb_nsei(msg), ns_bvci, cfg->nsip_sgsn_nsei);
@ -1961,7 +1986,7 @@ int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei,
int remote_end_is_sgsn = nsei == cfg->nsip_sgsn_nsei;
if (remote_end_is_sgsn)
gbprox_patch_bssgp_message(cfg, msg, NULL, 1);
gbprox_process_bssgp_message(cfg, msg, NULL, 1);
/* Only BVCI=0 messages need special treatment */
if (ns_bvci == 0 || ns_bvci == 1) {