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
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index e797549..d36ff5b 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -1347,8 +1347,8 @@
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 @@
}
/* 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 @@
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 @@
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 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) {