From nhofmeyr at sysmocom.de Thu Oct 1 13:23:49 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:49 +0200 Subject: next version of OAP patch Message-ID: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Hi openbsc, here is my improved version of the OAP aka SGSN-ID patch series. This series is pushed to the neels/sgsn-id-3 branch. This version is substantially simpler, because I decided against factoring out the IPA client. Instead, the gprs_gsup_client.c will directly call the OAP API to handle OAP messages. Factoring out the IPA client was not a requirement and taking too much time, and since the name will remain "GSUP client" (to avoid changing the VTY configuration names among other things), it does after all make sense to think of it as: "the GSUP client employs OAP to authenticate" instead of "GSUP and OAP are two separate clients on the IPA wire". The OAP spec has changed. Particularly instead of SRES and Kc, the challenge response now sends XRES only; and the spec now includes an AUTS request (not yet implemented). Going through the changes, I've made a few fixes (like wrong file header comments), and made some changes. The OAP API looks quite different, and now merely returns struct msgb* and lets the caller take care of sending. This time, OAP has its own separate testsuite tests/oap. I have further OAP tests in mind to add; particularly the complete SGSN registration test from the previous patch version is not yet included here. Anyway, the OAP API test has become more comprehensive. Some of the patch mods have come from comments by hfreyther and jerlbeck, other changes were obvious from reviewing the code. I think this time around the patch is much more mature. I hope you agree, if not I'll gladly improve it further, of course :) Thanks for your reviews! ~Neels From nhofmeyr at sysmocom.de Thu Oct 1 13:23:55 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:55 +0200 Subject: [PATCH 6/8] oap: add OAP API test In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-7-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/tests/oap/oap_test.c | 193 +++++++++++++++++++++++++++++++++++++++++- openbsc/tests/oap/oap_test.ok | 7 +- 2 files changed, 195 insertions(+), 5 deletions(-) diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c index b03c8dc..9a2063b 100644 --- a/openbsc/tests/oap/oap_test.c +++ b/openbsc/tests/oap/oap_test.c @@ -27,10 +27,195 @@ #include - -static void test_oap(void) +static void test_oap_api(void) { - printf("not implemented\n"); + printf("Testing OAP API\n - Config parsing\n"); + + struct oap_config _config; + struct oap_config *config = &_config; + + struct oap_state _state; + struct oap_state *state = &_state; + + memset(config, 0, sizeof(*config)); + memset(state, 0, sizeof(*state)); + + OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16); + OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16); + + /* make sure filling with zeros means uninitialized */ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + /* invalid client_id and shared secret */ + config->client_id = 0; + config->secret_k_present = 0; + config->secret_opc_present = 0; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + /* reset state */ + memset(state, 0, sizeof(*state)); + + /* only client_id is invalid */ + config->client_id = 0; + config->secret_k_present = 1; + config->secret_opc_present = 1; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + /* valid id, but omitted shared_secret (1/2) */ + config->client_id = 12345; + config->secret_k_present = 0; + config->secret_opc_present = 1; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + /* valid id, but omitted shared_secret (2/2) */ + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 0; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + + /* mint configuration */ + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 1; + /*config->secret_* buffers are still set from the top */ + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_INITIALIZED); + + printf(" - AUTN failures\n"); + + struct oap_message oap_rx; + struct oap_message oap_tx; + struct msgb *msg_rx; + struct msgb *msg_tx; + + memset(&oap_rx, 0, sizeof(oap_rx)); + + /* Missing challenge data */ + oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST; + oap_rx.rand_present = 0; + oap_rx.autn_present = 0; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* AUTN missing */ + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + oap_rx.rand_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* RAND missing */ + oap_rx.rand_present = 0; + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.autn_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* wrong autn (by one bit) */ + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + osmo_hexparse("dec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.rand_present = 1; + oap_rx.autn_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* all data correct */ + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + msg_rx = oap_encoded(&oap_rx); + + /* but refuse to evaluate in uninitialized state */ + OSMO_ASSERT(state->state == OAP_INITIALIZED); + + state->state = OAP_UNINITIALIZED; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1); + OSMO_ASSERT(!msg_tx); + + state->state = OAP_DISABLED; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1); + OSMO_ASSERT(!msg_tx); + + state->state = OAP_INITIALIZED; + + /* now everything is correct */ + printf(" - AUTN success\n"); + /* a successful return value here indicates correct autn */ + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + msgb_free(msg_rx); + + /* Expect the challenge response in msg_tx */ + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT); + OSMO_ASSERT(strcmp("e2d05b598c61d9ba", + osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres))) + == 0); + OSMO_ASSERT(state->state == OAP_SENT_CHALLENGE_RESULT); + msgb_free(msg_tx); + msg_tx = 0; + + struct oap_state saved_state = _state; + + printf(" - Registration failure\n"); + + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_ERROR; + oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC; + msg_rx = oap_encoded(&oap_rx); + + /* Receive registration error for the first time. */ + OSMO_ASSERT(state->registration_failures == 0); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(state->registration_failures == 1); + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST); + OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE); + msgb_free(msg_tx); + msg_tx = 0; + + /* Receive registration error for the Nth time. */ + state->registration_failures = 999; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -11); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OAP_INITIALIZED); + msgb_free(msg_tx); + msg_tx = 0; + + msgb_free(msg_rx); + + printf(" - Registration success\n"); + + _state = saved_state; + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_RESULT; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OAP_REGISTERED); + msgb_free(msg_rx); } static struct log_info_cat gprs_categories[] = { @@ -50,7 +235,7 @@ int main(int argc, char **argv) { osmo_init_logging(&info); - test_oap(); + test_oap_api(); printf("Done\n"); return 0; diff --git a/openbsc/tests/oap/oap_test.ok b/openbsc/tests/oap/oap_test.ok index e411ad9..2e9ecf0 100644 --- a/openbsc/tests/oap/oap_test.ok +++ b/openbsc/tests/oap/oap_test.ok @@ -1,2 +1,7 @@ -not implemented +Testing OAP API + - Config parsing + - AUTN failures + - AUTN success + - Registration failure + - Registration success Done -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:54 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:54 +0200 Subject: [PATCH 5/8] oap: add oap testsuite skeleton In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-6-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/.gitignore | 1 + openbsc/configure.ac | 1 + openbsc/tests/Makefile.am | 2 +- openbsc/tests/oap/Makefile.am | 19 ++++++++++++++ openbsc/tests/oap/oap_test.c | 58 +++++++++++++++++++++++++++++++++++++++++++ openbsc/tests/oap/oap_test.ok | 2 ++ openbsc/tests/testsuite.at | 7 ++++++ 7 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/oap/Makefile.am create mode 100644 openbsc/tests/oap/oap_test.c create mode 100644 openbsc/tests/oap/oap_test.ok diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 2210c47..ca73db6 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -77,6 +77,7 @@ tests/trau/trau_test tests/mgcp/mgcp_transcoding_test tests/sgsn/sgsn_test tests/subscr/subscr_test +tests/oap/oap_test tests/atconfig tests/atlocal diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 78302dd..228db58 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -209,6 +209,7 @@ AC_OUTPUT( tests/trau/Makefile tests/sgsn/Makefile tests/subscr/Makefile + tests/oap/Makefile doc/Makefile doc/examples/Makefile Makefile) diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 773830b..1b557d4 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr oap if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/oap/Makefile.am b/openbsc/tests/oap/Makefile.am new file mode 100644 index 0000000..e160902 --- /dev/null +++ b/openbsc/tests/oap/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) + +EXTRA_DIST = oap_test.ok + +noinst_PROGRAMS = oap_test + +oap_test_SOURCES = oap_test.c + +oap_test_LDADD = \ + $(top_builddir)/src/gprs/oap.o \ + $(top_builddir)/src/gprs/oap_messages.o \ + $(top_builddir)/src/gprs/gprs_utils.o \ + $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + -lrt + diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c new file mode 100644 index 0000000..b03c8dc --- /dev/null +++ b/openbsc/tests/oap/oap_test.c @@ -0,0 +1,58 @@ +/* Test Osmocom Authentication Protocol */ +/* + * (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include + +#include +#include + +#include + + +static void test_oap(void) +{ + printf("not implemented\n"); +} + +static struct log_info_cat gprs_categories[] = { + [DGPRS] = { + .name = "DGPRS", + .description = "GPRS Packet Service", + .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) +{ + osmo_init_logging(&info); + + test_oap(); + printf("Done\n"); + + return 0; +} + diff --git a/openbsc/tests/oap/oap_test.ok b/openbsc/tests/oap/oap_test.ok new file mode 100644 index 0000000..e411ad9 --- /dev/null +++ b/openbsc/tests/oap/oap_test.ok @@ -0,0 +1,2 @@ +not implemented +Done diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 74aaef0..78aa47e 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -103,3 +103,10 @@ AT_CHECK([test "$enable_sgsn_test" != no || exit 77]) cat $abs_srcdir/sgsn/sgsn_test.ok > expout AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([oap]) +AT_KEYWORDS([oap]) +AT_CHECK([test "$enable_oap_test" != no || exit 77]) +cat $abs_srcdir/oap/oap_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/oap/oap_test], [], [expout], [ignore]) +AT_CLEANUP -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:52 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:52 +0200 Subject: [PATCH 3/8] Add OAP design document. In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-4-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/doc/osmocom-authn-protocol.txt | 250 +++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 openbsc/doc/osmocom-authn-protocol.txt diff --git a/openbsc/doc/osmocom-authn-protocol.txt b/openbsc/doc/osmocom-authn-protocol.txt new file mode 100644 index 0000000..1b6794e --- /dev/null +++ b/openbsc/doc/osmocom-authn-protocol.txt @@ -0,0 +1,250 @@ + + Osmocom Authentication Protocol (OAP) + +1. General + +The Osmocom Authentication Protocol employs mutual authentication to register a +client with a server over an IPA connection. Milenage is used as the +authentication algorithm, where client and server have a shared secret. + +For example, an SGSN, as OAP client, may use its SGSN ID to register with a MAP +proxy, an OAP server. + +1.1. Connection + +The protocol expects that a reliable, ordered, packet boundaries preserving +connection is used (e.g. IPA over TCP). + +1.2. Using IPA + +By default, the following identifiers should be used: + - IPA protocol: 0xee (OSMO) + - IPA OSMO protocol extension: 0x06 (OAP) + +2. Procedures + +Ideal communication sequence: + + Client Server + | | + | Register (ID) | + |----------------------------------->| + | | + | Challenge (RAND+AUTN) | + |<-----------------------------------| + | | + | Challenge Result (XRES) | + |----------------------------------->| + | | + | Register Result | + |<-----------------------------------| + +Variation "test setup": + + Client Server + | | + | Register (ID) | + |----------------------------------->| + | | + | Register Result | + |<-----------------------------------| + +Variation "invalid sequence nr": + + Client Server + | | + | Register (ID) | + |----------------------------------->| + | | + | Challenge (RAND+AUTN) | + |<-----------------------------------| + | | + | Sync Request (AUTS) | + |----------------------------------->| + | | + | Challenge (RAND'+AUTN') | + |<-----------------------------------| + | | + | Challenge Result (XRES) | + |----------------------------------->| + | | + | Register Result | + |<-----------------------------------| + +2.1. Register + +The client sends a REGISTER_REQ message containing an identifier number. + +2.2. Challenge + +The OAP server (optionally) sends back a CHALLENGE_REQ, containing random bytes +and a milenage authentication token generated from these random bytes, using a +shared secret, to authenticate itself to the OAP client. The server may omit +this challenge entirely, based on its configuration, and immediately reply with +a Register Result response. If the client cannot be registered (e.g. id is +invalid), the server sends a REGISTER_ERR response. + +2.3. Challenge Result + +When the client has received a Challenge, it may verify the server's +authenticity and validity of the sequence number (included in AUTN), and, if +valid, reply with a CHALLENGE_RES message. This shall contain an XRES +authentication token generated by milenage from the same random bytes received +from the server and the same shared secet. If the client decides to cancel the +registration (e.g. invalid AUTN), it shall not reply to the CHALLENGE_REQ; a +CHALLENGE_ERR message may be sent, but is not mandatory. For example, the +client may directly start with a new REGISTER_REQ message. + +2.4. Sync Request + +When the client has received a Challenge but sees an invalid sequence number +(embedded in AUTN, according to the milenage algorithm), the client may send a +SYNC_REQ message containing an AUTS synchronisation token. + +2.5. Sync Result + +If the server has received a valid Sync Request, it shall answer by directly +sending another Challenge (see 2.2.). If an invalid Sync Request is received, +the server shall reply with a REGISTER_ERR message. + +2.6. Register Result + +The server sends a REGISTER_RES message to indicate that registration has been +successful. If the server cannot register the client (e.g. invalid challenge +response), it shall send a REGISTER_ERR message. + +3. Message Format + +3.1. General + +Every message is based on the following message format + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + +The receiver shall be able to receive IEs in any order. Unknown IEs shall be +ignored. + +3.2.1. Register Request + +Client -> Server + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 30 Client ID big endian int (2 oct) M TLV 4 + +3.2.2. Register Error + +Server -> Client + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 02 Cause GMM cause, M TLV 3 + 04.08: 10.5.5.14 + +3.2.6. Register Result + +Server -> Client + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + +3.2.3. Challenge + +Server -> Client + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 20 RAND octet string (16) M TLV 18 + 23 AUTN octet string (16) M TLV 18 + +3.2.4. Challenge Error + +Client -> Server + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 02 Cause GMM cause, M TLV 3 + 04.08: 10.5.5.14 + +3.2.5. Challenge Result + +Client -> Server + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 21 XRES octet string (8) M TLV 10 + +3.2.3. Sync Request + +Client -> Server + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 20 AUTS octet string (16) M TLV 18 + +3.2.4. Sync Error + +Server -> Client + + IEI Info Element Type Pres. Format Length + Message type 4.2.1 M V 1 + 02 Cause GMM cause, M TLV 3 + 04.08: 10.5.5.14 + +4. Information Elements + +4.1. General + +[...] + +4.2.1. Message Type + + +---------------------------------------------------+ + | 8 7 6 5 4 3 2 1 | + | | + | 0 0 0 0 0 1 0 0 - Register Request | + | 0 0 0 0 0 1 0 1 - Register Error | + | 0 0 0 0 0 1 1 0 - Register Result | + | | + | 0 0 0 0 1 0 0 0 - Challenge Request | + | 0 0 0 0 1 0 0 1 - Challenge Error | + | 0 0 0 0 1 0 1 0 - Challenge Result | + | | + | 0 0 0 0 1 1 0 0 - Sync Request | + | 0 0 0 0 1 1 0 1 - Sync Error (not used) | + | 0 0 0 0 1 1 1 0 - Sync Result (not used) | + | | + +---------------------------------------------------+ + +4.2.2. IE Identifier (informational) + +These are the standard values for the IEI. + + +---------------------------------------------------------+ + | IEI Info Element Type | + | | + | 0x02 Cause GMM cause, 04.08: 10.5.5.14 | + | 0x20 RAND octet string | + | 0x23 AUTN octet string | + | 0x24 XRES octet string | + | 0x25 AUTS octet string | + | 0x30 Client ID big endian int (2 octets) | + +---------------------------------------------------------+ + +4.2.3. Client ID + + 8 7 6 5 4 3 2 1 + +-----------------------------------------------------+ + | | Client ID IEI | octet 1 + +-----------------------------------------------------+ + | Length of Client ID IE contents (2) | octet 2 + +-----------------------------------------------------+ + | Client ID number, most significant byte | octet 3 + +-----------------------------------------------------+ + | Client ID number, least significant byte | octet 4 + +-----------------------------------------------------+ + +The Client ID number shall be interpreted as an unsigned 16bit integer, where 0 +indicates an invalid / unset ID. + -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:51 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:51 +0200 Subject: [PATCH 2/8] gsup: factor out header composition & sending. In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-3-git-send-email-nhofmeyr@sysmocom.de> Move IPA header composition and sending to new static gsup_client_send() (so I can use it in the upcoming OAP code). Sponsored-by: On-Waves ehf --- openbsc/src/gprs/gprs_gsup_client.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c index 807b0c1..1f9e34c 100644 --- a/openbsc/src/gprs/gprs_gsup_client.c +++ b/openbsc/src/gprs/gprs_gsup_client.c @@ -100,6 +100,14 @@ static void connect_timer_cb(void *gsupc_) gsup_client_connect(gsupc); } +static void gsup_client_send(struct gprs_gsup_client *gsupc, int proto_ext, struct msgb *msg_tx) +{ + ipa_prepend_header_ext(msg_tx, proto_ext); + ipa_msg_push_header(msg_tx, IPAC_PROTO_OSMO); + ipa_client_conn_send(gsupc->link, msg_tx); + /* msg_tx is now queued and will be freed. */ +} + static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) { struct gprs_gsup_client *gsupc = link->data; @@ -275,9 +283,7 @@ int gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) return -EAGAIN; } - ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_GSUP); - ipa_msg_push_header(msg, IPAC_PROTO_OSMO); - ipa_client_conn_send(gsupc->link, msg); + gsup_client_send(gsupc, IPAC_PROTO_EXT_GSUP, msg); return 0; } -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:57 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:57 +0200 Subject: [PATCH 8/8] oap: add OAP config to VTY In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-9-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/src/gprs/sgsn_vty.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index b74d01a..838644e 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -214,6 +214,18 @@ static int config_write_sgsn(struct vty *vty) if (g_cfg->gsup_server_port) vty_out(vty, " gsup remote-port %d%s", g_cfg->gsup_server_port, VTY_NEWLINE); + + vty_out(vty, " gsup oap-id %d%s", + (int)g_cfg->oap.client_id, VTY_NEWLINE); + if (g_cfg->oap.secret_k_present != 0) + vty_out(vty, " gsup oap-k %s%s", + osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)), + VTY_NEWLINE); + if (g_cfg->oap.secret_opc_present != 0) + vty_out(vty, " gsup oap-opc %s%s", + osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)), + VTY_NEWLINE); + llist_for_each_entry(acl, &g_cfg->imsi_acl, list) vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE); @@ -895,6 +907,82 @@ DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd, return CMD_SUCCESS; } +DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd, + "gsup oap-id <0-65535>", + "GSUP Parameters\n" + "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n") +{ + /* VTY ensures range */ + g_cfg->oap.client_id = (uint16_t)atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd, + "gsup oap-k K", + "GSUP Parameters\n" + "Set the OAP shared secret K\nK value (16 byte) hex\n") +{ + const char *k = argv[0]; + + g_cfg->oap.secret_k_present = 0; + + if ((!k) || (strlen(k) == 0)) + goto disable; + + int k_len = osmo_hexparse(k, + g_cfg->oap.secret_k, + sizeof(g_cfg->oap.secret_k)); + if (k_len != 16) { + vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s", + k_len, VTY_NEWLINE); + goto disable; + } + + g_cfg->oap.secret_k_present = 1; + return CMD_SUCCESS; + +disable: + if (g_cfg->oap.client_id > 0) { + vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd, + "gsup oap-opc OPC", + "GSUP Parameters\n" + "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n") +{ + const char *opc = argv[0]; + + g_cfg->oap.secret_opc_present = 0; + + if ((!opc) || (strlen(opc) == 0)) + goto disable; + + int opc_len = osmo_hexparse(opc, + g_cfg->oap.secret_opc, + sizeof(g_cfg->oap.secret_opc)); + if (opc_len != 16) { + vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s", + opc_len, VTY_NEWLINE); + goto disable; + } + + g_cfg->oap.secret_opc_present = 1; + return CMD_SUCCESS; + +disable: + if (g_cfg->oap.client_id > 0) { + vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + DEFUN(cfg_apn_name, cfg_apn_name_cmd, "access-point-name NAME", "Configure a global list of allowed APNs\n" @@ -969,6 +1057,9 @@ int sgsn_vty_init(void) install_element(SGSN_NODE, &cfg_auth_policy_cmd); install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd); install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd); install_element(SGSN_NODE, &cfg_apn_ggsn_cmd); install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd); install_element(SGSN_NODE, &cfg_apn_name_cmd); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:50 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:50 +0200 Subject: [PATCH 1/8] libcommon: soak up three static functions. In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-2-git-send-email-nhofmeyr@sysmocom.de> Add new kitchen sink openbsc/utils.h and libcommon/utils.c to make three so far static functions public (so I can use them in the upcoming OAP code). A place to put them could have been the gprs_utils.h, but all general functions in there have a gprs_ prefix, and todo markings to move them away. All other libcommon headers are too specific, so I opened up this kitchen sink header. Apply the change in Makefiles and C files. --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/utils.h | 17 ++++++++++ openbsc/src/gprs/gprs_gsup_messages.c | 30 +--------------- openbsc/src/libcommon/Makefile.am | 2 +- openbsc/src/libcommon/utils.c | 64 +++++++++++++++++++++++++++++++++++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 12 +------ openbsc/tests/gprs/Makefile.am | 3 +- 7 files changed, 87 insertions(+), 43 deletions(-) create mode 100644 openbsc/include/openbsc/utils.h create mode 100644 openbsc/src/libcommon/utils.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 254f43d..828f5bd 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -14,7 +14,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \ bss.h gsm_data_shared.h ipaccess.h mncc_int.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ - osmux.h mgcp_transcode.h gprs_utils.h \ + osmux.h mgcp_transcode.h gprs_utils.h utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ gprs_gsup_client.h bsc_msg_filter.h diff --git a/openbsc/include/openbsc/utils.h b/openbsc/include/openbsc/utils.h new file mode 100644 index 0000000..739b7a3 --- /dev/null +++ b/openbsc/include/openbsc/utils.h @@ -0,0 +1,17 @@ +/* OpenBSC kitchen sink */ + +#pragma once + +#include +#include + +/* Compare count bytes of exp to rel. Return 0 if they are identical, 1 + * otherwise. Do not return a mismatch on the first mismatching byte, + * but always compare all bytes, regardless. The idea is that the amount of + * matching bytes cannot be inferred from the time the comparison took.*/ +int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count); + +uint64_t decode_big_endian(const uint8_t *data, size_t data_len); +uint8_t *encode_big_endian(uint64_t value, size_t data_len); + + diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index bdcff5f..07485f7 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -26,41 +26,13 @@ #include #include +#include #include #include #include - -static uint64_t decode_big_endian(const uint8_t *data, size_t data_len) -{ - uint64_t value = 0; - - while (data_len > 0) { - value = (value << 8) + *data; - data += 1; - data_len -= 1; - } - - return value; -} - -static uint8_t *encode_big_endian(uint64_t value, size_t data_len) -{ - static uint8_t buf[sizeof(uint64_t)]; - int idx; - - OSMO_ASSERT(data_len <= ARRAY_SIZE(buf)); - - for (idx = data_len - 1; idx >= 0; idx--) { - buf[idx] = (uint8_t)value; - value = value >> 8; - } - - return buf; -} - static int decode_pdp_info(uint8_t *data, size_t data_len, struct gprs_gsup_pdp_info *pdp_info) { diff --git a/openbsc/src/libcommon/Makefile.am b/openbsc/src/libcommon/Makefile.am index 75f40ee..84c7544 100644 --- a/openbsc/src/libcommon/Makefile.am +++ b/openbsc/src/libcommon/Makefile.am @@ -6,4 +6,4 @@ noinst_LIBRARIES = libcommon.a libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c \ gsm_data_shared.c socket.c talloc_ctx.c \ - gsm_subscriber_base.c + gsm_subscriber_base.c utils.c diff --git a/openbsc/src/libcommon/utils.c b/openbsc/src/libcommon/utils.c new file mode 100644 index 0000000..615eba9 --- /dev/null +++ b/openbsc/src/libcommon/utils.c @@ -0,0 +1,64 @@ +/* OpenBSC kitchen sink */ + +/* (C) 2015 by sysmocom s.m.f.c + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include + +/* Wishful thinking to generate a constant time compare */ +int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count) +{ + int x = 0, i; + + for (i = 0; i < count; ++i) + x |= exp[i] ^ rel[i]; + + /* if x is zero, all data was identical */ + return x? 1 : 0; +} + + +uint64_t decode_big_endian(const uint8_t *data, size_t data_len) +{ + uint64_t value = 0; + + while (data_len > 0) { + value = (value << 8) + *data; + data += 1; + data_len -= 1; + } + + return value; +} + +uint8_t *encode_big_endian(uint64_t value, size_t data_len) +{ + static uint8_t buf[sizeof(uint64_t)]; + int idx; + + OSMO_ASSERT(data_len <= ARRAY_SIZE(buf)); + + for (idx = data_len - 1; idx >= 0; idx--) { + buf[idx] = (uint8_t)value; + value = value >> 8; + } + + return buf; +} + diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 56c6286..18343dd 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -987,17 +988,6 @@ static void ipaccess_close_bsc(void *data) bsc_close_connection(conn); } -/* Wishful thinking to generate a constant time compare */ -static int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count) -{ - int x = 0, i; - - for (i = 0; i < count; ++i) - x |= exp[i] ^ rel[i]; - - return x != 0; -} - static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen) { struct osmo_auth_vector vec; diff --git a/openbsc/tests/gprs/Makefile.am b/openbsc/tests/gprs/Makefile.am index 633c362..b57977b 100644 --- a/openbsc/tests/gprs/Makefile.am +++ b/openbsc/tests/gprs/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = gprs_test.ok noinst_PROGRAMS = gprs_test gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c \ - $(top_srcdir)/src/gprs/gprs_gsup_messages.c + $(top_srcdir)/src/gprs/gprs_gsup_messages.c \ + $(top_srcdir)/src/libcommon/utils.c gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:56 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:56 +0200 Subject: [PATCH 7/8] gsup/oap: add OAP to GSUP client. In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-8-git-send-email-nhofmeyr@sysmocom.de> Trigger an OAP registration upon IPA connect. Feed incoming OAP messages to oap_handle() and send replies returned by it. Add oap_config to sgsn_config (todo: vty). Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_gsup_client.h | 7 +++- openbsc/include/openbsc/sgsn.h | 3 ++ openbsc/src/gprs/gprs_gsup_client.c | 58 ++++++++++++++++++++++++++---- openbsc/src/gprs/gprs_subscriber.c | 3 +- openbsc/tests/sgsn/Makefile.am | 2 ++ 5 files changed, 65 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_client.h b/openbsc/include/openbsc/gprs_gsup_client.h index 9537db4..ccfa388 100644 --- a/openbsc/include/openbsc/gprs_gsup_client.h +++ b/openbsc/include/openbsc/gprs_gsup_client.h @@ -23,6 +23,8 @@ #include +#include + #define GPRS_GSUP_RECONNECT_INTERVAL 10 #define GPRS_GSUP_PING_INTERVAL 20 @@ -38,6 +40,8 @@ struct gprs_gsup_client { gprs_gsup_read_cb_t read_cb; void *data; + struct oap_state oap_state; + struct osmo_timer_list ping_timer; struct osmo_timer_list connect_timer; int is_connected; @@ -46,7 +50,8 @@ struct gprs_gsup_client { struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb); + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config); void gprs_gsup_client_destroy(struct gprs_gsup_client *gsupc); int gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg); diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h index d4f9913..2b1b97c 100644 --- a/openbsc/include/openbsc/sgsn.h +++ b/openbsc/include/openbsc/sgsn.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -61,6 +62,8 @@ struct sgsn_config { } timers; int dynamic_lookup; + + struct oap_config oap; }; struct sgsn_instance { diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c index 1f9e34c..a332fa7 100644 --- a/openbsc/src/gprs/gprs_gsup_client.c +++ b/openbsc/src/gprs/gprs_gsup_client.c @@ -108,6 +108,20 @@ static void gsup_client_send(struct gprs_gsup_client *gsupc, int proto_ext, stru /* msg_tx is now queued and will be freed. */ } +static void gsup_client_oap_register(struct gprs_gsup_client *gsupc) +{ + struct msgb *msg_tx; + int rc; + rc = oap_register(&gsupc->oap_state, &msg_tx); + + if ((rc < 0) || (!msg_tx)) { + LOGP(DGPRS, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n"); + return; + } + + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); +} + static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) { struct gprs_gsup_client *gsupc = link->data; @@ -120,6 +134,9 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) if (up) { start_test_procedure(gsupc); + if (gsupc->oap_state.state == OAP_INITIALIZED) + gsup_client_oap_register(gsupc); + osmo_timer_del(&gsupc->connect_timer); } else { osmo_timer_del(&gsupc->ping_timer); @@ -129,6 +146,22 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) } } +static int gsup_client_oap_handle(struct gprs_gsup_client *gsupc, struct msgb *msg_rx) +{ + int rc; + struct msgb *msg_tx; + + rc = oap_handle(&gsupc->oap_state, msg_rx, &msg_tx); + msgb_free(msg_rx); + if (rc < 0) + return rc; + + if (msg_tx) + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); + + return 0; +} + static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) { struct ipaccess_head *hh = (struct ipaccess_head *) msg->data; @@ -168,16 +201,24 @@ static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) if (hh->proto != IPAC_PROTO_OSMO) goto invalid; - if (!he || msgb_l2len(msg) < sizeof(*he) || - he->proto != IPAC_PROTO_EXT_GSUP) + if (!he || msgb_l2len(msg) < sizeof(*he)) goto invalid; msg->l2h = &he->data[0]; - OSMO_ASSERT(gsupc->read_cb != NULL); - gsupc->read_cb(gsupc, msg); + if (he->proto == IPAC_PROTO_EXT_GSUP) { + OSMO_ASSERT(gsupc->read_cb != NULL); + gsupc->read_cb(gsupc, msg); + /* expecting read_cb() to free msg */ + } + else + if (he->proto == IPAC_PROTO_EXT_OAP) { + return gsup_client_oap_handle(gsupc, msg); + /* gsup_client_oap_handle frees msg */ + } + else + goto invalid; - /* Not freeing msg here, because that must be done by the read_cb. */ return 0; invalid: @@ -222,7 +263,8 @@ static void start_test_procedure(struct gprs_gsup_client *gsupc) struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb) + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config) { struct gprs_gsup_client *gsupc; int rc; @@ -230,6 +272,10 @@ struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, gsupc = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client); OSMO_ASSERT(gsupc); + rc = oap_init(oap_config, &gsupc->oap_state); + if (rc != 0) + goto failed; + gsupc->link = ipa_client_conn_create(gsupc, /* no e1inp */ NULL, 0, diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 8231e8c..3467293 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -63,7 +63,8 @@ int gprs_subscr_init(struct sgsn_instance *sgi) sgi->gsup_client = gprs_gsup_client_create( addr_str, sgi->cfg.gsup_server_port, - &gsup_read_cb); + &gsup_read_cb, + &sgi->cfg.oap); if (!sgi->gsup_client) return -1; diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index 3c202dd..24504c2 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -28,6 +28,8 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ + $(top_builddir)/src/gprs/oap.o \ + $(top_builddir)/src/gprs/oap_messages.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOABIS_LIBS) \ $(LIBOSMOCORE_LIBS) \ -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 1 13:23:53 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 1 Oct 2015 15:23:53 +0200 Subject: [PATCH 4/8] oap: implement initial OAP API. In-Reply-To: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> Add oap.[hc] and oap_messages.[hc]. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/Makefile.am | 3 +- openbsc/include/openbsc/oap.h | 77 ++++++++++ openbsc/include/openbsc/oap_messages.h | 70 +++++++++ openbsc/src/gprs/Makefile.am | 3 +- openbsc/src/gprs/oap.c | 254 +++++++++++++++++++++++++++++++++ openbsc/src/gprs/oap_messages.c | 178 +++++++++++++++++++++++ 6 files changed, 583 insertions(+), 2 deletions(-) create mode 100644 openbsc/include/openbsc/oap.h create mode 100644 openbsc/include/openbsc/oap_messages.h create mode 100644 openbsc/src/gprs/oap.c create mode 100644 openbsc/src/gprs/oap_messages.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 828f5bd..8a074c2 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -16,7 +16,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ - gprs_gsup_client.h bsc_msg_filter.h + gprs_gsup_client.h bsc_msg_filter.h \ + oap.h oap_messages.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/oap.h b/openbsc/include/openbsc/oap.h new file mode 100644 index 0000000..d106118 --- /dev/null +++ b/openbsc/include/openbsc/oap.h @@ -0,0 +1,77 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +struct msgb; +struct oap_message; + +/* This is the config part for vty. It is essentially copied in oap_state, + * where values are copied over once the config is considered valid. */ +struct oap_config { + uint16_t client_id; + int secret_k_present; + uint8_t secret_k[16]; + int secret_opc_present; + uint8_t secret_opc[16]; +}; + +/* The runtime state of the OAP client. client_id and the secrets are in fact + * duplicated from oap_config, so that a separate validation of the config data + * is possible, and so that only a struct oap_state* is passed around. */ +struct oap_state { + enum { + OAP_UNINITIALIZED = 0, // just allocated. + OAP_DISABLED, // disabled by config. + OAP_INITIALIZED, // shared_secret valid. + OAP_REQUESTED_CHALLENGE, + OAP_SENT_CHALLENGE_RESULT, + OAP_REGISTERED + } state; + uint16_t client_id; + uint8_t secret_k[16]; + uint8_t secret_opc[16]; + int registration_failures; +}; + +/* From config, initialize state. Return 0 on success. */ +int oap_init(struct oap_config *config, struct oap_state *state); + +/* Construct an OAP registration message and return in *msg_tx. Use + * state->client_id and update state->state. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_register(struct oap_state *state, struct msgb **msg_tx); + +/* Decode and act on a received OAP message msg_rx. Update state->state. If a + * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP + * server (and freed) by the caller. The received msg_rx is not freed. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb **msg_tx); + +/* Allocate a msgb and in it, return the encoded oap_msg. Return NULL on + * error. (Like oap_encode(), but also allocates a msgb.) */ +struct msgb *oap_encoded(const struct oap_message *oap_msg); + diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h new file mode 100644 index 0000000..a7a254c --- /dev/null +++ b/openbsc/include/openbsc/oap_messages.h @@ -0,0 +1,70 @@ +/* Osmocom Authentication Protocol message encoder/decoder */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include +#include +#include + +/* Some numbers are out of sequence because (so far) they match gprs_gsup_iei. + */ +enum oap_iei { + OAP_CAUSE_IE = 0x02, + OAP_RAND_IE = 0x20, + OAP_AUTN_IE = 0x23, + OAP_XRES_IE = 0x24, + OAP_AUTS_IE = 0x25, + OAP_CLIENT_ID_IE = 0x30, +}; + +enum oap_message_type { + OAP_MSGT_REGISTER_REQUEST = 0b00000100, + OAP_MSGT_REGISTER_ERROR = 0b00000101, + OAP_MSGT_REGISTER_RESULT = 0b00000110, + + OAP_MSGT_CHALLENGE_REQUEST = 0b00001000, + OAP_MSGT_CHALLENGE_ERROR = 0b00001001, + OAP_MSGT_CHALLENGE_RESULT = 0b00001010, + + OAP_MSGT_SYNC_REQUEST = 0b00001100, + OAP_MSGT_SYNC_ERROR = 0b00001101, + OAP_MSGT_SYNC_RESULT = 0b00001110, +}; + +struct oap_message { + enum oap_message_type message_type; + enum gsm48_gmm_cause cause; + uint16_t client_id; + int rand_present; + uint8_t rand[16]; + int autn_present; + uint8_t autn[16]; + int xres_present; + uint8_t xres[8]; + int auts_present; + uint8_t auts[16]; +}; + +int oap_decode(const uint8_t *data, size_t data_len, + struct oap_message *oap_msg); +void oap_encode(struct msgb *msg, const struct oap_message *oap_msg); + diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f46a402..0952d41 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -27,7 +27,8 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ gprs_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ - gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c + gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c \ + oap.c oap_messages.c osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) -lrt diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c new file mode 100644 index 0000000..2c17d04 --- /dev/null +++ b/openbsc/src/gprs/oap.c @@ -0,0 +1,254 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include +#include + +int oap_init(struct oap_config *config, struct oap_state *state) +{ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + if (config->client_id == 0) + goto disable; + + if (config->secret_k_present == 0) { + LOGP(DGPRS, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n"); + goto disable; + } + + if (config->secret_opc_present == 0) { + LOGP(DGPRS, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n"); + goto disable; + } + + state->client_id = config->client_id; + memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); + memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); + state->state = OAP_INITIALIZED; + return 0; + +disable: + state->state = OAP_DISABLED; + return 0; +} + +/* From the given state and received RAND and AUTN octets, validate the + * server's authenticity and formulate the matching milenage reply octets in + * *tx_xres. The state is not modified. + * On success, and if tx_res is not NULL, exactly 8 octets will be written to + * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8 + * octets. The caller will want to send XRES back to the server in a challenge + * response message and update the state. + * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail + * the authentication check; -3 for any other errors. */ +static int oap_evaluate_challenge(const struct oap_state *state, + const uint8_t *rx_random, + const uint8_t *rx_autn, + uint8_t *tx_xres) +{ + switch(state->state) { + case OAP_UNINITIALIZED: + case OAP_DISABLED: + return -1; + default: + break; + } + + struct osmo_auth_vector vec; + + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_UMTS, + .algo = OSMO_AUTH_ALG_MILENAGE, + }; + + OSMO_ASSERT(sizeof(auth.u.umts.k) == sizeof(state->secret_k)); + OSMO_ASSERT(sizeof(auth.u.umts.opc) == sizeof(state->secret_opc)); + + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); + memset(auth.u.umts.amf, 0, 2); + auth.u.umts.sqn = 42; /* TODO */ + + memset(&vec, 0, sizeof(vec)); + osmo_auth_gen_vec(&vec, &auth, rx_random); + + if (vec.res_len != 8) { + LOGP(DGPRS, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n", + vec.res_len); + return -3; + } + + if (constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { + LOGP(DGPRS, LOGL_ERROR, "OAP: AUTN mismatch!\n"); + LOGP(DGPRS, LOGL_INFO, "OAP: AUTN from server: %s\n", + osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); + LOGP(DGPRS, LOGL_INFO, "OAP: AUTN expected: %s\n", + osmo_hexdump_nospc(vec.autn, sizeof(vec.autn))); + return -2; + } + + if (tx_xres != NULL) + memcpy(tx_xres, vec.res, 8); + return 0; +} + +struct msgb *oap_encoded(const struct oap_message *oap_msg) +{ + struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); + OSMO_ASSERT(msg); + oap_encode(msg, oap_msg); + return msg; +} + +/* Create a new msgb containing an OAP registration message. + * On error, return NULL. */ +static struct msgb* oap_msg_register(uint16_t client_id) +{ + if (client_id < 1) { + LOGP(DGPRS, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); + return NULL; + } + + struct oap_message oap_msg = {0}; + oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; + oap_msg.client_id = client_id; + return oap_encoded(&oap_msg); +} + +int oap_register(struct oap_state *state, struct msgb **msg_tx) +{ + *msg_tx = oap_msg_register(state->client_id); + if (!(*msg_tx)) + return -1; + + state->state = OAP_REQUESTED_CHALLENGE; + return 0; +} + +/* Create a new msgb containing an OAP challenge response message. + * xres must point at 8 octets to return as challenge response. + * On error, return NULL. */ +static struct msgb* oap_msg_challenge_response(uint8_t *xres) +{ + struct oap_message oap_reply = {0}; + + oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; + memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); + oap_reply.xres_present = 1; + return oap_encoded(&oap_reply); +} + +static int handle_challenge(struct oap_state *state, + struct oap_message *oap_rx, + struct msgb **msg_tx) +{ + int rc; + if (!(oap_rx->rand_present && oap_rx->autn_present)) { + LOGP(DGPRS, LOGL_ERROR, + "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", + oap_rx->rand_present, oap_rx->autn_present); + rc = -2; + goto failure; + } + + uint8_t xres[8]; + rc = oap_evaluate_challenge(state, + oap_rx->rand, + oap_rx->autn, + xres); + if (rc < 0) + goto failure; + + *msg_tx = oap_msg_challenge_response(xres); + if ((*msg_tx) == NULL) { + rc = -1; + goto failure; + } + + state->state = OAP_SENT_CHALLENGE_RESULT; + return 0; + +failure: + OSMO_ASSERT(rc < 0); + state->state = OAP_INITIALIZED; + return rc; +} + +int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb **msg_tx) +{ + *msg_tx = NULL; + + uint8_t *data = msgb_l2(msg_rx); + size_t data_len = msgb_l2len(msg_rx); + int rc = 0; + + struct oap_message oap_msg = {0}; + + OSMO_ASSERT(data); + + rc = oap_decode(data, data_len, &oap_msg); + if (rc < 0) { + LOGP(DGPRS, LOGL_ERROR, + "Decoding OAP message failed with error '%s' (%d)\n", + get_value_string(gsm48_gmm_cause_names, -rc), -rc); + return -10; + } + + switch (oap_msg.message_type) { + case OAP_MSGT_CHALLENGE_REQUEST: + return handle_challenge(state, &oap_msg, msg_tx); + + case OAP_MSGT_REGISTER_RESULT: + // successfully registered! + state->state = OAP_REGISTERED; + break; + + case OAP_MSGT_REGISTER_ERROR: + LOGP(DGPRS, LOGL_ERROR, + "OAP registration failed\n"); + state->state = OAP_INITIALIZED; + if (state->registration_failures < 3) { + state->registration_failures ++; + return oap_register(state, msg_tx); + } + return -11; + + case OAP_MSGT_REGISTER_REQUEST: + case OAP_MSGT_CHALLENGE_RESULT: + LOGP(DGPRS, LOGL_ERROR, + "Received invalid OAP message type for OAP client side: %d\n", + (int)oap_msg.message_type); + return -12; + + default: + LOGP(DGPRS, LOGL_ERROR, + "Unknown OAP message type: %d\n", + (int)oap_msg.message_type); + return -13; + } + + return 0; +} diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c new file mode 100644 index 0000000..eb52053 --- /dev/null +++ b/openbsc/src/gprs/oap_messages.c @@ -0,0 +1,178 @@ +/* Osmocom Authentication Protocol message encoder/decoder */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include + +#include +#include + +#include + + +int oap_decode(const uint8_t *const_data, size_t data_len, + struct oap_message *oap_msg) +{ + int rc; + uint8_t tag; + /* the shift/match functions expect non-const pointers, but we'll + * either copy the data or cast pointers back to const before returning + * them + */ + uint8_t *data = (uint8_t *)const_data; + uint8_t *value; + size_t value_len; + + memset(oap_msg, 0, sizeof(*oap_msg)); + + /* message type */ + rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); + if (rc < 0) + return -GMM_CAUSE_INV_MAND_INFO; + oap_msg->message_type = decode_big_endian(value, 1); + + /* specific parts */ + while (data_len > 0) { + enum oap_iei iei; + + rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + if (rc < 0) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + iei = tag; + + switch (iei) { + case OAP_CLIENT_ID_IE: + if (value_len != 2) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type client ID (%d) should be 2 octets, but has %d\n", + (int)iei, (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + + oap_msg->client_id = decode_big_endian(value, value_len); + + if (oap_msg->client_id == 0) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type client ID (%d): client ID must be nonzero.\n", + (int)iei); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + break; + + case OAP_AUTN_IE: + if (value_len != sizeof(oap_msg->autn)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type AUTN (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->autn), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->autn, value, value_len); + oap_msg->autn_present = value_len; + break; + + case OAP_RAND_IE: + if (value_len != sizeof(oap_msg->rand)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type RAND (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->rand), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->rand, value, value_len); + oap_msg->rand_present = value_len; + break; + + case OAP_XRES_IE: + if (value_len != sizeof(oap_msg->xres)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type XRES (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->xres), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->xres, value, value_len); + oap_msg->xres_present = value_len; + break; + + case OAP_AUTS_IE: + if (value_len != sizeof(oap_msg->auts)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type AUTS (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->auts), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->auts, value, value_len); + oap_msg->auts_present = value_len; + break; + + case OAP_CAUSE_IE: + if (value_len > 1) { + LOGP(DGPRS, LOGL_ERROR, + "OAP cause may not exceed one octet, is %d", (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + oap_msg->cause = *value; + break; + + default: + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type %d unknown\n", iei); + continue; + } + } + + return 0; +} + +void oap_encode(struct msgb *msg, const struct oap_message *oap_msg) +{ + uint8_t u8; + + /* generic part */ + OSMO_ASSERT(oap_msg->message_type); + msgb_v_put(msg, (uint8_t)oap_msg->message_type); + + /* specific parts */ + if ((u8 = oap_msg->cause)) + msgb_tlv_put(msg, OAP_CAUSE_IE, sizeof(u8), &u8); + + if (oap_msg->client_id > 0) + msgb_tlv_put(msg, OAP_CLIENT_ID_IE, sizeof(oap_msg->client_id), + encode_big_endian(oap_msg->client_id, sizeof(oap_msg->client_id))); + + if (oap_msg->rand_present) + msgb_tlv_put(msg, OAP_RAND_IE, sizeof(oap_msg->rand), oap_msg->rand); + + if (oap_msg->autn_present) + msgb_tlv_put(msg, OAP_AUTN_IE, sizeof(oap_msg->autn), oap_msg->autn); + + if (oap_msg->auts_present) + msgb_tlv_put(msg, OAP_AUTS_IE, sizeof(oap_msg->auts), oap_msg->auts); + + if (oap_msg->xres_present) + msgb_tlv_put(msg, OAP_XRES_IE, sizeof(oap_msg->xres), oap_msg->xres); + + msg->l2h = msg->data; +} + -- 2.1.4 From risky at mail.ru Thu Oct 1 18:20:15 2015 From: risky at mail.ru (Sergey V. Efimov) Date: Thu, 1 Oct 2015 21:20:15 +0300 Subject: Help needed with BS-11 Message-ID: Hello, One of our BS-11 stations began to behave strangely. I see the following messages during boot-up: PHASE: 1 Load SMU Intended Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: No Load MBCCU1: No Load Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: No Load Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: Load BTSCAC Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: No Load Abis-link: Down It looks like BS tries to load firmware on MBCCU1 and then gives up. I tried to delete and re-create trx1 objects using bs11_config, no result. Tried to reflash BS11, but got software load NACK, and when using ?force option the software download process finishes but the boot-up message is the same as above. Does it mean that TRX1 is failed and cannot be used no more? Best Regards, Sergey. -------------- next part -------------- An HTML attachment was scrubbed... URL: From laforge at gnumonks.org Fri Oct 2 12:35:43 2015 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 2 Oct 2015 14:35:43 +0200 Subject: Help needed with BS11 In-Reply-To: References: Message-ID: <20151002123543.GC31027@nataraja> Hi Sergey, I honstely don't have any idea what is going on. The last time I looked at the boot / initializaiton process of the BS-11 is many years ago. So unless somebdoy else on this list has any good ideas, I would presume some kind of hardware damage. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Oct 3 18:00:57 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 3 Oct 2015 20:00:57 +0200 Subject: Oct 07, 8pm / Osmocom Berlin User Group meeting Message-ID: <20151003180057.GH29331@nataraja> Hi all! This is the announcement for the re-incarnated Osmocom Berlin meeting: Oct 7, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin Harald will be presenting about the Iuh protocol stack of UMTS small cells / femtocells and his work towards implementing it as part of Osmocom. Agenda: 20:00h Welcome 20:15h Presentation about Iuh / osmo-iuh 21:00h Informal meeting / chatting The meeting is open to anyone interested in mobile communications. You do not have to be involved with the Osmocom projects in order to attend. Anyone interested in mobile communications protocols is welcome. If you are interested to show up, feel free to do so. There is no registration required. The meeting is free as in "free beer", despite no actual free beer being around. Regards, Harald -- - Harald Welte ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Oct 3 20:39:05 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 3 Oct 2015 22:39:05 +0200 Subject: Oct 15, 8pm / OSMUG: "Running OpenAirInterface" Message-ID: <20151003203905.GM29331@nataraja> Hi all! This is an announcement for an "irregular" Berlin Osmocom User Group event. David Rupprecht of Ruhr-Uni Bochum has offered to give us a presentation sharing his experience in Running OpenAirInterface. OpenAirInterface (http://openairinterface.eurecom.fr/) is a project of the Eurecom research institute in Sofia Antipoils / France. For many years they have been working towards an open source SDR LTE implementation. The presentation will be held on Oct 15, 8pm @ IN-Berlin, Lehrter Str. 53, 10557 Berlin (yes, this is _NOT_ CCC Berlin where regular OSMUG meetings are held!) The meeting is open to anyone interested in mobile communications. You do not have to be involved with the Osmocom projects in order to attend. Anyone interested in mobile communications protocols is welcome. If you are interested to show up, feel free to do so. The meeting is "free as in free beer", despite no actual free beer being around ;) More information about the venue can be found at http://www.in-berlin.de/space/ The official event announcement website is http://openbsc.osmocom.org/trac/blog/david-rub-openair-20151015 Regards, Harald -- - Harald Welte ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Sun Oct 4 09:22:49 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:49 +0200 Subject: [PATCH 1/6] osmux: Test cid allocation and de-allocation Message-ID: <1443950574-75194-1-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther * Test that one can get an id * That they are assigned predicatble right now * That returning them will make the number of used ones go down * That allocating more will fail --- openbsc/include/openbsc/osmux.h | 1 + openbsc/src/libmgcp/mgcp_osmux.c | 14 ++++++++++++++ openbsc/tests/mgcp/mgcp_test.c | 26 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/openbsc/include/openbsc/osmux.h b/openbsc/include/openbsc/osmux.h index 8c01fd0..0e727d5 100644 --- a/openbsc/include/openbsc/osmux.h +++ b/openbsc/include/openbsc/osmux.h @@ -22,6 +22,7 @@ int osmux_send_dummy(struct mgcp_endpoint *endp); int osmux_get_cid(void); void osmux_put_cid(uint8_t osmux_cid); +int osmux_used_cid(void); enum osmux_state { OSMUX_STATE_DISABLED = 0, diff --git a/openbsc/src/libmgcp/mgcp_osmux.c b/openbsc/src/libmgcp/mgcp_osmux.c index 90b7368..b0ef69f 100644 --- a/openbsc/src/libmgcp/mgcp_osmux.c +++ b/openbsc/src/libmgcp/mgcp_osmux.c @@ -532,6 +532,20 @@ int osmux_send_dummy(struct mgcp_endpoint *endp) /* bsc-nat allocates/releases the Osmux circuit ID */ static uint8_t osmux_cid_bitmap[16]; +int osmux_used_cid(void) +{ + int i, j, used = 0; + + for (i = 0; i < sizeof(osmux_cid_bitmap) / 8; i++) { + for (j = 0; j < 8; j++) { + if (osmux_cid_bitmap[i] & (1 << j)) + used += 1; + } + } + + return used; +} + int osmux_get_cid(void) { int i, j; diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index b2cb938..7b5de31 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -1175,6 +1175,31 @@ static void test_no_name(void) talloc_free(cfg); } +static void test_osmux_cid(void) +{ + int id, i; + + OSMO_ASSERT(osmux_used_cid() == 0); + id = osmux_get_cid(); + OSMO_ASSERT(id == 0); + OSMO_ASSERT(osmux_used_cid() == 1); + osmux_put_cid(id); + OSMO_ASSERT(osmux_used_cid() == 0); + + for (i = 0; i < 16; ++i) { + id = osmux_get_cid(); + OSMO_ASSERT(id == i); + OSMO_ASSERT(osmux_used_cid() == i + 1); + } + + id = osmux_get_cid(); + OSMO_ASSERT(id == -1); + + for (i = 0; i < 256; ++i) + osmux_put_cid(i); + OSMO_ASSERT(osmux_used_cid() == 0); +} + int main(int argc, char **argv) { osmo_init_logging(&log_info); @@ -1193,6 +1218,7 @@ int main(int argc, char **argv) test_multilple_codec(); test_no_cycle(); test_no_name(); + test_osmux_cid(); printf("Done\n"); return EXIT_SUCCESS; -- 2.6.0 From holger at freyther.de Sun Oct 4 09:22:50 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:50 +0200 Subject: [PATCH 2/6] osmux: Do not divide the number of bytes by eight. In-Reply-To: <1443950574-75194-1-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> Message-ID: <1443950574-75194-2-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther sizeof(uint8_t) == 1 and there is no need to create an array with 16 bytes and then only use the first two of them. This means the CID range is from 0 to 127 and we should be able to extend this to 256 by changing the array size to 32. Update the testcase now that we can have more than 16 calls with Osmux. --- openbsc/src/libmgcp/mgcp_osmux.c | 4 ++-- openbsc/tests/mgcp/mgcp_test.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openbsc/src/libmgcp/mgcp_osmux.c b/openbsc/src/libmgcp/mgcp_osmux.c index b0ef69f..30a81cb 100644 --- a/openbsc/src/libmgcp/mgcp_osmux.c +++ b/openbsc/src/libmgcp/mgcp_osmux.c @@ -536,7 +536,7 @@ int osmux_used_cid(void) { int i, j, used = 0; - for (i = 0; i < sizeof(osmux_cid_bitmap) / 8; i++) { + for (i = 0; i < sizeof(osmux_cid_bitmap); i++) { for (j = 0; j < 8; j++) { if (osmux_cid_bitmap[i] & (1 << j)) used += 1; @@ -550,7 +550,7 @@ int osmux_get_cid(void) { int i, j; - for (i = 0; i < sizeof(osmux_cid_bitmap) / 8; i++) { + for (i = 0; i < sizeof(osmux_cid_bitmap); i++) { for (j = 0; j < 8; j++) { if (osmux_cid_bitmap[i] & (1 << j)) continue; diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c index 7b5de31..ec86c55 100644 --- a/openbsc/tests/mgcp/mgcp_test.c +++ b/openbsc/tests/mgcp/mgcp_test.c @@ -1186,7 +1186,7 @@ static void test_osmux_cid(void) osmux_put_cid(id); OSMO_ASSERT(osmux_used_cid() == 0); - for (i = 0; i < 16; ++i) { + for (i = 0; i < 128; ++i) { id = osmux_get_cid(); OSMO_ASSERT(id == i); OSMO_ASSERT(osmux_used_cid() == i + 1); -- 2.6.0 From holger at freyther.de Sun Oct 4 09:22:51 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:51 +0200 Subject: [PATCH 3/6] osmux: Add introspection for osmux. In-Reply-To: <1443950574-75194-1-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> Message-ID: <1443950574-75194-3-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther * Print number of used CIDs for the system * Hopefully this is just the beginning --- openbsc/src/libmgcp/mgcp_vty.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index fc2f818..2b76436 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -226,6 +226,9 @@ DEFUN(show_mcgp, show_mgcp_cmd, llist_for_each_entry(trunk, &g_cfg->trunks, entry) dump_trunk(vty, trunk, show_stats); + if (g_cfg->osmux) + vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE); + return CMD_SUCCESS; } -- 2.6.0 From holger at freyther.de Sun Oct 4 09:22:52 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:52 +0200 Subject: [PATCH 4/6] osmux: Allow to enforce using Osmux for the client In-Reply-To: <1443950574-75194-1-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> Message-ID: <1443950574-75194-4-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Some systems only want to use Osmux. In case only Osmux should be used fail if it has not be offered/acked. Client: Verified On, Off and Only with X-Osmux: 3 and without this field. <000b> mgcp_protocol.c:823 Osmux only and no osmux offered on 0x14 <000b> mgcp_protocol.c:884 Resource error on 0x14 NAT: Not tested and implemented Fixes: OW#1492 --- openbsc/include/openbsc/osmux.h | 6 +++++ openbsc/src/libmgcp/mgcp_protocol.c | 4 ++++ openbsc/src/libmgcp/mgcp_vty.c | 45 +++++++++++++++++++++++++------------ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/openbsc/include/openbsc/osmux.h b/openbsc/include/openbsc/osmux.h index 0e727d5..88d045b 100644 --- a/openbsc/include/openbsc/osmux.h +++ b/openbsc/include/openbsc/osmux.h @@ -30,4 +30,10 @@ enum osmux_state { OSMUX_STATE_ENABLED, }; +enum osmux_usage { + OSMUX_USAGE_OFF = 0, + OSMUX_USAGE_ON = 1, + OSMUX_USAGE_ONLY = 2, +}; + #endif diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index ab98be1..e2bda3a 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -818,6 +818,10 @@ mgcp_header_done: if (osmux_cid >= 0) { endp->osmux.cid = osmux_cid; endp->osmux.state = OSMUX_STATE_ACTIVATING; + } else if(endp->cfg->osmux == OSMUX_USAGE_ONLY) { + LOGP(DMGCP, LOGL_ERROR, + "Osmux only and no osmux offered on 0x%x\n", ENDPOINT_NUMBER(endp)); + goto error2; } endp->allocated = 1; diff --git a/openbsc/src/libmgcp/mgcp_vty.c b/openbsc/src/libmgcp/mgcp_vty.c index 2b76436..c478b0a 100644 --- a/openbsc/src/libmgcp/mgcp_vty.c +++ b/openbsc/src/libmgcp/mgcp_vty.c @@ -139,8 +139,19 @@ static int config_write_mgcp(struct vty *vty) if (g_cfg->bts_force_ptime > 0) vty_out(vty, " rtp force-ptime %d%s", g_cfg->bts_force_ptime, VTY_NEWLINE); vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE); - vty_out(vty, " osmux %s%s", - g_cfg->osmux == 1 ? "on" : "off", VTY_NEWLINE); + + switch (g_cfg->osmux) { + case OSMUX_USAGE_ON: + vty_out(vty, " osmux on%s", VTY_NEWLINE); + break; + case OSMUX_USAGE_ONLY: + vty_out(vty, " osmux only%s", VTY_NEWLINE); + break; + case OSMUX_USAGE_OFF: + default: + vty_out(vty, " osmux off%s", VTY_NEWLINE); + break; + } if (g_cfg->osmux) { vty_out(vty, " osmux batch-factor %d%s", g_cfg->osmux_batch, VTY_NEWLINE); @@ -1249,18 +1260,24 @@ DEFUN(reset_all_endp, reset_all_endp_cmd, #define OSMUX_STR "RTP multiplexing\n" DEFUN(cfg_mgcp_osmux, cfg_mgcp_osmux_cmd, - "osmux (on|off)", - OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n") -{ - if (strcmp(argv[0], "on") == 0) { - g_cfg->osmux = 1; - if (g_cfg->trunk.audio_loop) { - vty_out(vty, "Cannot use `loop' with `osmux'.%s", - VTY_NEWLINE); - return CMD_WARNING; - } - } else if (strcmp(argv[0], "off") == 0) - g_cfg->osmux = 0; + "osmux (on|off|only)", + OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n") +{ + if (strcmp(argv[0], "off") == 0) { + g_cfg->osmux = OSMUX_USAGE_OFF; + return CMD_SUCCESS; + } + + if (strcmp(argv[0], "on") == 0) + g_cfg->osmux = OSMUX_USAGE_ON; + else if (strcmp(argv[0], "only") == 0) + g_cfg->osmux = OSMUX_USAGE_ONLY; + + if (g_cfg->trunk.audio_loop) { + vty_out(vty, "Cannot use `loop' with `osmux'.%s", + VTY_NEWLINE); + return CMD_WARNING; + } return CMD_SUCCESS; } -- 2.6.0 From holger at freyther.de Sun Oct 4 09:22:53 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:53 +0200 Subject: [PATCH 5/6] osmux: Enforce Osmux only global and per BSC configuration In-Reply-To: <1443950574-75194-1-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> Message-ID: <1443950574-75194-5-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther Extend the osmux only setting from the MGCP MGW to the NAT. This is applied when an endpoint is allocated and/or when the allocation is confirmed by the remote system. Not tested. The impact should only be when the new option is being used. Fixes: OW#1492 --- openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c | 32 ++++++++++++++++++++++++++++--- openbsc/src/osmo-bsc_nat/bsc_nat_vty.c | 22 ++++++++++++++------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index f19cb4c..aad59d4 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -499,6 +499,15 @@ struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *nat, int endpoint) return NULL; } +static int nat_osmux_only(struct mgcp_config *mgcp_cfg, struct bsc_config *bsc_cfg) +{ + if (mgcp_cfg->osmux == OSMUX_USAGE_ONLY) + return 1; + if (bsc_cfg->osmux == OSMUX_USAGE_ONLY) + return 1; + return 0; +} + static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int state, const char *transaction_id) { struct bsc_nat *nat; @@ -544,9 +553,16 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int } /* Allocate a Osmux circuit ID */ - if (state == MGCP_ENDP_CRCX && - nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) - osmux_cid = osmux_get_cid(); + if (state == MGCP_ENDP_CRCX) { + if (nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) { + osmux_cid = osmux_get_cid(); + if (osmux_cid < 0 && nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) { + LOGP(DMGCP, LOGL_ERROR, + "Rejecting usage of endpoint\n"); + return MGCP_POLICY_REJECT; + } + } + } /* we need to generate a new and patched message */ bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length, @@ -734,6 +750,16 @@ void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg) if (endp->osmux.state == OSMUX_STATE_ACTIVATING) bsc_mgcp_osmux_confirm(endp, (const char *) msg->l2h); + /* If we require osmux and it is not disabled.. fail */ + if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) && + endp->osmux.state == OSMUX_STATE_DISABLED) { + LOGP(DMGCP, LOGL_ERROR, + "Failed to activate osmux endpoint 0x%x\n", + ENDPOINT_NUMBER(endp)); + free_chan_downstream(endp, bsc_endp, bsc); + return; + } + /* free some stuff */ talloc_free(bsc_endp->transaction_id); bsc_endp->transaction_id = NULL; diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c index 981168c..cd8293c 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c @@ -162,8 +162,14 @@ static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc) if (bsc->paging_group != -1) vty_out(vty, " paging group %d%s", bsc->paging_group, VTY_NEWLINE); vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE); - if (bsc->osmux) + switch (bsc->osmux) { + case OSMUX_USAGE_ON: vty_out(vty, " osmux on%s", VTY_NEWLINE); + break; + case OSMUX_USAGE_ONLY: + vty_out(vty, " osmux only%s", VTY_NEWLINE); + break; + } } static int config_write_bsc(struct vty *vty) @@ -1124,18 +1130,20 @@ DEFUN(show_ussd_connection, #define OSMUX_STR "RTP multiplexing\n" DEFUN(cfg_bsc_osmux, cfg_bsc_osmux_cmd, - "osmux (on|off)", - OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n") + "osmux (on|off|only)", + OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only OSMUX\n") { struct bsc_config *conf = vty->index; int old = conf->osmux; if (strcmp(argv[0], "on") == 0) - conf->osmux = 1; + conf->osmux = OSMUX_USAGE_ON; else if (strcmp(argv[0], "off") == 0) - conf->osmux = 0; + conf->osmux = OSMUX_USAGE_OFF; + else if (strcmp(argv[0], "only") == 0) + conf->osmux = OSMUX_USAGE_ONLY; - if (old == 0 && conf->osmux == 1 && !conf->nat->mgcp_cfg->osmux_init) { + if (old == 0 && conf->osmux > 0 && !conf->nat->mgcp_cfg->osmux_init) { LOGP(DMGCP, LOGL_NOTICE, "Setting up OSMUX socket\n"); if (osmux_init(OSMUX_ROLE_BSC_NAT, conf->nat->mgcp_cfg) < 0) { LOGP(DMGCP, LOGL_ERROR, "Cannot init OSMUX\n"); @@ -1143,7 +1151,7 @@ DEFUN(cfg_bsc_osmux, VTY_NEWLINE); return CMD_WARNING; } - } else if (old == 1 && conf->osmux == 0) { + } else if (old > 0 && conf->osmux == 0) { LOGP(DMGCP, LOGL_NOTICE, "Disabling OSMUX socket\n"); /* Don't stop the socket, we may already have ongoing voice * flows already using Osmux. This just switch indicates that -- 2.6.0 From holger at freyther.de Sun Oct 4 09:22:54 2015 From: holger at freyther.de (Holger Hans Peter Freyther) Date: Sun, 4 Oct 2015 11:22:54 +0200 Subject: [PATCH 6/6] osmux: Remember the allocated CID and make sure it is release In-Reply-To: <1443950574-75194-1-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> Message-ID: <1443950574-75194-6-git-send-email-holger@freyther.de> From: Holger Hans Peter Freyther There appears to be a leak of CIDs: <000b> mgcp_osmux.c:544 All Osmux circuits are in use! There are paths that a CID had been requested and never released of the NAT. Remember the allocated CID inside the endpoint so it can always be released. It is using a new variable as the behavior for the NAT and MGCP MGW is different. Fixes: OW#1493 --- openbsc/include/openbsc/mgcp_internal.h | 2 ++ openbsc/include/openbsc/osmux.h | 2 ++ openbsc/src/libmgcp/mgcp_osmux.c | 13 +++++++++++++ openbsc/src/libmgcp/mgcp_protocol.c | 4 ++++ openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c | 18 +++++++++--------- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h index 1f83659..8bb8f22 100644 --- a/openbsc/include/openbsc/mgcp_internal.h +++ b/openbsc/include/openbsc/mgcp_internal.h @@ -192,6 +192,8 @@ struct mgcp_endpoint { /* Osmux state: disabled, activating, active */ enum osmux_state state; /* Allocated Osmux circuit ID for this endpoint */ + uint8_t allocated_cid; + /* Used Osmux circuit ID for this endpoint */ uint8_t cid; /* handle to batch messages */ struct osmux_in_handle *in; diff --git a/openbsc/include/openbsc/osmux.h b/openbsc/include/openbsc/osmux.h index 88d045b..82b8fa3 100644 --- a/openbsc/include/openbsc/osmux.h +++ b/openbsc/include/openbsc/osmux.h @@ -14,6 +14,8 @@ int osmux_init(int role, struct mgcp_config *cfg); int osmux_enable_endpoint(struct mgcp_endpoint *endp, int role, struct in_addr *addr, uint16_t port); void osmux_disable_endpoint(struct mgcp_endpoint *endp); +void osmux_allocate_cid(struct mgcp_endpoint *endp); +void osmux_release_cid(struct mgcp_endpoint *endp); int osmux_xfrm_to_rtp(struct mgcp_endpoint *endp, int type, char *buf, int rc); int osmux_xfrm_to_osmux(int type, char *buf, int rc, struct mgcp_endpoint *endp); diff --git a/openbsc/src/libmgcp/mgcp_osmux.c b/openbsc/src/libmgcp/mgcp_osmux.c index 30a81cb..2d39b2c 100644 --- a/openbsc/src/libmgcp/mgcp_osmux.c +++ b/openbsc/src/libmgcp/mgcp_osmux.c @@ -492,6 +492,19 @@ void osmux_disable_endpoint(struct mgcp_endpoint *endp) osmux_handle_put(endp->osmux.in); } +void osmux_release_cid(struct mgcp_endpoint *endp) +{ + if (endp->osmux.allocated_cid >= 0) + osmux_put_cid(endp->osmux.allocated_cid); + endp->osmux.allocated_cid = -1; +} + +void osmux_allocate_cid(struct mgcp_endpoint *endp) +{ + osmux_release_cid(endp); + endp->osmux.allocated_cid = osmux_get_cid(); +} + /* We don't need to send the dummy load for osmux so often as another endpoint * may have already punched the hole in the firewall. This approach is simple * though. diff --git a/openbsc/src/libmgcp/mgcp_protocol.c b/openbsc/src/libmgcp/mgcp_protocol.c index e2bda3a..42ce8bb 100644 --- a/openbsc/src/libmgcp/mgcp_protocol.c +++ b/openbsc/src/libmgcp/mgcp_protocol.c @@ -1314,6 +1314,7 @@ int mgcp_endpoints_allocate(struct mgcp_trunk_config *tcfg) return -1; for (i = 0; i < tcfg->number_endpoints; ++i) { + tcfg->endpoints[i].osmux.allocated_cid = -1; tcfg->endpoints[i].ci = CI_UNUSED; tcfg->endpoints[i].cfg = tcfg->cfg; tcfg->endpoints[i].tcfg = tcfg; @@ -1354,6 +1355,9 @@ void mgcp_release_endp(struct mgcp_endpoint *endp) if (endp->osmux.state == OSMUX_STATE_ENABLED) osmux_disable_endpoint(endp); + /* release the circuit ID if it had been allocated */ + osmux_release_cid(endp); + memset(&endp->taps, 0, sizeof(endp->taps)); } diff --git a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c index aad59d4..bd8f7a4 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c +++ b/openbsc/src/osmo-bsc_nat/bsc_mgcp_utils.c @@ -515,7 +515,6 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int struct nat_sccp_connection *sccp; struct mgcp_endpoint *mgcp_endp; struct msgb *bsc_msg; - int osmux_cid = -1; nat = tcfg->cfg->data; bsc_endp = &nat->bsc_endpoints[endpoint]; @@ -555,8 +554,9 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* Allocate a Osmux circuit ID */ if (state == MGCP_ENDP_CRCX) { if (nat->mgcp_cfg->osmux && sccp->bsc->cfg->osmux) { - osmux_cid = osmux_get_cid(); - if (osmux_cid < 0 && nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) { + osmux_allocate_cid(mgcp_endp); + if (mgcp_endp->osmux.allocated_cid < 0 && + nat_osmux_only(nat->mgcp_cfg, sccp->bsc->cfg)) { LOGP(DMGCP, LOGL_ERROR, "Rejecting usage of endpoint\n"); return MGCP_POLICY_REJECT; @@ -567,7 +567,8 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* we need to generate a new and patched message */ bsc_msg = bsc_mgcp_rewrite((char *) nat->mgcp_msg, nat->mgcp_length, sccp->bsc_endp, mgcp_bts_src_addr(mgcp_endp), - mgcp_endp->bts_end.local_port, osmux_cid, + mgcp_endp->bts_end.local_port, + mgcp_endp->osmux.allocated_cid, &mgcp_endp->net_end.codec.payload_type, nat->sdp_ensure_amr_mode_set); if (!bsc_msg) { @@ -587,10 +588,10 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* Annotate the allocated Osmux CID until the bsc confirms that * it agrees to use Osmux for this voice flow. */ - if (osmux_cid >= 0 && + if (mgcp_endp->osmux.allocated_cid >= 0 && mgcp_endp->osmux.state != OSMUX_STATE_ENABLED) { mgcp_endp->osmux.state = OSMUX_STATE_ACTIVATING; - mgcp_endp->osmux.cid = osmux_cid; + mgcp_endp->osmux.cid = mgcp_endp->osmux.allocated_cid; } socklen_t len = sizeof(sock); @@ -612,7 +613,7 @@ static int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int /* libmgcp clears the MGCP endpoint for us */ if (mgcp_endp->osmux.state == OSMUX_STATE_ENABLED) - osmux_put_cid(mgcp_endp->osmux.cid); + osmux_release_cid(mgcp_endp); return MGCP_POLICY_CONT; } else { @@ -681,8 +682,7 @@ static void bsc_mgcp_osmux_confirm(struct mgcp_endpoint *endp, const char *str) osmux_cid); return; err: - osmux_put_cid(endp->osmux.cid); - endp->osmux.cid = -1; + osmux_release_cid(endp); endp->osmux.state = OSMUX_STATE_DISABLED; } -- 2.6.0 From nhofmeyr at sysmocom.de Mon Oct 5 10:37:58 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 5 Oct 2015 12:37:58 +0200 Subject: [PATCH 5/6] osmux: Enforce Osmux only global and per BSC configuration In-Reply-To: <1443950574-75194-5-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> <1443950574-75194-5-git-send-email-holger@freyther.de> Message-ID: <20151005103758.GA1232@dub5> On Sun, Oct 04, 2015 at 11:22:53AM +0200, Holger Hans Peter Freyther wrote: > + /* If we require osmux and it is not disabled.. fail */ > + if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) && > + endp->osmux.state == OSMUX_STATE_DISABLED) { [...] Comment: If we require osmux and it IS disabled, fail That's the only thing I spotted in your patch series. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From holger at freyther.de Mon Oct 5 14:22:23 2015 From: holger at freyther.de (Holger Freyther) Date: Mon, 5 Oct 2015 16:22:23 +0200 Subject: [PATCH 5/6] osmux: Enforce Osmux only global and per BSC configuration In-Reply-To: <20151005103758.GA1232@dub5> References: <1443950574-75194-1-git-send-email-holger@freyther.de> <1443950574-75194-5-git-send-email-holger@freyther.de> <20151005103758.GA1232@dub5> Message-ID: > On 05 Oct 2015, at 12:37, Neels Hofmeyr wrote: > > On Sun, Oct 04, 2015 at 11:22:53AM +0200, Holger Hans Peter Freyther wrote: >> + /* If we require osmux and it is not disabled.. fail */ >> + if (nat_osmux_only(bsc->nat->mgcp_cfg, bsc->cfg) && >> + endp->osmux.state == OSMUX_STATE_DISABLED) { > [...] > > Comment: If we require osmux and it IS disabled, fail > > That's the only thing I spotted in your patch series. thanks! From laforge at gnumonks.org Mon Oct 5 14:39:00 2015 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 5 Oct 2015 16:39:00 +0200 Subject: Oct 07, 8pm / Osmocom Berlin User Group meeting In-Reply-To: <20151004115941.GA95636@ngolde.de> References: <20151003180057.GH29331@nataraja> <20151004115941.GA95636@ngolde.de> Message-ID: <20151005143900.GG8672@nataraja> Hi Nico, [responding to the openbsc list, as it is more applicable than baseband-devel] On Sun, Oct 04, 2015 at 01:59:41PM +0200, Nico Golde wrote: > For those interested... is there any code for osmo-iuh already available > somewhere? I don't see it on git.osmocom.org. it is not yet published, I would like to do that at the date of the event itself. It will be on git.osmocom.org. The actual core HNBAP/RUA code is already there. Next is the plan on how to integrate with the existing OsmoNITB. Somehow the A interface code needs to be abstracted out, so that a subscriber_connection can either be served by an A or by an IuCS interface. Another step currently needed is UMTS AKA in the NITB. Once the above two problem areas are adressed, we should have a solution that works at least for signalling (LU, SMS, USSD,...). -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Tue Oct 6 20:20:42 2015 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 6 Oct 2015 22:20:42 +0200 Subject: Oct 07, 8pm / Osmocom Berlin User Group meeting In-Reply-To: <20151005143900.GG8672@nataraja> References: <20151003180057.GH29331@nataraja> <20151004115941.GA95636@ngolde.de> <20151005143900.GG8672@nataraja> Message-ID: <20151006202042.GQ8672@nataraja> Hi Nico and list, On Mon, Oct 05, 2015 at 04:39:00PM +0200, Harald Welte wrote: > On Sun, Oct 04, 2015 at 01:59:41PM +0200, Nico Golde wrote: > > For those interested... is there any code for osmo-iuh already available > > somewhere? I don't see it on git.osmocom.org. > > it is not yet published, I would like to do that at the date of the > event itself. It will be on git.osmocom.org. Ok, I finally added the copyright statements and AGPLv3 license disclaimers and released it at http://git.osmocom.org/osmo-iuh/ or rather 'git clone git://git.osmocom.org/osmo-iuh'. Anyone interested in contributing: I'm happy to give git commit access. It's not much, but it was quite a long struggle to get there, mostly in terms of getting asn1c into shape and understanding the hacks of the OpenAirInterface asn1tostruct.py, which helps to work around the lack of information object classes in asn1c, ... The world would be such a better place if anyone with understanding of compiler theory would work on a usable and complete free software asn1 compiler. Having worked with Fabrice Bellard's ffasn1c is such a pleasure, but unfortunately he is not interested in making it open source - and apparently isn't even actively selling licenses of it either. More explanations in about 22 hours from now at CCCB. Regards, Harald -- - Harald Welte ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Wed Oct 7 14:18:22 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:22 +0200 Subject: [PATCH 04/10] gtphub: add skeletal gtphub.[hc] In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-5-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/Makefile.am | 3 +- openbsc/include/openbsc/gtphub.h | 98 +++++++++++++++++++++++++++++++++++++ openbsc/src/gprs/Makefile.am | 2 +- openbsc/src/gprs/gtphub.c | 45 +++++++++++++++++ 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 openbsc/include/openbsc/gtphub.h create mode 100644 openbsc/src/gprs/gtphub.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 254f43d..c5dd6af 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -16,7 +16,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ - gprs_gsup_client.h bsc_msg_filter.h + gprs_gsup_client.h bsc_msg_filter.h \ + gtphub.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h new file mode 100644 index 0000000..cd4c215 --- /dev/null +++ b/openbsc/include/openbsc/gtphub.h @@ -0,0 +1,98 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +#include + + +/* general */ + +enum gtphub_port_idx { + GTPH_PORT_CONTROL = 0, + GTPH_PORT_USER = 1, + GTPH_PORT_N +}; + +extern const char* const gtphub_port_idx_names[GTPH_PORT_N]; + + +/* config */ + +struct gtphub_cfg_addr { + const char *addr_str; + uint16_t port; +}; + +struct gtphub_cfg_bind { + struct gtphub_cfg_addr bind; +}; + +struct gtphub_cfg { + struct gtphub_cfg_bind to_clients[GTPH_PORT_N]; + struct gtphub_cfg_bind to_servers[GTPH_PORT_N]; +}; + + +/* state */ + +struct gtphub; + +struct gtphub_addr { + struct sockaddr_storage a; + socklen_t l; +}; + +struct gtphub_peer { + struct llist_head entry; + + struct gtphub_addr addr; +}; + +struct gtphub_bind { + struct osmo_fd ofd; + + /* list of struct gtphub_peer */ + struct llist_head peers; +}; + +struct gtphub { + struct gtphub_bind to_clients[GTPH_PORT_N]; + struct gtphub_bind to_servers[GTPH_PORT_N]; +}; + + +/* api */ + +void gtphub_zero(struct gtphub *hub); +int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg); + +/* Create a new gtphub_peer instance added to peers_list. + * Initialize to all-zero. Return a pointer to the new instance, or NULL on + * error. */ +struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind); + +/* Remove a gtphub_peer from its list and free it. */ +void gtphub_peer_del(struct gtphub_peer *peer); + diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 753a073..9053766 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -33,5 +33,5 @@ osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) -lrt -osmo_gtphub_SOURCES = gtphub_main.c +osmo_gtphub_SOURCES = gtphub_main.c gtphub.c osmo_gtphub_LDADD = $(LIBOSMOCORE_LIBS) -lrt diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c new file mode 100644 index 0000000..ffe0d4a --- /dev/null +++ b/openbsc/src/gprs/gtphub.c @@ -0,0 +1,45 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include +#include + +void *osmo_gtphub_ctx; + +#define LOGERR(fmt, args...) \ + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) + +void gtphub_zero(struct gtphub *hub) +{ + memset(hub, '\0', sizeof(*hub)); +} + +int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) +{ + LOGERR("%s not implemented\n", __func__); + return -1; +} + -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:19 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:19 +0200 Subject: [PATCH 01/10] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> First steps towards a new GTP hub. The aim is to mux GTP connections, so that multiple SGSN <--> GGSN links can pass through a single point. Background: allow having more than one SGSN, possibly in various remote locations. The recent addition of OAP to GSUP is related to the same background idea. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/debug.h | 1 + openbsc/src/gprs/gtphub_main.c | 296 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 openbsc/src/gprs/gtphub_main.c diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 19d8fc2..189ca47 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -33,6 +33,7 @@ enum { DCTRL, DSMPP, DFILTER, + DGTPHUB, Debug_LastEntry, }; diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c new file mode 100644 index 0000000..aa35952 --- /dev/null +++ b/openbsc/src/gprs/gtphub_main.c @@ -0,0 +1,296 @@ +/* GTP Hub main program */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#define LOGERR(fmt, args...) \ + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) + +#define LOG(fmt, args...) \ + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) + +extern void *osmo_gtphub_ctx; + +/* TODO move to osmocom/core/socket.c ? */ +#include +/* The caller is required to call freeaddrinfo(*result), iff zero is returned. */ +/* use this in osmo_sock_init() to remove dup. */ +static int _osmo_getaddrinfo(struct addrinfo **result, + uint16_t family, uint16_t type, uint8_t proto, + const char *host, uint16_t port) +{ + struct addrinfo hints; + char portbuf[16]; + + sprintf(portbuf, "%u", port); + memset(&hints, '\0', sizeof(struct addrinfo)); + hints.ai_family = family; + if (type == SOCK_RAW) { + /* Workaround for glibc, that returns EAI_SERVICE (-8) if + * SOCK_RAW and IPPROTO_GRE is used. + */ + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } else { + hints.ai_socktype = type; + hints.ai_protocol = proto; + } + + return getaddrinfo(host, portbuf, &hints, result); +} + +/* TODO move to osmocom/core/socket.c ? */ +/*! \brief Initialize a sockaddr \param[out] addr valid sockaddr pointer to + * write result to \param[out] addr_len valid pointer to write addr length to + * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC + * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM \param[in] proto + * Protocol like IPPROTO_TCP, IPPROTO_UDP \param[in] host remote host name or + * IP address in string form \param[in] port remote port number in host byte + * order \returns 0 on success, otherwise an error code (from getaddrinfo()). + * + * Copy the first result from a getaddrinfo() call with the given parameters to + * *addr and *addr_len. On error, do not change *addr and return nonzero. + */ +int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, + uint16_t family, uint16_t type, uint8_t proto, + const char *host, uint16_t port) +{ + struct addrinfo *res; + int rc; + rc = _osmo_getaddrinfo(&res, family, type, proto, host, port); + + if (rc != 0) { + LOGERR("getaddrinfo returned error %d\n", (int)rc); + return -EINVAL; + } + + OSMO_ASSERT(res->ai_addrlen <= sizeof(*addr)); + memcpy(addr, res->ai_addr, res->ai_addrlen); + *addr_len = res->ai_addrlen; + freeaddrinfo(res); + + return 0; +} + + +void *tall_bsc_ctx; + +const char *gtphub_copyright = + "Copyright (C) 2015 sysmocom s.m.f.c GmbH \r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct log_info_cat gtphub_categories[] = { + [DGTPHUB] = { + .name = "DGTPHUB", + .description = "GTP Hub", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +int gtphub_log_filter_fn(const struct log_context *ctx, + struct log_target *tar) +{ + return 0; +} + +static const struct log_info gtphub_log_info = { + .filter_fn = gtphub_log_filter_fn, + .cat = gtphub_categories, + .num_cat = ARRAY_SIZE(gtphub_categories), +}; + +/* Recv datagram from from->fd, optionally write sender's address to *from_addr + * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using + * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ +int gtp_relay(struct osmo_fd *from, struct sockaddr_storage *from_addr, socklen_t *from_addr_len, + struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len) +{ + static uint8_t buf[4096]; + + errno = 0; + ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, + (struct sockaddr*)from_addr, from_addr_len); + + if (received <= 0) { + if (errno != EAGAIN) + LOGERR("error: %s\n", strerror(errno)); + return -errno; + } + + if (from_addr) { + LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); + } + + if (received <= 0) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + /* insert magic here */ + + errno = 0; + ssize_t sent = sendto(to->fd, buf, received, 0, + (struct sockaddr*)to_addr, to_addr_len); + + if (to_addr) { + LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); + } + + if (sent == -1) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + if (sent != received) + LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); + else + LOG("%d b ok\n", (int)sent); + + return 0; +} + +struct sockaddr_storage last_client_addr; +socklen_t last_client_addr_len; +struct sockaddr_storage server_addr; +socklen_t server_addr_len; + +int clients_read_cb(struct osmo_fd *clients_ofd, unsigned int what) +{ + LOG("reading from clients socket\n"); + struct osmo_fd *server_ofd = clients_ofd->data; + + if (!(what & BSC_FD_READ)) + return 0; + + last_client_addr_len = sizeof(last_client_addr); + return gtp_relay(clients_ofd, &last_client_addr, &last_client_addr_len, + server_ofd, &server_addr, server_addr_len); +} + +int server_read_cb(struct osmo_fd *server_ofd, unsigned int what) +{ + LOG("reading from server socket\n"); + struct osmo_fd *clients_ofd = server_ofd->data; + + if (!(what & BSC_FD_READ)) + return 0; + + return gtp_relay(server_ofd, NULL, NULL, + clients_ofd, &last_client_addr, last_client_addr_len); +} + +int main(int argc, char **argv) +{ + osmo_init_logging(>phub_log_info); + + int rc; + + const char* clients_addr_str = "localhost"; + uint16_t clients_port = 3386; + + const char* server_addr_str = "localhost"; + uint16_t server_port = 1234; + + /* Which local interface to use to listen for the GTP server's + * responses */ + const char* server_rx_addr_str = "localhost"; + uint16_t server_rx_port = 4321; + + rc = osmo_sockaddr_init(&server_addr, &server_addr_len, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_addr_str, server_port); + if (rc != 0) { + LOGERR("Cannot resolve '%s port %d'\n", server_addr_str, server_port); + exit(-1); + } + + struct osmo_fd clients_ofd; + struct osmo_fd server_ofd; + + memset(&clients_ofd, 0, sizeof(clients_ofd)); + clients_ofd.when = BSC_FD_READ; + clients_ofd.cb = clients_read_cb; + clients_ofd.data = &server_ofd; + + rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d\n", clients_addr_str, clients_port); + exit(-1); + } + + memset(&server_ofd, 0, sizeof(server_ofd)); + server_ofd.when = BSC_FD_READ; + server_ofd.cb = server_read_cb; + server_ofd.data = &clients_ofd; + + rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d\n", server_rx_addr_str, server_rx_port); + exit(-1); + } + + LOG("GTP server connection: %s port %d <--> %s port %d\n", + server_rx_addr_str, (int)server_rx_port, + server_addr_str, (int)server_port); + LOG("Listening for clients on %s port %d.\n", clients_addr_str, clients_port); + + int daemonize = 0; + + if (daemonize) { + rc = osmo_daemonize(); + if (rc < 0) { + LOGERR("Error during daemonize"); + exit(1); + } + } + + while (1) { + rc = osmo_select_main(0); + if (rc < 0) + exit(3); + } + + /* not reached */ + exit(0); +} -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:27 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:27 +0200 Subject: [PATCH 09/10] gtphub: add GTP header validation In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-10-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/src/gprs/gtphub.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 419b21f..c6ce4f6 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -46,6 +48,116 @@ typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); #define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) #define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) +/* TODO duplicated from openggsn/gtp/gtpie.h */ +#define ntoh16(x) ntohs(x) +#define ntoh32(x) ntohl(x) + +/* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */ + +enum gtp_header_type { + GTPH_V0 = 0, + GTPH_V1 = 1, + + GTPH_TOOSHORT = -1, + GTPH_UNSUPPORTED_VERSION = -2, + GTPH_LOWER_VERSION = -3, // when gtp0 is received by gtp1 socket +}; + +int validate_gtp0_header(const uint8_t *data, int data_len) +{ + struct gtp0_header *pheader; + pheader = (struct gtp0_header *)(data); + + OSMO_ASSERT(data_len >= 1); + + int version = (*data) >> 5; + + /* Version should be gtp0 (or earlier) */ + /* 09.60 is somewhat unclear on this issue. On gsn->fd0 we expect only */ + /* GTP 0 messages. If other version message is received we reply that we */ + /* only support version 0, implying that this is the only version */ + /* supported on this port */ + if (version != 0) { + LOGERR("Expecting GTP version 0, got: %d\n", version); + return GTPH_UNSUPPORTED_VERSION; + } + + /* Check length of gtp0 packet */ + if (data_len < GTP0_HEADER_SIZE) { + LOGERR("GTP0 packet too short: %d\n", data_len); + return GTPH_TOOSHORT; + } + + /* Check packet length field versus length of packet */ + if (data_len != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) { + LOGERR("GTP packet length field (%d + %d) does not match" + " actual length (%d)\n", + GTP0_HEADER_SIZE, (int)ntoh16(pheader->length), + data_len); + return GTPH_TOOSHORT; + } + + return GTPH_V0; +} + +int validate_gtp1_header(const uint8_t *data, int data_len) +{ + struct gtp1_header_short *pheader; + pheader = (struct gtp1_header_short *)data; + + OSMO_ASSERT(data_len >= 1); + + int version = (*data) >> 5; + + if (version != 1) { + LOGERR("Expecting GTP version 1, got: %d\n", version); + return (version < 1? GTPH_LOWER_VERSION : GTPH_UNSUPPORTED_VERSION); + } + + /* Check length of packet */ + if (data_len < GTP1_HEADER_SIZE_LONG) { + LOGERR("GTP packet too short: %d\n", data_len); + return GTPH_TOOSHORT; + } + + /* Check packet length field versus length of packet */ + if (data_len != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) { + LOGERR("GTP packet length field (%d + %d) does not match" + " actual length (%d)\n", + GTP1_HEADER_SIZE_SHORT, (int)ntoh16(pheader->length), + data_len); + return GTPH_TOOSHORT; + } + + return GTPH_V1; +} + +/* Examine whether given data of size data_len has a valid GTP header. + * Return the GTP version, or < 0 on error (see enum gtp_header_type). + */ +int validate_gtp_header(const uint8_t *data, int data_len) +{ + /* Need at least 1 byte in order to check version */ + if (data_len < (1)) { + LOGERR("Discarding packet - too small\n"); + return GTPH_TOOSHORT; + } + + int version = (*data) >> 5; + + switch (version) { + case 0: + return validate_gtp0_header(data, data_len); + case 1: + return validate_gtp1_header(data, data_len); + default: + break; + } + + LOGERR("Unsupported GTP version: %d\n", version); + return GTPH_UNSUPPORTED_VERSION; +} + /* general */ @@ -55,6 +167,8 @@ const char* const gtphub_port_idx_names[GTPH_PORT_N] = { }; +/* tei_map, tei_pool */ + void tei_pool_init(struct tei_pool *pool) { *pool = (struct tei_pool){}; @@ -215,6 +329,16 @@ static int gtp_relay(struct osmo_fd *from, /* insert magic here */ + int gtph = validate_gtp_header(buf, received); + + if (gtph >= 0) + LOG("Valid GTP header (v%d)\n", gtph); +#if 0 + else + // error has been logged + return 0; +#endif + errno = 0; ssize_t sent = sendto(to->fd, buf, received, 0, (struct sockaddr*)to_addr, to_addr_len); -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:26 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:26 +0200 Subject: [PATCH 08/10] gtphub: add TEI map test In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-9-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/tests/gtphub/Makefile.am | 1 + openbsc/tests/gtphub/gtphub_test.c | 60 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/openbsc/tests/gtphub/Makefile.am b/openbsc/tests/gtphub/Makefile.am index c4b3ec1..4b852e4 100644 --- a/openbsc/tests/gtphub/Makefile.am +++ b/openbsc/tests/gtphub/Makefile.am @@ -11,6 +11,7 @@ noinst_PROGRAMS = gtphub_test gtphub_test_SOURCES = gtphub_test.c gtphub_test_LDADD = \ + $(top_builddir)/src/gprs/gtphub.o \ $(LIBOSMOCORE_LIBS) \ -lgtp -lrt diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c index 95f82c3..25e51e7 100644 --- a/openbsc/tests/gtphub/gtphub_test.c +++ b/openbsc/tests/gtphub/gtphub_test.c @@ -28,11 +28,65 @@ #include +#include + void *osmo_gtphub_ctx; -static void test_gtphub_api(void) +/* TODO copied from libosmo-abis/src/subchan_demux.c, remove dup */ +static int llist_len(struct llist_head *head) +{ + struct llist_head *entry; + int i = 0; + + llist_for_each(entry, head) + i++; + + return i; +} + +static void test_tei_map(void) { - OSMO_ASSERT(1); + /* Basic */ + struct tei_pool _pool; + struct tei_pool *pool = &_pool; + struct tei_map _map; + struct tei_map *map = &_map; + + tei_pool_init(pool); + tei_map_init(map, pool); + + OSMO_ASSERT(llist_empty(&map->mappings)); + +#define TEST_N 100 +#define TEST_I 123 + uint32_t i, check_i; + uint32_t m[TEST_N]; + + /* create TEST_N mappings */ + for (i = 0; i < TEST_N; i++) { + m[i] = tei_map_get(map, TEST_I + i); + OSMO_ASSERT(m[i] != 0); + OSMO_ASSERT(llist_len(&map->mappings) == (i+1)); + for (check_i = 0; check_i < i; check_i++) + OSMO_ASSERT(m[check_i] != m[i]); + } + OSMO_ASSERT(llist_len(&map->mappings) == TEST_N); + + /* verify mappings */ + for (i = 0; i < TEST_N; i++) { + OSMO_ASSERT(tei_map_get(map, TEST_I + i) == m[i]); + OSMO_ASSERT(tei_map_get_rev(map, m[i]) == (TEST_I + i)); + } + OSMO_ASSERT(llist_len(&map->mappings) == TEST_N); + + /* remove all mappings */ + for (i = 0; i < TEST_N; i++) { + tei_map_del(map, TEST_I + i); + OSMO_ASSERT(llist_len(&map->mappings) == (TEST_N - (i+1))); + } + OSMO_ASSERT(llist_empty(&map->mappings)); +#undef TEST_N +#undef TEST_I } static struct log_info_cat gtphub_categories[] = { @@ -54,7 +108,7 @@ int main(int argc, char **argv) osmo_init_logging(&info); osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); - test_gtphub_api(); + test_tei_map(); printf("Done\n"); talloc_report_full(osmo_gtphub_ctx, stderr); -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:18 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:18 +0200 Subject: No subject Message-ID: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Hi openbsc, the following patch series adds a GTP hub program (maturity level: proof-of-concept). Its aim is related to the recent addition of OAP: it will allow routing multiple SGSNs through one GTP server hub (proxy). The program so far forwards UDP packets to and from hardcoded ports, and logs validity of GTP headers passing through. I think this a good time to do a review cycle and merge to master, before adding the interesting stuff. What will follow: decode GTP body, map/separate PDP contexts across clients and servers, replace TEIs. To do that without reinventing the GTP wheel, I may need to separate data parsing from send/recv in openggsn. There are also some bits that should probably be moved out (to where I copied it from) and the API there changed (so that I can use it here without copying). Those are clearly marked with todo comments. Thanks for your review! ~Neels From nhofmeyr at sysmocom.de Wed Oct 7 14:18:21 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:21 +0200 Subject: [PATCH 03/10] gtphub: add simple netcat test In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-4-git-send-email-nhofmeyr@sysmocom.de> Tweak the hardcoded default ports/interfaces for the test. Sponsored-by: On-Waves ehf --- openbsc/configure.ac | 1 + openbsc/src/gprs/gtphub_main.c | 14 ++++---- openbsc/tests/Makefile.am | 2 +- openbsc/tests/gtphub/Makefile.am | 3 ++ openbsc/tests/gtphub/gtphub_nc_test.ok | 7 ++++ openbsc/tests/gtphub/gtphub_nc_test.sh | 58 ++++++++++++++++++++++++++++++++++ openbsc/tests/testsuite.at | 7 ++++ 7 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 openbsc/tests/gtphub/Makefile.am create mode 100644 openbsc/tests/gtphub/gtphub_nc_test.ok create mode 100755 openbsc/tests/gtphub/gtphub_nc_test.sh diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 78302dd..7809feb 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -209,6 +209,7 @@ AC_OUTPUT( tests/trau/Makefile tests/sgsn/Makefile tests/subscr/Makefile + tests/gtphub/Makefile doc/Makefile doc/examples/Makefile Makefile) diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index aa35952..f8bcd59 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -227,16 +227,18 @@ int main(int argc, char **argv) int rc; - const char* clients_addr_str = "localhost"; - uint16_t clients_port = 3386; + /* Which local interface to use to listen for GTP clients */ + const char* clients_addr_str = "127.0.0.3"; + uint16_t clients_port = 2123; - const char* server_addr_str = "localhost"; - uint16_t server_port = 1234; + /* Where the GTP server sits that we're relaying for */ + const char* server_addr_str = "127.0.0.2"; + uint16_t server_port = 2123; /* Which local interface to use to listen for the GTP server's * responses */ - const char* server_rx_addr_str = "localhost"; - uint16_t server_rx_port = 4321; + const char* server_rx_addr_str = "127.0.0.4"; + uint16_t server_rx_port = 2123; rc = osmo_sockaddr_init(&server_addr, &server_addr_len, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_addr_str, server_port); diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 773830b..7dda124 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr gtphub if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gtphub/Makefile.am b/openbsc/tests/gtphub/Makefile.am new file mode 100644 index 0000000..d53c19d --- /dev/null +++ b/openbsc/tests/gtphub/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = \ + gtphub_nc_test.sh \ + gtphub_nc_test.ok diff --git a/openbsc/tests/gtphub/gtphub_nc_test.ok b/openbsc/tests/gtphub/gtphub_nc_test.ok new file mode 100644 index 0000000..e4f641b --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_nc_test.ok @@ -0,0 +1,7 @@ +--- recv_server: +[msg 1: client to server] +OK +--- recv_client: +[msg 2: server to client] +OK +done diff --git a/openbsc/tests/gtphub/gtphub_nc_test.sh b/openbsc/tests/gtphub/gtphub_nc_test.sh new file mode 100755 index 0000000..179bad7 --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_nc_test.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# gtphub_nc_test.sh + +# TODO does this work with all relevant netcat implementations? +# TODO skip if netcat not found? + +gtphub_bin="$1" +if [ ! -x "$gtphub_bin" ]; then + echo "executable not found: $gtphub_bin" + exit 1; +fi + +# client osmo-gtphub gtp server +# 127.0.0.1:9876 <--> 127.0.0.3:2123 | 127.0.0.4:2123 <--> 127.0.0.2 2123 +# (netcat) ($gtphub_bin) (netcat) + +# start gtphub relay +"$gtphub_bin" & +sleep 0.1 + +# log what reaches client and server +nc --recv-only -u -l -p 9876 -s 127.0.0.1 > recv_client & +nc --recv-only -u -l -p 2123 -s 127.0.0.2 > recv_server & +sleep .1 + +# send test messages, both ways +msg1="[msg 1: client to server]" +echo "$msg1" | nc --send-only -u -s 127.0.0.1 -p 9876 127.0.0.3 2123 + +msg2="[msg 2: server to client]" +echo "$msg2" | nc --send-only -u -s 127.0.0.2 -p 2123 127.0.0.4 2123 + +sleep .1 +kill %1 %2 %3 + +# log what has reached the server and client ends, matched against +# gtphub_nc_test.ok +retval=0 +echo "--- recv_server:" +cat recv_server +if [ "$(cat recv_server)" == "$msg1" ]; then + echo "OK" +else + echo "*** FAILURE" + retval=1 +fi + +echo "--- recv_client:" +cat recv_client +if [ "$(cat recv_client)" == "$msg2" ]; then + echo "OK" +else + echo "*** FAILURE" + retval=2 +fi + +echo "done" +exit "$retval" diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 74aaef0..14d1f72 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -103,3 +103,10 @@ AT_CHECK([test "$enable_sgsn_test" != no || exit 77]) cat $abs_srcdir/sgsn/sgsn_test.ok > expout AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([gtphub]) +AT_KEYWORDS([gtphub]) +AT_CHECK([test "$enable_gtphub_test" != no || exit 77]) +cat $abs_srcdir/gtphub/gtphub_nc_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gtphub/gtphub_nc_test.sh $abs_top_builddir/src/gprs/osmo-gtphub], [], [expout], [ignore]) +AT_CLEANUP -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:20 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:20 +0200 Subject: [PATCH 02/10] gtphub: add to build In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-3-git-send-email-nhofmeyr@sysmocom.de> Add program osmo-gtphub from gtphub_main.c to Makefile.am. Add osmo-gtphub binary to gitignore. Sponsored-by: On-Waves ehf --- openbsc/.gitignore | 1 + openbsc/src/gprs/Makefile.am | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 2210c47..f024d76 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -53,6 +53,7 @@ src/utils/isdnsync src/nat/bsc_nat src/gprs/osmo-sgsn src/gprs/osmo-gbproxy +src/gprs/osmo-gtphub src/osmo-bsc_nat/osmo-bsc_nat #tests diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f46a402..753a073 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -11,6 +11,7 @@ noinst_HEADERS = gprs_sndcp.h bin_PROGRAMS = osmo-gbproxy if HAVE_LIBGTP +bin_PROGRAMS += osmo-gtphub if HAVE_LIBCARES bin_PROGRAMS += osmo-sgsn endif @@ -31,3 +32,6 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) -lrt + +osmo_gtphub_SOURCES = gtphub_main.c +osmo_gtphub_LDADD = $(LIBOSMOCORE_LIBS) -lrt -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:23 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:23 +0200 Subject: [PATCH 05/10] gtphub: populate API impl from test prog In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-6-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/src/gprs/gtphub.c | 209 ++++++++++++++++++++++++++++++++++++++++- openbsc/src/gprs/gtphub_main.c | 183 +++++++++++------------------------- 2 files changed, 261 insertions(+), 131 deletions(-) diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index ffe0d4a..a8bd276 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -20,26 +20,231 @@ */ #include +#include +#include #include #include #include #include +#include void *osmo_gtphub_ctx; #define LOGERR(fmt, args...) \ LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) +#define LOG(fmt, args...) \ + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) + +/* TODO move this to osmocom/core/select.h ? */ +typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); + +/* TODO move this to osmocom/core/linuxlist.h ? */ +#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) +#define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) + + +/* general */ + +const char* const gtphub_port_idx_names[GTPH_PORT_N] = { + "CTRL", + "USER", +}; + + +/* gtphub */ + void gtphub_zero(struct gtphub *hub) { memset(hub, '\0', sizeof(*hub)); } +static int gtphub_sock_init(struct osmo_fd *ofd, + const struct gtphub_cfg_addr *addr, + osmo_fd_cb_t cb, + void *data, + int ofd_id) +{ + ofd->when = BSC_FD_READ; + ofd->cb = cb; + ofd->data = data; + ofd->priv_nr = ofd_id; + + int rc; + rc = osmo_sock_init_ofd(ofd, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + addr->addr_str, addr->port, + OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d (rc %d)\n", + addr->addr_str, (int)addr->port, rc); + return -1; + } + + return 0; +} + +static int gtphub_gtp_bind_init(struct gtphub_bind *b, + const struct gtphub_cfg_bind *cfg, + osmo_fd_cb_t cb, void *cb_data, + unsigned int ofd_id) +{ + memset(b, '\0', sizeof(*b)); + + INIT_LLIST_HEAD(&b->peers); + + if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0) + return -1; + return 0; +} + +/* Recv datagram from from->fd, optionally write sender's address to *from_addr + * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using + * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ +static int gtp_relay(struct osmo_fd *from, + struct sockaddr_storage *from_addr, + socklen_t *from_addr_len, + struct osmo_fd *to, + struct sockaddr_storage *to_addr, + socklen_t to_addr_len) +{ + static uint8_t buf[4096]; + + /* recvfrom requires the available length to be set in *from_addr_len. */ + if (from_addr_len && from_addr) + *from_addr_len = sizeof(*from_addr); + + errno = 0; + ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, + (struct sockaddr*)from_addr, from_addr_len); + + if (received <= 0) { + if (errno != EAGAIN) + LOGERR("error: %s\n", strerror(errno)); + return -errno; + } + + if (from_addr) { + LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); + } + + if (received <= 0) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + /* insert magic here */ + + errno = 0; + ssize_t sent = sendto(to->fd, buf, received, 0, + (struct sockaddr*)to_addr, to_addr_len); + + if (to_addr) { + LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); + } + + if (sent == -1) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + if (sent != received) + LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); + else + LOG("%d b ok\n", (int)sent); + + return 0; +} + +int servers_read_cb(struct osmo_fd *servers_ofd, unsigned int what) +{ + unsigned int port_idx = servers_ofd->priv_nr; + OSMO_ASSERT(port_idx < GTPH_PORT_N); + LOG("reading from servers socket (%s)\n", gtphub_port_idx_names[port_idx]); + if (!(what & BSC_FD_READ)) + return 0; + + struct gtphub *hub = servers_ofd->data; + + /* TODO this will not be hardcoded. */ + struct gtphub_peer *client = llist_first(&hub->to_clients[port_idx].peers, + struct gtphub_peer, entry); + if (!client) { + LOGERR("no client"); + return 0; + } + + return gtp_relay(servers_ofd, NULL, NULL, + &hub->to_clients[port_idx].ofd, + &client->addr.a, client->addr.l); +} + +int clients_read_cb(struct osmo_fd *clients_ofd, unsigned int what) +{ + unsigned int port_idx = clients_ofd->priv_nr; + OSMO_ASSERT(port_idx < GTPH_PORT_N); + LOG("reading from clients socket (%s)\n", gtphub_port_idx_names[port_idx]); + + if (!(what & BSC_FD_READ)) + return 0; + + struct gtphub *hub = clients_ofd->data; + + /* TODO this will not be hardcoded. */ + /* so far just remembering the last client */ + struct gtphub_peer *server = llist_first(&hub->to_servers[port_idx].peers, + struct gtphub_peer, entry); + if (!server) { + LOGERR("no server to send to\n"); + return 0; + } + + struct gtphub_peer *client = llist_first(&hub->to_clients[port_idx].peers, + struct gtphub_peer, entry); + if (!client) + client = gtphub_peer_new(&hub->to_clients[port_idx]); + + return gtp_relay(clients_ofd, &client->addr.a, &client->addr.l, + &hub->to_servers[port_idx].ofd, + &server->addr.a, server->addr.l); +} + int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) { - LOGERR("%s not implemented\n", __func__); - return -1; + gtphub_zero(hub); + + int port_id; + for (port_id = 0; port_id < GTPH_PORT_N; port_id++) { + int rc; + rc = gtphub_gtp_bind_init(&hub->to_servers[port_id], + &cfg->to_servers[port_id], + servers_read_cb, hub, port_id); + if (rc < 0) + return rc; + + rc = gtphub_gtp_bind_init(&hub->to_clients[port_id], + &cfg->to_clients[port_id], + clients_read_cb, hub, port_id); + if (rc < 0) + return rc; + + /* ... */ + } + return 0; +} + +struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind) +{ + struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer); + llist_add(&n->entry, &bind->peers); + return n; +} + +void gtphub_peer_del(struct gtphub_peer *peer) +{ + llist_del(&peer->entry); + talloc_free(peer); } diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index f8bcd59..104cbfd 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -20,27 +20,17 @@ */ #include -#include -#include #include -#include -#include - #define _GNU_SOURCE #include #include -#include -#include -#include #include +#include #include - -#include - -#include +#include #define LOGERR(fmt, args...) \ LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) @@ -112,7 +102,6 @@ int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, } -void *tall_bsc_ctx; const char *gtphub_copyright = "Copyright (C) 2015 sysmocom s.m.f.c GmbH \r\n" @@ -141,141 +130,77 @@ static const struct log_info gtphub_log_info = { .num_cat = ARRAY_SIZE(gtphub_categories), }; -/* Recv datagram from from->fd, optionally write sender's address to *from_addr - * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using - * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ -int gtp_relay(struct osmo_fd *from, struct sockaddr_storage *from_addr, socklen_t *from_addr_len, - struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len) +void log_cfg(struct gtphub_cfg *cfg) { - static uint8_t buf[4096]; - - errno = 0; - ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, - (struct sockaddr*)from_addr, from_addr_len); - - if (received <= 0) { - if (errno != EAGAIN) - LOGERR("error: %s\n", strerror(errno)); - return -errno; - } - - if (from_addr) { - LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); - } - - if (received <= 0) { - LOGERR("error: %s\n", strerror(errno)); - return -EINVAL; - } - - /* insert magic here */ - - errno = 0; - ssize_t sent = sendto(to->fd, buf, received, 0, - (struct sockaddr*)to_addr, to_addr_len); - - if (to_addr) { - LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); - } - - if (sent == -1) { - LOGERR("error: %s\n", strerror(errno)); - return -EINVAL; - } - - if (sent != received) - LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); - else - LOG("%d b ok\n", (int)sent); - - return 0; + struct gtphub_cfg_addr *a; + a = &cfg->to_clients[GTPH_PORT_CONTROL].bind; + LOG("Clients bind, Control: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_clients[GTPH_PORT_USER].bind; + LOG("Clients bind, User: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_servers[GTPH_PORT_CONTROL].bind; + LOG("GTP server bind, Control: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_servers[GTPH_PORT_USER].bind; + LOG("GTP server bind, User: %s port %d\n", + a->addr_str, a->port); } -struct sockaddr_storage last_client_addr; -socklen_t last_client_addr_len; -struct sockaddr_storage server_addr; -socklen_t server_addr_len; - -int clients_read_cb(struct osmo_fd *clients_ofd, unsigned int what) +int main(int argc, char **argv) { - LOG("reading from clients socket\n"); - struct osmo_fd *server_ofd = clients_ofd->data; + osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); - if (!(what & BSC_FD_READ)) - return 0; - - last_client_addr_len = sizeof(last_client_addr); - return gtp_relay(clients_ofd, &last_client_addr, &last_client_addr_len, - server_ofd, &server_addr, server_addr_len); -} - -int server_read_cb(struct osmo_fd *server_ofd, unsigned int what) -{ - LOG("reading from server socket\n"); - struct osmo_fd *clients_ofd = server_ofd->data; + osmo_init_logging(>phub_log_info); - if (!(what & BSC_FD_READ)) - return 0; + int rc; - return gtp_relay(server_ofd, NULL, NULL, - clients_ofd, &last_client_addr, last_client_addr_len); -} + struct gtphub_cfg _cfg = { + .to_clients = { + { .bind = { + .addr_str = "127.0.0.3", + .port = 2123, + } }, + { .bind = { + .addr_str = "127.0.0.3", + .port = 2152, + } }, + }, + .to_servers = { + { .bind = { + .addr_str = "127.0.0.4", + .port = 2123, + } }, + { .bind = { + .addr_str = "127.0.0.4", + .port = 2152, + } }, + }, + }; -int main(int argc, char **argv) -{ - osmo_init_logging(>phub_log_info); + struct gtphub_cfg *cfg = &_cfg; - int rc; + struct gtphub _hub; + struct gtphub *hub = &_hub; - /* Which local interface to use to listen for GTP clients */ - const char* clients_addr_str = "127.0.0.3"; - uint16_t clients_port = 2123; + if (gtphub_init(hub, cfg) != 0) + return -1; + /* TODO this will not be configured, gtphub will have to find the + * servers from incoming GTP PDUs. */ /* Where the GTP server sits that we're relaying for */ const char* server_addr_str = "127.0.0.2"; uint16_t server_port = 2123; - - /* Which local interface to use to listen for the GTP server's - * responses */ - const char* server_rx_addr_str = "127.0.0.4"; - uint16_t server_rx_port = 2123; - - rc = osmo_sockaddr_init(&server_addr, &server_addr_len, - AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_addr_str, server_port); + struct gtphub_peer *test_server = gtphub_peer_new(&hub->to_servers[GTPH_PORT_CONTROL]); + rc = osmo_sockaddr_init(&test_server->addr.a, &test_server->addr.l, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + server_addr_str, server_port); if (rc != 0) { LOGERR("Cannot resolve '%s port %d'\n", server_addr_str, server_port); exit(-1); } - struct osmo_fd clients_ofd; - struct osmo_fd server_ofd; - - memset(&clients_ofd, 0, sizeof(clients_ofd)); - clients_ofd.when = BSC_FD_READ; - clients_ofd.cb = clients_read_cb; - clients_ofd.data = &server_ofd; - - rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); - if (rc < 1) { - LOGERR("Cannot bind to %s port %d\n", clients_addr_str, clients_port); - exit(-1); - } - - memset(&server_ofd, 0, sizeof(server_ofd)); - server_ofd.when = BSC_FD_READ; - server_ofd.cb = server_read_cb; - server_ofd.data = &clients_ofd; - - rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); - if (rc < 1) { - LOGERR("Cannot bind to %s port %d\n", server_rx_addr_str, server_rx_port); - exit(-1); - } - - LOG("GTP server connection: %s port %d <--> %s port %d\n", - server_rx_addr_str, (int)server_rx_port, - server_addr_str, (int)server_port); - LOG("Listening for clients on %s port %d.\n", clients_addr_str, clients_port); + log_cfg(cfg); int daemonize = 0; -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:24 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:24 +0200 Subject: [PATCH 06/10] gtphub: add TEI map API. In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-7-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/include/openbsc/gtphub.h | 42 +++++++++++++++++++++ openbsc/src/gprs/gtphub.c | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h index cd4c215..f25c56b 100644 --- a/openbsc/include/openbsc/gtphub.h +++ b/openbsc/include/openbsc/gtphub.h @@ -38,6 +38,46 @@ enum gtphub_port_idx { extern const char* const gtphub_port_idx_names[GTPH_PORT_N]; +/* Generator for unused TEI IDs. So far this counts upwards from zero, but the + * implementation may change in the future. Treat this like an opaque struct. */ +struct tei_pool { + uint32_t last_tei; +}; + +void tei_pool_init(struct tei_pool *pool); + +/* Return the next unused TEI from the tei_pool. */ +uint32_t tei_pool_next(struct tei_pool *pool); + + +struct tei_mapping { + struct llist_head entry; + + uint32_t orig; + uint32_t repl; +}; + +struct tei_map { + struct tei_pool *pool; + struct llist_head mappings; +}; + +/* Initialize an (already allocated) tei_map, and set the map's TEI pool. + * Multiple tei_map instances may use the same tei_pool. */ +void tei_map_init(struct tei_map *map, struct tei_pool *pool); + +/* Return a replacement TEI for tei_orig. If tei_orig is unknown, create a new + * mapping using a so far unused TEI to map tei_orig to. Return 0 on error. */ +uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig); + +/* Return the original TEI for a replacement TEI. If no mapping exists to + * tei_repl, return 0. */ +uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl); + +/* Remove the mapping for tei_orig, if it exists. */ +void tei_map_del(struct tei_map *map, uint32_t tei_orig); + + /* config */ struct gtphub_cfg_addr { @@ -68,10 +108,12 @@ struct gtphub_peer { struct llist_head entry; struct gtphub_addr addr; + struct tei_map teim; }; struct gtphub_bind { struct osmo_fd ofd; + struct tei_pool teip; /* list of struct gtphub_peer */ struct llist_head peers; diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index a8bd276..419b21f 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -54,6 +55,82 @@ const char* const gtphub_port_idx_names[GTPH_PORT_N] = { }; +void tei_pool_init(struct tei_pool *pool) +{ + *pool = (struct tei_pool){}; +} + +uint32_t tei_pool_next(struct tei_pool *pool) +{ + pool->last_tei ++; + + OSMO_ASSERT(pool->last_tei > 0); + /* TODO: gracefully handle running out of TEIs. */ + /* TODO: random TEIs. */ + + return pool->last_tei; +} + +void tei_map_init(struct tei_map *map, struct tei_pool *pool) +{ + *map = (struct tei_map){}; + map->pool = pool; + INIT_LLIST_HEAD(&map->mappings); +} + +static uint32_t tei_map_new(struct tei_map *map, uint32_t tei_orig) +{ + struct tei_mapping *mapping; + mapping = talloc_zero(osmo_gtphub_ctx, struct tei_mapping); + OSMO_ASSERT(mapping); + mapping->orig = tei_orig; + mapping->repl = tei_pool_next(map->pool); + llist_add(&mapping->entry, &map->mappings); + return mapping->repl; +} + +uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig) +{ + OSMO_ASSERT(tei_orig != 0); + + struct tei_mapping *mapping; + llist_for_each_entry(mapping, &map->mappings, entry) { + if (mapping->orig == tei_orig) + return mapping->repl; + } + /* Not found. */ + + return tei_map_new(map, tei_orig); +} + +uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl) +{ + OSMO_ASSERT(tei_repl != 0); + + struct tei_mapping *pos; + llist_for_each_entry(pos, &map->mappings, entry) { + if (pos->repl == tei_repl) { + OSMO_ASSERT(pos->orig); + return pos->orig; + } + } + return 0; +} + +void tei_map_del(struct tei_map *map, uint32_t tei_orig) +{ + struct tei_mapping *mapping; + llist_for_each_entry(mapping, &map->mappings, entry) { + if (mapping->orig == tei_orig) { + llist_del(&mapping->entry); + talloc_free(mapping); + return; + } + } + LOGERR("No mapping exists for TEI %" PRIu32 ".\n", tei_orig); +} + + /* gtphub */ void gtphub_zero(struct gtphub *hub) @@ -93,6 +170,7 @@ static int gtphub_gtp_bind_init(struct gtphub_bind *b, { memset(b, '\0', sizeof(*b)); + tei_pool_init(&b->teip); INIT_LLIST_HEAD(&b->peers); if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0) @@ -238,6 +316,9 @@ int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind) { struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer); + + tei_map_init(&n->teim, &bind->teip); + llist_add(&n->entry, &bind->peers); return n; } -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:25 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:25 +0200 Subject: [PATCH 07/10] gtphub: add gtphub_test.c (empty) In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-8-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/.gitignore | 1 + openbsc/tests/gtphub/Makefile.am | 15 ++++++++- openbsc/tests/gtphub/gtphub_test.c | 63 +++++++++++++++++++++++++++++++++++++ openbsc/tests/gtphub/gtphub_test.ok | 1 + openbsc/tests/testsuite.at | 2 ++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/gtphub/gtphub_test.c create mode 100644 openbsc/tests/gtphub/gtphub_test.ok diff --git a/openbsc/.gitignore b/openbsc/.gitignore index f024d76..bf05ac2 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -78,6 +78,7 @@ tests/trau/trau_test tests/mgcp/mgcp_transcoding_test tests/sgsn/sgsn_test tests/subscr/subscr_test +tests/gtphub/gtphub_test tests/atconfig tests/atlocal diff --git a/openbsc/tests/gtphub/Makefile.am b/openbsc/tests/gtphub/Makefile.am index d53c19d..c4b3ec1 100644 --- a/openbsc/tests/gtphub/Makefile.am +++ b/openbsc/tests/gtphub/Makefile.am @@ -1,3 +1,16 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) + EXTRA_DIST = \ gtphub_nc_test.sh \ - gtphub_nc_test.ok + gtphub_nc_test.ok \ + gtphub_test.ok + +noinst_PROGRAMS = gtphub_test + +gtphub_test_SOURCES = gtphub_test.c + +gtphub_test_LDADD = \ + $(LIBOSMOCORE_LIBS) \ + -lgtp -lrt + diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c new file mode 100644 index 0000000..95f82c3 --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_test.c @@ -0,0 +1,63 @@ +/* Test the GTP hub */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include + +#include + +void *osmo_gtphub_ctx; + +static void test_gtphub_api(void) +{ + OSMO_ASSERT(1); +} + +static struct log_info_cat gtphub_categories[] = { + [DGTPHUB] = { + .name = "DGTPHUB", + .description = "GTP Hub", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +static struct log_info info = { + .cat = gtphub_categories, + .num_cat = ARRAY_SIZE(gtphub_categories), +}; + +int main(int argc, char **argv) +{ + osmo_init_logging(&info); + osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); + + test_gtphub_api(); + printf("Done\n"); + + talloc_report_full(osmo_gtphub_ctx, stderr); + return 0; +} + diff --git a/openbsc/tests/gtphub/gtphub_test.ok b/openbsc/tests/gtphub/gtphub_test.ok new file mode 100644 index 0000000..a965a70 --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_test.ok @@ -0,0 +1 @@ +Done diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 14d1f72..9a1f9dd 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -109,4 +109,6 @@ AT_KEYWORDS([gtphub]) AT_CHECK([test "$enable_gtphub_test" != no || exit 77]) cat $abs_srcdir/gtphub/gtphub_nc_test.ok > expout AT_CHECK([$abs_top_builddir/tests/gtphub/gtphub_nc_test.sh $abs_top_builddir/src/gprs/osmo-gtphub], [], [expout], [ignore]) +cat $abs_srcdir/gtphub/gtphub_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gtphub/gtphub_test], [], [expout], [ignore]) AT_CLEANUP -- 2.1.4 From nhofmeyr at sysmocom.de Wed Oct 7 14:18:28 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 7 Oct 2015 16:18:28 +0200 Subject: [PATCH 10/10] gtphub: debug log In-Reply-To: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444227508-26608-11-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi --- openbsc/src/gprs/gtphub.c | 19 +++++++++++++++++-- openbsc/src/gprs/gtphub_main.c | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index c6ce4f6..5d7b63d 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -97,13 +97,14 @@ int validate_gtp0_header(const uint8_t *data, int data_len) return GTPH_TOOSHORT; } + LOG("GTP v0 TID = %" PRIu64 "\n", pheader->tid); return GTPH_V0; } int validate_gtp1_header(const uint8_t *data, int data_len) { - struct gtp1_header_short *pheader; - pheader = (struct gtp1_header_short *)data; + struct gtp1_header_long *pheader; + pheader = (struct gtp1_header_long *)data; OSMO_ASSERT(data_len >= 1); @@ -129,6 +130,18 @@ int validate_gtp1_header(const uint8_t *data, int data_len) return GTPH_TOOSHORT; } + LOG("GTP v1 type = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->type, pheader->type); + LOG("GTP v1 length = %" PRIu16 " 0x%04" PRIx16 "\n", + ntoh16(pheader->length), ntoh16(pheader->length)); + LOG("GTP v1 TEI = %" PRIu32 " 0x%08" PRIx32 "\n", + ntoh32(pheader->tei), ntoh32(pheader->tei)); + LOG("GTP v1 seq = %" PRIu16 " 0x%04" PRIx16 "\n", + ntoh16(pheader->seq), ntoh16(pheader->seq)); + LOG("GTP v1 npdu = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->npdu, pheader->npdu); + LOG("GTP v1 next = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->next, pheader->next); return GTPH_V1; } @@ -329,6 +342,8 @@ static int gtp_relay(struct osmo_fd *from, /* insert magic here */ + LOG("DATA\n%s\n", osmo_hexdump(buf, received)); + int gtph = validate_gtp_header(buf, received); if (gtph >= 0) diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index 104cbfd..b584617 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -199,6 +199,7 @@ int main(int argc, char **argv) LOGERR("Cannot resolve '%s port %d'\n", server_addr_str, server_port); exit(-1); } + LOG("DEBUG: using GTP server %s port %d\n", server_addr_str, server_port); log_cfg(cfg); -- 2.1.4 From holger at freyther.de Wed Oct 7 16:57:21 2015 From: holger at freyther.de (Holger Freyther) Date: Wed, 7 Oct 2015 18:57:21 +0200 Subject: [PATCH 1/8] libcommon: soak up three static functions. In-Reply-To: <1443705837-25727-2-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <0EA0041C-1AE2-47E9-8579-287F422830B8@freyther.de> > On 01 Oct 2015, at 15:23, Neels Hofmeyr wrote: > > +/* (C) 2015 by sysmocom s.m.f.c if you copy code from one place to another you need to obey the copyright of the original code e.g. the decode routines might have been added in 2014 You need to to put the "Rechtsform" in the name as well s.f.m.c. GmbH > +uint64_t decode_big_endian(const uint8_t *data, size_t data_len) > > +uint8_t *encode_big_endian(uint64_t value, size_t data_len) have you looked at osmo_load64le_ext of libosmocore? I think you don't need these routines. and it applies to GSUP too. From holger at freyther.de Wed Oct 7 16:58:19 2015 From: holger at freyther.de (Holger Freyther) Date: Wed, 7 Oct 2015 18:58:19 +0200 Subject: [PATCH 2/8] gsup: factor out header composition & sending. In-Reply-To: <1443705837-25727-3-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-3-git-send-email-nhofmeyr@sysmocom.de> Message-ID: > On 01 Oct 2015, at 15:23, Neels Hofmeyr wrote: > > Move IPA header composition and sending to new static gsup_client_send() (so I > can use it in the upcoming OAP code). okay. From holger at freyther.de Wed Oct 7 17:00:56 2015 From: holger at freyther.de (Holger Freyther) Date: Wed, 7 Oct 2015 19:00:56 +0200 Subject: [PATCH 3/8] Add OAP design document. In-Reply-To: <1443705837-25727-4-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-4-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <619AE477-20CF-42E7-8B62-572B00304F37@freyther.de> > On 01 Oct 2015, at 15:23, Neels Hofmeyr wrote: > not read again. :) From holger at freyther.de Wed Oct 7 17:16:58 2015 From: holger at freyther.de (Holger Freyther) Date: Wed, 7 Oct 2015 19:16:58 +0200 Subject: [PATCH 4/8] oap: implement initial OAP API. In-Reply-To: <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <85E056D8-E24E-4B47-9F2B-724BD54FF6F1@freyther.de> > On 01 Oct 2015, at 15:23, Neels Hofmeyr wrote: > > + OAP_UNINITIALIZED = 0, // just allocated. No C99 comments > > +static int oap_evaluate_challenge(const struct oap_state *state, > + const uint8_t *rx_random, > + const uint8_t *rx_autn, > + uint8_t *tx_xres) > +{ > > + OSMO_ASSERT(sizeof(auth.u.umts.k) == sizeof(state->secret_k)); > + OSMO_ASSERT(sizeof(auth.u.umts.opc) == sizeof(state->secret_opc)); static assert? > + > + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); > + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); > + memset(auth.u.umts.amf, 0, 2); sizeof? > + auth.u.umts.sqn = 42; /* TODO */ In three years we wonder what the todo is. I think it is a good habbit to add a short summary what we want to do. > > +struct msgb *oap_encoded(const struct oap_message *oap_msg) encode? Sure it is encoded after the function is done but it triggers the encoding? > +{ > +int oap_register(struct oap_state *state, struct msgb **msg_tx) return the struct msgb*? If it is NULL you already know it didnt't work and the -1/0 carry as much value right now? > > + case OAP_MSGT_REGISTER_RESULT: > + // successfully registered! no C99 comments (sorry to have away the method again) I have not looked at the state machine, we can do it together. holger From holger at freyther.de Wed Oct 7 17:17:45 2015 From: holger at freyther.de (Holger Freyther) Date: Wed, 7 Oct 2015 19:17:45 +0200 Subject: [PATCH 5/8] oap: add oap testsuite skeleton In-Reply-To: <1443705837-25727-6-git-send-email-nhofmeyr@sysmocom.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-6-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <94255D8A-2FB1-45C7-A386-28F5B2CA16D0@freyther.de> > On 01 Oct 2015, at 15:23, Neels Hofmeyr wrote: looks okay but can't merge it right now :) From holger at freyther.de Thu Oct 8 08:48:07 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 8 Oct 2015 10:48:07 +0200 Subject: [PATCH 01/10] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: > On 07 Oct 2015, at 16:18, Neels Hofmeyr wrote: > > > +/* TODO move to osmocom/core/socket.c ? */ where did you take this from? > +/* TODO move to osmocom/core/socket.c ? */ > +int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, > + uint16_t family, uint16_t type, uint8_t proto, > + const char *host, uint16_t port) > +{ ah yeah. the by hostname is a good idea. But this should only be used at the beginning of an application as we don't want to block on a DNS query. > > +static struct log_info_cat gtphub_categories[] = { > +static const struct log_info gtphub_log_info = { > + .filter_fn = gtphub_log_filter_fn, > + .cat = gtphub_categories, > + .num_cat = ARRAY_SIZE(gtphub_categories), > +}; nothing else will be used as debug log? Depending on the answer it might be better to just always initialize the GTPHUB area.. > > +int gtp_relay(struct osmo_fd *from, struct sockaddr_storage *from_addr, socklen_t *from_addr_len, > + struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len) > +{ > + static uint8_t buf[4096]; > + > + errno = 0; > + ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, > + (struct sockaddr*)from_addr, from_addr_len); > + When the first gbproxy was built our buffer was smaller and we truncated messages. Now 4k is pretty big and bigger than our expectation for a UDP message. If you use recvmsg then the msg_flags will have MSG_TRUNC set or not. Not sure if you want to use it. > + rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); > + rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); Who is the server? who is the client? Maybe give it names to what we expect on the side? One is the SGSN, the other is the GGSN? From holger at freyther.de Thu Oct 8 08:50:48 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 8 Oct 2015 10:50:48 +0200 Subject: [PATCH 03/10] gtphub: add simple netcat test In-Reply-To: <1444227508-26608-4-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-4-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <672545D6-C419-4D35-BC71-67CF919083A8@freyther.de> > On 07 Oct 2015, at 16:18, Neels Hofmeyr wrote: > > > - const char* clients_addr_str = "localhost"; > - uint16_t clients_port = 3386; > + /* Which local interface to use to listen for GTP clients */ > + const char* clients_addr_str = "127.0.0.3"; > + uint16_t clients_port = 2123; > > - const char* server_addr_str = "localhost"; > - uint16_t server_port = 1234; > + /* Where the GTP server sits that we're relaying for */ > + const char* server_addr_str = "127.0.0.2"; > + uint16_t server_port = 2123; > > /* Which local interface to use to listen for the GTP server's > * responses */ > - const char* server_rx_addr_str = "localhost"; > - uint16_t server_rx_port = 4321; > + const char* server_rx_addr_str = "127.0.0.4"; > + uint16_t server_rx_port = 2123; this won't work on FreeBSD (unless you add the ip addresses by hand). Could you use different ports? holger From holger at freyther.de Thu Oct 8 09:05:21 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 8 Oct 2015 11:05:21 +0200 Subject: [PATCH 05/10] gtphub: populate API impl from test prog In-Reply-To: <1444227508-26608-6-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-6-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <40B6AE58-119F-455C-8E5B-9C901427D033@freyther.de> > On 07 Oct 2015, at 16:18, Neels Hofmeyr wrote: > > +/* TODO move this to osmocom/core/linuxlist.h ? */ > +#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) > +#define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) Why the null check? I mean struct *foo = llist_first(list); if (!foo) return vs. if (llist_empty(list)) return; struct *foo = llist_first(list); has no difference? > +int servers_read_cb(struct osmo_fd *servers_ofd, unsigned int what) > +{ > + unsigned int port_idx = servers_ofd->priv_nr; > + OSMO_ASSERT(port_idx < GTPH_PORT_N); > + LOG("reading from servers socket (%s)\n", gtphub_port_idx_names[port_idx]); > + if (!(what & BSC_FD_READ)) > + return 0; > + > + struct gtphub *hub = servers_ofd->data; > + > + /* TODO this will not be hardcoded. */ > + struct gtphub_peer *client = llist_first(&hub->to_clients[port_idx].peers, > + struct gtphub_peer, entry); interesting that you are the first to use the llist in this way. As you will track multiple peers the need for a llist_first will vanish? From nhofmeyr at sysmocom.de Thu Oct 8 11:24:17 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 8 Oct 2015 13:24:17 +0200 Subject: [PATCH 01/10] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20151008112417.GA5397@dub5> On Thu, Oct 08, 2015 at 10:48:07AM +0200, Holger Freyther wrote: > > > On 07 Oct 2015, at 16:18, Neels Hofmeyr wrote: > > > > > > +/* TODO move to osmocom/core/socket.c ? */ > > where did you take this from? basically the beginning of osmo_sock_init() > > +/* TODO move to osmocom/core/socket.c ? */ > > > > +int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, > > + uint16_t family, uint16_t type, uint8_t proto, > > + const char *host, uint16_t port) > > +{ > > ah yeah. the by hostname is a good idea. But this should only be used at the > beginning of an application as we don't want to block on a DNS query. In fact, I use this function to hardcode the GTP server. We will in future fetch the GTP server by DNS, and I'm not entirely clear on whether getaddrinfo() can resolve that. If we need a full res_query() instead, the gtphub will no longer need this function, and its use is reduced to a courtesy to future API users... > > +static struct log_info_cat gtphub_categories[] = { > > > +static const struct log_info gtphub_log_info = { > > + .filter_fn = gtphub_log_filter_fn, > > + .cat = gtphub_categories, > > + .num_cat = ARRAY_SIZE(gtphub_categories), > > +}; > > nothing else will be used as debug log? Depending on the answer it might be > better to just always initialize the GTPHUB area.. I don't fully see thru the debug setup yet. Other binaries around seem to re-create very similar category lists, apparently just listing all that is defined. I tried to find the minimum first. Others may be added as needed. What do you mean by > better to just always initialize the GTPHUB area.. ? IIUC that's what the patch is doing right now? > If you use recvmsg then the msg_flags will have MSG_TRUNC set or not. > Not sure if you want to use it. I'll put a TODO comment there. The 4kb buf should suffice for now. Thanks for the hint! Wasn't aware. > > + rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); > > + rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); > > > Who is the server? who is the client? Maybe give it names to what we expect on the side? > One is the SGSN, the other is the GGSN? I thought of a GTP server == GGSN and GTP client == SGSN. If that's ambiguous at all I'll be happy to change it, e.g. to to_sgsns, to_ggsns. [SGSN] <---> [to_sgsns GTPHUB to_ggsns] <---> [GGSN] With the "to_" prefix to avoid this ambiguity: if the SGSN contacts the gtphub, the gtphub looks like a GGSN, so a confused reader could think of the "to_sgsns" port as a GGSN. Or rather a "from_" prefix? :P ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Oct 8 11:49:43 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 8 Oct 2015 13:49:43 +0200 Subject: [PATCH 03/10] gtphub: add simple netcat test In-Reply-To: <672545D6-C419-4D35-BC71-67CF919083A8@freyther.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-4-git-send-email-nhofmeyr@sysmocom.de> <672545D6-C419-4D35-BC71-67CF919083A8@freyther.de> Message-ID: <20151008114943.GB5397@dub5> On Thu, Oct 08, 2015 at 10:50:48AM +0200, Holger Freyther wrote: > this won't work on FreeBSD (unless you add the ip addresses by hand). Could you > use different ports? The reason why I picked these: I want to put the osmo-gtphub binary between an openggsn and an sgsnemu, without changing their configuration. I did that and it works :) To keep this working, let's change the ports in the test once the config interface (vty and/or cmdline args) is in place. Then the test can configure various ports on 127.0.0.1. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Oct 8 11:58:53 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 8 Oct 2015 13:58:53 +0200 Subject: [PATCH 05/10] gtphub: populate API impl from test prog In-Reply-To: <40B6AE58-119F-455C-8E5B-9C901427D033@freyther.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-6-git-send-email-nhofmeyr@sysmocom.de> <40B6AE58-119F-455C-8E5B-9C901427D033@freyther.de> Message-ID: <20151008115853.GC5397@dub5> On Thu, Oct 08, 2015 at 11:05:21AM +0200, Holger Freyther wrote: > > +#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) > > +#define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) > > Why the null check? I mean > > struct *foo = llist_first(list); > if (!foo) > return > > vs. > > if (llist_empty(list)) > return; > struct *foo = llist_first(list); > > has no difference? Almost. All it does is make sure I don't forget the emptiness check, really... a NULL dereference will more reliably result in a segfault than dereferencing a list item struct from an llist_head. But anyway: ... > > + /* TODO this will not be hardcoded. */ > > + struct gtphub_peer *client = llist_first(&hub->to_clients[port_idx].peers, > > + struct gtphub_peer, entry); > > interesting that you are the first to use the llist in this way. As you will track > multiple peers the need for a llist_first will vanish? ... Indeed. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From dwilllmann at sysmocom.de Thu Oct 8 14:10:22 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Thu, 8 Oct 2015 16:10:22 +0200 Subject: [openbsc 0/4] Use RAND_bytes() instead of rand() Message-ID: From: Daniel Willmann The following patches uses RAND_bytes() from openssl instead of rand() to generate TMSI/P-TMSI and auth tuples. I didn't change the use of rand_r() in gb-proxy because the gbproxy test seems to depend on predictable randomness. Daniel Willmann (4): libmsc: Use RAND_bytes when choosing a tmsi gprs: Use RAND_bytes for p-tmsi libmsc: Use RAND_bytes to choose auth tuple libmsc: Use RAND_bytes to generate a token openbsc/configure.ac | 2 +- openbsc/src/gprs/gprs_sgsn.c | 4 +++- openbsc/src/libmsc/Makefile.am | 2 +- openbsc/src/libmsc/auth.c | 9 +++++++-- openbsc/src/libmsc/db.c | 12 ++++++++++-- openbsc/src/osmo-nitb/Makefile.am | 2 +- openbsc/tests/channel/Makefile.am | 2 +- openbsc/tests/db/Makefile.am | 2 +- 8 files changed, 25 insertions(+), 10 deletions(-) -- 2.1.4 From dwilllmann at sysmocom.de Thu Oct 8 14:10:26 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Thu, 8 Oct 2015 16:10:26 +0200 Subject: [openbsc 4/4] libmsc: Use RAND_bytes to generate a token In-Reply-To: References: Message-ID: From: Daniel Willmann --- openbsc/src/libmsc/db.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index faae982..863a092 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -1275,7 +1275,10 @@ int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t *token uint32_t try; for (;;) { - try = rand(); + if (RAND_bytes(&try, sizeof(try)) != 1) { + LOGP(DDB, LOGL_ERROR, "RAND_bytes failed\n"); + return 1; + } if (!try) /* 0 is an invalid token */ continue; result = dbi_conn_queryf(conn, -- 2.1.4 From dwilllmann at sysmocom.de Thu Oct 8 14:10:25 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Thu, 8 Oct 2015 16:10:25 +0200 Subject: [openbsc 3/4] libmsc: Use RAND_bytes to choose auth tuple In-Reply-To: References: Message-ID: From: Daniel Willmann --- openbsc/src/libmsc/auth.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openbsc/src/libmsc/auth.c b/openbsc/src/libmsc/auth.c index 10d8edf..93ee71f 100644 --- a/openbsc/src/libmsc/auth.c +++ b/openbsc/src/libmsc/auth.c @@ -27,6 +27,8 @@ #include +#include + #include @@ -100,8 +102,11 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple, /* Generate a new one */ atuple->use_count = 1; atuple->key_seq = (atuple->key_seq + 1) % 7; - for (i=0; irand); i++) - atuple->rand[i] = random() & 0xff; + + if (RAND_bytes(atuple->rand, sizeof(atuple->rand)) != 1) { + LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n"); + return -1; + } switch (ainfo.auth_algo) { case AUTH_ALGO_NONE: -- 2.1.4 From dwilllmann at sysmocom.de Thu Oct 8 14:10:24 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Thu, 8 Oct 2015 16:10:24 +0200 Subject: [openbsc 2/4] gprs: Use RAND_bytes for p-tmsi In-Reply-To: References: Message-ID: From: Daniel Willmann --- openbsc/src/gprs/gprs_sgsn.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index f40de0b..2af1e97 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -525,7 +525,9 @@ uint32_t sgsn_alloc_ptmsi(void) int max_retries = 100; restart: - ptmsi = rand(); + if (RAND_bytes(&ptmsi, sizeof(ptmsi)) != 1) + goto failed; + /* Enforce that the 2 MSB are set without loosing the distance between * identical values. Since rand() has no duplicate values within a * period (because the size of the state is the same like the size of -- 2.1.4 From dwilllmann at sysmocom.de Thu Oct 8 14:10:23 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Thu, 8 Oct 2015 16:10:23 +0200 Subject: [openbsc 1/4] libmsc: Use RAND_bytes when choosing a tmsi In-Reply-To: References: Message-ID: <4535ddc5c828125fe8df7ee0e415413d742b66c7.1444298449.git.daniel@totalueberwachung.de> From: Daniel Willmann Require openssl version to be >= 0.9.5 because we rely on the RAND_bytes return value. --- openbsc/configure.ac | 2 +- openbsc/src/libmsc/Makefile.am | 2 +- openbsc/src/libmsc/db.c | 7 ++++++- openbsc/src/osmo-nitb/Makefile.am | 2 +- openbsc/tests/channel/Makefile.am | 2 +- openbsc/tests/db/Makefile.am | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openbsc/configure.ac b/openbsc/configure.ac index 78302dd..fc30b5e 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -27,13 +27,13 @@ PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.7.0) PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.2.0) PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.6.4) PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.0.1) +PKG_CHECK_MODULES(LIBCRYPTO, libcrypto >= 0.9.5) # Enabke/disable the NAT? AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])], [osmo_ac_build_nat="$enableval"],[osmo_ac_build_nat="no"]) if test "$osmo_ac_build_nat" = "yes" ; then PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2) - PKG_CHECK_MODULES(LIBCRYPTO, libcrypto) fi AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes") AC_SUBST(osmo_ac_build_nat) diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index aa7d8ae..18bfa0c 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) \ - $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) + $(LIBOSMOABIS_CFLAGS) $(COVERAGE_CFLAGS) $(LIBCRYPTO_CFLAGS) noinst_HEADERS = meas_feed.h diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c index 035202d..faae982 100644 --- a/openbsc/src/libmsc/db.c +++ b/openbsc/src/libmsc/db.c @@ -38,6 +38,8 @@ #include #include +#include + /* Semi-Private-Interface (SPI) for the subscriber code */ void subscr_direct_free(struct gsm_subscriber *subscr); @@ -1194,7 +1196,10 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber) char *tmsi_quoted; for (;;) { - subscriber->tmsi = rand(); + if (RAND_bytes(&subscriber->tmsi, sizeof(subscriber->tmsi)) != 1) { + LOGP(DDB, LOGL_ERROR, "RAND_bytes failed\n"); + return 1; + } if (subscriber->tmsi == GSM_RESERVED_TMSI) continue; diff --git a/openbsc/src/osmo-nitb/Makefile.am b/openbsc/src/osmo-nitb/Makefile.am index 57a9284..d3b97f8 100644 --- a/openbsc/src/osmo-nitb/Makefile.am +++ b/openbsc/src/osmo-nitb/Makefile.am @@ -16,4 +16,4 @@ osmo_nitb_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -ldbi $(LIBCRYPT) \ $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOCTRL_LIBS) $(LIBOSMOABIS_LIBS) $(LIBSMPP34_LIBS) + $(LIBOSMOCTRL_LIBS) $(LIBOSMOABIS_LIBS) $(LIBSMPP34_LIBS) $(LIBCRYPTO_LIBS) diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am index 519efbd..51b2f83 100644 --- a/openbsc/tests/channel/Makefile.am +++ b/openbsc/tests/channel/Makefile.am @@ -11,4 +11,4 @@ channel_test_LDADD = \ $(top_builddir)/src/libmsc/libmsc.a \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) \ - -ldbi $(LIBOSMOGSM_LIBS) + -ldbi $(LIBOSMOGSM_LIBS) $(LIBCRYPTO_LIBS) diff --git a/openbsc/tests/db/Makefile.am b/openbsc/tests/db/Makefile.am index 647b519..be3af5f 100644 --- a/openbsc/tests/db/Makefile.am +++ b/openbsc/tests/db/Makefile.am @@ -13,5 +13,5 @@ db_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libtrau/libtrau.a \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) $(LIBOSMOABIS_LIBS) \ - $(LIBOSMOGSM_LIBS) $(LIBSMPP34_LIBS) $(LIBOSMOVTY_LIBS) -ldbi + $(LIBOSMOGSM_LIBS) $(LIBSMPP34_LIBS) $(LIBOSMOVTY_LIBS) $(LIBCRYPTO_LIBS) -ldbi -- 2.1.4 From holger at freyther.de Thu Oct 8 14:45:20 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 8 Oct 2015 16:45:20 +0200 Subject: [PATCH 6/6] osmux: Remember the allocated CID and make sure it is release In-Reply-To: <1443950574-75194-6-git-send-email-holger@freyther.de> References: <1443950574-75194-1-git-send-email-holger@freyther.de> <1443950574-75194-6-git-send-email-holger@freyther.de> Message-ID: > On 04 Oct 2015, at 11:22, Holger Hans Peter Freyther wrote: > > > + uint8_t allocated_cid; ... > + endp->osmux.allocated_cid = -1; that doesn't mix too well. This means I assigned 255 to the value and then we have the next funny business in: char osmux_extension[strlen("X-Osmux: 255")]; buf[0] = buf[39] = '\0'; ret = sscanf(tok, "%*s %s", buf); if (ret != 1) { LOGP(DMGCP, LOGL_ERROR, "Failed to find Endpoint in: %s\n", tok); return; } if (osmux_cid >= 0) sprintf(osmux_extension, "\nX-Osmux: %u", osmux_cid); 1.) osmux_extension doesn't account for the \n 2.) osmux_extension doesn't account for the \0 at the end of the string 3.) we use '%u' so nothing in this method checks if this is a uint8_t. I will increase the buffer a bit. This would have started to crash on tripple digit osmux cid's (so on setup of the 101st call). holger From laforge at gnumonks.org Thu Oct 8 15:00:08 2015 From: laforge at gnumonks.org (Harald Welte) Date: Thu, 8 Oct 2015 17:00:08 +0200 Subject: [PATCH 01/10] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20151008150007.GM4626@nataraja> Hi Neels, On Wed, Oct 07, 2015 at 04:18:19PM +0200, Neels Hofmeyr wrote: > +#define LOGERR(fmt, args...) \ > + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) > + > +#define LOG(fmt, args...) \ > + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) we typically don't do this in the Osmo* codebase,bt use the full statement. However, it is your choice. The problem I see with this is that you reduce/remove the flexibility of using multiplelog subsstems and levels. You more or less assume that there will always only be two log levels used, and all messages will use the same subsystem. Is that really the case? When the full statement is used everytime, it is also easier to later change / tune the logging levels of certain statements, which is typically what happens after you run it in production with thousands of messages flowing through and you see what kind of granularity makes sense. Also, I think in patch 10/10 you state 'add debug messages' but then use the LOG() macro. So in fact you are adding NOTICE messages, not DEBUG messages. So either of the two statements is wrong. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Thu Oct 8 22:25:15 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 9 Oct 2015 00:25:15 +0200 Subject: [PATCH 4/8] oap: implement initial OAP API. In-Reply-To: <85E056D8-E24E-4B47-9F2B-724BD54FF6F1@freyther.de> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> <85E056D8-E24E-4B47-9F2B-724BD54FF6F1@freyther.de> Message-ID: <20151008222515.GA3991@dub5> On Wed, Oct 07, 2015 at 07:16:58PM +0200, Holger Freyther wrote: > > +static int oap_evaluate_challenge(const struct oap_state *state, > > + const uint8_t *rx_random, > > + const uint8_t *rx_autn, > > + uint8_t *tx_xres) > > +{ > > > > + OSMO_ASSERT(sizeof(auth.u.umts.k) == sizeof(state->secret_k)); > > + OSMO_ASSERT(sizeof(auth.u.umts.opc) == sizeof(state->secret_opc)); > > static assert? erm, that's a bit dumb indeed. I do feel more warm and fuzzy with it around somewhere. Can I put it in oap_init()? > > + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); > > + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); > > + memset(auth.u.umts.amf, 0, 2); > > sizeof? I picked it up from some other code around. Kindly elaborate on the question..? > > + auth.u.umts.sqn = 42; /* TODO */ > > In three years we wonder what the todo is. I think it is a good habbit to add > a short summary what we want to do. I think it's pretty much right in every crypto face. The sequence nr is constant! let me out! ;) but ok BTW we talked about whether OAP is finished, but indeed this part is missing. > > +struct msgb *oap_encoded(const struct oap_message *oap_msg) > > encode? Sure it is encoded after the function is done but it triggers the > encoding? It takes care of allocation in The OAP Way (tm) (makes a msgb with given numbers) and conveniently does the obvious steps of encoding an oap_msg struct. It encodes. trigger? > > +{ > > +int oap_register(struct oap_state *state, struct msgb **msg_tx) > > return the struct msgb*? If it is NULL you already know it didnt't work > and the -1/0 carry as much value right now? At the time of writing I kept the option of returning distinct error codes. This just needs a bool apparently, that's correct. But in fact I would like to keep the msg_tx analogy to oap_handle(). > > + case OAP_MSGT_REGISTER_RESULT: > > + // successfully registered! > > no C99 comments (sorry to have away the method again) I don't understand "have away the method". But will fix the comment. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Oct 8 23:44:54 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 9 Oct 2015 01:44:54 +0200 Subject: osmo_loadXXbe_ext -- was: [PATCH 1/8] libcommon: soak up three static functions. Message-ID: <20151008234454.GB3991@dub5> > > +uint64_t decode_big_endian(const uint8_t *data, size_t data_len) > > +uint8_t *encode_big_endian(uint64_t value, size_t data_len) > have you looked at osmo_load64le_ext of libosmocore? I think you don't need > these routines. and it applies to GSUP too. Ah, nice. Hadn't seen those yet. Oh well, I notice that the decode_big_endian() is more elegant to use than osmo_load64be_ext(), since passing a length of less than 8 bytes to decode_big_endian() writes the N least significant bytes, and allows this: uint16_t val; val = decode_big_endian(buf, sizeof(val)); It has the desired result. However this: uint16_t val; val = osmo_load64be_ext(buf, sizeof(val)); will write the bytes bound to the "wrong", most significant end of the uint64_t, and only zero is written to val. So I would need to explicitly use osmo_load16be(). Which is less elegant, isn't it? Is it about performance? Would changing that behavior break anything besides bitrev_test.c? (It checks for exactly this ordering) I'd like to change only the osmo_loadXXbe_ext() function, so that it writes the least significant bytes, like decode_big_endian() does. But first, does it write the most significant end for a reason? If it doesn't, we don't actually need to generate functions for each integer size. Instead we can glorify the decode_big_endian() and encode_big_endian(), made threadsafe, to become osmo_load/store*(). Right?? Except for bitrev_test.c, all callers I found (in my currently cloned few source trees) use only the non-"_ext" functions, and would not be affected by the change at all. ~Neels P.S.: Holger, after I said to you that osmo_loadXXbe_ext is not less elegant after all, I re-re-realized that it is indeed still less elegant... -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Fri Oct 9 00:01:07 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 9 Oct 2015 02:01:07 +0200 Subject: [PATCH 01/10] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: <20151008150007.GM4626@nataraja> References: <1444227508-26608-1-git-send-email-nhofmeyr@sysmocom.de> <1444227508-26608-2-git-send-email-nhofmeyr@sysmocom.de> <20151008150007.GM4626@nataraja> Message-ID: <20151009000107.GC3991@dub5> On Thu, Oct 08, 2015 at 05:00:08PM +0200, Harald Welte wrote: > Hi Neels, > > On Wed, Oct 07, 2015 at 04:18:19PM +0200, Neels Hofmeyr wrote: > > +#define LOGERR(fmt, args...) \ > > + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) > > + > > +#define LOG(fmt, args...) \ > > + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) > > we typically don't do this in the Osmo* codebase,bt use the full > statement. However, it is your choice. > > The problem I see with this is that you reduce/remove the flexibility of > using multiplelog subsstems and levels. You more or less assume that > there will always only be two log levels used, and all messages will use > the same subsystem. Is that really the case? It's intended as a per-C-file local definition just to reduce repetition. If a file needs another log level (more than once), I intend to create another LOGxxx #define; but never in an h. LOGP() is also available. > When the full statement is used everytime, it is also easier to later > change / tune the logging levels of certain statements, which is > typically what happens after you run it in production with thousands of > messages flowing through and you see what kind of granularity makes > sense. ok, I see. I'll drop them as I go, then. > Also, I think in patch 10/10 you state 'add debug messages' but then > use the LOG() macro. So in fact you are adding NOTICE messages, not > DEBUG messages. So either of the two statements is wrong. That's right. Most current LOG()s are actually not intended to live past the commit that concludes GTP transcoding, fairly soon. That's what I meant by debug, really. Thanks! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Fri Oct 9 12:00:41 2015 From: laforge at gnumonks.org (Harald Welte) Date: Fri, 9 Oct 2015 14:00:41 +0200 Subject: CANCELLED: Oct 15, 8pm / OSMUG: "Running OpenAirInterface" In-Reply-To: <20151003203905.GM29331@nataraja> References: <20151003203905.GM29331@nataraja> Message-ID: <20151009120041.GB4626@nataraja> Hi all! I'm sorry to announce that the OpenAirInterface presentation on October 15 has ben CANCELLED. The reason is some schedule changes imposed on the speaker. There is a chance that we will be able to re-schedule the event at some point in November. Once that has been cleared up, there will be a separate announcement. The next regular Osmocom Meeting Berlin is scheduled for October 21 at the usual location (CCC Berlin), looking forward to meeting you there. -- - Harald Welte ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Mon Oct 12 00:54:35 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 02:54:35 +0200 Subject: [PATCH 3/3] gtp.h: rename gsn_t.dublicate (->p). In-Reply-To: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444611275-2552-4-git-send-email-nhofmeyr@sysmocom.de> This is potentially breaking API compat. --- gtp/gtp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtp/gtp.h b/gtp/gtp.h index 7f8ec91..4f96015 100644 --- a/gtp/gtp.h +++ b/gtp/gtp.h @@ -276,7 +276,7 @@ struct gsn_t { uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */ uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */ uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */ - uint64_t dublicate; /* Number of dublicate or unsolicited replies */ + uint64_t duplicate; /* Number of duplicate or unsolicited replies */ uint64_t missing; /* Number of missing information field messages */ uint64_t incorrect; /* Number of incorrect information field messages */ uint64_t invalid; /* Number of invalid message format messages */ -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 00:54:33 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 02:54:33 +0200 Subject: [PATCH 1/3] gtp.c: improve an error log. In-Reply-To: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444611275-2552-2-git-send-email-nhofmeyr@sysmocom.de> It would print the memory location of the address buffer. Instead, print the first few hex values of the address buffer. --- gtp/gtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index cfce244..90e0326 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -741,7 +741,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, (*gsn)->err_socket++; LOGP(DLGTP, LOGL_ERROR, "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s\n", - (*gsn)->fd0, (unsigned long)&addr, sizeof(addr), + (*gsn)->fd0, *((unsigned long*)&addr), sizeof(addr), strerror(errno)); return -1; } -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 00:54:34 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 02:54:34 +0200 Subject: [PATCH 2/3] Rename gtp_dublicate, cosmetic. In-Reply-To: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444611275-2552-3-git-send-email-nhofmeyr@sysmocom.de> Fix spelling dublicate -> duplicate in comments and in (apparently only statically used) gtp_dublicate(). Add two TODO comments. Fix other spelling/punctuation and one numbering in comments. Remove an opening brace from a comment to not mix up cindent in vim. Break a long line. --- gtp/gtp.c | 38 ++++++++++++++++++++------------------ gtp/gtp.h | 4 ++-- sgsnemu/sgsnemu.c | 22 ++++++++++++++-------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index 90e0326..bf244dd 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -300,19 +300,19 @@ static uint32_t get_tei(void *pack) * requires the receiving GSN to send a response, with the same information * as in the original response. For most messages this happens automatically: * - * Echo: Automatically dublicates the original response + * Echo: Automatically duplicates the original response * Create pdp context: The SGSN may send create context request even if - * a context allready exist (imsi+nsapi?). This means that the reply will - automatically dublicate the original response. It might however have + * a context already exist (imsi+nsapi?). This means that the reply will + * automatically duplicate the original response. It might however have * side effects in the application which is asked twice to validate * the login. - * Update pdp context: Automatically dublicates the original response??? + * Update pdp context: Automatically duplicates the original response??? * Delete pdp context. Automatically in gtp0, but in gtp1 will generate * a nonexist reply message. * * The correct solution will be to make a queue containing response messages. * This queue should be checked whenever a request is received. If the - * response is allready in the queue that response should be transmitted. + * response is already in the queue that response should be transmitted. * It should be possible to find messages in this queue on the basis of * the sequence number and peer GSN IP address (The sequense number is unique * within each path). This need to be implemented by a hash table. Furthermore @@ -609,7 +609,7 @@ int gtp_notification(struct gsn_t *gsn, int version, return 0; } -int gtp_dublicate(struct gsn_t *gsn, int version, +int gtp_duplicate(struct gsn_t *gsn, int version, struct sockaddr_in *peer, uint16_t seq) { struct qmsg_t *qmsg; @@ -871,8 +871,8 @@ int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer, int fd, void *pack, unsigned len) { - /* Check if it was a dublicate request */ - if (!gtp_dublicate(gsn, 0, peer, get_seq(pack))) + /* Check if it was a duplicate request */ + if (!gtp_duplicate(gsn, 0, peer, get_seq(pack))) return 0; /* Send off reply to request */ @@ -1256,13 +1256,15 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version, uint8_t linked_nsapi = 0; struct pdp_t *linked_pdp = NULL; - if (!gtp_dublicate(gsn, version, peer, seq)) + /* TODO describe what this is all about: */ + if (!gtp_duplicate(gsn, version, peer, seq)) return 0; pdp = &pdp_buf; memset(pdp, 0, sizeof(struct pdp_t)); if (version == 0) { + /* TODO code dup: get_tid() */ uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid); pdp_set_imsi_nsapi(pdp, tid); @@ -1509,7 +1511,7 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version, if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) { /* Found old pdp with same tid. Now the voodoo begins! */ /* 09.60 / 29.060 allows create on existing context to "steal" */ - /* the context which was allready established */ + /* the context which was already established */ /* We check that the APN, selection mode and MSISDN is the same */ DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n"); if ((pdp->apn_req.l == pdp_old->apn_req.l) @@ -1951,9 +1953,9 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version, uint64_t imsi; uint8_t nsapi; - /* Is this a dublicate ? */ - if (!gtp_dublicate(gsn, version, peer, seq)) { - return 0; /* We allready send of response once */ + /* Is this a duplicate ? */ + if (!gtp_duplicate(gsn, version, peer, seq)) { + return 0; /* We already sent of response once */ } /* Decode information elements */ @@ -2083,7 +2085,7 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version, } /* TEIC (conditional) */ - /* If TEIC is not included it means that we have allready received it */ + /* If TEIC is not included it means that we have already received it */ /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */ /* all updated contexts, or only for one of the linked contexts */ gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn); @@ -2422,9 +2424,9 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version, int n; int count = 0; - /* Is this a dublicate ? */ - if (!gtp_dublicate(gsn, version, peer, seq)) { - return 0; /* We allready send off response once */ + /* Is this a duplicate ? */ + if (!gtp_duplicate(gsn, version, peer, seq)) { + return 0; /* We already sent off response once */ } /* Find the linked context in question */ @@ -2636,7 +2638,7 @@ int gtp_gpdu_ind(struct gsn_t *gsn, int version, return 0; } -/* Receives GTP packet and sends off for further processing +/* Receives GTP packet and sends off for further processing. * Function will check the validity of the header. If the header * is not valid the packet is either dropped or a version not * supported is returned to the peer. diff --git a/gtp/gtp.h b/gtp/gtp.h index 76c967b..7f8ec91 100644 --- a/gtp/gtp.h +++ b/gtp/gtp.h @@ -147,7 +147,7 @@ struct ul16_t; struct gtp0_header { /* Descriptions from 3GPP 09.60 */ uint8_t flags; /* 01 bitfield, with typical values */ - /* 000..... Version: 1 (0) */ + /* 000..... Version: 0 */ /* ...1111. Spare (7) */ /* .......0 SNDCP N-PDU Number flag (0) */ uint8_t type; /* 02 Message type. T-PDU = 0xff */ @@ -223,7 +223,7 @@ union gtp_packet { * application this struct is provided in order to store all * relevant information related to the gsn. * - * Note that this does not include information storage for ' + * Note that this does not include information storage for * each pdp context. This is stored in another struct. *************************************************************/ diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index 5b56751..a9c706f 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -1569,7 +1569,7 @@ int main(int argc, char **argv) 512 = Flat rate, 256 = Hot billing */ /* Create context */ - /* We send this of once. Retransmissions are handled by gtplib */ + /* We send this off once. Retransmissions are handled by gtplib */ gtp_create_context_req(gsn, pdp, &iparr[n]); } @@ -1577,9 +1577,9 @@ int main(int argc, char **argv) printf("Waiting for response from ggsn........\n\n"); - /******************************************************************/ + /******************************************************************/ /* Main select loop */ - /******************************************************************/ + /******************************************************************/ while ((0 != state) && (5 != state)) { @@ -1613,7 +1613,7 @@ int main(int argc, char **argv) state = 3; } - /* Send off disconnect */ + /* Send disconnect */ if (3 == state) { state = 4; stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */ @@ -1628,17 +1628,23 @@ int main(int argc, char **argv) } } - /* Send of ping packets */ + /* Send ping packets */ diff = 0; while ((diff <= 0) && /* Send off an ICMP ping packet */ - /*if ( */ (options.pinghost.s_addr) && (2 == state) && + /*if */ (options.pinghost.s_addr) && (2 == state) && ((pingseq < options.pingcount) - || (options.pingcount == 0))) { + || (options.pingcount == 0))) + { if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */ gettimeofday(&tv, &tz); - diff = 1000000 / options.pingrate * pingseq - 1000000 * (tv.tv_sec - firstping.tv_sec) - (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */ + + /* Microseconds safe up to 500 sec */ + diff = 1e6 / options.pingrate * pingseq + - 1e6 * (tv.tv_sec - firstping.tv_sec) + - (tv.tv_usec - firstping.tv_usec); + if (diff <= 0) { if (options.debug) printf("Create_ping %d\n", diff); -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 00:54:32 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 02:54:32 +0200 Subject: openggsn cosmetics Message-ID: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> These patches fix some things that hurt my eyes. The renames from dublicate to duplicate may theoretically break API compat, but I could find no affected callers. These are not required, feel free to veto... ~Neels From holger at freyther.de Mon Oct 12 07:01:57 2015 From: holger at freyther.de (Holger Freyther) Date: Mon, 12 Oct 2015 09:01:57 +0200 Subject: [openbsc 1/4] libmsc: Use RAND_bytes when choosing a tmsi In-Reply-To: <4535ddc5c828125fe8df7ee0e415413d742b66c7.1444298449.git.daniel@totalueberwachung.de> References: <4535ddc5c828125fe8df7ee0e415413d742b66c7.1444298449.git.daniel@totalueberwachung.de> Message-ID: <0C1E80E5-3D17-490C-979B-F9BDC61215E1@freyther.de> > On 08 Oct 2015, at 16:10, Daniel Willmann wrote: > > > for (;;) { > - subscriber->tmsi = rand(); > + if (RAND_bytes(&subscriber->tmsi, sizeof(subscriber->tmsi)) != 1) { > + LOGP(DDB, LOGL_ERROR, "RAND_bytes failed\n"); db.c:1199:18: warning: passing argument 1 of ?RAND_bytes? from incompatible pointer type if (RAND_bytes(&subscriber->tmsi, sizeof(subscriber->tmsi)) != 1) { :} From holger at freyther.de Mon Oct 12 07:22:53 2015 From: holger at freyther.de (Holger Freyther) Date: Mon, 12 Oct 2015 09:22:53 +0200 Subject: [PATCH 1/3] gtp.c: improve an error log. In-Reply-To: <1444611275-2552-2-git-send-email-nhofmeyr@sysmocom.de> References: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> <1444611275-2552-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: > On 12 Oct 2015, at 02:54, Neels Hofmeyr wrote: > > diff --git a/gtp/gtp.c b/gtp/gtp.c > index cfce244..90e0326 100644 > --- a/gtp/gtp.c > +++ b/gtp/gtp.c > @@ -741,7 +741,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, > (*gsn)->err_socket++; > LOGP(DLGTP, LOGL_ERROR, > "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s\n", > - (*gsn)->fd0, (unsigned long)&addr, sizeof(addr), > + (*gsn)->fd0, *((unsigned long*)&addr), sizeof(addr), did you run into this? At first I wanted to say then use osmo_hexdump but as this is an in_addr.. a user wants to see the IP addr and the port number that could not be bound to. Could you improve this? holger From holger at freyther.de Mon Oct 12 07:59:47 2015 From: holger at freyther.de (Holger Freyther) Date: Mon, 12 Oct 2015 09:59:47 +0200 Subject: [openbsc 2/4] gprs: Use RAND_bytes for p-tmsi In-Reply-To: References: Message-ID: <04EC40DF-796E-4BF1-88D2-634CBA9E4CF5@freyther.de> > On 08 Oct 2015, at 16:10, Daniel Willmann wrote: > > From: Daniel Willmann * missing include for the RAND_bytes prototype * missing cat of ptmsi * missing linking to LIBCRYPTO_LIBS * missing linking to LIBCRYPTO_LIBS in the test and after that.. the sgsn tests fail because of the TMSI situation. I have now reverted the code. Please look at it with Jacob and extract the TMSI from the SGSN state instead of resetting the RNG in the test. holger From nhofmeyr at sysmocom.de Mon Oct 12 08:46:04 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 10:46:04 +0200 Subject: [PATCH 1/3] gtp.c: improve an error log. In-Reply-To: References: <1444611275-2552-1-git-send-email-nhofmeyr@sysmocom.de> <1444611275-2552-2-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20151012084604.GA1518@dub5> On Mon, Oct 12, 2015 at 09:22:53AM +0200, Holger Freyther wrote: > > > On 12 Oct 2015, at 02:54, Neels Hofmeyr wrote: > > > > diff --git a/gtp/gtp.c b/gtp/gtp.c > > index cfce244..90e0326 100644 > > --- a/gtp/gtp.c > > +++ b/gtp/gtp.c > > @@ -741,7 +741,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, > > (*gsn)->err_socket++; > > LOGP(DLGTP, LOGL_ERROR, > > "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s\n", > > - (*gsn)->fd0, (unsigned long)&addr, sizeof(addr), > > + (*gsn)->fd0, *((unsigned long*)&addr), sizeof(addr), > > did you run into this? yea, during testing, when the port was already bound or the address was invalid. I was puzzled by the hex value and figured that this would have been the intended thing to print. But it's not great at all. > a user wants to see the IP addr and the port number that could not be > bound to. Could you improve this? probably, yes... I'll come back to this later. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Oct 12 09:13:30 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:13:30 +0200 Subject: [PATCH 4/8] oap: implement initial OAP API. In-Reply-To: <20151008222515.GA3991@dub5> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> <85E056D8-E24E-4B47-9F2B-724BD54FF6F1@freyther.de> <20151008222515.GA3991@dub5> Message-ID: <20151012091330.GC1518@dub5> On Fri, Oct 09, 2015 at 12:25:15AM +0200, Neels Hofmeyr wrote: > > > + memset(auth.u.umts.amf, 0, 2); > > > > sizeof? > > I picked it up from some other code around. Kindly elaborate on the > question..? I get it now, you mean s/2/sizeof(auth.u.umts.amf). This is copy-pasted from somewhere, that's why it says 2 so far. Will also change the 0 to '\0'. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Oct 12 09:16:13 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:16:13 +0200 Subject: [PATCH 4/8] oap: implement initial OAP API. In-Reply-To: <20151008222515.GA3991@dub5> References: <1443705837-25727-1-git-send-email-nhofmeyr@sysmocom.de> <1443705837-25727-5-git-send-email-nhofmeyr@sysmocom.de> <85E056D8-E24E-4B47-9F2B-724BD54FF6F1@freyther.de> <20151008222515.GA3991@dub5> Message-ID: <20151012091613.GD1518@dub5> On Fri, Oct 09, 2015 at 12:25:15AM +0200, Neels Hofmeyr wrote: > On Wed, Oct 07, 2015 at 07:16:58PM +0200, Holger Freyther wrote: > > > +static int oap_evaluate_challenge(const struct oap_state *state, > > > + const uint8_t *rx_random, > > > + const uint8_t *rx_autn, > > > + uint8_t *tx_xres) > > > +{ > > > > > > + OSMO_ASSERT(sizeof(auth.u.umts.k) == sizeof(state->secret_k)); > > > + OSMO_ASSERT(sizeof(auth.u.umts.opc) == sizeof(state->secret_opc)); > > > > static assert? For the record: see osmo_static_assert() in libosmocore's utils.h. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Oct 12 09:57:34 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:34 +0200 Subject: [PATCH 2/6] oap: implement initial OAP API. In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-3-git-send-email-nhofmeyr@sysmocom.de> Add oap.[hc] and oap_messages.[hc]. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/Makefile.am | 3 +- openbsc/include/openbsc/oap.h | 78 ++++++++++ openbsc/include/openbsc/oap_messages.h | 70 +++++++++ openbsc/src/gprs/Makefile.am | 3 +- openbsc/src/gprs/oap.c | 256 +++++++++++++++++++++++++++++++++ openbsc/src/gprs/oap_messages.c | 178 +++++++++++++++++++++++ 6 files changed, 586 insertions(+), 2 deletions(-) create mode 100644 openbsc/include/openbsc/oap.h create mode 100644 openbsc/include/openbsc/oap_messages.h create mode 100644 openbsc/src/gprs/oap.c create mode 100644 openbsc/src/gprs/oap_messages.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 828f5bd..8a074c2 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -16,7 +16,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ - gprs_gsup_client.h bsc_msg_filter.h + gprs_gsup_client.h bsc_msg_filter.h \ + oap.h oap_messages.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/oap.h b/openbsc/include/openbsc/oap.h new file mode 100644 index 0000000..2370cbe --- /dev/null +++ b/openbsc/include/openbsc/oap.h @@ -0,0 +1,78 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +struct msgb; +struct oap_message; + +/* This is the config part for vty. It is essentially copied in oap_state, + * where values are copied over once the config is considered valid. */ +struct oap_config { + uint16_t client_id; + int secret_k_present; + uint8_t secret_k[16]; + int secret_opc_present; + uint8_t secret_opc[16]; +}; + +/* The runtime state of the OAP client. client_id and the secrets are in fact + * duplicated from oap_config, so that a separate validation of the config data + * is possible, and so that only a struct oap_state* is passed around. */ +struct oap_state { + enum { + OAP_UNINITIALIZED = 0, /* just allocated. */ + OAP_DISABLED, /* disabled by config. */ + OAP_INITIALIZED, /* enabled, config is valid. */ + OAP_REQUESTED_CHALLENGE, + OAP_SENT_CHALLENGE_RESULT, + OAP_REGISTERED + } state; + uint16_t client_id; + uint8_t secret_k[16]; + uint8_t secret_opc[16]; + int registration_failures; +}; + +/* From config, initialize state. Return 0 on success. */ +int oap_init(struct oap_config *config, struct oap_state *state); + +/* Construct an OAP registration message and return in *msg_tx. Use + * state->client_id and update state->state. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_register(struct oap_state *state, struct msgb **msg_tx); + +/* Decode and act on a received OAP message msg_rx. Update state->state. If a + * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP + * server (and freed) by the caller. The received msg_rx is not freed. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb **msg_tx); + +/* Allocate a msgb and in it, return the encoded oap_msg. Return NULL on + * error. (Like oap_encode(), but also allocates a msgb.) + * About the name: the idea is do_something(oap_encoded(my_struct)) */ +struct msgb *oap_encoded(const struct oap_message *oap_msg); + diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h new file mode 100644 index 0000000..a7a254c --- /dev/null +++ b/openbsc/include/openbsc/oap_messages.h @@ -0,0 +1,70 @@ +/* Osmocom Authentication Protocol message encoder/decoder */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include +#include +#include + +/* Some numbers are out of sequence because (so far) they match gprs_gsup_iei. + */ +enum oap_iei { + OAP_CAUSE_IE = 0x02, + OAP_RAND_IE = 0x20, + OAP_AUTN_IE = 0x23, + OAP_XRES_IE = 0x24, + OAP_AUTS_IE = 0x25, + OAP_CLIENT_ID_IE = 0x30, +}; + +enum oap_message_type { + OAP_MSGT_REGISTER_REQUEST = 0b00000100, + OAP_MSGT_REGISTER_ERROR = 0b00000101, + OAP_MSGT_REGISTER_RESULT = 0b00000110, + + OAP_MSGT_CHALLENGE_REQUEST = 0b00001000, + OAP_MSGT_CHALLENGE_ERROR = 0b00001001, + OAP_MSGT_CHALLENGE_RESULT = 0b00001010, + + OAP_MSGT_SYNC_REQUEST = 0b00001100, + OAP_MSGT_SYNC_ERROR = 0b00001101, + OAP_MSGT_SYNC_RESULT = 0b00001110, +}; + +struct oap_message { + enum oap_message_type message_type; + enum gsm48_gmm_cause cause; + uint16_t client_id; + int rand_present; + uint8_t rand[16]; + int autn_present; + uint8_t autn[16]; + int xres_present; + uint8_t xres[8]; + int auts_present; + uint8_t auts[16]; +}; + +int oap_decode(const uint8_t *data, size_t data_len, + struct oap_message *oap_msg); +void oap_encode(struct msgb *msg, const struct oap_message *oap_msg); + diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f46a402..0952d41 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -27,7 +27,8 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ gprs_llc.c gprs_llc_parse.c gprs_llc_vty.c crc24.c \ sgsn_ctrl.c sgsn_auth.c gprs_subscriber.c \ gprs_gsup_messages.c gprs_utils.c gprs_gsup_client.c \ - gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c + gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c \ + oap.c oap_messages.c osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) -lrt diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c new file mode 100644 index 0000000..1426702 --- /dev/null +++ b/openbsc/src/gprs/oap.c @@ -0,0 +1,256 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include +#include + +int oap_init(struct oap_config *config, struct oap_state *state) +{ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + if (config->client_id == 0) + goto disable; + + if (config->secret_k_present == 0) { + LOGP(DGPRS, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n"); + goto disable; + } + + if (config->secret_opc_present == 0) { + LOGP(DGPRS, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n"); + goto disable; + } + + state->client_id = config->client_id; + memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); + memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); + state->state = OAP_INITIALIZED; + return 0; + +disable: + state->state = OAP_DISABLED; + return 0; +} + +/* From the given state and received RAND and AUTN octets, validate the + * server's authenticity and formulate the matching milenage reply octets in + * *tx_xres. The state is not modified. + * On success, and if tx_res is not NULL, exactly 8 octets will be written to + * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8 + * octets. The caller will want to send XRES back to the server in a challenge + * response message and update the state. + * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail + * the authentication check; -3 for any other errors. */ +static int oap_evaluate_challenge(const struct oap_state *state, + const uint8_t *rx_random, + const uint8_t *rx_autn, + uint8_t *tx_xres) +{ + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k) + == sizeof(state->secret_k), _secret_k_size_match); + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc) + == sizeof(state->secret_opc), _secret_opc_size_match); + + switch(state->state) { + case OAP_UNINITIALIZED: + case OAP_DISABLED: + return -1; + default: + break; + } + + struct osmo_auth_vector vec; + + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_UMTS, + .algo = OSMO_AUTH_ALG_MILENAGE, + }; + + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); + memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf)); + auth.u.umts.sqn = 42; /* TODO use incrementing sequence nr */ + + memset(&vec, 0, sizeof(vec)); + osmo_auth_gen_vec(&vec, &auth, rx_random); + + if (vec.res_len != 8) { + LOGP(DGPRS, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n", + vec.res_len); + return -3; + } + + if (constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { + LOGP(DGPRS, LOGL_ERROR, "OAP: AUTN mismatch!\n"); + LOGP(DGPRS, LOGL_INFO, "OAP: AUTN from server: %s\n", + osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); + LOGP(DGPRS, LOGL_INFO, "OAP: AUTN expected: %s\n", + osmo_hexdump_nospc(vec.autn, sizeof(vec.autn))); + return -2; + } + + if (tx_xres != NULL) + memcpy(tx_xres, vec.res, 8); + return 0; +} + +struct msgb *oap_encoded(const struct oap_message *oap_msg) +{ + struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); + OSMO_ASSERT(msg); + oap_encode(msg, oap_msg); + return msg; +} + +/* Create a new msgb containing an OAP registration message. + * On error, return NULL. */ +static struct msgb* oap_msg_register(uint16_t client_id) +{ + if (client_id < 1) { + LOGP(DGPRS, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); + return NULL; + } + + struct oap_message oap_msg = {0}; + oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; + oap_msg.client_id = client_id; + return oap_encoded(&oap_msg); +} + +int oap_register(struct oap_state *state, struct msgb **msg_tx) +{ + *msg_tx = oap_msg_register(state->client_id); + if (!(*msg_tx)) + return -1; + + state->state = OAP_REQUESTED_CHALLENGE; + return 0; +} + +/* Create a new msgb containing an OAP challenge response message. + * xres must point at 8 octets to return as challenge response. + * On error, return NULL. */ +static struct msgb* oap_msg_challenge_response(uint8_t *xres) +{ + struct oap_message oap_reply = {0}; + + oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; + memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); + oap_reply.xres_present = 1; + return oap_encoded(&oap_reply); +} + +static int handle_challenge(struct oap_state *state, + struct oap_message *oap_rx, + struct msgb **msg_tx) +{ + int rc; + if (!(oap_rx->rand_present && oap_rx->autn_present)) { + LOGP(DGPRS, LOGL_ERROR, + "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", + oap_rx->rand_present, oap_rx->autn_present); + rc = -2; + goto failure; + } + + uint8_t xres[8]; + rc = oap_evaluate_challenge(state, + oap_rx->rand, + oap_rx->autn, + xres); + if (rc < 0) + goto failure; + + *msg_tx = oap_msg_challenge_response(xres); + if ((*msg_tx) == NULL) { + rc = -1; + goto failure; + } + + state->state = OAP_SENT_CHALLENGE_RESULT; + return 0; + +failure: + OSMO_ASSERT(rc < 0); + state->state = OAP_INITIALIZED; + return rc; +} + +int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb **msg_tx) +{ + *msg_tx = NULL; + + uint8_t *data = msgb_l2(msg_rx); + size_t data_len = msgb_l2len(msg_rx); + int rc = 0; + + struct oap_message oap_msg = {0}; + + OSMO_ASSERT(data); + + rc = oap_decode(data, data_len, &oap_msg); + if (rc < 0) { + LOGP(DGPRS, LOGL_ERROR, + "Decoding OAP message failed with error '%s' (%d)\n", + get_value_string(gsm48_gmm_cause_names, -rc), -rc); + return -10; + } + + switch (oap_msg.message_type) { + case OAP_MSGT_CHALLENGE_REQUEST: + return handle_challenge(state, &oap_msg, msg_tx); + + case OAP_MSGT_REGISTER_RESULT: + /* successfully registered */ + state->state = OAP_REGISTERED; + break; + + case OAP_MSGT_REGISTER_ERROR: + LOGP(DGPRS, LOGL_ERROR, + "OAP registration failed\n"); + state->state = OAP_INITIALIZED; + if (state->registration_failures < 3) { + state->registration_failures ++; + return oap_register(state, msg_tx); + } + return -11; + + case OAP_MSGT_REGISTER_REQUEST: + case OAP_MSGT_CHALLENGE_RESULT: + LOGP(DGPRS, LOGL_ERROR, + "Received invalid OAP message type for OAP client side: %d\n", + (int)oap_msg.message_type); + return -12; + + default: + LOGP(DGPRS, LOGL_ERROR, + "Unknown OAP message type: %d\n", + (int)oap_msg.message_type); + return -13; + } + + return 0; +} diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c new file mode 100644 index 0000000..eb52053 --- /dev/null +++ b/openbsc/src/gprs/oap_messages.c @@ -0,0 +1,178 @@ +/* Osmocom Authentication Protocol message encoder/decoder */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include + +#include +#include + +#include + + +int oap_decode(const uint8_t *const_data, size_t data_len, + struct oap_message *oap_msg) +{ + int rc; + uint8_t tag; + /* the shift/match functions expect non-const pointers, but we'll + * either copy the data or cast pointers back to const before returning + * them + */ + uint8_t *data = (uint8_t *)const_data; + uint8_t *value; + size_t value_len; + + memset(oap_msg, 0, sizeof(*oap_msg)); + + /* message type */ + rc = gprs_shift_v_fixed(&data, &data_len, 1, &value); + if (rc < 0) + return -GMM_CAUSE_INV_MAND_INFO; + oap_msg->message_type = decode_big_endian(value, 1); + + /* specific parts */ + while (data_len > 0) { + enum oap_iei iei; + + rc = gprs_shift_tlv(&data, &data_len, &tag, &value, &value_len); + if (rc < 0) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + iei = tag; + + switch (iei) { + case OAP_CLIENT_ID_IE: + if (value_len != 2) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type client ID (%d) should be 2 octets, but has %d\n", + (int)iei, (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + + oap_msg->client_id = decode_big_endian(value, value_len); + + if (oap_msg->client_id == 0) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type client ID (%d): client ID must be nonzero.\n", + (int)iei); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + break; + + case OAP_AUTN_IE: + if (value_len != sizeof(oap_msg->autn)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type AUTN (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->autn), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->autn, value, value_len); + oap_msg->autn_present = value_len; + break; + + case OAP_RAND_IE: + if (value_len != sizeof(oap_msg->rand)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type RAND (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->rand), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->rand, value, value_len); + oap_msg->rand_present = value_len; + break; + + case OAP_XRES_IE: + if (value_len != sizeof(oap_msg->xres)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type XRES (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->xres), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->xres, value, value_len); + oap_msg->xres_present = value_len; + break; + + case OAP_AUTS_IE: + if (value_len != sizeof(oap_msg->auts)) { + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type AUTS (%d) should be %d octets, but has %d\n", + (int)iei, (int)sizeof(oap_msg->auts), (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + memcpy(oap_msg->auts, value, value_len); + oap_msg->auts_present = value_len; + break; + + case OAP_CAUSE_IE: + if (value_len > 1) { + LOGP(DGPRS, LOGL_ERROR, + "OAP cause may not exceed one octet, is %d", (int)value_len); + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + } + oap_msg->cause = *value; + break; + + default: + LOGP(DGPRS, LOGL_NOTICE, + "OAP IE type %d unknown\n", iei); + continue; + } + } + + return 0; +} + +void oap_encode(struct msgb *msg, const struct oap_message *oap_msg) +{ + uint8_t u8; + + /* generic part */ + OSMO_ASSERT(oap_msg->message_type); + msgb_v_put(msg, (uint8_t)oap_msg->message_type); + + /* specific parts */ + if ((u8 = oap_msg->cause)) + msgb_tlv_put(msg, OAP_CAUSE_IE, sizeof(u8), &u8); + + if (oap_msg->client_id > 0) + msgb_tlv_put(msg, OAP_CLIENT_ID_IE, sizeof(oap_msg->client_id), + encode_big_endian(oap_msg->client_id, sizeof(oap_msg->client_id))); + + if (oap_msg->rand_present) + msgb_tlv_put(msg, OAP_RAND_IE, sizeof(oap_msg->rand), oap_msg->rand); + + if (oap_msg->autn_present) + msgb_tlv_put(msg, OAP_AUTN_IE, sizeof(oap_msg->autn), oap_msg->autn); + + if (oap_msg->auts_present) + msgb_tlv_put(msg, OAP_AUTS_IE, sizeof(oap_msg->auts), oap_msg->auts); + + if (oap_msg->xres_present) + msgb_tlv_put(msg, OAP_XRES_IE, sizeof(oap_msg->xres), oap_msg->xres); + + msg->l2h = msg->data; +} + -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 09:57:35 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:35 +0200 Subject: [PATCH 3/6] oap: add oap testsuite skeleton In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-4-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/.gitignore | 1 + openbsc/configure.ac | 1 + openbsc/tests/Makefile.am | 2 +- openbsc/tests/oap/Makefile.am | 19 ++++++++++++++ openbsc/tests/oap/oap_test.c | 58 +++++++++++++++++++++++++++++++++++++++++++ openbsc/tests/oap/oap_test.ok | 2 ++ openbsc/tests/testsuite.at | 7 ++++++ 7 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/oap/Makefile.am create mode 100644 openbsc/tests/oap/oap_test.c create mode 100644 openbsc/tests/oap/oap_test.ok diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 2210c47..ca73db6 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -77,6 +77,7 @@ tests/trau/trau_test tests/mgcp/mgcp_transcoding_test tests/sgsn/sgsn_test tests/subscr/subscr_test +tests/oap/oap_test tests/atconfig tests/atlocal diff --git a/openbsc/configure.ac b/openbsc/configure.ac index fc30b5e..8b7ce62 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -209,6 +209,7 @@ AC_OUTPUT( tests/trau/Makefile tests/sgsn/Makefile tests/subscr/Makefile + tests/oap/Makefile doc/Makefile doc/examples/Makefile Makefile) diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 773830b..1b557d4 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr oap if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/oap/Makefile.am b/openbsc/tests/oap/Makefile.am new file mode 100644 index 0000000..e160902 --- /dev/null +++ b/openbsc/tests/oap/Makefile.am @@ -0,0 +1,19 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) + +EXTRA_DIST = oap_test.ok + +noinst_PROGRAMS = oap_test + +oap_test_SOURCES = oap_test.c + +oap_test_LDADD = \ + $(top_builddir)/src/gprs/oap.o \ + $(top_builddir)/src/gprs/oap_messages.o \ + $(top_builddir)/src/gprs/gprs_utils.o \ + $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + -lrt + diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c new file mode 100644 index 0000000..b03c8dc --- /dev/null +++ b/openbsc/tests/oap/oap_test.c @@ -0,0 +1,58 @@ +/* Test Osmocom Authentication Protocol */ +/* + * (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include + +#include +#include + +#include + + +static void test_oap(void) +{ + printf("not implemented\n"); +} + +static struct log_info_cat gprs_categories[] = { + [DGPRS] = { + .name = "DGPRS", + .description = "GPRS Packet Service", + .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) +{ + osmo_init_logging(&info); + + test_oap(); + printf("Done\n"); + + return 0; +} + diff --git a/openbsc/tests/oap/oap_test.ok b/openbsc/tests/oap/oap_test.ok new file mode 100644 index 0000000..e411ad9 --- /dev/null +++ b/openbsc/tests/oap/oap_test.ok @@ -0,0 +1,2 @@ +not implemented +Done diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 74aaef0..78aa47e 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -103,3 +103,10 @@ AT_CHECK([test "$enable_sgsn_test" != no || exit 77]) cat $abs_srcdir/sgsn/sgsn_test.ok > expout AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([oap]) +AT_KEYWORDS([oap]) +AT_CHECK([test "$enable_oap_test" != no || exit 77]) +cat $abs_srcdir/oap/oap_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/oap/oap_test], [], [expout], [ignore]) +AT_CLEANUP -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 09:57:36 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:36 +0200 Subject: [PATCH 4/6] oap: add OAP API test In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-5-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/tests/oap/oap_test.c | 193 +++++++++++++++++++++++++++++++++++++++++- openbsc/tests/oap/oap_test.ok | 7 +- 2 files changed, 195 insertions(+), 5 deletions(-) diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c index b03c8dc..9a2063b 100644 --- a/openbsc/tests/oap/oap_test.c +++ b/openbsc/tests/oap/oap_test.c @@ -27,10 +27,195 @@ #include - -static void test_oap(void) +static void test_oap_api(void) { - printf("not implemented\n"); + printf("Testing OAP API\n - Config parsing\n"); + + struct oap_config _config; + struct oap_config *config = &_config; + + struct oap_state _state; + struct oap_state *state = &_state; + + memset(config, 0, sizeof(*config)); + memset(state, 0, sizeof(*state)); + + OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16); + OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16); + + /* make sure filling with zeros means uninitialized */ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + /* invalid client_id and shared secret */ + config->client_id = 0; + config->secret_k_present = 0; + config->secret_opc_present = 0; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + /* reset state */ + memset(state, 0, sizeof(*state)); + + /* only client_id is invalid */ + config->client_id = 0; + config->secret_k_present = 1; + config->secret_opc_present = 1; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + /* valid id, but omitted shared_secret (1/2) */ + config->client_id = 12345; + config->secret_k_present = 0; + config->secret_opc_present = 1; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + /* valid id, but omitted shared_secret (2/2) */ + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 0; + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + + /* mint configuration */ + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 1; + /*config->secret_* buffers are still set from the top */ + OSMO_ASSERT( oap_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OAP_INITIALIZED); + + printf(" - AUTN failures\n"); + + struct oap_message oap_rx; + struct oap_message oap_tx; + struct msgb *msg_rx; + struct msgb *msg_tx; + + memset(&oap_rx, 0, sizeof(oap_rx)); + + /* Missing challenge data */ + oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST; + oap_rx.rand_present = 0; + oap_rx.autn_present = 0; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* AUTN missing */ + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + oap_rx.rand_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* RAND missing */ + oap_rx.rand_present = 0; + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.autn_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* wrong autn (by one bit) */ + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + osmo_hexparse("dec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.rand_present = 1; + oap_rx.autn_present = 1; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + /* all data correct */ + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + msg_rx = oap_encoded(&oap_rx); + + /* but refuse to evaluate in uninitialized state */ + OSMO_ASSERT(state->state == OAP_INITIALIZED); + + state->state = OAP_UNINITIALIZED; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1); + OSMO_ASSERT(!msg_tx); + + state->state = OAP_DISABLED; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1); + OSMO_ASSERT(!msg_tx); + + state->state = OAP_INITIALIZED; + + /* now everything is correct */ + printf(" - AUTN success\n"); + /* a successful return value here indicates correct autn */ + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + msgb_free(msg_rx); + + /* Expect the challenge response in msg_tx */ + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT); + OSMO_ASSERT(strcmp("e2d05b598c61d9ba", + osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres))) + == 0); + OSMO_ASSERT(state->state == OAP_SENT_CHALLENGE_RESULT); + msgb_free(msg_tx); + msg_tx = 0; + + struct oap_state saved_state = _state; + + printf(" - Registration failure\n"); + + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_ERROR; + oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC; + msg_rx = oap_encoded(&oap_rx); + + /* Receive registration error for the first time. */ + OSMO_ASSERT(state->registration_failures == 0); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(state->registration_failures == 1); + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST); + OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE); + msgb_free(msg_tx); + msg_tx = 0; + + /* Receive registration error for the Nth time. */ + state->registration_failures = 999; + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -11); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OAP_INITIALIZED); + msgb_free(msg_tx); + msg_tx = 0; + + msgb_free(msg_rx); + + printf(" - Registration success\n"); + + _state = saved_state; + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_RESULT; + msg_rx = oap_encoded(&oap_rx); + OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OAP_REGISTERED); + msgb_free(msg_rx); } static struct log_info_cat gprs_categories[] = { @@ -50,7 +235,7 @@ int main(int argc, char **argv) { osmo_init_logging(&info); - test_oap(); + test_oap_api(); printf("Done\n"); return 0; diff --git a/openbsc/tests/oap/oap_test.ok b/openbsc/tests/oap/oap_test.ok index e411ad9..2e9ecf0 100644 --- a/openbsc/tests/oap/oap_test.ok +++ b/openbsc/tests/oap/oap_test.ok @@ -1,2 +1,7 @@ -not implemented +Testing OAP API + - Config parsing + - AUTN failures + - AUTN success + - Registration failure + - Registration success Done -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 09:57:37 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:37 +0200 Subject: [PATCH 5/6] gsup/oap: add OAP to GSUP client. In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-6-git-send-email-nhofmeyr@sysmocom.de> Trigger an OAP registration upon IPA connect. Feed incoming OAP messages to oap_handle() and send replies returned by it. Add oap_config to sgsn_config (todo: vty). Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_gsup_client.h | 7 +++- openbsc/include/openbsc/sgsn.h | 3 ++ openbsc/src/gprs/gprs_gsup_client.c | 58 ++++++++++++++++++++++++++---- openbsc/src/gprs/gprs_subscriber.c | 3 +- openbsc/tests/sgsn/Makefile.am | 2 ++ 5 files changed, 65 insertions(+), 8 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_client.h b/openbsc/include/openbsc/gprs_gsup_client.h index 9537db4..ccfa388 100644 --- a/openbsc/include/openbsc/gprs_gsup_client.h +++ b/openbsc/include/openbsc/gprs_gsup_client.h @@ -23,6 +23,8 @@ #include +#include + #define GPRS_GSUP_RECONNECT_INTERVAL 10 #define GPRS_GSUP_PING_INTERVAL 20 @@ -38,6 +40,8 @@ struct gprs_gsup_client { gprs_gsup_read_cb_t read_cb; void *data; + struct oap_state oap_state; + struct osmo_timer_list ping_timer; struct osmo_timer_list connect_timer; int is_connected; @@ -46,7 +50,8 @@ struct gprs_gsup_client { struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb); + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config); void gprs_gsup_client_destroy(struct gprs_gsup_client *gsupc); int gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg); diff --git a/openbsc/include/openbsc/sgsn.h b/openbsc/include/openbsc/sgsn.h index d4f9913..2b1b97c 100644 --- a/openbsc/include/openbsc/sgsn.h +++ b/openbsc/include/openbsc/sgsn.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -61,6 +62,8 @@ struct sgsn_config { } timers; int dynamic_lookup; + + struct oap_config oap; }; struct sgsn_instance { diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c index 1f9e34c..a332fa7 100644 --- a/openbsc/src/gprs/gprs_gsup_client.c +++ b/openbsc/src/gprs/gprs_gsup_client.c @@ -108,6 +108,20 @@ static void gsup_client_send(struct gprs_gsup_client *gsupc, int proto_ext, stru /* msg_tx is now queued and will be freed. */ } +static void gsup_client_oap_register(struct gprs_gsup_client *gsupc) +{ + struct msgb *msg_tx; + int rc; + rc = oap_register(&gsupc->oap_state, &msg_tx); + + if ((rc < 0) || (!msg_tx)) { + LOGP(DGPRS, LOGL_ERROR, "GSUP OAP set up, but cannot register.\n"); + return; + } + + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); +} + static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) { struct gprs_gsup_client *gsupc = link->data; @@ -120,6 +134,9 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) if (up) { start_test_procedure(gsupc); + if (gsupc->oap_state.state == OAP_INITIALIZED) + gsup_client_oap_register(gsupc); + osmo_timer_del(&gsupc->connect_timer); } else { osmo_timer_del(&gsupc->ping_timer); @@ -129,6 +146,22 @@ static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) } } +static int gsup_client_oap_handle(struct gprs_gsup_client *gsupc, struct msgb *msg_rx) +{ + int rc; + struct msgb *msg_tx; + + rc = oap_handle(&gsupc->oap_state, msg_rx, &msg_tx); + msgb_free(msg_rx); + if (rc < 0) + return rc; + + if (msg_tx) + gsup_client_send(gsupc, IPAC_PROTO_EXT_OAP, msg_tx); + + return 0; +} + static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) { struct ipaccess_head *hh = (struct ipaccess_head *) msg->data; @@ -168,16 +201,24 @@ static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) if (hh->proto != IPAC_PROTO_OSMO) goto invalid; - if (!he || msgb_l2len(msg) < sizeof(*he) || - he->proto != IPAC_PROTO_EXT_GSUP) + if (!he || msgb_l2len(msg) < sizeof(*he)) goto invalid; msg->l2h = &he->data[0]; - OSMO_ASSERT(gsupc->read_cb != NULL); - gsupc->read_cb(gsupc, msg); + if (he->proto == IPAC_PROTO_EXT_GSUP) { + OSMO_ASSERT(gsupc->read_cb != NULL); + gsupc->read_cb(gsupc, msg); + /* expecting read_cb() to free msg */ + } + else + if (he->proto == IPAC_PROTO_EXT_OAP) { + return gsup_client_oap_handle(gsupc, msg); + /* gsup_client_oap_handle frees msg */ + } + else + goto invalid; - /* Not freeing msg here, because that must be done by the read_cb. */ return 0; invalid: @@ -222,7 +263,8 @@ static void start_test_procedure(struct gprs_gsup_client *gsupc) struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, unsigned int tcp_port, - gprs_gsup_read_cb_t read_cb) + gprs_gsup_read_cb_t read_cb, + struct oap_config *oap_config) { struct gprs_gsup_client *gsupc; int rc; @@ -230,6 +272,10 @@ struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, gsupc = talloc_zero(tall_bsc_ctx, struct gprs_gsup_client); OSMO_ASSERT(gsupc); + rc = oap_init(oap_config, &gsupc->oap_state); + if (rc != 0) + goto failed; + gsupc->link = ipa_client_conn_create(gsupc, /* no e1inp */ NULL, 0, diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c index 8231e8c..3467293 100644 --- a/openbsc/src/gprs/gprs_subscriber.c +++ b/openbsc/src/gprs/gprs_subscriber.c @@ -63,7 +63,8 @@ int gprs_subscr_init(struct sgsn_instance *sgi) sgi->gsup_client = gprs_gsup_client_create( addr_str, sgi->cfg.gsup_server_port, - &gsup_read_cb); + &gsup_read_cb, + &sgi->cfg.oap); if (!sgi->gsup_client) return -1; diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index 3c202dd..24504c2 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -28,6 +28,8 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ + $(top_builddir)/src/gprs/oap.o \ + $(top_builddir)/src/gprs/oap_messages.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOABIS_LIBS) \ $(LIBOSMOCORE_LIBS) \ -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 09:57:38 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:38 +0200 Subject: [PATCH 6/6] oap: add OAP config to VTY In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-7-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf --- openbsc/src/gprs/sgsn_vty.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c index b74d01a..838644e 100644 --- a/openbsc/src/gprs/sgsn_vty.c +++ b/openbsc/src/gprs/sgsn_vty.c @@ -214,6 +214,18 @@ static int config_write_sgsn(struct vty *vty) if (g_cfg->gsup_server_port) vty_out(vty, " gsup remote-port %d%s", g_cfg->gsup_server_port, VTY_NEWLINE); + + vty_out(vty, " gsup oap-id %d%s", + (int)g_cfg->oap.client_id, VTY_NEWLINE); + if (g_cfg->oap.secret_k_present != 0) + vty_out(vty, " gsup oap-k %s%s", + osmo_hexdump_nospc(g_cfg->oap.secret_k, sizeof(g_cfg->oap.secret_k)), + VTY_NEWLINE); + if (g_cfg->oap.secret_opc_present != 0) + vty_out(vty, " gsup oap-opc %s%s", + osmo_hexdump_nospc(g_cfg->oap.secret_opc, sizeof(g_cfg->oap.secret_opc)), + VTY_NEWLINE); + llist_for_each_entry(acl, &g_cfg->imsi_acl, list) vty_out(vty, " imsi-acl add %s%s", acl->imsi, VTY_NEWLINE); @@ -895,6 +907,82 @@ DEFUN(cfg_gsup_remote_port, cfg_gsup_remote_port_cmd, return CMD_SUCCESS; } +DEFUN(cfg_gsup_oap_id, cfg_gsup_oap_id_cmd, + "gsup oap-id <0-65535>", + "GSUP Parameters\n" + "Set the SGSN's OAP client ID\nOAP client ID (0 == disabled)\n") +{ + /* VTY ensures range */ + g_cfg->oap.client_id = (uint16_t)atoi(argv[0]); + return CMD_SUCCESS; +} + +DEFUN(cfg_gsup_oap_k, cfg_gsup_oap_k_cmd, + "gsup oap-k K", + "GSUP Parameters\n" + "Set the OAP shared secret K\nK value (16 byte) hex\n") +{ + const char *k = argv[0]; + + g_cfg->oap.secret_k_present = 0; + + if ((!k) || (strlen(k) == 0)) + goto disable; + + int k_len = osmo_hexparse(k, + g_cfg->oap.secret_k, + sizeof(g_cfg->oap.secret_k)); + if (k_len != 16) { + vty_out(vty, "%% need exactly 16 octets for oap-k, got %d.%s", + k_len, VTY_NEWLINE); + goto disable; + } + + g_cfg->oap.secret_k_present = 1; + return CMD_SUCCESS; + +disable: + if (g_cfg->oap.client_id > 0) { + vty_out(vty, "%% OAP client ID set, but invalid oap-k value disables OAP.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + +DEFUN(cfg_gsup_oap_opc, cfg_gsup_oap_opc_cmd, + "gsup oap-opc OPC", + "GSUP Parameters\n" + "Set the OAP shared secret OPC\nOPC value (16 byte) hex\n") +{ + const char *opc = argv[0]; + + g_cfg->oap.secret_opc_present = 0; + + if ((!opc) || (strlen(opc) == 0)) + goto disable; + + int opc_len = osmo_hexparse(opc, + g_cfg->oap.secret_opc, + sizeof(g_cfg->oap.secret_opc)); + if (opc_len != 16) { + vty_out(vty, "%% need exactly 16 octets for oap-opc, got %d.%s", + opc_len, VTY_NEWLINE); + goto disable; + } + + g_cfg->oap.secret_opc_present = 1; + return CMD_SUCCESS; + +disable: + if (g_cfg->oap.client_id > 0) { + vty_out(vty, "%% OAP client ID set, but invalid oap-opc value disables OAP.%s", + VTY_NEWLINE); + return CMD_WARNING; + } + return CMD_SUCCESS; +} + DEFUN(cfg_apn_name, cfg_apn_name_cmd, "access-point-name NAME", "Configure a global list of allowed APNs\n" @@ -969,6 +1057,9 @@ int sgsn_vty_init(void) install_element(SGSN_NODE, &cfg_auth_policy_cmd); install_element(SGSN_NODE, &cfg_gsup_remote_ip_cmd); install_element(SGSN_NODE, &cfg_gsup_remote_port_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_id_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_k_cmd); + install_element(SGSN_NODE, &cfg_gsup_oap_opc_cmd); install_element(SGSN_NODE, &cfg_apn_ggsn_cmd); install_element(SGSN_NODE, &cfg_apn_imsi_ggsn_cmd); install_element(SGSN_NODE, &cfg_apn_name_cmd); -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 09:57:32 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:32 +0200 Subject: OAP patch set fixes Message-ID: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Here is the fixed OAP patch set of those changes not merged yet. For decode_big_endian(), see the new API comment and my mail from thursday night/friday morning. Thanks for the review! ~Neels From nhofmeyr at sysmocom.de Mon Oct 12 09:57:33 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 11:57:33 +0200 Subject: [PATCH 1/6] libcommon: soak up three static functions. In-Reply-To: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444643858-15149-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444643858-15149-2-git-send-email-nhofmeyr@sysmocom.de> Add new kitchen sink openbsc/utils.h and libcommon/utils.c to make three so far static functions public (so I can use them in the upcoming OAP code). A place to put them could have been the gprs_utils.h, but all general functions in there have a gprs_ prefix, and todo markings to move them away. All other libcommon headers are too specific, so I opened up this kitchen sink header. Replace the implementation of encode_big_endian() with a call to osmo_store64be_ext(). See comments. Apply the change in Makefiles and C files. --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/utils.h | 26 ++++++++++++++++ openbsc/src/gprs/gprs_gsup_messages.c | 30 +----------------- openbsc/src/libcommon/Makefile.am | 2 +- openbsc/src/libcommon/utils.c | 58 +++++++++++++++++++++++++++++++++++ openbsc/src/osmo-bsc_nat/bsc_nat.c | 12 +------- openbsc/tests/gprs/Makefile.am | 3 +- 7 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 openbsc/include/openbsc/utils.h create mode 100644 openbsc/src/libcommon/utils.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 254f43d..828f5bd 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -14,7 +14,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ osmo_msc_data.h osmo_bsc_grace.h sms_queue.h abis_om2000.h \ bss.h gsm_data_shared.h ipaccess.h mncc_int.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ - osmux.h mgcp_transcode.h gprs_utils.h \ + osmux.h mgcp_transcode.h gprs_utils.h utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ gprs_gsup_client.h bsc_msg_filter.h diff --git a/openbsc/include/openbsc/utils.h b/openbsc/include/openbsc/utils.h new file mode 100644 index 0000000..d605487 --- /dev/null +++ b/openbsc/include/openbsc/utils.h @@ -0,0 +1,26 @@ +/* OpenBSC kitchen sink */ + +#pragma once + +#include +#include + +/* Compare count bytes of exp to rel. Return 0 if they are identical, 1 + * otherwise. Do not return a mismatch on the first mismatching byte, + * but always compare all bytes, regardless. The idea is that the amount of + * matching bytes cannot be inferred from the time the comparison took.*/ +int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count); + +/* This is like osmo_load64be_ext, except that if data_len is less than + * sizeof(uint64_t), the data is interpreted as the least significant bytes + * (osmo_load64be_ext loads them as the most significant bytes into the + * returned uint64_t). In this way, any integer size up to 64 bits can be + * decoded conveniently by using sizeof(), without the need to call specific + * numbered functions (osmo_load16, 32, ...). */ +uint64_t decode_big_endian(const uint8_t *data, size_t data_len); + +/* This is like osmo_store64be_ext, except that this returns a static buffer of + * the result (for convenience, but not threadsafe). If data_len is less than + * sizeof(uint64_t), only the least significant bytes of value are encoded. */ +uint8_t *encode_big_endian(uint64_t value, size_t data_len); + diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c index bdcff5f..07485f7 100644 --- a/openbsc/src/gprs/gprs_gsup_messages.c +++ b/openbsc/src/gprs/gprs_gsup_messages.c @@ -26,41 +26,13 @@ #include #include +#include #include #include #include - -static uint64_t decode_big_endian(const uint8_t *data, size_t data_len) -{ - uint64_t value = 0; - - while (data_len > 0) { - value = (value << 8) + *data; - data += 1; - data_len -= 1; - } - - return value; -} - -static uint8_t *encode_big_endian(uint64_t value, size_t data_len) -{ - static uint8_t buf[sizeof(uint64_t)]; - int idx; - - OSMO_ASSERT(data_len <= ARRAY_SIZE(buf)); - - for (idx = data_len - 1; idx >= 0; idx--) { - buf[idx] = (uint8_t)value; - value = value >> 8; - } - - return buf; -} - static int decode_pdp_info(uint8_t *data, size_t data_len, struct gprs_gsup_pdp_info *pdp_info) { diff --git a/openbsc/src/libcommon/Makefile.am b/openbsc/src/libcommon/Makefile.am index 75f40ee..84c7544 100644 --- a/openbsc/src/libcommon/Makefile.am +++ b/openbsc/src/libcommon/Makefile.am @@ -6,4 +6,4 @@ noinst_LIBRARIES = libcommon.a libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c \ gsm_data_shared.c socket.c talloc_ctx.c \ - gsm_subscriber_base.c + gsm_subscriber_base.c utils.c diff --git a/openbsc/src/libcommon/utils.c b/openbsc/src/libcommon/utils.c new file mode 100644 index 0000000..c47dcae --- /dev/null +++ b/openbsc/src/libcommon/utils.c @@ -0,0 +1,58 @@ +/* OpenBSC kitchen sink */ + +/* (C) 2015 by sysmocom s.m.f.c GmbH + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include + +/* Wishful thinking to generate a constant time compare */ +int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count) +{ + int x = 0, i; + + for (i = 0; i < count; ++i) + x |= exp[i] ^ rel[i]; + + /* if x is zero, all data was identical */ + return x? 1 : 0; +} + + +uint64_t decode_big_endian(const uint8_t *data, size_t data_len) +{ + uint64_t value = 0; + + while (data_len > 0) { + value = (value << 8) + *data; + data += 1; + data_len -= 1; + } + + return value; +} + +uint8_t *encode_big_endian(uint64_t value, size_t data_len) +{ + static uint8_t buf[sizeof(uint64_t)]; + OSMO_ASSERT(data_len <= ARRAY_SIZE(buf)); + osmo_store64be_ext(value, buf, data_len); + return buf; +} + diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c index 56c6286..18343dd 100644 --- a/openbsc/src/osmo-bsc_nat/bsc_nat.c +++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -987,17 +988,6 @@ static void ipaccess_close_bsc(void *data) bsc_close_connection(conn); } -/* Wishful thinking to generate a constant time compare */ -static int constant_time_cmp(const uint8_t *exp, const uint8_t *rel, const int count) -{ - int x = 0, i; - - for (i = 0; i < count; ++i) - x |= exp[i] ^ rel[i]; - - return x != 0; -} - static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, const uint8_t *key, const int keylen) { struct osmo_auth_vector vec; diff --git a/openbsc/tests/gprs/Makefile.am b/openbsc/tests/gprs/Makefile.am index 633c362..b57977b 100644 --- a/openbsc/tests/gprs/Makefile.am +++ b/openbsc/tests/gprs/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DIST = gprs_test.ok noinst_PROGRAMS = gprs_test gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c \ - $(top_srcdir)/src/gprs/gprs_gsup_messages.c + $(top_srcdir)/src/gprs/gprs_gsup_messages.c \ + $(top_srcdir)/src/libcommon/utils.c gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 11:08:50 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 13:08:50 +0200 Subject: gtphub: End User Address IE Message-ID: <20151012110850.GE1518@dub5> Hi, I just noticed that the GGSN returns its IP address in a GTP packet about PDP, in the "End User Address" IE (etsi/GSM/by_chapter/29.060.pdf 7.7.27). I'm asking myself whether this needs to be mapped by gtphub. 127.0.0.3 127.0.0.2 SGSN <-------- GTPHUB <--------- GGSN "127.0.0.2" "127.0.0.2" map this? ^ This sounds almost like no mapping is required, as if it tells the MS which IP address it has "as seen from outside": "The PDP Address shall be the address that this PDP context of the MS is identified with from the external packet data network." But I have no idea, really. Does anyone else? If not, we'll just have to see later... Thanks! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Mon Oct 12 12:00:18 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:00:18 +0200 Subject: Improved patches: openggsn cosmetics Message-ID: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> Here is another set of cosmetic improvements for openggsn (branch: neels/refactor). This prints the host address in human readable form and covers two more similar occurences. A new error log fix has been added (see 4/4). A nonstandard curly brace change from the previous patch has been dropped, and replaced by a blank line to increase readability. ~Neels From nhofmeyr at sysmocom.de Mon Oct 12 12:00:20 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:00:20 +0200 Subject: [PATCH 2/4] Rename gtp_dublicate, cosmetic. In-Reply-To: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444651222-27697-3-git-send-email-nhofmeyr@sysmocom.de> Fix spelling dublicate -> duplicate in comments and in (apparently only statically used) gtp_dublicate(). Add two TODO comments. Fix other spelling/punctuation and one numbering in comments. Remove an opening brace from a comment to not mix up cindent in vim. Break a long line. --- gtp/gtp.c | 38 ++++++++++++++++++++------------------ gtp/gtp.h | 4 ++-- sgsnemu/sgsnemu.c | 20 +++++++++++++------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index 08a9d61..2a39934 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -305,19 +305,19 @@ static uint32_t get_tei(void *pack) * requires the receiving GSN to send a response, with the same information * as in the original response. For most messages this happens automatically: * - * Echo: Automatically dublicates the original response + * Echo: Automatically duplicates the original response * Create pdp context: The SGSN may send create context request even if - * a context allready exist (imsi+nsapi?). This means that the reply will - automatically dublicate the original response. It might however have + * a context already exist (imsi+nsapi?). This means that the reply will + * automatically duplicate the original response. It might however have * side effects in the application which is asked twice to validate * the login. - * Update pdp context: Automatically dublicates the original response??? + * Update pdp context: Automatically duplicates the original response??? * Delete pdp context. Automatically in gtp0, but in gtp1 will generate * a nonexist reply message. * * The correct solution will be to make a queue containing response messages. * This queue should be checked whenever a request is received. If the - * response is allready in the queue that response should be transmitted. + * response is already in the queue that response should be transmitted. * It should be possible to find messages in this queue on the basis of * the sequence number and peer GSN IP address (The sequense number is unique * within each path). This need to be implemented by a hash table. Furthermore @@ -614,7 +614,7 @@ int gtp_notification(struct gsn_t *gsn, int version, return 0; } -int gtp_dublicate(struct gsn_t *gsn, int version, +int gtp_duplicate(struct gsn_t *gsn, int version, struct sockaddr_in *peer, uint16_t seq) { struct qmsg_t *qmsg; @@ -873,8 +873,8 @@ int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer, int fd, void *pack, unsigned len) { - /* Check if it was a dublicate request */ - if (!gtp_dublicate(gsn, 0, peer, get_seq(pack))) + /* Check if it was a duplicate request */ + if (!gtp_duplicate(gsn, 0, peer, get_seq(pack))) return 0; /* Send off reply to request */ @@ -1258,13 +1258,15 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version, uint8_t linked_nsapi = 0; struct pdp_t *linked_pdp = NULL; - if (!gtp_dublicate(gsn, version, peer, seq)) + /* TODO describe what this is all about: */ + if (!gtp_duplicate(gsn, version, peer, seq)) return 0; pdp = &pdp_buf; memset(pdp, 0, sizeof(struct pdp_t)); if (version == 0) { + /* TODO code dup: get_tid() */ uint64_t tid = be64toh(((union gtp_packet *)pack)->gtp0.h.tid); pdp_set_imsi_nsapi(pdp, tid); @@ -1511,7 +1513,7 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version, if (!pdp_getimsi(&pdp_old, pdp->imsi, pdp->nsapi)) { /* Found old pdp with same tid. Now the voodoo begins! */ /* 09.60 / 29.060 allows create on existing context to "steal" */ - /* the context which was allready established */ + /* the context which was already established */ /* We check that the APN, selection mode and MSISDN is the same */ DEBUGP(DLGTP, "gtp_create_pdp_ind: Old context found\n"); if ((pdp->apn_req.l == pdp_old->apn_req.l) @@ -1953,9 +1955,9 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version, uint64_t imsi; uint8_t nsapi; - /* Is this a dublicate ? */ - if (!gtp_dublicate(gsn, version, peer, seq)) { - return 0; /* We allready send of response once */ + /* Is this a duplicate ? */ + if (!gtp_duplicate(gsn, version, peer, seq)) { + return 0; /* We already sent of response once */ } /* Decode information elements */ @@ -2085,7 +2087,7 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version, } /* TEIC (conditional) */ - /* If TEIC is not included it means that we have allready received it */ + /* If TEIC is not included it means that we have already received it */ /* TODO: From 29.060 it is not clear if TEI_C MUST be included for */ /* all updated contexts, or only for one of the linked contexts */ gtpie_gettv4(ie, GTPIE_TEI_C, 0, &pdp->teic_gn); @@ -2424,9 +2426,9 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version, int n; int count = 0; - /* Is this a dublicate ? */ - if (!gtp_dublicate(gsn, version, peer, seq)) { - return 0; /* We allready send off response once */ + /* Is this a duplicate ? */ + if (!gtp_duplicate(gsn, version, peer, seq)) { + return 0; /* We already sent off response once */ } /* Find the linked context in question */ @@ -2638,7 +2640,7 @@ int gtp_gpdu_ind(struct gsn_t *gsn, int version, return 0; } -/* Receives GTP packet and sends off for further processing +/* Receives GTP packet and sends off for further processing. * Function will check the validity of the header. If the header * is not valid the packet is either dropped or a version not * supported is returned to the peer. diff --git a/gtp/gtp.h b/gtp/gtp.h index 76c967b..7f8ec91 100644 --- a/gtp/gtp.h +++ b/gtp/gtp.h @@ -147,7 +147,7 @@ struct ul16_t; struct gtp0_header { /* Descriptions from 3GPP 09.60 */ uint8_t flags; /* 01 bitfield, with typical values */ - /* 000..... Version: 1 (0) */ + /* 000..... Version: 0 */ /* ...1111. Spare (7) */ /* .......0 SNDCP N-PDU Number flag (0) */ uint8_t type; /* 02 Message type. T-PDU = 0xff */ @@ -223,7 +223,7 @@ union gtp_packet { * application this struct is provided in order to store all * relevant information related to the gsn. * - * Note that this does not include information storage for ' + * Note that this does not include information storage for * each pdp context. This is stored in another struct. *************************************************************/ diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c index 5b56751..13692e0 100644 --- a/sgsnemu/sgsnemu.c +++ b/sgsnemu/sgsnemu.c @@ -1569,7 +1569,7 @@ int main(int argc, char **argv) 512 = Flat rate, 256 = Hot billing */ /* Create context */ - /* We send this of once. Retransmissions are handled by gtplib */ + /* We send this off once. Retransmissions are handled by gtplib */ gtp_create_context_req(gsn, pdp, &iparr[n]); } @@ -1577,9 +1577,9 @@ int main(int argc, char **argv) printf("Waiting for response from ggsn........\n\n"); - /******************************************************************/ + /******************************************************************/ /* Main select loop */ - /******************************************************************/ + /******************************************************************/ while ((0 != state) && (5 != state)) { @@ -1613,7 +1613,7 @@ int main(int argc, char **argv) state = 3; } - /* Send off disconnect */ + /* Send disconnect */ if (3 == state) { state = 4; stoptime = time(NULL) + 5; /* Extra seconds to allow disconnect */ @@ -1628,17 +1628,23 @@ int main(int argc, char **argv) } } - /* Send of ping packets */ + /* Send ping packets */ diff = 0; while ((diff <= 0) && /* Send off an ICMP ping packet */ - /*if ( */ (options.pinghost.s_addr) && (2 == state) && + /*if */ (options.pinghost.s_addr) && (2 == state) && ((pingseq < options.pingcount) || (options.pingcount == 0))) { + if (!pingseq) gettimeofday(&firstping, &tz); /* Set time of first ping */ gettimeofday(&tv, &tz); - diff = 1000000 / options.pingrate * pingseq - 1000000 * (tv.tv_sec - firstping.tv_sec) - (tv.tv_usec - firstping.tv_usec); /* Microseconds safe up to 500 sec */ + + /* Microseconds safe up to 500 sec */ + diff = 1e6 / options.pingrate * pingseq + - 1e6 * (tv.tv_sec - firstping.tv_sec) + - (tv.tv_usec - firstping.tv_usec); + if (diff <= 0) { if (options.debug) printf("Create_ping %d\n", diff); -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 12:00:19 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:00:19 +0200 Subject: [PATCH 1/4] gtp.c: improve 3 error logs. In-Reply-To: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444651222-27697-2-git-send-email-nhofmeyr@sysmocom.de> It would print the memory location of the address buffer. Instead, print the human readable host address and port. The current code base supports only IPv4, and thread safety is apparently not required, hence just use inet_ntoa(). (The IPv6 and thread capable version is 4 times longer and harder to read.) --- gtp/gtp.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index cfce244..08a9d61 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -71,6 +71,11 @@ len, osmo_hexdump((const uint8_t *) pack, len), \ ##args); +#define LOGP_WITH_ADDR(ss, level, addr, fmt, args...) \ + LOGP(ss, level, "addr(%s:%d) " fmt, \ + inet_ntoa((addr).sin_addr), htons((addr).sin_port), \ + ##args); + /* API Functions */ const char *gtp_version() @@ -739,10 +744,9 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, if (bind((*gsn)->fd0, (struct sockaddr *)&addr, sizeof(addr)) < 0) { (*gsn)->err_socket++; - LOGP(DLGTP, LOGL_ERROR, - "bind(fd0=%d, addr=%lx, len=%d) failed: Error = %s\n", - (*gsn)->fd0, (unsigned long)&addr, sizeof(addr), - strerror(errno)); + LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr, + "bind(fd0=%d) failed: Error = %s\n", + (*gsn)->fd0, strerror(errno)); return -1; } @@ -765,10 +769,9 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, if (bind((*gsn)->fd1c, (struct sockaddr *)&addr, sizeof(addr)) < 0) { (*gsn)->err_socket++; - LOGP(DLGTP, LOGL_ERROR, - "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s\n", - (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr), - strerror(errno)); + LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr, + "bind(fd1c=%d) failed: Error = %s\n", + (*gsn)->fd1c, strerror(errno)); return -1; } @@ -791,10 +794,9 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) { (*gsn)->err_socket++; - LOGP(DLGTP, LOGL_ERROR, - "bind(fd1c=%d, addr=%lx, len=%d) failed: Error = %s\n", - (*gsn)->fd1c, (unsigned long)&addr, sizeof(addr), - strerror(errno)); + LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr, + "bind(fd1c=%d) failed: Error = %s\n", + (*gsn)->fd1c, strerror(errno)); return -1; } -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 12:00:21 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:00:21 +0200 Subject: [PATCH 3/4] gtp.h: rename gsn_t.dublicate to duplicate. In-Reply-To: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444651222-27697-4-git-send-email-nhofmeyr@sysmocom.de> Fix spelling dublicate -> duplicate. This is potentially breaking API compat, but currently, no users of gsn_t.dublicate are known. --- gtp/gtp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtp/gtp.h b/gtp/gtp.h index 7f8ec91..4f96015 100644 --- a/gtp/gtp.h +++ b/gtp/gtp.h @@ -276,7 +276,7 @@ struct gsn_t { uint64_t tooshort; /* Number of too short headers 29.60 11.1.2 */ uint64_t unknown; /* Number of unknown messages 29.60 11.1.3 */ uint64_t unexpect; /* Number of unexpected messages 29.60 11.1.4 */ - uint64_t dublicate; /* Number of dublicate or unsolicited replies */ + uint64_t duplicate; /* Number of duplicate or unsolicited replies */ uint64_t missing; /* Number of missing information field messages */ uint64_t incorrect; /* Number of incorrect information field messages */ uint64_t invalid; /* Number of invalid message format messages */ -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 12:00:22 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:00:22 +0200 Subject: [PATCH 4/4] gtp.c: fix an error log. In-Reply-To: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444651222-27697-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444651222-27697-5-git-send-email-nhofmeyr@sysmocom.de> Fix: the code handles fd1u but prints fd1c. --- gtp/gtp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index 2a39934..73ed76a 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -795,8 +795,8 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen, if (bind((*gsn)->fd1u, (struct sockaddr *)&addr, sizeof(addr)) < 0) { (*gsn)->err_socket++; LOGP_WITH_ADDR(DLGTP, LOGL_ERROR, addr, - "bind(fd1c=%d) failed: Error = %s\n", - (*gsn)->fd1c, strerror(errno)); + "bind(fd1u=%d) failed: Error = %s\n", + (*gsn)->fd1u, strerror(errno)); return -1; } -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 12:29:00 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:29:00 +0200 Subject: Another openggsn cosmetic Message-ID: <1444652941-28379-1-git-send-email-nhofmeyr@sysmocom.de> Another addition to the neels/refactor branch, marking a possible problem in gtp.c. ~Neels From nhofmeyr at sysmocom.de Mon Oct 12 12:29:01 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 14:29:01 +0200 Subject: [PATCH] add todo comments In-Reply-To: <1444652941-28379-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444652941-28379-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444652941-28379-2-git-send-email-nhofmeyr@sysmocom.de> --- gtp/gtp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gtp/gtp.c b/gtp/gtp.c index 73ed76a..e6a610d 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -2181,6 +2181,9 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version, if (gtp_conf(gsn, 0, peer, pack, len, &type, &cbp)) return EOF; + /* TODO This function is called from gtp_decaps1c() (for GTP v1) but + * uses gtp0.h.flow (GTP v0 data element) + */ /* Find the context in question */ if (pdp_getgtp0(&pdp, ntoh16(((union gtp_packet *)pack)->gtp0.h.flow))) { gsn->err_unknownpdp++; @@ -2194,6 +2197,9 @@ int gtp_update_pdp_conf(struct gsn_t *gsn, int version, /* Register that we have received a valid teic from GGSN */ pdp->teic_confirmed = 1; + /* TODO This function is called from gtp_decaps1c() (for GTP v1) but + * explicitly passes version 0 and GTP0_HEADER_SIZE to gtpie_decaps() + */ /* Decode information elements */ if (gtpie_decaps (ie, 0, pack + GTP0_HEADER_SIZE, len - GTP0_HEADER_SIZE)) { -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 13:02:36 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 15:02:36 +0200 Subject: [PATCH] gtp_duplicate(): comment, add todo. Message-ID: <1444654956-29744-1-git-send-email-nhofmeyr@sysmocom.de> --- gtp/gtp.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/gtp/gtp.c b/gtp/gtp.c index e6a610d..de6a7b4 100644 --- a/gtp/gtp.c +++ b/gtp/gtp.c @@ -614,6 +614,15 @@ int gtp_notification(struct gsn_t *gsn, int version, return 0; } +/* Look for a message in the response queue for the given peer and sequence + * number seq. If found, (re-)send the response message and return 0. Otherwise + * return nonzero. This allows catching duplicate messages. + * A response message stays in the response queue until it times out. + * So, for any number of identical requests within that timeout period, the + * same packet can be resent. + * TODO this only checks the peer and sequence number, and does not verify that + * the GTP request is identical to the previous one for this peer and sequence + * nr: a mere peer or seq glitch can cause leaks of previous responses. */ int gtp_duplicate(struct gsn_t *gsn, int version, struct sockaddr_in *peer, uint16_t seq) { @@ -873,7 +882,7 @@ int gtp_echo_ind(struct gsn_t *gsn, int version, struct sockaddr_in *peer, int fd, void *pack, unsigned len) { - /* Check if it was a duplicate request */ + /* Repeat previous response in case of duplicate request */ if (!gtp_duplicate(gsn, 0, peer, get_seq(pack))) return 0; @@ -1258,7 +1267,7 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version, uint8_t linked_nsapi = 0; struct pdp_t *linked_pdp = NULL; - /* TODO describe what this is all about: */ + /* Repeat previous response in case of duplicate request */ if (!gtp_duplicate(gsn, version, peer, seq)) return 0; @@ -1955,10 +1964,9 @@ int gtp_update_pdp_ind(struct gsn_t *gsn, int version, uint64_t imsi; uint8_t nsapi; - /* Is this a duplicate ? */ - if (!gtp_duplicate(gsn, version, peer, seq)) { - return 0; /* We already sent of response once */ - } + /* Repeat previous response in case of duplicate request */ + if (!gtp_duplicate(gsn, version, peer, seq)) + return 0; /* Decode information elements */ if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) { @@ -2432,10 +2440,9 @@ int gtp_delete_pdp_ind(struct gsn_t *gsn, int version, int n; int count = 0; - /* Is this a duplicate ? */ - if (!gtp_duplicate(gsn, version, peer, seq)) { - return 0; /* We already sent off response once */ - } + /* Repeat previous response in case of duplicate request */ + if (!gtp_duplicate(gsn, version, peer, seq)) + return 0; /* Find the linked context in question */ if (pdp_getgtp1(&linked_pdp, get_tei(pack))) { -- 2.1.4 From nhofmeyr at sysmocom.de Mon Oct 12 13:12:26 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 12 Oct 2015 15:12:26 +0200 Subject: [PATCH] gtp_duplicate(): comment, add todo. In-Reply-To: <1444654956-29744-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444654956-29744-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <20151012131226.GA30217@dub5> On Mon, Oct 12, 2015 at 03:02:36PM +0200, Neels Hofmeyr wrote: > --- a/gtp/gtp.c > +++ b/gtp/gtp.c > @@ -614,6 +614,15 @@ int gtp_notification(struct gsn_t *gsn, int version, > return 0; > } > > +/* Look for a message in the response queue for the given peer and sequence > + * number seq. If found, (re-)send the response message and return 0. Otherwise > + * return nonzero. This allows catching duplicate messages. > + * A response message stays in the response queue until it times out. > + * So, for any number of identical requests within that timeout period, the > + * same packet can be resent. > + * TODO this only checks the peer and sequence number, and does not verify that > + * the GTP request is identical to the previous one for this peer and sequence > + * nr: a mere peer or seq glitch can cause leaks of previous responses. */ Actually, the repeated transfer will go to the same qmsg_t.peer that the response was originially addressed to. So fishing for other clients' responses is not likely... I can drop the todo... Any opinions on this? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From dwilllmann at sysmocom.de Mon Oct 12 17:36:30 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:30 +0200 Subject: [openbsc 0/5] sgsn/gbproxy RAND_bytes() usage and test cases Message-ID: From: Daniel Willmann Hello, the following patches should complete the usage of RAND_bytes() for GPRS. Jacob improved the SGSN test case so it would extract the PTMSI from the LLC frames and use those in the response. This means the gprs_sgsn patch will not break the test anymore. Furthermore, I changed the gbproxy implementation and test case to use RAND_bytes() instead of rand_r(). The test case previously used rand_r() to (re-)set the seed value for TLLI/PTMSI allocation in order to get predictable results. With RAND_bytes() this is not possible. Instead the tests overrides that function, replacing it with a predictable sequence of random numbers. Regards Daniel Daniel Willmann (3): gprs: Use RAND_bytes for p-tmsi gbproxy/test: Add and call cleanup_test function gprs/gb_proxy: Use RAND_bytes for gbproxy TLLI/TMSI allocation Jacob Erlbeck (2): sgsn/test: Add and call cleanup_test function sgsn/test: Really parse received DL LLC messages openbsc/include/openbsc/gb_proxy.h | 4 - openbsc/src/gprs/Makefile.am | 7 +- openbsc/src/gprs/gb_proxy.c | 16 +- openbsc/src/gprs/gprs_sgsn.c | 6 +- openbsc/tests/gbproxy/Makefile.am | 4 +- openbsc/tests/gbproxy/gbproxy_test.c | 110 +++++--- openbsc/tests/gbproxy/gbproxy_test.ok | 514 +++++++++++++++++----------------- openbsc/tests/sgsn/Makefile.am | 2 + openbsc/tests/sgsn/sgsn_test.c | 133 +++++++-- 9 files changed, 464 insertions(+), 332 deletions(-) -- 2.1.4 From dwilllmann at sysmocom.de Mon Oct 12 17:36:34 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:34 +0200 Subject: [openbsc 4/5] gbproxy/test: Add and call cleanup_test function In-Reply-To: References: Message-ID: <11e44bf459215a78e6e37605f76b18bb4335afe3.1444671220.git.dwillmann@sysmocom.de> From: Daniel Willmann This (currently empty) function is meant to contain code that cleans up the left-overs of the test functions. This is needed by the next commit to reset the RAND_bytes sequence. --- openbsc/tests/gbproxy/gbproxy_test.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index 17f0a17..cee79ca 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -51,6 +51,10 @@ struct gbproxy_config gbcfg = {0}; struct llist_head *received_messages = NULL; +static void cleanup_test() +{ +} + static int dump_global(FILE *stream, int indent) { unsigned int i; @@ -2145,6 +2149,8 @@ static void test_gbproxy_ptmsi_assignment() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } static void test_gbproxy_ptmsi_patching() @@ -2482,6 +2488,8 @@ static void test_gbproxy_ptmsi_patching() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } static void test_gbproxy_ptmsi_patching_bad_cases() @@ -2661,6 +2669,8 @@ static void test_gbproxy_ptmsi_patching_bad_cases() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } @@ -2973,6 +2983,8 @@ static void test_gbproxy_imsi_acquisition() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } static void test_gbproxy_secondary_sgsn() @@ -3474,6 +3486,8 @@ static void test_gbproxy_secondary_sgsn() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } static void test_gbproxy_keep_info() @@ -4417,6 +4431,8 @@ static void test_gbproxy_keep_info() gbprox_reset(&gbcfg); gprs_ns_destroy(nsi); nsi = NULL; + + cleanup_test(); } struct gbproxy_link_info *register_tlli( @@ -4700,6 +4716,8 @@ static void test_gbproxy_tlli_expire(void) } gbproxy_clear_patch_filter(&cfg.matches[GBPROX_MATCH_PATCHING]); gbprox_reset(&cfg); + + cleanup_test(); } static void test_gbproxy_imsi_matching(void) @@ -4774,6 +4792,8 @@ static void test_gbproxy_imsi_matching(void) gbproxy_clear_patch_filter(&match); OSMO_ASSERT(match.enable == 0); + + cleanup_test(); } static struct log_info_cat gprs_categories[] = { -- 2.1.4 From dwilllmann at sysmocom.de Mon Oct 12 17:36:32 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:32 +0200 Subject: [openbsc 2/5] sgsn/test: Really parse received DL LLC messages In-Reply-To: References: Message-ID: <9e26901bb4f2cb4aec99eab029b917e84d9101bd.1444671220.git.dwillmann@sysmocom.de> From: Jacob Erlbeck Currently just the number of intercepted downlink messages is counted and eventually checked. The contents of the messages is lost. The PTMSI contained in ATTACH/RAU Accept messages is just 'guessed' by resetting the random number generator after reference PTMSIs have been generated. While this works with rand_r, RAND_bytes cannot be forced to recreate a certain number sequence this way (unless the backend is replaced). This commit changes that behaviour so that the last received msgb is kept and decoded. The PTMSI that has been assigned by the SGSN is then taken in the affected test cases and used instead of a 'guessed' one. This is similar to how a real MS would react to the Accept message. Sponsored-by: On-Waves ehf --- openbsc/tests/sgsn/Makefile.am | 1 + openbsc/tests/sgsn/sgsn_test.c | 87 +++++++++++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index 3c202dd..2782d9e 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -28,6 +28,7 @@ sgsn_test_LDADD = \ $(top_builddir)/src/gprs/gprs_utils.o \ $(top_builddir)/src/gprs/gprs_subscriber.o \ $(top_builddir)/src/gprs/gsm_04_08_gprs.o \ + $(top_builddir)/src/gprs/gprs_gb_parse.o \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOABIS_LIBS) \ $(LIBOSMOCORE_LIBS) \ diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index d669830..859223f 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -51,17 +52,53 @@ static struct sgsn_instance sgsn_inst = { }; struct sgsn_instance *sgsn = &sgsn_inst; unsigned sgsn_tx_counter = 0; +struct msgb *last_msg = NULL; +struct gprs_gb_parse_context last_dl_parse_ctx; + +static void reset_last_msg() +{ + if (last_msg) + msgb_free(last_msg); + + last_msg = NULL; + memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx)); +} static void cleanup_test() { + reset_last_msg(); +} + +static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx) +{ + uint32_t new_ptmsi = GSM_RESERVED_TMSI; + + if (parse_ctx->new_ptmsi_enc) + gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi); + + return new_ptmsi; } /* override */ int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime, struct bssgp_dl_ud_par *dup) { + int rc; + + reset_last_msg(); + + last_msg = msg; + OSMO_ASSERT(msgb_data(last_msg) != NULL); + + rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg), + &last_dl_parse_ctx); + + fprintf(stderr, "Got DL LLC message: %s\n", + gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN")); + + OSMO_ASSERT(rc > 0); + sgsn_tx_counter += 1; - msgb_free(msg); return 0; } @@ -153,6 +190,7 @@ static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli, { struct msgb *msg; + reset_last_msg(); sgsn_tx_counter = 0; msg = create_msg(data, data_len); @@ -911,16 +949,6 @@ static void test_gmm_attach(int retry) printf("Testing GMM attach%s\n", retry ? " with retry" : ""); - /* reset the PRNG used by sgsn_alloc_ptmsi */ - srand(1); - - ptmsi1 = sgsn_alloc_ptmsi(); - OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI); - - /* reset the PRNG, so that the same P-TMSI sequence will be generated - * again */ - srand(1); - foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN); /* Create a LLE/LLME */ @@ -984,6 +1012,8 @@ retry_attach_req: /* we expect an attach accept/reject */ OSMO_ASSERT(sgsn_tx_counter == 1); + ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx); + OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI); /* this has been randomly assigned by the SGSN */ local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL); @@ -1507,16 +1537,6 @@ static void test_gmm_cancel(void) sgsn_inst.cfg.auth_policy = SGSN_AUTH_POLICY_OPEN; - /* reset the PRNG used by sgsn_alloc_ptmsi */ - srand(1); - - ptmsi1 = sgsn_alloc_ptmsi(); - OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI); - - /* reset the PRNG, so that the same P-TMSI sequence will be generated - * again */ - srand(1); - foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN); /* Create a LLE/LLME */ @@ -1554,6 +1574,8 @@ static void test_gmm_cancel(void) /* we expect an attach accept/reject */ OSMO_ASSERT(sgsn_tx_counter == 1); + ptmsi1 = get_new_ptmsi(&last_dl_parse_ctx); + OSMO_ASSERT(ptmsi1 != GSM_RESERVED_TMSI); /* this has been randomly assigned by the SGSN */ local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL); @@ -1591,6 +1613,7 @@ static void test_gmm_ptmsi_allocation(void) uint32_t foreign_tlli; uint32_t ptmsi1; uint32_t ptmsi2; + uint32_t received_ptmsi; uint32_t old_ptmsi; uint32_t local_tlli = 0; struct gprs_llc_lle *lle; @@ -1658,11 +1681,9 @@ static void test_gmm_ptmsi_allocation(void) OSMO_ASSERT(ptmsi1 != ptmsi2); - printf(" - Repeated Attach Request\n"); + ptmsi1 = ptmsi2 = GSM_RESERVED_TMSI; - /* reset the PRNG, so that the same P-TMSI will be generated - * again */ - srand(1); + printf(" - Repeated Attach Request\n"); foreign_tlli = gprs_tmsi2tlli(0xc0000023, TLLI_FOREIGN); @@ -1678,7 +1699,8 @@ static void test_gmm_ptmsi_allocation(void) ctx = sgsn_mm_ctx_by_tlli(foreign_tlli, &raid); OSMO_ASSERT(ctx != NULL); OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT); - OSMO_ASSERT(ctx->p_tmsi == ptmsi1); + OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI); + ptmsi1 = ctx->p_tmsi; old_ptmsi = ctx->p_tmsi_old; @@ -1698,6 +1720,8 @@ static void test_gmm_ptmsi_allocation(void) /* we expect an attach accept */ OSMO_ASSERT(sgsn_tx_counter == 1); + received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx); + OSMO_ASSERT(received_ptmsi == ptmsi1); /* we ignore this and send the attach again */ send_0408_message(lle->llme, foreign_tlli, @@ -1710,6 +1734,11 @@ static void test_gmm_ptmsi_allocation(void) OSMO_ASSERT(ctx->p_tmsi_old == old_ptmsi); OSMO_ASSERT(ctx->p_tmsi == ptmsi1); + /* we expect an attach accept */ + OSMO_ASSERT(sgsn_tx_counter == 1); + received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx); + OSMO_ASSERT(received_ptmsi == ptmsi1); + /* inject the attach complete */ local_tlli = gprs_tmsi2tlli(ptmsi1, TLLI_LOCAL); send_0408_message(ctx->llme, local_tlli, @@ -1733,7 +1762,9 @@ static void test_gmm_ptmsi_allocation(void) OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT); OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1); - OSMO_ASSERT(ctx->p_tmsi == ptmsi2); + OSMO_ASSERT(ctx->p_tmsi != GSM_RESERVED_TMSI); + OSMO_ASSERT(ctx->p_tmsi != ptmsi1); + ptmsi2 = ctx->p_tmsi; /* repeat the RA update request */ send_0408_message(ctx->llme, local_tlli, @@ -1741,6 +1772,8 @@ static void test_gmm_ptmsi_allocation(void) /* we expect an RA update accept */ OSMO_ASSERT(sgsn_tx_counter == 1); + received_ptmsi = get_new_ptmsi(&last_dl_parse_ctx); + OSMO_ASSERT(received_ptmsi == ptmsi2); OSMO_ASSERT(ctx->mm_state == GMM_COMMON_PROC_INIT); OSMO_ASSERT(ctx->p_tmsi_old == ptmsi1); -- 2.1.4 From dwilllmann at sysmocom.de Mon Oct 12 17:36:31 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:31 +0200 Subject: [openbsc 1/5] sgsn/test: Add and call cleanup_test function In-Reply-To: References: Message-ID: <8f5d9d07b829f53c97ca66844ccf0d160d1ad00d.1444671220.git.dwillmann@sysmocom.de> From: Jacob Erlbeck This (currently empty) function is meant to contain code that cleans up the left-overs of the test functions. This will be needed by the next commit that will store the last received msgb for later inspection. Sponsored-by: On-Waves ehf --- openbsc/tests/sgsn/sgsn_test.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c index 7e5ab1a..d669830 100644 --- a/openbsc/tests/sgsn/sgsn_test.c +++ b/openbsc/tests/sgsn/sgsn_test.c @@ -52,6 +52,10 @@ static struct sgsn_instance sgsn_inst = { struct sgsn_instance *sgsn = &sgsn_inst; unsigned sgsn_tx_counter = 0; +static void cleanup_test() +{ +} + /* override */ int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime, struct bssgp_dl_ud_par *dup) @@ -188,6 +192,8 @@ static void test_llme(void) /* Check that everything was cleaned up */ OSMO_ASSERT(count(gprs_llme_list()) == 0); + + cleanup_test(); } struct gsm_subscriber *last_updated_subscr = NULL; @@ -297,6 +303,8 @@ static void test_subscriber(void) OSMO_ASSERT(llist_empty(&active_subscribers)); update_subscriber_data_cb = __real_sgsn_update_subscriber_data; + + cleanup_test(); } static void test_auth_triplets(void) @@ -358,6 +366,8 @@ static void test_auth_triplets(void) sgsn_mm_ctx_cleanup_free(ctx); s1found = gprs_subscr_get_by_imsi(imsi1); OSMO_ASSERT(s1found == NULL); + + cleanup_test(); } #define TEST_GSUP_IMSI1_IE 0x01, 0x05, 0x21, 0x43, 0x65, 0x87, 0x09 @@ -649,6 +659,8 @@ static void test_subscriber_gsup(void) OSMO_ASSERT(last_updated_subscr == NULL); update_subscriber_data_cb = __real_sgsn_update_subscriber_data; + + cleanup_test(); } int my_gprs_gsup_client_send_dummy(struct gprs_gsup_client *gsupc, struct msgb *msg) @@ -694,6 +706,8 @@ static void test_gmm_detach(void) OSMO_ASSERT(count(gprs_llme_list()) == 0); ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid); OSMO_ASSERT(!ictx); + + cleanup_test(); } /* @@ -733,6 +747,8 @@ static void test_gmm_detach_power_off(void) OSMO_ASSERT(count(gprs_llme_list()) == 0); ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid); OSMO_ASSERT(!ictx); + + cleanup_test(); } /* @@ -765,6 +781,8 @@ static void test_gmm_detach_no_mmctx(void) /* verify that the LLME is gone */ OSMO_ASSERT(count(gprs_llme_list()) == 0); + + cleanup_test(); } /* @@ -799,6 +817,8 @@ static void test_gmm_detach_accept_unexpected(void) /* verify that things are gone */ OSMO_ASSERT(count(gprs_llme_list()) == 0); + + cleanup_test(); } /* @@ -832,6 +852,8 @@ static void test_gmm_status_no_mmctx(void) /* verify that the LLME is gone */ OSMO_ASSERT(count(gprs_llme_list()) == 0); + + cleanup_test(); } /* @@ -983,6 +1005,8 @@ retry_attach_req: OSMO_ASSERT(count(gprs_llme_list()) == 0); ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid); OSMO_ASSERT(!ictx); + + cleanup_test(); } static void test_gmm_attach_acl(void) @@ -996,6 +1020,8 @@ static void test_gmm_attach_acl(void) sgsn_acl_del("123456789012345", &sgsn->cfg); sgsn->cfg.auth_policy = saved_auth_policy; + + cleanup_test(); } int my_subscr_request_update_location(struct sgsn_mm_ctx *mmctx) { @@ -1033,6 +1059,8 @@ static void test_gmm_attach_subscr(void) sgsn->cfg.auth_policy = saved_auth_policy; subscr_request_update_location_cb = __real_gprs_subscr_request_update_location; subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info; + + cleanup_test(); } int my_subscr_request_auth_info_fake_auth(struct sgsn_mm_ctx *mmctx) @@ -1067,6 +1095,8 @@ static void test_gmm_attach_subscr_fake_auth(void) sgsn->cfg.auth_policy = saved_auth_policy; subscr_request_update_location_cb = __real_gprs_subscr_request_update_location; subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info; + + cleanup_test(); } int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx) @@ -1108,6 +1138,8 @@ static void test_gmm_attach_subscr_real_auth(void) sgsn->cfg.auth_policy = saved_auth_policy; subscr_request_update_location_cb = __real_gprs_subscr_request_update_location; subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info; + + cleanup_test(); } #define TEST_GSUP_IMSI_LONG_IE 0x01, 0x08, \ @@ -1199,6 +1231,8 @@ static void test_gmm_attach_subscr_gsup_auth(int retry) subscr_request_auth_info_cb = __real_gprs_subscr_request_auth_info; upd_loc_skip = 0; auth_info_skip = 0; + + cleanup_test(); } int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) @@ -1280,6 +1314,8 @@ static void test_gmm_attach_subscr_real_gsup_auth(int retry) auth_info_skip = 0; talloc_free(sgsn->gsup_client); sgsn->gsup_client = NULL; + + cleanup_test(); } /* @@ -1422,6 +1458,8 @@ static void test_gmm_reject(void) OSMO_ASSERT(ctx == NULL); OSMO_ASSERT(count(gprs_llme_list()) == 0); } + + cleanup_test(); } /* @@ -1538,6 +1576,8 @@ static void test_gmm_cancel(void) OSMO_ASSERT(!ictx); sgsn->cfg.auth_policy = saved_auth_policy; + + cleanup_test(); } /* @@ -1728,6 +1768,8 @@ static void test_gmm_ptmsi_allocation(void) OSMO_ASSERT(!ictx); sgsn->cfg.auth_policy = saved_auth_policy; + + cleanup_test(); } static void test_apn_matching(void) @@ -1820,6 +1862,8 @@ static void test_apn_matching(void) sgsn_apn_ctx_free(actxs[3]); actx = sgsn_apn_ctx_match("abc.def.test", "12345678"); OSMO_ASSERT(actx == NULL); + + cleanup_test(); } struct sgsn_subscriber_pdp_data* sgsn_subscriber_pdp_data_alloc( @@ -1962,6 +2006,8 @@ static void test_ggsn_selection(void) sgsn_ggsn_ctx_free(ggcs[2]); gprs_gsup_client_send_cb = __real_gprs_gsup_client_send; + + cleanup_test(); } static struct log_info_cat gprs_categories[] = { -- 2.1.4 From dwilllmann at sysmocom.de Mon Oct 12 17:36:33 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:33 +0200 Subject: [openbsc 3/5] gprs: Use RAND_bytes for p-tmsi In-Reply-To: References: Message-ID: <0ff0e449d3e476466cd8ce7bc46c2720d74f0c46.1444671220.git.dwillmann@sysmocom.de> From: Daniel Willmann [hfreyther: Link to libcrypto, include header, add uint8_t* cast] --- openbsc/src/gprs/Makefile.am | 3 ++- openbsc/src/gprs/gprs_sgsn.c | 6 +++++- openbsc/tests/sgsn/Makefile.am | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f46a402..dcc6842 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -30,4 +30,5 @@ osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ - -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) -lrt + -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \ + $(LIBCRYPTO_LIBS) -lrt diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c index f40de0b..9b11c35 100644 --- a/openbsc/src/gprs/gprs_sgsn.c +++ b/openbsc/src/gprs/gprs_sgsn.c @@ -41,6 +41,8 @@ #include +#include + #define GPRS_LLME_CHECK_TICK 30 extern struct sgsn_instance *sgsn; @@ -525,7 +527,9 @@ uint32_t sgsn_alloc_ptmsi(void) int max_retries = 100; restart: - ptmsi = rand(); + if (RAND_bytes((uint8_t *) &ptmsi, sizeof(ptmsi)) != 1) + goto failed; + /* Enforce that the 2 MSB are set without loosing the distance between * identical values. Since rand() has no duplicate values within a * period (because the size of the state is the same like the size of diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am index 2782d9e..4c6ba9f 100644 --- a/openbsc/tests/sgsn/Makefile.am +++ b/openbsc/tests/sgsn/Makefile.am @@ -35,5 +35,6 @@ sgsn_test_LDADD = \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOGB_LIBS) \ $(LIBCARES_LIBS) \ + $(LIBCRYPTO_LIBS) \ -lgtp -lrt -- 2.1.4 From dwilllmann at sysmocom.de Mon Oct 12 17:36:35 2015 From: dwilllmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 19:36:35 +0200 Subject: [openbsc 5/5] gprs/gb_proxy: Use RAND_bytes for gbproxy TLLI/TMSI allocation In-Reply-To: References: Message-ID: <7298d9081ef76f6c6fdf5af33e18211b005d1dd7.1444671220.git.dwillmann@sysmocom.de> From: Daniel Willmann This change has some implications for the test case. It manipulated bss_ptmsi_state and sgsn_tlli_state variables to make the output of rand_r() and thus the TLLI/TMSI used predictable. This possibility is gone when using RAND_bytes() so instead it is overridden by a function that returns a deterministic sequence of values (0x00dead00, 0x00dead01, ...). The test cases are adapted to expect these values instead of the pseudo random values before. The gbproxy_test stdout file changes as well, but only where the TLLI/TMSI is displayed (in the hex dumps as well as the TLLI cache entries). All other output is the same. --- openbsc/include/openbsc/gb_proxy.h | 4 - openbsc/src/gprs/Makefile.am | 4 +- openbsc/src/gprs/gb_proxy.c | 16 +- openbsc/tests/gbproxy/Makefile.am | 4 +- openbsc/tests/gbproxy/gbproxy_test.c | 90 +++--- openbsc/tests/gbproxy/gbproxy_test.ok | 514 +++++++++++++++++----------------- 6 files changed, 329 insertions(+), 303 deletions(-) diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h index 74dc6d4..ff35a39 100644 --- a/openbsc/include/openbsc/gb_proxy.h +++ b/openbsc/include/openbsc/gb_proxy.h @@ -101,10 +101,6 @@ struct gbproxy_config { /* IMSI checking/matching */ struct gbproxy_match matches[GBPROX_MATCH_LAST]; - - /* Used to generate identifiers */ - unsigned bss_ptmsi_state; - unsigned sgsn_tlli_state; }; struct gbproxy_patch_state { diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index dcc6842..f012003 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) AM_CFLAGS=-Wall -fno-strict-aliasing $(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOCTRL_CFLAGS) \ $(LIBOSMOABIS_CFLAGS) $(LIBOSMOGB_CFLAGS) $(COVERAGE_CFLAGS) \ - $(LIBCARES_CFLAGS) + $(LIBCARES_CFLAGS) $(LIBCRYPTO_CFLAGS) OSMO_LIBS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \ $(LIBOSMOCTRL_LIBS) $(LIBOSMOGB_LIBS) @@ -20,7 +20,7 @@ osmo_gbproxy_SOURCES = gb_proxy.c gb_proxy_main.c gb_proxy_vty.c \ gb_proxy_patch.c gb_proxy_tlli.c gb_proxy_peer.c \ gprs_gb_parse.c gprs_llc_parse.c crc24.c gprs_utils.c osmo_gbproxy_LDADD = $(top_builddir)/src/libcommon/libcommon.a \ - $(OSMO_LIBS) -lrt + $(OSMO_LIBS) $(LIBCRYPTO_LIBS) -lrt osmo_sgsn_SOURCES = gprs_gmm.c gprs_sgsn.c gprs_sndcp.c gprs_sndcp_vty.c \ sgsn_main.c sgsn_vty.c sgsn_libgtp.c \ diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c index 21cd405..5b3ee28 100644 --- a/openbsc/src/gprs/gb_proxy.c +++ b/openbsc/src/gprs/gb_proxy.c @@ -50,6 +50,8 @@ #include #include +#include + static const struct rate_ctr_desc global_ctr_description[] = { { "inv-bvci", "Invalid BVC Identifier " }, { "inv-lai", "Invalid Location Area Identifier" }, @@ -232,7 +234,11 @@ uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, bss_ptmsi = sgsn_ptmsi; } else { do { - bss_ptmsi = rand_r(&peer->cfg->bss_ptmsi_state); + if (RAND_bytes((uint8_t *) &bss_ptmsi, sizeof(bss_ptmsi)) != 1) { + bss_ptmsi = GSM_RESERVED_TMSI; + break; + } + bss_ptmsi = bss_ptmsi | 0xC0000000; if (gbproxy_link_info_by_ptmsi(peer, bss_ptmsi)) @@ -265,7 +271,11 @@ uint32_t gbproxy_make_sgsn_tlli(struct gbproxy_peer *peer, } else { do { /* create random TLLI, 0b01111xxx... */ - sgsn_tlli = rand_r(&peer->cfg->sgsn_tlli_state); + if (RAND_bytes((uint8_t *) &sgsn_tlli, sizeof(sgsn_tlli)) != 1) { + sgsn_tlli = 0; + break; + } + sgsn_tlli = (sgsn_tlli & 0x7fffffff) | 0x78000000; if (gbproxy_link_info_by_any_sgsn_tlli(peer, sgsn_tlli)) @@ -1365,8 +1375,6 @@ int gbproxy_init_config(struct gbproxy_config *cfg) INIT_LLIST_HEAD(&cfg->bts_peers); cfg->ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0); clock_gettime(CLOCK_REALTIME, &tp); - cfg->bss_ptmsi_state = tp.tv_sec + tp.tv_nsec; - cfg->sgsn_tlli_state = tp.tv_sec - tp.tv_nsec; return 0; } diff --git a/openbsc/tests/gbproxy/Makefile.am b/openbsc/tests/gbproxy/Makefile.am index 4577e3a..18d77a8 100644 --- a/openbsc/tests/gbproxy/Makefile.am +++ b/openbsc/tests/gbproxy/Makefile.am @@ -7,6 +7,8 @@ EXTRA_DIST = gbproxy_test.ok noinst_PROGRAMS = gbproxy_test gbproxy_test_SOURCES = gbproxy_test.c +gbproxy_test_LDFLAGS = \ + -Wl,--wrap=RAND_bytes gbproxy_test_LDADD = \ $(top_builddir)/src/gprs/gb_proxy.o \ $(top_builddir)/src/gprs/gb_proxy_patch.o \ @@ -22,4 +24,4 @@ gbproxy_test_LDADD = \ $(LIBOSMOCORE_LIBS) $(LIBOSMOGB_LIBS) \ $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) \ $(LIBOSMOABIS_LIBS) $(LIBRARY_DL) \ - -lrt + $(LIBCRYPTO_LIBS) -lrt diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c index cee79ca..0ba827f 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.c +++ b/openbsc/tests/gbproxy/gbproxy_test.c @@ -37,6 +37,8 @@ #include #include +#include + #define REMOTE_BSS_ADDR 0x01020304 #define REMOTE_SGSN_ADDR 0x05060708 @@ -51,8 +53,37 @@ struct gbproxy_config gbcfg = {0}; struct llist_head *received_messages = NULL; +/* override, requires '-Wl,--wrap=RAND_bytes' */ +int __real_RAND_bytes(unsigned char *buf, int num); +int mock_RAND_bytes(unsigned char *buf, int num); +int (*RAND_bytes_cb)(unsigned char *, int) = + &mock_RAND_bytes; + +int __wrap_RAND_bytes(unsigned char *buf, int num) +{ + return (*RAND_bytes_cb)(buf, num); +} + +static int rand_seq_num = 0; +int mock_RAND_bytes(unsigned char *buf, int num) +{ + uint32_t val; + + OSMO_ASSERT(num == sizeof(val)); + OSMO_ASSERT(__real_RAND_bytes(buf, num) == 1); + + val = 0x00dead00 + rand_seq_num; + + rand_seq_num++; + + memcpy(buf, &val, num); + + return 1; +} + static void cleanup_test() { + rand_seq_num = 0; } static int dump_global(FILE *stream, int indent) @@ -1972,8 +2003,6 @@ static void test_gbproxy_ptmsi_assignment() gbcfg.core_apn = talloc_zero_size(NULL, 100); gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar"); gbcfg.patch_ptmsi = 0; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; configure_sgsn_peer(&sgsn_peer); configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer)); @@ -2174,15 +2203,15 @@ static void test_gbproxy_ptmsi_patching() const uint32_t local_sgsn_tlli = 0xefe2b700; const uint32_t local_sgsn_tlli2 = 0xe0987654; const uint32_t local_sgsn_tlli3 = 0xe0543210; - const uint32_t random_sgsn_tlli = 0x7c69fb81; + const uint32_t random_sgsn_tlli = 0x78dead00; const uint32_t unknown_sgsn_tlli = 0xeebadbad; - const uint32_t bss_ptmsi = 0xc00f7304; - const uint32_t bss_ptmsi2 = 0xe656aa1f; - const uint32_t bss_ptmsi3 = 0xead4775a; - const uint32_t local_bss_tlli = 0xc00f7304; - const uint32_t local_bss_tlli2 = 0xe656aa1f; - const uint32_t local_bss_tlli3 = 0xead4775a; + const uint32_t bss_ptmsi = 0xc0dead01; + const uint32_t bss_ptmsi2 = 0xc0dead02; + const uint32_t bss_ptmsi3 = 0xc0dead03; + const uint32_t local_bss_tlli = 0xc0dead01; + const uint32_t local_bss_tlli2 = 0xc0dead02; + const uint32_t local_bss_tlli3 = 0xc0dead03; const uint32_t foreign_bss_tlli = 0x8000dead; @@ -2208,8 +2237,6 @@ static void test_gbproxy_ptmsi_patching() gbcfg.core_apn = talloc_zero_size(NULL, 100); gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar"); gbcfg.patch_ptmsi = 1; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; configure_sgsn_peer(&sgsn_peer); configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer)); @@ -2505,10 +2532,10 @@ static void test_gbproxy_ptmsi_patching_bad_cases() const uint32_t sgsn_ptmsi = 0xefe2b700; const uint32_t local_sgsn_tlli = 0xefe2b700; - const uint32_t random_sgsn_tlli = 0x7c69fb81; + const uint32_t random_sgsn_tlli = 0x78dead00; - const uint32_t bss_ptmsi = 0xc00f7304; - const uint32_t local_bss_tlli = 0xc00f7304; + const uint32_t bss_ptmsi = 0xc0dead01; + const uint32_t local_bss_tlli = 0xc0dead01; const uint32_t foreign_bss_tlli = 0x8000dead; @@ -2529,8 +2556,6 @@ static void test_gbproxy_ptmsi_patching_bad_cases() gbcfg.core_apn = talloc_zero_size(NULL, 100); gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar"); gbcfg.patch_ptmsi = 1; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; configure_sgsn_peer(&sgsn_peer); configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer)); @@ -2691,11 +2716,11 @@ static void test_gbproxy_imsi_acquisition() const uint32_t sgsn_ptmsi = 0xefe2b700; const uint32_t local_sgsn_tlli = 0xefe2b700; - const uint32_t random_sgsn_tlli = 0x7c69fb81; - const uint32_t random_sgsn_tlli2 = 0x7eb52dfb; + const uint32_t random_sgsn_tlli = 0x78dead00; + const uint32_t random_sgsn_tlli2 = 0x78dead02; - const uint32_t bss_ptmsi = 0xc00f7304; - const uint32_t local_bss_tlli = 0xc00f7304; + const uint32_t bss_ptmsi = 0xc0dead01; + const uint32_t local_bss_tlli = 0xc0dead01; const uint32_t foreign_bss_tlli = 0x8000dead; const uint32_t other_bss_tlli = 0x8000beef; @@ -2716,8 +2741,6 @@ static void test_gbproxy_imsi_acquisition() gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar"); gbcfg.patch_ptmsi = 1; gbcfg.acquire_imsi = 1; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; configure_sgsn_peer(&sgsn_peer); configure_bss_peers(bss_peer, ARRAY_SIZE(bss_peer)); @@ -3002,22 +3025,22 @@ static void test_gbproxy_secondary_sgsn() const uint32_t sgsn_ptmsi = 0xefe2b700; const uint32_t local_sgsn_tlli = 0xefe2b700; - const uint32_t random_sgsn_tlli = 0x7c69fb81; + const uint32_t random_sgsn_tlli = 0x78dead00; - const uint32_t bss_ptmsi = 0xc00f7304; - const uint32_t local_bss_tlli = 0xc00f7304; + const uint32_t bss_ptmsi = 0xc0dead01; + const uint32_t local_bss_tlli = 0xc0dead01; const uint32_t foreign_bss_tlli = 0x8000dead; const uint32_t sgsn_ptmsi2 = 0xe0987654; const uint32_t local_sgsn_tlli2 = 0xe0987654; - const uint32_t random_sgsn_tlli2 = 0x7eb52dfb; - const uint32_t bss_ptmsi2 = 0xe656aa1f; - const uint32_t local_bss_tlli2 = 0xe656aa1f; + const uint32_t random_sgsn_tlli2 = 0x78dead02; + const uint32_t bss_ptmsi2 = 0xc0dead03; + const uint32_t local_bss_tlli2 = 0xc0dead03; const uint32_t foreign_bss_tlli2 = 0x8000beef; - const uint32_t random_sgsn_tlli3 = 0x7e23ef54; - const uint32_t bss_ptmsi3 = 0xead4775a; - const uint32_t local_bss_tlli3 = 0xead4775a; + const uint32_t random_sgsn_tlli3 = 0x78dead04; + const uint32_t bss_ptmsi3 = 0xc0dead05; + const uint32_t local_bss_tlli3 = 0xc0dead05; const uint32_t foreign_bss_tlli3 = 0x8000feed; const uint8_t imsi1[] = {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18}; @@ -3044,8 +3067,7 @@ static void test_gbproxy_secondary_sgsn() gbcfg.core_apn_size = gprs_str_to_apn(gbcfg.core_apn, 100, "foo.bar"); gbcfg.patch_ptmsi = 1; gbcfg.acquire_imsi = 1; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; + gbcfg.route_to_sgsn2 = 1; gbcfg.nsip_sgsn2_nsei = SGSN2_NSEI; @@ -3518,8 +3540,6 @@ static void test_gbproxy_keep_info() gbcfg.nsip_sgsn_nsei = SGSN_NSEI; gbcfg.patch_ptmsi = 0; gbcfg.acquire_imsi = 1; - gbcfg.bss_ptmsi_state = 0; - gbcfg.sgsn_tlli_state = 1; gbcfg.core_mcc = 0; gbcfg.core_mnc = 0; gbcfg.core_apn = NULL; diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok index 46bbcbd..bbb6820 100644 --- a/openbsc/tests/gbproxy/gbproxy_test.ok +++ b/openbsc/tests/gbproxy/gbproxy_test.ok @@ -2368,7 +2368,7 @@ CALLBACK, event 0, msg length 75, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 00 63 60 12 34 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 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 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 (ATTACH REQUEST) = 79 @@ -2379,12 +2379,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0 + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0 PROCESSING IDENT REQUEST from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -2400,7 +2400,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0 + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 @@ -2409,7 +2409,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 44 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 +00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 result (IDENT RESPONSE) = 44 @@ -2421,16 +2421,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0 PROCESSING ATTACH ACCEPT from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 de ad 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 c0 0f 73 04 50 22 97 +00 00 10 02 00 80 00 de ad 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 c0 de ad 01 0c 0a 29 result (ATTACH ACCEPT) = 92 @@ -2444,12 +2444,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 35 @@ -2467,7 +2467,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING GMM INFO from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 88 41 c0 09 08 21 04 ba 3d @@ -2476,7 +2476,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 c0 0f 73 04 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 88 41 c0 09 08 21 04 ba 3d +00 00 10 02 00 c0 de ad 01 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 88 41 c0 09 08 21 04 ba 3d result (GMM INFO) = 70 @@ -2490,12 +2490,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING ACT PDP CTX REQ (REPLACE APN) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 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 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 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 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 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 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 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 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 85 @@ -2514,12 +2514,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING XID (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 CALLBACK, event 0, msg length 38, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 42 @@ -2535,15 +2535,15 @@ CALLBACK, event 0, msg length 70, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 74 -00 00 10 02 00 c0 0f 73 04 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e +00 00 10 02 00 c0 de ad 01 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e result (XID (DL)) = 74 PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 CALLBACK, event 0, msg length 89, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 93 @@ -2559,7 +2559,7 @@ CALLBACK, event 0, msg length 267, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 271 -00 00 10 02 00 c0 0f 73 04 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 +00 00 10 02 00 c0 de ad 01 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 result (LL11 DNS RESP (DL)) = 271 @@ -2574,12 +2574,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING RA UPD REQ (P-TMSI 2) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 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 e2 6d 78 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 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 e2 6d 78 CALLBACK, event 0, msg length 85, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 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 e2 6d 78 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 3e 01 c0 11 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 e2 6d 78 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 89 @@ -2595,7 +2595,7 @@ CALLBACK, event 0, msg length 87, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 91 -00 00 10 02 00 c0 0f 73 04 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 9d 41 c0 0d 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 e6 56 aa 1f 17 16 c5 7f 98 +00 00 10 02 00 c0 de ad 01 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 9d 41 c0 0d 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 02 17 16 bb 4d a0 result (RA UDP ACC (P-TMSI 2)) = 91 @@ -2610,12 +2610,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304/e656aa1f -> efe2b700/e0987654, IMSI 12131415161718, AGE 0 + TLLI c0dead01/c0dead02 -> efe2b700/e0987654, IMSI 12131415161718, AGE 0 PROCESSING RA UPD REQ (P-TMSI 3) from 0x01020304:1111 -00 00 10 02 01 e6 56 aa 1f 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 c0 de ad 02 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 -00 00 10 02 01 e6 56 aa 1f 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 c0 de ad 02 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 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 89 @@ -2631,7 +2631,7 @@ CALLBACK, event 0, msg length 87, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 91 -00 00 10 02 00 e6 56 aa 1f 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 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 ea d4 77 5a 17 16 31 d5 78 +00 00 10 02 00 c0 de ad 02 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 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 03 17 16 6e 58 26 result (RA UDP ACC (P-TMSI 3)) = 91 @@ -2646,12 +2646,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304/ead4775a -> efe2b700/e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead01/c0dead03 -> efe2b700/e0543210, IMSI 12131415161718, AGE 0 PROCESSING RA UPD COMPLETE from 0x01020304:1111 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 70 80 00 80 0e 00 08 01 c0 19 08 0a d5 5f 5e NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 35 @@ -2667,7 +2667,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 ea d4 77 5a 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 88 41 c0 15 08 21 bb c1 c6 +00 00 10 02 00 c0 de ad 03 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 88 41 c0 15 08 21 bb c1 c6 result (GMM INFO) = 70 @@ -2682,12 +2682,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 ea d4 77 5a 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 ea d4 77 5a 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 @@ -2706,12 +2706,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING BVC_SUSPEND from 0x01020304:1111 -00 00 00 00 0b 1f 84 ea d4 77 5a 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 CALLBACK, event 0, msg length 15, bvci 0x0000 -00 00 00 00 0b 1f 84 ea d4 77 5a 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 19 @@ -2730,7 +2730,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000 00 00 00 00 0c 1f 84 e0 54 32 10 1b 86 21 63 54 40 50 60 1d 81 01 @@ -2739,7 +2739,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 ea d4 77 5a 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -2754,7 +2754,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING PAGING_PS from 0x05060708:32000 00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 e0 54 32 10 @@ -2763,7 +2763,7 @@ CALLBACK, event 0, msg length 34, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 34 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 38 -00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 ea d4 77 5a +00 00 00 00 06 0d 88 11 12 13 14 15 16 17 18 0a 82 07 04 1b 86 11 22 33 40 50 60 18 83 00 00 00 20 84 c0 de ad 03 result (PAGING_PS) = 38 @@ -2778,12 +2778,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 ea d4 77 5a 0f 81 01 04 82 ee e1 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 ee e1 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 ea d4 77 5a 0f 81 01 04 82 ee e1 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 ee e1 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 @@ -2815,7 +2815,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 ea d4 77 5a 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -2847,10 +2847,10 @@ MESSAGE to BSS at 0x01020304:1111, msg length 70 result (GMM INFO) = 70 PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 48 @@ -2871,7 +2871,7 @@ Peers: TLLI from SGSN unknown : 2 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> e0543210, IMSI 12131415161718, AGE 0 + TLLI c0dead03 -> e0543210, IMSI 12131415161718, AGE 0 PROCESSING DETACH ACC from 0x05060708:32000 00 00 10 02 00 e0 54 32 10 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 89 41 c0 19 08 06 00 04 ff 52 @@ -2880,7 +2880,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 ea d4 77 5a 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 89 41 c0 19 08 06 00 04 ff 52 +00 00 10 02 00 c0 de ad 03 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 89 41 c0 19 08 06 00 04 ff 52 result (DETACH ACC) = 71 @@ -3022,7 +3022,7 @@ CALLBACK, event 0, msg length 75, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 00 63 60 12 34 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 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 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 (ATTACH REQUEST) = 79 @@ -3033,12 +3033,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0 + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0 PROCESSING IDENT REQUEST from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -3054,7 +3054,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0 + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 @@ -3063,7 +3063,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 44 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 +00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 result (IDENT RESPONSE) = 44 @@ -3075,16 +3075,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0 PROCESSING ATTACH ACCEPT from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 de ad 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 c0 0f 73 04 50 22 97 +00 00 10 02 00 80 00 de ad 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 c0 de ad 01 0c 0a 29 result (ATTACH ACCEPT) = 92 @@ -3098,16 +3098,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING ATTACH ACCEPT (duplicated) from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 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 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 +00 00 10 02 00 78 de ad 00 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 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 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 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 +00 00 10 02 00 78 de ad 00 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 09 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 1d 9e 24 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 de ad 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 09 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 0f 73 04 1e de 42 +00 00 10 02 00 80 00 de ad 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 09 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 01 42 f6 fc result (ATTACH ACCEPT (duplicated)) = 92 @@ -3121,12 +3121,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 09 08 03 39 d7 bc NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 35 @@ -3144,7 +3144,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING GMM INFO from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 88 41 c0 0d 08 21 68 71 6b @@ -3153,7 +3153,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 c0 0f 73 04 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 88 41 c0 0d 08 21 68 71 6b +00 00 10 02 00 c0 de ad 01 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 88 41 c0 0d 08 21 68 71 6b result (GMM INFO) = 70 @@ -3167,12 +3167,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 0d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 37 67 c6 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 48 @@ -3190,7 +3190,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING DETACH ACC from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 89 41 c0 11 08 06 00 cf 8a 58 @@ -3199,7 +3199,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 c0 0f 73 04 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 89 41 c0 11 08 06 00 cf 8a 58 +00 00 10 02 00 c0 de ad 01 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 89 41 c0 11 08 06 00 cf 8a 58 result (DETACH ACC) = 71 @@ -3346,7 +3346,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 @@ -3355,7 +3355,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 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 +00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 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 (IDENT RESPONSE) = 0 @@ -3366,12 +3366,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0 PROCESSING IDENT REQUEST from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -3387,7 +3387,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 @@ -3396,7 +3396,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 44 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 +00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 result (IDENT RESPONSE) = 44 @@ -3408,16 +3408,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0 PROCESSING ATTACH ACCEPT from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 de ad 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 c0 0f 73 04 50 22 97 +00 00 10 02 00 80 00 de ad 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 c0 de ad 01 0c 0a 29 result (ATTACH ACCEPT) = 92 @@ -3431,12 +3431,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 35 @@ -3454,7 +3454,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING GMM INFO from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 88 41 c0 09 08 21 04 ba 3d @@ -3463,7 +3463,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 c0 0f 73 04 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 88 41 c0 09 08 21 04 ba 3d +00 00 10 02 00 c0 de ad 01 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 88 41 c0 09 08 21 04 ba 3d result (GMM INFO) = 70 @@ -3477,12 +3477,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING XID (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 CALLBACK, event 0, msg length 38, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 42 @@ -3498,15 +3498,15 @@ CALLBACK, event 0, msg length 70, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 74 -00 00 10 02 00 c0 0f 73 04 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e +00 00 10 02 00 c0 de ad 01 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e result (XID (DL)) = 74 PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 CALLBACK, event 0, msg length 89, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 93 @@ -3522,7 +3522,7 @@ CALLBACK, event 0, msg length 267, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 271 -00 00 10 02 00 c0 0f 73 04 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 +00 00 10 02 00 c0 de ad 01 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 result (LL11 DNS RESP (DL)) = 271 @@ -3536,12 +3536,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 @@ -3559,7 +3559,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING LLC_DISCARDED from 0x05060708:32000 00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c @@ -3582,12 +3582,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING BVC_SUSPEND from 0x01020304:1111 -00 00 00 00 0b 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 CALLBACK, event 0, msg length 15, bvci 0x0000 -00 00 00 00 0b 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 19 @@ -3605,7 +3605,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000 00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 @@ -3614,7 +3614,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -3628,12 +3628,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 ee e1 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 ee e1 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 ee e1 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 ee e1 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 @@ -3667,7 +3667,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -3676,10 +3676,10 @@ Gbproxy global: BSSGP protocol error (SGSN): 1 Patch error: no peer : 1 PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 11 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 6d b1 de NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 48 @@ -3697,7 +3697,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0 PROCESSING DETACH ACC from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 89 41 c0 0d 08 06 00 aa ab ee @@ -3706,7 +3706,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 c0 0f 73 04 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 89 41 c0 0d 08 06 00 aa ab ee +00 00 10 02 00 c0 de ad 01 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 89 41 c0 0d 08 06 00 aa ab ee result (DETACH ACC) = 71 @@ -3739,7 +3739,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 85 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 89 -00 00 10 02 01 7e b5 2d fb 00 00 04 08 88 21 63 54 00 63 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 78 de ad 02 00 00 04 08 88 21 63 54 00 63 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 (IDENT RESPONSE) = 0 @@ -3753,16 +3753,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7eb52dfb, IMSI 12131415161718, AGE 0 + TLLI 8000dead -> 78dead02, IMSI 12131415161718, AGE 0 PROCESSING RA UDP ACC from 0x05060708:32000 -00 00 10 02 00 7e b5 2d fb 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 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 +00 00 10 02 00 78 de ad 02 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 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 CALLBACK, event 0, msg length 87, bvci 0x1002 -00 00 10 02 00 7e b5 2d fb 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 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 +00 00 10 02 00 78 de ad 02 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 9d 41 c0 11 08 09 00 49 21 63 54 40 50 60 19 54 ab b3 18 05 f4 ef e2 b7 00 17 16 36 98 77 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 87 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 91 -00 00 10 02 00 80 00 de ad 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 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 e6 56 aa 1f 17 16 cb d8 0b +00 00 10 02 00 80 00 de ad 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 9d 41 c0 11 08 09 00 49 11 22 33 40 50 60 19 54 ab b3 18 05 f4 c0 de ad 03 17 16 6e 58 26 result (RA UDP ACC) = 91 @@ -3776,16 +3776,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/e656aa1f -> 7eb52dfb/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead03 -> 78dead02/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 1d 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb aa cc a3 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 28 -00 00 10 02 00 c0 0f 73 04 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 06 00 11 f5 c0 +00 00 10 02 00 c0 de ad 01 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 06 00 11 f5 c0 result (DETACH REQ) = 0 @@ -3799,7 +3799,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/e656aa1f -> 7eb52dfb/efe2b700, IMSI 12131415161718, AGE 0 + TLLI 8000dead/c0dead03 -> 78dead02/efe2b700, IMSI 12131415161718, AGE 0 PROCESSING DETACH ACC from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 89 41 c0 15 08 06 00 f7 35 f0 @@ -3808,7 +3808,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 e6 56 aa 1f 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 89 41 c0 15 08 06 00 f7 35 f0 +00 00 10 02 00 c0 de ad 03 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 89 41 c0 15 08 06 00 f7 35 f0 result (DETACH ACC) = 71 @@ -4181,7 +4181,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 + TLLI 8000dead -> 78dead00, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 05 08 16 08 11 12 13 14 15 16 17 18 ad 05 28 @@ -4190,7 +4190,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 79 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 00 63 60 12 34 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 78 de ad 00 00 00 04 08 88 21 63 54 00 63 60 12 34 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 (IDENT RESPONSE) = 0 @@ -4201,12 +4201,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT REQUEST from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba +00 00 10 02 00 78 de ad 00 00 50 20 16 82 02 58 0e 89 41 c0 01 08 15 01 ff 6c ba NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -4222,7 +4222,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 de ad 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 @@ -4231,7 +4231,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 44 -00 00 10 02 01 7c 69 fb 81 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 +00 00 10 02 01 78 de ad 00 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 09 08 16 08 11 12 13 14 15 16 17 18 ba 14 c3 result (IDENT RESPONSE) = 44 @@ -4243,16 +4243,16 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead -> 7c69fb81, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000dead -> 78dead00, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH ACCEPT from 0x05060708:32000 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7c 69 fb 81 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 ef e2 b7 00 53 62 f1 +00 00 10 02 00 78 de ad 00 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 ef e2 b7 00 53 62 f1 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 de ad 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 c0 0f 73 04 50 22 97 +00 00 10 02 00 80 00 de ad 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 c0 de ad 01 0c 0a 29 result (ATTACH ACCEPT) = 92 @@ -4266,12 +4266,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 0d 08 03 55 1c ea NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 35 @@ -4289,7 +4289,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI 8000dead/c00f7304 -> 7c69fb81/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000dead/c0dead01 -> 78dead00/efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING GMM INFO from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 88 41 c0 09 08 21 04 ba 3d @@ -4298,7 +4298,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 c0 0f 73 04 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 88 41 c0 09 08 21 04 ba 3d +00 00 10 02 00 c0 de ad 01 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 88 41 c0 09 08 21 04 ba 3d result (GMM INFO) = 70 @@ -4312,12 +4312,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING XID (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 CALLBACK, event 0, msg length 38, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 42 @@ -4333,15 +4333,15 @@ CALLBACK, event 0, msg length 70, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 74 -00 00 10 02 00 c0 0f 73 04 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e +00 00 10 02 00 c0 de ad 01 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 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e result (XID (DL)) = 74 PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 CALLBACK, event 0, msg length 89, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 93 @@ -4357,7 +4357,7 @@ CALLBACK, event 0, msg length 267, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 271 -00 00 10 02 00 c0 0f 73 04 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 +00 00 10 02 00 c0 de ad 01 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 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 result (LL11 DNS RESP (DL)) = 271 @@ -4371,12 +4371,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 c0 0f 73 04 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 01 0f 81 01 04 82 10 02 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 23 @@ -4394,7 +4394,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING LLC_DISCARDED from 0x05060708:32000 00 00 00 00 2c 1f 84 ef e2 b7 00 0f 81 01 04 82 10 02 25 83 00 00 0c @@ -4417,12 +4417,12 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING BVC_SUSPEND from 0x01020304:1111 -00 00 00 00 0b 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 CALLBACK, event 0, msg length 15, bvci 0x0000 -00 00 00 00 0b 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 NS UNITDATA MESSAGE to SGSN, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 19 @@ -4440,7 +4440,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING BVC_SUSPEND_ACK from 0x05060708:32000 00 00 00 00 0c 1f 84 ef e2 b7 00 1b 86 21 63 54 40 50 60 1d 81 01 @@ -4449,7 +4449,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 c0 0f 73 04 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 01 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -4463,7 +4463,7 @@ Peers: Attach Request count : 1 TLLI cache size : 1 TLLI-Cache: 1 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 --- Establish GPRS connection (SGSN 2) --- PROCESSING ATTACH REQUEST from 0x01020304:1111 @@ -4488,8 +4488,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef -> 7eb52dfb, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef -> 78dead02, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 15 08 16 08 11 12 99 99 99 16 17 18 b2 dd 58 @@ -4498,7 +4498,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 79 -00 00 10 02 01 7e b5 2d fb 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 11 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 bf 00 5c +00 00 10 02 01 78 de ad 02 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 11 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 bf 00 5c result (IDENT RESPONSE) = 0 @@ -4512,13 +4512,13 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef -> 7eb52dfb, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT REQUEST from 0x15161718:32001 -00 00 10 02 00 7e b5 2d fb 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 +00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7e b5 2d fb 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 +00 00 10 02 00 78 de ad 02 00 50 20 16 82 02 58 0e 89 41 c0 0d 08 15 01 0c a6 18 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -4536,8 +4536,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef -> 7eb52dfb, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 be ef 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 @@ -4546,7 +4546,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 44 -00 00 10 02 01 7e b5 2d fb 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 +00 00 10 02 01 78 de ad 02 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 19 08 16 08 11 12 99 99 99 16 17 18 a5 cc b3 result (IDENT RESPONSE) = 0 @@ -4560,17 +4560,17 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef -> 7eb52dfb, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef -> 78dead02, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH ACCEPT from 0x15161718:32001 -00 00 10 02 00 7e b5 2d fb 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b +00 00 10 02 00 78 de ad 02 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7e b5 2d fb 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b +00 00 10 02 00 78 de ad 02 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 e0 98 76 54 cb 1c 5b NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 be ef 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 e6 56 aa 1f 8c 69 67 +00 00 10 02 00 80 00 be ef 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 99 99 99 16 17 18 00 81 00 0e 9e 41 c0 11 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 03 32 40 fa result (ATTACH ACCEPT) = 92 @@ -4584,13 +4584,13 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef/e656aa1f -> 7eb52dfb/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef/c0dead03 -> 78dead02/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 1d 08 03 5e 3a ea NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 35 @@ -4608,8 +4608,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI 8000beef/e656aa1f -> 7eb52dfb/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000beef/c0dead03 -> 78dead02/e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING GMM INFO from 0x15161718:32001 00 00 10 02 00 e0 98 76 54 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 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 @@ -4618,7 +4618,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 e6 56 aa 1f 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 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 +00 00 10 02 00 c0 de ad 03 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 99 99 99 16 17 18 00 81 00 0e 88 41 c0 15 08 21 bb c1 c6 result (GMM INFO) = 70 @@ -4632,13 +4632,13 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING XID (UL) from 0x01020304:1111 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 CALLBACK, event 0, msg length 38, bvci 0x1002 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 0f 41 fb 01 00 0e 00 64 11 05 16 01 90 66 b3 28 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 38 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 42 @@ -4654,15 +4654,15 @@ CALLBACK, event 0, msg length 70, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 70 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 74 -00 00 10 02 00 e6 56 aa 1f 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 99 99 99 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e +00 00 10 02 00 c0 de ad 03 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 99 99 99 16 17 18 00 81 00 0e 8c 41 fb 30 84 10 61 b6 64 e4 a9 1a 9e result (XID (DL)) = 74 PROCESSING LL11 DNS QUERY (UL) from 0x01020304:1111 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 CALLBACK, event 0, msg length 89, bvci 0x1002 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 42 0b c0 01 65 00 00 00 45 00 00 38 95 72 00 00 45 11 20 85 0a c0 07 e4 ac 10 01 0a ad ab 00 35 00 24 0e 1c 3b e0 01 00 00 01 00 00 00 00 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 47 8f 07 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 89 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 93 @@ -4678,7 +4678,7 @@ CALLBACK, event 0, msg length 267, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 267 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 271 -00 00 10 02 00 e6 56 aa 1f 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 99 99 99 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 +00 00 10 02 00 c0 de ad 03 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 99 99 99 16 17 18 00 81 00 0e 00 d0 4b c0 01 65 00 00 00 45 00 00 c6 00 00 40 00 3e 11 7c 69 ac 10 01 0a 0a c0 07 e4 00 35 ad ab 00 b2 74 4e 3b e0 81 80 00 01 00 01 00 05 00 00 01 6d 05 68 65 69 73 65 02 64 65 00 00 01 00 01 c0 0c 00 01 00 01 00 00 0e 10 00 04 c1 63 90 58 c0 0e 00 02 00 01 00 00 0e 10 00 16 03 6e 73 32 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 03 6e 65 74 00 c0 0e 00 02 00 01 00 00 0e 10 00 10 02 6e 73 01 73 08 70 6c 75 73 6c 69 6e 65 c0 14 c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 0e c0 0e 00 02 00 01 00 00 0e 10 00 05 02 6e 73 c0 5f c0 0e 00 02 00 01 00 00 0e 10 00 12 02 6e 73 0c 70 6f 70 2d 68 61 6e 6e 6f 76 65 72 c0 14 aa df 31 result (LL11 DNS RESP (DL)) = 271 @@ -4692,13 +4692,13 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING LLC_DISCARDED from 0x01020304:1111 -00 00 00 00 2c 1f 84 e6 56 aa 1f 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c CALLBACK, event 0, msg length 19, bvci 0x0000 -00 00 00 00 2c 1f 84 e6 56 aa 1f 0f 81 01 04 82 10 02 25 83 00 00 0c +00 00 00 00 2c 1f 84 c0 de ad 03 0f 81 01 04 82 10 02 25 83 00 00 0c NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 19 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 23 @@ -4716,8 +4716,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING LLC_DISCARDED from 0x15161718:32001 00 00 00 00 2c 1f 84 e0 98 76 54 0f 81 01 04 82 10 02 25 83 00 00 0c @@ -4740,13 +4740,13 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING BVC_SUSPEND from 0x01020304:1111 -00 00 00 00 0b 1f 84 e6 56 aa 1f 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 CALLBACK, event 0, msg length 15, bvci 0x0000 -00 00 00 00 0b 1f 84 e6 56 aa 1f 1b 86 11 22 33 40 50 60 +00 00 00 00 0b 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x0000, msg length 15 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 19 @@ -4764,8 +4764,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING BVC_SUSPEND_ACK from 0x15161718:32001 00 00 00 00 0c 1f 84 e0 98 76 54 1b 86 21 63 54 40 50 60 1d 81 01 @@ -4774,7 +4774,7 @@ CALLBACK, event 0, msg length 18, bvci 0x0000 NS UNITDATA MESSAGE to BSS, BVCI 0x0000, msg length 18 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 22 -00 00 00 00 0c 1f 84 e6 56 aa 1f 1b 86 11 22 33 40 50 60 1d 81 01 +00 00 00 00 0c 1f 84 c0 de ad 03 1b 86 11 22 33 40 50 60 1d 81 01 result (BVC_SUSPEND_ACK) = 22 @@ -4788,8 +4788,8 @@ Peers: Attach Request count : 2 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 --- Establish GPRS connection (SGSN 2, P-TMSI collision) --- PROCESSING ATTACH REQUEST from 0x01020304:1111 @@ -4814,9 +4814,9 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed -> 7e23ef54, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed -> 78dead04, IMSI (none), AGE 0, STORED 1, IMSI acquisition in progress, SGSN NSEI 65535 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 25 08 16 08 11 12 99 99 99 26 27 28 58 c7 cb @@ -4825,7 +4825,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 75 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 79 -00 00 10 02 01 7e 23 ef 54 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 21 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 44 b6 bb +00 00 10 02 01 78 de ad 04 00 00 04 08 88 21 63 54 00 63 60 12 34 00 80 0e 00 34 01 c0 21 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 44 b6 bb result (IDENT RESPONSE) = 0 @@ -4839,14 +4839,14 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed -> 7e23ef54, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT REQUEST from 0x15161718:32001 -00 00 10 02 00 7e 23 ef 54 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 +00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 CALLBACK, event 0, msg length 23, bvci 0x1002 -00 00 10 02 00 7e 23 ef 54 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 +00 00 10 02 00 78 de ad 04 00 50 20 16 82 02 58 0e 89 41 c0 19 08 15 01 a2 f2 a4 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 23 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 27 @@ -4864,9 +4864,9 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed -> 7e23ef54, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING IDENT RESPONSE from 0x01020304:1111 00 00 10 02 01 80 00 fe ed 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 @@ -4875,7 +4875,7 @@ CALLBACK, event 0, msg length 40, bvci 0x1002 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 40 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 44 -00 00 10 02 01 7e 23 ef 54 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 +00 00 10 02 01 78 de ad 04 00 00 04 08 88 21 63 54 40 50 60 12 34 00 80 0e 00 11 01 c0 29 08 16 08 11 12 99 99 99 26 27 28 4f d6 20 result (IDENT RESPONSE) = 0 @@ -4889,18 +4889,18 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed -> 7e23ef54, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed -> 78dead04, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH ACCEPT (P-TMSI 1) from 0x15161718:32001 -00 00 10 02 00 7e 23 ef 54 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 +00 00 10 02 00 78 de ad 04 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 CALLBACK, event 0, msg length 88, bvci 0x1002 -00 00 10 02 00 7e 23 ef 54 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 +00 00 10 02 00 78 de ad 04 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 21 63 54 40 50 60 19 cd d7 08 17 16 18 05 f4 ef e2 b7 00 74 91 01 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 88 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 92 -00 00 10 02 00 80 00 fe ed 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 ea d4 77 5a c4 f8 6d +00 00 10 02 00 80 00 fe ed 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 99 99 99 26 27 28 00 81 00 0e 9e 41 c0 1d 08 02 01 49 04 11 22 33 40 50 60 19 cd d7 08 17 16 18 05 f4 c0 de ad 05 3e 78 6e result (ATTACH ACCEPT (P-TMSI 1)) = 92 @@ -4914,14 +4914,14 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed/ead4775a -> 7e23ef54/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed/c0dead05 -> 78dead04/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING ATTACH COMPLETE from 0x01020304:1111 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea +00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea CALLBACK, event 0, msg length 31, bvci 0x1002 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea +00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 08 01 c0 2d 08 03 43 50 ea NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 31 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 35 @@ -4939,9 +4939,9 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI 8000feed/ead4775a -> 7e23ef54/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI 8000feed/c0dead05 -> 78dead04/efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 PROCESSING GMM INFO from 0x15161718:32001 00 00 10 02 00 ef e2 b7 00 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 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 @@ -4950,7 +4950,7 @@ CALLBACK, event 0, msg length 66, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 66 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 70 -00 00 10 02 00 ea d4 77 5a 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 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 +00 00 10 02 00 c0 de ad 05 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 99 99 99 26 27 28 00 81 00 0e 88 41 c0 21 08 21 ca 60 90 result (GMM INFO) = 70 @@ -4964,16 +4964,16 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 --- Shutdown GPRS connection (SGSN 1) --- PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 c0 0f 73 04 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 +00 00 10 02 01 c0 de ad 01 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 31 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 57 e6 15 NS UNITDATA MESSAGE to SGSN, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN at 0x05060708:32000, msg length 48 @@ -4991,9 +4991,9 @@ Peers: Attach Request count : 3 TLLI cache size : 3 TLLI-Cache: 3 - TLLI c00f7304 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead01 -> efe2b700, IMSI 12131415161718, AGE 0, SGSN NSEI 256 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 PROCESSING DETACH ACC from 0x05060708:32000 00 00 10 02 00 ef e2 b7 00 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 89 41 c0 25 08 06 00 4d 09 cd @@ -5002,7 +5002,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 c0 0f 73 04 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 89 41 c0 25 08 06 00 4d 09 cd +00 00 10 02 00 c0 de ad 01 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 89 41 c0 25 08 06 00 4d 09 cd result (DETACH ACC) = 71 @@ -5016,15 +5016,15 @@ Peers: Attach Request count : 3 TLLI cache size : 2 TLLI-Cache: 2 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 --- Shutdown GPRS connection (SGSN 2) --- PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 e6 56 aa 1f 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 +00 00 10 02 01 c0 de ad 03 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 35 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 83 cb f7 NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 48 @@ -5043,8 +5043,8 @@ Peers: Attach Request count : 3 TLLI cache size : 2 TLLI-Cache: 2 - TLLI e656aa1f -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead03 -> e0987654, IMSI 12199999961718, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 PROCESSING DETACH ACC from 0x15161718:32001 00 00 10 02 00 e0 98 76 54 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 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f @@ -5053,7 +5053,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 e6 56 aa 1f 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 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f +00 00 10 02 00 c0 de ad 03 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 99 99 99 16 17 18 00 81 00 0e 89 41 c0 29 08 06 00 be c3 6f result (DETACH ACC) = 71 @@ -5068,14 +5068,14 @@ Peers: Attach Request count : 3 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 --- Shutdown GPRS connection (SGSN 2, P-TMSI 1) --- PROCESSING DETACH REQ from 0x01020304:1111 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a +00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a CALLBACK, event 0, msg length 44, bvci 0x1002 -00 00 10 02 01 ea d4 77 5a 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a +00 00 10 02 01 c0 de ad 05 00 00 04 08 88 11 22 33 40 50 60 12 34 00 80 0e 00 15 01 c0 39 08 05 01 18 05 f4 ef e2 b7 00 19 03 b9 97 cb 44 b6 8a NS UNITDATA MESSAGE to SGSN 2, BVCI 0x1002, msg length 44 (gprs_ns_sendmsg) MESSAGE to SGSN 2 at 0x15161718:32001, msg length 48 @@ -5094,7 +5094,7 @@ Peers: Attach Request count : 3 TLLI cache size : 1 TLLI-Cache: 1 - TLLI ead4775a -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 + TLLI c0dead05 -> efe2b700, IMSI 12199999962728, AGE 0, IMSI matches, SGSN NSEI 258 PROCESSING DETACH ACC from 0x15161718:32001 00 00 10 02 00 ef e2 b7 00 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 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 @@ -5103,7 +5103,7 @@ CALLBACK, event 0, msg length 67, bvci 0x1002 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 67 (gprs_ns_sendmsg) MESSAGE to BSS at 0x01020304:1111, msg length 71 -00 00 10 02 00 ea d4 77 5a 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 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 +00 00 10 02 00 c0 de ad 05 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 99 99 99 26 27 28 00 81 00 0e 89 41 c0 2d 08 06 00 86 7c c7 result (DETACH ACC) = 71 -- 2.1.4 From nhofmeyr at sysmocom.de Tue Oct 13 09:36:33 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 13 Oct 2015 11:36:33 +0200 Subject: [openbsc 2/5] sgsn/test: Really parse received DL LLC messages In-Reply-To: <9e26901bb4f2cb4aec99eab029b917e84d9101bd.1444671220.git.dwillmann@sysmocom.de> References: <9e26901bb4f2cb4aec99eab029b917e84d9101bd.1444671220.git.dwillmann@sysmocom.de> Message-ID: <20151013093633.GA1563@dub5> Interesting how reset_last_msg() and bssgp_tx_dl_ud() use the global last_dl_parse_ctx directly, while get_new_ptmsi() receives it as argument :) ~Neels On Mon, Oct 12, 2015 at 07:36:32PM +0200, Daniel Willmann wrote: > unsigned sgsn_tx_counter = 0; > +struct msgb *last_msg = NULL; > +struct gprs_gb_parse_context last_dl_parse_ctx; > + > +static void reset_last_msg() > +{ > + if (last_msg) > + msgb_free(last_msg); > + > + last_msg = NULL; > + memset(&last_dl_parse_ctx, 0, sizeof(last_dl_parse_ctx)); > +} > > static void cleanup_test() > { > + reset_last_msg(); > +} > + > +static uint32_t get_new_ptmsi(const struct gprs_gb_parse_context *parse_ctx) > +{ > + uint32_t new_ptmsi = GSM_RESERVED_TMSI; > + > + if (parse_ctx->new_ptmsi_enc) > + gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi); > + > + return new_ptmsi; > } > > /* override */ > int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime, > struct bssgp_dl_ud_par *dup) > { > + int rc; > + > + reset_last_msg(); > + > + last_msg = msg; > + OSMO_ASSERT(msgb_data(last_msg) != NULL); > + > + rc = gprs_gb_parse_llc(msgb_data(last_msg), msgb_length(last_msg), > + &last_dl_parse_ctx); > + > + fprintf(stderr, "Got DL LLC message: %s\n", > + gprs_gb_message_name(&last_dl_parse_ctx, "UNKNOWN")); > + > + OSMO_ASSERT(rc > 0); > + > sgsn_tx_counter += 1; > - msgb_free(msg); > return 0; > } -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From ravi.varun00 at gmail.com Tue Oct 13 09:54:12 2015 From: ravi.varun00 at gmail.com (Ravi Shankar) Date: Tue, 13 Oct 2015 15:24:12 +0530 Subject: Authorization using IMEI Message-ID: Dear Sir It's mentioned on the site that the non-secure authorization is feasible with IMEI/IMSI. How can we authorize any MS using IMEI ?? I mean, the authorization field is in the Subscriber table of the database so how is it possible to set authorization with IMEI number. Regards. -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcin.starzyk at gmail.com Tue Oct 13 12:12:31 2015 From: marcin.starzyk at gmail.com (Marcin Starzyk) Date: Tue, 13 Oct 2015 14:12:31 +0200 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault Message-ID: Hi All, I?m facing an issue with osmo-nitb (HLR/sqlite part) - segmentation fault. All works ok for the first usage od DB (e.g. Location Updating Request) ? but there is segmentation fault on second Location Updating request or any other attempt to execute any command using VTY for HLR. Syslog____________________________________________________________________________ Oct 12 20:32:29 debian kernel: [ 2397.242984] osmo-nitb[985]: segfault at 64692e74 ip b77c15c9 sp bf8688b0 error 4 in libdbdsqlite3.so[b77be000+8000] Part of bt__________________________________________________________________________ #0 0xb77c15c9 in ?? () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so #1 0xb77c17e4 in ?? () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so #2 0xb77c26f7 in dbd_query () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so No symbol table info available. Can anybody please advise? Thank you, Regards, Marcin Attached files -Tcpump (between nanoBTS(.34) and BSC (.20)) -Debug output, backtrace, syslog below Debug-output 1/2________________________________________________________________________ <0004> abis_rsl.c:1465 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(514) SS(0) lctype SDCCH r=LOCATION_UPDATE ra=0x01 ta=0 <0004> abis_rsl.c:1199 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:1136 LOCATION UPDATING REQUEST: MI(IMSI)=260060059332155 type=NORMAL <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x18 to MS. <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0003> bsc_api.c:500 CLASSMARK CHANGE CM2(len=3) CM3(len=7) <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:523 IDENTITY RESPONSE: MI(IMEI)=359809011036930 <0002> gsm_04_08.c:568 Location Updating Request procedure timedout. <0002> gsm_04_08.c:452 Subscriber 260060059332155: LOCATION UPDATING REJECT LAC=1 BTS=0 <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x04 to MS. <0000> chan_alloc.c:324 (bts=0,trx=0,ts=0,ss=0) starting release sequence <0003> gsm_04_08_utils.c:239 Sending Channel Release: Chan: Number: 0 Type: 1 <0004> abis_rsl.c:616 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD DB-ouput___________________________________________________________________________ sqlite> select * from subscriber ; 1|2015-10-12 18:31:38|2015-10-12 18:31:39|260060059332155||22685|0||0| Debug-output 2/2_____________________________________________________________________ <0004> abis_rsl.c:1465 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(514) SS(0) lctype SDCCH r=LOCATION_UPDATE ra=0x07 ta=0 <0004> abis_rsl.c:1199 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK 0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:1136 LOCATION UPDATING REQUEST: MI(IMSI)=260060059332155 type=NORMAL <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x18 to MS. Segmentation fault (core dumped) Syslog____________________________________________________________________________ Oct 12 20:32:29 debian kernel: [ 2397.242984] osmo-nitb[985]: segfault at 64692e74 ip b77c15c9 sp bf8688b0 error 4 in libdbdsqlite3.so[b77be000+8000] Backtrace__________________________________________________________________________ root at debian:~/openbsc/openbsc/src/osmo-nitb# gdb osmo-nitb core GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1 Copyright (C) 2014 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i586-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: . Find the GDB manual and other documentation resources online at: . For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from osmo-nitb...done. [New LWP 985] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/i386-linux-gnu/i686/cmov/libthread_db.so.1". Core was generated by `./osmo-nitb --debug=DRLL:DCC:DMM:DRR:DRSL:DNM'. Program terminated with signal SIGSEGV, Segmentation fault. #0 0xb77c15c9 in ?? () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so (gdb) bt full #0 0xb77c15c9 in ?? () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so No symbol table info available. #1 0xb77c17e4 in ?? () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so No symbol table info available. #2 0xb77c26f7 in dbd_query () from /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so No symbol table info available. #3 0xb77a7122 in dbi_conn_queryf () from /usr/lib/i386-linux-gnu/libdbi.so.1 No symbol table info available. #4 0x0806f99f in get_equipment_by_subscr (subscr=0x9055b60) at db.c:550 result = 0x9053520 cm2 = 0xbf8688e4 "" cm3 = 0xbf8688e4 "" #5 0x08070523 in db_get_subscriber (field=151346016, id=0xbf868e00 "260060059332155") at db.c:897 result = 0x9053520 quoted = 0x904fa58 "x4q\267x5\005\t2015-10-12 18:31:39" subscr = 0x9055b60 #6 0x0807423a in get_subscriber (ident=0xbf868e00 "260060059332155", type=0, sgrp=0x9010840) at gsm_subscriber.c:67 subscr = #7 subscr_get_by_imsi (sgrp=0x9010840, imsi=0xbf868e00 "260060059332155") at gsm_subscriber.c:240 subscr = 0x80c20e0 #8 0x0807f8a5 in mm_rx_loc_upd_req (msg=, conn=0x9063740) at gsm_04_08.c:643 subscr = 0x0 bts = 0xb7737b01 ---Type to continue, or q to quit--- mi_type = gh = 0x9063793 mi_string = "260060059332155\000\267zs\267\230+\005\t at 7 \006\t\206\353\a\b" #9 gsm0408_rcv_mm (msg=0x8085488, conn=0x9063740) at gsm_04_08.c:1137 gh = rc = 0 #10 gsm0408_dispatch (conn=0x9052b98, msg=0x9063740) at gsm_04_08.c:3594 gh = pdisc = rc = 0 #11 0x0807895a in msc_compl_l3 (conn=0x9052b98, msg=0x9063740, chosen_channel=0) at osmo_msc.c:49 No locals. #12 0x0804e468 in gsm0408_rcvmsg (msg=0x9063740, link_id=0 '\000') at bsc_api.c:684 rc = -1081702172 #13 0x0806619b in abis_rsl_rx_rll (msg=) at abis_rsl.c:1674 ts_name = 0xbf8688e4 "" sapi = 0 '\000' #14 abis_rsl_rcvmsg (msg=0x9063740) at abis_rsl.c:2085 rc = 151402378 #15 0xb771f107 in handle_ts1_read (bfd=) at input/ipaccess.c:271 link = 0xbf8688e4 hh = 0x5 msg = 0x9063740 ---Type to continue, or q to quit--- ts_nr = 3077720460 #16 ipaccess_fd_cb (bfd=0x9056b30, what=1) at input/ipaccess.c:386 rc = 151348668 #17 0xb77380d8 in osmo_select_main (polling=0) at select.c:160 flags = 1 ufd = 0x9056b30 tmp = 0xb7754524 readset = {__fds_bits = {0 }} writeset = {__fds_bits = {0 }} exceptset = {__fds_bits = {0 }} work = 1 rc = no_time = {tv_sec = 0, tv_usec = 0} #18 0x0804c8bf in main (argc=2, argv=0xbf869214) at bsc_hack.c:356 rc = -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: osmo-nitb-seg_faultv1.cap Type: application/octet-stream Size: 49623 bytes Desc: not available URL: From palm.wang at hotmail.com Wed Oct 14 00:46:08 2015 From: palm.wang at hotmail.com (wangpalm) Date: Wed, 14 Oct 2015 08:46:08 +0800 Subject: EGPRS(EDGE) data rate is not stable? Message-ID: With phone attached to my configured EGPRS, sometimes it has a data rate around 200kbps (which is near optimal), while frequently it has a intolerablly slow data rate. Is it a common problem, or it's due to incorrect configrations or hardware problems? I run a gsm test system with nanobts, and the libosmocore, openbsc, openggsn codes are based on the version around end of April 2015. The configuration is made accorrding to the instruction from openbsc web. The correction in fc_queue_timer_cfg has also been made according to Jacob Erlbeck. -------------- next part -------------- An HTML attachment was scrubbed... URL: From nhofmeyr at sysmocom.de Wed Oct 14 20:53:54 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 14 Oct 2015 22:53:54 +0200 Subject: recent patch set with wrong From address dwilllmann@ Message-ID: <20151014205354.GB4691@dub5> Daniel, your from address had triple l's in them. Just saying in case some config needs fixing. I noticed because I was replying on a patch and got a bounce from sysmocom.de. ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Oct 14 21:00:52 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 14 Oct 2015 23:00:52 +0200 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: References: Message-ID: <20151014210052.GC4691@dub5> Hi Marcin, just general guessing ... since the segfault is in libdbdsqlite3, maybe it's a building/linking issue? Maybe there are multiple instances of a library, or dependencies have upgraded and it needs a clean build...? ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From pablo at gnumonks.org Thu Oct 15 05:57:29 2015 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Thu, 15 Oct 2015 07:57:29 +0200 Subject: [PATCH openbsc] mgcp_osmux: available circuit IDs from 0 to 255, not from 0 to 128 Message-ID: <1444888649-12349-1-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso Holger reports that the bitmap that accounts for available Osmux circuit IDs is limited to 128, when the maximum number of circuit IDs are determined by the uint8_t field in the header (ie. 256 circuits). --- @Holger: Will be revisiting libosmo-netif too, at quick glance I can see insufficient validation of several functions there that take this allocated ccid as input parameter. openbsc/src/libmgcp/mgcp_osmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsc/src/libmgcp/mgcp_osmux.c b/openbsc/src/libmgcp/mgcp_osmux.c index 90b7368..d110f42 100644 --- a/openbsc/src/libmgcp/mgcp_osmux.c +++ b/openbsc/src/libmgcp/mgcp_osmux.c @@ -530,7 +530,7 @@ int osmux_send_dummy(struct mgcp_endpoint *endp) } /* bsc-nat allocates/releases the Osmux circuit ID */ -static uint8_t osmux_cid_bitmap[16]; +static uint8_t osmux_cid_bitmap[(OSMUX_CID_MAX + 1) / 8]; int osmux_get_cid(void) { -- 2.1.4 From pablo at gnumonks.org Thu Oct 15 06:12:02 2015 From: pablo at gnumonks.org (pablo at gnumonks.org) Date: Thu, 15 Oct 2015 08:12:02 +0200 Subject: [PATCH] initial commit for libosmo-gtp Message-ID: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> From: Pablo Neira Ayuso I started this libosmo-gtp library after spending quite some time trying to clean up libgtp and add IPv6 support to it in some clean way. The result was this library that I started from scratch in my spare time. The basic idea behind this is to avoid mixing the carrier (socket) code with the message building and parsing, and avoid overly the complicated callback scheme of libgtp. This implements minimal support for GTPv0, it also includes automated tests by generating GTPv0 messages then hand it over to gtp0_recv() which generates the reply. I remember that I also validated this code by sending GTPv0 messages over UDP to inspect them through wireshark, and they were OK. It's fairly incomplete. The only client I have for this library is an initial (fairly incomplete) osmo-gtp daemon using this library to replace opengtp. BTW, there's a src/libosmocore.c file that contains helper functions to provide a more consistent way to work with different TLV types. Probably it can be uploaded to the osmocom repository even if incomplete? Well, just wanted to get this code out there, it got stuck here and I didn't find so far more time to make more progress on it, but we'll try to update it when traveling or something. .gitignore | 43 +++ Makefile.am | 13 + configure.ac | 42 +++ git-version-gen | 151 +++++++++++ include/Makefile.am | 3 + include/gtp.h | 102 +++++++ include/libosmocore.h | 20 ++ include/osmocom/gtp/gtp.h | 49 ++++ libosmogtp.pc.in | 11 + src/Makefile.am | 15 ++ src/gtp.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++ src/libosmocore.c | 70 +++++ tests/Makefile.am | 52 ++++ tests/gtp/gtp_test.ok | 0 tests/gtp_test.c | 121 +++++++++ tests/gtp_test.ok | 4 + tests/testsuite.at | 18 ++ 17 files changed, 1383 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 configure.ac create mode 100755 git-version-gen create mode 100644 include/Makefile.am create mode 100644 include/gtp.h create mode 100644 include/libosmocore.h create mode 100644 include/osmocom/gtp/gtp.h create mode 100644 libosmogtp.pc.in create mode 100644 src/Makefile.am create mode 100644 src/gtp.c create mode 100644 src/libosmocore.c create mode 100644 tests/Makefile.am create mode 100644 tests/gtp/gtp_test.ok create mode 100644 tests/gtp_test.c create mode 100644 tests/gtp_test.ok create mode 100644 tests/testsuite.at diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ee984ce --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +Makefile +Makefile.in +.deps +.libs +*.o +*.lo +*.la +*.pc +aclocal.m4 +m4/*.m4 +autom4te.cache +config.h* +config.sub +config.log +config.status +config.guess +configure +compile +depcomp +missing +ltmain.sh +install-sh +stamp-h1 +libtool +#libosmo-abis-* +tests/*_test + +.tarball-version +.version +.dirstamp + +# tests +tests/atconfig +tests/package.m4 +tests/testsuite +tests/testsuite.log +tests/testsuite.dir/ +tests/gtp_test + + + +# vi/vim files +*.sw? diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..5ab1484 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +ACLOCAL_AMFLAGS = -I m4 + +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +SUBDIRS = include src tests + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libosmogtp.pc + +BUILT_SOURCES = $(top_srcdir)/.version +$(top_srcdir)/.version: + echo $(VERSION) > $@-t && mv $@-t $@ +dist-hook: + echo $(VERSION) > $(distdir)/.tarball-version diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..c22fab4 --- /dev/null +++ b/configure.ac @@ -0,0 +1,42 @@ +AC_INIT([libosmogtp], + m4_esyscmd([./git-version-gen .tarball-version]), + [gprs at lists.osmocom.org]) + +AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip 1.6]) +AC_CONFIG_TESTDIR(tests) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl checks for programs +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_INSTALL +LT_INIT([pic-only]) + +AC_CONFIG_MACRO_DIR([m4]) + +# The following test is taken from WebKit's webkit.m4 +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fvisibility=hidden " +AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([char foo;])], + [ AC_MSG_RESULT([yes]) + SYMBOL_VISIBILITY="-fvisibility=hidden"], + AC_MSG_RESULT([no])) +CFLAGS="$saved_CFLAGS" +AC_SUBST(SYMBOL_VISIBILITY) + +dnl Generate the output +AM_CONFIG_HEADER(config.h) + +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.3.0) +PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0) +PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.3.10) + +AC_OUTPUT( + libosmogtp.pc + include/Makefile + src/Makefile + tests/Makefile + Makefile) diff --git a/git-version-gen b/git-version-gen new file mode 100755 index 0000000..42cf3d2 --- /dev/null +++ b/git-version-gen @@ -0,0 +1,151 @@ +#!/bin/sh +# Print a version string. +scriptversion=2010-01-28.01 + +# Copyright (C) 2007-2010 Free Software Foundation, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/. +# It may be run two ways: +# - from a git repository in which the "git describe" command below +# produces useful output (thus requiring at least one signed tag) +# - from a non-git-repo directory containing a .tarball-version file, which +# presumes this script is invoked like "./git-version-gen .tarball-version". + +# In order to use intra-version strings in your project, you will need two +# separate generated version string files: +# +# .tarball-version - present only in a distribution tarball, and not in +# a checked-out repository. Created with contents that were learned at +# the last time autoconf was run, and used by git-version-gen. Must not +# be present in either $(srcdir) or $(builddir) for git-version-gen to +# give accurate answers during normal development with a checked out tree, +# but must be present in a tarball when there is no version control system. +# Therefore, it cannot be used in any dependencies. GNUmakefile has +# hooks to force a reconfigure at distribution time to get the value +# correct, without penalizing normal development with extra reconfigures. +# +# .version - present in a checked-out repository and in a distribution +# tarball. Usable in dependencies, particularly for files that don't +# want to depend on config.h but do want to track version changes. +# Delete this file prior to any autoconf run where you want to rebuild +# files to pick up a version string change; and leave it stale to +# minimize rebuild time after unrelated changes to configure sources. +# +# It is probably wise to add these two files to .gitignore, so that you +# don't accidentally commit either generated file. +# +# Use the following line in your configure.ac, so that $(VERSION) will +# automatically be up-to-date each time configure is run (and note that +# since configure.ac no longer includes a version string, Makefile rules +# should not depend on configure.ac for version updates). +# +# AC_INIT([GNU project], +# m4_esyscmd([build-aux/git-version-gen .tarball-version]), +# [bug-project at example]) +# +# Then use the following lines in your Makefile.am, so that .version +# will be present for dependencies, and so that .tarball-version will +# exist in distribution tarballs. +# +# BUILT_SOURCES = $(top_srcdir)/.version +# $(top_srcdir)/.version: +# echo $(VERSION) > $@-t && mv $@-t $@ +# dist-hook: +# echo $(VERSION) > $(distdir)/.tarball-version + +case $# in + 1) ;; + *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;; +esac + +tarball_version_file=$1 +nl=' +' + +# First see if there is a tarball-only version file. +# then try "git describe", then default. +if test -f $tarball_version_file +then + v=`cat $tarball_version_file` || exit 1 + case $v in + *$nl*) v= ;; # reject multi-line output + [0-9]*) ;; + *) v= ;; + esac + test -z "$v" \ + && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2 +fi + +if test -n "$v" +then + : # use $v +elif + v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \ + || git describe --abbrev=4 HEAD 2>/dev/null` \ + && case $v in + [0-9]*) ;; + v[0-9]*) ;; + *) (exit 1) ;; + esac +then + # Is this a new git that lists number of commits since the last + # tag or the previous older version that did not? + # Newer: v6.10-77-g0f8faeb + # Older: v6.10-g0f8faeb + case $v in + *-*-*) : git describe is okay three part flavor ;; + *-*) + : git describe is older two part flavor + # Recreate the number of commits and rewrite such that the + # result is the same as if we were using the newer version + # of git describe. + vtag=`echo "$v" | sed 's/-.*//'` + numcommits=`git rev-list "$vtag"..HEAD | wc -l` + v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`; + ;; + esac + + # Change the first '-' to a '.', so version-comparing tools work properly. + # Remove the "g" in git describe's output string, to save a byte. + v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`; +else + v=UNKNOWN +fi + +v=`echo "$v" |sed 's/^v//'` + +# Don't declare a version "dirty" merely because a time stamp has changed. +git status > /dev/null 2>&1 + +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty= +case "$dirty" in + '') ;; + *) # Append the suffix only if there isn't one already. + case $v in + *-dirty) ;; + *) v="$v-dirty" ;; + esac ;; +esac + +# Omit the trailing newline, so that m4_esyscmd can use the result directly. +echo "$v" | tr -d '\012' + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..d04cac0 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,3 @@ +noinst_HEADERS = gtp.h libosmocore.h + +nobase_include_HEADERS = osmocom/gtp/gtp.h diff --git a/include/gtp.h b/include/gtp.h new file mode 100644 index 0000000..3a47de6 --- /dev/null +++ b/include/gtp.h @@ -0,0 +1,102 @@ +#ifndef _GTP_PROTOCOL_H_ +#define _GTP_PROTOCOL_H_ + +enum gtp_type { + GTP_UNUSED = 0, /* GSM 09.60 says for future use */ + GTP_ECHO_REQ = 1, /* 7.4.1 GSM 09.60 */ + GTP_ECHO_RESP = 2, /* 7.4.2 GSM 09.60 */ + GTP_VERSION_NOTSUPP = 3, /* 7.4.3 GSM 09.60 */ + GTP_PDP_CREATE_REQ = 16, /* 7.5.1 GSM 09.60 */ + GTP_PDP_CREATE_RESP = 17, /* 7.5.2 GSM 09.60 */ + GTP_PDP_UPDATE_REQ = 18, /* 7.5.3 GSM 09.60 */ + GTP_PDP_UPDATE_RESP = 19, /* 7.5.4 GSM 09.60 */ + GTP_PDP_DELETE_REQ = 20, /* 7.5.5 GSM 09.60 */ + GTP_PDP_DELETE_RESP = 21, /* 7.5.6 GSM 09.60 */ + GTP_TYPE_MAX, +}; + +struct gtp0_header { +#if BYTE_ORDER == BIG_ENDIAN + uint8_t version:3, + pt:1, + spare:3, + snn:1; +#elif BYTE_ORDER == LITTLE_ENDIAN + uint8_t snn:1, + spare:3, + pt:1, + version:3; +#else +#warn "BYTE_ORDER is not defined, please fix your headers" +#endif + uint8_t type; + uint16_t length; + uint16_t seq; + uint16_t flow; + uint8_t number; + uint8_t spare1; + uint8_t spare2; + uint8_t spare3; + uint64_t tid; +} __attribute__((packed)); + +/* + * Information elements + */ +/* TV */ +#define GTPV0_IE_CAUSE 1 /* 8 bits */ +#define GTPV0_IE_QOS_PROFILE 6 /* 24 bits */ +#define GTPV0_IE_REORDERING_REQ 8 /* 1 bit */ +#define GTPV0_IE_RECOVERY 14 /* 8 bit */ +#define GTPV0_IE_SELECT_MODE 15 /* 16 bits */ +#define GTPV0_IE_FLOW_LABEL_DATA 16 /* 16 bits */ +#define GTPV0_IE_FLOW_LABEL_SIGNAL 17 /* 16 bits */ +#define GTPV0_IE_CHARGING_ID 127 /* 32 bits */ +/* TLV >= 128 */ +#define GTPV0_IE_ENDUSER_ADDR 128 +#define GTPV0_IE_AP_NAME 131 +#define GTPV0_IE_PROTO_CONF_OPTS 132 +#define GTPV0_IE_GSN_ADDR 133 +#define GTPV0_IE_MSISDN 134 +#define GTPV0_IE_CHARGING_GW_ADDR 251 + +/* + * Other + */ +#define GTPV0_CAUSE_REQ_ACCEPTED 128 /* GSM 09.60 7.9.1 */ + +#include + +struct enduser_addr_ie_payload_ipv4 { +#if BYTE_ORDER == BIG_ENDIAN + uint8_t spare:4, + pdp_org_type:4; +#elif BYTE_ORDER == LITTLE_ENDIAN + uint8_t pdp_org_type:4, + spare:4; +#else +#warn "BYTE_ORDER is not defined, please fix your headers" +#endif + uint8_t pdp_type_number; + struct in_addr addr; +} __attribute__((packed)); + +struct enduser_addr_ie_payload_ipv6 { +#if BYTE_ORDER == BIG_ENDIAN + uint8_t spare:4, + pdp_org_type:4; +#elif BYTE_ORDER == LITTLE_ENDIAN + uint8_t pdp_org_type:4, + spare:4; +#else +#warn "BYTE_ORDER is not defined, please fix your headers" +#endif + uint8_t pdp_type_number; + struct in6_addr addr; +} __attribute__((packed)); + +#define PDP_ORG_IETF 1 +#define PDP_TYPE_IPV4 0x21 +#define PDP_TYPE_IPV6 0x57 + +#endif diff --git a/include/libosmocore.h b/include/libosmocore.h new file mode 100644 index 0000000..dab9265 --- /dev/null +++ b/include/libosmocore.h @@ -0,0 +1,20 @@ +#ifndef _GTP_LIBOSMOCORE_H_ +#define _GTP_LIBOSMOCORE_H_ + +#include + +void *msgb_tv_put_be8(struct msgb *msg, int type, uint8_t value); +void *msgb_tv_put_be16(struct msgb *msg, int type, uint16_t value); +void *msgb_tv_put_be24(struct msgb *msg, int type, uint32_t value); +void *msgb_tv_put_be32(struct msgb *msg, int type, uint32_t value); +void *msgb_tlv_put_be32(struct msgb *msg, int type, uint32_t data); +void *msgb_tlv_put_data(struct msgb *msg, int type, int len, void *data); + +uint8_t tv_get_be8(struct tlv_parsed *tp, int type); +uint16_t tv_get_be16(struct tlv_parsed *tp, int type); +uint32_t tv_get_be24(struct tlv_parsed *tp, int type); +uint32_t tv_get_be32(struct tlv_parsed *tp, int type); +const char *tv_get_strdup(struct tlv_parsed *tp, int type); +const char *tlv_get_strdup(struct tlv_parsed *tp, int type); + +#endif diff --git a/include/osmocom/gtp/gtp.h b/include/osmocom/gtp/gtp.h new file mode 100644 index 0000000..cb1b362 --- /dev/null +++ b/include/osmocom/gtp/gtp.h @@ -0,0 +1,49 @@ +#ifndef _OSMO_GTP_H_ +#define _OSMO_GTP_H_ + +enum osmo_gtp_event { + OSMO_GTP_PDP_NEW, + OSMO_GTP_PDP_UPD, + OSMO_GTP_PDP_DEL, + /* XXX add more events here */ + OSMO_GTP_EVENT_MAX, +}; + +enum gtp_err_type { + GTP_ENOSUPP = 0, + GTP_ETOOSHORT, + GTP_ETRUNCATED, + GTP_EMALFORMED, + GTP_EMAX +}; + +struct osmo_gtp_err { + const char *file; + int line; + enum gtp_err_type type; +}; + +struct osmo_gsn; + +struct osmo_gsn *osmo_gsn_alloc(void); + +struct msgb *gtp0_recv(struct osmo_gsn *gsn, struct msgb *msg, + struct osmo_gtp_err *err); + +enum { + OSMO_GTP_DEFAULT = 0, + OSMO_GTP_HEX, +}; + +void osmo_gtp0_fprintf(FILE *fd, struct msgb *msg, uint32_t type); + +struct gtp0_header *gtp0_header_put(struct msgb *msg, uint32_t type, + uint16_t seq, uint16_t flow, uint64_t tid); +void gtp0_header_end(struct gtp0_header *gtp0h, struct msgb *msg); + +enum osmo_gsn_proto { + OSMO_GSN_IPV4 = 0, + OSMO_GSN_IPV6, +}; + +#endif diff --git a/libosmogtp.pc.in b/libosmogtp.pc.in new file mode 100644 index 0000000..f8998ea --- /dev/null +++ b/libosmogtp.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: GTP Core Library +Description: C Utility Library +Version: @VERSION@ +Libs: -L${libdir} -losmogtp +Cflags: -I${includedir}/ + diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..cad0c75 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,15 @@ +# This is _NOT_ the library release version, it's an API version. +# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification +LIBVERSION=0:0:0 + +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) +AM_CFLAGS= -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) +COMMONLIBS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) + +lib_LTLIBRARIES = libosmogtp.la + +libosmogtp_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBVERSION) +libosmogtp_la_LIBADD = $(COMMONLIBS) +libosmogtp_la_SOURCES = gtp.c \ + libosmocore.c diff --git a/src/gtp.c b/src/gtp.c new file mode 100644 index 0000000..672af5a --- /dev/null +++ b/src/gtp.c @@ -0,0 +1,669 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "libosmocore.h" + +/* Generic context pointer to data in the event context */ +struct osmo_gtp_ctx { + struct osmo_gtp_pdp *pdp; + /* XXX Add more event context here */ +}; + +/* Events are called from the GTP stack to notify upper layer application */ +struct gtp_event_cb { + int (*cb)(enum osmo_gtp_event event, struct osmo_gtp_ctx *ctx); +}; + +struct osmo_gsn { + struct { + enum osmo_gsn_proto proto; + bool reordering_required; + union { + struct in_addr ip_addr; + struct in6_addr ip6_addr; + } ggsn; + } cfg; + + struct gtp_event_cb event[OSMO_GTP_EVENT_MAX]; + + uint8_t restart_counter; +}; + +struct osmo_gtp_pdp { + uint32_t qos_profile:24; + uint16_t flow_label_data; + uint16_t flow_label_signal; + uint8_t sel_mode; + const char *ap_name; + union { + struct in_addr ip_addr; + struct in6_addr ip6_addr; + } enduser; + union { + struct in_addr ip_addr; + struct in6_addr ip6_addr; + } sgsn; + const char *msisdn; +}; + +#define OSMO_GTP_MTU 1500 + +#define GTPV0 0 /* GSM 09.60 */ +#define GTP_PRIME 0 /* GSM 09.60 */ +#define GTP_NON_PRIME 1 /* GSM 12.15 */ +#define GTP_SNDCP_NPDU_UNSET 0 + +struct gtp0_header *gtp0_header_put(struct msgb *msg, uint32_t type, + uint16_t seq, uint16_t flow, uint64_t tid) +{ + struct gtp0_header *gtp0h = (struct gtp0_header *)msg->data; + + gtp0h->version = GTPV0; + gtp0h->pt = GTP_NON_PRIME; + gtp0h->spare = 0x7; + gtp0h->snn = GTP_SNDCP_NPDU_UNSET; + gtp0h->type = type; + gtp0h->seq = htons(seq); + gtp0h->tid = htobe64(tid); + gtp0h->spare1 = 0xff; + gtp0h->spare2 = 0xff; + gtp0h->spare3 = 0xff; + gtp0h->number = 0xff; + gtp0h->flow = flow; + msgb_put(msg, sizeof(*gtp0h)); + + return gtp0h; +} + +void gtp0_header_end(struct gtp0_header *gtp0h, struct msgb *msg) +{ + gtp0h->length = htons(msg->len - sizeof(*gtp0h)); +} + +uint64_t gtp0h_tid(const struct msgb *msg) +{ + const struct gtp0_header *gtp0h = + (const struct gtp0_header *)msg->data; + + return be64toh(gtp0h->tid); +} + +uint16_t gtp0h_seq(const struct msgb *msg) +{ + const struct gtp0_header *gtp0h = + (const struct gtp0_header *)msg->data; + + return ntohs(gtp0h->seq); +} + +struct osmo_gsn *osmo_gsn_alloc(void) +{ + return calloc(1, sizeof(struct osmo_gsn)); +} + +static struct msgb *gtp_unsupp(struct msgb *msg) +{ + struct msgb *reply; + struct gtp0_header *gtp0h; + + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); + if (reply == NULL) + return NULL; + + gtp0h = gtp0_header_put(reply, GTP_VERSION_NOTSUPP, gtp0h_seq(msg), 0, + gtp0h_tid(msg)); + gtp0_header_end(gtp0h, reply); + + return reply; +} + +struct osmo_gtp_handler { + bool request; + struct msgb *(*handler)(struct osmo_gsn *gsn, struct msgb *msg, + struct osmo_gtp_err *err); +}; + +static struct msgb *gtp_echo_req_handler(struct osmo_gsn *gsn, + struct msgb *msg, + struct osmo_gtp_err *err) +{ + struct msgb *reply; + struct gtp0_header *gtp0h; + + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); + if (reply == NULL) + return NULL; + + gtp0h = gtp0_header_put(reply, GTP_ECHO_RESP, gtp0h_seq(msg), 0, + gtp0h_tid(msg)); + msgb_tv_put(reply, GTPV0_IE_RECOVERY, gsn->restart_counter); + + /* TODO: Private extension. 7.9.26 (Optional) */ + /* TODO: IE T=255 Length ExtensionID=(8 bits) ExtValue=(variable) */ + + gtp0_header_end(gtp0h, reply); + + return reply; +} + +static int ip_alloc(struct osmo_gtp_pdp *pdp) +{ + pdp->enduser.ip_addr.s_addr= 0x01020304; + return 0; +} + +static int ip6_alloc(struct osmo_gtp_pdp *pdp) +{ + return 0; +} + +static void build_enduser_addr(struct msgb *reply, struct osmo_gsn *gsn, + struct osmo_gtp_pdp *pdp) +{ + switch (gsn->cfg.proto) { + case OSMO_GSN_IPV4: { + struct enduser_addr_ie_payload_ipv4 ie_ipv4; + + ip_alloc(pdp); + + ie_ipv4.spare = 0xf; + ie_ipv4.pdp_org_type = PDP_ORG_IETF; + ie_ipv4.pdp_type_number = PDP_TYPE_IPV4; + ie_ipv4.addr = pdp->enduser.ip_addr; + + msgb_tlv_put_data(reply, GTPV0_IE_ENDUSER_ADDR, + sizeof(ie_ipv4), &ie_ipv4); + break; + } + case OSMO_GSN_IPV6: { + struct enduser_addr_ie_payload_ipv6 ie_ipv6; + + ip6_alloc(pdp); + + ie_ipv6.spare = 0xf; + ie_ipv6.pdp_org_type = PDP_ORG_IETF; + ie_ipv6.pdp_type_number = PDP_TYPE_IPV6; + ie_ipv6.addr = pdp->enduser.ip6_addr; + + msgb_tlv_put_data(reply, GTPV0_IE_ENDUSER_ADDR, + sizeof(ie_ipv6), &ie_ipv6); + } + break; + } +} + +static void build_gsn_addr(struct msgb *reply, struct osmo_gsn *gsn, + struct osmo_gtp_pdp *pdp) +{ + switch (gsn->cfg.proto) { + case OSMO_GSN_IPV4: + msgb_tlv_put_data(reply, GTPV0_IE_GSN_ADDR, + sizeof(struct in_addr), + &gsn->cfg.ggsn.ip_addr); + break; + case OSMO_GSN_IPV6: + msgb_tlv_put_data(reply, GTPV0_IE_GSN_ADDR, + sizeof(struct in6_addr), + &gsn->cfg.ggsn.ip6_addr); + break; + } +} + +static struct msgb *gtp_pdp_ctx_create_resp(struct osmo_gsn *gsn, + const struct msgb *msg, + struct osmo_gtp_pdp *pdp) +{ + struct msgb *reply; + struct gtp0_header *gtp0h; + + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); + if (reply == NULL) + return NULL; + + gtp0h = gtp0_header_put(reply, GTP_PDP_CREATE_RESP, gtp0h_seq(msg), 0, + gtp0h_tid(msg)); + + /* TODO: implement reject PDP request + reason */ + msgb_tv_put_be8(reply, GTPV0_IE_CAUSE, GTPV0_CAUSE_REQ_ACCEPTED); + + if (GTPV0_CAUSE_REQ_ACCEPTED == GTPV0_CAUSE_REQ_ACCEPTED) { + /* Quality of service profile. 7.9.6 (Conditional) */ + + /* broken u24 */ + msgb_tv_put_be24(reply, GTPV0_IE_QOS_PROFILE, pdp->qos_profile); + + /* Reordering required. 7.9.7 (Conditional) */ + msgb_tv_put_be8(reply, GTPV0_IE_REORDERING_REQ, + gsn->cfg.reordering_required | 0xfe); + + /* Recovery. 7.9.12 (Optional) */ + msgb_tv_put_be8(reply, GTPV0_IE_RECOVERY, gsn->restart_counter); + + int val = 0xa; + + /* Flow label signalling. 7.9.15 (Conditional) */ + msgb_tv_put_be16(reply, GTPV0_IE_FLOW_LABEL_DATA, val); + /* Flow label data I. 7.9.14 (Conditional) */ + msgb_tv_put_be16(reply, GTPV0_IE_FLOW_LABEL_SIGNAL, val); + + /* Charging ID. 7.9.17 (Conditional) */ + msgb_tv_put_be32(reply, GTPV0_IE_CHARGING_ID, val); + + /* End user address. 7.9.18 (Conditional) */ + build_enduser_addr(reply, gsn, pdp); + + /* TODO: Protocol configuration options. 7.9.22 (Optional) */ + + /* TODO: GGSN Address for signalling. 7.9.23 (Conditional) */ + /* TODO: GGSN Address for user traffic. 7.9.23 (Conditional) */ + build_gsn_addr(reply, gsn, pdp); + + /* TODO: Charging Gateway Address. 7.9.25 (Optional) */ + msgb_tlv_put_data(reply, GTPV0_IE_CHARGING_GW_ADDR, sizeof(val), &val); + + /* TODO: Private extension. 7.9.26 (Optional) */ + } + + gtp0_header_end(gtp0h, reply); + + return reply; +} + +static const struct tlv_definition gtp_pdp_create_req_attr_tlvdef = { + .def = { + [GTPV0_IE_QOS_PROFILE] = { TLV_TYPE_FIXED, 3 }, + [GTPV0_IE_RECOVERY] = { TLV_TYPE_FIXED, 1 }, + [GTPV0_IE_SELECT_MODE] = { TLV_TYPE_FIXED, 1 }, + [GTPV0_IE_FLOW_LABEL_DATA] = { TLV_TYPE_FIXED, 2 }, + [GTPV0_IE_FLOW_LABEL_SIGNAL] = { TLV_TYPE_FIXED, 2 }, + [GTPV0_IE_ENDUSER_ADDR] = { TLV_TYPE_TL16V }, + [GTPV0_IE_AP_NAME] = { TLV_TYPE_TL16V }, + [GTPV0_IE_PROTO_CONF_OPTS] = { TLV_TYPE_TL16V }, + [GTPV0_IE_GSN_ADDR] = { TLV_TYPE_TL16V }, + [GTPV0_IE_MSISDN] = { TLV_TYPE_TL16V }, + }, +}; + +struct enduser_addr_ie_payload { +#if BYTE_ORDER == BIG_ENDIAN + uint8_t spare:4, + pdp_org_type:4; +#elif BYTE_ORDER == LITTLE_ENDIAN + uint8_t pdp_org_type:4, + spare:4; +#else +#warn "BYTE_ORDER is not defined, please fix your headers" +#endif + uint8_t pdp_type_number; + char addr[0]; +} __attribute__((packed)); + +static int gtp0_parse_enduser_addr(struct tlv_parsed *tp, + struct osmo_gtp_pdp *pdp) +{ + struct enduser_addr_ie_payload *ie = + (struct enduser_addr_ie_payload *) + TLVP_VAL(tp, GTPV0_IE_ENDUSER_ADDR); + int attrlen = TLVP_LEN(tp, GTPV0_IE_ENDUSER_ADDR); + int hdrlen = sizeof(struct enduser_addr_ie_payload); + + if (ie->pdp_org_type != PDP_ORG_IETF) { + LOGP(DLINP, LOGL_ERROR, "Unsupported PDP org type %d", + ie->pdp_org_type); + return -1; + } + + switch (ie->pdp_type_number) { + case PDP_TYPE_IPV4: + if (attrlen != hdrlen + sizeof(struct in_addr)) { + LOGP(DLINP, LOGL_ERROR, + "bad enduser address length %d for IPv4", + attrlen); + return -1; + } + memcpy(&pdp->enduser.ip_addr, ie->addr, sizeof(struct in_addr)); + break; + case PDP_TYPE_IPV6: + if (attrlen != hdrlen + sizeof(struct in6_addr)) { + LOGP(DLINP, LOGL_ERROR, + "bad enduser address length %d for IPv6", + attrlen); + return -1; + } + memcpy(&pdp->enduser.ip6_addr, ie->addr, sizeof(struct in6_addr)); + break; + default: + LOGP(DLINP, LOGL_ERROR, "Unsupported PDP type number %d\n", + ie->pdp_type_number); + break; + } + + return 0; +} + +static int gtp0_parse_gsn_addr(struct tlv_parsed *tp, + struct osmo_gtp_pdp *pdp) +{ + switch (TLVP_LEN(tp, GTPV0_IE_GSN_ADDR)) { + case sizeof(struct in_addr): + memcpy(&pdp->sgsn, TLVP_VAL(tp, GTPV0_IE_GSN_ADDR), + sizeof(struct in_addr)); + break; + case sizeof(struct in6_addr): + memcpy(&pdp->sgsn, TLVP_VAL(tp, GTPV0_IE_GSN_ADDR), + sizeof(struct in6_addr)); + break; + default: + return -1; + } + return 0; +} + +static struct msgb *gtp_pdp_create_req_handler(struct osmo_gsn *gsn, + struct msgb *msg, + struct osmo_gtp_err *err) +{ + struct msgb *reply; + struct tlv_parsed tp; + struct osmo_gtp_pdp _pdp, *pdp = &_pdp; + int ret; + + memset(pdp, 0, sizeof(_pdp)); + + ret = tlv_parse(&tp, >p_pdp_create_req_attr_tlvdef, + msg->data + sizeof(struct gtp0_header), + msg->len - sizeof(struct gtp0_header), 0, 0); + if (ret < 0) { + LOGP(DLINP, LOGL_ERROR, "cannot parse TLVs: %u\n", ret); + return NULL; + } + + /* Mandatory attributes: + * + * 1) 7.9.6. QoS profile. 32 bits. GSM 04.08 + * 2) 7.9.13. Selection mode. 8 bits & 0x3. + * 3) 7.9.14. Flow label data. 16 bits + * 4) 7.9.15. Flow label signalling. 16 bits + * 5) 7.9.18. End User Address (see struct enduser_addr_ie_payload). + * 6) 7.9.21. Access Point (AP) Name (variable length) + * 7) 7.9.23. GSN address (variable length) + * 8) 7.9.24. MSISDN (variable length) + */ + if (!TLVP_PRESENT(&tp, GTPV0_IE_QOS_PROFILE) || + !TLVP_PRESENT(&tp, GTPV0_IE_SELECT_MODE) || + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_DATA) || + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL) || + !TLVP_PRESENT(&tp, GTPV0_IE_ENDUSER_ADDR) || + !TLVP_PRESENT(&tp, GTPV0_IE_AP_NAME) || + !TLVP_PRESENT(&tp, GTPV0_IE_GSN_ADDR) || + !TLVP_PRESENT(&tp, GTPV0_IE_MSISDN)) { + LOGP(DLINP, LOGL_ERROR, "missing mandatory TLV\n"); + return NULL; + } + + pdp->qos_profile = tv_get_be24(&tp, GTPV0_IE_QOS_PROFILE); + + /* Validate spare 6 bits to one (7.9.13)? */ + pdp->sel_mode = tv_get_be8(&tp, GTPV0_IE_SELECT_MODE) & 0x03; + pdp->flow_label_data = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_DATA); + pdp->flow_label_signal = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL); + pdp->ap_name = tv_get_strdup(&tp, GTPV0_IE_AP_NAME); + + if (gtp0_parse_enduser_addr(&tp, pdp) < 0 || + gtp0_parse_gsn_addr(&tp, pdp) < 0) + return NULL; + + pdp->msisdn = tlv_get_strdup(&tp, GTPV0_IE_MSISDN); + + /* TODO: Optional attributes: + * 1) 7.9.21. Protocol configuration options. GSM 04.08. + */ + if (TLVP_PRESENT(&tp, GTPV0_IE_PROTO_CONF_OPTS)) { + } + + reply = gtp_pdp_ctx_create_resp(gsn, msg, pdp); + if (reply == NULL) + return NULL; + + return reply; +} + +static const struct tlv_definition gtp_pdp_update_req_attr_tlvdef = { + .def = { + [GTPV0_IE_QOS_PROFILE] = { TLV_TYPE_FIXED, 3 }, + [GTPV0_IE_RECOVERY] = { TLV_TYPE_FIXED, 1 }, + [GTPV0_IE_FLOW_LABEL_DATA] = { TLV_TYPE_FIXED, 2 }, + [GTPV0_IE_FLOW_LABEL_SIGNAL] = { TLV_TYPE_FIXED, 2 }, + [GTPV0_IE_GSN_ADDR] = { TLV_TYPE_TL16V }, + }, +}; + +static struct msgb *gtp_pdp_ctx_update_resp(struct osmo_gsn *gsn, + const struct msgb *msg, + struct osmo_gtp_pdp *pdp) +{ + struct msgb *reply; + struct gtp0_header *gtp0h; + + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); + if (reply == NULL) + return NULL; + + gtp0h = gtp0_header_put(reply, GTP_PDP_UPDATE_RESP, gtp0h_seq(msg), 0, + gtp0h_tid(msg)); + + /* TODO: implement reject PDP request + reason */ + msgb_tv_put_be8(reply, GTPV0_IE_CAUSE, GTPV0_CAUSE_REQ_ACCEPTED); + + if (GTPV0_CAUSE_REQ_ACCEPTED == GTPV0_CAUSE_REQ_ACCEPTED) { + /* Quality of service profile. 7.9.6 (Conditional) */ + + /* broken u24 */ + msgb_tv_put_be24(reply, GTPV0_IE_QOS_PROFILE, pdp->qos_profile); + + /* Recovery. 7.9.12 (Optional) */ + msgb_tv_put_be8(reply, GTPV0_IE_RECOVERY, gsn->restart_counter); + + int val = 0xa; + + /* Flow label signalling. 7.9.15 (Conditional) */ + msgb_tv_put_be16(reply, GTPV0_IE_FLOW_LABEL_DATA, val); + /* Flow label data I. 7.9.14 (Conditional) */ + msgb_tv_put_be16(reply, GTPV0_IE_FLOW_LABEL_SIGNAL, val); + + /* Charging ID. 7.9.17 (Conditional) */ + msgb_tv_put_be32(reply, GTPV0_IE_CHARGING_ID, val); + + /* TODO: Protocol configuration options. 7.9.22 (Optional) */ + /* TODO: GGSN Address for signalling. 7.9.23 (Conditional) */ + /* TODO: GGSN Address for user traffic. 7.9.23 (Conditional) */ + build_gsn_addr(reply, gsn, pdp); + + /* TODO: Charging Gateway Address. 7.9.25 (Optional) */ + msgb_tlv_put_data(reply, GTPV0_IE_CHARGING_GW_ADDR, sizeof(val), &val); + + /* TODO: Private extension. 7.9.26 (Optional) */ + } + + gtp0_header_end(gtp0h, reply); + + return reply; +} + +static struct msgb *gtp_pdp_update_req_handler(struct osmo_gsn *gsn, + struct msgb *msg, + struct osmo_gtp_err *err) +{ + struct msgb *reply; + struct tlv_parsed tp; + struct osmo_gtp_pdp _pdp, *pdp = &_pdp; + int ret; + + memset(pdp, 0, sizeof(_pdp)); + + ret = tlv_parse(&tp, >p_pdp_update_req_attr_tlvdef, + msg->data + sizeof(struct gtp0_header), + msg->len - sizeof(struct gtp0_header), 0, 0); + if (ret < 0) { + LOGP(DLINP, LOGL_ERROR, "cannot parse TLVs: %u\n", ret); + return NULL; + } + + /* Mandatory attributes: + * + * 1) 7.9.6. QoS profile. 32 bits. GSM 04.08 + * 2) 7.9.14. Flow label data. 16 bits + * 3) 7.9.15. Flow label signalling. 16 bits + * 4) 7.9.23. GSN address (variable length) + * 5) 7.9.24. MSISDN (variable length) + */ + if (!TLVP_PRESENT(&tp, GTPV0_IE_QOS_PROFILE) || + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_DATA) || + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL) || + !TLVP_PRESENT(&tp, GTPV0_IE_GSN_ADDR)) { + LOGP(DLINP, LOGL_ERROR, "missing mandatory TLV\n"); + return NULL; + } + + pdp->qos_profile = tv_get_be24(&tp, GTPV0_IE_QOS_PROFILE); + + pdp->flow_label_data = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_DATA); + pdp->flow_label_signal = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL); + if (gtp0_parse_gsn_addr(&tp, pdp) < 0) + return NULL; + + reply = gtp_pdp_ctx_update_resp(gsn, msg, pdp); + if (reply == NULL) + return NULL; + + return reply; +} + +static struct msgb *gtp_pdp_ctx_delete_resp(struct osmo_gsn *gsn, + const struct msgb *msg, + struct osmo_gtp_pdp *pdp) +{ + struct msgb *reply; + struct gtp0_header *gtp0h; + + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); + if (reply == NULL) + return NULL; + + gtp0h = gtp0_header_put(reply, GTP_PDP_DELETE_RESP, gtp0h_seq(msg), 0, + gtp0h_tid(msg)); + + /* TODO: implement reject PDP request + reason */ + msgb_tv_put_be8(reply, GTPV0_IE_CAUSE, GTPV0_CAUSE_REQ_ACCEPTED); + + gtp0_header_end(gtp0h, reply); + + return reply; +} + +static struct msgb *gtp_pdp_delete_req_handler(struct osmo_gsn *gsn, + struct msgb *msg, + struct osmo_gtp_err *err) +{ + struct msgb *reply; + struct osmo_gtp_pdp _pdp, *pdp = &_pdp; + + reply = gtp_pdp_ctx_delete_resp(gsn, msg, pdp); + if (reply == NULL) + return NULL; + + return reply; +} + +static struct osmo_gtp_handler gtp0_handler[GTP_TYPE_MAX] = { + [GTP_ECHO_REQ] = { + .request = true, + .handler = gtp_echo_req_handler, + }, + [GTP_PDP_CREATE_REQ] = { + .request = true, + .handler = gtp_pdp_create_req_handler, + }, + [GTP_PDP_UPDATE_REQ] = { + .request = true, + .handler = gtp_pdp_update_req_handler, + }, + [GTP_PDP_DELETE_REQ] = { + .request = true, + .handler = gtp_pdp_delete_req_handler, + }, +}; + +struct msgb *gtp0_recv(struct osmo_gsn *gsn, struct msgb *msg, + struct osmo_gtp_err *err) +{ + struct gtp0_header *gtp0h = (struct gtp0_header *)msg->data; + struct msgb *reply = NULL; + + if (gtp0h->version != 0) { + LOGP(DLINP, LOGL_ERROR, "wrong GTP packet version %u\n", + gtp0h->version); + return gtp_unsupp(msg); + } + if (msg->len < sizeof(*gtp0h)) { + LOGP(DLINP, LOGL_ERROR, "GTPv0 packet too short msg->len %u\n", + msg->len); + return NULL; + } + if (msg->len != ntohs(gtp0h->length) + sizeof(*gtp0h)) { + LOGP(DLINP, LOGL_ERROR, + "truncated GTPv0 header msg->len %u != %u\n", + msg->len, ntohs(gtp0h->length) + (int)sizeof(*gtp0h)); + return NULL; + } + + if ((gtp0h->type < GTP_TYPE_MAX) && gtp0_handler[gtp0h->type].handler) + reply = gtp0_handler[gtp0h->type].handler(gsn, msg, err); + + return reply; +} + +struct osmo_gtp_pdp *osmo_gtp_get_pdp(struct osmo_gtp_ctx *ctx) +{ + return ctx->pdp; +} + +void osmo_gtp0_fprintf(FILE *fd, struct msgb *msg, uint32_t type) +{ + struct gtp0_header *gtp0h = (struct gtp0_header *)msg->data; + int i; + + if (msg->len < sizeof(*gtp0h)) + return; + + switch (type) { + case OSMO_GTP_DEFAULT: + printf("version pt spare snn\n%x %x %x %x\n", + gtp0h->version, gtp0h->pt, gtp0h->spare, gtp0h->snn); + printf("type seq tid flow\n%u %x %llx %x\n", + gtp0h->type, ntohs(gtp0h->seq), + (unsigned long long)be64toh(gtp0h->tid), gtp0h->flow); + + for (i = sizeof(*gtp0h); i < msg->len; i++) { + printf("(%d) %.2x ", i, msg->data[i] & 0xff); + } + printf("\n"); + break; + case OSMO_GTP_HEX: + for (i = 0; i < msg->len; i++) + printf("\\x%.2x", msg->data[i] & 0xff); + + printf("\n"); + break; + } +} diff --git a/src/libosmocore.c b/src/libosmocore.c new file mode 100644 index 0000000..28b60d0 --- /dev/null +++ b/src/libosmocore.c @@ -0,0 +1,70 @@ +#include +#include "libosmocore.h" +#include + +void *msgb_tv_put_be8(struct msgb *msg, int type, uint8_t value) +{ + return msgb_tv_fixed_put(msg, type, 1, (uint8_t *)&value); +} + +void *msgb_tv_put_be16(struct msgb *msg, int type, uint16_t value) +{ + value = htons(value); + return msgb_tv_fixed_put(msg, type, 2, (uint8_t *)&value); +} + +void *msgb_tv_put_be24(struct msgb *msg, int type, uint32_t value) +{ + value = htonl(value & 0x00ffffff) >> 8; + return msgb_tv_fixed_put(msg, type, 3, (uint8_t *)&value); +} + +void *msgb_tv_put_be32(struct msgb *msg, int type, uint32_t value) +{ + value = htonl(value); + return msgb_tv_fixed_put(msg, type, 4, (uint8_t *)&value); +} + +void *msgb_tlv_put_be32(struct msgb *msg, int type, uint32_t value) +{ + value = htonl(value); + return msgb_tlv_put(msg, type, sizeof(uint32_t), (uint8_t *)&value); +} + +void *msgb_tlv_put_data(struct msgb *msg, int type, int len, void *data) +{ + return msgb_tl16v_put(msg, type, len, data); +} + +uint8_t tv_get_be8(struct tlv_parsed *tp, int type) +{ + return *((uint8_t *)TLVP_VAL(tp, type)); +} + +uint16_t tv_get_be16(struct tlv_parsed *tp, int type) +{ + return ntohs(*((uint16_t *)TLVP_VAL(tp, type))); +} + +uint32_t tv_get_be24(struct tlv_parsed *tp, int type) +{ + uint32_t tmp = *((uint32_t *)TLVP_VAL(tp, type)); + + return ntohl(tmp) >> 8; +} + +uint32_t tv_get_be32(struct tlv_parsed *tp, int type) +{ + return ntohl(*((uint32_t *)TLVP_VAL(tp, type))); +} + +const char *tv_get_strdup(struct tlv_parsed *tp, int type) +{ + return strndup((const char *)TLVP_VAL(tp, type), TLVP_LEN(tp, type)); +} + +const char *tlv_get_strdup(struct tlv_parsed *tp, int type) +{ + /* XXX validate length */ + return strndup((const char *)TLVP_VAL(tp, type), TLVP_LEN(tp, type)); +} diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..9dfe830 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,52 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -g $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(COVERAGE_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) + +check_PROGRAMS = gtp_test + +gtp_test_SOURCES = gtp_test.c +gtp_test_LDADD = $(top_builddir)/src/libosmogtp.la \ + $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) + +# boilerplate for the tests +# The `:;' works around a Bash 3.2 bug when the output is not writeable. +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + :;{ \ + echo '# Signature of the current package.' && \ + echo 'm4_define([AT_PACKAGE_NAME],' && \ + echo ' [$(PACKAGE_NAME)])' && \ + echo 'm4_define([AT_PACKAGE_TARNAME],' && \ + echo ' [$(PACKAGE_TARNAME)])' && \ + echo 'm4_define([AT_PACKAGE_VERSION],' && \ + echo ' [$(PACKAGE_VERSION)])' && \ + echo 'm4_define([AT_PACKAGE_STRING],' && \ + echo ' [$(PACKAGE_STRING)])' && \ + echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \ + echo ' [$(PACKAGE_BUGREPORT)])'; \ + echo 'm4_define([AT_PACKAGE_URL],' && \ + echo ' [$(PACKAGE_URL)])'; \ + } >'$(srcdir)/package.m4' + +EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ + gtp/gtp_test.ok + +TESTSUITE = $(srcdir)/testsuite + +DISTCLEANFILES = atconfig + +check-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) + +installcheck-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ + $(TESTSUITEFLAGS) + +clean-local: + test ! -f '$(TESTSUITE)' || \ + $(SHELL) '$(TESTSUITE)' --clean + +AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te +AUTOTEST = $(AUTOM4TE) --language=autotest +$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 + $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at + mv $@.tmp $@ diff --git a/tests/gtp/gtp_test.ok b/tests/gtp/gtp_test.ok new file mode 100644 index 0000000..e69de29 diff --git a/tests/gtp_test.c b/tests/gtp_test.c new file mode 100644 index 0000000..53be1da --- /dev/null +++ b/tests/gtp_test.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "libosmocore.h" + +int main(void) +{ + struct osmo_gsn *gsn; + struct msgb *msg, *reply; + struct osmo_gtp_err err; + struct gtp0_header *gtp0h; + + gsn = osmo_gsn_alloc(); + + msg = msgb_alloc(1500, "gtp-test"); + + /* + * GTP echo request + */ + gtp0h = gtp0_header_put(msg, GTP_ECHO_REQ, 0x1234, 0, 0); + gtp0_header_end(gtp0h, msg); + + reply = gtp0_recv(gsn, msg, &err); + if (reply) + osmo_gtp0_fprintf(stdout, reply, OSMO_GTP_HEX); + else + printf("failure\n"); + + msgb_free(reply); + msgb_reset(msg); + + /* + * GTP PDP context create request + */ + int val = 0x654321; + + gtp0h = gtp0_header_put(msg, GTP_PDP_CREATE_REQ, 0x1234, 0, 10); + msgb_tv_put_be24(msg, GTPV0_IE_QOS_PROFILE, val); + msgb_tv_put_be8(msg, GTPV0_IE_SELECT_MODE, 0); + msgb_tv_put_be16(msg, GTPV0_IE_FLOW_LABEL_DATA, 1); + msgb_tv_put_be16(msg, GTPV0_IE_FLOW_LABEL_SIGNAL, 2); + + const char *test = "test"; + + struct enduser_addr_ie_payload_ipv4 ie_ipv4 = { + .spare = 0xf, + .pdp_org_type = PDP_ORG_IETF, + .pdp_type_number = PDP_TYPE_IPV4, + .addr = { + .s_addr = 0x04030201, + }, + }; + msgb_tlv_put_data(msg, GTPV0_IE_ENDUSER_ADDR, sizeof(ie_ipv4), + &ie_ipv4); + msgb_tlv_put_data(msg, GTPV0_IE_AP_NAME, strlen(test), (uint8_t *)test); + val = 0x01020304; + msgb_tlv_put_data(msg, GTPV0_IE_GSN_ADDR, sizeof(val), (uint8_t *)&val); + val = 0x0a0b0c0d; + + const char *msisdn = "650102030"; + msgb_tlv_put_data(msg, GTPV0_IE_MSISDN, strlen(msisdn), (uint8_t *)msisdn); + + gtp0_header_end(gtp0h, msg); + + reply = gtp0_recv(gsn, msg, &err); + if (reply) + osmo_gtp0_fprintf(stdout, reply, OSMO_GTP_HEX); + else + printf("failure\n"); + + msgb_free(reply); + msgb_reset(msg); + + /* + * GTP Update PDP context request + */ + val = 0x654321; + + gtp0h = gtp0_header_put(msg, GTP_PDP_UPDATE_REQ, 0x1234, 0, 10); + msgb_tv_put_be24(msg, GTPV0_IE_QOS_PROFILE, val); + /* Recovery 7.9.12 optional */ + msgb_tv_put_be16(msg, GTPV0_IE_FLOW_LABEL_DATA, 1); + msgb_tv_put_be16(msg, GTPV0_IE_FLOW_LABEL_SIGNAL, 2); + val = 0x01020304; + msgb_tlv_put_data(msg, GTPV0_IE_GSN_ADDR, sizeof(val), (uint8_t *)&val); + + gtp0_header_end(gtp0h, msg); + + reply = gtp0_recv(gsn, msg, &err); + if (reply) + osmo_gtp0_fprintf(stdout, reply, OSMO_GTP_HEX); + else + printf("failure\n"); + + msgb_free(reply); + msgb_reset(msg); + + /* + * GTP delete PDP context request + */ + val = 0x654321; + + gtp0h = gtp0_header_put(msg, GTP_PDP_DELETE_REQ, 0x1234, 0, 10); + gtp0_header_end(gtp0h, msg); + + reply = gtp0_recv(gsn, msg, &err); + if (reply) + osmo_gtp0_fprintf(stdout, reply, OSMO_GTP_HEX); + else + printf("failure\n"); + + msgb_free(reply); + msgb_reset(msg); + + return EXIT_SUCCESS; +} diff --git a/tests/gtp_test.ok b/tests/gtp_test.ok new file mode 100644 index 0000000..6860a40 --- /dev/null +++ b/tests/gtp_test.ok @@ -0,0 +1,4 @@ +version pt spare snn +0 1 7 0 +ntype seq tid flow +2 3412 0 0(20) e (21) 0 diff --git a/tests/testsuite.at b/tests/testsuite.at new file mode 100644 index 0000000..fb55669 --- /dev/null +++ b/tests/testsuite.at @@ -0,0 +1,18 @@ +AT_INIT +AT_BANNER([Regression tests.]) + +# Example for tests.. copy and uncomment. This creates a new category +# and test. It will copy the expected output to expout and then run +# the given test. The stdout will be compared with the expout to determine +# if the test was successfull. +# AT_SETUP([NAME]) +# AT_KEYWORDS([NAME]) +# cat $abs_srcdir/NAME/NAME_test.ok > expout +# AT_CHECK([$abs_top_builddir/tests/NAME/NAME_test], [], [expout]) +# AT_CLEANUP + +AT_SETUP([gtp_test]) +AT_KEYWORDS([gtp_test]) +cat $abs_srcdir/gtp_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gtp_test], [], [expout], [ignore]) +AT_CLEANUP -- 2.1.4 From holger at freyther.de Thu Oct 15 07:30:56 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 15 Oct 2015 15:30:56 +0800 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: References: Message-ID: <51E95836-8C1C-4B85-A63B-C85BD6111AEE@freyther.de> > On 13 Oct 2015, at 20:12, Marcin Starzyk wrote: > > Hi All, > > > I?m facing an issue with osmo-nitb (HLR/sqlite part) - segmentation fault. All works ok for the first usage od DB (e.g. Location Updating Request) ? but there is segmentation fault on second Location Updating request or any other attempt to execute any command using VTY for HLR. please use valgrind to build with the address sanitizer. There are known out og bounds reads of libdbd but you don't seem to hit those. holger From holger at freyther.de Thu Oct 15 07:32:06 2015 From: holger at freyther.de (Holger Freyther) Date: Thu, 15 Oct 2015 15:32:06 +0800 Subject: Authorization using IMEI In-Reply-To: References: Message-ID: > On 13 Oct 2015, at 17:54, Ravi Shankar wrote: > > > > I mean, the authorization field is in the Subscriber table of the database so how is it possible to set authorization with IMEI number. it is not possible. A subscriber has the concept of being authorized but he is not tied to an equipment. holger From nhofmeyr at sysmocom.de Thu Oct 15 13:32:02 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Thu, 15 Oct 2015 15:32:02 +0200 Subject: [PATCH] initial commit for libosmo-gtp In-Reply-To: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> References: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> Message-ID: <20151015133202.GA1306@dub5> Hi Pablo, I am currently entering the same trajectory as you have: I'm tweaking and forwarding GTP messages in the openbsc:neels/gtphub branch. The more I try to use the gtp.h API (from openggsn), the more I am forced to re-implement it. In that sense, a new and proper library for GTP messages is highly interesting to me. GTPv0 is in fact less interesting, as seemingly *all* messages I need to deal with are GTPv1. Adding v1 should actually be pretty quick, though. Let me take a look at the patch, comments are inline... I'm not implying that you should work on it more. That would be great, but if not, they are remarks for whomever would like to go on with it. Probably me anyway. Thank you loads for sharing this! ~Neels comments follow: On Thu, Oct 15, 2015 at 08:12:02AM +0200, pablo at gnumonks.org wrote: > From: Pablo Neira Ayuso > > I started this libosmo-gtp library after spending quite some time trying to > clean up libgtp and add IPv6 support to it in some clean way. > > The result was this library that I started from scratch in my spare time. > > The basic idea behind this is to avoid mixing the carrier (socket) code with > the message building and parsing, and avoid overly the complicated callback > scheme of libgtp. +1 !!! > This implements minimal support for GTPv0, it also includes automated tests > by generating GTPv0 messages then hand it over to gtp0_recv() which generates > the reply. > > I remember that I also validated this code by sending GTPv0 messages over UDP > to inspect them through wireshark, and they were OK. gtphub would be interesting testing grounds: it deals entirely with "real" GTP messages coming from elsewhere, but also recodes them. > It's fairly incomplete. The only client I have for this library is an initial > (fairly incomplete) osmo-gtp daemon using this library to replace opengtp. > > BTW, there's a src/libosmocore.c file that contains helper functions to > provide a more consistent way to work with different TLV types. > > Probably it can be uploaded to the osmocom repository even if incomplete? > > Well, just wanted to get this code out there, it got stuck here and I didn't > find so far more time to make more progress on it, but we'll try to update > it when traveling or something. > > .gitignore | 43 +++ > Makefile.am | 13 + > configure.ac | 42 +++ > git-version-gen | 151 +++++++++++ > include/Makefile.am | 3 + > include/gtp.h | 102 +++++++ > include/libosmocore.h | 20 ++ > include/osmocom/gtp/gtp.h | 49 ++++ > libosmogtp.pc.in | 11 + > src/Makefile.am | 15 ++ > src/gtp.c | 669 ++++++++++++++++++++++++++++++++++++++++++++++ > src/libosmocore.c | 70 +++++ > tests/Makefile.am | 52 ++++ > tests/gtp/gtp_test.ok | 0 > tests/gtp_test.c | 121 +++++++++ > tests/gtp_test.ok | 4 + > tests/testsuite.at | 18 ++ > 17 files changed, 1383 insertions(+) > create mode 100644 .gitignore > create mode 100644 Makefile.am > create mode 100644 configure.ac > create mode 100755 git-version-gen > create mode 100644 include/Makefile.am > create mode 100644 include/gtp.h > create mode 100644 include/libosmocore.h > create mode 100644 include/osmocom/gtp/gtp.h > create mode 100644 libosmogtp.pc.in > create mode 100644 src/Makefile.am > create mode 100644 src/gtp.c > create mode 100644 src/libosmocore.c > create mode 100644 tests/Makefile.am > create mode 100644 tests/gtp/gtp_test.ok > create mode 100644 tests/gtp_test.c > create mode 100644 tests/gtp_test.ok > create mode 100644 tests/testsuite.at [...] > diff --git a/include/gtp.h b/include/gtp.h > new file mode 100644 > index 0000000..3a47de6 > --- /dev/null > +++ b/include/gtp.h > @@ -0,0 +1,102 @@ > +#ifndef _GTP_PROTOCOL_H_ > +#define _GTP_PROTOCOL_H_ > + > +enum gtp_type { > + GTP_UNUSED = 0, /* GSM 09.60 says for future use */ > + GTP_ECHO_REQ = 1, /* 7.4.1 GSM 09.60 */ > + GTP_ECHO_RESP = 2, /* 7.4.2 GSM 09.60 */ > + GTP_VERSION_NOTSUPP = 3, /* 7.4.3 GSM 09.60 */ > + GTP_PDP_CREATE_REQ = 16, /* 7.5.1 GSM 09.60 */ > + GTP_PDP_CREATE_RESP = 17, /* 7.5.2 GSM 09.60 */ > + GTP_PDP_UPDATE_REQ = 18, /* 7.5.3 GSM 09.60 */ > + GTP_PDP_UPDATE_RESP = 19, /* 7.5.4 GSM 09.60 */ > + GTP_PDP_DELETE_REQ = 20, /* 7.5.5 GSM 09.60 */ > + GTP_PDP_DELETE_RESP = 21, /* 7.5.6 GSM 09.60 */ > + GTP_TYPE_MAX, > +}; > + > +struct gtp0_header { > +#if BYTE_ORDER == BIG_ENDIAN > + uint8_t version:3, > + pt:1, > + spare:3, > + snn:1; > +#elif BYTE_ORDER == LITTLE_ENDIAN > + uint8_t snn:1, > + spare:3, > + pt:1, > + version:3; Hmm, endianness is about *byte* order, not *bit* order, right? I suggest to use one of the existing decoding functions for endianness instead: - ntohs()/ntohl() - osmo_loadXXbe() - decode_big_endian() (yet static in openbsc/src/gprs/gprs_gsup_messages.c, see also the first commit it openbsc:neels/sgsn-id-3) Anyway, this single octet should not be affected by endianness, but those uint16,32,64_t below are. > +#else > +#warn "BYTE_ORDER is not defined, please fix your headers" > +#endif > + uint8_t type; > + uint16_t length; > + uint16_t seq; > + uint16_t flow; > + uint8_t number; > + uint8_t spare1; > + uint8_t spare2; > + uint8_t spare3; > + uint64_t tid; > +} __attribute__((packed)); > + > +/* > + * Information elements > + */ > +/* TV */ > +#define GTPV0_IE_CAUSE 1 /* 8 bits */ > +#define GTPV0_IE_QOS_PROFILE 6 /* 24 bits */ > +#define GTPV0_IE_REORDERING_REQ 8 /* 1 bit */ > +#define GTPV0_IE_RECOVERY 14 /* 8 bit */ > +#define GTPV0_IE_SELECT_MODE 15 /* 16 bits */ > +#define GTPV0_IE_FLOW_LABEL_DATA 16 /* 16 bits */ > +#define GTPV0_IE_FLOW_LABEL_SIGNAL 17 /* 16 bits */ > +#define GTPV0_IE_CHARGING_ID 127 /* 32 bits */ > +/* TLV >= 128 */ > +#define GTPV0_IE_ENDUSER_ADDR 128 > +#define GTPV0_IE_AP_NAME 131 > +#define GTPV0_IE_PROTO_CONF_OPTS 132 > +#define GTPV0_IE_GSN_ADDR 133 > +#define GTPV0_IE_MSISDN 134 > +#define GTPV0_IE_CHARGING_GW_ADDR 251 > + > +/* > + * Other > + */ > +#define GTPV0_CAUSE_REQ_ACCEPTED 128 /* GSM 09.60 7.9.1 */ > + > +#include > + > +struct enduser_addr_ie_payload_ipv4 { heh, amazing name :) > +#if BYTE_ORDER == BIG_ENDIAN > + uint8_t spare:4, > + pdp_org_type:4; > +#elif BYTE_ORDER == LITTLE_ENDIAN > + uint8_t pdp_org_type:4, > + spare:4; > +#else > +#warn "BYTE_ORDER is not defined, please fix your headers" > +#endif > + uint8_t pdp_type_number; > + struct in_addr addr; > +} __attribute__((packed)); > + > +struct enduser_addr_ie_payload_ipv6 { > +#if BYTE_ORDER == BIG_ENDIAN > + uint8_t spare:4, > + pdp_org_type:4; > +#elif BYTE_ORDER == LITTLE_ENDIAN > + uint8_t pdp_org_type:4, > + spare:4; > +#else > +#warn "BYTE_ORDER is not defined, please fix your headers" > +#endif > + uint8_t pdp_type_number; > + struct in6_addr addr; > +} __attribute__((packed)); > + > +#define PDP_ORG_IETF 1 > +#define PDP_TYPE_IPV4 0x21 > +#define PDP_TYPE_IPV6 0x57 > + > +#endif > diff --git a/include/libosmocore.h b/include/libosmocore.h > new file mode 100644 > index 0000000..dab9265 > --- /dev/null > +++ b/include/libosmocore.h > @@ -0,0 +1,20 @@ > +#ifndef _GTP_LIBOSMOCORE_H_ > +#define _GTP_LIBOSMOCORE_H_ > + > +#include > + > +void *msgb_tv_put_be8(struct msgb *msg, int type, uint8_t value); > +void *msgb_tv_put_be16(struct msgb *msg, int type, uint16_t value); > +void *msgb_tv_put_be24(struct msgb *msg, int type, uint32_t value); > +void *msgb_tv_put_be32(struct msgb *msg, int type, uint32_t value); > +void *msgb_tlv_put_be32(struct msgb *msg, int type, uint32_t data); > +void *msgb_tlv_put_data(struct msgb *msg, int type, int len, void *data); > + > +uint8_t tv_get_be8(struct tlv_parsed *tp, int type); > +uint16_t tv_get_be16(struct tlv_parsed *tp, int type); > +uint32_t tv_get_be24(struct tlv_parsed *tp, int type); > +uint32_t tv_get_be32(struct tlv_parsed *tp, int type); I like how endianness is dealt with at the msgb put/get level. The same should probably happen with the header struct above, with msgb_v_get_beXX(). The old gtp.h also has a "big endian struct"... it's cumbersome as one cannot simply use the struct fields, but one needs to remember to ntohX() first. Might make for more optimized code, though, unless read often. > +const char *tv_get_strdup(struct tlv_parsed *tp, int type); > +const char *tlv_get_strdup(struct tlv_parsed *tp, int type); > + > +#endif > diff --git a/include/osmocom/gtp/gtp.h b/include/osmocom/gtp/gtp.h > new file mode 100644 > index 0000000..cb1b362 > --- /dev/null > +++ b/include/osmocom/gtp/gtp.h > @@ -0,0 +1,49 @@ [...] > +enum osmo_gsn_proto { > + OSMO_GSN_IPV4 = 0, > + OSMO_GSN_IPV6, > +}; It would be great if IPv6 were handled implicitly, by passing the addr size around and let getaddrinfo() et al deal with it. Am I missing something that's standing in the way there? [...] > diff --git a/src/gtp.c b/src/gtp.c > new file mode 100644 > index 0000000..672af5a > --- /dev/null > +++ b/src/gtp.c > @@ -0,0 +1,669 @@ > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "libosmocore.h" > + > +/* Generic context pointer to data in the event context */ > +struct osmo_gtp_ctx { > + struct osmo_gtp_pdp *pdp; > + /* XXX Add more event context here */ > +}; > + > +/* Events are called from the GTP stack to notify upper layer application */ > +struct gtp_event_cb { > + int (*cb)(enum osmo_gtp_event event, struct osmo_gtp_ctx *ctx); > +}; > + > +struct osmo_gsn { > + struct { > + enum osmo_gsn_proto proto; > + bool reordering_required; > + union { > + struct in_addr ip_addr; > + struct in6_addr ip6_addr; > + } ggsn; > + } cfg; > + > + struct gtp_event_cb event[OSMO_GTP_EVENT_MAX]; > + > + uint8_t restart_counter; > +}; > + > +struct osmo_gtp_pdp { > + uint32_t qos_profile:24; > + uint16_t flow_label_data; > + uint16_t flow_label_signal; > + uint8_t sel_mode; > + const char *ap_name; > + union { > + struct in_addr ip_addr; > + struct in6_addr ip6_addr; > + } enduser; > + union { > + struct in_addr ip_addr; > + struct in6_addr ip6_addr; > + } sgsn; > + const char *msisdn; > +}; > + > +#define OSMO_GTP_MTU 1500 > + > +#define GTPV0 0 /* GSM 09.60 */ > +#define GTP_PRIME 0 /* GSM 09.60 */ > +#define GTP_NON_PRIME 1 /* GSM 12.15 */ > +#define GTP_SNDCP_NPDU_UNSET 0 > + > +struct gtp0_header *gtp0_header_put(struct msgb *msg, uint32_t type, > + uint16_t seq, uint16_t flow, uint64_t tid) > +{ > + struct gtp0_header *gtp0h = (struct gtp0_header *)msg->data; > + > + gtp0h->version = GTPV0; > + gtp0h->pt = GTP_NON_PRIME; > + gtp0h->spare = 0x7; > + gtp0h->snn = GTP_SNDCP_NPDU_UNSET; > + gtp0h->type = type; > + gtp0h->seq = htons(seq); > + gtp0h->tid = htobe64(tid); Ah, here it is: htons() stored in the header struct. I'd prefer a host-byte-order struct. > + gtp0h->spare1 = 0xff; > + gtp0h->spare2 = 0xff; > + gtp0h->spare3 = 0xff; > + gtp0h->number = 0xff; > + gtp0h->flow = flow; > + msgb_put(msg, sizeof(*gtp0h)); > + > + return gtp0h; > +} > + > +void gtp0_header_end(struct gtp0_header *gtp0h, struct msgb *msg) > +{ > + gtp0h->length = htons(msg->len - sizeof(*gtp0h)); With msgb_alloc_headroom(), it is possible to first write the IEs to the msgb, and then prepend the header with the correct size later on. See for example in openbsc, gprs_gsup_msgb_alloc() and ipa_msg_push_header(). [...] > +static struct msgb *gtp_unsupp(struct msgb *msg) > +{ > + struct msgb *reply; > + struct gtp0_header *gtp0h; > + > + reply = msgb_alloc(OSMO_GTP_MTU, "gtp"); > + if (reply == NULL) > + return NULL; > + > + gtp0h = gtp0_header_put(reply, GTP_VERSION_NOTSUPP, gtp0h_seq(msg), 0, > + gtp0h_tid(msg)); > + gtp0_header_end(gtp0h, reply); > + > + return reply; > +} [...] > +static int ip_alloc(struct osmo_gtp_pdp *pdp) > +{ > + pdp->enduser.ip_addr.s_addr= 0x01020304; > + return 0; > +} > + > +static int ip6_alloc(struct osmo_gtp_pdp *pdp) > +{ > + return 0; > +} Why are these two called *alloc? > +static const struct tlv_definition gtp_pdp_create_req_attr_tlvdef = { > + .def = { > + [GTPV0_IE_QOS_PROFILE] = { TLV_TYPE_FIXED, 3 }, > + [GTPV0_IE_RECOVERY] = { TLV_TYPE_FIXED, 1 }, > + [GTPV0_IE_SELECT_MODE] = { TLV_TYPE_FIXED, 1 }, > + [GTPV0_IE_FLOW_LABEL_DATA] = { TLV_TYPE_FIXED, 2 }, > + [GTPV0_IE_FLOW_LABEL_SIGNAL] = { TLV_TYPE_FIXED, 2 }, > + [GTPV0_IE_ENDUSER_ADDR] = { TLV_TYPE_TL16V }, > + [GTPV0_IE_AP_NAME] = { TLV_TYPE_TL16V }, > + [GTPV0_IE_PROTO_CONF_OPTS] = { TLV_TYPE_TL16V }, > + [GTPV0_IE_GSN_ADDR] = { TLV_TYPE_TL16V }, > + [GTPV0_IE_MSISDN] = { TLV_TYPE_TL16V }, > + }, > +}; I can't begin to express how much better this looks than the old gtpie.h! > + > +static struct msgb *gtp_pdp_create_req_handler(struct osmo_gsn *gsn, > + struct msgb *msg, > + struct osmo_gtp_err *err) > +{ > + struct msgb *reply; > + struct tlv_parsed tp; > + struct osmo_gtp_pdp _pdp, *pdp = &_pdp; > + int ret; > + > + memset(pdp, 0, sizeof(_pdp)); > + > + ret = tlv_parse(&tp, >p_pdp_create_req_attr_tlvdef, > + msg->data + sizeof(struct gtp0_header), > + msg->len - sizeof(struct gtp0_header), 0, 0); > + if (ret < 0) { > + LOGP(DLINP, LOGL_ERROR, "cannot parse TLVs: %u\n", ret); > + return NULL; > + } > + > + /* Mandatory attributes: > + * > + * 1) 7.9.6. QoS profile. 32 bits. GSM 04.08 > + * 2) 7.9.13. Selection mode. 8 bits & 0x3. > + * 3) 7.9.14. Flow label data. 16 bits > + * 4) 7.9.15. Flow label signalling. 16 bits > + * 5) 7.9.18. End User Address (see struct enduser_addr_ie_payload). > + * 6) 7.9.21. Access Point (AP) Name (variable length) > + * 7) 7.9.23. GSN address (variable length) > + * 8) 7.9.24. MSISDN (variable length) > + */ > + if (!TLVP_PRESENT(&tp, GTPV0_IE_QOS_PROFILE) || > + !TLVP_PRESENT(&tp, GTPV0_IE_SELECT_MODE) || > + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_DATA) || > + !TLVP_PRESENT(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL) || > + !TLVP_PRESENT(&tp, GTPV0_IE_ENDUSER_ADDR) || > + !TLVP_PRESENT(&tp, GTPV0_IE_AP_NAME) || > + !TLVP_PRESENT(&tp, GTPV0_IE_GSN_ADDR) || > + !TLVP_PRESENT(&tp, GTPV0_IE_MSISDN)) { > + LOGP(DLINP, LOGL_ERROR, "missing mandatory TLV\n"); > + return NULL; > + } Oh, how pleasing to the openggsn ridden eye :) > + > + pdp->qos_profile = tv_get_be24(&tp, GTPV0_IE_QOS_PROFILE); > + > + /* Validate spare 6 bits to one (7.9.13)? */ > + pdp->sel_mode = tv_get_be8(&tp, GTPV0_IE_SELECT_MODE) & 0x03; > + pdp->flow_label_data = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_DATA); > + pdp->flow_label_signal = tv_get_be16(&tp, GTPV0_IE_FLOW_LABEL_SIGNAL); > + pdp->ap_name = tv_get_strdup(&tp, GTPV0_IE_AP_NAME); > + > + if (gtp0_parse_enduser_addr(&tp, pdp) < 0 || > + gtp0_parse_gsn_addr(&tp, pdp) < 0) > + return NULL; > + > + pdp->msisdn = tlv_get_strdup(&tp, GTPV0_IE_MSISDN); > + > + /* TODO: Optional attributes: > + * 1) 7.9.21. Protocol configuration options. GSM 04.08. > + */ > + if (TLVP_PRESENT(&tp, GTPV0_IE_PROTO_CONF_OPTS)) { > + } > + > + reply = gtp_pdp_ctx_create_resp(gsn, msg, pdp); For gtphub, I would need to have the response composition separate from parsing. Well, not much left to do, is there, with a nice and clean API like this ;) In fact, I'd like to have message decoding/encoding in an entirely separate header/c file pair from message handling. > + if (reply == NULL) > + return NULL; > + > + return reply; > +} > + [...] > +static struct osmo_gtp_handler gtp0_handler[GTP_TYPE_MAX] = { > + [GTP_ECHO_REQ] = { > + .request = true, > + .handler = gtp_echo_req_handler, > + }, > + [GTP_PDP_CREATE_REQ] = { > + .request = true, > + .handler = gtp_pdp_create_req_handler, > + }, > + [GTP_PDP_UPDATE_REQ] = { > + .request = true, > + .handler = gtp_pdp_update_req_handler, > + }, > + [GTP_PDP_DELETE_REQ] = { > + .request = true, > + .handler = gtp_pdp_delete_req_handler, > + }, > +}; nice. Though it seems to be an implementation detail for the client you were writing (I'm always thinking in terms of gtphub, which doesn't usually take own actions, but just forwards tweaked GTP data). > +struct msgb *gtp0_recv(struct osmo_gsn *gsn, struct msgb *msg, > + struct osmo_gtp_err *err) > +{ > + struct gtp0_header *gtp0h = (struct gtp0_header *)msg->data; > + struct msgb *reply = NULL; > + > + if (gtp0h->version != 0) { > + LOGP(DLINP, LOGL_ERROR, "wrong GTP packet version %u\n", > + gtp0h->version); > + return gtp_unsupp(msg); > + } > + if (msg->len < sizeof(*gtp0h)) { > + LOGP(DLINP, LOGL_ERROR, "GTPv0 packet too short msg->len %u\n", > + msg->len); > + return NULL; > + } > + if (msg->len != ntohs(gtp0h->length) + sizeof(*gtp0h)) { > + LOGP(DLINP, LOGL_ERROR, > + "truncated GTPv0 header msg->len %u != %u\n", > + msg->len, ntohs(gtp0h->length) + (int)sizeof(*gtp0h)); > + return NULL; > + } Heh, this is pretty much 1:1 what I've pasted/written for gtphub :) > + > + if ((gtp0h->type < GTP_TYPE_MAX) && gtp0_handler[gtp0h->type].handler) > + reply = gtp0_handler[gtp0h->type].handler(gsn, msg, err); > + > + return reply; > +} > + [...] > diff --git a/src/libosmocore.c b/src/libosmocore.c > new file mode 100644 > index 0000000..28b60d0 > --- /dev/null > +++ b/src/libosmocore.c > @@ -0,0 +1,70 @@ > +#include [...] > +void *msgb_tv_put_be24(struct msgb *msg, int type, uint32_t value) > +{ > + value = htonl(value & 0x00ffffff) >> 8; heh, interesting :) This won't work on a BE system. You can't portably do a host CPU shift-right on a network byte order value. Imagining a class: Big Endian 101, Professor asks: "Can anyone explain the results of this code on a big endian and a little endian system?" Half an hour of vigorous discussion follows. > + return msgb_tv_fixed_put(msg, type, 3, (uint8_t *)&value); > +} [...] Thanks again! -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Thu Oct 15 22:13:47 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:47 +0200 Subject: [PATCH 03/15] gtphub: add skeletal gtphub.[hc] In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-4-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehf create mode 100644 openbsc/include/openbsc/gtphub.h create mode 100644 openbsc/src/gprs/gtphub.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 254f43d..c5dd6af 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -16,7 +16,8 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ arfcn_range_encode.h nat_rewrite_trie.h bsc_nat_callstats.h \ osmux.h mgcp_transcode.h gprs_utils.h \ gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \ - gprs_gsup_client.h bsc_msg_filter.h + gprs_gsup_client.h bsc_msg_filter.h \ + gtphub.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h new file mode 100644 index 0000000..7c89db1 --- /dev/null +++ b/openbsc/include/openbsc/gtphub.h @@ -0,0 +1,96 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include + +#include + + +/* general */ + +enum gtphub_port_idx { + GTPH_PORT_CONTROL = 0, + GTPH_PORT_USER = 1, + GTPH_PORT_N +}; + +extern const char* const gtphub_port_idx_names[GTPH_PORT_N]; + + +/* config */ + +struct gtphub_cfg_addr { + const char *addr_str; + uint16_t port; +}; + +struct gtphub_cfg_bind { + struct gtphub_cfg_addr bind; +}; + +struct gtphub_cfg { + struct gtphub_cfg_bind to_sgsns[GTPH_PORT_N]; + struct gtphub_cfg_bind to_ggsns[GTPH_PORT_N]; +}; + + +/* state */ + +struct gtphub_addr { + struct sockaddr_storage a; + socklen_t l; +}; + +struct gtphub_peer { + struct llist_head entry; + + struct gtphub_addr addr; +}; + +struct gtphub_bind { + struct osmo_fd ofd; + + /* list of struct gtphub_peer */ + struct llist_head peers; +}; + +struct gtphub { + struct gtphub_bind to_sgsns[GTPH_PORT_N]; + struct gtphub_bind to_ggsns[GTPH_PORT_N]; +}; + + +/* api */ + +void gtphub_zero(struct gtphub *hub); +int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg); + +/* Create a new gtphub_peer instance added to peers_list. + * Initialize to all-zero. Return a pointer to the new instance, or NULL on + * error. */ +struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind); + +/* Remove a gtphub_peer from its list and free it. */ +void gtphub_peer_del(struct gtphub_peer *peer); + diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index 66d0625..f2f914d 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -34,5 +34,5 @@ osmo_sgsn_LDADD = \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \ $(LIBCRYPTO_LIBS) -lrt -osmo_gtphub_SOURCES = gtphub_main.c +osmo_gtphub_SOURCES = gtphub_main.c gtphub.c osmo_gtphub_LDADD = $(LIBOSMOCORE_LIBS) -lrt diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c new file mode 100644 index 0000000..ffe0d4a --- /dev/null +++ b/openbsc/src/gprs/gtphub.c @@ -0,0 +1,45 @@ +/* GTP Hub Implementation */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include + +#include +#include + +void *osmo_gtphub_ctx; + +#define LOGERR(fmt, args...) \ + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) + +void gtphub_zero(struct gtphub *hub) +{ + memset(hub, '\0', sizeof(*hub)); +} + +int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) +{ + LOGERR("%s not implemented\n", __func__); + return -1; +} + -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:49 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:49 +0200 Subject: [PATCH 05/15] gtphub: add a todo comment In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-6-git-send-email-nhofmeyr@sysmocom.de> diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 97e52a6..577a2d0 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -119,6 +119,8 @@ static int gtp_relay(struct osmo_fd *from, errno = 0; ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, (struct sockaddr*)from_addr, from_addr_len); + /* TODO use recvmsg and get a MSG_TRUNC flag to make sure the message + * is not truncated. Then maybe reduce buf's size. */ if (received <= 0) { if (errno != EAGAIN) -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:50 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:50 +0200 Subject: [PATCH 06/15] gtphub: add TEI map API. In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-7-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h index 7c89db1..7354786 100644 --- a/openbsc/include/openbsc/gtphub.h +++ b/openbsc/include/openbsc/gtphub.h @@ -38,6 +38,46 @@ enum gtphub_port_idx { extern const char* const gtphub_port_idx_names[GTPH_PORT_N]; +/* Generator for unused TEI IDs. So far this counts upwards from zero, but the + * implementation may change in the future. Treat this like an opaque struct. */ +struct tei_pool { + uint32_t last_tei; +}; + +void tei_pool_init(struct tei_pool *pool); + +/* Return the next unused TEI from the tei_pool. */ +uint32_t tei_pool_next(struct tei_pool *pool); + + +struct tei_mapping { + struct llist_head entry; + + uint32_t orig; + uint32_t repl; +}; + +struct tei_map { + struct tei_pool *pool; + struct llist_head mappings; +}; + +/* Initialize an (already allocated) tei_map, and set the map's TEI pool. + * Multiple tei_map instances may use the same tei_pool. */ +void tei_map_init(struct tei_map *map, struct tei_pool *pool); + +/* Return a replacement TEI for tei_orig. If tei_orig is unknown, create a new + * mapping using a so far unused TEI to map tei_orig to. Return 0 on error. */ +uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig); + +/* Return the original TEI for a replacement TEI. If no mapping exists to + * tei_repl, return 0. */ +uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl); + +/* Remove the mapping for tei_orig, if it exists. */ +void tei_map_del(struct tei_map *map, uint32_t tei_orig); + + /* config */ struct gtphub_cfg_addr { @@ -66,10 +106,12 @@ struct gtphub_peer { struct llist_head entry; struct gtphub_addr addr; + struct tei_map teim; }; struct gtphub_bind { struct osmo_fd ofd; + struct tei_pool teip; /* list of struct gtphub_peer */ struct llist_head peers; diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 577a2d0..a80243c 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -54,6 +55,82 @@ const char* const gtphub_port_idx_names[GTPH_PORT_N] = { }; +void tei_pool_init(struct tei_pool *pool) +{ + *pool = (struct tei_pool){}; +} + +uint32_t tei_pool_next(struct tei_pool *pool) +{ + pool->last_tei ++; + + OSMO_ASSERT(pool->last_tei > 0); + /* TODO: gracefully handle running out of TEIs. */ + /* TODO: random TEIs. */ + + return pool->last_tei; +} + +void tei_map_init(struct tei_map *map, struct tei_pool *pool) +{ + *map = (struct tei_map){}; + map->pool = pool; + INIT_LLIST_HEAD(&map->mappings); +} + +static uint32_t tei_map_new(struct tei_map *map, uint32_t tei_orig) +{ + struct tei_mapping *mapping; + mapping = talloc_zero(osmo_gtphub_ctx, struct tei_mapping); + OSMO_ASSERT(mapping); + mapping->orig = tei_orig; + mapping->repl = tei_pool_next(map->pool); + llist_add(&mapping->entry, &map->mappings); + return mapping->repl; +} + +uint32_t tei_map_get(struct tei_map *map, uint32_t tei_orig) +{ + OSMO_ASSERT(tei_orig != 0); + + struct tei_mapping *mapping; + llist_for_each_entry(mapping, &map->mappings, entry) { + if (mapping->orig == tei_orig) + return mapping->repl; + } + /* Not found. */ + + return tei_map_new(map, tei_orig); +} + +uint32_t tei_map_get_rev(struct tei_map *map, uint32_t tei_repl) +{ + OSMO_ASSERT(tei_repl != 0); + + struct tei_mapping *pos; + llist_for_each_entry(pos, &map->mappings, entry) { + if (pos->repl == tei_repl) { + OSMO_ASSERT(pos->orig); + return pos->orig; + } + } + return 0; +} + +void tei_map_del(struct tei_map *map, uint32_t tei_orig) +{ + struct tei_mapping *mapping; + llist_for_each_entry(mapping, &map->mappings, entry) { + if (mapping->orig == tei_orig) { + llist_del(&mapping->entry); + talloc_free(mapping); + return; + } + } + LOGERR("No mapping exists for TEI %" PRIu32 ".\n", tei_orig); +} + + /* gtphub */ void gtphub_zero(struct gtphub *hub) @@ -93,6 +170,7 @@ static int gtphub_gtp_bind_init(struct gtphub_bind *b, { memset(b, '\0', sizeof(*b)); + tei_pool_init(&b->teip); INIT_LLIST_HEAD(&b->peers); if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0) @@ -240,6 +318,9 @@ int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind) { struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer); + + tei_map_init(&n->teim, &bind->teip); + llist_add(&n->entry, &bind->peers); return n; } -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:51 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:51 +0200 Subject: [PATCH 07/15] gtphub: add gtphub_test.c (empty) In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-8-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi create mode 100644 openbsc/tests/gtphub/Makefile.am create mode 100644 openbsc/tests/gtphub/gtphub_test.c create mode 100644 openbsc/tests/gtphub/gtphub_test.ok diff --git a/openbsc/.gitignore b/openbsc/.gitignore index f024d76..bf05ac2 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -78,6 +78,7 @@ tests/trau/trau_test tests/mgcp/mgcp_transcoding_test tests/sgsn/sgsn_test tests/subscr/subscr_test +tests/gtphub/gtphub_test tests/atconfig tests/atlocal diff --git a/openbsc/configure.ac b/openbsc/configure.ac index fc30b5e..9393282 100644 --- a/openbsc/configure.ac +++ b/openbsc/configure.ac @@ -209,6 +209,7 @@ AC_OUTPUT( tests/trau/Makefile tests/sgsn/Makefile tests/subscr/Makefile + tests/gtphub/Makefile doc/Makefile doc/examples/Makefile Makefile) diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 773830b..7dda124 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr +SUBDIRS = gsm0408 db channel mgcp gprs abis gbproxy trau subscr gtphub if BUILD_NAT SUBDIRS += bsc-nat bsc-nat-trie diff --git a/openbsc/tests/gtphub/Makefile.am b/openbsc/tests/gtphub/Makefile.am new file mode 100644 index 0000000..7cc3ac9 --- /dev/null +++ b/openbsc/tests/gtphub/Makefile.am @@ -0,0 +1,14 @@ +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 $(LIBOSMOCORE_CFLAGS) + +EXTRA_DIST = \ + gtphub_test.ok + +noinst_PROGRAMS = gtphub_test + +gtphub_test_SOURCES = gtphub_test.c + +gtphub_test_LDADD = \ + $(LIBOSMOCORE_LIBS) \ + -lgtp -lrt + diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c new file mode 100644 index 0000000..95f82c3 --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_test.c @@ -0,0 +1,63 @@ +/* Test the GTP hub */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include +#include + +#include + +void *osmo_gtphub_ctx; + +static void test_gtphub_api(void) +{ + OSMO_ASSERT(1); +} + +static struct log_info_cat gtphub_categories[] = { + [DGTPHUB] = { + .name = "DGTPHUB", + .description = "GTP Hub", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +static struct log_info info = { + .cat = gtphub_categories, + .num_cat = ARRAY_SIZE(gtphub_categories), +}; + +int main(int argc, char **argv) +{ + osmo_init_logging(&info); + osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); + + test_gtphub_api(); + printf("Done\n"); + + talloc_report_full(osmo_gtphub_ctx, stderr); + return 0; +} + diff --git a/openbsc/tests/gtphub/gtphub_test.ok b/openbsc/tests/gtphub/gtphub_test.ok new file mode 100644 index 0000000..a965a70 --- /dev/null +++ b/openbsc/tests/gtphub/gtphub_test.ok @@ -0,0 +1 @@ +Done diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 74aaef0..bfaa76e 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -103,3 +103,10 @@ AT_CHECK([test "$enable_sgsn_test" != no || exit 77]) cat $abs_srcdir/sgsn/sgsn_test.ok > expout AT_CHECK([$abs_top_builddir/tests/sgsn/sgsn_test], [], [expout], [ignore]) AT_CLEANUP + +AT_SETUP([gtphub]) +AT_KEYWORDS([gtphub]) +AT_CHECK([test "$enable_gtphub_test" != no || exit 77]) +cat $abs_srcdir/gtphub/gtphub_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gtphub/gtphub_test], [], [expout], [ignore]) +AT_CLEANUP -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:52 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:52 +0200 Subject: [PATCH 08/15] gtphub: add TEI map test In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-9-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi diff --git a/openbsc/tests/gtphub/Makefile.am b/openbsc/tests/gtphub/Makefile.am index 7cc3ac9..5347811 100644 --- a/openbsc/tests/gtphub/Makefile.am +++ b/openbsc/tests/gtphub/Makefile.am @@ -9,6 +9,7 @@ noinst_PROGRAMS = gtphub_test gtphub_test_SOURCES = gtphub_test.c gtphub_test_LDADD = \ + $(top_builddir)/src/gprs/gtphub.o \ $(LIBOSMOCORE_LIBS) \ -lgtp -lrt diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c index 95f82c3..25e51e7 100644 --- a/openbsc/tests/gtphub/gtphub_test.c +++ b/openbsc/tests/gtphub/gtphub_test.c @@ -28,11 +28,65 @@ #include +#include + void *osmo_gtphub_ctx; -static void test_gtphub_api(void) +/* TODO copied from libosmo-abis/src/subchan_demux.c, remove dup */ +static int llist_len(struct llist_head *head) +{ + struct llist_head *entry; + int i = 0; + + llist_for_each(entry, head) + i++; + + return i; +} + +static void test_tei_map(void) { - OSMO_ASSERT(1); + /* Basic */ + struct tei_pool _pool; + struct tei_pool *pool = &_pool; + struct tei_map _map; + struct tei_map *map = &_map; + + tei_pool_init(pool); + tei_map_init(map, pool); + + OSMO_ASSERT(llist_empty(&map->mappings)); + +#define TEST_N 100 +#define TEST_I 123 + uint32_t i, check_i; + uint32_t m[TEST_N]; + + /* create TEST_N mappings */ + for (i = 0; i < TEST_N; i++) { + m[i] = tei_map_get(map, TEST_I + i); + OSMO_ASSERT(m[i] != 0); + OSMO_ASSERT(llist_len(&map->mappings) == (i+1)); + for (check_i = 0; check_i < i; check_i++) + OSMO_ASSERT(m[check_i] != m[i]); + } + OSMO_ASSERT(llist_len(&map->mappings) == TEST_N); + + /* verify mappings */ + for (i = 0; i < TEST_N; i++) { + OSMO_ASSERT(tei_map_get(map, TEST_I + i) == m[i]); + OSMO_ASSERT(tei_map_get_rev(map, m[i]) == (TEST_I + i)); + } + OSMO_ASSERT(llist_len(&map->mappings) == TEST_N); + + /* remove all mappings */ + for (i = 0; i < TEST_N; i++) { + tei_map_del(map, TEST_I + i); + OSMO_ASSERT(llist_len(&map->mappings) == (TEST_N - (i+1))); + } + OSMO_ASSERT(llist_empty(&map->mappings)); +#undef TEST_N +#undef TEST_I } static struct log_info_cat gtphub_categories[] = { @@ -54,7 +108,7 @@ int main(int argc, char **argv) osmo_init_logging(&info); osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); - test_gtphub_api(); + test_tei_map(); printf("Done\n"); talloc_report_full(osmo_gtphub_ctx, stderr); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:53 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:53 +0200 Subject: [PATCH 09/15] gtphub: add GTP header validation In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-10-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f2f914d..d571d8d 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -35,4 +35,4 @@ osmo_sgsn_LDADD = \ $(LIBCRYPTO_LIBS) -lrt osmo_gtphub_SOURCES = gtphub_main.c gtphub.c -osmo_gtphub_LDADD = $(LIBOSMOCORE_LIBS) -lrt +osmo_gtphub_LDADD = -lgtp $(LIBOSMOCORE_LIBS) -lrt diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index a80243c..208b623 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -46,6 +48,150 @@ typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); #define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) #define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) +/* TODO duplicated from openggsn/gtp/gtpie.h */ +#define ntoh16(x) ntohs(x) +#define ntoh32(x) ntohl(x) + +/* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */ + +enum gtp_rc { + GTP_RC_UNKNOWN = 0, + GTP_RC_TINY = 1, /* no IEs (like ping/pong) */ + GTP_RC_PDU = 2, /* a real packet with IEs */ + + GTP_RC_TOOSHORT = -1, + GTP_RC_UNSUPPORTED_VERSION = -2, + GTP_RC_INVALID_IE = -3, +}; + +struct gtp_packet_desc { + const union gtp_packet *data; + int data_len; + int header_len; + int version; + int rc; +}; + +/* Validate GTP version 0 data; analogous to validate_gtp1_header(), see there. + */ +void validate_gtp0_header(struct gtp_packet_desc *p) +{ + const struct gtp0_header *pheader = &(p->data->gtp0.h); + p->rc = GTP_RC_UNKNOWN; + p->header_len = 0; + + OSMO_ASSERT(p->data_len >= 1); + OSMO_ASSERT(p->version == 0); + + if (p->data_len < GTP0_HEADER_SIZE) { + LOGERR("GTP0 packet too short: %d\n", p->data_len); + p->rc = GTP_RC_TOOSHORT; + return; + } + + if (p->data_len == GTP0_HEADER_SIZE) { + p->rc = GTP_RC_TINY; + p->header_len = GTP0_HEADER_SIZE; + return; + } + + /* Check packet length field versus length of packet */ + if (p->data_len != (ntoh16(pheader->length) + GTP0_HEADER_SIZE)) { + LOGERR("GTP packet length field (%d + %d) does not match" + " actual length (%d)\n", + GTP0_HEADER_SIZE, (int)ntoh16(pheader->length), + p->data_len); + p->rc = GTP_RC_TOOSHORT; + return; + } + + p->header_len = GTP0_HEADER_SIZE; + p->rc = GTP_RC_PDU; +} + +/* Validate GTP version 1 data, and update p->rc with the result, as well as + * p->header_len in case of a valid header. */ +void validate_gtp1_header(struct gtp_packet_desc *p) +{ + const struct gtp1_header_long *pheader = &(p->data->gtp1l.h); + p->rc = GTP_RC_UNKNOWN; + p->header_len = 0; + + OSMO_ASSERT(p->data_len >= 1); + OSMO_ASSERT(p->version == 1); + + if ((p->data_len < GTP1_HEADER_SIZE_LONG) + && (p->data_len != GTP1_HEADER_SIZE_SHORT)){ + LOGERR("GTP packet too short: %d\n", p->data_len); + p->rc = GTP_RC_TOOSHORT; + return; + } + + if (p->data_len <= GTP1_HEADER_SIZE_LONG) { + p->rc = GTP_RC_TINY; + p->header_len = GTP1_HEADER_SIZE_SHORT; + return; + } + + /* Check packet length field versus length of packet */ + if (p->data_len != (ntoh16(pheader->length) + GTP1_HEADER_SIZE_SHORT)) { + LOGERR("GTP packet length field (%d + %d) does not match" + " actual length (%d)\n", + GTP1_HEADER_SIZE_SHORT, (int)ntoh16(pheader->length), + p->data_len); + p->rc = GTP_RC_TOOSHORT; + return; + } + + p->rc = GTP_RC_PDU; + p->header_len = GTP1_HEADER_SIZE_LONG; +} + +/* Examine whether p->data of size p->data_len has a valid GTP header. Set + * p->version, p->rc and p->header_len. On error, p->rc <= 0 (see enum + * gtp_rc). p->data must point at a buffer with p->data_len set. */ +void validate_gtp_header(struct gtp_packet_desc *p) +{ + p->rc = GTP_RC_UNKNOWN; + + /* Need at least 1 byte in order to check version */ + if (p->data_len < (1)) { + LOGERR("Discarding packet - too small\n"); + p->rc = GTP_RC_TOOSHORT; + return; + } + + p->version = p->data->flags >> 5; + + switch (p->version) { + case 0: + validate_gtp0_header(p); + break; + case 1: + validate_gtp1_header(p); + break; + default: + LOGERR("Unsupported GTP version: %d\n", p->version); + p->rc = GTP_RC_UNSUPPORTED_VERSION; + break; + } +} + +/* Validate header, and index information elements. Write decoded packet + * information to *res. res->data will point at the given data buffer. On + * error, p->rc is set <= 0 (see enum gtp_rc). */ +static void gtp_decode(const uint8_t *data, int data_len, struct gtp_packet_desc *res) +{ + memset(res, '\0', sizeof(*res)); + res->data = (union gtp_packet*)data; + res->data_len = data_len; + + validate_gtp_header(res); + + if (res->rc == GTP_RC_TINY) + LOG("tiny: no IEs in this GTP packet\n"); +} + /* general */ @@ -55,6 +201,8 @@ const char* const gtphub_port_idx_names[GTPH_PORT_N] = { }; +/* tei_map, tei_pool */ + void tei_pool_init(struct tei_pool *pool) { *pool = (struct tei_pool){}; @@ -217,6 +365,17 @@ static int gtp_relay(struct osmo_fd *from, /* insert magic here */ + struct gtp_packet_desc p; + gtp_decode(buf, received, &p); + + if (p.rc > 0) + LOG("Valid GTP header (v%d)\n", p.version); +#if 0 + else + // error has been logged + return 0; +#endif + errno = 0; ssize_t sent = sendto(to->fd, buf, received, 0, (struct sockaddr*)to_addr, to_addr_len); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:54 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:54 +0200 Subject: [PATCH 10/15] gtphub: undup code: memset on a struct. In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-11-git-send-email-nhofmeyr@sysmocom.de> diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 208b623..1d9c6d5 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -41,6 +41,8 @@ void *osmo_gtphub_ctx; #define LOG(fmt, args...) \ LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) +#define ZERO_STRUCT(struct_pointer) memset(struct_pointer, '\0', sizeof(*(struct_pointer))) + /* TODO move this to osmocom/core/select.h ? */ typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); @@ -182,7 +184,7 @@ void validate_gtp_header(struct gtp_packet_desc *p) * error, p->rc is set <= 0 (see enum gtp_rc). */ static void gtp_decode(const uint8_t *data, int data_len, struct gtp_packet_desc *res) { - memset(res, '\0', sizeof(*res)); + ZERO_STRUCT(res); res->data = (union gtp_packet*)data; res->data_len = data_len; @@ -221,7 +223,7 @@ uint32_t tei_pool_next(struct tei_pool *pool) void tei_map_init(struct tei_map *map, struct tei_pool *pool) { - *map = (struct tei_map){}; + ZERO_STRUCT(map); map->pool = pool; INIT_LLIST_HEAD(&map->mappings); } @@ -283,7 +285,7 @@ void tei_map_del(struct tei_map *map, uint32_t tei_orig) void gtphub_zero(struct gtphub *hub) { - memset(hub, '\0', sizeof(*hub)); + ZERO_STRUCT(hub); } static int gtphub_sock_init(struct osmo_fd *ofd, @@ -316,7 +318,7 @@ static int gtphub_gtp_bind_init(struct gtphub_bind *b, osmo_fd_cb_t cb, void *cb_data, unsigned int ofd_id) { - memset(b, '\0', sizeof(*b)); + ZERO_STRUCT(b); tei_pool_init(&b->teip); INIT_LLIST_HEAD(&b->peers); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:55 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:55 +0200 Subject: [PATCH 11/15] gtphub: tweak logging In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-12-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 1d9c6d5..e849a8f 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -107,6 +107,7 @@ void validate_gtp0_header(struct gtp_packet_desc *p) return; } + LOG("GTP v0 TID = %" PRIu64 "\n", pheader->tid); p->header_len = GTP0_HEADER_SIZE; p->rc = GTP_RC_PDU; } @@ -129,6 +130,20 @@ void validate_gtp1_header(struct gtp_packet_desc *p) return; } + LOG("|GTPv1\n"); + LOG("| type = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->type, pheader->type); + LOG("| length = %" PRIu16 " 0x%04" PRIx16 "\n", + ntoh16(pheader->length), ntoh16(pheader->length)); + LOG("| TEI = %" PRIu32 " 0x%08" PRIx32 "\n", + ntoh32(pheader->tei), ntoh32(pheader->tei)); + LOG("| seq = %" PRIu16 " 0x%04" PRIx16 "\n", + ntoh16(pheader->seq), ntoh16(pheader->seq)); + LOG("| npdu = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->npdu, pheader->npdu); + LOG("| next = %" PRIu8 " 0x%02" PRIx8 "\n", + pheader->next, pheader->next); + if (p->data_len <= GTP1_HEADER_SIZE_LONG) { p->rc = GTP_RC_TINY; p->header_len = GTP1_HEADER_SIZE_SHORT; @@ -366,6 +381,7 @@ static int gtp_relay(struct osmo_fd *from, } /* insert magic here */ + LOG("Received %d\n%s\n", (int)received, osmo_hexdump(buf, received)); struct gtp_packet_desc p; gtp_decode(buf, received, &p); @@ -403,7 +419,7 @@ int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what) { unsigned int port_idx = from_ggsns_ofd->priv_nr; OSMO_ASSERT(port_idx < GTPH_PORT_N); - LOG("reading from GGSN (%s)\n", gtphub_port_idx_names[port_idx]); + LOG("\n\n=== reading from GGSN (%s)\n", gtphub_port_idx_names[port_idx]); if (!(what & BSC_FD_READ)) return 0; @@ -426,7 +442,7 @@ int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what) { unsigned int port_idx = from_sgsns_ofd->priv_nr; OSMO_ASSERT(port_idx < GTPH_PORT_N); - LOG("reading from SGSN (%s)\n", gtphub_port_idx_names[port_idx]); + LOG("\n\n=== reading from SGSN (%s)\n", gtphub_port_idx_names[port_idx]); if (!(what & BSC_FD_READ)) return 0; diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index b43e28d..f3237fe 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -200,6 +200,7 @@ int main(int argc, char **argv) LOGERR("Cannot resolve '%s port %d'\n", ggsn_addr_str, ggsn_port); exit(-1); } + LOG("DEBUG: using GGSN %s port %d\n", ggsn_addr_str, ggsn_port); log_cfg(cfg); -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:56 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:56 +0200 Subject: [PATCH 12/15] gtphub: index IEs, decode and log a few. In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-13-git-send-email-nhofmeyr@sysmocom.de> diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index e849a8f..73e7c02 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -33,6 +34,8 @@ #include #include +#define GTPHUB_DEBUG 1 + void *osmo_gtphub_ctx; #define LOGERR(fmt, args...) \ @@ -54,6 +57,23 @@ typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); #define ntoh16(x) ntohs(x) #define ntoh32(x) ntohl(x) +/* cheat to use gtpie.h API. + * TODO publish gtpie.h upon openggsn installation */ +union gtpie_member; +extern int gtpie_decaps(union gtpie_member *ie[], int version, + void *pack, unsigned len); +extern int gtpie_gettv0(union gtpie_member *ie[], int type, int instance, + void *dst, unsigned int size); +extern int gtpie_gettv1(union gtpie_member *ie[], int type, int instance, + uint8_t *dst); +extern int gtpie_gettlv(union gtpie_member *ie[], int type, int instance, + unsigned int *length, void *dst, unsigned int size); +#define GTPIE_IMSI 2 /* International Mobile Subscriber Identity 8 */ +#define GTPIE_NSAPI 20 /* NSAPI 1 */ +#define GTPIE_GSN_ADDR 133 /* GSN Address */ +#define GTPIE_SIZE 256 +/* end of things needed from gtpie.h */ + /* TODO move GTP header stuff to openggsn/gtp/ ? See gtp_decaps*() */ enum gtp_rc { @@ -72,6 +92,7 @@ struct gtp_packet_desc { int header_len; int version; int rc; + union gtpie_member *ie[GTPIE_SIZE]; }; /* Validate GTP version 0 data; analogous to validate_gtp1_header(), see there. @@ -194,6 +215,45 @@ void validate_gtp_header(struct gtp_packet_desc *p) } } + +/* Return the value of the i'th IMSI IEI by copying to *imsi. + * The first IEI is reached by passing i = 0. + * imsi must point at allocated space of (at least) 8 bytes. + * Return 1 on success, or 0 if not found. */ +static int get_ie_imsi(union gtpie_member *ie[], uint8_t *imsi, int i) +{ + return gtpie_gettv0(ie, GTPIE_IMSI, i, imsi, 8) == 0; +} + +/* Analogous to get_ie_imsi(). nsapi must point at a single uint8_t. */ +static int get_ie_nsapi(union gtpie_member *ie[], uint8_t *nsapi, int i) +{ + return gtpie_gettv1(ie, GTPIE_NSAPI, i, nsapi) == 0; +} + +static char imsi_digit_to_char(uint8_t nibble) +{ + nibble &= 0x0f; + if (nibble > 9) + return (nibble == 0x0f) ? '\0' : '?'; + return '0' + nibble; +} + +/* Return a human readable IMSI string, in a static buffer. + * imsi must point at 8 octets of IMSI IE encoded IMSI data. */ +static const char *imsi_to_str(uint8_t *imsi) +{ + static char str[17]; + int i; + + for (i = 0; i < 8; i++) { + str[2*i] = imsi_digit_to_char(imsi[i]); + str[2*i + 1] = imsi_digit_to_char(imsi[i] >> 4); + } + str[16] = '\0'; + return str; +} + /* Validate header, and index information elements. Write decoded packet * information to *res. res->data will point at the given data buffer. On * error, p->rc is set <= 0 (see enum gtp_rc). */ @@ -207,6 +267,43 @@ static void gtp_decode(const uint8_t *data, int data_len, struct gtp_packet_desc if (res->rc == GTP_RC_TINY) LOG("tiny: no IEs in this GTP packet\n"); + + if (res->rc != GTP_RC_PDU) + return; + + if (gtpie_decaps(res->ie, res->version, + (void*)(data + res->header_len), + res->data_len - res->header_len) != 0) { + res->rc = GTP_RC_INVALID_IE; + return; + } + +#if GTPHUB_DEBUG + int i; + + for (i = 0; i < 10; i++) { + uint8_t imsi[8]; + if (!get_ie_imsi(res->ie, imsi, i)) + break; + LOG("- IMSI %s\n", imsi_to_str(imsi)); + } + + for (i = 0; i < 10; i++) { + uint8_t nsapi; + if (!get_ie_nsapi(res->ie, &nsapi, i)) + break; + LOG("- NSAPI %d\n", (int)nsapi); + } + + for (i = 0; i < 10; i++) { + unsigned int addr_len; + struct in_addr addr; + if (gtpie_gettlv(res->ie, GTPIE_GSN_ADDR, i, &addr_len, &addr, + sizeof(addr)) != 0) + break; + LOG("- addr %s\n", inet_ntoa(addr)); + } +#endif } -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:57 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:57 +0200 Subject: [PATCH 13/15] gtphub: split gtp_relay() in r/w funcs In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-14-git-send-email-nhofmeyr@sysmocom.de> diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 73e7c02..9f3e021 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -265,6 +265,9 @@ static void gtp_decode(const uint8_t *data, int data_len, struct gtp_packet_desc validate_gtp_header(res); + if (res->rc > 0) + LOG("Valid GTP header (v%d)\n", res->version); + if (res->rc == GTP_RC_TINY) LOG("tiny: no IEs in this GTP packet\n"); @@ -441,23 +444,20 @@ static int gtphub_gtp_bind_init(struct gtphub_bind *b, } /* Recv datagram from from->fd, optionally write sender's address to *from_addr - * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using - * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ -static int gtp_relay(struct osmo_fd *from, - struct sockaddr_storage *from_addr, - socklen_t *from_addr_len, - struct osmo_fd *to, - struct sockaddr_storage *to_addr, - socklen_t to_addr_len) + * and *from_addr_len. Return the number of bytes read. */ +/* Send datagram to to->fd using *to_addr. to_addr may be NULL, if an address + * is set on to->fd. */ +static int gtphub_read(struct osmo_fd *from, + struct sockaddr_storage *from_addr, + socklen_t *from_addr_len, + uint8_t *buf, size_t buf_len) { - static uint8_t buf[4096]; - /* recvfrom requires the available length to be set in *from_addr_len. */ if (from_addr_len && from_addr) *from_addr_len = sizeof(*from_addr); errno = 0; - ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, + ssize_t received = recvfrom(from->fd, buf, buf_len, 0, (struct sockaddr*)from_addr, from_addr_len); /* TODO use recvmsg and get a MSG_TRUNC flag to make sure the message * is not truncated. Then maybe reduce buf's size. */ @@ -465,7 +465,7 @@ static int gtp_relay(struct osmo_fd *from, if (received <= 0) { if (errno != EAGAIN) LOGERR("error: %s\n", strerror(errno)); - return -errno; + return 0; } if (from_addr) { @@ -474,25 +474,20 @@ static int gtp_relay(struct osmo_fd *from, if (received <= 0) { LOGERR("error: %s\n", strerror(errno)); - return -EINVAL; + return 0; } - /* insert magic here */ LOG("Received %d\n%s\n", (int)received, osmo_hexdump(buf, received)); + return received; +} - struct gtp_packet_desc p; - gtp_decode(buf, received, &p); - - if (p.rc > 0) - LOG("Valid GTP header (v%d)\n", p.version); -#if 0 - else - // error has been logged - return 0; -#endif - +static int gtphub_write(struct osmo_fd *to, + struct sockaddr_storage *to_addr, + socklen_t to_addr_len, + uint8_t *buf, size_t buf_len) +{ errno = 0; - ssize_t sent = sendto(to->fd, buf, received, 0, + ssize_t sent = sendto(to->fd, buf, buf_len, 0, (struct sockaddr*)to_addr, to_addr_len); if (to_addr) { @@ -504,8 +499,8 @@ static int gtp_relay(struct osmo_fd *from, return -EINVAL; } - if (sent != received) - LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); + if (sent != buf_len) + LOGERR("sent(%d) != data_len(%d)\n", (int)sent, (int)buf_len); else LOG("%d b ok\n", (int)sent); @@ -530,9 +525,23 @@ int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what) return 0; } - return gtp_relay(from_ggsns_ofd, NULL, NULL, - &hub->to_sgsns[port_idx].ofd, - &sgsn->addr.a, sgsn->addr.l); + static uint8_t buf[4096]; + size_t received = gtphub_read(from_ggsns_ofd, NULL, NULL, + buf, sizeof(buf)); + if (received < 1) + return 0; + + static struct gtp_packet_desc p; + gtp_decode(buf, received, &p); + +#if 0 + if (p.rc <= 0) + return 0; +#endif + + return gtphub_write(&hub->to_sgsns[port_idx].ofd, + &sgsn->addr.a, sgsn->addr.l, + (uint8_t*)p.data, p.data_len); } int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what) @@ -560,9 +569,23 @@ int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what) if (!sgsn) sgsn = gtphub_peer_new(&hub->to_sgsns[port_idx]); - return gtp_relay(from_sgsns_ofd, &sgsn->addr.a, &sgsn->addr.l, - &hub->to_ggsns[port_idx].ofd, - &ggsn->addr.a, ggsn->addr.l); + static uint8_t buf[4096]; + size_t received = gtphub_read(from_sgsns_ofd, &sgsn->addr.a, &sgsn->addr.l, + buf, sizeof(buf)); + if (received < 1) + return 0; + + static struct gtp_packet_desc p; + gtp_decode(buf, received, &p); + +#if 0 + if (p.rc <= 0) + return 0; +#endif + + return gtphub_write(&hub->to_ggsns[port_idx].ofd, + &ggsn->addr.a, ggsn->addr.l, + (uint8_t*)p.data, p.data_len); } int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:58 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:58 +0200 Subject: [PATCH 14/15] gtphub: map sequence numbers SGSNs<->GGSNs In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-15-git-send-email-nhofmeyr@sysmocom.de> Avoid sequence number collisions and allow routing a GGSN's response back to the SGSN that sent a request: - Towards each GGSN, send other sequence numbers than received from an SGSN, - and remember the mapping (with timeouts). - When receiving from a GGSN, find the SGSN from the sequence number returned. This covers only requests by the SGSN followed by GGSN responses, it does not cover requests initiated by a GGSN. Sponsored-by: On-Waves ehi diff --git a/openbsc/include/openbsc/gtphub.h b/openbsc/include/openbsc/gtphub.h index 7354786..ccea5aa 100644 --- a/openbsc/include/openbsc/gtphub.h +++ b/openbsc/include/openbsc/gtphub.h @@ -23,6 +23,7 @@ #include #include +#include #include @@ -107,6 +108,18 @@ struct gtphub_peer { struct gtphub_addr addr; struct tei_map teim; + uint16_t next_peer_seq; /* the latest used sequence nr + 1 */ + struct llist_head seq_map; /* of struct gtphub_seq_mapping */ + int ref_count; /* references from other peers' seq_maps */ +}; + +struct gtphub_seq_mapping { + struct llist_head entry; + + uint16_t peer_seq; + struct gtphub_peer *from; + uint16_t from_seq; + struct timeval timeout; }; struct gtphub_bind { diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index 9f3e021..f6733e3 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ #include #define GTPHUB_DEBUG 1 +#define MAP_SEQ 1 void *osmo_gtphub_ctx; @@ -57,6 +59,8 @@ typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); #define ntoh16(x) ntohs(x) #define ntoh32(x) ntohl(x) +#define hton16(x) htons(x) + /* cheat to use gtpie.h API. * TODO publish gtpie.h upon openggsn installation */ union gtpie_member; @@ -87,7 +91,7 @@ enum gtp_rc { }; struct gtp_packet_desc { - const union gtp_packet *data; + union gtp_packet *data; int data_len; int header_len; int version; @@ -481,6 +485,63 @@ static int gtphub_read(struct osmo_fd *from, return received; } +#if MAP_SEQ + +inline uint16_t get_seq(struct gtp_packet_desc *p) +{ + OSMO_ASSERT(p->version == 1); + return ntoh16(p->data->gtp1l.h.seq); +} + +inline void set_seq(struct gtp_packet_desc *p, uint16_t seq) +{ + OSMO_ASSERT(p->version == 1); + p->data->gtp1l.h.seq = hton16(seq); +} + +static int gtphub_map_seq(struct gtp_packet_desc *p, + struct gtphub_peer *from_peer, struct gtphub_peer *to_peer) +{ + + struct gtphub_seq_mapping *m = talloc_zero(osmo_gtphub_ctx, struct gtphub_seq_mapping); + OSMO_ASSERT(m); + + m->peer_seq = to_peer->next_peer_seq++; + m->from = from_peer; + m->from_seq = get_seq(p); + LOG(" MAP %d --> %d\n", (int)m->from_seq, (int)m->peer_seq); + + llist_add(&m->entry, &to_peer->seq_map); + set_seq(p, m->peer_seq); + + return 0; +} + +static struct gtphub_peer *gtphub_unmap_seq(struct gtp_packet_desc *p, + struct gtphub_peer *from_peer) +{ + OSMO_ASSERT(p->version == 1); + + uint16_t from_seq = get_seq(p); + + struct gtphub_seq_mapping *mapping; + llist_for_each_entry(mapping, &from_peer->seq_map, entry) { + if (mapping->peer_seq == from_seq) + break; + } + + if (&mapping->entry == &from_peer->seq_map) { + /* not found. */ + return NULL; + } + + LOG("UNMAP %d <-- %d\n", (int)(mapping->from_seq), (int)from_seq); + set_seq(p, mapping->from_seq); + return mapping->from; +} + +#endif + static int gtphub_write(struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len, @@ -517,11 +578,14 @@ int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what) struct gtphub *hub = from_ggsns_ofd->data; + struct gtphub_peer *ggsn = NULL; + struct gtphub_peer *sgsn = NULL; + /* TODO this will not be hardcoded. */ - struct gtphub_peer *sgsn = llist_first(&hub->to_sgsns[port_idx].peers, - struct gtphub_peer, entry); - if (!sgsn) { - LOGERR("no sgsn"); + ggsn = llist_first(&hub->to_ggsns[port_idx].peers, + struct gtphub_peer, entry); + if (!ggsn) { + LOGERR("no ggsn\n"); return 0; } @@ -539,6 +603,20 @@ int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what) return 0; #endif +#if MAP_SEQ + sgsn = gtphub_unmap_seq(&p, ggsn); +#else + /* TODO this will not be hardcoded. */ + sgsn = llist_first(&hub->to_sgsns[port_idx].peers, + struct gtphub_peer, entry); +#endif + + if (!sgsn) { + LOGERR("no sgsn"); + return 0; + } + + return gtphub_write(&hub->to_sgsns[port_idx].ofd, &sgsn->addr.a, sgsn->addr.l, (uint8_t*)p.data, p.data_len); @@ -583,6 +661,10 @@ int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what) return 0; #endif +#if MAP_SEQ + gtphub_map_seq(&p, sgsn, ggsn); +#endif + return gtphub_write(&hub->to_ggsns[port_idx].ofd, &ggsn->addr.a, ggsn->addr.l, (uint8_t*)p.data, p.data_len); @@ -616,7 +698,9 @@ struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind) { struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer); + INIT_LLIST_HEAD(&n->seq_map); tei_map_init(&n->teim, &bind->teip); + n->next_peer_seq = rand(); /* TODO seed or use something else */ llist_add(&n->entry, &bind->peers); return n; -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:59 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:59 +0200 Subject: [PATCH 15/15] gtphub: add signal handler to gtphub_main In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-16-git-send-email-nhofmeyr@sysmocom.de> diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index f3237fe..509c49f 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -19,12 +19,15 @@ * along with this program. If not, see . */ +#include +#include #include #include #define _GNU_SOURCE #include +#include #include #include #include @@ -148,10 +151,38 @@ void log_cfg(struct gtphub_cfg *cfg) a->addr_str, a->port); } +static void signal_handler(int signal) +{ + fprintf(stdout, "signal %u received\n", signal); + + switch (signal) { + case SIGINT: + osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL); + sleep(1); + exit(0); + break; + case SIGABRT: + /* in case of abort, we want to obtain a talloc report + * and then return to the caller, who will abort the process */ + case SIGUSR1: + case SIGUSR2: + talloc_report_full(osmo_gtphub_ctx, stderr); + break; + default: + break; + } +} + int main(int argc, char **argv) { osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); + signal(SIGINT, &signal_handler); + signal(SIGABRT, &signal_handler); + signal(SIGUSR1, &signal_handler); + signal(SIGUSR2, &signal_handler); + osmo_init_ignore_signals(); + osmo_init_logging(>phub_log_info); int rc; -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:46 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:46 +0200 Subject: [PATCH 02/15] gtphub: add to build In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-3-git-send-email-nhofmeyr@sysmocom.de> Add program osmo-gtphub from gtphub_main.c to Makefile.am. Add osmo-gtphub binary to gitignore. Sponsored-by: On-Waves ehf diff --git a/openbsc/.gitignore b/openbsc/.gitignore index 2210c47..f024d76 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -53,6 +53,7 @@ src/utils/isdnsync src/nat/bsc_nat src/gprs/osmo-sgsn src/gprs/osmo-gbproxy +src/gprs/osmo-gtphub src/osmo-bsc_nat/osmo-bsc_nat #tests diff --git a/openbsc/src/gprs/Makefile.am b/openbsc/src/gprs/Makefile.am index f012003..66d0625 100644 --- a/openbsc/src/gprs/Makefile.am +++ b/openbsc/src/gprs/Makefile.am @@ -11,6 +11,7 @@ noinst_HEADERS = gprs_sndcp.h bin_PROGRAMS = osmo-gbproxy if HAVE_LIBGTP +bin_PROGRAMS += osmo-gtphub if HAVE_LIBCARES bin_PROGRAMS += osmo-sgsn endif @@ -32,3 +33,6 @@ osmo_sgsn_LDADD = \ $(top_builddir)/src/libcommon/libcommon.a \ -lgtp $(OSMO_LIBS) $(LIBOSMOABIS_LIBS) $(LIBCARES_LIBS) \ $(LIBCRYPTO_LIBS) -lrt + +osmo_gtphub_SOURCES = gtphub_main.c +osmo_gtphub_LDADD = $(LIBOSMOCORE_LIBS) -lrt -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:45 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:45 +0200 Subject: [PATCH 01/15] Add GTP hub stub, as simplistic UDP forwarder. In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-2-git-send-email-nhofmeyr@sysmocom.de> First steps towards a new GTP hub. The aim is to mux GTP connections, so that multiple SGSN <--> GGSN links can pass through a single point. Background: allow having more than one SGSN, possibly in various remote locations. The recent addition of OAP to GSUP is related to the same background idea. Sponsored-by: On-Waves ehf create mode 100644 openbsc/src/gprs/gtphub_main.c diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 19d8fc2..189ca47 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -33,6 +33,7 @@ enum { DCTRL, DSMPP, DFILTER, + DGTPHUB, Debug_LastEntry, }; diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c new file mode 100644 index 0000000..f225efc --- /dev/null +++ b/openbsc/src/gprs/gtphub_main.c @@ -0,0 +1,297 @@ +/* GTP Hub main program */ + +/* (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include + +#define _GNU_SOURCE +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#define LOGERR(fmt, args...) \ + LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) + +#define LOG(fmt, args...) \ + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) + +extern void *osmo_gtphub_ctx; + +/* TODO move to osmocom/core/socket.c ? */ +#include +/* The caller is required to call freeaddrinfo(*result), iff zero is returned. */ +/* use this in osmo_sock_init() to remove dup. */ +static int _osmo_getaddrinfo(struct addrinfo **result, + uint16_t family, uint16_t type, uint8_t proto, + const char *host, uint16_t port) +{ + struct addrinfo hints; + char portbuf[16]; + + sprintf(portbuf, "%u", port); + memset(&hints, '\0', sizeof(struct addrinfo)); + hints.ai_family = family; + if (type == SOCK_RAW) { + /* Workaround for glibc, that returns EAI_SERVICE (-8) if + * SOCK_RAW and IPPROTO_GRE is used. + */ + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } else { + hints.ai_socktype = type; + hints.ai_protocol = proto; + } + + return getaddrinfo(host, portbuf, &hints, result); +} + +/* TODO move to osmocom/core/socket.c ? + * -- will actually disappear when the GGSNs are resolved by DNS. */ +/*! \brief Initialize a sockaddr \param[out] addr valid sockaddr pointer to + * write result to \param[out] addr_len valid pointer to write addr length to + * \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC + * \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM \param[in] proto + * Protocol like IPPROTO_TCP, IPPROTO_UDP \param[in] host remote host name or + * IP address in string form \param[in] port remote port number in host byte + * order \returns 0 on success, otherwise an error code (from getaddrinfo()). + * + * Copy the first result from a getaddrinfo() call with the given parameters to + * *addr and *addr_len. On error, do not change *addr and return nonzero. + */ +int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, + uint16_t family, uint16_t type, uint8_t proto, + const char *host, uint16_t port) +{ + struct addrinfo *res; + int rc; + rc = _osmo_getaddrinfo(&res, family, type, proto, host, port); + + if (rc != 0) { + LOGERR("getaddrinfo returned error %d\n", (int)rc); + return -EINVAL; + } + + OSMO_ASSERT(res->ai_addrlen <= sizeof(*addr)); + memcpy(addr, res->ai_addr, res->ai_addrlen); + *addr_len = res->ai_addrlen; + freeaddrinfo(res); + + return 0; +} + + +void *tall_bsc_ctx; + +const char *gtphub_copyright = + "Copyright (C) 2015 sysmocom s.m.f.c GmbH \r\n" + "License AGPLv3+: GNU AGPL version 2 or later \r\n" + "This is free software: you are free to change and redistribute it.\r\n" + "There is NO WARRANTY, to the extent permitted by law.\r\n"; + +static struct log_info_cat gtphub_categories[] = { + [DGTPHUB] = { + .name = "DGTPHUB", + .description = "GTP Hub", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, +}; + +int gtphub_log_filter_fn(const struct log_context *ctx, + struct log_target *tar) +{ + return 0; +} + +static const struct log_info gtphub_log_info = { + .filter_fn = gtphub_log_filter_fn, + .cat = gtphub_categories, + .num_cat = ARRAY_SIZE(gtphub_categories), +}; + +/* Recv datagram from from->fd, optionally write sender's address to *from_addr + * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using + * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ +int gtp_relay(struct osmo_fd *from, struct sockaddr_storage *from_addr, socklen_t *from_addr_len, + struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len) +{ + static uint8_t buf[4096]; + + errno = 0; + ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, + (struct sockaddr*)from_addr, from_addr_len); + + if (received <= 0) { + if (errno != EAGAIN) + LOGERR("error: %s\n", strerror(errno)); + return -errno; + } + + if (from_addr) { + LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); + } + + if (received <= 0) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + /* insert magic here */ + + errno = 0; + ssize_t sent = sendto(to->fd, buf, received, 0, + (struct sockaddr*)to_addr, to_addr_len); + + if (to_addr) { + LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); + } + + if (sent == -1) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + if (sent != received) + LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); + else + LOG("%d b ok\n", (int)sent); + + return 0; +} + +struct sockaddr_storage last_client_addr; +socklen_t last_client_addr_len; +struct sockaddr_storage server_addr; +socklen_t server_addr_len; + +int clients_read_cb(struct osmo_fd *clients_ofd, unsigned int what) +{ + LOG("reading from clients socket\n"); + struct osmo_fd *server_ofd = clients_ofd->data; + + if (!(what & BSC_FD_READ)) + return 0; + + last_client_addr_len = sizeof(last_client_addr); + return gtp_relay(clients_ofd, &last_client_addr, &last_client_addr_len, + server_ofd, &server_addr, server_addr_len); +} + +int server_read_cb(struct osmo_fd *server_ofd, unsigned int what) +{ + LOG("reading from server socket\n"); + struct osmo_fd *clients_ofd = server_ofd->data; + + if (!(what & BSC_FD_READ)) + return 0; + + return gtp_relay(server_ofd, NULL, NULL, + clients_ofd, &last_client_addr, last_client_addr_len); +} + +int main(int argc, char **argv) +{ + osmo_init_logging(>phub_log_info); + + int rc; + + const char* clients_addr_str = "localhost"; + uint16_t clients_port = 3386; + + const char* server_addr_str = "localhost"; + uint16_t server_port = 1234; + + /* Which local interface to use to listen for the GTP server's + * responses */ + const char* server_rx_addr_str = "localhost"; + uint16_t server_rx_port = 4321; + + rc = osmo_sockaddr_init(&server_addr, &server_addr_len, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_addr_str, server_port); + if (rc != 0) { + LOGERR("Cannot resolve '%s port %d'\n", server_addr_str, server_port); + exit(-1); + } + + struct osmo_fd clients_ofd; + struct osmo_fd server_ofd; + + memset(&clients_ofd, 0, sizeof(clients_ofd)); + clients_ofd.when = BSC_FD_READ; + clients_ofd.cb = clients_read_cb; + clients_ofd.data = &server_ofd; + + rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d\n", clients_addr_str, clients_port); + exit(-1); + } + + memset(&server_ofd, 0, sizeof(server_ofd)); + server_ofd.when = BSC_FD_READ; + server_ofd.cb = server_read_cb; + server_ofd.data = &clients_ofd; + + rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d\n", server_rx_addr_str, server_rx_port); + exit(-1); + } + + LOG("GTP server connection: %s port %d <--> %s port %d\n", + server_rx_addr_str, (int)server_rx_port, + server_addr_str, (int)server_port); + LOG("Listening for clients on %s port %d.\n", clients_addr_str, clients_port); + + int daemonize = 0; + + if (daemonize) { + rc = osmo_daemonize(); + if (rc < 0) { + LOGERR("Error during daemonize"); + exit(1); + } + } + + while (1) { + rc = osmo_select_main(0); + if (rc < 0) + exit(3); + } + + /* not reached */ + exit(0); +} -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:44 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:44 +0200 Subject: [PATCH 00/15] Add GTP hub, in early alpha stage Message-ID: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Here is the part of the branch openbsc:neels/gtphub that I believe may be merged to master at this point. (Holger: please go ahead with the merge, or tell me to do so...) The remaining bit is mostly a unit test netcat'ing to a gtphub instance. To do that properly, gtphub must be configurable. Hence I'm starting to add VTY config, which is not complete yet. Hence that part is still omitted here. Neels Hofmeyr (15): Add GTP hub stub, as simplistic UDP forwarder. gtphub: add to build gtphub: add skeletal gtphub.[hc] gtphub: populate API impl from test prog gtphub: add a todo comment gtphub: add TEI map API. gtphub: add gtphub_test.c (empty) gtphub: add TEI map test gtphub: add GTP header validation gtphub: undup code: memset on a struct. gtphub: tweak logging gtphub: index IEs, decode and log a few. gtphub: split gtp_relay() in r/w funcs gtphub: map sequence numbers SGSNs<->GGSNs gtphub: add signal handler to gtphub_main openbsc/.gitignore | 2 + openbsc/configure.ac | 1 + openbsc/include/openbsc/Makefile.am | 3 +- openbsc/include/openbsc/debug.h | 1 + openbsc/include/openbsc/gtphub.h | 151 ++++++++ openbsc/src/gprs/Makefile.am | 4 + openbsc/src/gprs/gtphub.c | 714 ++++++++++++++++++++++++++++++++++++ openbsc/src/gprs/gtphub_main.c | 256 +++++++++++++ openbsc/tests/Makefile.am | 2 +- openbsc/tests/gtphub/Makefile.am | 15 + openbsc/tests/gtphub/gtphub_test.c | 117 ++++++ openbsc/tests/gtphub/gtphub_test.ok | 1 + openbsc/tests/testsuite.at | 7 + 13 files changed, 1272 insertions(+), 2 deletions(-) create mode 100644 openbsc/include/openbsc/gtphub.h create mode 100644 openbsc/src/gprs/gtphub.c create mode 100644 openbsc/src/gprs/gtphub_main.c create mode 100644 openbsc/tests/gtphub/Makefile.am create mode 100644 openbsc/tests/gtphub/gtphub_test.c create mode 100644 openbsc/tests/gtphub/gtphub_test.ok -- 2.1.4 From nhofmeyr at sysmocom.de Thu Oct 15 22:13:48 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Fri, 16 Oct 2015 00:13:48 +0200 Subject: [PATCH 04/15] gtphub: populate API impl from test prog In-Reply-To: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> References: <1444947239-17582-1-git-send-email-nhofmeyr@sysmocom.de> Message-ID: <1444947239-17582-5-git-send-email-nhofmeyr@sysmocom.de> Sponsored-by: On-Waves ehi diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c index ffe0d4a..97e52a6 100644 --- a/openbsc/src/gprs/gtphub.c +++ b/openbsc/src/gprs/gtphub.c @@ -20,26 +20,231 @@ */ #include +#include +#include #include #include #include #include +#include void *osmo_gtphub_ctx; #define LOGERR(fmt, args...) \ LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) +#define LOG(fmt, args...) \ + LOGP(DGTPHUB, LOGL_NOTICE, fmt, ##args) + +/* TODO move this to osmocom/core/select.h ? */ +typedef int (*osmo_fd_cb_t)(struct osmo_fd *fd, unsigned int what); + +/* TODO move this to osmocom/core/linuxlist.h ? */ +#define __llist_first(head) (((head)->next == (head)) ? NULL : (head)->next) +#define llist_first(head, type, entry) llist_entry(__llist_first(head), type, entry) + + +/* general */ + +const char* const gtphub_port_idx_names[GTPH_PORT_N] = { + "CTRL", + "USER", +}; + + +/* gtphub */ + void gtphub_zero(struct gtphub *hub) { memset(hub, '\0', sizeof(*hub)); } +static int gtphub_sock_init(struct osmo_fd *ofd, + const struct gtphub_cfg_addr *addr, + osmo_fd_cb_t cb, + void *data, + int ofd_id) +{ + ofd->when = BSC_FD_READ; + ofd->cb = cb; + ofd->data = data; + ofd->priv_nr = ofd_id; + + int rc; + rc = osmo_sock_init_ofd(ofd, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + addr->addr_str, addr->port, + OSMO_SOCK_F_BIND); + if (rc < 1) { + LOGERR("Cannot bind to %s port %d (rc %d)\n", + addr->addr_str, (int)addr->port, rc); + return -1; + } + + return 0; +} + +static int gtphub_gtp_bind_init(struct gtphub_bind *b, + const struct gtphub_cfg_bind *cfg, + osmo_fd_cb_t cb, void *cb_data, + unsigned int ofd_id) +{ + memset(b, '\0', sizeof(*b)); + + INIT_LLIST_HEAD(&b->peers); + + if (gtphub_sock_init(&b->ofd, &cfg->bind, cb, cb_data, ofd_id) != 0) + return -1; + return 0; +} + +/* Recv datagram from from->fd, optionally write sender's address to *from_addr + * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using + * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ +static int gtp_relay(struct osmo_fd *from, + struct sockaddr_storage *from_addr, + socklen_t *from_addr_len, + struct osmo_fd *to, + struct sockaddr_storage *to_addr, + socklen_t to_addr_len) +{ + static uint8_t buf[4096]; + + /* recvfrom requires the available length to be set in *from_addr_len. */ + if (from_addr_len && from_addr) + *from_addr_len = sizeof(*from_addr); + + errno = 0; + ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, + (struct sockaddr*)from_addr, from_addr_len); + + if (received <= 0) { + if (errno != EAGAIN) + LOGERR("error: %s\n", strerror(errno)); + return -errno; + } + + if (from_addr) { + LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); + } + + if (received <= 0) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + /* insert magic here */ + + errno = 0; + ssize_t sent = sendto(to->fd, buf, received, 0, + (struct sockaddr*)to_addr, to_addr_len); + + if (to_addr) { + LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); + } + + if (sent == -1) { + LOGERR("error: %s\n", strerror(errno)); + return -EINVAL; + } + + if (sent != received) + LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); + else + LOG("%d b ok\n", (int)sent); + + return 0; +} + +int from_ggsns_read_cb(struct osmo_fd *from_ggsns_ofd, unsigned int what) +{ + unsigned int port_idx = from_ggsns_ofd->priv_nr; + OSMO_ASSERT(port_idx < GTPH_PORT_N); + LOG("reading from GGSN (%s)\n", gtphub_port_idx_names[port_idx]); + if (!(what & BSC_FD_READ)) + return 0; + + struct gtphub *hub = from_ggsns_ofd->data; + + /* TODO this will not be hardcoded. */ + struct gtphub_peer *sgsn = llist_first(&hub->to_sgsns[port_idx].peers, + struct gtphub_peer, entry); + if (!sgsn) { + LOGERR("no sgsn"); + return 0; + } + + return gtp_relay(from_ggsns_ofd, NULL, NULL, + &hub->to_sgsns[port_idx].ofd, + &sgsn->addr.a, sgsn->addr.l); +} + +int from_sgsns_read_cb(struct osmo_fd *from_sgsns_ofd, unsigned int what) +{ + unsigned int port_idx = from_sgsns_ofd->priv_nr; + OSMO_ASSERT(port_idx < GTPH_PORT_N); + LOG("reading from SGSN (%s)\n", gtphub_port_idx_names[port_idx]); + + if (!(what & BSC_FD_READ)) + return 0; + + struct gtphub *hub = from_sgsns_ofd->data; + + /* TODO this will not be hardcoded. */ + struct gtphub_peer *ggsn = llist_first(&hub->to_ggsns[port_idx].peers, + struct gtphub_peer, entry); + if (!ggsn) { + LOGERR("no ggsn to send to\n"); + return 0; + } + + /* so far just remembering the last sgsn */ + struct gtphub_peer *sgsn = llist_first(&hub->to_sgsns[port_idx].peers, + struct gtphub_peer, entry); + if (!sgsn) + sgsn = gtphub_peer_new(&hub->to_sgsns[port_idx]); + + return gtp_relay(from_sgsns_ofd, &sgsn->addr.a, &sgsn->addr.l, + &hub->to_ggsns[port_idx].ofd, + &ggsn->addr.a, ggsn->addr.l); +} + int gtphub_init(struct gtphub *hub, struct gtphub_cfg *cfg) { - LOGERR("%s not implemented\n", __func__); - return -1; + gtphub_zero(hub); + + int port_id; + for (port_id = 0; port_id < GTPH_PORT_N; port_id++) { + int rc; + rc = gtphub_gtp_bind_init(&hub->to_ggsns[port_id], + &cfg->to_ggsns[port_id], + from_ggsns_read_cb, hub, port_id); + if (rc < 0) + return rc; + + rc = gtphub_gtp_bind_init(&hub->to_sgsns[port_id], + &cfg->to_sgsns[port_id], + from_sgsns_read_cb, hub, port_id); + if (rc < 0) + return rc; + + /* ... */ + } + return 0; +} + +struct gtphub_peer *gtphub_peer_new(struct gtphub_bind *bind) +{ + struct gtphub_peer *n = talloc_zero(osmo_gtphub_ctx, struct gtphub_peer); + llist_add(&n->entry, &bind->peers); + return n; +} + +void gtphub_peer_del(struct gtphub_peer *peer) +{ + llist_del(&peer->entry); + talloc_free(peer); } diff --git a/openbsc/src/gprs/gtphub_main.c b/openbsc/src/gprs/gtphub_main.c index f225efc..b43e28d 100644 --- a/openbsc/src/gprs/gtphub_main.c +++ b/openbsc/src/gprs/gtphub_main.c @@ -20,27 +20,17 @@ */ #include -#include -#include #include -#include -#include - #define _GNU_SOURCE #include #include -#include -#include -#include #include +#include #include - -#include - -#include +#include #define LOGERR(fmt, args...) \ LOGP(DGTPHUB, LOGL_ERROR, fmt, ##args) @@ -113,7 +103,6 @@ int osmo_sockaddr_init(struct sockaddr_storage *addr, socklen_t *addr_len, } -void *tall_bsc_ctx; const char *gtphub_copyright = "Copyright (C) 2015 sysmocom s.m.f.c GmbH \r\n" @@ -142,139 +131,77 @@ static const struct log_info gtphub_log_info = { .num_cat = ARRAY_SIZE(gtphub_categories), }; -/* Recv datagram from from->fd, optionally write sender's address to *from_addr - * and *from_addr_len, parse datagram as GTP, and forward on to to->fd using - * *to_addr. to_addr may be NULL, if an address is set on to->fd. */ -int gtp_relay(struct osmo_fd *from, struct sockaddr_storage *from_addr, socklen_t *from_addr_len, - struct osmo_fd *to, struct sockaddr_storage *to_addr, socklen_t to_addr_len) +void log_cfg(struct gtphub_cfg *cfg) { - static uint8_t buf[4096]; - - errno = 0; - ssize_t received = recvfrom(from->fd, buf, sizeof(buf), 0, - (struct sockaddr*)from_addr, from_addr_len); - - if (received <= 0) { - if (errno != EAGAIN) - LOGERR("error: %s\n", strerror(errno)); - return -errno; - } - - if (from_addr) { - LOG("from %s\n", osmo_hexdump((uint8_t*)from_addr, *from_addr_len)); - } - - if (received <= 0) { - LOGERR("error: %s\n", strerror(errno)); - return -EINVAL; - } - - /* insert magic here */ - - errno = 0; - ssize_t sent = sendto(to->fd, buf, received, 0, - (struct sockaddr*)to_addr, to_addr_len); - - if (to_addr) { - LOG("to %s\n", osmo_hexdump((uint8_t*)to_addr, to_addr_len)); - } - - if (sent == -1) { - LOGERR("error: %s\n", strerror(errno)); - return -EINVAL; - } - - if (sent != received) - LOGERR("sent(%d) != received(%d)\n", (int)sent, (int)received); - else - LOG("%d b ok\n", (int)sent); - - return 0; -} - -struct sockaddr_storage last_client_addr; -socklen_t last_client_addr_len; -struct sockaddr_storage server_addr; -socklen_t server_addr_len; - -int clients_read_cb(struct osmo_fd *clients_ofd, unsigned int what) -{ - LOG("reading from clients socket\n"); - struct osmo_fd *server_ofd = clients_ofd->data; - - if (!(what & BSC_FD_READ)) - return 0; - - last_client_addr_len = sizeof(last_client_addr); - return gtp_relay(clients_ofd, &last_client_addr, &last_client_addr_len, - server_ofd, &server_addr, server_addr_len); -} - -int server_read_cb(struct osmo_fd *server_ofd, unsigned int what) -{ - LOG("reading from server socket\n"); - struct osmo_fd *clients_ofd = server_ofd->data; - - if (!(what & BSC_FD_READ)) - return 0; - - return gtp_relay(server_ofd, NULL, NULL, - clients_ofd, &last_client_addr, last_client_addr_len); + struct gtphub_cfg_addr *a; + a = &cfg->to_sgsns[GTPH_PORT_CONTROL].bind; + LOG("to-SGSNs bind, Control: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_sgsns[GTPH_PORT_USER].bind; + LOG("to-SGSNs bind, User: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_ggsns[GTPH_PORT_CONTROL].bind; + LOG("to-GGSNs bind, Control: %s port %d\n", + a->addr_str, a->port); + a = &cfg->to_ggsns[GTPH_PORT_USER].bind; + LOG("to-GGSNs bind, User: %s port %d\n", + a->addr_str, a->port); } int main(int argc, char **argv) { + osmo_gtphub_ctx = talloc_named_const(NULL, 0, "osmo_gtphub"); + osmo_init_logging(>phub_log_info); int rc; - const char* clients_addr_str = "localhost"; - uint16_t clients_port = 3386; - - const char* server_addr_str = "localhost"; - uint16_t server_port = 1234; - - /* Which local interface to use to listen for the GTP server's - * responses */ - const char* server_rx_addr_str = "localhost"; - uint16_t server_rx_port = 4321; - - rc = osmo_sockaddr_init(&server_addr, &server_addr_len, - AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_addr_str, server_port); - if (rc != 0) { - LOGERR("Cannot resolve '%s port %d'\n", server_addr_str, server_port); - exit(-1); - } - - struct osmo_fd clients_ofd; - struct osmo_fd server_ofd; + struct gtphub_cfg _cfg = { + .to_sgsns = { + { .bind = { + .addr_str = "127.0.0.3", + .port = 2123, + } }, + { .bind = { + .addr_str = "127.0.0.3", + .port = 2152, + } }, + }, + .to_ggsns = { + { .bind = { + .addr_str = "127.0.0.4", + .port = 2123, + } }, + { .bind = { + .addr_str = "127.0.0.4", + .port = 2152, + } }, + }, + }; - memset(&clients_ofd, 0, sizeof(clients_ofd)); - clients_ofd.when = BSC_FD_READ; - clients_ofd.cb = clients_read_cb; - clients_ofd.data = &server_ofd; + struct gtphub_cfg *cfg = &_cfg; - rc = osmo_sock_init_ofd(&clients_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, clients_addr_str, clients_port, OSMO_SOCK_F_BIND); - if (rc < 1) { - LOGERR("Cannot bind to %s port %d\n", clients_addr_str, clients_port); - exit(-1); - } + struct gtphub _hub; + struct gtphub *hub = &_hub; - memset(&server_ofd, 0, sizeof(server_ofd)); - server_ofd.when = BSC_FD_READ; - server_ofd.cb = server_read_cb; - server_ofd.data = &clients_ofd; + if (gtphub_init(hub, cfg) != 0) + return -1; - rc = osmo_sock_init_ofd(&server_ofd, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, server_rx_addr_str, server_rx_port, OSMO_SOCK_F_BIND); - if (rc < 1) { - LOGERR("Cannot bind to %s port %d\n", server_rx_addr_str, server_rx_port); + /* TODO this will not be configured, gtphub will have to find the + * ggsns from incoming GTP PDUs. */ + /* Where the GTP ggsn sits that we're relaying for */ + const char* ggsn_addr_str = "127.0.0.2"; + uint16_t ggsn_port = 2123; + struct gtphub_peer *test_ggsn = gtphub_peer_new(&hub->to_ggsns[GTPH_PORT_CONTROL]); + rc = osmo_sockaddr_init(&test_ggsn->addr.a, &test_ggsn->addr.l, + AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, + ggsn_addr_str, ggsn_port); + if (rc != 0) { + LOGERR("Cannot resolve '%s port %d'\n", ggsn_addr_str, ggsn_port); exit(-1); } - LOG("GTP server connection: %s port %d <--> %s port %d\n", - server_rx_addr_str, (int)server_rx_port, - server_addr_str, (int)server_port); - LOG("Listening for clients on %s port %d.\n", clients_addr_str, clients_port); + log_cfg(cfg); int daemonize = 0; -- 2.1.4 From marcin.starzyk at gmail.com Fri Oct 16 15:27:53 2015 From: marcin.starzyk at gmail.com (Marcin Starzyk) Date: Fri, 16 Oct 2015 17:27:53 +0200 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: <20151014210052.GC4691@dub5> References: <20151014210052.GC4691@dub5> Message-ID: Hi Neels, Thank you for your email. There is only one instance of libdbsqlite3.so - and it's a fresh build. root at debian:~/openbsc/openbsc/src/osmo-nitb# locate libdbdsqlite3.so /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so root at debian:~/openbsc/openbsc/src/osmo-nitb# file /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BuildID[sha1]=fd673630ac267d5ef3f2d82665ffc5d0b80d24fc, stripped root at debian:~/openbsc/openbsc/src/osmo-nitb# ls -ls /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so 36 -rw-r--r-- 1 root root 35696 Apr 4 2014 /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so Regards, Marcin On 14 October 2015 at 23:00, Neels Hofmeyr wrote: > Hi Marcin, > > just general guessing ... since the segfault is in libdbdsqlite3, maybe > it's a building/linking issue? Maybe there are multiple instances of a > library, or dependencies have upgraded and it needs a clean build...? > > ~Neels > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From marcin.starzyk at gmail.com Fri Oct 16 15:40:42 2015 From: marcin.starzyk at gmail.com (Marcin Starzyk) Date: Fri, 16 Oct 2015 17:40:42 +0200 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: <51E95836-8C1C-4B85-A63B-C85BD6111AEE@freyther.de> References: <51E95836-8C1C-4B85-A63B-C85BD6111AEE@freyther.de> Message-ID: Hi Holger, Thank you very much for your help I've run osmo-nitb with valgrind (trace attached). There are some errors but it seems valgrind is suppressing segmentation fault - so LUP works , which is good enough for me now. But is there any permanent solution I could work on (unfortunately I don't' understand what do you mean by using valgrind to build with the address sanitizer)? Regards, Marcin On 15 October 2015 at 09:30, Holger Freyther wrote: > > > On 13 Oct 2015, at 20:12, Marcin Starzyk > wrote: > > > > Hi All, > > > > > > I?m facing an issue with osmo-nitb (HLR/sqlite part) - segmentation > fault. All works ok for the first usage od DB (e.g. Location Updating > Request) ? but there is segmentation fault on second Location Updating > request or any other attempt to execute any command using VTY for HLR. > > please use valgrind to build with the address sanitizer. There are known > out og > bounds reads of libdbd but you don't seem to hit those. > > holger -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- root at debian:~/openbsc/openbsc/src/osmo-nitb# valgrind ./osmo-nitb --debug=DRLL:DCC:DMM:DRR:DRSL:DNM ==1178== Memcheck, a memory error detector ==1178== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==1178== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info ==1178== Command: ./osmo-nitb --debug=DRLL:DCC:DMM:DRR:DRSL:DNM ==1178== DB: Database initialized. DB: Database prepared. (part cut out) <0004> abis_rsl.c:1465 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(514) SS(0) lctype SDCCH r=LOCATION_UPDATE ra=0x08 ta=0 <0004> abis_rsl.c:1199 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:1136 LOCATION UPDATING REQUEST: MI(TMSI)=1694680593 type=IMSI ATTACH ==1178== Invalid read of size 1 ==1178== at 0x40395C9: ??? (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x40397E3: ??? (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x403A6F6: dbd_query (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4051121: dbi_conn_queryf (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x806F99E: get_equipment_by_subscr (db.c:550) ==1178== by 0x8070522: db_get_subscriber (db.c:897) ==1178== by 0x80741AC: get_subscriber (gsm_subscriber.c:67) ==1178== by 0x80741AC: subscr_get_by_tmsi (gsm_subscriber.c:227) ==1178== by 0x807FB08: mm_rx_loc_upd_req (gsm_04_08.c:657) ==1178== by 0x807FB08: gsm0408_rcv_mm (gsm_04_08.c:1137) ==1178== by 0x807FB08: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x8078959: msc_compl_l3 (osmo_msc.c:49) ==1178== by 0x804E467: gsm0408_rcvmsg (bsc_api.c:684) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== Address 0x64692e74 is not stack'd, malloc'd or (recently) free'd ==1178== <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x18 to MS. <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0003> bsc_api.c:500 CLASSMARK CHANGE CM2(len=3) CM3(len=7) ==1178== Invalid read of size 4 ==1178== at 0x4039068: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x462123c is 4 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== ==1178== Invalid write of size 2 ==1178== at 0x4039091: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x462123d is 5 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== ==1178== Invalid read of size 1 ==1178== at 0x412E488: vfprintf (vfprintf.c:1642) ==1178== by 0x41E2CF0: __vasprintf_chk (vasprintf_chk.c:66) ==1178== by 0x40510FE: dbi_conn_queryf (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070CD5: db_sync_equipment (db.c:1145) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x462123e is 0 bytes after a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x804E61A: handle_classmark_chg (bsc_api.c:526) ==1178== by 0x804E61A: dispatch_dtap (bsc_api.c:630) ==1178== by 0x804E61A: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:523 IDENTITY RESPONSE: MI(IMEI)=359809011036930 ==1178== Invalid read of size 4 ==1178== at 0x4039068: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F119: mm_rx_id_resp (gsm_04_08.c:550) ==1178== by 0x807F119: gsm0408_rcv_mm (gsm_04_08.c:1140) ==1178== by 0x807F119: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x804E40F: dispatch_dtap (bsc_api.c:650) ==1178== by 0x804E40F: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x46333f4 is 4 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F119: mm_rx_id_resp (gsm_04_08.c:550) ==1178== by 0x807F119: gsm0408_rcv_mm (gsm_04_08.c:1140) ==1178== by 0x807F119: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x804E40F: dispatch_dtap (bsc_api.c:650) ==1178== by 0x804E40F: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== ==1178== Invalid write of size 2 ==1178== at 0x4039091: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F119: mm_rx_id_resp (gsm_04_08.c:550) ==1178== by 0x807F119: gsm0408_rcv_mm (gsm_04_08.c:1140) ==1178== by 0x807F119: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x804E40F: dispatch_dtap (bsc_api.c:650) ==1178== by 0x804E40F: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x46333f5 is 5 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F119: mm_rx_id_resp (gsm_04_08.c:550) ==1178== by 0x807F119: gsm0408_rcv_mm (gsm_04_08.c:1140) ==1178== by 0x807F119: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x804E40F: dispatch_dtap (bsc_api.c:650) ==1178== by 0x804E40F: gsm0408_rcvmsg (bsc_api.c:673) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== <0002> gsm_04_08.c:487 -> LOCATION UPDATE ACCEPT <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x02 to MS. <0002> gsm_04_08.c:850 -> MM INFO <0001> gsm_04_08.c:145 (bts 0 trx 0 ts 0 pd 05) Sending 0x32 to MS. <0002> gsm_subscriber.c:305 Subscriber 260060059332155 ATTACHED LAC=1 <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:1152 TMSI Reallocation Completed. Subscriber: 260060059332155 <0000> chan_alloc.c:324 (bts=0,trx=0,ts=0,ss=0) starting release sequence <0003> gsm_04_08_utils.c:239 Sending Channel Release: Chan: Number: 0 Type: 1 <0004> abis_rsl.c:616 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD <0004> abis_rsl.c:1103 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel <0004> abis_rsl.c:1103 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 RELEASE INDICATION <0004> abis_rsl.c:662 (bts=0,trx=0,ts=0,ss=0) RF Channel Release CMD due error 0 <0004> abis_rsl.c:718 (bts=0,trx=0,ts=0,ss=0) RF CHANNEL RELEASE ACK <0004> abis_rsl.c:1465 (bts=0,trx=0,ts=0,ss=0) Activating ARFCN(514) SS(0) lctype SDCCH r=OTHER ra=0x12 ta=0 <0004> abis_rsl.c:1199 (bts=0,trx=0,ts=0,ss=0) CHANNEL ACTIVATE ACK <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 ESTABLISH INDICATION <0000> gsm_04_08.c:3584 Dispatching 04.08 message, pdisc=5 <0002> gsm_04_08.c:1035 IMSI DETACH INDICATION: MI(TMSI)=1067395470 <0002> gsm_subscriber.c:318 Subscriber 260060059332155 DETACHED <0002> gsm_04_08.c:1063 Subscriber: 260060059332155 ==1178== Invalid read of size 4 ==1178== at 0x4039068: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F427: gsm48_rx_mm_imsi_detach_ind (gsm_04_08.c:1066) ==1178== by 0x807F427: gsm0408_rcv_mm (gsm_04_08.c:1156) ==1178== by 0x807F427: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x8078959: msc_compl_l3 (osmo_msc.c:49) ==1178== by 0x804E467: gsm0408_rcvmsg (bsc_api.c:684) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x48df5cc is 4 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F427: gsm48_rx_mm_imsi_detach_ind (gsm_04_08.c:1066) ==1178== by 0x807F427: gsm0408_rcv_mm (gsm_04_08.c:1156) ==1178== by 0x807F427: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x8078959: msc_compl_l3 (osmo_msc.c:49) ==1178== by 0x804E467: gsm0408_rcvmsg (bsc_api.c:684) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== ==1178== Invalid write of size 2 ==1178== at 0x4039091: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F427: gsm48_rx_mm_imsi_detach_ind (gsm_04_08.c:1066) ==1178== by 0x807F427: gsm0408_rcv_mm (gsm_04_08.c:1156) ==1178== by 0x807F427: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x8078959: msc_compl_l3 (osmo_msc.c:49) ==1178== by 0x804E467: gsm0408_rcvmsg (bsc_api.c:684) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== Address 0x48df5cd is 5 bytes inside a block of size 6 alloc'd ==1178== at 0x40291CC: malloc (vg_replace_malloc.c:296) ==1178== by 0x403904F: dbd_quote_binary (in /usr/lib/i386-linux-gnu/dbd/libdbdsqlite3.so) ==1178== by 0x4050366: dbi_conn_quote_binary_copy (in /usr/lib/i386-linux-gnu/libdbi.so.1.1.0) ==1178== by 0x8070C86: db_sync_equipment (db.c:1139) ==1178== by 0x807F427: gsm48_rx_mm_imsi_detach_ind (gsm_04_08.c:1066) ==1178== by 0x807F427: gsm0408_rcv_mm (gsm_04_08.c:1156) ==1178== by 0x807F427: gsm0408_dispatch (gsm_04_08.c:3594) ==1178== by 0x8078959: msc_compl_l3 (osmo_msc.c:49) ==1178== by 0x804E467: gsm0408_rcvmsg (bsc_api.c:684) ==1178== by 0x806619A: abis_rsl_rx_rll (abis_rsl.c:1674) ==1178== by 0x806619A: abis_rsl_rcvmsg (abis_rsl.c:2085) ==1178== by 0x40DB106: handle_ts1_read (ipaccess.c:271) ==1178== by 0x40DB106: ipaccess_fd_cb (ipaccess.c:386) ==1178== by 0x40AD0D7: osmo_select_main (select.c:160) ==1178== by 0x804C8BE: main (bsc_hack.c:356) ==1178== <0003> osmo_msc.c:59 MSC Complete L3: Rejecting connection. <0000> chan_alloc.c:324 (bts=0,trx=0,ts=0,ss=0) starting release sequence <0003> gsm_04_08_utils.c:239 Sending Channel Release: Chan: Number: 0 Type: 1 <0004> abis_rsl.c:616 (bts=0,trx=0,ts=0,ss=0) DEACTivate SACCH CMD <0004> abis_rsl.c:1103 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 DATA INDICATION <0004> bsc_api.c:665 Got data in non active state(RELEASE REQUESTED), discarding. <0004> abis_rsl.c:1103 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel <0004> abis_rsl.c:1103 (bts=0,trx=0,ts=0,ss=0): MEAS RES for inactive channel <0000> abis_rsl.c:1653 (bts=0,trx=0,ts=0,ss=0) SAPI=0 RELEASE INDICATION <0004> abis_rsl.c:662 (bts=0,trx=0,ts=0,ss=0) RF Channel Release CMD due error 0 <0004> abis_rsl.c:718 (bts=0,trx=0,ts=0,ss=0) RF CHANNEL RELEASE ACK ^Csignal 2 received <0005> bsc_init.c:91 shutting down OML for BTS 0 ==1178== Warning: invalid file descriptor -1 in syscall close() ==1178== ==1178== HEAP SUMMARY: ==1178== in use at exit: 874,455 bytes in 9,848 blocks ==1178== total heap usage: 33,413 allocs, 23,565 frees, 3,592,816 bytes allocated ==1178== ==1178== LEAK SUMMARY: ==1178== definitely lost: 0 bytes in 0 blocks ==1178== indirectly lost: 0 bytes in 0 blocks ==1178== possibly lost: 869,985 bytes in 9,729 blocks ==1178== still reachable: 4,470 bytes in 119 blocks ==1178== suppressed: 0 bytes in 0 blocks ==1178== Rerun with --leak-check=full to see details of leaked memory ==1178== ==1178== For counts of detected and suppressed errors, rerun with: -v ==1178== ERROR SUMMARY: 73 errors from 8 contexts (suppressed: 0 from 0) From holger at freyther.de Fri Oct 16 15:57:00 2015 From: holger at freyther.de (Holger Freyther) Date: Fri, 16 Oct 2015 23:57:00 +0800 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: References: <51E95836-8C1C-4B85-A63B-C85BD6111AEE@freyther.de> Message-ID: <6A2C9CA3-F6E5-4148-B419-EB49F7D84CF4@freyther.de> > On 16 Oct 2015, at 23:40, Marcin Starzyk wrote: > > Hi Holger, > > Thank you very much for your help > > I've run osmo-nitb with valgrind (trace attached). There are some errors but it seems valgrind is suppressing segmentation fault - so LUP works , which is good enough for me now. But is there any permanent solution I could work on (unfortunately I don't' understand what do you mean by using valgrind to build with the address sanitizer)? libdi/libdbd has various memory issues. Some I fixed, some are open. In general we want to stop using it. Would you be interested in contributing a patch to use sqlite3 directly and creating a migration path (e.g. to convert the blob format used by dbd/dbi to native support in sqlite)? holger From laforge at gnumonks.org Sat Oct 17 08:53:53 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 17 Oct 2015 10:53:53 +0200 Subject: [PATCH] initial commit for libosmo-gtp In-Reply-To: <20151015133202.GA1306@dub5> References: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> <20151015133202.GA1306@dub5> Message-ID: <20151017085353.GC2109@nataraja> Hi Neels and Pablo, first of all, it is great to see this code appear, I never liked libgtp much either... On Thu, Oct 15, 2015 at 03:32:02PM +0200, Neels Hofmeyr wrote: > > +struct gtp0_header { > > +#if BYTE_ORDER == BIG_ENDIAN > > + uint8_t version:3, > > + pt:1, > > + spare:3, > > + snn:1; > > +#elif BYTE_ORDER == LITTLE_ENDIAN > > + uint8_t snn:1, > > + spare:3, > > + pt:1, > > + version:3; > > Hmm, endianness is about *byte* order, not *bit* order, right? Life would be too simple for that. It there is both byte-endinanness and bit-endianness. And if you define bit-fields using the c syntax, then (at least on all platforms I know), you have to split your definition like above. Look at the definitions of IP header and TCP header in your /usr/include/netinet/ip.h or /usr/include/netinet/tcp.h > to use one of the existing decoding functions for endianness instead: > - ntohs()/ntohl() that doesn't help you with what pablo defined, as it is about an uint8_t ;) > > + gtp0h->seq = htons(seq); > > + gtp0h->tid = htobe64(tid); > > Ah, here it is: htons() stored in the header struct. > I'd prefer a host-byte-order struct. The struct itself (for 16bit/32bit members of the struct) dosen't care. And the function you refer to takes host-byte-order input and then pushes the values as network byte ordre to the msgb, which I think is fine. > > +void gtp0_header_end(struct gtp0_header *gtp0h, struct msgb *msg) > > +{ > > + gtp0h->length = htons(msg->len - sizeof(*gtp0h)); > > With msgb_alloc_headroom(), it is possible to first write the IEs to the > msgb, and then prepend the header with the correct size later on. See for > example in openbsc, gprs_gsup_msgb_alloc() and ipa_msg_push_header(). yes, that is the preferred method. > > +static const struct tlv_definition gtp_pdp_create_req_attr_tlvdef = { > > + .def = { > > + [GTPV0_IE_QOS_PROFILE] = { TLV_TYPE_FIXED, 3 }, > > +}; > > I can't begin to express how much better this looks than the old gtpie.h! Well, that's how we generaly deal with TLVs in libosmocore based programs :) > > +void *msgb_tv_put_be24(struct msgb *msg, int type, uint32_t value) > > +{ > > + value = htonl(value & 0x00ffffff) >> 8; > > heh, interesting :) > This won't work on a BE system. You can't portably do a > host CPU shift-right on a network byte order value. On a BE system the htonl() will evaporate and you end up with doning only a shift-right by 8, which is probably not what you wanted, indeed. > Imagining a class: Big Endian 101, Professor asks: "Can anyone explain > the results of this code on a big endian and a little endian system?" > Half an hour of vigorous discussion follows. Beware, Pablo is a CS Professor at Sevilla University ;) -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From sipos.csaba at kvk.uni-obuda.hu Sat Oct 17 10:48:58 2015 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Sat, 17 Oct 2015 12:48:58 +0200 (CEST) Subject: Femto - IuH In-Reply-To: <1674558519.3757814.1445078689447.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> Dear Harald, Now that the implementation of the IuH interface is on its way, can you please recommend any femtos which you think can probably be used with this implementation? I think in a previous conversation in this subject someone mentioned that probably Alcatel based units has the highest chance because of certain configuration and/or implementation options. Anyway, if you can shed some light on this subject, that would be awsome. Thanks! Csaba From laforge at gnumonks.org Sat Oct 17 13:15:49 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 17 Oct 2015 15:15:49 +0200 Subject: Femto - IuH In-Reply-To: <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> References: <1674558519.3757814.1445078689447.JavaMail.zimbra@kvk.uni-obuda.hu> <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: <20151017131549.GG2109@nataraja> Hi Sipos, On Sat, Oct 17, 2015 at 12:48:58PM +0200, Sipos Csaba wrote: > Now that the implementation of the IuH interface is on its way, can > you please recommend any femtos which you think can probably be used > with this implementation? I have no idea. The point is basically to find (surplus, second hand) femtocells on the market, that a) speak an Iuh interface (older models have URSL, UMA/GAN or other proprietary protocols) b) can be rooted somehow, so we can either replace the ipsec certificates, or disable ipsec towards the SEGW c) are available in quantities that make them interesting/useful to the community At sysmocom we tried very hard to find a femtocell manufaturer who would be willing to sell certain volumes to us, where we could then sell them to the open market (including the community). However, this has not been successful for several reasons, including: * the quantities of femtocells are typically large, much larger than we would likely be able to sell * the vendors typically work with one supplier of the respective SEGW/HNBGW and associated management solution, and they don't like (or maybe even are contractually forbidden) from selling to anyone who does not at the same time operate that core network infrastructure. As we are building our own infrastructure, they don't like that. > I think in a previous conversation in this subject someone mentioned > that probably Alcatel based units has the highest chance because of > certain configuration and/or implementation options. That was years ago. While those units are still quite hackable, they predate Iuh by some years and have some kind of proprietary framing around the RANAP (Iu) messages. So if you or anyone else on this list has some suggestions, it would of course be more than welcome. Some people are looking into now obsolete Huawei models (based on vxworks), where there was some presentation earlier this year: http://www.slideshare.net/arbitrarycode/adventures-in-femtoland-350-yuan-for-invaluable-fun It still needs to be seen what models using what firmware release are vulnerable as described in the slides, if the results can be reproduced, etc. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From sipos.csaba at kvk.uni-obuda.hu Sat Oct 17 13:50:52 2015 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Sat, 17 Oct 2015 15:50:52 +0200 (CEST) Subject: Femto - IuH In-Reply-To: <20151017131549.GG2109@nataraja> References: <1674558519.3757814.1445078689447.JavaMail.zimbra@kvk.uni-obuda.hu> <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> <20151017131549.GG2109@nataraja> Message-ID: <743308305.3768523.1445089852857.JavaMail.zimbra@kvk.uni-obuda.hu> Hi Harald, Thanks for clearing that up. Do you think that these vendor agnostic implementations can cahnge with the small cell forum API? http://scf.io/en/documents/082_-_LTE_eNB_L1_API_definition.php Do we know any femtos on the market that actually is compatible with this API? And if we have one, can that help us? Personally I wanted to order an AT&T small cell (I think its Cisco based) because its cheap and available, but it is quite an old model. I don't know if anybody knows sometinhg about this particular model? If there is no opposition I might order one just to play with it. Or maybe you have some specific models in mind you always wanted to try but never had the time? If you have any recommendations I would be happy to look into them. Regards, Csaba ----- Eredeti ?zenet ----- Felad?: "Harald Welte" C?mzett: "Sipos Csaba" M?solatot kap: "OpenBSC Mailing List" Elk?ld?tt ?zenetek: Szombat, 2015. Okt?ber 17. 15:15:49 T?rgy: Re: Femto - IuH Hi Sipos, On Sat, Oct 17, 2015 at 12:48:58PM +0200, Sipos Csaba wrote: > Now that the implementation of the IuH interface is on its way, can > you please recommend any femtos which you think can probably be used > with this implementation? I have no idea. The point is basically to find (surplus, second hand) femtocells on the market, that a) speak an Iuh interface (older models have URSL, UMA/GAN or other proprietary protocols) b) can be rooted somehow, so we can either replace the ipsec certificates, or disable ipsec towards the SEGW c) are available in quantities that make them interesting/useful to the community At sysmocom we tried very hard to find a femtocell manufaturer who would be willing to sell certain volumes to us, where we could then sell them to the open market (including the community). However, this has not been successful for several reasons, including: * the quantities of femtocells are typically large, much larger than we would likely be able to sell * the vendors typically work with one supplier of the respective SEGW/HNBGW and associated management solution, and they don't like (or maybe even are contractually forbidden) from selling to anyone who does not at the same time operate that core network infrastructure. As we are building our own infrastructure, they don't like that. > I think in a previous conversation in this subject someone mentioned > that probably Alcatel based units has the highest chance because of > certain configuration and/or implementation options. That was years ago. While those units are still quite hackable, they predate Iuh by some years and have some kind of proprietary framing around the RANAP (Iu) messages. So if you or anyone else on this list has some suggestions, it would of course be more than welcome. Some people are looking into now obsolete Huawei models (based on vxworks), where there was some presentation earlier this year: http://www.slideshare.net/arbitrarycode/adventures-in-femtoland-350-yuan-for-invaluable-fun It still needs to be seen what models using what firmware release are vulnerable as described in the slides, if the results can be reproduced, etc. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From laforge at gnumonks.org Sat Oct 17 18:20:09 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sat, 17 Oct 2015 20:20:09 +0200 Subject: Femto - IuH In-Reply-To: <743308305.3768523.1445089852857.JavaMail.zimbra@kvk.uni-obuda.hu> References: <1674558519.3757814.1445078689447.JavaMail.zimbra@kvk.uni-obuda.hu> <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> <20151017131549.GG2109@nataraja> <743308305.3768523.1445089852857.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: <20151017182009.GD4749@nataraja> On Sat, Oct 17, 2015 at 03:50:52PM +0200, Sipos Csaba wrote: > Do you think that these vendor agnostic implementations can cahnge > with the small cell forum API? no. > http://scf.io/en/documents/082_-_LTE_eNB_L1_API_definition.php This is the Layer 1 API between the PHY and the MAC/RLC layer. This is _very_ far from the Iuh interface. Compare it with the L1SAP interface of OsmoBTS. And Iuh is on th level of the A interface, not even Abis. Also, this API is for LTE, not for UMTS. > Do we know any femtos on the market that actually is compatible with > this API? And if we have one, can that help us? You can find transceiver hardware + PHY implementations that offer this L1 API. However, that is not a complete (femto/small) cell, but the hardware plus the PHY. I don't think anyone will quickly come about and implement all the missing layers, so in the context of developing a NITB with Iuh interface, it doesn't really help. > Or maybe you have some specific models in mind you always wanted to > try but never had the time? If you have any recommendations I would be > happy to look into them. I haven't really looked at any femtocells for a very long time. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From nhofmeyr at sysmocom.de Sat Oct 17 20:52:07 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Sat, 17 Oct 2015 22:52:07 +0200 Subject: [PATCH] initial commit for libosmo-gtp In-Reply-To: <20151017085353.GC2109@nataraja> References: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> <20151015133202.GA1306@dub5> <20151017085353.GC2109@nataraja> Message-ID: <20151017205207.GA16768@dub5> On Sat, Oct 17, 2015 at 10:53:53AM +0200, Harald Welte wrote: > Hi Neels and Pablo, > > first of all, it is great to see this code appear, I never liked libgtp > much either... > > On Thu, Oct 15, 2015 at 03:32:02PM +0200, Neels Hofmeyr wrote: > > > +struct gtp0_header { > > > +#if BYTE_ORDER == BIG_ENDIAN > > > + uint8_t version:3, > > > + pt:1, > > > + spare:3, > > > + snn:1; > > > +#elif BYTE_ORDER == LITTLE_ENDIAN > > > + uint8_t snn:1, > > > + spare:3, > > > + pt:1, > > > + version:3; > > /usr/include/netinet/ip.h or /usr/include/netinet/tcp.h Learning never ends indeed. Thanks! And then, I take it, the bits within each bitfield element are also reversed, but since it matches the host, they are correct and ready... I'm confused by the fact that the bitfields' order is "reversed" on BE. Is that consistent with shift left and right operators?? Don't tell me that you have to reverse those as well on a BE system. Either way, would be great if C had a way that doesn't need everything written twice... [... TLVs] > Well, that's how we generaly deal with TLVs in libosmocore based > programs :) About that: I see that values are referenced from the struct tlv_parsed. That's mighty fast. But GTP does have duplicate IEs: more than one LV with the same T. I need to loop tlv_parse_one() myself then, right? :/ I noticed because I found code in libgtp that targets the second occurence of an IE type. The one instance I know of so far is in etsi/GSM/by_chapter/29.060.pdf 7.3.2 Create PDP Context Request which has NSAPI and Linked NSAPI both referencing 7.7.17, as well as two SGSN addresses both referencing 7.7.32 as IE description. > Beware, Pablo is a CS Professor at Sevilla University ;) /me bows I actually picked some oranges in the Sevilla Monasteria once - delicious! It was free, too. And I had una thervesa on the Alameda :) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Sun Oct 18 08:23:50 2015 From: laforge at gnumonks.org (Harald Welte) Date: Sun, 18 Oct 2015 10:23:50 +0200 Subject: [PATCH] initial commit for libosmo-gtp In-Reply-To: <20151017205207.GA16768@dub5> References: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> <20151015133202.GA1306@dub5> <20151017085353.GC2109@nataraja> <20151017205207.GA16768@dub5> Message-ID: <20151018082350.GA24238@nataraja> Hi Neels, On Sat, Oct 17, 2015 at 10:52:07PM +0200, Neels Hofmeyr wrote: > [... TLVs] > > Well, that's how we generaly deal with TLVs in libosmocore based > > programs :) > > About that: I see that values are referenced from the struct tlv_parsed. > That's mighty fast. But GTP does have duplicate IEs: more than one LV > with the same T. I need to loop tlv_parse_one() myself then, right? :/ Indeed. At least for those messages where that might happen. I don't really see a clean way to handle that, other than having a function where the caller hands in multiple struct tlv_parsed (or an array of them), which is equally ugly. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From holger at freyther.de Sun Oct 18 10:23:50 2015 From: holger at freyther.de (Holger Freyther) Date: Sun, 18 Oct 2015 18:23:50 +0800 Subject: osmo-nitb (HLR/sqlite part) - segmentation fault In-Reply-To: References: <51E95836-8C1C-4B85-A63B-C85BD6111AEE@freyther.de> <6A2C9CA3-F6E5-4148-B419-EB49F7D84CF4@freyther.de> Message-ID: > On 18 Oct 2015, at 05:26, Marcin Starzyk wrote: > Hi! > Is it acceptable for you?- if so - how should I start? (I've read section for developers on openbsc wiki but still things are not clear to me as to how to start) 0.) The first libdbi corruption has been fixed by a patch[1]. You might just suffer from this one. 1.) In OpenBSC and when linking against libdbi 0.9 we get crashes on i386. I have a first analysis here[2] you could see which part fails. E.g. you could start compiling libdbi/libdi-drivers on your system with the address sanitizer (ASAN) and see if crashes are already triggered by the builtin testsuite, if not move on to OpenBSC 2.) Start looking into replacing libdbi calls with direct sqlite3 calls. To store "BLOB" libdi was wrapping it and we either copy that code or we migrate the data. E.g. have a look at how we migrate SMS on a schema change. 1st and 2nd are two alternatives, both of them have ups and downs and are acceptable ways to move forward. holger [1] https://github.com/sysmocom/meta-telephony/blob/master/recipes-misc/libdbi/files/memory-corruption-fixes.patch [2] http://sourceforge.net/p/libdbi/mailman/message/32607036/ From sipos.csaba at kvk.uni-obuda.hu Sun Oct 18 19:09:06 2015 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Sun, 18 Oct 2015 21:09:06 +0200 (CEST) Subject: Femto - IuH In-Reply-To: <20151017182009.GD4749@nataraja> References: <1674558519.3757814.1445078689447.JavaMail.zimbra@kvk.uni-obuda.hu> <690356817.3757963.1445078938485.JavaMail.zimbra@kvk.uni-obuda.hu> <20151017131549.GG2109@nataraja> <743308305.3768523.1445089852857.JavaMail.zimbra@kvk.uni-obuda.hu> <20151017182009.GD4749@nataraja> Message-ID: <216362132.3956430.1445195346646.JavaMail.zimbra@kvk.uni-obuda.hu> Hi Harald, SCF has a similar thing for 3G femtos, but its pretty much the same L1 implementation and not talking about the management of the femtos. I actually looking into these units: http://www.ebay.com/itm/AT-T-3G-MicroCell-signal-booster-DPH151-AT/161858135473?_trksid=p2047675.c100005.m1851&_trkparms=aid%3D222007%26algo%3DSIC.MBE%26ao%3D1%26asc%3D33873%26meid%3D41d794ede0bf4edba3633feaa00b4db3%26pid%3D100005%26rk%3D2%26rkt%3D6%26sd%3D291591420414 There is a lot of them, they are fairly cheap, I already know they run embedded linux (95% that its not VxWorks), and it is a Cisco product. If you or nobody has any opposition (know something that makes this unit a near impossible candidate), I will probably buy one and take a look. It seems the successor of this product is also embedded linux, and it seems AT&T deploys them in huge quantities, so this seems to be a good candidate. Regards, Csaba ----- Eredeti ?zenet ----- Felad?: "Harald Welte" C?mzett: "Sipos Csaba" M?solatot kap: "OpenBSC Mailing List" Elk?ld?tt ?zenetek: Szombat, 2015. Okt?ber 17. 20:20:09 T?rgy: Re: Femto - IuH On Sat, Oct 17, 2015 at 03:50:52PM +0200, Sipos Csaba wrote: > Do you think that these vendor agnostic implementations can cahnge > with the small cell forum API? no. > http://scf.io/en/documents/082_-_LTE_eNB_L1_API_definition.php This is the Layer 1 API between the PHY and the MAC/RLC layer. This is _very_ far from the Iuh interface. Compare it with the L1SAP interface of OsmoBTS. And Iuh is on th level of the A interface, not even Abis. Also, this API is for LTE, not for UMTS. > Do we know any femtos on the market that actually is compatible with > this API? And if we have one, can that help us? You can find transceiver hardware + PHY implementations that offer this L1 API. However, that is not a complete (femto/small) cell, but the hardware plus the PHY. I don't think anyone will quickly come about and implement all the missing layers, so in the context of developing a NITB with Iuh interface, it doesn't really help. > Or maybe you have some specific models in mind you always wanted to > try but never had the time? If you have any recommendations I would be > happy to look into them. I haven't really looked at any femtocells for a very long time. -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From ruben.undheim at gmail.com Thu Oct 15 18:13:56 2015 From: ruben.undheim at gmail.com (Ruben Undheim) Date: Thu, 15 Oct 2015 20:13:56 +0200 Subject: libosmocore and osmo-trx uploaded to Debian Message-ID: <20151015181356.GA21711@macbookair> Hi everyone, I just want to announce that packages of libosmocore and osmo-trx have been uploaded to Debian. They are waiting in the NEW queue to be accepted by the FTP masters: - https://ftp-master.debian.org/new/libosmocore_0.8.3-1.html - https://ftp-master.debian.org/new/osmo-trx_0~20150325gitf147b17+dfsg-1.html Best regards, Ruben From ruben.undheim at gmail.com Mon Oct 19 05:21:03 2015 From: ruben.undheim at gmail.com (Ruben Undheim) Date: Mon, 19 Oct 2015 07:21:03 +0200 Subject: libosmocore and osmo-trx uploaded to Debian In-Reply-To: <20151015181356.GA21711@macbookair> References: <20151015181356.GA21711@macbookair> Message-ID: Hi everyone, I just want to announce that packages of libosmocore and osmo-trx have been uploaded to Debian. They are waiting in the NEW queue to be accepted by the FTP masters: - https://ftp-master.debian.org/new/libosmocore_0.8.3-1.html - https://ftp-master.debian.org/new/osmo-trx_0~20150325gitf147b17+dfsg-1.html Best regards, Ruben -------------- next part -------------- An HTML attachment was scrubbed... URL: From nhofmeyr at sysmocom.de Mon Oct 19 11:01:55 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Mon, 19 Oct 2015 13:01:55 +0200 Subject: osmo_loadXXbe_ext -- was: [PATCH 1/8] libcommon: soak up three static functions. In-Reply-To: <20151008234454.GB3991@dub5> References: <20151008234454.GB3991@dub5> Message-ID: <20151019110155.GA3500@dub5> bump ... any opinions on changing osmo_load*_ext() so that it always writes the least significant end instead of (currently) the most significant one? Details below... It would technically require a major version bump, but are there likely any callers relying on current behavior? It would not make much sense anyway (maybe a partial read, but I see no way to resume such read). Thanks, ~Neels On Fri, Oct 09, 2015 at 01:44:54AM +0200, Neels Hofmeyr wrote: > > > +uint64_t decode_big_endian(const uint8_t *data, size_t data_len) > > > +uint8_t *encode_big_endian(uint64_t value, size_t data_len) > > have you looked at osmo_load64le_ext of libosmocore? I think you don't need > > these routines. and it applies to GSUP too. > > Ah, nice. Hadn't seen those yet. > > Oh well, I notice that the decode_big_endian() is more elegant to use than > osmo_load64be_ext(), since passing a length of less than 8 bytes to > decode_big_endian() writes the N least significant bytes, and allows this: > > uint16_t val; > val = decode_big_endian(buf, sizeof(val)); > > It has the desired result. However this: > > uint16_t val; > val = osmo_load64be_ext(buf, sizeof(val)); > > will write the bytes bound to the "wrong", most significant end of the > uint64_t, and only zero is written to val. So I would need to explicitly > use osmo_load16be(). > > Which is less elegant, isn't it? Is it about performance? Would changing > that behavior break anything besides bitrev_test.c? (It checks for exactly > this ordering) > > I'd like to change only the osmo_loadXXbe_ext() function, so that it > writes the least significant bytes, like decode_big_endian() does. But > first, does it write the most significant end for a reason? > > If it doesn't, we don't actually need to generate functions for each > integer size. Instead we can glorify the decode_big_endian() and > encode_big_endian(), made threadsafe, to become osmo_load/store*(). > > Right?? > > Except for bitrev_test.c, all callers I found (in my currently cloned few > source trees) use only the non-"_ext" functions, and would not be affected > by the change at all. > > ~Neels > > > P.S.: Holger, after I said to you that osmo_loadXXbe_ext is not less > elegant after all, I re-re-realized that it is indeed still less > elegant... -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From laforge at gnumonks.org Mon Oct 19 12:23:34 2015 From: laforge at gnumonks.org (Harald Welte) Date: Mon, 19 Oct 2015 14:23:34 +0200 Subject: Oct 21, 8pm / Osmocom Berlin Meeting Message-ID: <20151019122334.GF14744@nataraja> Hi all! This is the announcement for the re-incarnation of our bi-weekly Osmocom Berlin Meeting. Oct 21, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin There is no formal presentation this time, but * there will be SDR equipment in case more people are interested to have a look at MPT1327 and/or Tetrapol signals that can be received in Berlin * Harald would like to discuss OpenBSC website / documentation improvements The meeting is open to anyone interested in mobile communications. You do not have to be involved with the Osmocom projects in order to attend. Anyone interested in mobile communications protocols is welcome. If you are interested to show up, feel free to do so. The meeting is "free as in free beer", despite no actual free beer being around ;) More information can be found at http://openbsc.osmocom.org/trac/wiki/OsmocomMeeting/Berlin Regards, Harald -- - Harald Welte ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From jerlbeck at sysmocom.de Mon Oct 19 12:42:50 2015 From: jerlbeck at sysmocom.de (Jacob Erlbeck) Date: Mon, 19 Oct 2015 14:42:50 +0200 Subject: [PATCH] initial commit for libosmo-gtp In-Reply-To: <20151017205207.GA16768@dub5> References: <1444889522-12665-1-git-send-email-pablo@gnumonks.org> <20151015133202.GA1306@dub5> <20151017085353.GC2109@nataraja> <20151017205207.GA16768@dub5> Message-ID: <5624E54A.9000507@sysmocom.de> On 17.10.2015 22:52, Neels Hofmeyr wrote: > On Sat, Oct 17, 2015 at 10:53:53AM +0200, Harald Welte wrote: >> Hi Neels and Pablo, >> >> first of all, it is great to see this code appear, I never liked libgtp >> much either... >> >> On Thu, Oct 15, 2015 at 03:32:02PM +0200, Neels Hofmeyr wrote: >>>> +struct gtp0_header { >>>> +#if BYTE_ORDER == BIG_ENDIAN >>>> + uint8_t version:3, >>>> + pt:1, >>>> + spare:3, >>>> + snn:1; >>>> +#elif BYTE_ORDER == LITTLE_ENDIAN >>>> + uint8_t snn:1, >>>> + spare:3, >>>> + pt:1, >>>> + version:3; >> >> /usr/include/netinet/ip.h or /usr/include/netinet/tcp.h > > Learning never ends indeed. Thanks! > > And then, I take it, the bits within each bitfield element are also > reversed, but since it matches the host, they are correct and ready... > > I'm confused by the fact that the bitfields' order is "reversed" on BE. > Is that consistent with shift left and right operators?? Don't tell me > that you have to reverse those as well on a BE system. The ordering of bitfields is not necessarily tied to the byte ordering. > > Either way, would be great if C had a way that doesn't need everything > written twice... In fact you have to write it two times only, because we know we are using gcc. The C99 spec leaves it open to the compiler implementer whether the bit fields within a unit are "high-order to low-order or low-order to high-order" [C99: 6.7.2.1 (10)]. Have a look at the definition of the 'ms_struct' and 'gcc_struct' variable attributes in the gcc documentation for further details. Supporting both ABIs would lead to four variants. So this approach to do serialisation/deserialisation is not really portable with respect to the specification. Jacob -- - Jacob Erlbeck http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From aschultz at tpip.net Mon Oct 26 17:14:19 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Mon, 26 Oct 2015 18:14:19 +0100 (CET) Subject: [RFC] GTP-U v0/v1 kernel module Message-ID: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> Hi, Some time ago, Pablo Neira Ayuso wrote a GTP-U kernel module and OpenGGSN support for it. The OpenGGSN side is easily available in the osmocom git [1]. The kernel part is somewhat harder to find, but it's at [2]. It seems that both sides are at 70% completion and only somewhat working. I have played with the kernel module, changed a couple things and would like to get some feedback on my changes. It can be found at: https://github.com/RoadRunnr/osmo-ggsn Things I've changed: * requires kernel from net-next (or 4.3) * convert to use the existing kernel iptunnel infrastructure * fix GTP-u v1 TEI usage (we need one TEI for RX and another one for TX) * use UDP sockets passed from userland for sending (instead of direct push to network interface) * fix resource release on GTP-U socket shutdown * release all resource on module removal The module currently works with a proof-of-concept GGSN/PGW implemented in Erlang (will post once the licensing is sorted). OpenGGSN will need some small changes (will post soon). Andreas [1]: http://git.osmocom.org/openggsn/ [2]: http://git.sysmocom.de/osmo-ggsn From sipos.csaba at kvk.uni-obuda.hu Mon Oct 26 20:45:26 2015 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Mon, 26 Oct 2015 21:45:26 +0100 (CET) Subject: Meas_web and meas_json In-Reply-To: <1510240027.5443523.1445891932058.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: <1010582984.5443937.1445892326559.JavaMail.zimbra@kvk.uni-obuda.hu> Hi Alexander, Just wanted to thank you for the web version of meas_vis utility, and wanted to confirm that it works very well with Nokia Site family (E1 based) and the USRP B200 too :-) If someone missed it, the web version can be found here: https://github.com/fairwaves/meas_web It would make life easier if the meas_json utility would make it to the master branch: http://cgit.osmocom.org/openbsc/log/?h=achemeris/meas_json Is there a reason it is not being merged? Regards, Csaba From alexander.chemeris at gmail.com Mon Oct 26 21:15:30 2015 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Tue, 27 Oct 2015 00:15:30 +0300 Subject: Meas_web and meas_json In-Reply-To: <1010582984.5443937.1445892326559.JavaMail.zimbra@kvk.uni-obuda.hu> References: <1510240027.5443523.1445891932058.JavaMail.zimbra@kvk.uni-obuda.hu> <1010582984.5443937.1445892326559.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: Hi Sipos, On Mon, Oct 26, 2015 at 11:45 PM, Sipos Csaba wrote: > Just wanted to thank you for the web version of meas_vis utility, and wanted to confirm that it works very well with Nokia Site family (E1 based) and the USRP B200 too :-) Glad someone found it useful and was even able to get it working. :) Do you mind contributing to the documentation? It would be great to have a brief page about it at the wiki and some more details for the installation instructions, but we never got to write it :( > It would make life easier if the meas_json utility would make it to the master branch: > > http://cgit.osmocom.org/openbsc/log/?h=achemeris/meas_json > > Is there a reason it is not being merged? I guess the primary reason is that I've never submitted it. I still plan on doing that, just need to find some time to do that. -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From sipos.csaba at kvk.uni-obuda.hu Mon Oct 26 21:51:04 2015 From: sipos.csaba at kvk.uni-obuda.hu (Sipos Csaba) Date: Mon, 26 Oct 2015 22:51:04 +0100 (CET) Subject: Meas_web and meas_json In-Reply-To: References: <1510240027.5443523.1445891932058.JavaMail.zimbra@kvk.uni-obuda.hu> <1010582984.5443937.1445892326559.JavaMail.zimbra@kvk.uni-obuda.hu> Message-ID: <213728024.5449223.1445896264483.JavaMail.zimbra@kvk.uni-obuda.hu> Dear Alexander, > Do you mind contributing to the documentation? I don't mind at all :-) In fact I have some points which was a littlebit to brief and we might want to put some more details. For example the fact that the meas_json utility is not part of the master and where can it be found :-) What would be nice is to make it work with the PCU to get and display the GPRS/EDGE meas data too. Will put up some wiki (or at least further detail the readme) and send it to you when I have the time, but first I want to finish the B200/B210 (and potentionally UmTRX) wiki page which you can find here: http://openbsc.osmocom.org/trac/wiki/Ettus_USRP_B2xx_family Its not finished yet, but most of the nasty stuff is up and it works, but here and there some more details will be needed for newbies. If you, or anyone else find any problems, have some questions or suggestions, please tell me so I can correct it :-) Regards, Csaba ----- Eredeti ?zenet ----- Felad?: "Alexander Chemeris" C?mzett: "Sipos Csaba" M?solatot kap: "OpenBSC Mailing List" Elk?ld?tt ?zenetek: H?tf?, 2015. Okt?ber 26. 22:15:30 T?rgy: Re: Meas_web and meas_json Hi Sipos, On Mon, Oct 26, 2015 at 11:45 PM, Sipos Csaba wrote: > Just wanted to thank you for the web version of meas_vis utility, and wanted to confirm that it works very well with Nokia Site family (E1 based) and the USRP B200 too :-) Glad someone found it useful and was even able to get it working. :) Do you mind contributing to the documentation? It would be great to have a brief page about it at the wiki and some more details for the installation instructions, but we never got to write it :( > It would make life easier if the meas_json utility would make it to the master branch: > > http://cgit.osmocom.org/openbsc/log/?h=achemeris/meas_json > > Is there a reason it is not being merged? I guess the primary reason is that I've never submitted it. I still plan on doing that, just need to find some time to do that. -- Regards, Alexander Chemeris. CEO, Fairwaves, Inc. https://fairwaves.co From pablo at gnumonks.org Mon Oct 26 23:07:56 2015 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Tue, 27 Oct 2015 00:07:56 +0100 Subject: [RFC] GTP-U v0/v1 kernel module In-Reply-To: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> References: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> Message-ID: <20151026230756.GA16420@salvia> On Mon, Oct 26, 2015 at 06:14:19PM +0100, Andreas Schultz wrote: > Hi, > > Some time ago, Pablo Neira Ayuso wrote a GTP-U kernel module and OpenGGSN > support for it. The OpenGGSN side is easily available in the osmocom git [1]. > The kernel part is somewhat harder to find, but it's at [2]. > > It seems that both sides are at 70% completion and only somewhat working. > > I have played with the kernel module, changed a couple things and would > like to get some feedback on my changes. > > It can be found at: https://github.com/RoadRunnr/osmo-ggsn > > Things I've changed: > > * requires kernel from net-next (or 4.3) > * convert to use the existing kernel iptunnel infrastructure > * fix GTP-u v1 TEI usage (we need one TEI for RX and another one > for TX) > * use UDP sockets passed from userland for sending (instead of > direct push to network interface) > * fix resource release on GTP-U socket shutdown > * release all resource on module removal > > The module currently works with a proof-of-concept GGSN/PGW implemented > in Erlang (will post once the licensing is sorted). OpenGGSN will need > some small changes (will post soon). Will looking into this, probably we can get this submitted mainstream soon. Thanks for sharing incremental updates. From laforge at gnumonks.org Tue Oct 27 07:36:35 2015 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 27 Oct 2015 08:36:35 +0100 Subject: [RFC] GTP-U v0/v1 kernel module In-Reply-To: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> References: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> Message-ID: <20151027073635.GI2056@nataraja> Hi Andreas, good to seee you on the mailing list, and thanks for sharing your work. On Mon, Oct 26, 2015 at 06:14:19PM +0100, Andreas Schultz wrote: > Some time ago, Pablo Neira Ayuso wrote a GTP-U kernel module and OpenGGSN > support for it. The OpenGGSN side is easily available in the osmocom git [1]. > The kernel part is somewhat harder to find, but it's at [2]. This is for historical reasons... I've now moved the kernel part to http://git.osmocom.org/osmo-gtp-kernel/ and the 'osmocom developers with commit access' can now push to it via git://gitosis at git.osmocom.org:osmo-gtp-kernel.git > It seems that both sides are at 70% completion and only somewhat working. I would have expected a higher percentage, but then indeed it is true, the project got halted / postponed at the time due to changing customer requirements, as far as I remember > I have played with the kernel module, changed a couple things and would > like to get some feedback on my changes. > > It can be found at: https://github.com/RoadRunnr/osmo-ggsn I think it would be best (and customary practise) to send your changes to this list (using git format-patch / send-email) for review. After a brief initial review it looks fine to me, but Pablo is clearly the better judge of that. One thing I seem to notice immediaately at a brief look is that it appears often 8 spaces are used instead of tab for indentation. I know it's picky, but that has to be adressed before any mainline merge attempt :/ I think you mentioned last week that you still had some issues with module unloading ? It would be good to share any remaining problems, maybe somebody has some idea/input on what is causing the problem. Please also feel free to add yourself to the list of Copyright holders in the file headers, so we have proper documentation of that before submission. Regards, Harald -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From aschultz at tpip.net Tue Oct 27 09:13:58 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Tue, 27 Oct 2015 10:13:58 +0100 Subject: [RFC] GTP-U v0/v1 kernel module In-Reply-To: <20151027073635.GI2056@nataraja> References: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> <20151027073635.GI2056@nataraja> Message-ID: <562F4056.30502@tpip.net> On 10/27/2015 08:36 AM, Harald Welte wrote: > Hi Andreas, > > good to seee you on the mailing list, and thanks for sharing your work. > > On Mon, Oct 26, 2015 at 06:14:19PM +0100, Andreas Schultz wrote: >> Some time ago, Pablo Neira Ayuso wrote a GTP-U kernel module and OpenGGSN >> support for it. The OpenGGSN side is easily available in the osmocom git [1]. >> The kernel part is somewhat harder to find, but it's at [2]. > > This is for historical reasons... I've now moved the kernel part to > http://git.osmocom.org/osmo-gtp-kernel/ > and the 'osmocom developers with commit access' can now push to it via > git://gitosis at git.osmocom.org:osmo-gtp-kernel.git Great, thanks. >> It seems that both sides are at 70% completion and only somewhat working. > > I would have expected a higher percentage, but then indeed it is true, > the project got halted / postponed at the time due to changing customer > requirements, as far as I remember The number was just a guestimate, but the existing code was definitely a great starting point. >> I have played with the kernel module, changed a couple things and would >> like to get some feedback on my changes. >> >> It can be found at: https://github.com/RoadRunnr/osmo-ggsn > > I think it would be best (and customary practise) to send your changes > to this list (using git format-patch / send-email) for review. Will do, but I think I will have to rework the changesets a bit. There are a few intermediate commits that can probably be squashed and others that might have to be split. > After a brief initial review it looks fine to me, but Pablo is clearly > the better judge of that. > > One thing I seem to notice immediaately at a brief look is that it > appears often 8 spaces are used instead of tab for indentation. I know > it's picky, but that has to be adressed before any mainline merge > attempt :/ Oops, bad editor settings combined with cut&paste ;-) > I think you mentioned last week that you still had some issues with > module unloading ? It would be good to share any remaining problems, > maybe somebody has some idea/input on what is causing the problem. I've found that, it's fixed in the last commit. The problem was actually the error handling when the creation of the gtp interface failed. > Please also feel free to add yourself to the list of Copyright holders > in the file headers, so we have proper documentation of that before > submission. Will do. Andreas > > Regards, > Harald > From nhofmeyr at sysmocom.de Tue Oct 27 14:03:13 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 27 Oct 2015 15:03:13 +0100 Subject: openggsn: gtpie.h Message-ID: <20151027140313.GA1810@dub5> Hi all, though promising GTP implementations are emerging from the shadows, current GTP Hub development is still using OpenGGSN's kludgy GTP API. I'd love to switch, but it's not the time for that yet. To be able to query and manipulate IEs in the OpenGGSN way, I've taken the liberty to commit below patch on openggsn.git/master, which publishes gtpie.h. ~Neels commit 6c06d25667f7c46e179bfd1121c512234c98649f Author: Neels Hofmeyr Date: Tue Oct 27 14:57:18 2015 +0100 make install: also install gtpie.h diff --git a/gtp/Makefile.am b/gtp/Makefile.am index 4ad9f65..9586dfe 100644 --- a/gtp/Makefile.am +++ b/gtp/Makefile.am @@ -1,6 +1,6 @@ lib_LTLIBRARIES = libgtp.la -include_HEADERS = gtp.h pdp.h +include_HEADERS = gtp.h pdp.h gtpie.h AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Tue Oct 27 15:19:07 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Tue, 27 Oct 2015 16:19:07 +0100 Subject: GTP ports and IP addresses Message-ID: <20151027151907.GB1810@dub5> Hi all, a remark / question about GTP, in the context of writing code for gtphub... So far I've tried to keep the GTP IP addresses and ports config general -- you never know what weird things one might want to do some day (different IP addresses for User and Control? Nonstandard port numbers?). But now I'm at the point where I've got a Control plane message from a "control peer", and need to figure out the matching peer on the User plane. How do I do that? By IP address, of course. Thus it struck me that GTP *depends* on a setup where the User IP address is identical to the IP of the sender of the Ctrl plane packet. (view with a monospaced font) SGSN GGSN (or gtphub) 1.2.3.4 5.6.7.8 Ctrl: 2123 <-------> 2123 User: 2152 <-------> 2152 So trying to stay general with IP addresses is an exercise in futility, because it plainly doesn't work for GTP: I can't match up a peer's two message planes unless the above standard is given. Thinking of a nonstandard situation: GGSN (or gtphub) SGSN 5.6.7.8 Ctrl: 1.2.3.4:111 <-------> 2123 User: 4.3.2.1:222 X-------> 2152 The GGSN can record that there's a Ctrl peer at 1.2.3.4:111, from the incoming GTP packet's sender address. Say it receives a Create PDP Context Request, in which the nonstandard SGSN sends two TEIs it wants to use, on the Ctrl *and* User plane. Now, the GGSN cannot possibly know that 4.3.2.1 is the User plane peer for which the TEI from the Create PDP Ctx Req should be valid. One may think that the SGSN can just contact the GGSN from 4.3.2.1:222 and send the TEI from the Create PDP, so the GGSN could know that it's the same peer. But in fact a TEI is scoped *within* a comm plane with a peer, meaning that any other peer could choose the exact same TEI at any point, and the means to disambiguate is the peer's IP address. So my wishful thinking to stay general there is thwarted by design. The Ctrl and User IP addresses must be identical. Still, the SGSN's port numbers could theoretically be chosen freely. The GGSN knows the sender of the Ctrl packet(s), and as soon as a User packet comes in from the same IP address, it also knows the User plane port. As long as the IP address is the same and there are no other SGSNs using different ports on the same IP address, the GGSN could figure out both nonstandard Ctrl and User ports like this. BTW, we've also thought about securing the GTP wire towards gtphub with some kind of authentication (future). With identification sent on both planes, the limitations discussed here would be void... So I'll actually keep gtphub's config as general as it is, but will not invest time, neither in implications of choosing nonstandard setups, nor in prohibiting them (yet). The nonstandard ports config capability actually comes in handy for unit testing, where I can place some netcats and a gtphub on arbitrary port numbers on the same IP address. (Since implicit creation of 127.0.0.N interfaces is linux specific, using several local addresses without root privilege is not portable). If you spot any thinkos there, please let me know :) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From aschultz at tpip.net Tue Oct 27 15:50:37 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Tue, 27 Oct 2015 16:50:37 +0100 Subject: GTP ports and IP addresses In-Reply-To: <20151027151907.GB1810@dub5> References: <20151027151907.GB1810@dub5> Message-ID: <562F9D4D.8030208@tpip.net> Hi Neels, I'm quite new to the GTP game, so take my comments with a grain of salt. More inline... On 10/27/2015 04:19 PM, Neels Hofmeyr wrote: > Hi all, > > a remark / question about GTP, in the context of writing code for > gtphub... > > So far I've tried to keep the GTP IP addresses and ports config general -- > you never know what weird things one might want to do some day (different > IP addresses for User and Control? Nonstandard port numbers?). > > But now I'm at the point where I've got a Control plane message from a > "control peer", and need to figure out the matching peer on the User > plane. How do I do that? By IP address, of course. > > Thus it struck me that GTP *depends* on a setup where the User IP address > is identical to the IP of the sender of the Ctrl plane packet. I don't think so. In 3GPP TS 29.060 version 12.9.0, the table of information elements for Create PDP Context Request does list SGSN Address for signalling AND SGSN Address for user traffic, both are mandatory. > (view with a monospaced font) > > SGSN GGSN (or gtphub) > 1.2.3.4 5.6.7.8 > Ctrl: 2123 <-------> 2123 > User: 2152 <-------> 2152 > > So trying to stay general with IP addresses is an exercise in futility, > because it plainly doesn't work for GTP: I can't match up a peer's two > message planes unless the above standard is given. > > Thinking of a nonstandard situation: > > GGSN (or gtphub) > SGSN 5.6.7.8 > Ctrl: 1.2.3.4:111 <-------> 2123 > User: 4.3.2.1:222 X-------> 2152 You arrows imply bidirectional connection. The above wouldn't be allowed in that case. But something like would. 3GPP TS 29.281 version 12.1.0 does say this: Section 4.4.2.0 General: > For the messages described below, the UDP Source Port (except as specified > for the Echo Response message) may be > allocated either statically or > dynamically by the sending GTP-U entity. Section 4.4.2.2 Echo Response Message: > The UDP Destination Port value shall be the value of the UDP Source Port of > the corresponding request message. Section 4.4.2.3 Encapsulated T-PDUs: > The UDP Destination Port number shall be 2152. It is the registered port > number for GTP-U. This means the following situation is completely valid: GGSN (or gtphub) SGSN 5.6.7.8 Ctrl: 1.2.3.4:111 -------> 2123 1.2.3.4:2123 <------- 5678 User: 4.3.2.1:222 -------> 2152 4.3.2.1:2152 <------- 9012 > The GGSN can record that there's a Ctrl peer at 1.2.3.4:111, from the > incoming GTP packet's sender address. Say it receives a Create PDP Context > Request, in which the nonstandard SGSN sends two TEIs it wants to use, on > the Ctrl *and* User plane. Now, the GGSN cannot possibly know that 4.3.2.1 > is the User plane peer for which the TEI from the Create PDP Ctx Req > should be valid. As fas as I understand, the GGSN would get these IEs: * Tunnel Endpoint Identifier Control Plane + SGSN Address for user traffic * Tunnel Endpoint Identifier Data I + SGSN Address for signalling It would then reply with: * GGSN Address for Control Plane + Tunnel Endpoint Identifier Control Plane * GGSN Address for user traffic + Tunnel Endpoint Identifier Data I Together this should transport all the information required to match the tunnels. > One may think that the SGSN can just contact the GGSN > from 4.3.2.1:222 and send the TEI from the Create PDP, so the GGSN could > know that it's the same peer. But in fact a TEI is scoped *within* a comm > plane with a peer, meaning that any other peer could choose the exact same > TEI at any point, and the means to disambiguate is the peer's IP address. > > So my wishful thinking to stay general there is thwarted by design. The > Ctrl and User IP addresses must be identical. > > Still, the SGSN's port numbers could theoretically be chosen freely. The > GGSN knows the sender of the Ctrl packet(s), and as soon as a User packet > comes in from the same IP address, it also knows the User plane port. As As pointed out earlier, the ports are no bidirectional. It is mandatory that GTP-U receives at port 2152 and GTP-C v1 receives at 2123. The sending ports can be chosen freely. > long as the IP address is the same and there are no other SGSNs using > different ports on the same IP address, the GGSN could figure out both > nonstandard Ctrl and User ports like this. > > BTW, we've also thought about securing the GTP wire towards gtphub with > some kind of authentication (future). With identification sent on both > planes, the limitations discussed here would be void... IMHO, GTP (in 3GPP land) is not spoken over unsecured networks. So there is no need for security. > So I'll actually keep gtphub's config as general as it is, but will not > invest time, neither in implications of choosing nonstandard setups, nor > in prohibiting them (yet). > > The nonstandard ports config capability actually comes in handy for unit > testing, where I can place some netcats and a gtphub on arbitrary port > numbers on the same IP address. (Since implicit creation of 127.0.0.N > interfaces is linux specific, using several local addresses without root > privilege is not portable). > > If you spot any thinkos there, please let me know :) > > ~Neels Regards Andreas From laforge at gnumonks.org Tue Oct 27 19:10:31 2015 From: laforge at gnumonks.org (Harald Welte) Date: Tue, 27 Oct 2015 20:10:31 +0100 Subject: GTP ports and IP addresses In-Reply-To: <562F9D4D.8030208@tpip.net> References: <20151027151907.GB1810@dub5> <562F9D4D.8030208@tpip.net> Message-ID: <20151027191031.GA30193@nataraja> Hi Andreas, first of all thanks for your valid clarifications. On Tue, Oct 27, 2015 at 04:50:37PM +0100, Andreas Schultz wrote: > IMHO, GTP (in 3GPP land) is not spoken over unsecured networks. So there > is no need for security. That's what you think, and what _should_ be th case. Don't think that this is the reality, though. Same is true for SIGTRAN :/ -- - Harald Welte http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6) From pablo at gnumonks.org Wed Oct 28 03:40:48 2015 From: pablo at gnumonks.org (Pablo Neira Ayuso) Date: Wed, 28 Oct 2015 04:40:48 +0100 Subject: [RFC] GTP-U v0/v1 kernel module In-Reply-To: <562F4056.30502@tpip.net> References: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> <20151027073635.GI2056@nataraja> <562F4056.30502@tpip.net> Message-ID: <20151028034048.GA22140@salvia> On Tue, Oct 27, 2015 at 10:13:58AM +0100, Andreas Schultz wrote: > On 10/27/2015 08:36 AM, Harald Welte wrote: [...] > >I think it would be best (and customary practise) to send your changes > >to this list (using git format-patch / send-email) for review. > > Will do, but I think I will have to rework the changesets a bit. There > are a few intermediate commits that can probably be squashed and others > that might have to be split. This is a fairly large changeset (20 patches), I'd suggest you start with bugfixes in first place. The patches are lacking also descriptions, they are important. Try to send a small batch to start with, to avoid a small patchbomb thing ;-) The update to port this on top of iptunnel is fairly large, I would expect that. I wonder if you can find a good way to split this in logic changes to make the review easier. Thanks. From nhofmeyr at sysmocom.de Wed Oct 28 13:38:04 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 28 Oct 2015 14:38:04 +0100 Subject: GTP ports and IP addresses In-Reply-To: <562F9D4D.8030208@tpip.net> References: <20151027151907.GB1810@dub5> <562F9D4D.8030208@tpip.net> Message-ID: <20151028133804.GA1306@dub5> On Tue, Oct 27, 2015 at 04:50:37PM +0100, Andreas Schultz wrote: > In 3GPP TS 29.060 version 12.9.0, the table of information elements for > Create PDP Context Request does list SGSN Address for signalling AND > SGSN Address for user traffic, both are mandatory. Wow, how did I not see that! Thanks! Still learning my ways around GTP... > Section 4.4.2.0 General: > > For the messages described below, the UDP Source Port (except as specified > > for the Echo Response message) may be > allocated either statically or > > dynamically by the sending GTP-U entity. > Section 4.4.2.3 Encapsulated T-PDUs: > > The UDP Destination Port number shall be 2152. It is the registered port > > number for GTP-U. > This means the following situation is completely valid: > > GGSN (or gtphub) > SGSN 5.6.7.8 > Ctrl: 1.2.3.4:111 -------> 2123 > 1.2.3.4:2123 <------- 5678 > > User: 4.3.2.1:222 -------> 2152 > 4.3.2.1:2152 <------- 9012 So SGSN and GGSN can pick any IP addresses independently for the two planes, and they can *send from* any port they choose; but they must always *listen* on precisely ports 2123 and 2152. Meaning that even if gtphub received something from port 111 or 222, it must discard that port information and reply on either 2123 or 2152. Hyyypothetically, the GGSN could choose to reply to the port it received from (111 or 222), which it actually does for Echos, but otherwise, that's not how GTP do. > As fas as I understand, the GGSN would get these IEs: > > * Tunnel Endpoint Identifier Control Plane + SGSN Address for user traffic > * Tunnel Endpoint Identifier Data I + SGSN Address for signalling > > It would then reply with: > > * GGSN Address for Control Plane + Tunnel Endpoint Identifier Control Plane > * GGSN Address for user traffic + Tunnel Endpoint Identifier Data I > > Together this should transport all the information required to match > the tunnels. Well, indeed... I see it now :) > >Still, the SGSN's port numbers could theoretically be chosen freely. The > >GGSN knows the sender of the Ctrl packet(s), and as soon as a User packet > >comes in from the same IP address, it also knows the User plane port. As > > As pointed out earlier, the ports are no bidirectional. It is mandatory that > GTP-U receives at port 2152 and GTP-C v1 receives at 2123. The sending ports > can be chosen freely. Indeed. Thanks a lot for clarifying this! In pratice that means I simply cannot simulate several GSNs on the same IP address, because each wants to hog ports 2123 and 2152... Even if the secondary GSNs are just netcats, the first GSN would send to itself. To enable a test setup like this, I would need some non-standard config option, but that would compromise the meaning of the test. Well then. Which brings us back to OpenGGSN: it doesn't heed these specs! OpenGGSN always does reply back to where things came from. When I configure gtphub to listen on and also send GTP-C from port 2222, OpenGGSN happily plays along and replies GTP-C to port 2222. I *can* have gtphub and OpenGGSN on the same IP address, just tested that it works. So anyone using OpenGGSN probably uses ports 2123 and 2152 merely by incidence, because the SGSN side happens to send from these ports, too. If an SGSN picked a separate sending port, OpenGGSN would stop working. I presume that's a fail on OpenGGSN's side, not a choice, right? And this shows that users up to now don't seem to pick separate sending ports, kind of making the use of exactly the ports 2123 and 2152 for both sending and receiving a de facto standard...? Thanks again! ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From nhofmeyr at sysmocom.de Wed Oct 28 13:59:10 2015 From: nhofmeyr at sysmocom.de (Neels Hofmeyr) Date: Wed, 28 Oct 2015 14:59:10 +0100 Subject: [RFC] GTP-U v0/v1 kernel module In-Reply-To: <20151028034048.GA22140@salvia> References: <1906952785.699576.1445879659327.JavaMail.zimbra@tpip.net> <20151027073635.GI2056@nataraja> <562F4056.30502@tpip.net> <20151028034048.GA22140@salvia> Message-ID: <20151028135910.GB1306@dub5> On Wed, Oct 28, 2015 at 04:40:48AM +0100, Pablo Neira Ayuso wrote: > Try to send a small batch to start with, to avoid a small patchbomb > thing ;-) *cough* like my patch bombs... But, in fact, I would personally prefer to read a large number of small neat patches than a small number of large convoluted patches. So me, I'm basically all for patch bombs (presuming sufficiently detailed commit log messages). They are rather easy to skip in the mail inbox and allow for easier review. It can pay off to invest "too much" time in restructuring/splitting patches, allowing N people to save time reading them. My occasional tiny cosmetic patches are split off for this reason alone. > I wonder if you can find a good way to split this in logic changes to > make the review easier. There, you said it ;) But, please do let me know if I should refrain from sending patch bombs... (My current work being sponsored does produce a lot of patches, and once Holger is done reviewing the last one, there's a lot more to come.) ~Neels -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: Digital signature URL: From aschultz at tpip.net Thu Oct 29 11:39:00 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:39:00 +0100 Subject: [PATCH 4/6] gtp: update for Linux > 4.1+, __ip_select_ident arguments have changed In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-5-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gtp.c b/gtp.c index 6eb1178..0d1b5ee 100644 --- a/gtp.c +++ b/gtp.c @@ -616,7 +616,7 @@ gtp_push_ip4hdr(struct sk_buff *skb, struct gtp_pktinfo *pktinfo) iph->daddr = pktinfo->fl4.daddr; iph->saddr = pktinfo->fl4.saddr; iph->ttl = ip4_dst_hoplimit(&pktinfo->rt->dst); - __ip_select_ident(iph, &pktinfo->rt->dst, + __ip_select_ident(dev_net(pktinfo->rt->dst.dev), iph, (skb_shinfo(skb)->gso_segs ?: 1) - 1); netdev_dbg(pktinfo->dev, "gtp -> IP src: %pI4 dst: %pI4\n", -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:38:58 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:38:58 +0100 Subject: [PATCH 2/6] gtp: remove genl_ops compat ifdef for Linux < 3.13 In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-3-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gtp.c b/gtp.c index 61db1c3..6eb1178 100644 --- a/gtp.c +++ b/gtp.c @@ -1291,11 +1291,7 @@ static struct nla_policy gtp_genl_policy[GTPA_MAX + 1] = { [GTPA_FLOW] = { .type = NLA_U16, }, }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) static const struct genl_ops gtp_genl_ops[] = { -#else -static struct genl_ops gtp_genl_ops[] = { -#endif { .cmd = GTP_CMD_TUNNEL_NEW, .doit = gtp_genl_tunnel_new, -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:38:56 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:38:56 +0100 Subject: [PATCH 0/6] gtp: compat and build updates Message-ID: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Hi, This is the first series of my gtp kernel updates. It contains mostly the removal of Linux version ifdefs. After this the module builds only on 4.3+. The goal here is the preparation for main line inclusion. The other small change is a update to the Makefile for simpler out-of-tree build Andreas -- Andreas Schultz (6): build: update Makefile for simpler out of tree builds gtp: remove genl_ops compat ifdef for Linux < 3.13 gtp: remove per cpu stats compat ifdef for Linux < 3.13 gtp: update for Linux > 4.1+, __ip_select_ident arguments have changed gtp: update for Linux > 4.1+, genlmsg_end return should be ignored gtp: update for Linux > 4.2+, set NO_QUEUE flag on gtp device Makefile | 17 ++++++++++++----- gtp.c | 11 +++++------ gtp.h | 4 ---- 3 files changed, 17 insertions(+), 15 deletions(-) -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:39:02 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:39:02 +0100 Subject: [PATCH 6/6] gtp: update for Linux > 4.2+, set NO_QUEUE flag on gtp device In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-7-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gtp.c b/gtp.c index 7fa9c38..7c72eb0 100644 --- a/gtp.c +++ b/gtp.c @@ -718,6 +718,8 @@ static const struct net_device_ops gtp_netdev_ops = { static void gtp_link_setup(struct net_device *dev) { + dev->priv_flags |= IFF_NO_QUEUE; + dev->netdev_ops = >p_netdev_ops; dev->destructor = free_netdev; } -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:38:57 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:38:57 +0100 Subject: [PATCH 1/6] build: update Makefile for simpler out of tree builds In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-2-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- Makefile | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 9081679..2b3b4f5 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,16 @@ -CC=gcc -KDIR := /lib/modules/$(shell uname -r)/build +KERNEL_SRC := /lib/modules/$(shell uname -r)/build obj-m += gtp.o -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules +SRC := $(shell pwd) + +all: + $(MAKE) -C $(KERNEL_SRC) M=$(SRC) + +modules_install: + $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install + clean: - rm -rf *.o *.mod.* modules.order Module.symvers *.ko .tmp_versions .*.cmd + rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c + rm -f Module.markers Module.symvers modules.order + rm -rf .tmp_versions Modules.symvers -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:38:59 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:38:59 +0100 Subject: [PATCH 3/6] gtp: remove per cpu stats compat ifdef for Linux < 3.13 In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-4-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gtp.h b/gtp.h index 8422875..5f8d8a2 100644 --- a/gtp.h +++ b/gtp.h @@ -10,10 +10,6 @@ #define UDP_ENCAP_GTP1U 5 #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) -#define pcpu_sw_netstats pcpu_tstats -#endif - /* general GTP protocol related definitions */ #define GTP0_PORT 3386 -- 2.5.0 From aschultz at tpip.net Thu Oct 29 11:39:01 2015 From: aschultz at tpip.net (Andreas Schultz) Date: Thu, 29 Oct 2015 12:39:01 +0100 Subject: [PATCH 5/6] gtp: update for Linux > 4.1+, genlmsg_end return should be ignored In-Reply-To: <1446118742-22809-1-git-send-email-aschultz@tpip.net> References: <1446118742-22809-1-git-send-email-aschultz@tpip.net> Message-ID: <1446118742-22809-6-git-send-email-aschultz@tpip.net> Signed-off-by: Andreas Schultz --- gtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gtp.c b/gtp.c index 0d1b5ee..7fa9c38 100644 --- a/gtp.c +++ b/gtp.c @@ -1153,7 +1153,8 @@ gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq, nla_put_u16(skb, GTPA_FLOW, pctx->flow))) goto nla_put_failure; - return genlmsg_end(skb, genlh); + genlmsg_end(skb, genlh); + return 0; nlmsg_failure: nla_put_failure: -- 2.5.0 From se at connecto.tv Thu Oct 1 18:05:41 2015 From: se at connecto.tv (Sergey V. Efimov) Date: Thu, 01 Oct 2015 18:05:41 -0000 Subject: Help needed with BS11 Message-ID: Hello, One of our BS-11 stations began to behave strangely. I see the following messages during boot-up: PHASE: 1 Load SMU Intended Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: No Load MBCCU1: No Load Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: No Load Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: Load BTSCAC Abis-link: Down PHASE: 2 Load MBCCU MBCCU0: Load BTSCAC MBCCU1: No Load Abis-link: Down It looks like BS tries to load firmware on MBCCU1 and then gives up. I tried to delete and re-create trx1 objects using bs11_config, no result. Tried to reflash BS11, but got software load NACK, and when using ?force option the software download process finishes but the boot-up message is the same as above. Does it mean that TRX1 is failed and cannot be used no more? Best Regards, Sergey. -------------- next part -------------- An HTML attachment was scrubbed... URL: From royal_angel2009 at hotmail.com Tue Oct 13 10:18:07 2015 From: royal_angel2009 at hotmail.com (Rehab Khan) Date: Tue, 13 Oct 2015 10:18:07 -0000 Subject: Osmo-BTS-trx compilation Error Message-ID: Hello list, I have compiled OpenBSC stack following the link http://openbsc.osmocom.org/trac/wiki/network_from_scratch. Everything has been compiled and configured smoothly except osmo-bts.For installing osmo-bts,i git cloned master branch from https://github.com/osmocom/osmo-bts. Following the link, i did configure --enable-trx and when make osmo-bts, i am getting the following error: l1_if.c: In function ?bts_model_l1sap_down?: l1_if.c:552:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:553:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:554:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:555:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:580:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:581:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:582:23: error: ?struct amr_multirate_conf? has no member named ?mode? l1_if.c:583:23: error: ?struct amr_multirate_conf? has no member named ?mode? make: *** [l1_if.o] Error 1 I have tried it with the change branch: jolly/trx and also tried to make osmo-bts-trx in the src directory of osmo-bts but same error persisits. Any help in this regard will be a worth. Thanks Best Regards -------------- next part -------------- An HTML attachment was scrubbed... URL: From royal_angel2009 at hotmail.com Wed Oct 21 06:57:14 2015 From: royal_angel2009 at hotmail.com (Rehab Khan) Date: Wed, 21 Oct 2015 06:57:14 -0000 Subject: osmo-nitb initialzing_error Message-ID: Hey all, I am having some trouble in initializing osmo-nitb. When i run osmo-nitb -c /etc/osmocom.openbsc.cfg -l /etc/osmocom.openbsc.cfg P -C --debug=DRLL:DCC:DMM:DRR:DRSL:DNMi am receiving an error DB: Failed to create connection. DB: Failed to init database. Please check the option settings. Can anyone please guide me how to proceed?? I have checked all the drivers required initialze database as per suggested in http://openbsc.osmocom.org/trac/wiki/osmo-nitb Still the issue is consistent. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dwillmann at sysmocom.de Mon Oct 12 17:32:19 2015 From: dwillmann at sysmocom.de (Daniel Willmann) Date: Mon, 12 Oct 2015 17:32:19 -0000 Subject: [openbsc 2/4] gprs: Use RAND_bytes for p-tmsi In-Reply-To: <04EC40DF-796E-4BF1-88D2-634CBA9E4CF5@freyther.de> (sfid-20151012_095951_332297_7F30C20A) References: <04EC40DF-796E-4BF1-88D2-634CBA9E4CF5@freyther.de> (sfid-20151012_095951_332297_7F30C20A) Message-ID: <1444671079.1667.5.camel@sysmocom.de> On Mon, 2015-10-12 at 09:59 +0200, Holger Freyther wrote: > > On 08 Oct 2015, at 16:10, Daniel Willmann wrote: > > > > From: Daniel Willmann > > > * missing include for the RAND_bytes prototype > * missing cat of ptmsi > * missing linking to LIBCRYPTO_LIBS > * missing linking to LIBCRYPTO_LIBS in the test > and after that.. the sgsn tests fail because of the TMSI situation. I have now > reverted the code. Please look at it with Jacob and extract the TMSI from the > SGSN state instead of resetting the RNG in the test. ...sorry, it seems that it never even executed the test on my new system due to missing libgtp. I'll send another patchset which solves this issue (and does the same for gbproxy). Daniel -- - Daniel Willmann http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Alt-Moabit 93 * 10559 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte