From 4b663ac34a993cb1f1aa8e993dfc37bcb6841123 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Thu, 21 Aug 2014 15:07:11 +0200 Subject: gbproxy: Create STATUS message with original PDU Currently when patching is enabled and an error happens when receiving a message from the SGSN, the patched message is sent back with the PDU_IN_ERROR IE. This patch modifies gbprox_rx_sig_from_sgsn() to copy the message before it is patched, so that the original message can be used with the STATUS message. gbprox_rx_ptp_from_sgsn() does all checks before the message is patched, so copying is not necessary. Since gbprox_rx_sig_from_sgsn() is not called for BSSGP UNITDATA messages and the msgb is already been copied in the gbprox_relay2peer function, the relative performance impact is expected to be low. Note that the PDU IE of STATUS messages received from an MS and forwarded to the SGSN will not be patched. STATUS messages from the SGSN are only logged and not forwarded to the MS. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_gb_parse.h | 1 + openbsc/src/gprs/gb_proxy.c | 42 ++++++++++++++++++++++----------- openbsc/src/gprs/gprs_gb_parse.c | 20 ++++++++++++---- openbsc/tests/gbproxy/gbproxy_test.ok | 26 ++++++++++---------- 4 files changed, 58 insertions(+), 31 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gb_parse.h b/openbsc/include/openbsc/gprs_gb_parse.h index 0aa364765..eaf42d35d 100644 --- a/openbsc/include/openbsc/gprs_gb_parse.h +++ b/openbsc/include/openbsc/gprs_gb_parse.h @@ -19,6 +19,7 @@ struct gprs_gb_parse_context { struct tlv_parsed bssgp_tp; int to_bss; uint8_t *tlli_enc; + uint8_t *old_tlli_enc; uint8_t *imsi; size_t imsi_len; uint8_t *apn_ie; diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index dfceabea0..280c55707 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -448,6 +448,8 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg, peer = gbproxy_peer_by_bvci(cfg, ns_bvci); + /* Send status messages before patching */ + if (!peer) { LOGP(DGPRS, LOGL_INFO, "Didn't find peer for " "BVCI=%u for message from NSVC=%u/NSEI=%u (SGSN)\n", @@ -466,6 +468,9 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg, return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, NULL, msg); } + /* Optionally patch the message */ + gbprox_process_bssgp_dl(cfg, msg, peer); + return gbprox_relay2peer(msg, peer, ns_bvci); } @@ -621,6 +626,7 @@ static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct /* Receive an incoming BVC-RESET message from the SGSN */ static int rx_reset_from_sgsn(struct gbproxy_config *cfg, + struct msgb *orig_msg, struct msgb *msg, struct tlv_parsed *tp, uint32_t nsei, uint16_t ns_bvci) { @@ -631,7 +637,7 @@ static int rx_reset_from_sgsn(struct gbproxy_config *cfg, rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, - NULL, msg); + NULL, orig_msg); } ptp_bvci = ntohs(tlvp_val16_unal(tp, BSSGP_IE_BVCI)); @@ -645,7 +651,7 @@ static int rx_reset_from_sgsn(struct gbproxy_config *cfg, rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_BVCI]); return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, - NULL, msg); + NULL, orig_msg); } return gbprox_relay2peer(msg, peer, ns_bvci); } @@ -662,15 +668,17 @@ static int rx_reset_from_sgsn(struct gbproxy_config *cfg, /* Receive an incoming signalling message from the SGSN-side NS-VC */ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg, - struct msgb *msg, uint32_t nsei, + struct msgb *orig_msg, uint32_t nsei, uint16_t ns_bvci) { - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); + struct bssgp_normal_hdr *bgph = + (struct bssgp_normal_hdr *) msgb_bssgph(orig_msg); struct tlv_parsed tp; uint8_t pdu_type = bgph->pdu_type; - int data_len = msgb_bssgp_len(msg) - sizeof(*bgph); + int data_len; struct gbproxy_peer *peer; uint16_t bvci; + struct msgb *msg; int rc = 0; if (ns_bvci != 0 && ns_bvci != 1) { @@ -686,14 +694,19 @@ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg, pdu_type == BSSGP_PDUT_DL_UNITDATA) { LOGP(DGPRS, LOGL_NOTICE, "NSEI=%u(SGSN) UNITDATA not allowed in " "signalling\n", nsei); - return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); + return bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, orig_msg); } + msg = gprs_msgb_copy(orig_msg, "rx_sig_from_sgsn"); + gbprox_process_bssgp_dl(cfg, msg, NULL); + /* Update message info */ + bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); + data_len = msgb_bssgp_len(orig_msg) - sizeof(*bgph); rc = bssgp_tlv_parse(&tp, bgph->data, data_len); switch (pdu_type) { case BSSGP_PDUT_BVC_RESET: - rc = rx_reset_from_sgsn(cfg, msg, &tp, nsei, ns_bvci); + rc = rx_reset_from_sgsn(cfg, msg, orig_msg, &tp, nsei, ns_bvci); break; case BSSGP_PDUT_FLUSH_LL: case BSSGP_PDUT_BVC_RESET_ACK: @@ -762,29 +775,33 @@ static int gbprox_rx_sig_from_sgsn(struct gbproxy_config *cfg, "NSEI=%u(SGSN) BSSGP INVOKE TRACE not supported\n",nsei); rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN]); - rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, msg); + rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, orig_msg); break; default: LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n", pdu_type); rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); - rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); + rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, orig_msg); break; } + msgb_free(msg); + return rc; err_mand_ie: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) missing mandatory IE\n", nsei); rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]); - return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); + msgb_free(msg); + return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, orig_msg); err_no_peer: LOGP(DGPRS, LOGL_ERROR, "NSEI=%u(SGSN) cannot find peer based on RAI\n", nsei); rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_RAI]); - return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, msg); + msgb_free(msg); + return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI, NULL, orig_msg); } /* Main input function for Gb proxy */ @@ -794,9 +811,6 @@ int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, int rc; int remote_end_is_sgsn = nsei == cfg->nsip_sgsn_nsei; - if (remote_end_is_sgsn) - gbprox_process_bssgp_dl(cfg, msg, NULL); - /* Only BVCI=0 messages need special treatment */ if (ns_bvci == 0 || ns_bvci == 1) { if (remote_end_is_sgsn) diff --git a/openbsc/src/gprs/gprs_gb_parse.c b/openbsc/src/gprs/gprs_gb_parse.c index f2ab20075..ef4a4d108 100644 --- a/openbsc/src/gprs/gprs_gb_parse.c +++ b/openbsc/src/gprs/gprs_gb_parse.c @@ -530,10 +530,13 @@ int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len, 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_TLLI)) { + if (parse_ctx->tlli_enc) + /* This is TLLI old, don't confuse it with TLLI current */ + parse_ctx->old_tlli_enc = (uint8_t *)TLVP_VAL(tp, BSSGP_IE_TLLI); + else + 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); @@ -581,6 +584,15 @@ void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx, sep = ","; } + if (parse_ctx->old_tlli_enc) { + LOGP(DGPRS, LOGL_DEBUG, "%s old TLLI %02x%02x%02x%02x", sep, + parse_ctx->old_tlli_enc[0], + parse_ctx->old_tlli_enc[1], + parse_ctx->old_tlli_enc[2], + parse_ctx->old_tlli_enc[3]); + sep = ","; + } + if (parse_ctx->bssgp_raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 8929b6cc8..4bd1d8cc7 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -2197,7 +2197,7 @@ CALLBACK, event 0, msg length 19, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c result (LLC_DISCARDED) = 23 @@ -2205,7 +2205,7 @@ Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 RAID patched (BSS ): 6 RAID patched (SGSN): 1 - TLLI patched (BSS ): 5 + TLLI patched (BSS ): 6 TLLI patched (SGSN): 5 P-TMSI patched (SGSN): 1 Attach Request count : 1 @@ -2220,7 +2220,7 @@ CALLBACK, event 0, msg length 15, bvci 0x0000 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 c0 0f 73 04 1b 86 21 63 54 40 50 60 +00 00 00 00 0b 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 result (BVC_SUSPEND) = 19 @@ -2228,7 +2228,7 @@ Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 RAID patched (BSS ): 7 RAID patched (SGSN): 1 - TLLI patched (BSS ): 5 + TLLI patched (BSS ): 7 TLLI patched (SGSN): 5 P-TMSI patched (SGSN): 1 Attach Request count : 1 @@ -2243,7 +2243,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 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 ef e2 b7 00 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -2251,8 +2251,8 @@ 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 + TLLI patched (BSS ): 7 + TLLI patched (SGSN): 6 P-TMSI patched (SGSN): 1 Attach Request count : 1 TLLI cache size : 1 @@ -2266,7 +2266,7 @@ CALLBACK, event 0, msg length 19, bvci 0x0000 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 ee e1 25 83 00 00 0c +00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 ee e1 25 83 00 00 0c result (LLC_DISCARDED) = 23 @@ -2294,7 +2294,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 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 ef e2 b7 00 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -2317,8 +2317,8 @@ Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 RAID patched (BSS ): 8 RAID patched (SGSN): 3 - TLLI patched (BSS ): 6 - TLLI patched (SGSN): 5 + TLLI patched (BSS ): 9 + TLLI patched (SGSN): 7 P-TMSI patched (SGSN): 1 Attach Request count : 1 TLLI cache size : 1 @@ -2340,8 +2340,8 @@ Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 RAID patched (BSS ): 8 RAID patched (SGSN): 3 - TLLI patched (BSS ): 6 - TLLI patched (SGSN): 6 + TLLI patched (BSS ): 9 + TLLI patched (SGSN): 8 P-TMSI patched (SGSN): 1 Attach Request count : 1 TLLI-Cache: 0 -- cgit v1.2.3