This adds a test case with several messages to test BSSGP patching. New messages:
- BSSGP/DTAP Attach Request - BSSGP/DTAP Attach Accept - BSSGP/DTAP Routing Area Update Request - BSSGP/DTAP Routing Area Update Accept - BSSGP/DTAP Activate PDP Context Request - BSSGP SUSPEND - BSSGP SUSPEND ACK
Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 199 ++++++++++++++++++++++++- openbsc/tests/gbproxy/gbproxy_test.ok | 268 ++++++++++++++++++++++++++++++++++ 2 files changed, 466 insertions(+), 1 deletion(-)
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index ea07a77..c372af1 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -28,13 +28,88 @@ #include <osmocom/gprs/gprs_bssgp.h>
#include <openbsc/gb_proxy.h> +#include <openbsc/debug.h>
#define REMOTE_BSS_ADDR 0x01020304 #define REMOTE_SGSN_ADDR 0x05060708
#define SGSN_NSEI 0x0100
-struct gbproxy_config gbcfg; +struct gbproxy_config gbcfg = {0}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Request */ +static const unsigned char bssgp_attach_req[75] = { + 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x34, 0x01, + 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, + 0x08, 0x02, 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, + 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, + 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, + 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, + 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, + 0x16, 0x6d, 0x01 +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */ +static const unsigned char bssgp_attach_acc[88] = { + 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20, + 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3, + 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, + 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, + 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a, + 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00, + 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01, + 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60, + 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05, + 0xf4, 0xfb, 0xc5, 0x47, 0x22, 0x42, 0x67, 0x9a +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */ +static const unsigned char bssgp_ra_upd_req[85] = { + 0x01, 0xaf, 0xe2, 0x80, 0x6e, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01, + 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, + 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, + 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, + 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, + 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, + 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, + 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, + 0x20, 0x00, 0x96, 0x3e, 0x97 +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */ +static const unsigned char bssgp_ra_upd_acc[91] = { + 0x00, 0xaf, 0xe2, 0x80, 0x6e, 0x00, 0x50, 0x20, + 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13, + 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, + 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, + 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, + 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d, + 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0, + 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54, + 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18, + 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16, + 0xc3, 0xbf, 0xcc +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */ +static const unsigned char bssgp_act_pdp_ctx_req[76] = { + 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01, + 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00, + 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03, + 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21, + 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x5a, 0xff, 0x02 +};
static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, @@ -168,6 +243,39 @@ static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi, send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg)); }
+static void send_bssgp_suspend(struct gprs_ns_inst *nsi, + struct sockaddr_in *src_addr, + struct gprs_ra_id *raid) +{ + /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */ + unsigned char msg[15] = { + 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b, + 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60 + }; + + if (raid) + gsm48_construct_ra(msg + 9, raid); + + send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg)); +} + +static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi, + struct sockaddr_in *src_addr, + struct gprs_ra_id *raid) +{ + /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */ + unsigned char msg[18] = { + 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b, + 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d, + 0x81, 0x01 + }; + + if (raid) + gsm48_construct_ra(msg + 9, raid); + + send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg)); +} + static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, uint16_t nsvci, uint16_t nsei) { @@ -686,6 +794,94 @@ static void test_gbproxy_ident_changes() gbprox_reset(); }
+static void test_gbproxy_ra_patching() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in bss_peer[1] = {{0},}; + struct sockaddr_in sgsn_peer= {0}; + struct gprs_ra_id rai_bss = + {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96}; + struct gprs_ra_id rai_sgsn = + {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96}; + struct gprs_ra_id rai_unknown = + {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96}; + + bssgp_nsi = nsi; + gbcfg.nsi = bssgp_nsi; + gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + bss_peer[0].sin_family = AF_INET; + bss_peer[0].sin_port = htons(1111); + bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Initialise SGSN ---\n\n"); + + gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, &sgsn_peer); + send_ns_unblock_ack(nsi, &sgsn_peer); + send_ns_alive(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Initialise BSS 1 ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0, 1); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + + send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss); + send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn); + + gbprox_dump_global(stdout, 0, 1); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_attach_req, sizeof(bssgp_attach_req)); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1002, + bssgp_attach_acc, sizeof(bssgp_attach_acc)); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req)); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1002, + bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc)); + + /* Replace APN */ + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req)); + + /* TODO: Re-configure to test APN IE removal */ + + /* Remove APN */ + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req)); + + gbprox_dump_global(stdout, 0, 1); + gbprox_dump_peers(stdout, 0, 1); + + printf("--- Bad cases ---\n\n"); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1eee); + send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown); + + gbprox_dump_global(stdout, 0, 1); + gbprox_dump_peers(stdout, 0, 1); + + gprs_ns_destroy(nsi); + nsi = NULL; + gbprox_reset(); +} +
static struct log_info info = {};
@@ -706,6 +902,7 @@ int main(int argc, char **argv) printf("===== GbProxy test START\n"); test_gbproxy(); test_gbproxy_ident_changes(); + test_gbproxy_ra_patching(); printf("===== GbProxy test END\n\n");
exit(EXIT_SUCCESS); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 3b25922..58add97 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1518,5 +1518,273 @@ Peers: NS Transmission error : 2 NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96 NSEI mismatch : 1 +--- 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 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 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 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +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 +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 +0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 + +MESSAGE to SGSN at 0x05060708:32000, msg length 19 +00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 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 +0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 + +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 21 63 54 40 50 60 1d 81 01 + +result (BVC_SUSPEND_ACK) = 28 + +Gbproxy global: + Invalid Routing Area Identifier : 1 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 79 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 (UNITDATA) = 79 + +PROCESSING UNITDATA 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 fb c5 47 22 42 67 9a + +CALLBACK, event 0, msg length 88, bvci 0x1002 +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 fb c5 47 22 42 67 9a + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 +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 fb c5 47 22 42 67 9a + +MESSAGE to BSS at 0x01020304:1111, msg length 92 +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 fb c5 47 22 42 67 9a + +result (UNITDATA) = 92 + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +CALLBACK, event 0, msg length 85, bvci 0x1002 +01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 +01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +MESSAGE to SGSN at 0x05060708:32000, msg length 89 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +result (UNITDATA) = 89 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 02 00 af e2 80 6e 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 91, bvci 0x1002 +00 af e2 80 6e 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 + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 91 +00 af e2 80 6e 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 + +MESSAGE to BSS at 0x01020304:1111, msg length 95 +00 00 10 02 00 af e2 80 6e 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 + +result (UNITDATA) = 95 + +PROCESSING UNITDATA 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 + +CALLBACK, event 0, msg length 76, bvci 0x1002 +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 +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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 80 +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 + +result (UNITDATA) = 80 + +PROCESSING UNITDATA 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 + +CALLBACK, event 0, msg length 76, bvci 0x1002 +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 +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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 80 +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 + +result (UNITDATA) = 80 + +Gbproxy global: + Invalid Routing Area Identifier : 1 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +--- Bad cases --- + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 1e ee + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 1e ee + +result (BVC_RESET_ACK) = -2 + +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 + +CALLBACK, event 0, msg length 18, bvci 0x0000 +0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 + +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 00 f1 99 00 63 60 1d 81 01 + +result (BVC_SUSPEND_ACK) = 28 + +Gbproxy global: + Invalid BVC Identifier : 1 + Invalid Routing Area Identifier : 2 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 ===== GbProxy test END
Enable the generation of more log messages.
Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index c372af1..2aaf109 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -883,7 +883,28 @@ static void test_gbproxy_ra_patching() }
-static struct log_info info = {}; +static struct log_info_cat gprs_categories[] = { + [DGPRS] = { + .name = "DGPRS", + .description = "GPRS Packet Service", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, + [DNS] = { + .name = "DNS", + .description = "GPRS Network Service (NS)", + .enabled = 1, .loglevel = LOGL_INFO, + }, + [DBSSGP] = { + .name = "DBSSGP", + .description = "GPRS BSS Gateway Protocol (BSSGP)", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, +}; + +static struct log_info info = { + .cat = gprs_categories, + .num_cat = ARRAY_SIZE(gprs_categories), +};
int main(int argc, char **argv) { @@ -893,7 +914,8 @@ int main(int argc, char **argv) osmo_signal_register_handler(SS_L_NS, &test_signal, NULL);
log_set_print_filename(osmo_stderr_target, 0); - log_set_log_level(osmo_stderr_target, LOGL_INFO); + log_set_log_level(osmo_stderr_target, LOGL_DEBUG); + log_set_all_filter(osmo_stderr_target, 1);
rate_ctr_init(NULL);
This adds a feature to patch the BSSGP MNC/MCC fields of messages going to and coming from the SGSN. To enable this feature, the gbproxy's VTY commands 'core-mobile-country-code' and/or 'core-mobile-network-code' must be used. All packets to the SGSN are patched to match the configured values. Packets received from the SGSN are patched to the corresponding values as last seen from the BSS side.
Note that this will probably not work with a gbproxy used for several BSS simultaneously.
Note also, that MCC/MNC contained in a LLC IE will not be patched.
Ticket: OW#1185 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 4 + openbsc/src/gprs/Makefile.am | 3 +- openbsc/src/gprs/gb_proxy.c | 133 ++++++++++++++++++++++++++++++++++ openbsc/src/gprs/gb_proxy_main.c | 2 +- openbsc/src/gprs/gb_proxy_vty.c | 52 +++++++++++++ openbsc/tests/gbproxy/Makefile.am | 2 + openbsc/tests/gbproxy/gbproxy_test.c | 2 + openbsc/tests/gbproxy/gbproxy_test.ok | 48 ++++++------ 8 files changed, 222 insertions(+), 24 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 4d189a6..220636e 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -13,6 +13,10 @@ struct gbproxy_config {
/* misc */ struct gprs_ns_inst *nsi; + + /* force mcc/mnc */ + int core_mnc; + int core_mcc; };
extern struct gbproxy_config gbcfg; diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 049d41d..87dbc30 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -13,7 +13,8 @@ else bin_PROGRAMS = osmo-gbproxy endif
-osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c +osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \ + gprs_llc_parse.c crc24.c osmo_gbproxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a \ $(OSMO_LIBS)
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 4799344..61059bb 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -43,6 +43,10 @@ #include <openbsc/debug.h> #include <openbsc/gb_proxy.h>
+#include <openbsc/gprs_llc.h> +#include <openbsc/gsm_04_08.h> +#include <openbsc/gsm_04_08_gprs.h> + enum gbprox_global_ctr { GBPROX_GLOB_CTR_INV_BVCI, GBPROX_GLOB_CTR_INV_LAI, @@ -55,6 +59,9 @@ 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_PATCH_ERR, };
static const struct rate_ctr_desc global_ctr_description[] = { @@ -69,6 +76,9 @@ 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)" }, + { "mod-err", "Patching error " }, };
static const struct rate_ctr_group_desc global_ctrg_desc = { @@ -112,6 +122,11 @@ static const struct rate_ctr_group_desc peer_ctrg_desc = { .ctr_desc = peer_ctr_description, };
+static struct gbprox_patch_state { + int local_mnc; + int local_mcc; +} gbprox_patch_state = {0}; + struct gbprox_peer { struct llist_head list;
@@ -260,6 +275,119 @@ static void strip_ns_hdr(struct msgb *msg) msgb_pull(msg, strip_len); }
+/* patch RA identifier in place, update peer accordingly */ +static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *state, + int to_bss, const char *log_text) +{ + int old_local_mcc = state->local_mcc; + int old_local_mnc = state->local_mnc; + 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 */ + /* save BSS side MCC/MNC */ + if (!gbcfg.core_mcc || raid.mcc == gbcfg.core_mcc) { + state->local_mcc = 0; + } else { + state->local_mcc = raid.mcc; + raid.mcc = gbcfg.core_mcc; + } + + if (!gbcfg.core_mnc || raid.mnc == gbcfg.core_mnc) { + state->local_mnc = 0; + } else { + state->local_mnc = raid.mnc; + raid.mnc = gbcfg.core_mnc; + } + } else { + /* SGSN -> BSS */ + if (state->local_mcc) + raid.mcc = state->local_mcc; + + if (state->local_mnc) + raid.mnc = state->local_mnc; + } + + if (old_local_mcc != state->local_mcc || + old_local_mnc != state->local_mnc) + LOGP(DGPRS, LOGL_NOTICE, + "Patching RAID %sactivated, msg: %s, " + "local: %d-%d, core: %d-%d, to %s\n", + state->local_mcc || state->local_mnc ? + "" : "de", + log_text, + state->local_mcc, state->local_mnc, + gbcfg.core_mcc, gbcfg.core_mnc, + to_bss ? "BSS" : "SGSN"); + + if (state->local_mcc || state->local_mnc) { + enum gbprox_global_ctr counter = + to_bss ? + GBPROX_GLOB_CTR_RAID_PATCHED_SGSN : + GBPROX_GLOB_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(&get_global_ctrg()->ctr[counter]); + } +} + +/* patch BSSGP message to use core_mcc/mnc on the SGSN side */ +static void gbprox_patch_bssgp_message(struct msgb *msg, 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; + uint8_t *data; + size_t data_len; + + if (!gbcfg.core_mcc && !gbcfg.core_mnc) + return; + + bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); + 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; + data_len = msgb_bssgp_len(msg) - sizeof(*budh); + } else { + data = bgph->data; + data_len = msgb_bssgp_len(msg) - sizeof(*bgph); + } + + /* fix BSSGP */ + bssgp_tlv_parse(&tp, data, data_len); + + 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"); + + 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"); +} + /* feed a message down the NS-VC associated with the specified peer */ static int gbprox_relay2sgsn(struct msgb *old_msg, uint16_t ns_bvci) { @@ -276,6 +404,8 @@ 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]); @@ -679,6 +809,9 @@ int gbprox_rcvmsg(struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t ns struct gbprox_peer *peer; int remote_end_is_sgsn = nsei == gbcfg.nsip_sgsn_nsei;
+ if (remote_end_is_sgsn) + gbprox_patch_bssgp_message(msg, 1); + /* 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/gb_proxy_main.c b/openbsc/src/gprs/gb_proxy_main.c index ff2e14b..1f140d4 100644 --- a/openbsc/src/gprs/gb_proxy_main.c +++ b/openbsc/src/gprs/gb_proxy_main.c @@ -66,7 +66,7 @@ const char *openbsc_copyright = "There is NO WARRANTY, to the extent permitted by law.\r\n";
static char *config_file = "osmo_gbproxy.cfg"; -struct gbproxy_config gbcfg; +struct gbproxy_config gbcfg = {0}; static int daemonize = 0;
/* Pointer to the SGSN peer */ diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 2de0d3b..acd8051 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -51,6 +51,13 @@ static int config_write_gbproxy(struct vty *vty) vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei, VTY_NEWLINE);
+ if (g_cfg->core_mcc > 0) + vty_out(vty, " core-mobile-country-code %d%s", + g_cfg->core_mcc, VTY_NEWLINE); + if (g_cfg->core_mnc > 0) + vty_out(vty, " core-mobile-network-code %d%s", + g_cfg->core_mnc, VTY_NEWLINE); + return CMD_SUCCESS; }
@@ -76,6 +83,47 @@ DEFUN(cfg_nsip_sgsn_nsei, return CMD_SUCCESS; }
+#define GBPROXY_CORE_MNC_STR "Use this network code for the backbone\n" + +DEFUN(cfg_gbproxy_core_mnc, + cfg_gbproxy_core_mnc_cmd, + "core-mobile-network-code <1-999>", + GBPROXY_CORE_MNC_STR "NCC value\n") +{ + g_cfg->core_mnc = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_gbproxy_no_core_mnc, + cfg_gbproxy_no_core_mnc_cmd, + "no core-mobile-network-code", + NO_STR GBPROXY_CORE_MNC_STR) +{ + g_cfg->core_mnc = 0; + return CMD_SUCCESS; +} + +#define GBPROXY_CORE_MCC_STR "Use this country code for the backbone\n" + +DEFUN(cfg_gbproxy_core_mcc, + cfg_gbproxy_core_mcc_cmd, + "core-mobile-country-code <1-999>", + GBPROXY_CORE_MCC_STR "MCC value\n") +{ + g_cfg->core_mcc = atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_gbproxy_no_core_mcc, + cfg_gbproxy_no_core_mcc_cmd, + "no core-mobile-country-code", + NO_STR GBPROXY_CORE_MCC_STR) +{ + g_cfg->core_mcc = 0; + return CMD_SUCCESS; +} + + int gbproxy_vty_init(void) { install_element_ve(&show_gbproxy_cmd); @@ -87,6 +135,10 @@ int gbproxy_vty_init(void) install_node(&gbproxy_node, config_write_gbproxy); vty_install_default(GBPROXY_NODE); install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
return 0; } diff --git a/openbsc/tests/gbproxy/Makefile.am b/openbsc/tests/gbproxy/Makefile.am index 8e88dc4..9c1b2d0 100644 --- a/openbsc/tests/gbproxy/Makefile.am +++ b/openbsc/tests/gbproxy/Makefile.am @@ -9,6 +9,8 @@ noinst_PROGRAMS = gbproxy_test gbproxy_test_SOURCES = gbproxy_test.c gbproxy_test_LDADD = \ $(top_builddir)/src/gprs/gb_proxy.o \ + $(top_builddir)/src/gprs/gprs_llc_parse.o \ + $(top_builddir)/src/gprs/crc24.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libtrau/libtrau.a \ diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 2aaf109..8bf9527 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -809,6 +809,8 @@ static void test_gbproxy_ra_patching() bssgp_nsi = nsi; gbcfg.nsi = bssgp_nsi; gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + gbcfg.core_mcc = 123; + gbcfg.core_mnc = 456;
sgsn_peer.sin_family = AF_INET; sgsn_peer.sin_port = htons(32000); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 58add97..f8bd1e7 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1607,10 +1607,10 @@ CALLBACK, event 0, msg length 22, bvci 0x0000 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 -22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 +22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 00 00 00 00
MESSAGE to SGSN at 0x05060708:32000, msg length 26 -00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 21 63 54 40 50 60 10 00 00 00 00 00
result (BVC_RESET) = 26
@@ -1642,10 +1642,10 @@ CALLBACK, event 0, msg length 15, bvci 0x0000 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 -0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 +0b 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60
MESSAGE to SGSN at 0x05060708:32000, msg length 19 -00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60
result (BVC_SUSPEND) = 19
@@ -1655,16 +1655,17 @@ PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000 CALLBACK, event 0, msg length 18, bvci 0x0000 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01
-NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 -41 07 81 05 15 92 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 +0c 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 1d 81 01
-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 21 63 54 40 50 60 1d 81 01 +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) = 28 +result (BVC_SUSPEND_ACK) = 22
Gbproxy global: - Invalid Routing Area Identifier : 1 + RAID patched (BSS ): 2 + RAID patched (SGSN): 1 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 --- Send message from BSS 1 to SGSN, BVCI 0x1002 --- @@ -1676,10 +1677,10 @@ CALLBACK, event 0, msg length 75, bvci 0x1002 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 -01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 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
MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 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 (UNITDATA) = 79
@@ -1704,10 +1705,10 @@ CALLBACK, event 0, msg length 85, bvci 0x1002 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 -01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 +01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97
MESSAGE to SGSN at 0x05060708:32000, msg length 89 -00 00 10 02 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97
result (UNITDATA) = 89
@@ -1732,10 +1733,10 @@ CALLBACK, event 0, msg length 76, bvci 0x1002 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 -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 +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
MESSAGE to SGSN at 0x05060708:32000, msg length 80 -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 +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
result (UNITDATA) = 80
@@ -1746,15 +1747,16 @@ CALLBACK, event 0, msg length 76, bvci 0x1002 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 -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 +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
MESSAGE to SGSN at 0x05060708:32000, msg length 80 -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 +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
result (UNITDATA) = 80
Gbproxy global: - Invalid Routing Area Identifier : 1 + RAID patched (BSS ): 6 + RAID patched (SGSN): 1 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 --- Bad cases --- @@ -1774,16 +1776,18 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 -41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 11 22 33 00 63 60 1d 81 01
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 00 f1 99 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 11 22 33 00 63 60 1d 81 01
result (BVC_SUSPEND_ACK) = 28
Gbproxy global: Invalid BVC Identifier : 1 - Invalid Routing Area Identifier : 2 + Invalid Routing Area Identifier : 1 + RAID patched (BSS ): 6 + RAID patched (SGSN): 2 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 ===== GbProxy test END
On Thu, Jul 03, 2014 at 01:28:14PM +0200, Jacob Erlbeck wrote:
Good Evening Jacob,
- int old_local_mcc = state->local_mcc;
- int old_local_mnc = state->local_mnc;
make the above two const please.
- if (old_local_mcc != state->local_mcc ||
old_local_mnc != state->local_mnc)
LOGP(DGPRS, LOGL_NOTICE,
"Patching RAID %sactivated, msg: %s, "
"local: %d-%d, core: %d-%d, to %s\n",
state->local_mcc || state->local_mnc ?
"" : "de",
log_text,
state->local_mcc, state->local_mnc,
gbcfg.core_mcc, gbcfg.core_mnc,
to_bss ? "BSS" : "SGSN");
- if (state->local_mcc || state->local_mnc) {
What does this extra check/message bring to the table? Why is it a notice?
- /* fix BSSGP */
- bssgp_tlv_parse(&tp, data, data_len);
What exactly is fixed here?
-struct gbproxy_config gbcfg; +struct gbproxy_config gbcfg = {0};
We were lucky before or did the gbcfg end in the BSS before the patch as well?
+#define GBPROXY_CORE_MNC_STR "Use this network code for the backbone\n"
No idea if "core-network" is any better.
This patch extends the BSSGP patch code to also patch LLC information elements along with MCC/MNC patching support for the following messages:
- Attach Request - Attach Accept - Routing Area Update Request - Routing Area Update Accept - P-TMSI reallocation command
Note that encrypted packets will not be patched.
Ticket: OW#1185 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 10 ++ openbsc/src/gprs/gb_proxy.c | 281 +++++++++++++++++++++++++++++++++- openbsc/src/gprs/gb_proxy_vty.c | 34 ++++ openbsc/tests/gbproxy/gbproxy_test.ok | 24 +-- 4 files changed, 336 insertions(+), 13 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 220636e..7bac832 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -7,6 +7,15 @@ #include <osmocom/gprs/gprs_ns.h> #include <osmocom/vty/command.h>
+enum gbproxy_patch_mode { + GBPROX_PATCH_DEFAULT, + GBPROX_PATCH_BSSGP, /*!< BSGGP messages only */ + GBPROX_PATCH_LLC_ATTACH_REQ, /*!< BSSGP and Attach Request */ + GBPROX_PATCH_LLC_ATTACH, /*!< BSSGP and Attach Request/Response */ + GBPROX_PATCH_LLC_GMM, /*!< BSSGP and all GMM msgs */ + GBPROX_PATCH_LLC, /*!< BSSGP and all supported LLC msgs */ +}; + struct gbproxy_config { /* parsed from config file */ uint16_t nsip_sgsn_nsei; @@ -17,6 +26,7 @@ struct gbproxy_config { /* force mcc/mnc */ int core_mnc; int core_mcc; + enum gbproxy_patch_mode patch_mode; };
extern struct gbproxy_config gbcfg; diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 61059bb..5340c4d 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -61,6 +61,7 @@ enum gbprox_global_ctr { GBPROX_GLOB_CTR_OTHER_ERR, GBPROX_GLOB_CTR_RAID_PATCHED_BSS, GBPROX_GLOB_CTR_RAID_PATCHED_SGSN, + GBPROX_GLOB_CTR_PATCH_CRYPT_ERR, GBPROX_GLOB_CTR_PATCH_ERR, };
@@ -78,7 +79,8 @@ static const struct rate_ctr_desc global_ctr_description[] = { { "error", "Other error " }, { "raid-mod.bss", "RAID patched (BSS )" }, { "raid-mod.sgsn", "RAID patched (SGSN)" }, - { "mod-err", "Patching error " }, + { "mod-crypt-err", "Patch error: encrypted " }, + { "mod-err", "Patch error: other " }, };
static const struct rate_ctr_group_desc global_ctrg_desc = { @@ -346,6 +348,270 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *stat } }
+static int gbprox_patch_gmm_attach_req(struct msgb *msg, + uint8_t *data, size_t data_len, + struct gbprox_patch_state *state, + int to_bss, int *len_change) +{ + /* Check minimum length, always includes the RAI */ + if (data_len < 23) + return 0; + + /* Skip MS network capability */ + if (data[0] < 1 || data[0] > 2) + /* invalid */ + return 0; + data_len -= data[0] + 1; + data += data[0] + 1; + + /* Skip Attach type */ + /* Skip Ciphering key sequence number */ + /* Skip DRX parameter */ + data_len -= 3; + data += 3; + + /* Skip Mobile identity */ + if (data[0] < 5 || data[0] > 8) + /* invalid */ + return 0; + data_len -= data[0] + 1; + data += data[0] + 1; + + gbprox_patch_raid(data, state, 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, + int to_bss, int *len_change) +{ + /* Check minimum length, always includes the RAI */ + if (data_len < 9) + return 0;; + + /* Skip Attach result */ + /* Skip Force to standby */ + /* Skip Periodic RA update timer */ + /* Skip Radio priority for SMS */ + /* Skip Spare half octet */ + data_len -= 3; + data += 3; + + gbprox_patch_raid(data, state, 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, + int to_bss, int *len_change) +{ + /* Check minimum length, always includes the RAI */ + if (data_len < 13) + return 0;; + + /* Skip Update type */ + /* Skip GPRS ciphering key sequence number */ + data_len -= 1; + data += 1; + + gbprox_patch_raid(data, state, 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, + int to_bss, int *len_change) +{ + /* Check minimum length, always includes the RAI */ + if (data_len < 8) + return 0;; + + /* Skip Force to standby */ + /* Skip Update result */ + /* Skip Periodic RA update timer */ + data_len -= 2; + data += 2; + + gbprox_patch_raid(data, state, 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, + int to_bss, int *len_change) +{ + /* Check minimum length, always includes the RAI */ + if (data_len < 12) + return 0;; + + /* Skip Allocated P-TMSI */ + if (data[0] != 5) + /* invalid */ + return 0;; + data_len -= 6; + data += 6; + + gbprox_patch_raid(data, state, to_bss, "LLC/PTMSI_REALL_CMD"); + + return 1; +} + +static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len, + struct gbprox_patch_state *state, + enum gbproxy_patch_mode patch_mode, int to_bss, + int *len_change) +{ + struct gsm48_hdr *g48h; + + *len_change = 0; + + if (data_len < 2) + return 0; + + g48h = (struct gsm48_hdr *)data; + + data += sizeof(struct gsm48_hdr); + data_len -= sizeof(struct gsm48_hdr); + + if ((g48h->proto_discr & 0x0f) != GSM48_PDISC_MM_GPRS && + (g48h->proto_discr & 0x0f) != GSM48_PDISC_SM_GPRS) + return 0; + + 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); + + case GSM48_MT_GMM_ATTACH_ACK: + if (patch_mode < GBPROX_PATCH_LLC_ATTACH) + break; + return gbprox_patch_gmm_attach_ack(msg, data, data_len, + state, to_bss, len_change); + + case GSM48_MT_GMM_RA_UPD_REQ: + if (patch_mode < GBPROX_PATCH_LLC_GMM) + break; + return gbprox_patch_gmm_ra_upd_req(msg, data, data_len, + state, to_bss, len_change); + + case GSM48_MT_GMM_RA_UPD_ACK: + if (patch_mode < GBPROX_PATCH_LLC_GMM) + break; + return gbprox_patch_gmm_ra_upd_ack(msg, data, data_len, + state, to_bss, len_change); + + case GSM48_MT_GMM_PTMSI_REALL_CMD: + if (patch_mode < GBPROX_PATCH_LLC_GMM) + break; + return gbprox_patch_gmm_ptmsi_reall_cmd(msg, data, data_len, + state, to_bss, len_change); + + default: + break; + }; + + return 0; +} + +static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len, + struct gbprox_patch_state *state, + enum gbproxy_patch_mode patch_mode, int to_bss) +{ + struct gprs_llc_hdr_parsed ghp = {0}; + int rc; + uint8_t *data; + size_t data_len; + int fcs; + int len_change = 0; + const char *err_info = NULL; + int err_ctr = -1; + + /* 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; + } + + 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; + + if (ghp.sapi != GPRS_SAPI_GMM) + return; + + if (ghp.cmd != GPRS_LLC_UI) + return; + + if (ghp.is_encrypted) { + if (gbcfg.patch_mode > GBPROX_PATCH_LLC_ATTACH_REQ) { + /* LLC patch (GMM) has been requested explicitely */ + err_info = "GMM message is encrypted"; + err_ctr = GBPROX_GLOB_CTR_PATCH_CRYPT_ERR; + goto patch_error; + } + + return; + } + + /* fix DTAP GMM/GSM */ + data = ghp.data; + data_len = ghp.data_len; + + rc = gbprox_patch_dtap(msg, data, data_len, state, patch_mode, to_bss, + &len_change); + + if (rc > 0) { + llc_len += len_change; + ghp.crc_length += len_change; + + /* Fix LLC IE len */ + 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_GLOB_CTR_PATCH_ERR; + goto patch_error; + } + llc[-1] = llc_len | 0x80; + } else { + llc[-2] = (llc_len >> 8) & 0x7f; + llc[-1] = llc_len & 0xff; + } + + /* 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; + +patch_error: + OSMO_ASSERT(err_ctr >= 0); + rate_ctr_inc(&get_global_ctrg()->ctr[err_ctr]); + LOGP(DGPRS, LOGL_ERROR, + "Failed to patch BSSGP/GMM message as requested: %s.\n", err_info); + + return; +} + /* patch BSSGP message to use core_mcc/mnc on the SGSN side */ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) { @@ -356,6 +622,7 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) struct gbprox_patch_state *state = &gbprox_patch_state; uint8_t *data; size_t data_len; + enum gbproxy_patch_mode patch_mode;
if (!gbcfg.core_mcc && !gbcfg.core_mnc) return; @@ -363,6 +630,9 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg); pdu_type = bgph->pdu_type; + patch_mode = gbcfg.patch_mode; + if (patch_mode == GBPROX_PATCH_DEFAULT) + patch_mode = GBPROX_PATCH_LLC;
if (to_bss && !state->local_mcc && !state->local_mnc) return; @@ -386,6 +656,15 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) 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"); + + if (TLVP_PRESENT(&tp, BSSGP_IE_LLC_PDU) && + patch_mode >= 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, patch_mode, 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 */ diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index acd8051..06f8082 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -44,6 +44,16 @@ static struct cmd_node gbproxy_node = { 1, };
+static const struct value_string patch_modes[] = { + {GBPROX_PATCH_DEFAULT, "default"}, + {GBPROX_PATCH_BSSGP, "bssgp"}, + {GBPROX_PATCH_LLC_ATTACH_REQ, "llc-attach-req"}, + {GBPROX_PATCH_LLC_ATTACH, "llc-attach"}, + {GBPROX_PATCH_LLC_GMM, "llc-gmm"}, + {GBPROX_PATCH_LLC, "llc"}, + {0, NULL} +}; + static int config_write_gbproxy(struct vty *vty) { vty_out(vty, "gbproxy%s", VTY_NEWLINE); @@ -58,6 +68,11 @@ static int config_write_gbproxy(struct vty *vty) vty_out(vty, " core-mobile-network-code %d%s", g_cfg->core_mnc, VTY_NEWLINE);
+ if (g_cfg->patch_mode != GBPROX_PATCH_DEFAULT) + vty_out(vty, " patch-mode %s%s", + get_value_string(patch_modes, g_cfg->patch_mode), + VTY_NEWLINE); + return CMD_SUCCESS; }
@@ -123,6 +138,24 @@ DEFUN(cfg_gbproxy_no_core_mcc, return CMD_SUCCESS; }
+DEFUN(cfg_gbproxy_patch_mode, + cfg_gbproxy_patch_mode_cmd, + "patch-mode (default|bssgp|llc-attach-req|llc-attach|llc)", + "Set patch mode\n" + "Use build-in default (at least llc-attach-req)\n" + "Only patch BSSGP headers\n" + "Patch BSSGP headers and LLC Attach Request messages\n" + "Patch BSSGP headers and LLC Attach Request/Accept messages\n" + "Patch BSSGP headers and all supported GMM LLC messages\n" + ) +{ + int val = get_string_value(patch_modes, argv[0]); + OSMO_ASSERT(val >= 0); + g_cfg->patch_mode = val; + return CMD_SUCCESS; +} + +
int gbproxy_vty_init(void) { @@ -139,6 +172,7 @@ int gbproxy_vty_init(void) install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_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_patch_mode_cmd);
return 0; } diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index f8bd1e7..d3de445 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1677,10 +1677,10 @@ CALLBACK, event 0, msg length 75, bvci 0x1002 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 -01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 21 63 54 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 8e cd 32
MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 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 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 34 01 c0 01 08 01 02 f5 e0 21 08 02 05 f4 fb c5 46 79 21 63 54 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 8e cd 32
result (UNITDATA) = 79
@@ -1691,10 +1691,10 @@ CALLBACK, event 0, msg length 88, bvci 0x1002 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 fb c5 47 22 42 67 9a
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 -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 fb c5 47 22 42 67 9a +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 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 fb c5 47 22 af 3d ab
MESSAGE to BSS at 0x01020304:1111, msg length 92 -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 fb c5 47 22 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 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 fb c5 47 22 af 3d ab
result (UNITDATA) = 92
@@ -1705,10 +1705,10 @@ CALLBACK, event 0, msg length 85, bvci 0x1002 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97
NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 -01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 +01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 21 63 54 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 1d f0 41
MESSAGE to SGSN at 0x05060708:32000, msg length 89 -00 00 10 02 01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 21 63 54 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 21 63 54 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 1d f0 41
result (UNITDATA) = 89
@@ -1719,10 +1719,10 @@ CALLBACK, event 0, msg length 91, bvci 0x1002 00 af e2 80 6e 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
NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 91 -00 af e2 80 6e 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 af e2 80 6e 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
MESSAGE to BSS at 0x01020304:1111, msg length 95 -00 00 10 02 00 af e2 80 6e 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 af e2 80 6e 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
result (UNITDATA) = 95
@@ -1755,8 +1755,8 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 80 result (UNITDATA) = 80
Gbproxy global: - RAID patched (BSS ): 6 - RAID patched (SGSN): 1 + RAID patched (BSS ): 8 + RAID patched (SGSN): 3 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 --- Bad cases --- @@ -1786,8 +1786,8 @@ result (BVC_SUSPEND_ACK) = 28 Gbproxy global: Invalid BVC Identifier : 1 Invalid Routing Area Identifier : 1 - RAID patched (BSS ): 6 - RAID patched (SGSN): 2 + RAID patched (BSS ): 8 + RAID patched (SGSN): 4 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 ===== GbProxy test END
On Thu, Jul 03, 2014 at 01:28:15PM +0200, Jacob Erlbeck wrote:
- /* Skip Attach result */
- /* Skip Force to standby */
- /* Skip Periodic RA update timer */
- /* Skip Radio priority for SMS */
- /* Skip Spare half octet */
- data_len -= 3;
- data += 3;
Which are the other half octets here?
- /* Skip Update type */
- /* Skip GPRS ciphering key sequence number */
- data_len -= 1;
- data += 1;
I don't have a copy of the specification open right now. Could you please indicate how the number of skips relate to data_len/data adjustments here?
- if (data[0] != 5)
/* invalid */
return 0;;
Extra ';' :)
/* LLC patch (GMM) has been requested explicitely */
^-- typo
/* Fix LLC IE len */
if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
/* most probably a one byte length */
You mentioned this to me already. What API documentation do you need? Keep track inside the tlv_parsed structure of _where_ the tag started?
- patch_mode = gbcfg.patch_mode;
- if (patch_mode == GBPROX_PATCH_DEFAULT)
patch_mode = GBPROX_PATCH_LLC;
I am thinking of the "gbcfg.patch_mode > GBPROX_PATCH_LLC_ATTACH_REQ". So we are lucky as default is < GBPROX_PATCH_LLC_ATTACH_REQ right now. Wouldn't it be better to not access gbcfg.patch_mode directly and do the "default" handling inside this method?
Patch the APN in every 'Activate PDP Context Request' message to the value given by the 'core-access-point-name' command. If the command is given without an APN, the whole APN IE will be removed. If the command is being prefixed by a 'no', APN IE remain unmodified.
The patch mode 'llc-gsm' is added to selectively enable the patching of LLC session management messages. This is enabled implicitely by the patch mode 'llc'.
Note that the patch mode should not be set to a value not enabling the patching of LLC GSM messages ('llc-gsm', 'llc', and 'default' are sufficient to patch 'Activate PDP Context Request' messages).
Ticket: OW#1192 Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 6 ++ openbsc/src/gprs/gb_proxy.c | 198 +++++++++++++++++++++++++++++++++- openbsc/src/gprs/gb_proxy_vty.c | 69 +++++++++++- openbsc/tests/gbproxy/gbproxy_test.c | 5 +- openbsc/tests/gbproxy/gbproxy_test.ok | 22 ++-- 5 files changed, 285 insertions(+), 15 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 7bac832..2ecd49f 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -13,6 +13,7 @@ enum gbproxy_patch_mode { GBPROX_PATCH_LLC_ATTACH_REQ, /*!< BSSGP and Attach Request */ GBPROX_PATCH_LLC_ATTACH, /*!< BSSGP and Attach Request/Response */ GBPROX_PATCH_LLC_GMM, /*!< BSSGP and all GMM msgs */ + GBPROX_PATCH_LLC_GSM, /*!< BSSGP and all GMM and GSM msgs */ GBPROX_PATCH_LLC, /*!< BSSGP and all supported LLC msgs */ };
@@ -26,6 +27,8 @@ struct gbproxy_config { /* force mcc/mnc */ int core_mnc; int core_mcc; + uint8_t* core_apn; + size_t core_apn_size; enum gbproxy_patch_mode patch_mode; };
@@ -54,4 +57,7 @@ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi); int gbprox_dump_global(FILE *stream, int indent, int verbose); int gbprox_dump_peers(FILE *stream, int indent, int verbose); void gbprox_reset(); + +char *gbprox_apn_to_str(char *str, const uint8_t *apn_enc, size_t max_chars); +int gbprox_str_to_apn(uint8_t *apn_enc, const char *str, size_t max_chars); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 5340c4d..ea590b3 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -61,6 +61,7 @@ enum gbprox_global_ctr { 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, }; @@ -79,6 +80,7 @@ static const struct rate_ctr_desc global_ctr_description[] = { { "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 " }, }; @@ -277,6 +279,89 @@ static void strip_ns_hdr(struct msgb *msg) msgb_pull(msg, strip_len); }
+/* TODO: Move this to libosmocore/msgb.c */ +static int msgb_resize_area(struct msgb *msg, uint8_t *area, + size_t old_size, size_t new_size) +{ + int rc; + uint8_t *rest = area + old_size; + int rest_len = msg->len - old_size - (area - msg->data); + int delta_size = (int)new_size - (int)old_size; + + if (delta_size == 0) + return 0; + + if (delta_size > 0) { + rc = msgb_trim(msg, msg->len + delta_size); + if (rc < 0) + return rc; + } + + memmove(area + new_size, area + old_size, rest_len); + + if (msg->l1h >= rest) + msg->l1h += delta_size; + if (msg->l2h >= rest) + msg->l2h += delta_size; + if (msg->l3h >= rest) + msg->l3h += delta_size; + if (msg->l4h >= rest) + msg->l4h += delta_size; + + if (delta_size < 0) + msgb_trim(msg, msg->len + delta_size); + + return 0; +} + +/* TODO: Move these conversion functions to a utils file. */ +char * gbprox_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t rest_chars) +{ + char *str = out_str; + + while (rest_chars > 0 && apn_enc[0]) { + size_t label_size = apn_enc[0]; + if (label_size + 1 > rest_chars) + return NULL; + + memmove(str, apn_enc + 1, label_size); + str += label_size; + rest_chars -= label_size + 1; + apn_enc += label_size + 1; + + if (rest_chars) + *(str++) = '.'; + } + str[0] = '\0'; + + return out_str; +} + +int gbprox_str_to_apn(uint8_t *apn_enc, const char *str, size_t max_chars) +{ + uint8_t *last_len_field = apn_enc; + int len = 1; + apn_enc += 1; + + while (str[0]) { + if (str[0] == '.') { + *last_len_field = (apn_enc - last_len_field) - 1; + last_len_field = apn_enc; + } else { + *apn_enc = str[0]; + } + apn_enc += 1; + str += 1; + len += 1; + if (len > max_chars) + return -1; + } + + *last_len_field = (apn_enc - last_len_field) - 1; + + return len; +} + /* patch RA identifier in place, update peer accordingly */ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *state, int to_bss, const char *log_text) @@ -348,6 +433,56 @@ static void gbprox_patch_raid(uint8_t *raid_enc, struct gbprox_patch_state *stat } }
+static void gbprox_patch_apn_ie(struct msgb *msg, + uint8_t *apn_ie, size_t apn_ie_len, + 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 (gbcfg.core_apn_size == 0) { + char str1[110]; + /* Remove the IE */ + LOGP(DGPRS, LOGL_DEBUG, + "Patching %s to SGSN: Removing APN '%s'\n", + log_text, + gbprox_apn_to_str(str1, apn, apn_len)); + + *new_apn_ie_len = 0; + msgb_resize_area(msg, apn_ie, apn_ie_len, 0); + } else { + /* Resize the IE */ + char str1[110]; + char str2[110]; + + OSMO_ASSERT(gbcfg.core_apn_size <= 100); + + LOGP(DGPRS, LOGL_DEBUG, + "Patching %s to SGSN: " + "Replacing APN '%s' -> '%s'\n", + log_text, + gbprox_apn_to_str(str1, apn, apn_len), + gbprox_apn_to_str(str2, gbcfg.core_apn, + gbcfg.core_apn_size)); + + *new_apn_ie_len = gbcfg.core_apn_size + 2; + msgb_resize_area(msg, apn, apn_len, gbcfg.core_apn_size); + memcpy(apn, gbcfg.core_apn, gbcfg.core_apn_size); + hdr->apn_len = gbcfg.core_apn_size; + } + + rate_ctr_inc(&get_global_ctrg()->ctr[GBPROX_GLOB_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, @@ -464,6 +599,60 @@ static int gbprox_patch_gmm_ptmsi_reall_cmd(struct msgb *msg, 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, + int to_bss, int *len_change) +{ + size_t new_len, old_len; + + /* Check minimum length, always contains length field of + * Requested QoS */ + if (data_len < 9) + return 0; + + /* Skip Requested NSAPI */ + /* Skip Requested LLC SAPI */ + data_len -= 2; + data += 2; + + /* Skip Requested QoS (support 04.08 and 24.008) */ + if (data[0] < 4 || data[0] > 14 || + data_len - (data[0] + 1) < 0) + /* invalid */ + return 0; + data_len -= data[0] + 1; + data += data[0] + 1; + + /* Skip Requested PDP address */ + if (data_len < 1 || + data[0] < 2 || data[0] > 18 || + data_len - (data[0] + 1) < 0) + /* invalid */ + return 0; + data_len -= data[0] + 1; + data += data[0] + 1; + + /* Access point name */ + if (data_len < 2 || data[0] != GSM48_IE_GSM_APN) + return 0; + + if (data[1] < 1 || data[1] > 100 || + data_len - (data[1] + 2) < 0) + /* invalid */ + return 0; + + old_len = data[1] + 2; + + gbprox_patch_apn_ie(msg, data, old_len, &new_len, "LLC/ACT_PDP_REQ"); + + *len_change += (int)new_len - (int)old_len; + data_len -= old_len; + data += new_len; + + return 1; +} + static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len, struct gbprox_patch_state *state, enum gbproxy_patch_mode patch_mode, int to_bss, @@ -514,6 +703,13 @@ static int gbprox_patch_dtap(struct msgb *msg, uint8_t *data, size_t data_len, return gbprox_patch_gmm_ptmsi_reall_cmd(msg, data, data_len, state, to_bss, len_change);
+ case GSM48_MT_GSM_ACT_PDP_REQ: + if (patch_mode < GBPROX_PATCH_LLC_GSM) + break; + if (gbcfg.core_apn == NULL) + break; + return gbprox_patch_gsm_act_pdp_req(msg, data, data_len, + state, to_bss, len_change); default: break; }; @@ -624,7 +820,7 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) size_t data_len; enum gbproxy_patch_mode patch_mode;
- if (!gbcfg.core_mcc && !gbcfg.core_mnc) + if (!gbcfg.core_mcc && !gbcfg.core_mnc && !gbcfg.core_apn) return;
bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); diff --git a/openbsc/src/gprs/gb_proxy_vty.c b/openbsc/src/gprs/gb_proxy_vty.c index 06f8082..8d3ff25 100644 --- a/openbsc/src/gprs/gb_proxy_vty.c +++ b/openbsc/src/gprs/gb_proxy_vty.c @@ -21,6 +21,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <string.h>
#include <osmocom/core/talloc.h>
@@ -50,6 +51,7 @@ static const struct value_string patch_modes[] = { {GBPROX_PATCH_LLC_ATTACH_REQ, "llc-attach-req"}, {GBPROX_PATCH_LLC_ATTACH, "llc-attach"}, {GBPROX_PATCH_LLC_GMM, "llc-gmm"}, + {GBPROX_PATCH_LLC_GSM, "llc-gsm"}, {GBPROX_PATCH_LLC, "llc"}, {0, NULL} }; @@ -67,6 +69,18 @@ static int config_write_gbproxy(struct vty *vty) if (g_cfg->core_mnc > 0) vty_out(vty, " core-mobile-network-code %d%s", g_cfg->core_mnc, VTY_NEWLINE); + if (g_cfg->core_apn != NULL) { + if (g_cfg->core_apn_size > 0) { + char str[500] = {0}; + vty_out(vty, " core-access-point-name %s%s", + gbprox_apn_to_str(str, g_cfg->core_apn, + g_cfg->core_apn_size), + VTY_NEWLINE); + } else { + vty_out(vty, " core-access-point-name%s", + VTY_NEWLINE); + } + }
if (g_cfg->patch_mode != GBPROX_PATCH_DEFAULT) vty_out(vty, " patch-mode %s%s", @@ -138,15 +152,61 @@ DEFUN(cfg_gbproxy_no_core_mcc, return CMD_SUCCESS; }
+#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n" + +DEFUN(cfg_gbproxy_core_apn_remove, + cfg_gbproxy_core_apn_remove_cmd, + "core-access-point-name", + GBPROXY_CORE_APN_STR) +{ + talloc_free(g_cfg->core_apn); + /* TODO: replace NULL */ + g_cfg->core_apn = talloc_zero_size(NULL, 2); + g_cfg->core_apn_size = 0; + return CMD_SUCCESS; +} + +DEFUN(cfg_gbproxy_core_apn, + cfg_gbproxy_core_apn_cmd, + "core-access-point-name APN", + GBPROXY_CORE_APN_STR "Replacement APN\n") +{ + int apn_len = strlen(argv[0]) + 1; + + if (apn_len > 100) { + vty_out(vty, "APN string too long (max 99 chars)%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + /* TODO: replace NULL */ + g_cfg->core_apn = talloc_realloc_size(NULL, g_cfg->core_apn, apn_len); + g_cfg->core_apn_size = gbprox_str_to_apn(g_cfg->core_apn, argv[0], apn_len); + + return CMD_SUCCESS; +} + +DEFUN(cfg_gbproxy_no_core_apn, + cfg_gbproxy_no_core_apn_cmd, + "no core-access-point-name", + NO_STR GBPROXY_CORE_APN_STR) +{ + talloc_free(g_cfg->core_apn); + g_cfg->core_apn = NULL; + return CMD_SUCCESS; +} + DEFUN(cfg_gbproxy_patch_mode, cfg_gbproxy_patch_mode_cmd, - "patch-mode (default|bssgp|llc-attach-req|llc-attach|llc)", + "patch-mode (default|bssgp|llc-attach-req|llc-attach|llc-gmm|llc-gsm|llc)", "Set patch mode\n" - "Use build-in default (at least llc-attach-req)\n" + "Use build-in default (best effort, try to patch everything)\n" "Only patch BSSGP headers\n" "Patch BSSGP headers and LLC Attach Request messages\n" "Patch BSSGP headers and LLC Attach Request/Accept messages\n" - "Patch BSSGP headers and all supported GMM LLC messages\n" + "Patch BSSGP headers and LLC GMM messages\n" + "Patch BSSGP headers, LLC GMM, and LLC GSM messages\n" + "Patch BSSGP headers and all supported LLC messages\n" ) { int val = get_string_value(patch_modes, argv[0]); @@ -170,8 +230,11 @@ int gbproxy_vty_init(void) install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd); install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd); install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_remove_cmd); + install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_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_patch_mode_cmd);
return 0; diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 8bf9527..8aef59f 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -811,6 +811,8 @@ static void test_gbproxy_ra_patching() gbcfg.nsip_sgsn_nsei = SGSN_NSEI; gbcfg.core_mcc = 123; gbcfg.core_mnc = 456; + gbcfg.core_apn = talloc_zero_size(NULL, 100); + gbcfg.core_apn_size = gbprox_str_to_apn(gbcfg.core_apn, "foo.bar", 100);
sgsn_peer.sin_family = AF_INET; sgsn_peer.sin_port = htons(32000); @@ -862,7 +864,8 @@ static void test_gbproxy_ra_patching() send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req));
- /* TODO: Re-configure to test APN IE removal */ + gbcfg.core_apn[0] = 0; + gbcfg.core_apn_size = 0;
/* Remove APN */ send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index d3de445..e038afc 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1732,13 +1732,13 @@ PROCESSING UNITDATA from 0x01020304:1111 CALLBACK, event 0, msg length 76, bvci 0x1002 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 -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 81 +01 ef e2 b7 00 00 00 04 08 88 21 63 54 40 50 60 75 30 00 80 0e 00 3a 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 08 03 66 6f 6f 03 62 61 72 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 24 9d 75
-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 +MESSAGE to SGSN at 0x05060708:32000, msg length 85 +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 3a 01 c0 0d 0a 41 05 03 0c 00 00 1f 10 00 00 00 00 00 00 00 00 02 01 21 28 08 03 66 6f 6f 03 62 61 72 27 14 80 80 21 10 01 00 00 10 81 06 00 00 00 00 83 06 00 00 00 00 24 9d 75
-result (UNITDATA) = 80 +result (UNITDATA) = 85
PROCESSING UNITDATA 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 @@ -1746,17 +1746,18 @@ PROCESSING UNITDATA from 0x01020304:1111 CALLBACK, event 0, msg length 76, bvci 0x1002 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 -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 +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
-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 +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 (UNITDATA) = 80 +result (UNITDATA) = 75
Gbproxy global: RAID patched (BSS ): 8 RAID patched (SGSN): 3 + APN patched : 2 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 --- Bad cases --- @@ -1788,6 +1789,7 @@ Gbproxy global: Invalid Routing Area Identifier : 1 RAID patched (BSS ): 8 RAID patched (SGSN): 4 + APN patched : 2 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 ===== GbProxy test END
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 --- openbsc/src/gprs/gb_proxy.c | 191 +++++++++++++++++++++++----------- openbsc/tests/gbproxy/gbproxy_test.ok | 20 ++-- 2 files changed, 139 insertions(+), 72 deletions(-)
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index ea590b3..bead954 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -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) { @@ -363,9 +379,10 @@ int gbprox_str_to_apn(uint8_t *apn_enc, const char *str, size_t max_chars) }
/* 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; int old_local_mcc = state->local_mcc; int old_local_mnc = state->local_mnc; int old_mcc; @@ -415,10 +432,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: " @@ -429,12 +446,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 { @@ -480,12 +498,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 */ @@ -512,14 +530,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 */ @@ -534,14 +552,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 */ @@ -553,14 +571,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 */ @@ -573,14 +591,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 */ @@ -594,14 +612,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; @@ -644,7 +662,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; @@ -653,8 +671,31 @@ 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); + 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, + struct gbprox_peer *peer, enum gbproxy_patch_mode patch_mode, int to_bss, int *len_change) { @@ -677,31 +718,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 (patch_mode < 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 (patch_mode < 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 (patch_mode < 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 (patch_mode < 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 (patch_mode < GBPROX_PATCH_LLC_GSM) @@ -709,7 +750,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; }; @@ -718,7 +759,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, + struct gbprox_peer *peer, enum gbproxy_patch_mode patch_mode, int to_bss) { struct gprs_llc_hdr_parsed ghp = {0}; @@ -755,7 +796,7 @@ static void gbprox_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len, if (gbcfg.patch_mode > GBPROX_PATCH_LLC_ATTACH_REQ) { /* LLC patch (GMM) has been requested explicitely */ 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; }
@@ -766,7 +807,7 @@ 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, patch_mode, to_bss, + rc = gbprox_patch_dtap(msg, data, data_len, peer, patch_mode, to_bss, &len_change);
if (rc > 0) { @@ -778,7 +819,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; @@ -801,7 +842,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);
@@ -809,13 +850,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; enum gbproxy_patch_mode patch_mode; @@ -830,9 +872,6 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) if (patch_mode == GBPROX_PATCH_DEFAULT) patch_mode = GBPROX_PATCH_LLC;
- 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; @@ -845,32 +884,60 @@ static void gbprox_patch_bssgp_message(struct msgb *msg, int to_bss) /* fix BSSGP */ 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) && patch_mode >= 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, patch_mode, to_bss); + gbprox_patch_llc(msg, llc, llc_len, peer, patch_mode, 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);
@@ -879,8 +946,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]); @@ -971,7 +1036,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) { @@ -1062,7 +1127,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); @@ -1285,7 +1350,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) { @@ -1300,7 +1365,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 */ diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index e038afc..40b5376 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1621,6 +1621,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
@@ -1664,10 +1665,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 UNITDATA from 0x01020304:1111 @@ -1755,11 +1756,11 @@ MESSAGE to SGSN at 0x05060708:32000, msg length 75 result (UNITDATA) = 75
Gbproxy global: +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 RAID patched (BSS ): 8 RAID patched (SGSN): 3 APN patched : 2 -Peers: - NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 --- Bad cases ---
PROCESSING BVC_RESET_ACK from 0x05060708:32000 @@ -1777,20 +1778,21 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01
NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 -41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 11 22 33 00 63 60 1d 81 01 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01
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 ): 8 - RAID patched (SGSN): 4 - APN patched : 2 + Patch error: no peer : 2 Peers: NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 + RAID patched (BSS ): 8 + RAID patched (SGSN): 3 + APN patched : 2 ===== GbProxy test END
On Thu, Jul 03, 2014 at 01:28:12PM +0200, Jacob Erlbeck wrote:
+static void send_bssgp_suspend(struct gprs_ns_inst *nsi,
struct gprs_ra_id *raid)
+{
- if (raid)
Every branch spawns a new dimension in your test matrix. It is increasing complexity. All your callers pass a non-NULL raid. The best way is to no check for it being null then.
- struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL);
- struct sockaddr_in bss_peer[1] = {{0},};
- struct sockaddr_in sgsn_peer= {0};
- struct gprs_ra_id rai_bss =
{.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96};
- struct gprs_ra_id rai_sgsn =
{.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96};
- struct gprs_ra_id rai_unknown =
{.mcc = 1, .mnc = 99, .lac = 99, .rac = 96};
- bssgp_nsi = nsi;
- gbcfg.nsi = bssgp_nsi;
- gbcfg.nsip_sgsn_nsei = SGSN_NSEI;
- sgsn_peer.sin_family = AF_INET;
- sgsn_peer.sin_port = htons(32000);
- sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR);
- bss_peer[0].sin_family = AF_INET;
- bss_peer[0].sin_port = htons(1111);
- bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR);
- printf("--- Initialise SGSN ---\n\n");
- gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1);
- send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI);
- send_ns_alive_ack(nsi, &sgsn_peer);
- send_ns_unblock_ack(nsi, &sgsn_peer);
- send_ns_alive(nsi, &sgsn_peer);
- gprs_dump_nsi(nsi);
this can be easily shared. You seem to only vary the amount of bss_peer's you create.
- gbprox_dump_peers(stdout, 0, 1);
Please have a look here: http://qt-project.org/wiki/API_Design_Principles specially read about the boolean parameter trap.
My train just arrived. I will continue the review in a bit.
have a nice day holger
This parameter is not used (the methods are always called with an argument of 1 in the third position). Thus the parameter is removed completely.
Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gb_proxy.h | 4 +-- openbsc/src/gprs/gb_proxy.c | 10 ++----- openbsc/tests/gbproxy/gbproxy_test.c | 52 ++++++++++++++++++------------------ 3 files changed, 30 insertions(+), 36 deletions(-)
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 4d189a6..5f1f3a7 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -37,7 +37,7 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, /* Reset all persistent NS-VC's */ int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
-int gbprox_dump_global(FILE *stream, int indent, int verbose); -int gbprox_dump_peers(FILE *stream, int indent, int verbose); +int gbprox_dump_global(FILE *stream, int indent); +int gbprox_dump_peers(FILE *stream, int indent); void gbprox_reset(); #endif diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 4799344..9de2ca9 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -806,7 +806,7 @@ int gbprox_signal(unsigned int subsys, unsigned int signal, return 0; }
-int gbprox_dump_global(FILE *stream, int indent, int verbose) +int gbprox_dump_global(FILE *stream, int indent) { unsigned int i; const struct rate_ctr_group_desc *desc; @@ -816,9 +816,6 @@ int gbprox_dump_global(FILE *stream, int indent, int verbose) if (rc < 0) return rc;
- if (!verbose) - return 0; - desc = get_global_ctrg()->desc;
for (i = 0; i < desc->num_ctr; i++) { @@ -837,7 +834,7 @@ int gbprox_dump_global(FILE *stream, int indent, int verbose) return 0; }
-int gbprox_dump_peers(FILE *stream, int indent, int verbose) +int gbprox_dump_peers(FILE *stream, int indent) { struct gbprox_peer *peer; struct gprs_ra_id raid; @@ -862,9 +859,6 @@ int gbprox_dump_peers(FILE *stream, int indent, int verbose) if (rc < 0) return rc;
- if (!verbose) - continue; - desc = peer->ctrg->desc;
for (i = 0; i < desc->num_ctr; i++) { diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index ea07a77..a8f4eaf 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -420,7 +420,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -429,7 +429,7 @@ static void test_gbproxy() setup_ns(nsi, &bss_peer[1], 0x2001, 0x2000); setup_bssgp(nsi, &bss_peer[1], 0x2002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x2002);
@@ -437,43 +437,43 @@ static void test_gbproxy()
setup_ns(nsi, &bss_peer[2], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Move BSS 1 to current BSS 2 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Move BSS 2 to new port ---\n\n");
setup_ns(nsi, &bss_peer[3], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Move BSS 2 to former BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[2], 0x2001, 0x2000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Move BSS 1 to original BSS 1 port ---\n\n");
setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Reset BSS 1 with a new BVCI ---\n\n");
setup_bssgp(nsi, &bss_peer[0], 0x1012); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1012);
@@ -481,7 +481,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -489,7 +489,7 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[0], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -521,9 +521,9 @@ static void test_gbproxy()
setup_bssgp(nsi, &bss_peer[2], 0x1002); gprs_dump_nsi(nsi); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
- gbprox_dump_global(stdout, 0, 1); + gbprox_dump_global(stdout, 0);
send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002);
@@ -539,7 +539,7 @@ static void test_gbproxy()
send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x10ff, (uint8_t *)"", 0);
- gbprox_dump_global(stdout, 0, 1); + gbprox_dump_global(stdout, 0);
gprs_ns_destroy(nsi); nsi = NULL; @@ -585,13 +585,13 @@ static void test_gbproxy_ident_changes()
setup_bssgp(nsi, &bss_peer[0], bvci[0]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Setup BVCI 2 ---\n\n");
setup_bssgp(nsi, &bss_peer[0], bvci[1]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[1]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
@@ -612,13 +612,13 @@ static void test_gbproxy_ident_changes()
setup_bssgp(nsi, &bss_peer[0], bvci[0]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Setup BVCI 3 ---\n\n");
setup_bssgp(nsi, &bss_peer[0], bvci[2]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[2]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
@@ -629,9 +629,9 @@ static void test_gbproxy_ident_changes() " (should fail) ---\n\n");
send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0); send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
@@ -647,13 +647,13 @@ static void test_gbproxy_ident_changes()
setup_bssgp(nsi, &bss_peer[0], bvci[0]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[0]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Setup BVCI 4 ---\n\n");
setup_bssgp(nsi, &bss_peer[0], bvci[3]); send_bssgp_reset_ack(nsi, &sgsn_peer, bvci[3]); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Send message from BSS 1 to SGSN and back, BVCI 1 ---\n\n");
@@ -664,9 +664,9 @@ static void test_gbproxy_ident_changes() " (should fail) ---\n\n");
send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[1], (uint8_t *)"", 0); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0); send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[1], (uint8_t *)"", 0); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_peers(stdout, 0);
printf("--- Send message from BSS 1 to SGSN and back, BVCI 3 ---\n\n");
@@ -678,8 +678,8 @@ static void test_gbproxy_ident_changes() send_ns_unitdata(nsi, NULL, &bss_peer[0], bvci[3], (uint8_t *)"", 0); send_ns_unitdata(nsi, NULL, &sgsn_peer, bvci[3], (uint8_t *)"", 0);
- gbprox_dump_global(stdout, 0, 1); - gbprox_dump_peers(stdout, 0, 1); + gbprox_dump_global(stdout, 0); + gbprox_dump_peers(stdout, 0);
gprs_ns_destroy(nsi); nsi = NULL;
This function abstracts identical code sequences that are used at multiple places.
Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index a8f4eaf..ba1c51b 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -193,6 +193,15 @@ static void setup_bssgp(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, send_bssgp_reset(nsi, src_addr, bvci); }
+static void connect_sgsn(struct gprs_ns_inst *nsi, struct sockaddr_in *sgsn_peer) +{ + gprs_ns_nsip_connect(nsi, sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); + send_ns_reset_ack(nsi, sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); + send_ns_alive_ack(nsi, sgsn_peer); + send_ns_unblock_ack(nsi, sgsn_peer); + send_ns_alive(nsi, sgsn_peer); +} + int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, struct sockaddr_in *saddr, enum gprs_ns_ll ll);
@@ -408,11 +417,7 @@ static void test_gbproxy()
printf("--- Initialise SGSN ---\n\n");
- gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); - send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); - send_ns_alive_ack(nsi, &sgsn_peer); - send_ns_unblock_ack(nsi, &sgsn_peer); - send_ns_alive(nsi, &sgsn_peer); + connect_sgsn(nsi, &sgsn_peer); gprs_dump_nsi(nsi);
printf("--- Initialise BSS 1 ---\n\n"); @@ -569,11 +574,7 @@ static void test_gbproxy_ident_changes()
printf("--- Initialise SGSN ---\n\n");
- gprs_ns_nsip_connect(nsi, &sgsn_peer, SGSN_NSEI, SGSN_NSEI+1); - send_ns_reset_ack(nsi, &sgsn_peer, SGSN_NSEI+1, SGSN_NSEI); - send_ns_alive_ack(nsi, &sgsn_peer); - send_ns_unblock_ack(nsi, &sgsn_peer); - send_ns_alive(nsi, &sgsn_peer); + connect_sgsn(nsi, &sgsn_peer); gprs_dump_nsi(nsi);
printf("--- Initialise BSS 1 ---\n\n");
This adds a test case with several messages to test BSSGP patching. New messages:
- BSSGP/DTAP Attach Request - BSSGP/DTAP Attach Accept - BSSGP/DTAP Routing Area Update Request - BSSGP/DTAP Routing Area Update Accept - BSSGP/DTAP Activate PDP Context Request - BSSGP SUSPEND - BSSGP SUSPEND ACK
Sponsored-by: On-Waves ehf --- openbsc/tests/gbproxy/gbproxy_test.c | 193 +++++++++++++++++++++++- openbsc/tests/gbproxy/gbproxy_test.ok | 268 ++++++++++++++++++++++++++++++++++ 2 files changed, 460 insertions(+), 1 deletion(-)
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index ba1c51b..97dbfec 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -28,13 +28,88 @@ #include <osmocom/gprs/gprs_bssgp.h>
#include <openbsc/gb_proxy.h> +#include <openbsc/debug.h>
#define REMOTE_BSS_ADDR 0x01020304 #define REMOTE_SGSN_ADDR 0x05060708
#define SGSN_NSEI 0x0100
-struct gbproxy_config gbcfg; +struct gbproxy_config gbcfg = {0}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Request */ +static const unsigned char bssgp_attach_req[75] = { + 0x01, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x34, 0x01, + 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0xe0, 0x21, + 0x08, 0x02, 0x05, 0xf4, 0xfb, 0xc5, 0x46, 0x79, + 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x19, 0x18, + 0xb3, 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, + 0x80, 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, + 0xba, 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, + 0x16, 0x6d, 0x01 +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Attach Accept */ +static const unsigned char bssgp_attach_acc[88] = { + 0x00, 0xbb, 0xc5, 0x46, 0x79, 0x00, 0x50, 0x20, + 0x16, 0x82, 0x02, 0x58, 0x13, 0x99, 0x18, 0xb3, + 0x43, 0x2b, 0x25, 0x96, 0x62, 0x00, 0x60, 0x80, + 0x9a, 0xc2, 0xc6, 0x62, 0x00, 0x60, 0x80, 0xba, + 0xc8, 0xc6, 0x62, 0x00, 0x60, 0x80, 0x00, 0x0a, + 0x82, 0x08, 0x02, 0x0d, 0x88, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x81, 0x00, + 0x0e, 0x9e, 0x41, 0xc0, 0x05, 0x08, 0x02, 0x01, + 0x49, 0x04, 0x21, 0x63, 0x54, 0x40, 0x50, 0x60, + 0x19, 0xcd, 0xd7, 0x08, 0x17, 0x16, 0x18, 0x05, + 0xf4, 0xfb, 0xc5, 0x47, 0x22, 0x42, 0x67, 0x9a +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Request */ +static const unsigned char bssgp_ra_upd_req[85] = { + 0x01, 0xaf, 0xe2, 0x80, 0x6e, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x70, 0x80, 0x00, 0x80, 0x0e, 0x00, 0x3e, 0x01, + 0xc0, 0x15, 0x08, 0x08, 0x10, 0x11, 0x22, 0x33, + 0x40, 0x50, 0x60, 0x1d, 0x19, 0x13, 0x42, 0x33, + 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, 0x13, 0x48, + 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, 0x50, 0xc8, + 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, 0x48, 0x02, + 0x00, 0x19, 0x8b, 0xb2, 0x92, 0x17, 0x16, 0x27, + 0x07, 0x04, 0x31, 0x02, 0xe5, 0xe0, 0x32, 0x02, + 0x20, 0x00, 0x96, 0x3e, 0x97 +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Routing Area Update Accept */ +static const unsigned char bssgp_ra_upd_acc[91] = { + 0x00, 0xaf, 0xe2, 0x80, 0x6e, 0x00, 0x50, 0x20, + 0x16, 0x82, 0x02, 0x58, 0x13, 0x9d, 0x19, 0x13, + 0x42, 0x33, 0x57, 0x2b, 0xf7, 0xc8, 0x48, 0x02, + 0x13, 0x48, 0x50, 0xc8, 0x48, 0x02, 0x14, 0x48, + 0x50, 0xc8, 0x48, 0x02, 0x17, 0x49, 0x10, 0xc8, + 0x48, 0x02, 0x00, 0x0a, 0x82, 0x07, 0x04, 0x0d, + 0x88, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x00, 0x81, 0x00, 0x0e, 0x9d, 0x41, 0xc0, + 0x19, 0x08, 0x09, 0x00, 0x49, 0x21, 0x63, 0x54, + 0x40, 0x50, 0x60, 0x19, 0x54, 0xab, 0xb3, 0x18, + 0x05, 0xf4, 0xef, 0xe2, 0x81, 0x17, 0x17, 0x16, + 0xc3, 0xbf, 0xcc +}; + +/* Base Station Subsystem GPRS Protocol: GSM A-I/F DTAP - Activate PDP Context Request */ +static const unsigned char bssgp_act_pdp_ctx_req[76] = { + 0x01, 0xef, 0xe2, 0xb7, 0x00, 0x00, 0x00, 0x04, + 0x08, 0x88, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, + 0x75, 0x30, 0x00, 0x80, 0x0e, 0x00, 0x35, 0x01, + 0xc0, 0x0d, 0x0a, 0x41, 0x05, 0x03, 0x0c, 0x00, + 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, 0x03, + 0x02, 0x61, 0x62, 0x27, 0x14, 0x80, 0x80, 0x21, + 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x5a, 0xff, 0x02 +};
static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, struct sockaddr_in *peer, const unsigned char* data, @@ -168,6 +243,37 @@ static void send_bssgp_reset_ack(struct gprs_ns_inst *nsi, send_ns_unitdata(nsi, "BVC_RESET_ACK", src_addr, 0, msg, sizeof(msg)); }
+static void send_bssgp_suspend(struct gprs_ns_inst *nsi, + struct sockaddr_in *src_addr, + struct gprs_ra_id *raid) +{ + /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND */ + unsigned char msg[15] = { + 0x0b, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b, + 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60 + }; + + gsm48_construct_ra(msg + 9, raid); + + send_ns_unitdata(nsi, "BVC_SUSPEND", src_addr, 0, msg, sizeof(msg)); +} + +static void send_bssgp_suspend_ack(struct gprs_ns_inst *nsi, + struct sockaddr_in *src_addr, + struct gprs_ra_id *raid) +{ + /* Base Station Subsystem GPRS Protocol, BSSGP SUSPEND ACK */ + unsigned char msg[18] = { + 0x0c, 0x1f, 0x84, 0xcc, 0xd1, 0x75, 0x8b, 0x1b, + 0x86, 0x11, 0x22, 0x33, 0x40, 0x50, 0x60, 0x1d, + 0x81, 0x01 + }; + + gsm48_construct_ra(msg + 9, raid); + + send_ns_unitdata(nsi, "BVC_SUSPEND_ACK", src_addr, 0, msg, sizeof(msg)); +} + static void setup_ns(struct gprs_ns_inst *nsi, struct sockaddr_in *src_addr, uint16_t nsvci, uint16_t nsei) { @@ -687,6 +793,90 @@ static void test_gbproxy_ident_changes() gbprox_reset(); }
+static void test_gbproxy_ra_patching() +{ + struct gprs_ns_inst *nsi = gprs_ns_instantiate(gprs_ns_callback, NULL); + struct sockaddr_in bss_peer[1] = {{0},}; + struct sockaddr_in sgsn_peer= {0}; + struct gprs_ra_id rai_bss = + {.mcc = 112, .mnc = 332, .lac = 16464, .rac = 96}; + struct gprs_ra_id rai_sgsn = + {.mcc = 123, .mnc = 456, .lac = 16464, .rac = 96}; + struct gprs_ra_id rai_unknown = + {.mcc = 1, .mnc = 99, .lac = 99, .rac = 96}; + + bssgp_nsi = nsi; + gbcfg.nsi = bssgp_nsi; + gbcfg.nsip_sgsn_nsei = SGSN_NSEI; + + sgsn_peer.sin_family = AF_INET; + sgsn_peer.sin_port = htons(32000); + sgsn_peer.sin_addr.s_addr = htonl(REMOTE_SGSN_ADDR); + + bss_peer[0].sin_family = AF_INET; + bss_peer[0].sin_port = htons(1111); + bss_peer[0].sin_addr.s_addr = htonl(REMOTE_BSS_ADDR); + + printf("--- Initialise SGSN ---\n\n"); + + connect_sgsn(nsi, &sgsn_peer); + gprs_dump_nsi(nsi); + + printf("--- Initialise BSS 1 ---\n\n"); + + setup_ns(nsi, &bss_peer[0], 0x1001, 0x1000); + setup_bssgp(nsi, &bss_peer[0], 0x1002); + gprs_dump_nsi(nsi); + gbprox_dump_peers(stdout, 0); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1002); + + send_bssgp_suspend(nsi, &bss_peer[0], &rai_bss); + send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_sgsn); + + gbprox_dump_global(stdout, 0); + gbprox_dump_peers(stdout, 0); + + printf("--- Send message from BSS 1 to SGSN, BVCI 0x1002 ---\n\n"); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_attach_req, sizeof(bssgp_attach_req)); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1002, + bssgp_attach_acc, sizeof(bssgp_attach_acc)); + + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_ra_upd_req, sizeof(bssgp_ra_upd_req)); + + send_ns_unitdata(nsi, NULL, &sgsn_peer, 0x1002, + bssgp_ra_upd_acc, sizeof(bssgp_ra_upd_acc)); + + /* Replace APN */ + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req)); + + /* TODO: Re-configure to test APN IE removal */ + + /* Remove APN */ + send_ns_unitdata(nsi, NULL, &bss_peer[0], 0x1002, + bssgp_act_pdp_ctx_req, sizeof(bssgp_act_pdp_ctx_req)); + + gbprox_dump_global(stdout, 0); + gbprox_dump_peers(stdout, 0); + + printf("--- Bad cases ---\n\n"); + + send_bssgp_reset_ack(nsi, &sgsn_peer, 0x1eee); + send_bssgp_suspend_ack(nsi, &sgsn_peer, &rai_unknown); + + gbprox_dump_global(stdout, 0); + gbprox_dump_peers(stdout, 0); + + gprs_ns_destroy(nsi); + nsi = NULL; + gbprox_reset(); +} +
static struct log_info info = {};
@@ -707,6 +897,7 @@ int main(int argc, char **argv) printf("===== GbProxy test START\n"); test_gbproxy(); test_gbproxy_ident_changes(); + test_gbproxy_ra_patching(); printf("===== GbProxy test END\n\n");
exit(EXIT_SUCCESS); diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 3b25922..58add97 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -1518,5 +1518,273 @@ Peers: NS Transmission error : 2 NSEI 8192, BVCI 4098, not blocked, RAI 112-332-16464-96 NSEI mismatch : 1 +--- 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 + +Current NS-VCIs: + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 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 00 00 00 00 + +CALLBACK, event 0, msg length 22, bvci 0x0000 +22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 22 +22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +MESSAGE to SGSN at 0x05060708:32000, msg length 26 +00 00 00 00 22 04 82 10 02 07 81 08 08 88 11 22 33 40 50 60 10 00 00 00 00 00 + +result (BVC_RESET) = 26 + +Current NS-VCIs: + VCI 0x1001, NSEI 0x1000, peer 0x01020304:1111 + VCI 0x0101, NSEI 0x0100, peer 0x05060708:32000 + NS-VC Block count : 1 + +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 10 02 + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 10 02 + +NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 5 +23 04 82 10 02 + +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 +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 +0b 1f 84 cc d1 75 8b 1b 86 11 22 33 40 50 60 + +MESSAGE to SGSN at 0x05060708:32000, msg length 19 +00 00 00 00 0b 1f 84 cc d1 75 8b 1b 86 11 22 33 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 +0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 21 63 54 40 50 60 1d 81 01 + +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 21 63 54 40 50 60 1d 81 01 + +result (BVC_SUSPEND_ACK) = 28 + +Gbproxy global: + Invalid Routing Area Identifier : 1 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +--- Send message from BSS 1 to SGSN, BVCI 0x1002 --- + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 +01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 79 +00 00 10 02 01 bb c5 46 79 00 00 04 08 88 11 22 33 40 50 60 75 30 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 (UNITDATA) = 79 + +PROCESSING UNITDATA 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 fb c5 47 22 42 67 9a + +CALLBACK, event 0, msg length 88, bvci 0x1002 +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 fb c5 47 22 42 67 9a + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 +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 fb c5 47 22 42 67 9a + +MESSAGE to BSS at 0x01020304:1111, msg length 92 +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 fb c5 47 22 42 67 9a + +result (UNITDATA) = 92 + +PROCESSING UNITDATA from 0x01020304:1111 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +CALLBACK, event 0, msg length 85, bvci 0x1002 +01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 +01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +MESSAGE to SGSN at 0x05060708:32000, msg length 89 +00 00 10 02 01 af e2 80 6e 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 15 08 08 10 11 22 33 40 50 60 1d 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 19 8b b2 92 17 16 27 07 04 31 02 e5 e0 32 02 20 00 96 3e 97 + +result (UNITDATA) = 89 + +PROCESSING UNITDATA from 0x05060708:32000 +00 00 10 02 00 af e2 80 6e 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 91, bvci 0x1002 +00 af e2 80 6e 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 + +NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 91 +00 af e2 80 6e 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 + +MESSAGE to BSS at 0x01020304:1111, msg length 95 +00 00 10 02 00 af e2 80 6e 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 + +result (UNITDATA) = 95 + +PROCESSING UNITDATA 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 + +CALLBACK, event 0, msg length 76, bvci 0x1002 +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 +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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 80 +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 + +result (UNITDATA) = 80 + +PROCESSING UNITDATA 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 + +CALLBACK, event 0, msg length 76, bvci 0x1002 +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 +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 + +MESSAGE to SGSN at 0x05060708:32000, msg length 80 +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 + +result (UNITDATA) = 80 + +Gbproxy global: + Invalid Routing Area Identifier : 1 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 +--- Bad cases --- + +PROCESSING BVC_RESET_ACK from 0x05060708:32000 +00 00 00 00 23 04 82 1e ee + +CALLBACK, event 0, msg length 5, bvci 0x0000 +23 04 82 1e ee + +result (BVC_RESET_ACK) = -2 + +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 + +CALLBACK, event 0, msg length 18, bvci 0x0000 +0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 + +NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 24 +41 07 81 05 15 92 0c 1f 84 cc d1 75 8b 1b 86 00 f1 99 00 63 60 1d 81 01 + +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 00 f1 99 00 63 60 1d 81 01 + +result (BVC_SUSPEND_ACK) = 28 + +Gbproxy global: + Invalid BVC Identifier : 1 + Invalid Routing Area Identifier : 2 +Peers: + NSEI 4096, BVCI 4098, not blocked, RAI 112-332-16464-96 ===== GbProxy test END