aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/jenkins.sh57
-rw-r--r--openbsc/.gitignore4
-rw-r--r--openbsc/contrib/nat/ussd_example.py65
-rw-r--r--openbsc/doc/examples/osmo-bsc_nat/bscs.config13
-rw-r--r--openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg8
-rw-r--r--openbsc/include/openbsc/Makefile.am4
-rw-r--r--openbsc/include/openbsc/abis_rsl.h1
-rw-r--r--openbsc/include/openbsc/bsc_nat.h13
-rw-r--r--openbsc/include/openbsc/gprs_gsup_messages.h119
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h7
-rw-r--r--openbsc/include/openbsc/gprs_utils.h11
-rw-r--r--openbsc/include/openbsc/gsm_04_08_gprs.h397
-rw-r--r--openbsc/include/openbsc/gsm_data.h5
-rw-r--r--openbsc/include/openbsc/gsm_data_shared.h7
-rw-r--r--openbsc/include/openbsc/gsm_subscriber.h7
-rw-r--r--openbsc/include/openbsc/ipaccess.h3
-rw-r--r--openbsc/include/openbsc/oap.h4
-rw-r--r--openbsc/include/openbsc/oap_messages.h16
-rw-r--r--openbsc/include/openbsc/rest_octets.h10
-rw-r--r--openbsc/include/openbsc/system_information.h10
-rw-r--r--openbsc/include/openbsc/utils.h26
-rw-r--r--openbsc/src/gprs/Makefile.am2
-rw-r--r--openbsc/src/gprs/gb_proxy.c2
-rw-r--r--openbsc/src/gprs/gb_proxy_patch.c1
-rw-r--r--openbsc/src/gprs/gb_proxy_peer.c1
-rw-r--r--openbsc/src/gprs/gprs_gb_parse.c58
-rw-r--r--openbsc/src/gprs/gprs_gmm.c22
-rw-r--r--openbsc/src/gprs/gprs_gsup_messages.c419
-rw-r--r--openbsc/src/gprs/gprs_sgsn.c2
-rw-r--r--openbsc/src/gprs/gprs_subscriber.c131
-rw-r--r--openbsc/src/gprs/gprs_utils.c136
-rw-r--r--openbsc/src/gprs/gsm_04_08_gprs.c116
-rw-r--r--openbsc/src/gprs/gtphub.c10
-rw-r--r--openbsc/src/gprs/gtphub_ares.c2
-rw-r--r--openbsc/src/gprs/oap.c43
-rw-r--r--openbsc/src/gprs/oap_messages.c20
-rw-r--r--openbsc/src/gprs/sgsn_auth.c3
-rw-r--r--openbsc/src/gprs/sgsn_libgtp.c2
-rw-r--r--openbsc/src/gprs/sgsn_vty.c14
-rw-r--r--openbsc/src/libbsc/abis_nm.c2
-rw-r--r--openbsc/src/libbsc/abis_rsl.c2
-rw-r--r--openbsc/src/libbsc/bsc_api.c6
-rw-r--r--openbsc/src/libbsc/bsc_ctrl_commands.c12
-rw-r--r--openbsc/src/libbsc/bsc_init.c10
-rw-r--r--openbsc/src/libbsc/bsc_vty.c172
-rw-r--r--openbsc/src/libbsc/gsm_04_08_utils.c15
-rw-r--r--openbsc/src/libbsc/rest_octets.c263
-rw-r--r--openbsc/src/libbsc/system_information.c222
-rw-r--r--openbsc/src/libcommon/Makefile.am2
-rw-r--r--openbsc/src/libcommon/gsm_data.c5
-rw-r--r--openbsc/src/libcommon/gsm_subscriber_base.c2
-rw-r--r--openbsc/src/libcommon/utils.c58
-rw-r--r--openbsc/src/libiu/iu.c8
-rw-r--r--openbsc/src/libmsc/auth.c8
-rw-r--r--openbsc/src/libmsc/ctrl_commands.c62
-rw-r--r--openbsc/src/libmsc/db.c40
-rw-r--r--openbsc/src/libmsc/gsm_04_08.c87
-rw-r--r--openbsc/src/libmsc/mncc_builtin.c3
-rw-r--r--openbsc/src/libmsc/vty_interface_layer3.c22
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c13
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_utils.c7
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_vty.c98
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_ussd.c2
-rw-r--r--openbsc/src/osmo-cscn/cscn_main.c2
-rw-r--r--openbsc/tests/bsc-nat/bsc_nat_test.c14
-rw-r--r--openbsc/tests/ctrl_test_runner.py27
-rw-r--r--openbsc/tests/db/db_test.c6
-rw-r--r--openbsc/tests/gbproxy/gbproxy_test.c3
-rw-r--r--openbsc/tests/gprs/Makefile.am4
-rw-r--r--openbsc/tests/gprs/gprs_test.c480
-rw-r--r--openbsc/tests/gprs/gprs_test.ok14
-rw-r--r--openbsc/tests/gsm0408/Makefile.am3
-rw-r--r--openbsc/tests/gsm0408/gsm0408_test.c128
-rw-r--r--openbsc/tests/gsm0408/gsm0408_test.ok21
-rw-r--r--openbsc/tests/gtphub/gtphub_test.c2
-rw-r--r--openbsc/tests/mm_auth/mm_auth_test.c6
-rw-r--r--openbsc/tests/oap/Makefile.am1
-rw-r--r--openbsc/tests/oap/oap_test.c9
-rw-r--r--openbsc/tests/sgsn/Makefile.am1
-rw-r--r--openbsc/tests/sgsn/sgsn_test.c25
-rw-r--r--openbsc/tests/vty_test_runner.py225
81 files changed, 1735 insertions, 2128 deletions
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
new file mode 100755
index 000000000..bde117c06
--- /dev/null
+++ b/contrib/jenkins.sh
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+
+set -ex
+
+rm -rf deps/install
+mkdir deps || true
+export LD_LIBRARY_PATH=$PWD/deps/install/lib
+cd deps
+osmo-deps.sh libosmocore
+
+cd libosmocore
+autoreconf --install --force
+./configure --prefix=$PWD/../install
+$MAKE $PARALLEL_MAKE install
+
+
+cd ../
+osmo-deps.sh libosmo-abis
+cd libosmo-abis
+autoreconf --install --force
+PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install
+PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install
+
+cd ../
+osmo-deps.sh libosmo-netif
+cd libosmo-netif
+autoreconf --install --force
+PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install
+PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install
+
+cd ../
+osmo-deps.sh libosmo-sccp
+cd libosmo-sccp
+autoreconf --install --force
+PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install
+PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install
+
+cd ../
+osmo-deps.sh libsmpp34
+cd libsmpp34
+autoreconf --install --force
+./configure --prefix=$PWD/../install
+$MAKE install
+
+cd ../
+osmo-deps.sh openggsn
+cd openggsn
+autoreconf --install --force
+PKG_CONFIG_PATH=$PWD/../install/lib/pkgconfig ./configure --prefix=$PWD/../install
+PKG_CONFIG_PATH=$PWD/..//install/lib/pkgconfig $MAKE $PARALLEL_MAKE install
+
+cd ../../openbsc
+autoreconf --install --force
+PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig ./configure --enable-osmo-bsc --enable-nat $SMPP $MGCP --enable-vty-tests --enable-external-tests
+PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig $MAKE $PARALLEL_MAKE
+PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig LD_LIBRARY_PATH=$PWD/../deps/install/lib $MAKE check
+PKG_CONFIG_PATH=$PWD/../deps/install/lib/pkgconfig LD_LIBRARY_PATH=$PWD/../deps/install/lib $MAKE distcheck
diff --git a/openbsc/.gitignore b/openbsc/.gitignore
index d4c08d0fe..a3259681d 100644
--- a/openbsc/.gitignore
+++ b/openbsc/.gitignore
@@ -89,6 +89,6 @@ tests/package.m4
tests/testsuite
tests/testsuite.log
-writtenconfig
-
src/openbsc.cfg*
+writtenconfig/
+gtphub_restart_count
diff --git a/openbsc/contrib/nat/ussd_example.py b/openbsc/contrib/nat/ussd_example.py
new file mode 100644
index 000000000..8f7a58d3f
--- /dev/null
+++ b/openbsc/contrib/nat/ussd_example.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python2.7
+
+"""
+AGPLv3+ 2016 Copyright Holger Hans Peter Freyther
+
+Example of how to connect to the USSD side-channel and how to respond
+with a fixed message.
+"""
+
+import socket
+import struct
+
+ussdSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ussdSocket.connect(('127.0.0.1', 5001))
+
+def send_dt1(dstref, data):
+ dlen = struct.pack('B', len(data)).encode('hex')
+ hex = '06' + dstref.encode('hex') + '00' + '01' + dlen + data.encode('hex')
+ pdata = hex.decode('hex')
+ out = struct.pack('>HB', len(pdata), 0xfd) + pdata
+ ussdSocket.send(out)
+
+def send_rel(srcref, dstref):
+ hex = '04' + dstref.encode('hex') + srcref.encode('hex') + '000100'
+ pdata = hex.decode('hex')
+ out = struct.pack('>HB', len(pdata), 0xfd) + pdata
+ ussdSocket.send(out)
+
+def recv_one():
+ plen = ussdSocket.recv(3)
+ (plen,ptype) = struct.unpack(">HB", plen)
+ data = ussdSocket.recv(plen)
+
+ return ptype, data
+
+# Assume this is the ID request
+data = ussdSocket.recv(4)
+ussdSocket.send("\x00\x08\xfe\x05\x00" + "\x05\x01" + "ussd")
+# ^len ^len of tag ... and ignore
+
+# Expect a fake message. see struct ipac_msgt_sccp_state
+ptype, data = recv_one()
+print("%d %s" % (ptype, data.encode('hex')))
+(srcref, dstref, transid, invokeid) = struct.unpack("<3s3sBB", data[1:9])
+print("New transID %d invoke %d" % (transid, invokeid))
+
+# Expect a the invocation.. todo.. extract invoke id
+ptype, data = recv_one()
+print("%d %s" % (ptype, data.encode('hex')))
+
+# Reply with BSSAP + GSM 04.08 + MAP portion
+# 00 == invoke id 0f == DCS
+res = "01002a9b2a0802e1901c22a220020100301b02013b301604010f041155e7d2f9bc3a41412894991c06a9c9a713"
+send_dt1(dstref, res.decode('hex'))
+
+clear = "000420040109"
+send_dt1(dstref, clear.decode('hex'))
+
+# should be the clear complete
+send_rel(srcref, dstref)
+
+# Give it some time to handle connection shutdown properly
+print("Gracefully sleeping")
+import time
+time.sleep(3)
diff --git a/openbsc/doc/examples/osmo-bsc_nat/bscs.config b/openbsc/doc/examples/osmo-bsc_nat/bscs.config
new file mode 100644
index 000000000..176debe42
--- /dev/null
+++ b/openbsc/doc/examples/osmo-bsc_nat/bscs.config
@@ -0,0 +1,13 @@
+nat
+ bsc 0
+ token lol
+ location_area_code 1234
+ description bsc
+ max-endpoints 32
+ paging forbidden 0
+ bsc 1
+ token wat
+ location_area_code 5678
+ description bsc
+ max-endpoints 32
+ paging forbidden 0
diff --git a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
index 737d10474..2e00bc2c3 100644
--- a/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
+++ b/openbsc/doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg
@@ -62,11 +62,5 @@ nat
timeout ping 20
timeout pong 5
ip-dscp 0
+ bscs-config-file bscs.config
access-list bla imsi-allow ^11$
-
- bsc 0
- token bla
- location_area_code 1234
- description bsc
- max-endpoints 32
- paging forbidden 0
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index 475e82771..efb22b209 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -14,8 +14,8 @@ 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 utils.h \
- gprs_gb_parse.h smpp.h meas_feed.h gprs_gsup_messages.h \
+ osmux.h mgcp_transcode.h gprs_utils.h \
+ gprs_gb_parse.h smpp.h meas_feed.h \
gprs_gsup_client.h bsc_msg_filter.h \
oap.h oap_messages.h \
gtphub.h \
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h
index b27595e4a..100a6d11f 100644
--- a/openbsc/include/openbsc/abis_rsl.h
+++ b/openbsc/include/openbsc/abis_rsl.h
@@ -31,6 +31,7 @@ struct gsm_lchan;
struct gsm_subscriber;
struct gsm_bts_trx_ts;
+#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type,
const uint8_t *data, int len);
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 309adb1ba..94ab0e5ff 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -35,6 +35,7 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <regex.h>
+#include <stdbool.h>
#define DIR_BSC 1
#define DIR_MSC 2
@@ -164,6 +165,10 @@ struct bsc_config {
/* audio handling */
int max_endpoints;
+ /* used internally for reload handling */
+ bool remove;
+ bool token_updated;
+
/* backpointer */
struct bsc_nat *nat;
@@ -264,6 +269,11 @@ struct bsc_nat {
struct bsc_endpoint *bsc_endpoints;
+ /* path to file with BSC config */
+ char *include_file;
+ char *include_base;
+ char *resolved_path;
+
/* filter */
char *acc_lst_name;
@@ -320,7 +330,8 @@ struct bsc_nat_ussd_con {
};
/* create and init the structures */
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token);
+struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
+ unsigned int number);
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len);
void bsc_config_free(struct bsc_config *);
diff --git a/openbsc/include/openbsc/gprs_gsup_messages.h b/openbsc/include/openbsc/gprs_gsup_messages.h
deleted file mode 100644
index 8cbc809f7..000000000
--- a/openbsc/include/openbsc/gprs_gsup_messages.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* GPRS Subscriber Update Protocol message encoder/decoder */
-
-/* (C) 2014 by Sysmocom s.f.m.c. GmbH
- * All Rights Reserved
- *
- * Author: Jacob Erlbeck
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-#pragma once
-
-#include <stdint.h>
-#include <openbsc/gsm_04_08_gprs.h>
-#include <openbsc/gsm_data.h>
-/* Needed for GSM_IMSI_LENGTH: */
-#include <openbsc/gsm_subscriber.h>
-
-#define GPRS_GSUP_MAX_NUM_PDP_INFO 10 /* GSM 09.02 limits this to 50 */
-#define GPRS_GSUP_MAX_NUM_AUTH_INFO 5
-#define GPRS_GSUP_MAX_MSISDN_LEN 9
-
-#define GPRS_GSUP_PDP_TYPE_SIZE 2
-
-enum gprs_gsup_iei {
- GPRS_GSUP_IMSI_IE = 0x01,
- GPRS_GSUP_CAUSE_IE = 0x02,
- GPRS_GSUP_AUTH_TUPLE_IE = 0x03,
- GPRS_GSUP_PDP_INFO_COMPL_IE = 0x04,
- GPRS_GSUP_PDP_INFO_IE = 0x05,
- GPRS_GSUP_CANCEL_TYPE_IE = 0x06,
- GPRS_GSUP_FREEZE_PTMSI_IE = 0x07,
- GPRS_GSUP_MSISDN_IE = 0x08,
- GPRS_GSUP_HLR_NUMBER_IE = 0x09,
- GPRS_GSUP_PDP_CONTEXT_ID_IE = 0x10,
- GPRS_GSUP_PDP_TYPE_IE = 0x11,
- GPRS_GSUP_ACCESS_POINT_NAME_IE = 0x12,
- GPRS_GSUP_PDP_QOS_IE = 0x13,
- GPRS_GSUP_RAND_IE = 0x20,
- GPRS_GSUP_SRES_IE = 0x21,
- GPRS_GSUP_KC_IE = 0x22
-};
-
-enum gprs_gsup_message_type {
- GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST = 0b00000100,
- GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR = 0b00000101,
- GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT = 0b00000110,
-
- GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST = 0b00001000,
- GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR = 0b00001001,
- GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT = 0b00001010,
-
- GPRS_GSUP_MSGT_PURGE_MS_REQUEST = 0b00001100,
- GPRS_GSUP_MSGT_PURGE_MS_ERROR = 0b00001101,
- GPRS_GSUP_MSGT_PURGE_MS_RESULT = 0b00001110,
-
- GPRS_GSUP_MSGT_INSERT_DATA_REQUEST = 0b00010000,
- GPRS_GSUP_MSGT_INSERT_DATA_ERROR = 0b00010001,
- GPRS_GSUP_MSGT_INSERT_DATA_RESULT = 0b00010010,
-
- GPRS_GSUP_MSGT_DELETE_DATA_REQUEST = 0b00010100,
- GPRS_GSUP_MSGT_DELETE_DATA_ERROR = 0b00010101,
- GPRS_GSUP_MSGT_DELETE_DATA_RESULT = 0b00010110,
-
- GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST = 0b00011100,
- GPRS_GSUP_MSGT_LOCATION_CANCEL_ERROR = 0b00011101,
- GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT = 0b00011110,
-};
-
-#define GPRS_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00)
-#define GPRS_GSUP_IS_MSGT_ERROR(msgt) (((msgt) & 0b00000011) == 0b01)
-#define GPRS_GSUP_TO_MSGT_ERROR(msgt) (((msgt) & 0b11111100) | 0b01)
-
-enum gprs_gsup_cancel_type {
- GPRS_GSUP_CANCEL_TYPE_UPDATE = 1, /* on wire: 0 */
- GPRS_GSUP_CANCEL_TYPE_WITHDRAW = 2, /* on wire: 1 */
-};
-
-struct gprs_gsup_pdp_info {
- unsigned int context_id;
- int have_info;
- uint16_t pdp_type;
- const uint8_t *apn_enc;
- size_t apn_enc_len;
- const uint8_t *qos_enc;
- size_t qos_enc_len;
-};
-
-struct gprs_gsup_message {
- enum gprs_gsup_message_type message_type;
- char imsi[GSM_IMSI_LENGTH];
- enum gsm48_gmm_cause cause;
- enum gprs_gsup_cancel_type cancel_type;
- int pdp_info_compl;
- int freeze_ptmsi;
- struct gsm_auth_tuple auth_tuples[GPRS_GSUP_MAX_NUM_AUTH_INFO];
- size_t num_auth_tuples;
- struct gprs_gsup_pdp_info pdp_infos[GPRS_GSUP_MAX_NUM_PDP_INFO];
- size_t num_pdp_infos;
- const uint8_t *msisdn_enc;
- size_t msisdn_enc_len;
- const uint8_t *hlr_enc;
- size_t hlr_enc_len;
-};
-
-int gprs_gsup_decode(const uint8_t *data, size_t data_len,
- struct gprs_gsup_message *gsup_msg);
-void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg);
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 7dadfd214..28cbea5bd 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -9,11 +9,10 @@
#include <osmocom/gsm/gsm48.h>
#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <openbsc/gsm_data.h>
-#define GSM_IMSI_LENGTH 17
-#define GSM_IMEI_LENGTH 17
#define GSM_EXTENSION_LENGTH 15
#define GSM_APN_LENGTH 102
@@ -126,13 +125,13 @@ struct sgsn_mm_ctx {
enum sgsn_ran_type ran_type;
- char imsi[GSM_IMSI_LENGTH];
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
enum gprs_gmm_state mm_state;
enum gprs_pmm_state pmm_state;
uint32_t p_tmsi;
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
uint32_t p_tmsi_sig;
- char imei[GSM_IMEI_LENGTH];
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
/* Opt: Software Version Numbber / TS 23.195 */
char msisdn[GSM_EXTENSION_LENGTH];
struct gprs_ra_id ra;
diff --git a/openbsc/include/openbsc/gprs_utils.h b/openbsc/include/openbsc/gprs_utils.h
index 474eb45da..603605c7a 100644
--- a/openbsc/include/openbsc/gprs_utils.h
+++ b/openbsc/include/openbsc/gprs_utils.h
@@ -42,15 +42,4 @@ int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
-int gprs_shift_v_fixed(uint8_t **data, size_t *data_len,
- size_t len, uint8_t **value);
-int gprs_match_tv_fixed(uint8_t **data, size_t *data_len,
- uint8_t tag, size_t len, uint8_t **value);
-int gprs_shift_tlv(uint8_t **data, size_t *data_len,
- uint8_t *tag, uint8_t **value, size_t *value_len);
-int gprs_match_tlv(uint8_t **data, size_t *data_len,
- uint8_t tag, uint8_t **value, size_t *value_len);
-int gprs_shift_lv(uint8_t **data, size_t *data_len,
- uint8_t **value, size_t *value_len);
-
int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);
diff --git a/openbsc/include/openbsc/gsm_04_08_gprs.h b/openbsc/include/openbsc/gsm_04_08_gprs.h
index d122274ed..42b9a795e 100644
--- a/openbsc/include/openbsc/gsm_04_08_gprs.h
+++ b/openbsc/include/openbsc/gsm_04_08_gprs.h
@@ -1,403 +1,14 @@
-#ifndef _GSM48_GPRS_H
-#define _GSM48_GPRS_H
+#pragma once
-#include <stdint.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */
-#define GSM48_MT_GMM_ATTACH_REQ 0x01
-#define GSM48_MT_GMM_ATTACH_ACK 0x02
-#define GSM48_MT_GMM_ATTACH_COMPL 0x03
-#define GSM48_MT_GMM_ATTACH_REJ 0x04
-#define GSM48_MT_GMM_DETACH_REQ 0x05
-#define GSM48_MT_GMM_DETACH_ACK 0x06
-
-#define GSM48_MT_GMM_RA_UPD_REQ 0x08
-#define GSM48_MT_GMM_RA_UPD_ACK 0x09
-#define GSM48_MT_GMM_RA_UPD_COMPL 0x0a
-#define GSM48_MT_GMM_RA_UPD_REJ 0x0b
+/* TODO: Move this to osmocom/gsm/protocol/gsm_04_08_gprs.h ? */
/* Table 10.4 in 3GPP TS 24.008 (successor to 04.08) */
#define GSM48_MT_GMM_SERVICE_REQ 0x0c
#define GSM48_MT_GMM_SERVICE_ACK 0x0d
#define GSM48_MT_GMM_SERVICE_REJ 0x0e
-#define GSM48_MT_GMM_PTMSI_REALL_CMD 0x10
-#define GSM48_MT_GMM_PTMSI_REALL_COMPL 0x11
-#define GSM48_MT_GMM_AUTH_CIPH_REQ 0x12
-#define GSM48_MT_GMM_AUTH_CIPH_RESP 0x13
-#define GSM48_MT_GMM_AUTH_CIPH_REJ 0x14
-#define GSM48_MT_GMM_ID_REQ 0x15
-#define GSM48_MT_GMM_ID_RESP 0x16
-#define GSM48_MT_GMM_STATUS 0x20
-#define GSM48_MT_GMM_INFO 0x21
-
-/* Table 10.4a, GPRS Session Management (GSM) */
-#define GSM48_MT_GSM_ACT_PDP_REQ 0x41
-#define GSM48_MT_GSM_ACT_PDP_ACK 0x42
-#define GSM48_MT_GSM_ACT_PDP_REJ 0x43
-#define GSM48_MT_GSM_REQ_PDP_ACT 0x44
-#define GSM48_MT_GSM_REQ_PDP_ACT_REJ 0x45
-#define GSM48_MT_GSM_DEACT_PDP_REQ 0x46
-#define GSM48_MT_GSM_DEACT_PDP_ACK 0x47
-#define GSM48_MT_GSM_ACT_AA_PDP_REQ 0x50
-#define GSM48_MT_GSM_ACT_AA_PDP_ACK 0x51
-#define GSM48_MT_GSM_ACT_AA_PDP_REJ 0x52
-#define GSM48_MT_GSM_DEACT_AA_PDP_REQ 0x53
-#define GSM48_MT_GSM_DEACT_AA_PDP_ACK 0x54
-#define GSM48_MT_GSM_STATUS 0x55
-
-/* Chapter 10.5.5.2 / Table 10.5.135 */
-#define GPRS_ATT_T_ATTACH 1
-#define GPRS_ATT_T_ATT_WHILE_IMSI 2
-#define GPRS_ATT_T_COMBINED 3
-
-extern const struct value_string *gprs_att_t_strs;
-
-/* Chapter 10.5.5.5 / Table 10.5.138 */
-#define GPRS_DET_T_MO_GPRS 1
-#define GPRS_DET_T_MO_IMSI 2
-#define GPRS_DET_T_MO_COMBINED 3
-/* Network to MS direction */
-#define GPRS_DET_T_MT_REATT_REQ 1
-#define GPRS_DET_T_MT_REATT_NOTREQ 2
-#define GPRS_DET_T_MT_IMSI 3
-
-extern const struct value_string *gprs_det_t_mo_strs;
-extern const struct value_string *gprs_det_t_mt_strs;
-
-/* Chapter 10.5.5.18 / Table 105.150 */
-#define GPRS_UPD_T_RA 0
-#define GPRS_UPD_T_RA_LA 1
-#define GPRS_UPD_T_RA_LA_IMSI_ATT 2
-#define GPRS_UPD_T_PERIODIC 3
-
-extern const struct value_string *gprs_upd_t_strs;
-
-enum gsm48_gprs_ie_mm {
- GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */
- GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */
- GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */
- GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */
- GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */
- GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */
- GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */
- GSM48_IE_GMM_CAUSE = 0x25, /* 10.5.5.14 */
- GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */
- GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */
- GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */
- GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */
- GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */
-};
-
-enum gsm48_gprs_ie_sm {
- GSM48_IE_GSM_APN = 0x28, /* 10.5.6.1 */
- GSM48_IE_GSM_PROTO_CONF_OPT = 0x27, /* 10.5.6.3 */
- GSM48_IE_GSM_PDP_ADDR = 0x2b, /* 10.5.6.4 */
- GSM48_IE_GSM_AA_TMR = 0x29, /* 10.5.7.3 */
- GSM48_IE_GSM_NAME_FULL = 0x43, /* 10.5.3.5a */
- GSM48_IE_GSM_NAME_SHORT = 0x45, /* 10.5.3.5a */
- GSM48_IE_GSM_TIMEZONE = 0x46, /* 10.5.3.8 */
- GSM48_IE_GSM_UTC_AND_TZ = 0x47, /* 10.5.3.9 */
- GSM48_IE_GSM_LSA_ID = 0x48, /* 10.5.3.11 */
-
- /* Fake IEs that are not present on the Layer3 air interface,
- * but which we use to simplify internal APIs */
- OSMO_IE_GSM_REQ_QOS = 0xfd,
- OSMO_IE_GSM_REQ_PDP_ADDR = 0xfe,
- OSMO_IE_GSM_SUB_QOS = 0xff,
-};
-
-/* Chapter 9.4.15 / Table 9.4.15 */
-struct gsm48_ra_upd_ack {
- uint8_t force_stby:4, /* 10.5.5.7 */
- upd_result:4; /* 10.5.5.17 */
- uint8_t ra_upd_timer; /* 10.5.7.3 */
- struct gsm48_ra_id ra_id; /* 10.5.5.15 */
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 10.5.7.3 */
-enum gsm48_gprs_tmr_unit {
- GPRS_TMR_2SECONDS = 0 << 5,
- GPRS_TMR_MINUTE = 1 << 5,
- GPRS_TMR_6MINUTE = 2 << 5,
- GPRS_TMR_DEACTIVATED = 7 << 5,
-};
-
-#define GPRS_TMR_UNIT_MASK (7 << 5)
-#define GPRS_TMR_FACT_MASK ((1 << 5)-1)
-
-/* Chapter 9.4.2 / Table 9.4.2 */
-struct gsm48_attach_ack {
- uint8_t att_result:4, /* 10.5.5.7 */
- force_stby:4; /* 10.5.5.1 */
- uint8_t ra_upd_timer; /* 10.5.7.3 */
- uint8_t radio_prio; /* 10.5.7.2 */
- struct gsm48_ra_id ra_id; /* 10.5.5.15 */
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 9.4.9 / Table 9.4.9 */
-struct gsm48_auth_ciph_req {
- uint8_t ciph_alg:4, /* 10.5.5.3 */
- imeisv_req:4; /* 10.5.5.10 */
- uint8_t force_stby:4, /* 10.5.5.7 */
- ac_ref_nr:4; /* 10.5.5.19 */
- uint8_t data[0];
-} __attribute__((packed));
-/* optional: TV RAND, TV CKSN */
-
-struct gsm48_auth_ciph_resp {
- uint8_t ac_ref_nr:4,
- spare:4;
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 9.5.1 / Table 9.5.1 */
-struct gsm48_act_pdp_ctx_req {
- uint8_t req_nsapi;
- uint8_t req_llc_sapi;
- uint8_t data[0];
-} __attribute__((packed));
-
-/* Chapter 10.5.5.14 / Table 10.5.147 */
-enum gsm48_gmm_cause {
- GMM_CAUSE_IMSI_UNKNOWN = 0x02,
- GMM_CAUSE_ILLEGAL_MS = 0x03,
- GMM_CAUSE_ILLEGAL_ME = 0x06,
- GMM_CAUSE_GPRS_NOTALLOWED = 0x07,
- GMM_CAUSE_GPRS_OTHER_NOTALLOWED = 0x08,
- GMM_CAUSE_MS_ID_NOT_DERIVED = 0x09,
- GMM_CAUSE_IMPL_DETACHED = 0x0a,
- GMM_CAUSE_PLMN_NOTALLOWED = 0x0b,
- GMM_CAUSE_LA_NOTALLOWED = 0x0c,
- GMM_CAUSE_ROAMING_NOTALLOWED = 0x0d,
- GMM_CAUSE_NO_GPRS_PLMN = 0x0e,
- GMM_CAUSE_MSC_TEMP_NOTREACH = 0x10,
- GMM_CAUSE_NET_FAIL = 0x11,
- GMM_CAUSE_CONGESTION = 0x16,
- GMM_CAUSE_SEM_INCORR_MSG = 0x5f,
- GMM_CAUSE_INV_MAND_INFO = 0x60,
- GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
- GMM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
- GMM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
- GMM_CAUSE_COND_IE_ERR = 0x64,
- GMM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
- GMM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
-};
-
-extern const struct value_string *gsm48_gmm_cause_names;
-
-/* Chapter 10.4.6.6 / Table 10.5.157 */
-enum gsm48_gsm_cause {
- GSM_CAUSE_INSUFF_RSRC = 0x1a,
- GSM_CAUSE_MISSING_APN = 0x1b,
- GSM_CAUSE_UNKNOWN_PDP = 0x1c,
- GSM_CAUSE_AUTH_FAILED = 0x1d,
- GSM_CAUSE_ACT_REJ_GGSN = 0x1e,
- GSM_CAUSE_ACT_REJ_UNSPEC = 0x1f,
- GSM_CAUSE_SERV_OPT_NOTSUPP = 0x20,
- GSM_CAUSE_REQ_SERV_OPT_NOTSUB = 0x21,
- GSM_CAUSE_SERV_OPT_TEMP_OOO = 0x22,
- GSM_CAUSE_NSAPI_IN_USE = 0x23,
- GSM_CAUSE_DEACT_REGULAR = 0x24,
- GSM_CAUSE_QOS_NOT_ACCEPTED = 0x25,
- GSM_CAUSE_NET_FAIL = 0x26,
- GSM_CAUSE_REACT_RQD = 0x27,
- GSM_CAUSE_FEATURE_NOTSUPP = 0x28,
- GSM_CAUSE_INVALID_TRANS_ID = 0x51,
- GSM_CAUSE_SEM_INCORR_MSG = 0x5f,
- GSM_CAUSE_INV_MAND_INFO = 0x60,
- GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL = 0x61,
- GSM_CAUSE_MSGT_INCOMP_P_STATE = 0x62,
- GSM_CAUSE_IE_NOTEXIST_NOTIMPL = 0x63,
- GSM_CAUSE_COND_IE_ERR = 0x64,
- GSM_CAUSE_MSG_INCOMP_P_STATE = 0x65,
- GSM_CAUSE_PROTO_ERR_UNSPEC = 0x6f,
-};
-
-extern const struct value_string *gsm48_gsm_cause_names;
-
-/* Section 6.1.2.2: Session management states on the network side */
-enum gsm48_pdp_state {
- PDP_S_INACTIVE,
- PDP_S_ACTIVE_PENDING,
- PDP_S_ACTIVE,
- PDP_S_INACTIVE_PENDING,
- PDP_S_MODIFY_PENDING,
-};
-
-/* Table 10.5.155/3GPP TS 24.008 */
-enum gsm48_pdp_type_org {
- PDP_TYPE_ORG_ETSI = 0x00,
- PDP_TYPE_ORG_IETF = 0x01,
-};
-enum gsm48_pdp_type_nr {
- PDP_TYPE_N_ETSI_RESERVED = 0x00,
- PDP_TYPE_N_ETSI_PPP = 0x01,
- PDP_TYPE_N_IETF_IPv4 = 0x21,
- PDP_TYPE_N_IETF_IPv6 = 0x57,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_reliab_class {
- GSM48_QOS_RC_LLC_ACK_RLC_ACK_DATA_PROT = 2,
- GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT = 3,
- GSM48_QOS_RC_LLC_UN_RLC_UN_PROT_DATA = 4,
- GSM48_QOS_RC_LLC_UN_RLC_UN_DATA_UN = 5,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_preced_class {
- GSM48_QOS_PC_HIGH = 1,
- GSM48_QOS_PC_NORMAL = 2,
- GSM48_QOS_PC_LOW = 3,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_peak_tput {
- GSM48_QOS_PEAK_TPUT_1000bps = 1,
- GSM48_QOS_PEAK_TPUT_2000bps = 2,
- GSM48_QOS_PEAK_TPUT_4000bps = 3,
- GSM48_QOS_PEAK_TPUT_8000bps = 4,
- GSM48_QOS_PEAK_TPUT_16000bps = 5,
- GSM48_QOS_PEAK_TPUT_32000bps = 6,
- GSM48_QOS_PEAK_TPUT_64000bps = 7,
- GSM48_QOS_PEAK_TPUT_128000bps = 8,
- GSM48_QOS_PEAK_TPUT_256000bps = 9,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_mean_tput {
- GSM48_QOS_MEAN_TPUT_100bph = 1,
- GSM48_QOS_MEAN_TPUT_200bph = 2,
- GSM48_QOS_MEAN_TPUT_500bph = 3,
- GSM48_QOS_MEAN_TPUT_1000bph = 4,
- GSM48_QOS_MEAN_TPUT_2000bph = 5,
- GSM48_QOS_MEAN_TPUT_5000bph = 6,
- GSM48_QOS_MEAN_TPUT_10000bph = 7,
- GSM48_QOS_MEAN_TPUT_20000bph = 8,
- GSM48_QOS_MEAN_TPUT_50000bph = 9,
- GSM48_QOS_MEAN_TPUT_100kbph = 10,
- GSM48_QOS_MEAN_TPUT_200kbph = 11,
- GSM48_QOS_MEAN_TPUT_500kbph = 0xc,
- GSM48_QOS_MEAN_TPUT_1Mbph = 0xd,
- GSM48_QOS_MEAN_TPUT_2Mbph = 0xe,
- GSM48_QOS_MEAN_TPUT_5Mbph = 0xf,
- GSM48_QOS_MEAN_TPUT_10Mbph = 0x10,
- GSM48_QOS_MEAN_TPUT_20Mbph = 0x11,
- GSM48_QOS_MEAN_TPUT_50Mbph = 0x12,
- GSM48_QOS_MEAN_TPUT_BEST_EFFORT = 0x1f,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_err_sdu {
- GSM48_QOS_ERRSDU_NODETECT = 1,
- GSM48_QOS_ERRSDU_YES = 2,
- GSM48_QOS_ERRSDU_NO = 3,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_deliv_order {
- GSM48_QOS_DO_ORDERED = 1,
- GSM48_QOS_DO_UNORDERED = 2,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_traf_class {
- GSM48_QOS_TC_CONVERSATIONAL = 1,
- GSM48_QOS_TC_STREAMING = 2,
- GSM48_QOS_TC_INTERACTIVE = 3,
- GSM48_QOS_TC_BACKGROUND = 4,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_max_sdu_size {
- /* values below in 10 octet granularity */
- GSM48_QOS_MAXSDU_1502 = 0x97,
- GSM48_QOS_MAXSDU_1510 = 0x98,
- GSM48_QOS_MAXSDU_1520 = 0x99,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_max_bitrate {
- GSM48_QOS_MBRATE_1k = 0x01,
- GSM48_QOS_MBRATE_63k = 0x3f,
- GSM48_QOS_MBRATE_64k = 0x40,
- GSM48_QOS_MBRATE_568k = 0x7f,
- GSM48_QOS_MBRATE_576k = 0x80,
- GSM48_QOS_MBRATE_8640k = 0xfe,
- GSM48_QOS_MBRATE_0k = 0xff,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_resid_ber {
- GSM48_QOS_RBER_5e_2 = 0x01,
- GSM48_QOS_RBER_1e_2 = 0x02,
- GSM48_QOS_RBER_5e_3 = 0x03,
- GSM48_QOS_RBER_4e_3 = 0x04,
- GSM48_QOS_RBER_1e_3 = 0x05,
- GSM48_QOS_RBER_1e_4 = 0x06,
- GSM48_QOS_RBER_1e_5 = 0x07,
- GSM48_QOS_RBER_1e_6 = 0x08,
- GSM48_QOS_RBER_6e_8 = 0x09,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-enum gsm48_qos_sdu_err {
- GSM48_QOS_SERR_1e_2 = 0x01,
- GSM48_QOS_SERR_7e_2 = 0x02,
- GSM48_QOS_SERR_1e_3 = 0x03,
- GSM48_QOS_SERR_1e_4 = 0x04,
- GSM48_QOS_SERR_1e_5 = 0x05,
- GSM48_QOS_SERR_1e_6 = 0x06,
- GSM48_QOS_SERR_1e_1 = 0x07,
-};
-
-/* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */
-struct gsm48_qos {
- /* octet 3 */
- uint8_t reliab_class:3;
- uint8_t delay_class:3;
- uint8_t spare:2;
- /* octet 4 */
- uint8_t preced_class:3;
- uint8_t spare2:1;
- uint8_t peak_tput:4;
- /* octet 5 */
- uint8_t mean_tput:5;
- uint8_t spare3:3;
- /* octet 6 */
- uint8_t deliv_err_sdu:3;
- uint8_t deliv_order:2;
- uint8_t traf_class:3;
- /* octet 7 */
- uint8_t max_sdu_size;
- /* octet 8 */
- uint8_t max_bitrate_up;
- /* octet 9 */
- uint8_t max_bitrate_down;
- /* octet 10 */
- uint8_t sdu_err_ratio:4;
- uint8_t resid_ber:4;
- /* octet 11 */
- uint8_t handling_prio:2;
- uint8_t xfer_delay:6;
- /* octet 12 */
- uint8_t guar_bitrate_up;
- /* octet 13 */
- uint8_t guar_bitrate_down;
- /* octet 14 */
- uint8_t src_stats_desc:4;
- uint8_t sig_ind:1;
- uint8_t spare5:3;
- /* octet 15 */
- uint8_t max_bitrate_down_ext;
- /* octet 16 */
- uint8_t guar_bitrate_down_ext;
-};
-
/* 3GPP 24.008 / Chapter 10.5.5.20 / Table 10.5.153a */
enum gsm48_gmm_service_type {
GPRS_SERVICE_T_SIGNALLING = 0x00,
@@ -408,5 +19,3 @@ enum gsm48_gmm_service_type {
};
extern const struct value_string *gprs_service_t_strs;
-
-#endif /* _GSM48_GPRS_H */
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 0a450d754..44a83117e 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -5,6 +5,7 @@
#include <osmocom/core/timer.h>
#include <osmocom/core/select.h>
+#include <osmocom/crypt/auth.h>
#include <openbsc/rest_octets.h>
#include <openbsc/xsc.h>
@@ -48,9 +49,7 @@ struct gsm_auth_info {
struct gsm_auth_tuple {
int use_count;
int key_seq;
- uint8_t rand[16];
- uint8_t sres[4];
- uint8_t kc[8];
+ struct osmo_auth_vector vec;
};
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index e7372ab88..5643d48e6 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -106,6 +106,7 @@ struct gsm_abis_mo {
#define A38_XOR_MAX_KEY_LEN 16
#define A38_COMP128_KEY_LEN 16
#define RSL_ENC_ALG_A5(x) (x+1)
+#define MAX_EARFCN_LIST 32
/* is the data link established? who established it? */
#define LCHAN_SAPI_UNUSED 0
@@ -704,12 +705,18 @@ struct gsm_bts {
struct bitvec neigh_list;
struct bitvec cell_alloc;
struct bitvec si5_neigh_list;
+ struct osmo_earfcn_si2q si2quater_neigh_list;
+ size_t uarfcn_length; /* index for uarfcn and scramble lists */
struct {
/* bitmask large enough for all possible ARFCN's */
uint8_t neigh_list[1024/8];
uint8_t cell_alloc[1024/8];
/* If the user wants a different neighbor list in SI5 than in SI2 */
uint8_t si5_neigh_list[1024/8];
+ uint8_t meas_bw_list[MAX_EARFCN_LIST];
+ uint16_t earfcn_list[MAX_EARFCN_LIST];
+ uint16_t uarfcn_list[MAX_EARFCN_LIST];
+ uint16_t scramble_list[MAX_EARFCN_LIST];
} data;
} si_common;
diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h
index 62d121365..44e24b03c 100644
--- a/openbsc/include/openbsc/gsm_subscriber.h
+++ b/openbsc/include/openbsc/gsm_subscriber.h
@@ -5,9 +5,8 @@
#include "gsm_data.h"
#include <osmocom/core/linuxlist.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
-#define GSM_IMEI_LENGTH 17
-#define GSM_IMSI_LENGTH 17
#define GSM_NAME_LENGTH 160
#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
@@ -34,7 +33,7 @@ struct gsm_subscriber_group {
struct gsm_equipment {
long long unsigned int id;
- char imei[GSM_IMEI_LENGTH];
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
char name[GSM_NAME_LENGTH];
struct gsm48_classmark1 classmark1;
@@ -47,7 +46,7 @@ struct gsm_equipment {
struct gsm_subscriber {
struct gsm_subscriber_group *group;
long long unsigned int id;
- char imsi[GSM_IMSI_LENGTH];
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
uint32_t tmsi;
uint16_t lac;
char name[GSM_NAME_LENGTH];
diff --git a/openbsc/include/openbsc/ipaccess.h b/openbsc/include/openbsc/ipaccess.h
index 38151c477..82e89c27d 100644
--- a/openbsc/include/openbsc/ipaccess.h
+++ b/openbsc/include/openbsc/ipaccess.h
@@ -5,13 +5,14 @@
#include "gsm_subscriber.h"
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
struct ipac_msgt_sccp_state {
uint8_t src_ref[3];
uint8_t dst_ref[3];
uint8_t trans_id;
uint8_t invoke_id;
- char imsi[GSM_IMSI_LENGTH];
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
uint8_t data[0];
} __attribute__((packed));
diff --git a/openbsc/include/openbsc/oap.h b/openbsc/include/openbsc/oap.h
index 2370cbe07..2206184d1 100644
--- a/openbsc/include/openbsc/oap.h
+++ b/openbsc/include/openbsc/oap.h
@@ -25,7 +25,7 @@
#include <stdint.h>
struct msgb;
-struct oap_message;
+struct osmo_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. */
@@ -74,5 +74,5 @@ int oap_handle(struct oap_state *state, const struct msgb *msg_rx, struct msgb *
/* 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);
+struct msgb *oap_encoded(const struct osmo_oap_message *oap_msg);
diff --git a/openbsc/include/openbsc/oap_messages.h b/openbsc/include/openbsc/oap_messages.h
index a7a254c2e..ecb66df34 100644
--- a/openbsc/include/openbsc/oap_messages.h
+++ b/openbsc/include/openbsc/oap_messages.h
@@ -22,8 +22,8 @@
#pragma once
#include <stdint.h>
-#include <openbsc/gsm_04_08_gprs.h>
-#include <openbsc/gsm_data.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
/* Some numbers are out of sequence because (so far) they match gprs_gsup_iei.
*/
@@ -36,7 +36,7 @@ enum oap_iei {
OAP_CLIENT_ID_IE = 0x30,
};
-enum oap_message_type {
+enum osmo_oap_message_type {
OAP_MSGT_REGISTER_REQUEST = 0b00000100,
OAP_MSGT_REGISTER_ERROR = 0b00000101,
OAP_MSGT_REGISTER_RESULT = 0b00000110,
@@ -50,8 +50,8 @@ enum oap_message_type {
OAP_MSGT_SYNC_RESULT = 0b00001110,
};
-struct oap_message {
- enum oap_message_type message_type;
+struct osmo_oap_message {
+ enum osmo_oap_message_type message_type;
enum gsm48_gmm_cause cause;
uint16_t client_id;
int rand_present;
@@ -64,7 +64,7 @@ struct oap_message {
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);
+int osmo_oap_decode(struct osmo_oap_message *oap_msg,
+ const uint8_t *data, size_t data_len);
+void osmo_oap_encode(struct msgb *msg, const struct osmo_oap_message *oap_msg);
diff --git a/openbsc/include/openbsc/rest_octets.h b/openbsc/include/openbsc/rest_octets.h
index 963b010c9..32b996317 100644
--- a/openbsc/include/openbsc/rest_octets.h
+++ b/openbsc/include/openbsc/rest_octets.h
@@ -1,10 +1,17 @@
#ifndef _REST_OCTETS_H
#define _REST_OCTETS_H
+#include <stdbool.h>
#include <openbsc/gsm_04_08.h>
+#include <osmocom/gsm/sysinfo.h>
+
+#define SI2Q_MAX_LEN 160
+#define SI2Q_MIN_LEN 18
/* generate SI1 rest octets */
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net);
+int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
+ const uint16_t *u, const uint16_t *sc, size_t u_len);
struct gsm48_si_selection_params {
uint16_t penalty_time:5,
@@ -43,7 +50,8 @@ struct gsm48_si_ro_info {
present:1;
} scheduling;
struct gsm48_si3_gprs_ind gprs_ind;
-
+ /* SI 3 specific */
+ uint8_t si2quater_indicator;
/* SI 4 specific */
struct gsm48_lsa_params lsa_params;
uint16_t cell_id;
diff --git a/openbsc/include/openbsc/system_information.h b/openbsc/include/openbsc/system_information.h
index 6a5684821..7e3ceaa29 100644
--- a/openbsc/include/openbsc/system_information.h
+++ b/openbsc/include/openbsc/system_information.h
@@ -6,5 +6,13 @@
struct gsm_bts;
int gsm_generate_si(struct gsm_bts *bts, enum osmo_sysinfo_type type);
-
+uint16_t encode_fdd(uint16_t scramble, bool diversity);
+unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len);
+unsigned earfcn_size(const struct osmo_earfcn_si2q *e);
+unsigned range1024_p(unsigned n);
+unsigned range512_q(unsigned m);
+bool si2q_size_check(const struct gsm_bts *bts);
+int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble);
+int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
+ bool diversity);
#endif
diff --git a/openbsc/include/openbsc/utils.h b/openbsc/include/openbsc/utils.h
deleted file mode 100644
index d6054873b..000000000
--- a/openbsc/include/openbsc/utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* OpenBSC kitchen sink */
-
-#pragma once
-
-#include <stdint.h>
-#include <stdlib.h>
-
-/* 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/Makefile.am b/openbsc/src/gprs/Makefile.am
index 187b07ed9..d098559f9 100644
--- a/openbsc/src/gprs/Makefile.am
+++ b/openbsc/src/gprs/Makefile.am
@@ -30,7 +30,7 @@ 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 \
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 \
+ gprs_utils.c gprs_gsup_client.c \
gsm_04_08_gprs.c sgsn_cdr.c sgsn_ares.c \
oap.c oap_messages.c
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 6e6b03b86..111f05208 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -48,7 +48,7 @@
#include <openbsc/gprs_llc.h>
#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_04_08_gprs.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <openbsc/gprs_utils.h>
#include <openssl/rand.h>
diff --git a/openbsc/src/gprs/gb_proxy_patch.c b/openbsc/src/gprs/gb_proxy_patch.c
index c1d2497db..7bddc4494 100644
--- a/openbsc/src/gprs/gb_proxy_patch.c
+++ b/openbsc/src/gprs/gb_proxy_patch.c
@@ -23,7 +23,6 @@
#include <openbsc/gprs_utils.h>
#include <openbsc/gprs_gb_parse.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/gsm_data.h>
#include <openbsc/debug.h>
diff --git a/openbsc/src/gprs/gb_proxy_peer.c b/openbsc/src/gprs/gb_proxy_peer.c
index c2cdd0e67..5365ff0fa 100644
--- a/openbsc/src/gprs/gb_proxy_peer.c
+++ b/openbsc/src/gprs/gb_proxy_peer.c
@@ -24,7 +24,6 @@
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_data_shared.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
#include <osmocom/gprs/protocol/gsm_08_18.h>
diff --git a/openbsc/src/gprs/gprs_gb_parse.c b/openbsc/src/gprs/gprs_gb_parse.c
index 63ac9028d..f11d93aef 100644
--- a/openbsc/src/gprs/gprs_gb_parse.c
+++ b/openbsc/src/gprs/gprs_gb_parse.c
@@ -19,12 +19,12 @@
*/
#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <openbsc/gprs_gb_parse.h>
#include <openbsc/gprs_utils.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
#include <osmocom/gprs/gprs_bssgp.h>
@@ -38,7 +38,7 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
parse_ctx->llc_msg_name = "ATTACH_REQ";
/* Skip MS network capability */
- if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
+ if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
value_len < 1 || value_len > 8)
/* invalid */
return 0;
@@ -46,10 +46,10 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
/* Skip Attach type */
/* Skip Ciphering key sequence number */
/* Skip DRX parameter */
- gprs_shift_v_fixed(&data, &data_len, 3, NULL);
+ osmo_shift_v_fixed(&data, &data_len, 3, NULL);
/* Get Mobile identity */
- if (gprs_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
+ if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
value_len < 5 || value_len > 8)
/* invalid */
return 0;
@@ -61,7 +61,7 @@ static int gprs_gb_parse_gmm_attach_req(uint8_t *data, size_t data_len,
parse_ctx->imsi_len = value_len;
}
- if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
return 0;
parse_ctx->old_raid_enc = value;
@@ -82,21 +82,21 @@ static int gprs_gb_parse_gmm_attach_ack(uint8_t *data, size_t data_len,
/* Skip Periodic RA update timer */
/* Skip Radio priority for SMS */
/* Skip Spare half octet */
- gprs_shift_v_fixed(&data, &data_len, 3, NULL);
+ osmo_shift_v_fixed(&data, &data_len, 3, NULL);
- if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
return 0;
parse_ctx->raid_enc = value;
/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
- gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
+ osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
/* Skip Negotiated READY timer value (GPRS timer, opt, TV, length 2) */
- gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
+ osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_TIMER_READY, 1, NULL);
/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
- if (gprs_match_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
+ if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
&value, &value_len) > 0 &&
gprs_is_mi_tmsi(value, value_len))
parse_ctx->new_ptmsi_enc = value + 1;
@@ -111,7 +111,7 @@ static int gprs_gb_parse_gmm_attach_rej(uint8_t *data, size_t data_len,
parse_ctx->llc_msg_name = "ATTACH_REJ";
/* GMM cause */
- if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
return 0;
parse_ctx->invalidate_tlli = 1;
@@ -132,7 +132,7 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
/* Skip spare half octet */
/* Get Detach type */
- if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
/* invalid */
return 0;
@@ -150,7 +150,7 @@ static int gprs_gb_parse_gmm_detach_req(uint8_t *data, size_t data_len,
parse_ctx->invalidate_tlli = 1;
/* Get P-TMSI (Mobile identity), see GSM 24.008, 9.4.5.2 */
- if (gprs_match_tlv(&data, &data_len,
+ if (osmo_match_shift_tlv(&data, &data_len,
GSM48_IE_GMM_ALLOC_PTMSI, &value, &value_len) > 0)
{
if (gprs_is_mi_tmsi(value, value_len))
@@ -170,9 +170,9 @@ static int gprs_gb_parse_gmm_ra_upd_req(uint8_t *data, size_t data_len,
/* Skip Update type */
/* Skip GPRS ciphering key sequence number */
- gprs_shift_v_fixed(&data, &data_len, 1, NULL);
+ osmo_shift_v_fixed(&data, &data_len, 1, NULL);
- if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
return 0;
parse_ctx->old_raid_enc = value;
@@ -190,14 +190,14 @@ static int gprs_gb_parse_gmm_ra_upd_rej(uint8_t *data, size_t data_len,
parse_ctx->llc_msg_name = "RA_UPD_REJ";
/* GMM cause */
- if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
return 0;
cause = value[0];
/* Force to standby, 1/2 */
/* spare bits, 1/2 */
- if (gprs_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 1, &value) <= 0)
return 0;
force_standby = (value[0] & 0x07) == 0x01;
@@ -221,18 +221,18 @@ static int gprs_gb_parse_gmm_ra_upd_ack(uint8_t *data, size_t data_len,
/* Skip Force to standby */
/* Skip Update result */
/* Skip Periodic RA update timer */
- gprs_shift_v_fixed(&data, &data_len, 2, NULL);
+ osmo_shift_v_fixed(&data, &data_len, 2, NULL);
- if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
return 0;
parse_ctx->raid_enc = value;
/* Skip P-TMSI signature (P-TMSI signature, opt, TV, length 4) */
- gprs_match_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
+ osmo_match_shift_tv_fixed(&data, &data_len, GSM48_IE_GMM_PTMSI_SIG, 3, NULL);
/* Allocated P-TMSI (Mobile identity, opt, TLV, length 7) */
- if (gprs_match_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
+ if (osmo_match_shift_tlv(&data, &data_len, GSM48_IE_GMM_ALLOC_PTMSI,
&value, &value_len) > 0 &&
gprs_is_mi_tmsi(value, value_len))
parse_ctx->new_ptmsi_enc = value + 1;
@@ -252,11 +252,11 @@ static int gprs_gb_parse_gmm_ptmsi_reall_cmd(uint8_t *data, size_t data_len,
"Got P-TMSI Reallocation Command which is not covered by unit tests yet.\n");
/* Allocated P-TMSI */
- if (gprs_shift_lv(&data, &data_len, &value, &value_len) > 0 &&
+ if (osmo_shift_lv(&data, &data_len, &value, &value_len) > 0 &&
gprs_is_mi_tmsi(value, value_len))
parse_ctx->new_ptmsi_enc = value + 1;
- if (gprs_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, 6, &value) <= 0)
return 0;
parse_ctx->raid_enc = value;
@@ -273,7 +273,7 @@ static int gprs_gb_parse_gmm_id_resp(uint8_t *data, size_t data_len,
parse_ctx->llc_msg_name = "ID_RESP";
/* Mobile identity, Mobile identity 10.5.1.4, M LV 2-10 */
- if (gprs_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
+ if (osmo_shift_lv(&data, &data_len, &value, &value_len) <= 0 ||
value_len < 1 || value_len > 9)
/* invalid */
return 0;
@@ -299,22 +299,22 @@ static int gprs_gb_parse_gsm_act_pdp_req(uint8_t *data, size_t data_len,
/* Skip Requested NSAPI */
/* Skip Requested LLC SAPI */
- gprs_shift_v_fixed(&data, &data_len, 2, NULL);
+ osmo_shift_v_fixed(&data, &data_len, 2, NULL);
/* Skip Requested QoS (support 04.08 and 24.008) */
- if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
+ if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
value_len < 4 || value_len > 14)
/* invalid */
return 0;
/* Skip Requested PDP address */
- if (gprs_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
+ if (osmo_shift_lv(&data, &data_len, NULL, &value_len) <= 0 ||
value_len < 2 || value_len > 18)
/* invalid */
return 0;
/* Access point name */
- old_len = gprs_match_tlv(&data, &data_len,
+ old_len = osmo_match_shift_tlv(&data, &data_len,
GSM48_IE_GSM_APN, &value, &value_len);
if (old_len > 0 && value_len >=1 && value_len <= 100) {
@@ -332,7 +332,7 @@ int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
uint8_t pdisc;
uint8_t msg_type;
- if (gprs_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
+ if (osmo_shift_v_fixed(&data, &data_len, sizeof(*g48h), (uint8_t **)&g48h) <= 0)
return 0;
parse_ctx->g48_hdr = g48h;
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index f32854d74..2304c1a01 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -564,9 +564,9 @@ static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
at = &ctx->auth_triplet;
- if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->sres) ||
- memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->sres,
- sizeof(at->sres)) != 0) {
+ if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->vec.sres) ||
+ memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->vec.sres,
+ sizeof(at->vec.sres)) != 0) {
LOGMMCTXP(LOGL_NOTICE, ctx, "Received SRES doesn't match\n");
rc = gsm48_tx_gmm_auth_ciph_rej(ctx);
@@ -757,7 +757,8 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
struct gsm_auth_tuple *at = &ctx->auth_triplet;
mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
- return gsm48_tx_gmm_auth_ciph_req(ctx, at->rand, at->key_seq,
+ return gsm48_tx_gmm_auth_ciph_req(ctx, at->vec.rand,
+ at->key_seq,
GPRS_ALGO_GEA0);
}
@@ -1090,7 +1091,6 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
ctx->gb.cell_id = cid;
else if (ctx->ran_type == MM_CTX_T_UTRAN_Iu) {
unsigned char tmp_rand[16];
- struct osmo_auth_vector vec;
/* Ki 000102030405060708090a0b0c0d0e0f */
struct osmo_sub_auth_data auth = {
.type = OSMO_AUTH_TYPE_GSM,
@@ -1107,15 +1107,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
RAND_bytes(tmp_rand, 16);
- memset(&vec, 0, sizeof(vec));
- osmo_auth_gen_vec(&vec, &auth, tmp_rand);
-
-
+ memset(&ctx->auth_triplet.vec, 0, sizeof(ctx->auth_triplet.vec));
+ osmo_auth_gen_vec(&ctx->auth_triplet.vec, &auth, tmp_rand);
ctx->auth_triplet.key_seq = 0;
- memcpy(&ctx->auth_triplet.rand, &tmp_rand, sizeof(ctx->auth_triplet.rand));
- memcpy(&ctx->auth_triplet.sres, &vec.sres, sizeof(ctx->auth_triplet.sres));
- memcpy(&ctx->auth_triplet.kc, &vec.kc, sizeof(ctx->auth_triplet.kc));
}
/* Update MM Context with other data */
@@ -1821,7 +1816,8 @@ static void mmctx_timer_cb(void *_mm)
}
at = &mm->auth_triplet;
- gsm48_tx_gmm_auth_ciph_req(mm, at->rand, at->key_seq, GPRS_ALGO_GEA0);
+ gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq,
+ GPRS_ALGO_GEA0);
osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
break;
case 3370: /* waiting for IDENTITY RESPONSE */
diff --git a/openbsc/src/gprs/gprs_gsup_messages.c b/openbsc/src/gprs/gprs_gsup_messages.c
deleted file mode 100644
index 07485f7f9..000000000
--- a/openbsc/src/gprs/gprs_gsup_messages.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* GPRS Subscriber Update Protocol message encoder/decoder */
-
-/*
- * (C) 2014 by Sysmocom s.f.m.c. GmbH
- * (C) 2015 by Holger Hans Peter Freyther
- * All Rights Reserved
- *
- * Author: Jacob Erlbeck
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <openbsc/gprs_gsup_messages.h>
-
-#include <openbsc/debug.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/utils.h>
-
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-
-#include <stdint.h>
-
-static int decode_pdp_info(uint8_t *data, size_t data_len,
- struct gprs_gsup_pdp_info *pdp_info)
-{
- int rc;
- uint8_t tag;
- uint8_t *value;
- size_t value_len;
-
- /* specific parts */
- while (data_len > 0) {
- enum gprs_gsup_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 GPRS_GSUP_PDP_CONTEXT_ID_IE:
- pdp_info->context_id = decode_big_endian(value, value_len);
- break;
-
- case GPRS_GSUP_PDP_TYPE_IE:
- pdp_info->pdp_type =
- decode_big_endian(value, value_len) & 0x0fff;
- break;
-
- case GPRS_GSUP_ACCESS_POINT_NAME_IE:
- pdp_info->apn_enc = value;
- pdp_info->apn_enc_len = value_len;
- break;
-
- case GPRS_GSUP_PDP_QOS_IE:
- pdp_info->qos_enc = value;
- pdp_info->qos_enc_len = value_len;
- break;
-
- default:
- LOGP(DGPRS, LOGL_ERROR,
- "GSUP IE type %d not expected in PDP info\n", iei);
- continue;
- }
- }
-
- return 0;
-}
-
-static int decode_auth_info(uint8_t *data, size_t data_len,
- struct gsm_auth_tuple *auth_tuple)
-{
- int rc;
- uint8_t tag;
- uint8_t *value;
- size_t value_len;
- enum gprs_gsup_iei iei;
-
- /* specific parts */
- while (data_len > 0) {
- 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 GPRS_GSUP_RAND_IE:
- if (value_len != sizeof(auth_tuple->rand))
- goto parse_error;
-
- memcpy(auth_tuple->rand, value, value_len);
- break;
-
- case GPRS_GSUP_SRES_IE:
- if (value_len != sizeof(auth_tuple->sres))
- goto parse_error;
-
- memcpy(auth_tuple->sres, value, value_len);
- break;
-
- case GPRS_GSUP_KC_IE:
- if (value_len != sizeof(auth_tuple->kc))
- goto parse_error;
-
- memcpy(auth_tuple->kc, value, value_len);
- break;
-
- default:
- LOGP(DGPRS, LOGL_ERROR,
- "GSUP IE type %d not expected in PDP info\n", iei);
- continue;
- }
- }
-
- return 0;
-
-parse_error:
- LOGP(DGPRS, LOGL_ERROR,
- "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len);
-
- return -1;
-}
-
-int gprs_gsup_decode(const uint8_t *const_data, size_t data_len,
- struct gprs_gsup_message *gsup_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;
- static const struct gprs_gsup_pdp_info empty_pdp_info = {0};
- static const struct gsm_auth_tuple empty_auth_info = {0};
- static const struct gprs_gsup_message empty_gsup_message = {0};
-
- *gsup_msg = empty_gsup_message;
-
- /* generic part */
- rc = gprs_shift_v_fixed(&data, &data_len, 1, &value);
- if (rc < 0)
- return -GMM_CAUSE_INV_MAND_INFO;
-
- gsup_msg->message_type = decode_big_endian(value, 1);
-
- rc = gprs_match_tlv(&data, &data_len, GPRS_GSUP_IMSI_IE,
- &value, &value_len);
-
- if (rc <= 0)
- return -GMM_CAUSE_INV_MAND_INFO;
-
- if (value_len * 2 + 1 > sizeof(gsup_msg->imsi))
- return -GMM_CAUSE_INV_MAND_INFO;
-
- /* Note that gsm48_decode_bcd_number expects the number of encoded IMSI
- * octets in the first octet. By coincidence (the TLV encoding) the byte
- * before the value part already contains this length so we can use it
- * here.
- */
- OSMO_ASSERT(value[-1] == value_len);
- gsm48_decode_bcd_number(gsup_msg->imsi, sizeof(gsup_msg->imsi),
- value - 1, 0);
-
- /* specific parts */
- while (data_len > 0) {
- enum gprs_gsup_iei iei;
- struct gprs_gsup_pdp_info pdp_info;
- struct gsm_auth_tuple auth_info;
-
- 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 GPRS_GSUP_IMSI_IE:
- case GPRS_GSUP_PDP_TYPE_IE:
- case GPRS_GSUP_ACCESS_POINT_NAME_IE:
- case GPRS_GSUP_RAND_IE:
- case GPRS_GSUP_SRES_IE:
- case GPRS_GSUP_KC_IE:
- LOGP(DGPRS, LOGL_NOTICE,
- "GSUP IE type %d not expected (ignored)\n", iei);
- continue;
-
- case GPRS_GSUP_CAUSE_IE:
- gsup_msg->cause = decode_big_endian(value, value_len);
- break;
-
- case GPRS_GSUP_CANCEL_TYPE_IE:
- gsup_msg->cancel_type =
- decode_big_endian(value, value_len) + 1;
- break;
-
- case GPRS_GSUP_PDP_INFO_COMPL_IE:
- gsup_msg->pdp_info_compl = 1;
- break;
-
- case GPRS_GSUP_FREEZE_PTMSI_IE:
- gsup_msg->freeze_ptmsi = 1;
- break;
-
- case GPRS_GSUP_PDP_CONTEXT_ID_IE:
- /* When these IE appear in the top-level part of the
- * message, they are used by Delete Subscr Info to delete
- * single entries. We don't have an extra list for
- * these but use the PDP info list instead */
-
- /* fall through */
-
- case GPRS_GSUP_PDP_INFO_IE:
- if (gsup_msg->num_pdp_infos >= GPRS_GSUP_MAX_NUM_PDP_INFO) {
- LOGP(DGPRS, LOGL_ERROR,
- "GSUP IE type %d (PDP_INFO) max exceeded\n",
- iei);
- return -GMM_CAUSE_COND_IE_ERR;
- }
-
- pdp_info = empty_pdp_info;
-
- if (iei == GPRS_GSUP_PDP_INFO_IE) {
- rc = decode_pdp_info(value, value_len, &pdp_info);
- if (rc < 0)
- return rc;
- pdp_info.have_info = 1;
- } else {
- pdp_info.context_id =
- decode_big_endian(value, value_len);
- }
-
- gsup_msg->pdp_infos[gsup_msg->num_pdp_infos++] =
- pdp_info;
- break;
-
- case GPRS_GSUP_AUTH_TUPLE_IE:
- if (gsup_msg->num_auth_tuples >= GPRS_GSUP_MAX_NUM_AUTH_INFO) {
- LOGP(DGPRS, LOGL_ERROR,
- "GSUP IE type %d (AUTH_INFO) max exceeded\n",
- iei);
- return -GMM_CAUSE_INV_MAND_INFO;
- }
-
- auth_info = empty_auth_info;
- auth_info.key_seq = gsup_msg->num_auth_tuples;
-
- rc = decode_auth_info(value, value_len, &auth_info);
- if (rc < 0)
- return rc;
-
- gsup_msg->auth_tuples[gsup_msg->num_auth_tuples++] =
- auth_info;
- break;
-
- case GPRS_GSUP_MSISDN_IE:
- gsup_msg->msisdn_enc = value;
- gsup_msg->msisdn_enc_len = value_len;
- break;
-
- case GPRS_GSUP_HLR_NUMBER_IE:
- gsup_msg->hlr_enc = value;
- gsup_msg->hlr_enc_len = value_len;
- break;
-
- default:
- LOGP(DGPRS, LOGL_NOTICE,
- "GSUP IE type %d unknown\n", iei);
- continue;
- }
- }
-
- return 0;
-}
-
-static void encode_pdp_info(struct msgb *msg, enum gprs_gsup_iei iei,
- const struct gprs_gsup_pdp_info *pdp_info)
-{
- uint8_t *len_field;
- size_t old_len;
- uint8_t u8;
-
- len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1;
- old_len = msgb_length(msg);
-
- u8 = pdp_info->context_id;
- msgb_tlv_put(msg, GPRS_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8);
-
- if (pdp_info->pdp_type) {
- msgb_tlv_put(msg, GPRS_GSUP_PDP_TYPE_IE,
- GPRS_GSUP_PDP_TYPE_SIZE,
- encode_big_endian(pdp_info->pdp_type | 0xf000,
- GPRS_GSUP_PDP_TYPE_SIZE));
- }
-
- if (pdp_info->apn_enc) {
- msgb_tlv_put(msg, GPRS_GSUP_ACCESS_POINT_NAME_IE,
- pdp_info->apn_enc_len, pdp_info->apn_enc);
- }
-
- if (pdp_info->qos_enc) {
- msgb_tlv_put(msg, GPRS_GSUP_PDP_QOS_IE,
- pdp_info->qos_enc_len, pdp_info->qos_enc);
- }
-
- /* Update length field */
- *len_field = msgb_length(msg) - old_len;
-}
-
-static void encode_auth_info(struct msgb *msg, enum gprs_gsup_iei iei,
- const struct gsm_auth_tuple *auth_tuple)
-{
- uint8_t *len_field;
- size_t old_len;
-
- len_field = msgb_tlv_put(msg, iei, 0, NULL) - 1;
- old_len = msgb_length(msg);
-
- msgb_tlv_put(msg, GPRS_GSUP_RAND_IE,
- sizeof(auth_tuple->rand), auth_tuple->rand);
-
- msgb_tlv_put(msg, GPRS_GSUP_SRES_IE,
- sizeof(auth_tuple->sres), auth_tuple->sres);
-
- msgb_tlv_put(msg, GPRS_GSUP_KC_IE,
- sizeof(auth_tuple->kc), auth_tuple->kc);
-
- /* Update length field */
- *len_field = msgb_length(msg) - old_len;
-}
-
-void gprs_gsup_encode(struct msgb *msg, const struct gprs_gsup_message *gsup_msg)
-{
- uint8_t u8;
- int idx;
- uint8_t bcd_buf[GSM48_MI_SIZE] = {0};
- size_t bcd_len;
-
- /* generic part */
- OSMO_ASSERT(gsup_msg->message_type);
- msgb_v_put(msg, gsup_msg->message_type);
-
- bcd_len = gsm48_encode_bcd_number(bcd_buf, sizeof(bcd_buf), 0,
- gsup_msg->imsi);
-
- OSMO_ASSERT(bcd_len > 1);
-
- /* Note that gsm48_encode_bcd_number puts the length into the first
- * octet. Since msgb_tlv_put will add this length byte, we'll have to
- * skip it */
- msgb_tlv_put(msg, GPRS_GSUP_IMSI_IE, bcd_len - 1, &bcd_buf[1]);
-
- /* specific parts */
- if (gsup_msg->msisdn_enc)
- msgb_tlv_put(msg, GPRS_GSUP_MSISDN_IE,
- gsup_msg->msisdn_enc_len, gsup_msg->msisdn_enc);
- if (gsup_msg->hlr_enc)
- msgb_tlv_put(msg, GPRS_GSUP_HLR_NUMBER_IE,
- gsup_msg->hlr_enc_len, gsup_msg->hlr_enc);
-
- if ((u8 = gsup_msg->cause))
- msgb_tlv_put(msg, GPRS_GSUP_CAUSE_IE, sizeof(u8), &u8);
-
- if ((u8 = gsup_msg->cancel_type)) {
- u8 -= 1;
- msgb_tlv_put(msg, GPRS_GSUP_CANCEL_TYPE_IE, sizeof(u8), &u8);
- }
-
- if (gsup_msg->pdp_info_compl)
- msgb_tlv_put(msg, GPRS_GSUP_PDP_INFO_COMPL_IE, 0, &u8);
-
- if (gsup_msg->freeze_ptmsi)
- msgb_tlv_put(msg, GPRS_GSUP_FREEZE_PTMSI_IE, 0, &u8);
-
- for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
- const struct gprs_gsup_pdp_info *pdp_info;
-
- pdp_info = &gsup_msg->pdp_infos[idx];
-
- if (pdp_info->context_id == 0)
- continue;
-
- if (pdp_info->have_info) {
- encode_pdp_info(msg, GPRS_GSUP_PDP_INFO_IE, pdp_info);
- } else {
- u8 = pdp_info->context_id;
- msgb_tlv_put(msg, GPRS_GSUP_PDP_CONTEXT_ID_IE,
- sizeof(u8), &u8);
- }
- }
-
- for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
- const struct gsm_auth_tuple *auth_info;
-
- auth_info = &gsup_msg->auth_tuples[idx];
-
- if (auth_info->key_seq == GSM_KEY_SEQ_INVAL)
- continue;
-
- encode_auth_info(msg, GPRS_GSUP_AUTH_TUPLE_IE, auth_info);
- }
-}
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 6d0596a48..9e7143540 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -29,12 +29,12 @@
#include <osmocom/core/backtrace.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/sgsn.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/gprs_gmm.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/signal.h>
diff --git a/openbsc/src/gprs/gprs_subscriber.c b/openbsc/src/gprs/gprs_subscriber.c
index 3467293be..71f5ff188 100644
--- a/openbsc/src/gprs/gprs_subscriber.c
+++ b/openbsc/src/gprs/gprs_subscriber.c
@@ -20,13 +20,14 @@
*
*/
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+#include <osmocom/gsm/gsup.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/gprs_gsup_client.h>
#include <openbsc/sgsn.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/gprs_gmm.h>
-#include <openbsc/gprs_gsup_messages.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/debug.h>
@@ -158,14 +159,14 @@ void gprs_subscr_cancel(struct gsm_subscriber *subscr)
}
static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
struct msgb *msg = gprs_gsup_msgb_alloc();
if (strlen(gsup_msg->imsi) == 0 && subscr)
strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1);
- gprs_gsup_encode(msg, gsup_msg);
+ osmo_gsup_encode(msg, gsup_msg);
LOGGSUBSCRP(LOGL_INFO, subscr,
"Sending GSUP, will send: %s\n", msgb_hexdump(msg));
@@ -179,38 +180,38 @@ static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
}
static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_orig,
+ struct osmo_gsup_message *gsup_orig,
enum gsm48_gmm_cause cause)
{
- struct gprs_gsup_message gsup_reply = {0};
+ struct osmo_gsup_message gsup_reply = {0};
strncpy(gsup_reply.imsi, gsup_orig->imsi, sizeof(gsup_reply.imsi) - 1);
gsup_reply.cause = cause;
gsup_reply.message_type =
- GPRS_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
+ OSMO_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
}
static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
unsigned idx;
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
LOGGSUBSCRP(LOGL_INFO, subscr,
- "Got SendAuthenticationInfoResult, num_auth_tuples = %zu\n",
- gsup_msg->num_auth_tuples);
+ "Got SendAuthenticationInfoResult, num_auth_vectors = %zu\n",
+ gsup_msg->num_auth_vectors);
- if (gsup_msg->num_auth_tuples > 0) {
+ if (gsup_msg->num_auth_vectors > 0) {
memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
}
- for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
- size_t key_seq = gsup_msg->auth_tuples[idx].key_seq;
+ for (idx = 0; idx < gsup_msg->num_auth_vectors; idx++) {
+ size_t key_seq = idx;
LOGGSUBSCRP(LOGL_DEBUG, subscr,
"Adding auth tuple, cksn = %zu\n", key_seq);
if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
@@ -219,7 +220,8 @@ static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
key_seq);
continue;
}
- sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx];
+ sdata->auth_triplets[key_seq].vec = gsup_msg->auth_vectors[idx];
+ sdata->auth_triplets[key_seq].key_seq = key_seq;
}
sdata->auth_triplets_updated = 1;
@@ -259,7 +261,7 @@ static struct sgsn_subscriber_pdp_data *gprs_subscr_pdp_data_get_by_id(
static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
unsigned idx;
@@ -296,7 +298,7 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
}
for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
- struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
+ struct osmo_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
size_t ctx_id = pdp_info->context_id;
struct sgsn_subscriber_pdp_data *pdp_data;
@@ -336,8 +338,11 @@ static void gprs_subscr_gsup_insert_data(struct gsm_subscriber *subscr,
}
static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
+ /* contrary to MAP, we allow piggy-backing subscriber data onto
+ * the UPDATE LOCATION RESULT, and don't mandate the use of a
+ * separate nested INSERT SUBSCRIBER DATA transaction */
gprs_subscr_gsup_insert_data(subscr, gsup_msg);
subscr->authorized = 1;
@@ -349,6 +354,22 @@ static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
return 0;
}
+static int gprs_subscr_handle_gsup_isd_req(struct gsm_subscriber *subscr,
+ struct osmo_gsup_message *gsup_msg)
+{
+ struct osmo_gsup_message gsup_reply = {0};
+
+ gprs_subscr_gsup_insert_data(subscr, gsup_msg);
+
+ subscr->authorized = 1;
+ subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
+ subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
+ gprs_subscr_update(subscr);
+
+ gsup_reply.message_type = OSMO_GSUP_MSGT_INSERT_DATA_RESULT;
+ return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
+}
+
static int check_cause(int cause)
{
switch (cause) {
@@ -366,7 +387,7 @@ static int check_cause(int cause)
}
static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
unsigned idx;
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
@@ -419,7 +440,7 @@ static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
}
static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
int cause_err;
@@ -465,9 +486,9 @@ static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
}
static int gprs_subscr_handle_gsup_purge_no_subscr(
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
- if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
+ if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
LOGGSUPP(LOGL_NOTICE, gsup_msg,
"Purge MS has failed with cause '%s' (%d)\n",
get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
@@ -480,7 +501,7 @@ static int gprs_subscr_handle_gsup_purge_no_subscr(
}
static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
@@ -492,7 +513,7 @@ static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
}
static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
LOGGSUBSCRP(LOGL_NOTICE, subscr,
"Purge MS has failed with cause '%s' (%d)\n",
@@ -525,17 +546,17 @@ static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
}
static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr,
- struct gprs_gsup_message *gsup_msg)
+ struct osmo_gsup_message *gsup_msg)
{
- struct gprs_gsup_message gsup_reply = {0};
+ struct osmo_gsup_message gsup_reply = {0};
int is_update_procedure = !gsup_msg->cancel_type ||
- gsup_msg->cancel_type == GPRS_GSUP_CANCEL_TYPE_UPDATE;
+ gsup_msg->cancel_type == OSMO_GSUP_CANCEL_TYPE_UPDATE;
LOGGSUBSCRP(LOGL_INFO, subscr, "Cancelling MS subscriber (%s)\n",
is_update_procedure ?
"update procedure" : "subscription withdraw");
- gsup_reply.message_type = GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT;
+ gsup_reply.message_type = OSMO_GSUP_MSGT_LOCATION_CANCEL_RESULT;
gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
if (is_update_procedure)
@@ -552,16 +573,16 @@ static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr,
return 0;
}
-static int gprs_subscr_handle_unknown_imsi(struct gprs_gsup_message *gsup_msg)
+static int gprs_subscr_handle_unknown_imsi(struct osmo_gsup_message *gsup_msg)
{
- if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
+ if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
gprs_subscr_tx_gsup_error_reply(NULL, gsup_msg,
GMM_CAUSE_IMSI_UNKNOWN);
LOGP(DGPRS, LOGL_NOTICE,
"Unknown IMSI %s, discarding GSUP request "
"of type 0x%02x\n",
gsup_msg->imsi, gsup_msg->message_type);
- } else if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
+ } else if (OSMO_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
LOGP(DGPRS, LOGL_NOTICE,
"Unknown IMSI %s, discarding GSUP error "
"of type 0x%02x, cause '%s' (%d)\n",
@@ -584,10 +605,10 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
size_t data_len = msgb_l2len(msg);
int rc = 0;
- struct gprs_gsup_message gsup_msg = {0};
+ struct osmo_gsup_message gsup_msg = {0};
struct gsm_subscriber *subscr;
- rc = gprs_gsup_decode(data, data_len, &gsup_msg);
+ rc = osmo_gsup_decode(data, data_len, &gsup_msg);
if (rc < 0) {
LOGP(DGPRS, LOGL_ERROR,
"decoding GSUP message fails with error '%s' (%d)\n",
@@ -598,21 +619,21 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
if (!gsup_msg.imsi[0]) {
LOGP(DGPRS, LOGL_ERROR, "Missing IMSI in GSUP message\n");
- if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
+ if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
gprs_subscr_tx_gsup_error_reply(NULL, &gsup_msg,
GMM_CAUSE_INV_MAND_INFO);
return -GMM_CAUSE_INV_MAND_INFO;
}
- if (!gsup_msg.cause && GPRS_GSUP_IS_MSGT_ERROR(gsup_msg.message_type))
+ if (!gsup_msg.cause && OSMO_GSUP_IS_MSGT_ERROR(gsup_msg.message_type))
gsup_msg.cause = GMM_CAUSE_NET_FAIL;
subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
if (!subscr) {
switch (gsup_msg.message_type) {
- case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
- case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
+ case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
+ case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
return gprs_subscr_handle_gsup_purge_no_subscr(&gsup_msg);
default:
return gprs_subscr_handle_unknown_imsi(&gsup_msg);
@@ -623,36 +644,39 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
"Received GSUP message of type 0x%02x\n", gsup_msg.message_type);
switch (gsup_msg.message_type) {
- case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
+ case OSMO_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
rc = gprs_subscr_handle_loc_cancel_req(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
+ case OSMO_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
+ case OSMO_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
+ case OSMO_GSUP_MSGT_UPDATE_LOCATION_RESULT:
rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
+ case OSMO_GSUP_MSGT_UPDATE_LOCATION_ERROR:
rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
+ case OSMO_GSUP_MSGT_PURGE_MS_ERROR:
rc = gprs_subscr_handle_gsup_purge_err(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
+ case OSMO_GSUP_MSGT_PURGE_MS_RESULT:
rc = gprs_subscr_handle_gsup_purge_res(subscr, &gsup_msg);
break;
- case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
- case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
+ case OSMO_GSUP_MSGT_INSERT_DATA_REQUEST:
+ rc = gprs_subscr_handle_gsup_isd_req(subscr, &gsup_msg);
+ break;
+
+ case OSMO_GSUP_MSGT_DELETE_DATA_REQUEST:
LOGGSUBSCRP(LOGL_ERROR, subscr,
"Rx GSUP message type %d not yet implemented\n",
gsup_msg.message_type);
@@ -665,7 +689,7 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
LOGGSUBSCRP(LOGL_ERROR, subscr,
"Rx GSUP message type %d not valid at SGSN\n",
gsup_msg.message_type);
- if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
+ if (OSMO_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
gprs_subscr_tx_gsup_error_reply(
subscr, &gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
@@ -680,11 +704,11 @@ int gprs_subscr_rx_gsup_message(struct msgb *msg)
int gprs_subscr_purge(struct gsm_subscriber *subscr)
{
struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
- struct gprs_gsup_message gsup_msg = {0};
+ struct osmo_gsup_message gsup_msg = {0};
LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
- gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
+ gsup_msg.message_type = OSMO_GSUP_MSGT_PURGE_MS_REQUEST;
/* Provide the HLR number in case it is known */
gsup_msg.hlr_enc_len = sdata->hlr_len;
@@ -695,23 +719,23 @@ int gprs_subscr_purge(struct gsm_subscriber *subscr)
int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
{
- struct gprs_gsup_message gsup_msg = {0};
+ struct osmo_gsup_message gsup_msg = {0};
LOGGSUBSCRP(LOGL_INFO, subscr,
"subscriber auth info is not available\n");
- gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
+ gsup_msg.message_type = OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
}
int gprs_subscr_location_update(struct gsm_subscriber *subscr)
{
- struct gprs_gsup_message gsup_msg = {0};
+ struct osmo_gsup_message gsup_msg = {0};
LOGGSUBSCRP(LOGL_INFO, subscr,
"subscriber data is not available\n");
- gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
+ gsup_msg.message_type = OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
}
@@ -755,8 +779,9 @@ struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mm
}
if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
- strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
- subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
+ strncpy(subscr->equipment.imei, mmctx->imei,
+ sizeof(subscr->equipment.imei)-1);
+ subscr->equipment.imei[sizeof(subscr->equipment.imei)-1] = 0;
}
if (subscr->lac != mmctx->ra.lac)
diff --git a/openbsc/src/gprs/gprs_utils.c b/openbsc/src/gprs/gprs_utils.c
index 895a03384..64ed9788d 100644
--- a/openbsc/src/gprs/gprs_utils.c
+++ b/openbsc/src/gprs/gprs_utils.c
@@ -20,11 +20,11 @@
*
*/
#include <openbsc/gprs_utils.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gprs/gprs_ns.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/gsm48.h>
@@ -266,140 +266,6 @@ void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi)
*tmsi = ntohl(tmsi_be);
}
-/* TODO: Move shift functions to libosmocore */
-
-int gprs_shift_v_fixed(uint8_t **data, size_t *data_len,
- size_t len, uint8_t **value)
-{
- if (len > *data_len)
- goto fail;
-
- if (value)
- *value = *data;
-
- *data += len;
- *data_len -= len;
-
- return len;
-
-fail:
- *data += *data_len;
- *data_len = 0;
- return -1;
-}
-
-int gprs_match_tv_fixed(uint8_t **data, size_t *data_len,
- uint8_t tag, size_t len,
- uint8_t **value)
-{
- size_t ie_len;
-
- if (*data_len == 0)
- goto fail;
-
- if ((*data)[0] != tag)
- return 0;
-
- if (len > *data_len - 1)
- goto fail;
-
- if (value)
- *value = *data + 1;
-
- ie_len = len + 1;
- *data += ie_len;
- *data_len -= ie_len;
-
- return ie_len;
-
-fail:
- *data += *data_len;
- *data_len = 0;
- return -1;
-}
-
-int gprs_match_tlv(uint8_t **data, size_t *data_len,
- uint8_t expected_tag, uint8_t **value, size_t *value_len)
-{
- int rc;
- uint8_t tag;
- uint8_t *old_data = *data;
- size_t old_data_len = *data_len;
-
- rc = gprs_shift_tlv(data, data_len, &tag, value, value_len);
-
- if (rc > 0 && tag != expected_tag) {
- *data = old_data;
- *data_len = old_data_len;
- return 0;
- }
-
- return rc;
-}
-
-int gprs_shift_tlv(uint8_t **data, size_t *data_len,
- uint8_t *tag, uint8_t **value, size_t *value_len)
-{
- size_t len;
- size_t ie_len;
-
- if (*data_len < 2)
- goto fail;
-
- len = (*data)[1];
- if (len > *data_len - 2)
- goto fail;
-
- if (tag)
- *tag = (*data)[0];
- if (value)
- *value = *data + 2;
- if (value_len)
- *value_len = len;
-
- ie_len = len + 2;
-
- *data += ie_len;
- *data_len -= ie_len;
-
- return ie_len;
-
-fail:
- *data += *data_len;
- *data_len = 0;
- return -1;
-}
-
-int gprs_shift_lv(uint8_t **data, size_t *data_len,
- uint8_t **value, size_t *value_len)
-{
- size_t len;
- size_t ie_len;
-
- if (*data_len < 1)
- goto fail;
-
- len = (*data)[0];
- if (len > *data_len - 1)
- goto fail;
-
- if (value)
- *value = *data + 1;
- if (value_len)
- *value_len = len;
-
- ie_len = len + 1;
- *data += ie_len;
- *data_len -= ie_len;
-
- return ie_len;
-
-fail:
- *data += *data_len;
- *data_len = 0;
- return -1;
-}
-
int gprs_ra_id_equals(const struct gprs_ra_id *id1,
const struct gprs_ra_id *id2)
{
diff --git a/openbsc/src/gprs/gsm_04_08_gprs.c b/openbsc/src/gprs/gsm_04_08_gprs.c
index ed0172862..90657eb05 100644
--- a/openbsc/src/gprs/gsm_04_08_gprs.c
+++ b/openbsc/src/gprs/gsm_04_08_gprs.c
@@ -19,126 +19,12 @@
*
*/
+/* TODO: Move this to osmocom/gsm/protocol/gsm_04_08_gprs.h ? */
#include <openbsc/gsm_04_08_gprs.h>
#include <osmocom/core/utils.h>
-/* Protocol related stuff, should go into libosmocore */
-
-/* 10.5.5.14 GPRS MM Cause / Table 10.5.147 */
-const struct value_string gsm48_gmm_cause_names_[] = {
- { GMM_CAUSE_IMSI_UNKNOWN, "IMSI unknown in HLR" },
- { GMM_CAUSE_ILLEGAL_MS, "Illegal MS" },
- { GMM_CAUSE_ILLEGAL_ME, "Illegal ME" },
- { GMM_CAUSE_GPRS_NOTALLOWED, "GPRS services not allowed" },
- { GMM_CAUSE_GPRS_OTHER_NOTALLOWED,
- "GPRS services and non-GPRS services not allowed" },
- { GMM_CAUSE_MS_ID_NOT_DERIVED,
- "MS identity cannot be derived by the network" },
- { GMM_CAUSE_IMPL_DETACHED, "Implicitly detached" },
- { GMM_CAUSE_PLMN_NOTALLOWED, "PLMN not allowed" },
- { GMM_CAUSE_LA_NOTALLOWED, "Location Area not allowed" },
- { GMM_CAUSE_ROAMING_NOTALLOWED,
- "Roaming not allowed in this location area" },
- { GMM_CAUSE_NO_GPRS_PLMN,
- "GPRS services not allowed in this PLMN" },
- { GMM_CAUSE_MSC_TEMP_NOTREACH, "MSC temporarily not reachable" },
- { GMM_CAUSE_NET_FAIL, "Network failure" },
- { GMM_CAUSE_CONGESTION, "Congestion" },
- { GMM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
- { GMM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
- { GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
- "Message type non-existant or not implemented" },
- { GMM_CAUSE_MSGT_INCOMP_P_STATE,
- "Message type not compatible with protocol state" },
- { GMM_CAUSE_IE_NOTEXIST_NOTIMPL,
- "Information element non-existent or not implemented" },
- { GMM_CAUSE_COND_IE_ERR, "Conditional IE error" },
- { GMM_CAUSE_MSG_INCOMP_P_STATE,
- "Message not compatible with protocol state " },
- { GMM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
- { 0, NULL }
-};
-
-const struct value_string *gsm48_gmm_cause_names = gsm48_gmm_cause_names_;
-
-/* 10.5.6.6 SM Cause / Table 10.5.157 */
-const struct value_string gsm48_gsm_cause_names_[] = {
- { GSM_CAUSE_INSUFF_RSRC, "Insufficient resources" },
- { GSM_CAUSE_MISSING_APN, "Missing or unknown APN" },
- { GSM_CAUSE_UNKNOWN_PDP, "Unknown PDP address or PDP type" },
- { GSM_CAUSE_AUTH_FAILED, "User Authentication failed" },
- { GSM_CAUSE_ACT_REJ_GGSN, "Activation rejected by GGSN" },
- { GSM_CAUSE_ACT_REJ_UNSPEC, "Activation rejected, unspecified" },
- { GSM_CAUSE_SERV_OPT_NOTSUPP, "Service option not supported" },
- { GSM_CAUSE_REQ_SERV_OPT_NOTSUB,
- "Requested service option not subscribed" },
- { GSM_CAUSE_SERV_OPT_TEMP_OOO,
- "Service option temporarily out of order" },
- { GSM_CAUSE_NSAPI_IN_USE, "NSAPI already used" },
- { GSM_CAUSE_DEACT_REGULAR, "Regular deactivation" },
- { GSM_CAUSE_QOS_NOT_ACCEPTED, "QoS not accepted" },
- { GSM_CAUSE_NET_FAIL, "Network Failure" },
- { GSM_CAUSE_REACT_RQD, "Reactivation required" },
- { GSM_CAUSE_FEATURE_NOTSUPP, "Feature not supported " },
- { GSM_CAUSE_INVALID_TRANS_ID, "Invalid transaction identifier" },
- { GSM_CAUSE_SEM_INCORR_MSG, "Semantically incorrect message" },
- { GSM_CAUSE_INV_MAND_INFO, "Invalid mandatory information" },
- { GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL,
- "Message type non-existant or not implemented" },
- { GSM_CAUSE_MSGT_INCOMP_P_STATE,
- "Message type not compatible with protocol state" },
- { GSM_CAUSE_IE_NOTEXIST_NOTIMPL,
- "Information element non-existent or not implemented" },
- { GSM_CAUSE_COND_IE_ERR, "Conditional IE error" },
- { GSM_CAUSE_MSG_INCOMP_P_STATE,
- "Message not compatible with protocol state " },
- { GSM_CAUSE_PROTO_ERR_UNSPEC, "Protocol error, unspecified" },
- { 0, NULL }
-};
-
-const struct value_string *gsm48_gsm_cause_names = gsm48_gsm_cause_names_;
-
-/* 10.5.5.2 */
-const struct value_string gprs_att_t_strs_[] = {
- { GPRS_ATT_T_ATTACH, "GPRS attach" },
- { GPRS_ATT_T_ATT_WHILE_IMSI, "GPRS attach while IMSI attached" },
- { GPRS_ATT_T_COMBINED, "Combined GPRS/IMSI attach" },
- { 0, NULL }
-};
-
-const struct value_string *gprs_att_t_strs = gprs_att_t_strs_;
-
-const struct value_string gprs_upd_t_strs_[] = {
- { GPRS_UPD_T_RA, "RA updating" },
- { GPRS_UPD_T_RA_LA, "combined RA/LA updating" },
- { GPRS_UPD_T_RA_LA_IMSI_ATT, "combined RA/LA updating + IMSI attach" },
- { GPRS_UPD_T_PERIODIC, "periodic updating" },
- { 0, NULL }
-};
-
-const struct value_string *gprs_upd_t_strs = gprs_upd_t_strs_;
-
-/* 10.5.5.5 */
-const struct value_string gprs_det_t_mo_strs_[] = {
- { GPRS_DET_T_MO_GPRS, "GPRS detach" },
- { GPRS_DET_T_MO_IMSI, "IMSI detach" },
- { GPRS_DET_T_MO_COMBINED, "Combined GPRS/IMSI detach" },
- { 0, NULL }
-};
-
-const struct value_string *gprs_det_t_mo_strs = gprs_det_t_mo_strs_;
-
-const struct value_string gprs_det_t_mt_strs_[] = {
- { GPRS_DET_T_MT_REATT_REQ, "re-attach required" },
- { GPRS_DET_T_MT_REATT_NOTREQ, "re-attach not required" },
- { GPRS_DET_T_MT_IMSI, "IMSI detach (after VLR failure)" },
- { 0, NULL }
-};
-
-const struct value_string *gprs_det_t_mt_strs = gprs_det_t_mt_strs_;
-
const struct value_string gprs_service_t_strs_[] = {
{ GPRS_SERVICE_T_SIGNALLING, "signalling" },
{ GPRS_SERVICE_T_DATA, "data" },
diff --git a/openbsc/src/gprs/gtphub.c b/openbsc/src/gprs/gtphub.c
index e8bd3aee7..58300ea13 100644
--- a/openbsc/src/gprs/gtphub.c
+++ b/openbsc/src/gprs/gtphub.c
@@ -1434,14 +1434,16 @@ static int gtphub_unmap_header_tei(struct gtphub_peer_port **to_port_p,
p->header_tei_rx, gtphub_port_str(from_port));
return -1;
}
- OSMO_ASSERT(*unmapped_from_tun);
+
+ if (unmapped_from_tun) {
+ OSMO_ASSERT(*unmapped_from_tun);
+ LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n",
+ gtphub_tunnel_str(*unmapped_from_tun));
+ }
uint32_t unmapped_tei = to->tei_orig;
set_tei(p, unmapped_tei);
- LOG(LOGL_DEBUG, "Unmapped TEI coming from: %s\n",
- gtphub_tunnel_str(*unmapped_from_tun));
-
/* May be NULL for an invalidated tunnel. */
*to_port_p = to->peer;
diff --git a/openbsc/src/gprs/gtphub_ares.c b/openbsc/src/gprs/gtphub_ares.c
index 947f2ddd5..667013b8b 100644
--- a/openbsc/src/gprs/gtphub_ares.c
+++ b/openbsc/src/gprs/gtphub_ares.c
@@ -55,7 +55,7 @@ struct ggsn_lookup {
struct gtphub *hub;
- char imsi_str[GSM_IMSI_LENGTH];
+ char imsi_str[GSM23003_IMSI_MAX_DIGITS+1];
char apn_ni_str[GSM_APN_LENGTH];
char apn_oi_str[GSM_APN_LENGTH];
int have_3dig_mnc;
diff --git a/openbsc/src/gprs/oap.c b/openbsc/src/gprs/oap.c
index 1426702dd..c7c97774d 100644
--- a/openbsc/src/gprs/oap.c
+++ b/openbsc/src/gprs/oap.c
@@ -20,10 +20,12 @@
*
*/
+#include <string.h>
+
+#include <osmocom/core/utils.h>
#include <osmocom/crypt/auth.h>
#include <openbsc/oap.h>
-#include <openbsc/utils.h>
#include <openbsc/debug.h>
#include <openbsc/oap_messages.h>
@@ -69,12 +71,19 @@ static int oap_evaluate_challenge(const struct oap_state *state,
const uint8_t *rx_autn,
uint8_t *tx_xres)
{
+ struct osmo_auth_vector vec;
+
+ struct osmo_sub_auth_data auth = {
+ .type = OSMO_AUTH_TYPE_UMTS,
+ .algo = OSMO_AUTH_ALG_MILENAGE,
+ };
+
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) {
+ switch (state->state) {
case OAP_UNINITIALIZED:
case OAP_DISABLED:
return -1;
@@ -82,13 +91,6 @@ static int oap_evaluate_challenge(const struct oap_state *state,
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));
@@ -103,7 +105,7 @@ static int oap_evaluate_challenge(const struct oap_state *state,
return -3;
}
- if (constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) {
+ if (osmo_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)));
@@ -117,11 +119,11 @@ static int oap_evaluate_challenge(const struct oap_state *state,
return 0;
}
-struct msgb *oap_encoded(const struct oap_message *oap_msg)
+struct msgb *oap_encoded(const struct osmo_oap_message *oap_msg)
{
struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__);
OSMO_ASSERT(msg);
- oap_encode(msg, oap_msg);
+ osmo_oap_encode(msg, oap_msg);
return msg;
}
@@ -129,12 +131,13 @@ struct msgb *oap_encoded(const struct oap_message *oap_msg)
* On error, return NULL. */
static struct msgb* oap_msg_register(uint16_t client_id)
{
+ struct osmo_oap_message oap_msg = {0};
+
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);
@@ -155,7 +158,7 @@ int oap_register(struct oap_state *state, struct msgb **msg_tx)
* On error, return NULL. */
static struct msgb* oap_msg_challenge_response(uint8_t *xres)
{
- struct oap_message oap_reply = {0};
+ struct osmo_oap_message oap_reply = {0};
oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT;
memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres));
@@ -164,10 +167,12 @@ static struct msgb* oap_msg_challenge_response(uint8_t *xres)
}
static int handle_challenge(struct oap_state *state,
- struct oap_message *oap_rx,
+ struct osmo_oap_message *oap_rx,
struct msgb **msg_tx)
{
int rc;
+ uint8_t xres[8];
+
if (!(oap_rx->rand_present && oap_rx->autn_present)) {
LOGP(DGPRS, LOGL_ERROR,
"OAP challenge incomplete (rand_present: %d, autn_present: %d)\n",
@@ -176,7 +181,6 @@ static int handle_challenge(struct oap_state *state,
goto failure;
}
- uint8_t xres[8];
rc = oap_evaluate_challenge(state,
oap_rx->rand,
oap_rx->autn,
@@ -201,17 +205,16 @@ failure:
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);
+ struct osmo_oap_message oap_msg = {0};
int rc = 0;
- struct oap_message oap_msg = {0};
+ *msg_tx = NULL;
OSMO_ASSERT(data);
- rc = oap_decode(data, data_len, &oap_msg);
+ rc = osmo_oap_decode(&oap_msg, data, data_len);
if (rc < 0) {
LOGP(DGPRS, LOGL_ERROR,
"Decoding OAP message failed with error '%s' (%d)\n",
diff --git a/openbsc/src/gprs/oap_messages.c b/openbsc/src/gprs/oap_messages.c
index eb520532a..d81723fd6 100644
--- a/openbsc/src/gprs/oap_messages.c
+++ b/openbsc/src/gprs/oap_messages.c
@@ -20,11 +20,10 @@
*
*/
+#include <osmocom/core/utils.h>
#include <openbsc/oap_messages.h>
#include <openbsc/debug.h>
-#include <openbsc/gprs_utils.h>
-#include <openbsc/utils.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/msgb.h>
@@ -32,8 +31,8 @@
#include <stdint.h>
-int oap_decode(const uint8_t *const_data, size_t data_len,
- struct oap_message *oap_msg)
+int osmo_oap_decode(struct osmo_oap_message *oap_msg,
+ const uint8_t *const_data, size_t data_len)
{
int rc;
uint8_t tag;
@@ -48,16 +47,16 @@ int oap_decode(const uint8_t *const_data, size_t data_len,
memset(oap_msg, 0, sizeof(*oap_msg));
/* message type */
- rc = gprs_shift_v_fixed(&data, &data_len, 1, &value);
+ rc = osmo_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);
+ oap_msg->message_type = osmo_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);
+ rc = osmo_shift_tlv(&data, &data_len, &tag, &value, &value_len);
if (rc < 0)
return -GMM_CAUSE_PROTO_ERR_UNSPEC;
@@ -72,7 +71,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len,
return -GMM_CAUSE_PROTO_ERR_UNSPEC;
}
- oap_msg->client_id = decode_big_endian(value, value_len);
+ oap_msg->client_id = osmo_decode_big_endian(value, value_len);
if (oap_msg->client_id == 0) {
LOGP(DGPRS, LOGL_NOTICE,
@@ -145,7 +144,7 @@ int oap_decode(const uint8_t *const_data, size_t data_len,
return 0;
}
-void oap_encode(struct msgb *msg, const struct oap_message *oap_msg)
+void osmo_oap_encode(struct msgb *msg, const struct osmo_oap_message *oap_msg)
{
uint8_t u8;
@@ -159,7 +158,8 @@ void oap_encode(struct msgb *msg, const struct oap_message *oap_msg)
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)));
+ osmo_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);
diff --git a/openbsc/src/gprs/sgsn_auth.c b/openbsc/src/gprs/sgsn_auth.c
index b83294d30..4b69a0d10 100644
--- a/openbsc/src/gprs/sgsn_auth.c
+++ b/openbsc/src/gprs/sgsn_auth.c
@@ -19,17 +19,18 @@
*
*/
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <openbsc/sgsn.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/gprs_gmm.h>
#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
const struct value_string auth_state_names[] = {
{ SGSN_AUTH_ACCEPTED, "accepted"},
{ SGSN_AUTH_REJECTED, "rejected"},
{ SGSN_AUTH_UNKNOWN, "unknown"},
+ { SGSN_AUTH_AUTHENTICATE, "authenticate" },
{ 0, NULL }
};
diff --git a/openbsc/src/gprs/sgsn_libgtp.c b/openbsc/src/gprs/sgsn_libgtp.c
index 2a3ee01f0..303fa887c 100644
--- a/openbsc/src/gprs/sgsn_libgtp.c
+++ b/openbsc/src/gprs/sgsn_libgtp.c
@@ -39,8 +39,8 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/crypt/auth.h>
#include <osmocom/gprs/gprs_bssgp.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/signal.h>
#include <openbsc/debug.h>
#include <openbsc/sgsn.h>
diff --git a/openbsc/src/gprs/sgsn_vty.c b/openbsc/src/gprs/sgsn_vty.c
index 00c2761d6..02c0f318c 100644
--- a/openbsc/src/gprs/sgsn_vty.c
+++ b/openbsc/src/gprs/sgsn_vty.c
@@ -27,13 +27,13 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
#include <openbsc/sgsn.h>
#include <osmocom/gprs/gprs_ns.h>
#include <openbsc/gprs_sgsn.h>
#include <openbsc/vty.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/gprs_gsup_client.h>
#include <osmocom/vty/command.h>
@@ -613,11 +613,11 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr,
vty_out(vty, " seq # : %d, ",
at->key_seq);
vty_out(vty, " RAND : %s, ",
- osmo_hexdump(at->rand, sizeof(at->rand)));
+ osmo_hexdump(at->vec.rand, sizeof(at->vec.rand)));
vty_out(vty, " SRES : %s, ",
- osmo_hexdump(at->sres, sizeof(at->sres)));
+ osmo_hexdump(at->vec.sres, sizeof(at->vec.sres)));
vty_out(vty, " Kc : %s%s",
- osmo_hexdump(at->kc, sizeof(at->kc)),
+ osmo_hexdump(at->vec.kc, sizeof(at->vec.kc)),
VTY_NEWLINE);
}
@@ -704,17 +704,17 @@ DEFUN(update_subscr_insert_auth_triplet, update_subscr_insert_auth_triplet_cmd,
OSMO_ASSERT(subscr->sgsn_data);
- if (osmo_hexparse(sres_str, &at.sres[0], sizeof(at.sres)) < 0) {
+ if (osmo_hexparse(sres_str, &at.vec.sres[0], sizeof(at.vec.sres)) < 0) {
vty_out(vty, "%% invalid SRES value '%s'%s",
sres_str, VTY_NEWLINE);
goto failed;
}
- if (osmo_hexparse(rand_str, &at.rand[0], sizeof(at.rand)) < 0) {
+ if (osmo_hexparse(rand_str, &at.vec.rand[0], sizeof(at.vec.rand)) < 0) {
vty_out(vty, "%% invalid RAND value '%s'%s",
rand_str, VTY_NEWLINE);
goto failed;
}
- if (osmo_hexparse(kc_str, &at.kc[0], sizeof(at.kc)) < 0) {
+ if (osmo_hexparse(kc_str, &at.vec.kc[0], sizeof(at.vec.kc)) < 0) {
vty_out(vty, "%% invalid Kc value '%s'%s",
kc_str, VTY_NEWLINE);
goto failed;
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index c05e2f94f..3afc4c497 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -2598,7 +2598,7 @@ int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx)
fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC,
trx->bts->nr, trx->nr, 0xff);
- return abis_nm_sendmsg(trx->bts, msg);
+ return abis_nm_sendmsg_direct(trx->bts, msg);
}
int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class,
diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c
index 512576455..36a663824 100644
--- a/openbsc/src/libbsc/abis_rsl.c
+++ b/openbsc/src/libbsc/abis_rsl.c
@@ -1345,8 +1345,6 @@ static void t3109_expired(void *data)
rsl_rf_chan_release(lchan, 1, SACCH_NONE);
}
-#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
-
/* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
unsigned int num_req_refs,
diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c
index d9c34d035..a72f15121 100644
--- a/openbsc/src/libbsc/bsc_api.c
+++ b/openbsc/src/libbsc/bsc_api.c
@@ -395,11 +395,13 @@ int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, in
if (handle_new_assignment(conn, chan_mode, full_rate) != 0)
goto error;
} else {
- LOGP(DMSC, LOGL_NOTICE,
- "Sending ChanModify for speech %d %d\n", chan_mode, full_rate);
if (chan_mode == GSM48_CMODE_SPEECH_AMR)
handle_mr_config(conn, conn->lchan, full_rate);
+ LOGP(DMSC, LOGL_NOTICE,
+ "Sending ChanModify for speech: %s on channel %s\n",
+ get_value_string(gsm48_chan_mode_names, chan_mode),
+ get_value_string(gsm_chan_t_names, conn->lchan->type));
gsm48_lchan_modify(conn->lchan, chan_mode);
}
diff --git a/openbsc/src/libbsc/bsc_ctrl_commands.c b/openbsc/src/libbsc/bsc_ctrl_commands.c
index b6b1c9a8b..7e8479734 100644
--- a/openbsc/src/libbsc/bsc_ctrl_commands.c
+++ b/openbsc/src/libbsc/bsc_ctrl_commands.c
@@ -90,7 +90,17 @@ static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
if (!is_ipaccess_bts(bts))
continue;
- ipaccess_drop_oml(bts);
+ /*
+ * The ip.access nanoBTS seems to be unrelaible on BSSGP
+ * so let's us just reboot it. For the sysmoBTS we can just
+ * restart the process as all state is gone.
+ */
+ if (!is_sysmobts_v2(bts) && strcmp(cmd->value, "restart") == 0) {
+ struct gsm_bts_trx *trx;
+ llist_for_each_entry_reverse(trx, &bts->trx_list, list)
+ abis_nm_ipaccess_restart(trx);
+ } else
+ ipaccess_drop_oml(bts);
}
cmd->reply = "Tried to drop the BTS";
diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c
index 3ec3aa837..7abc4c666 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -140,6 +140,7 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx)
gen_si[n_si++] = SYSINFO_TYPE_2;
gen_si[n_si++] = SYSINFO_TYPE_2bis;
gen_si[n_si++] = SYSINFO_TYPE_2ter;
+ gen_si[n_si++] = SYSINFO_TYPE_2quater;
gen_si[n_si++] = SYSINFO_TYPE_3;
gen_si[n_si++] = SYSINFO_TYPE_4;
@@ -191,9 +192,9 @@ int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx)
return 0;
err_out:
- LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u, most likely "
- "a problem with neighbor cell list generation\n",
- get_value_string(osmo_sitype_strs, i), bts->nr);
+ LOGP(DRR, LOGL_ERROR, "Cannot generate SI%s for BTS %u: error <%s>,"
+ "most likely a problem with neighbor cell list generation\n",
+ get_value_string(osmo_sitype_strs, i), bts->nr, strerror(-rc));
return rc;
}
@@ -373,6 +374,9 @@ static int bootstrap_bts(struct gsm_bts *bts)
{
int i, n;
+ if (!bts->model)
+ return -EFAULT;
+
if (bts->model->start && !bts->model->started) {
int ret = bts->model->start(bts->network);
if (ret < 0)
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index 049f73a62..864907515 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -603,6 +603,29 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
}
}
+ for (i = 0; i < MAX_EARFCN_LIST; i++) {
+ if (bts->si_common.si2quater_neigh_list.arfcn[i] !=
+ OSMO_EARFCN_INVALID) {
+ vty_out(vty, " si2quater neighbor-list add earfcn %u threshold %u",
+ bts->si_common.si2quater_neigh_list.arfcn[i],
+ bts->si_common.si2quater_neigh_list.thresh_hi);
+ if (bts->si_common.si2quater_neigh_list.meas_bw[i] !=
+ OSMO_EARFCN_MEAS_INVALID)
+ vty_out(vty, " %u",
+ bts->si_common.si2quater_neigh_list.meas_bw[i]);
+
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
+ }
+
+ for (i = 0; i < bts->si_common.uarfcn_length; i++) {
+ vty_out(vty, " si2quater neighbor-list add uarfcn %u %u %u%s",
+ bts->si_common.data.uarfcn_list[i],
+ bts->si_common.data.scramble_list[i] & ~(1 << 9),
+ (bts->si_common.data.scramble_list[i] >> 9) & 1,
+ VTY_NEWLINE);
+ }
+
vty_out(vty, " codec-support fr");
if (bts->codec.hr)
vty_out(vty, " hr");
@@ -2265,6 +2288,112 @@ DEFUN(cfg_bts_neigh, cfg_bts_neigh_cmd,
return CMD_SUCCESS;
}
+
+DEFUN(cfg_bts_si2quater_neigh_add, cfg_bts_si2quater_neigh_add_cmd,
+ "si2quater neighbor-list add earfcn <0-65535> threshold <0-31> "
+ "[<0-7>]", "SI2quater Neighbor List\n"
+ "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n"
+ "EARFCN of neighbor\n" "EARFCN of neighbor\n" "threshold high bits\n"
+ "threshold high bits\n" "measurement bandwidth\n")
+{
+ struct gsm_bts *bts = vty->index;
+ struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
+ uint16_t arfcn = atoi(argv[0]);
+ uint8_t meas = OSMO_EARFCN_MEAS_INVALID, thresh = atoi(argv[1]);
+ int r;
+
+ if (3 == argc)
+ meas = atoi(argv[2]);
+
+ r = osmo_earfcn_add(e, arfcn, meas);
+
+ if (r < 0) {
+ vty_out(vty, "Unable to add arfcn %u: %s%s", arfcn, strerror(r),
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (si2q_size_check(bts)) {
+ if (e->thresh_hi && thresh != e->thresh_hi)
+ vty_out(vty, "Warning: multiple thresholds are not "
+ "supported, overriding previous threshold %u%s",
+ e->thresh_hi, VTY_NEWLINE);
+
+ e->thresh_hi = thresh;
+ return CMD_SUCCESS;
+ }
+ vty_out(vty, "Warning: not enough space in si2quater for a given arfcn%s"
+ , VTY_NEWLINE);
+ osmo_earfcn_del(e, arfcn);
+ return CMD_WARNING;
+}
+
+DEFUN(cfg_bts_si2quater_neigh_del, cfg_bts_si2quater_neigh_del_cmd,
+ "si2quater neighbor-list del earfcn <0-65535>",
+ "SI2quater Neighbor List\n"
+ "SI2quater Neighbor List\n"
+ "Delete from SI2quater manual neighbor list\n"
+ "EARFCN of neighbor\n"
+ "EARFCN\n")
+{
+ struct gsm_bts *bts = vty->index;
+ struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
+ uint16_t arfcn = atoi(argv[0]);
+ int r = osmo_earfcn_del(e, arfcn);
+ if (r < 0) {
+ vty_out(vty, "Unable to delete arfcn %u: %s%s", arfcn,
+ strerror(-r), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_si2quater_uarfcn_add, cfg_bts_si2quater_uarfcn_add_cmd,
+ "si2quater neighbor-list add uarfcn <0-16383> <0-511> <0-1>",
+ "SI2quater Neighbor List\n"
+ "SI2quater Neighbor List\n" "Add to manual SI2quater neighbor list\n"
+ "UARFCN of neighbor\n" "UARFCN of neighbor\n" "scrambling code\n"
+ "diversity bit\n")
+{
+ struct gsm_bts *bts = vty->index;
+ uint16_t arfcn = atoi(argv[0]), scramble = atoi(argv[1]);
+
+ switch(bts_uarfcn_add(bts, arfcn, scramble, atoi(argv[2]))) {
+ case -ENOMEM:
+ vty_out(vty, "Unable to add arfcn: max number of UARFCNs (%u) "
+ "reached%s", MAX_EARFCN_LIST, VTY_NEWLINE);
+ case -ENOSPC:
+ vty_out(vty, "Warning: not enough space in si2quater for a "
+ "given arfcn%s", VTY_NEWLINE);
+ case -EADDRINUSE:
+ vty_out(vty, "Unable to add arfcn: (%u, %u) is already added%s",
+ arfcn, scramble, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_si2quater_uarfcn_del, cfg_bts_si2quater_uarfcn_del_cmd,
+ "si2quater neighbor-list del uarfcn <0-16383> <0-511>",
+ "SI2quater Neighbor List\n"
+ "SI2quater Neighbor List\n"
+ "Delete from SI2quater manual neighbor list\n"
+ "UARFCN of neighbor\n"
+ "UARFCN\n"
+ "scrambling code\n")
+{
+ struct gsm_bts *bts = vty->index;
+
+ if (bts_uarfcn_del(bts, atoi(argv[0]), atoi(argv[1])) < 0) {
+ vty_out(vty, "Unable to delete uarfcn: pair not found%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_bts_si5_neigh, cfg_bts_si5_neigh_cmd,
"si5 neighbor-list (add|del) arfcn <0-1023>",
"SI5 Neighbor List\n"
@@ -3118,6 +3247,44 @@ DEFUN(drop_bts,
return CMD_SUCCESS;
}
+DEFUN(restart_bts, restart_bts_cmd,
+ "restart-bts <0-65535>",
+ "Restart ip.access nanoBTS through OML\n"
+ "BTS Number\n")
+{
+ struct gsm_network *gsmnet;
+ struct gsm_bts_trx *trx;
+ struct gsm_bts *bts;
+ unsigned int bts_nr;
+
+ gsmnet = gsmnet_from_vty(vty);
+
+ bts_nr = atoi(argv[0]);
+ if (bts_nr >= gsmnet->num_bts) {
+ vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
+ gsmnet->num_bts, bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts = gsm_bts_num(gsmnet, bts_nr);
+ if (!bts) {
+ vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!is_ipaccess_bts(bts) || is_sysmobts_v2(bts)) {
+ vty_out(vty, "This command only works for ipaccess nanoBTS.%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ /* go from last TRX to c0 */
+ llist_for_each_entry_reverse(trx, &bts->trx_list, list)
+ abis_nm_ipaccess_restart(trx);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(smscb_cmd, smscb_cmd_cmd,
"bts <0-255> smscb-command <1-4> HEXSTRING",
"BTS related commands\n" "BTS Number\n"
@@ -3320,6 +3487,10 @@ int bsc_vty_init(const struct log_info *cat, struct gsm_network *network)
install_element(BTS_NODE, &cfg_bts_neigh_mode_cmd);
install_element(BTS_NODE, &cfg_bts_neigh_cmd);
install_element(BTS_NODE, &cfg_bts_si5_neigh_cmd);
+ install_element(BTS_NODE, &cfg_bts_si2quater_neigh_add_cmd);
+ install_element(BTS_NODE, &cfg_bts_si2quater_neigh_del_cmd);
+ install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_add_cmd);
+ install_element(BTS_NODE, &cfg_bts_si2quater_uarfcn_del_cmd);
install_element(BTS_NODE, &cfg_bts_excl_rf_lock_cmd);
install_element(BTS_NODE, &cfg_bts_no_excl_rf_lock_cmd);
install_element(BTS_NODE, &cfg_bts_force_comb_si_cmd);
@@ -3380,6 +3551,7 @@ int bsc_vty_init(const struct log_info *cat, struct gsm_network *network)
install_element(TS_NODE, &cfg_ts_e1_subslot_cmd);
install_element(ENABLE_NODE, &drop_bts_cmd);
+ install_element(ENABLE_NODE, &restart_bts_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
install_element(ENABLE_NODE, &smscb_cmd_cmd);
diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c
index fd39c1c43..520a40ffc 100644
--- a/openbsc/src/libbsc/gsm_04_08_utils.c
+++ b/openbsc/src/libbsc/gsm_04_08_utils.c
@@ -440,7 +440,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan,
/*
* fill the channel information element, this code
* should probably be shared with rsl_rx_chan_rqd(),
- * gsm48_tx_chan_mode_modify. But beware that 10.5.2.5
+ * gsm48_lchan_modify(). But beware that 10.5.2.5
* 10.5.2.5.a have slightly different semantic for
* the chan_desc. But as long as multi-slot configurations
* are not used we seem to be fine.
@@ -465,7 +465,7 @@ int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan,
}
/* 9.1.5 Channel mode modify: Modify the mode on the MS side */
-int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode)
+int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t mode)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CHN MOD");
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -490,17 +490,6 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, uint8_t mode)
return gsm48_sendmsg(msg);
}
-int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode)
-{
- int rc;
-
- rc = gsm48_tx_chan_mode_modify(lchan, lchan_mode);
- if (rc < 0)
- return rc;
-
- return rc;
-}
-
int gsm48_rx_rr_modif_ack(struct msgb *msg)
{
int rc;
diff --git a/openbsc/src/libbsc/rest_octets.c b/openbsc/src/libbsc/rest_octets.c
index 4545794a9..aa286e578 100644
--- a/openbsc/src/libbsc/rest_octets.c
+++ b/openbsc/src/libbsc/rest_octets.c
@@ -24,10 +24,15 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <stdbool.h>
+#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <osmocom/core/bitvec.h>
+#include <osmocom/gsm/bitvec_gsm.h>
#include <openbsc/rest_octets.h>
+#include <openbsc/arfcn_range_encode.h>
+#include <openbsc/system_information.h>
/* generate SI1 rest octets */
int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
@@ -53,6 +58,255 @@ int rest_octets_si1(uint8_t *data, uint8_t *nch_pos, int is1800_net)
return bv.data_len;
}
+/* Append Repeated E-UTRAN Neighbour Cell to bitvec:
+ * see 3GPP TS 44.018 Table 10.5.2.33b.1
+ */
+static inline void append_eutran_neib_cell(struct bitvec *bv,
+ const struct osmo_earfcn_si2q *e)
+{
+ unsigned i;
+ for (i = 0; i < e->length; i++) {
+ if (e->arfcn[i] != OSMO_EARFCN_INVALID) {
+ bitvec_set_bit(bv, 1); /* EARFCN: */
+ bitvec_set_uint(bv, e->arfcn[i], 16);
+
+ if (OSMO_EARFCN_MEAS_INVALID == e->meas_bw[i])
+ bitvec_set_bit(bv, 0);
+ else {
+ /* Measurement Bandwidth: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->meas_bw[i], 3);
+ }
+ }
+ }
+
+ /* stop bit - end of EARFCN + Measurement Bandwidth sequence */
+ bitvec_set_bit(bv, 0);
+
+ if (e->prio_valid) {
+ /* E-UTRAN_PRIORITY: 3GPP TS 45.008*/
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->prio, 3);
+ } else
+ bitvec_set_bit(bv, 0);
+
+ /* THRESH_E-UTRAN_high */
+ bitvec_set_uint(bv, e->thresh_hi, 5);
+
+ if (e->thresh_lo_valid) {
+ /* THRESH_E-UTRAN_low: */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->thresh_lo, 5);
+ } else
+ bitvec_set_bit(bv, 0);
+
+ if (e->qrxlm_valid) {
+ /* E-UTRAN_QRXLEVMIN: */
+ bitvec_set_bit(bv, 1);
+ bitvec_set_uint(bv, e->qrxlm, 5);
+ } else
+ bitvec_set_bit(bv, 0);
+}
+
+static inline void append_earfcn(struct bitvec *bv,
+ const struct osmo_earfcn_si2q *e)
+{
+ /* Additions in Rel-5: */
+ bitvec_set_bit(bv, H);
+ /* No 3G Additional Measurement Param. Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No 3G ADDITIONAL MEASUREMENT Param. Descr. 2 */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-6: */
+ bitvec_set_bit(bv, H);
+ /* 3G_CCN_ACTIVE */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-7: */
+ bitvec_set_bit(bv, H);
+ /* No 700_REPORTING_OFFSET */
+ bitvec_set_bit(bv, 0);
+ /* No 810_REPORTING_OFFSET */
+ bitvec_set_bit(bv, 0);
+ /* Additions in Rel-8: */
+ bitvec_set_bit(bv, H);
+
+ /* Priority and E-UTRAN Parameters Description */
+ bitvec_set_bit(bv, 1);
+
+ /* No Serving Cell Priority Parameters Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No 3G Priority Parameters Description */
+ bitvec_set_bit(bv, 0);
+ /* E-UTRAN Parameters Description */
+ bitvec_set_bit(bv, 1);
+
+ /* E-UTRAN_CCN_ACTIVE */
+ bitvec_set_bit(bv, 0);
+ /* E-UTRAN_Start: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+ /* E-UTRAN_Stop: 9.1.54 */
+ bitvec_set_bit(bv, 1);
+
+ /* No E-UTRAN Measurement Parameters Descr. */
+ bitvec_set_bit(bv, 0);
+ /* No GPRS E-UTRAN Measurement Param. Descr. */
+ bitvec_set_bit(bv, 0);
+
+ /* Note: each of next 3 "repeated" structures might be repeated any
+ (0, 1, 2...) times - we only support 1 and 0 */
+
+ /* Repeated E-UTRAN Neighbour Cells */
+ bitvec_set_bit(bv, 1);
+
+ /* Note: we don't support different EARFCN arrays each with different
+ priority, threshold etc. */
+ append_eutran_neib_cell(bv, e);
+
+ /* stop bit - end of Repeated E-UTRAN Neighbour Cells sequence: */
+ bitvec_set_bit(bv, 0);
+
+ /* Note: following 2 repeated structs are not supported ATM */
+ /* stop bit - end of Repeated E-UTRAN Not Allowed Cells sequence: */
+ bitvec_set_bit(bv, 0);
+ /* stop bit - end of Repeated E-UTRAN PCID to TA mapping sequence: */
+ bitvec_set_bit(bv, 0);
+
+ /* Priority and E-UTRAN Parameters Description ends here */
+ /* No 3G CSG Description */
+ bitvec_set_bit(bv, 0);
+ /* No E-UTRAN CSG Description */
+ bitvec_set_bit(bv, 0);
+ /* No Additions in Rel-9: */
+ bitvec_set_bit(bv, L);
+}
+
+static inline void append_uarfcn(struct bitvec *bv, const uint16_t *u,
+ const uint16_t *sc, size_t length)
+{
+ int f0_inc, i, arfcns_used, w[RANGE_ENC_MAX_ARFCNS], a[length];
+ uint8_t chan_list[16] = {0};
+
+ /* 3G Neighbour Cell Description */
+ bitvec_set_bit(bv, 1);
+ /* No Index_Start_3G */
+ bitvec_set_bit(bv, 0);
+ /* No Absolute_Index_Start_EMR */
+ bitvec_set_bit(bv, 0);
+
+ /* UTRAN FDD Description */
+ bitvec_set_bit(bv, 1);
+ /* No Bandwidth_FDD */
+ bitvec_set_bit(bv, 0);
+
+ memset(w, 0, sizeof(w));
+ for (i = 0; i < length; i++)
+ a[i] = sc[i];
+
+ /* Note: we do not support repeating Neighbour Cells ATM */
+ /* Repeated UTRAN FDD Neighbour Cells */
+ bitvec_set_bit(bv, 1);
+
+ /* FDD-ARFCN */
+ bitvec_set_bit(bv, 0);
+ /* Note: we do not support multiple UARFCN values ATM: */
+ bitvec_set_uint(bv, u[0], 14);
+
+ arfcns_used = range_enc_filter_arfcns(a, length, 0, &f0_inc);
+ range_enc_arfcns(ARFCN_RANGE_1024, a, arfcns_used, w, 0);
+ range_enc_range1024(chan_list, 0, f0_inc, w);
+
+ /* FDD_Indic0: parameter value '0000000000' is not a member of the set */
+ bitvec_set_bit(bv, f0_inc);
+ /* NR_OF_FDD_CELLS */
+ bitvec_set_uint(bv, length, 5);
+
+ i = bv->cur_bit;
+ bitvec_add_range1024(bv, (struct gsm48_range_1024 *)chan_list);
+ bv->cur_bit = i + range1024_p(length);
+
+ /* stop bit - end of Repeated UTRAN FDD Neighbour Cells */
+ bitvec_set_bit(bv, 0);
+
+ /* UTRAN TDD Description */
+ bitvec_set_bit(bv, 0);
+}
+
+/* generate SI2quater rest octets: 3GPP TS 44.018 § 10.5.2.33b */
+int rest_octets_si2quater(uint8_t *data, const struct osmo_earfcn_si2q *e,
+ const uint16_t *u, const uint16_t *sc, size_t u_len)
+{
+ unsigned sz;
+ struct bitvec bv;
+ bv.data = data;
+ bv.data_len = 20;
+ bitvec_zero(&bv);
+
+ /* BA_IND */
+ bitvec_set_bit(&bv, 1);
+ /* 3G_BA_IND */
+ bitvec_set_bit(&bv, 1);
+ /* MP_CHANGE_MARK */
+ bitvec_set_bit(&bv, 0);
+
+ /* we do not support multiple si2quater messages at the moment: */
+ /* SI2quater_INDEX */
+ bitvec_set_uint(&bv, 0, 4);
+ /* SI2quater_COUNT */
+ bitvec_set_uint(&bv, 0, 4);
+
+ /* No Measurement_Parameters Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_Real Time Difference Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_BSIC Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_REPORT PRIORITY Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_MEASUREMENT_Parameters Description */
+ bitvec_set_bit(&bv, 0);
+ /* No NC Measurement Parameters */
+ bitvec_set_bit(&bv, 0);
+ /* No extension (length) */
+ bitvec_set_bit(&bv, 0);
+
+ if (u_len) {
+ sz = uarfcn_size(u, sc, u_len);
+ /* Even if we do not append EARFCN we still need to set 3 bits */
+ if (sz + bv.cur_bit + 3 > SI2Q_MAX_LEN) {
+ LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to "
+ "add UARFCNs bits, current %u + required %u + "
+ "reminder %u > max %u\n", bv.cur_bit, sz, 3,
+ SI2Q_MAX_LEN);
+ return -ENOMEM;
+ }
+ append_uarfcn(&bv, u, sc, u_len);
+ } else { /* No 3G Neighbour Cell Description */
+ bitvec_set_bit(&bv, 0);
+ }
+
+ /* No 3G Measurement Parameters Description */
+ bitvec_set_bit(&bv, 0);
+ /* No GPRS_3G_MEASUREMENT Parameters Descr. */
+ bitvec_set_bit(&bv, 0);
+
+ if (e) {
+ sz = earfcn_size(e);
+ if (sz + bv.cur_bit > SI2Q_MAX_LEN) {
+ LOGP(DRR, LOGL_ERROR, "SI2quater: not enough memory to "
+ "add EARFCNs bits, current %u + required %u > max "
+ "%u\n", bv.cur_bit, sz, SI2Q_MAX_LEN);
+ return -ENOMEM;
+ }
+ append_earfcn(&bv, e);
+ } else {
+ /* No Additions in Rel-5: */
+ bitvec_set_bit(&bv, L);
+ }
+
+ bitvec_spare_padding(&bv, (bv.data_len * 8) - 1);
+ return bv.data_len;
+}
+
/* Append selection parameters to bitvec */
static void append_selection_params(struct bitvec *bv,
const struct gsm48_si_selection_params *sp)
@@ -129,6 +383,15 @@ int rest_octets_si3(uint8_t *data, const struct gsm48_si_ro_info *si3)
/* GPRS Indicator */
append_gprs_ind(&bv, &si3->gprs_ind);
+ /* 3G Early Classmark Sending Restriction controlled by
+ * early_cm_ctrl above */
+ bitvec_set_bit(&bv, H);
+
+ if (si3->si2quater_indicator) {
+ bitvec_set_bit(&bv, H); /* indicator struct present */
+ bitvec_set_uint(&bv, 0, 1); /* message is sent on BCCH Norm */
+ }
+
bitvec_spare_padding(&bv, (bv.data_len*8)-1);
return bv.data_len;
}
diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c
index 1ee9d41c2..0d96621b2 100644
--- a/openbsc/src/libbsc/system_information.c
+++ b/openbsc/src/libbsc/system_information.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
+#include <stdbool.h>
#include <osmocom/core/bitvec.h>
#include <osmocom/core/utils.h>
@@ -67,8 +68,160 @@ static int is_dcs_net(const struct gsm_bts *bts)
return 1;
}
-static int use_arfcn(const struct gsm_bts *bts, const int bis, const int ter,
- const int pgsm, const int arfcn)
+/* Return p(n) for given NR_OF_TDD_CELLS - see Table 9.1.54.1a, 3GPP TS 44.018 */
+unsigned range1024_p(unsigned n)
+{
+ switch (n) {
+ case 0: return 0;
+ case 1: return 10;
+ case 2: return 19;
+ case 3: return 28;
+ case 4: return 36;
+ case 5: return 44;
+ case 6: return 52;
+ case 7: return 60;
+ case 8: return 67;
+ case 9: return 74;
+ case 10: return 81;
+ case 11: return 88;
+ case 12: return 95;
+ case 13: return 102;
+ case 14: return 109;
+ case 15: return 116;
+ case 16: return 122;
+ default: return 0;
+ }
+}
+
+/* Return q(m) for given NR_OF_TDD_CELLS - see Table 9.1.54.1b, 3GPP TS 44.018 */
+unsigned range512_q(unsigned m)
+{
+ switch (m) {
+ case 0: return 0;
+ case 1: return 9;
+ case 2: return 17;
+ case 3: return 25;
+ case 4: return 32;
+ case 5: return 39;
+ case 6: return 46;
+ case 7: return 53;
+ case 8: return 59;
+ case 9: return 65;
+ case 10: return 71;
+ case 11: return 77;
+ case 12: return 83;
+ case 13: return 89;
+ case 14: return 95;
+ case 15: return 101;
+ case 16: return 106;
+ case 17: return 111;
+ case 18: return 116;
+ case 19: return 121;
+ case 20: return 126;
+ default: return 0;
+ }
+}
+
+unsigned earfcn_size(const struct osmo_earfcn_si2q *e)
+{
+ /* account for all the constant bits in append_earfcn() */
+ return 25 + osmo_earfcn_bit_size(e);
+}
+
+unsigned uarfcn_size(const uint16_t *u, const uint16_t *sc, size_t u_len)
+{
+ /*account for all the constant bits in append_uarfcn() */
+ return 29 + range1024_p(u_len);
+}
+
+bool si2q_size_check(const struct gsm_bts *bts)
+{
+ const struct osmo_earfcn_si2q *e = &bts->si_common.si2quater_neigh_list;
+ const uint16_t *u = bts->si_common.data.uarfcn_list,
+ *sc = bts->si_common.data.scramble_list;
+ size_t len = bts->si_common.uarfcn_length;
+ unsigned e_sz = e ? earfcn_size(e) : 1,
+ u_sz = len ? uarfcn_size(u, sc, len) : 1;
+ /* 2 bits are used in between UARFCN and EARFCN structs */
+ if (SI2Q_MIN_LEN + u_sz + 2 + e_sz > SI2Q_MAX_LEN)
+ return false;
+ return true;
+}
+
+/* 3GPP TS 44.018, Table 9.1.54.1 - prepend diversity bit to scrambling code */
+uint16_t encode_fdd(uint16_t scramble, bool diversity)
+{
+ if (diversity)
+ return scramble | (1 << 9);
+ return scramble;
+}
+
+int bts_uarfcn_del(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble)
+{
+ uint16_t sc0 = encode_fdd(scramble, false), sc1 = encode_fdd(scramble, true),
+ *ual = bts->si_common.data.uarfcn_list,
+ *scl = bts->si_common.data.scramble_list;
+ size_t len = bts->si_common.uarfcn_length, i;
+ for (i = 0; i < len; i++) {
+ if (arfcn == ual[i] && (sc0 == scl[i] || sc1 == scl[i])) {
+ /* we rely on the assumption that (uarfcn, scramble)
+ tuple is unique in the lists */
+ if (i != len - 1) { /* move the tail if necessary */
+ memmove(ual + i, ual + i + 1, 2 * (len - i + 1));
+ memmove(scl + i, scl + i + 1, 2 * (len - i + 1));
+ }
+ break;
+ }
+ }
+
+ if (i == len)
+ return -EINVAL;
+
+ bts->si_common.uarfcn_length--;
+ return 0;
+}
+
+int bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn, uint16_t scramble,
+ bool diversity)
+{
+ size_t len = bts->si_common.uarfcn_length, i, k;
+ uint16_t scr, chk,
+ *ual = bts->si_common.data.uarfcn_list,
+ *scl = bts->si_common.data.scramble_list,
+ scramble1 = encode_fdd(scramble, true),
+ scramble0 = encode_fdd(scramble, false);
+
+ scr = diversity ? scramble1 : scramble0;
+ chk = diversity ? scramble0 : scramble1;
+
+ if (len == MAX_EARFCN_LIST)
+ return -ENOMEM;
+
+ for (i = 0, k = 0; i < len; i++) {
+ if (arfcn == ual[i] && (scr == scl[i] || chk == scl[i]))
+ return -EADDRINUSE;
+ if (scr > scl[i])
+ k = i + 1;
+ }
+ /* we keep lists sorted by scramble code:
+ insert into appropriate position and move the tail */
+ if (len - k) {
+ memmove(ual + k + 1, ual + k, (len - k) * 2);
+ memmove(scl + k + 1, scl + k, (len - k) * 2);
+ }
+ ual[k] = arfcn;
+ scl[k] = scr;
+ bts->si_common.uarfcn_length++;
+
+ if (si2q_size_check(bts))
+ return 0;
+
+ bts_uarfcn_del(bts, arfcn, scramble);
+ return -ENOSPC;
+}
+
+static inline int use_arfcn(const struct gsm_bts *bts, const bool bis, const bool ter,
+ const bool pgsm, const int arfcn)
{
if (bts->force_combined_si)
return !bis && !ter;
@@ -135,9 +288,9 @@ static int freq_list_bmrel_set_arfcn(uint8_t *chan_list, unsigned int arfcn)
}
/* generate a variable bitmap */
-static int enc_freq_lst_var_bitmap(uint8_t *chan_list,
+static inline int enc_freq_lst_var_bitmap(uint8_t *chan_list,
struct bitvec *bv, const struct gsm_bts *bts,
- int bis, int ter, int min, int pgsm)
+ bool bis, bool ter, int min, bool pgsm)
{
int i;
@@ -164,9 +317,9 @@ static int enc_freq_lst_var_bitmap(uint8_t *chan_list,
}
/* generate a frequency list with the range 512 format */
-static int enc_freq_lst_range(uint8_t *chan_list,
+static inline int enc_freq_lst_range(uint8_t *chan_list,
struct bitvec *bv, const struct gsm_bts *bts,
- int bis, int ter, int pgsm)
+ bool bis, bool ter, bool pgsm)
{
int arfcns[RANGE_ENC_MAX_ARFCNS];
int w[RANGE_ENC_MAX_ARFCNS];
@@ -226,15 +379,15 @@ static int enc_freq_lst_range(uint8_t *chan_list,
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
- const struct gsm_bts *bts, int bis, int ter)
+ const struct gsm_bts *bts, bool bis, bool ter)
{
- int i, rc, min = -1, max = -1, pgsm = 0, arfcns = 0;
-
+ int i, rc, min = -1, max = -1, arfcns = 0;
+ bool pgsm = false;
memset(chan_list, 0, 16);
if (bts->band == GSM_BAND_900
&& bts->c0->arfcn >= 1 && bts->c0->arfcn <= 124)
- pgsm = 1;
+ pgsm = true;
/* P-GSM-only handsets only support 'bit map 0 format' */
if (!bis && !ter && pgsm) {
chan_list[0] = 0;
@@ -327,12 +480,12 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv,
}
/* then we generate a GSM 04.08 frequency list from the bitvec */
- return bitvec2freq_list(chan_list, bv, bts, 0, 0);
+ return bitvec2freq_list(chan_list, bv, bts, false, false);
}
/* generate a cell channel list as per Section 10.5.2.1b of 04.08 */
static int generate_bcch_chan_list(uint8_t *chan_list, struct gsm_bts *bts,
- int si5, int bis, int ter)
+ bool si5, bool bis, bool ter)
{
struct gsm_bts *cur_bts;
struct bitvec *bv;
@@ -422,7 +575,7 @@ static int generate_si2(uint8_t *output, struct gsm_bts *bts)
si2->header.skip_indicator = 0;
si2->header.system_information = GSM48_MT_RR_SYSINFO_2;
- rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, 0, 0, 0);
+ rc = generate_bcch_chan_list(si2->bcch_frequency_list, bts, false, false, false);
if (rc < 0)
return rc;
list_arfcn(si2->bcch_frequency_list, 0xce,
@@ -448,7 +601,7 @@ static int generate_si2bis(uint8_t *output, struct gsm_bts *bts)
si2b->header.skip_indicator = 0;
si2b->header.system_information = GSM48_MT_RR_SYSINFO_2bis;
- rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, 0, 1, 0);
+ rc = generate_bcch_chan_list(si2b->bcch_frequency_list, bts, false, true, false);
if (rc < 0)
return rc;
n = list_arfcn(si2b->bcch_frequency_list, 0xce,
@@ -482,7 +635,7 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts)
si2t->header.skip_indicator = 0;
si2t->header.system_information = GSM48_MT_RR_SYSINFO_2ter;
- rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, 0, 0, 1);
+ rc = generate_bcch_chan_list(si2t->ext_bcch_frequency_list, bts, false, false, true);
if (rc < 0)
return rc;
n = list_arfcn(si2t->ext_bcch_frequency_list, 0x8e,
@@ -493,6 +646,30 @@ static int generate_si2ter(uint8_t *output, struct gsm_bts *bts)
return sizeof(*si2t);
}
+static int generate_si2quater(uint8_t *output, struct gsm_bts *bts)
+{
+ int rc;
+ struct gsm48_system_information_type_2quater *si2q =
+ (struct gsm48_system_information_type_2quater *) output;
+
+ memset(si2q, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN);
+
+ si2q->header.l2_plen = GSM48_LEN2PLEN(22);
+ si2q->header.rr_protocol_discriminator = GSM48_PDISC_RR;
+ si2q->header.skip_indicator = 0;
+ si2q->header.system_information = GSM48_MT_RR_SYSINFO_2quater;
+
+ rc = rest_octets_si2quater(si2q->rest_octets,
+ &bts->si_common.si2quater_neigh_list,
+ bts->si_common.data.uarfcn_list,
+ bts->si_common.data.scramble_list,
+ bts->si_common.uarfcn_length);
+ if (rc < 0)
+ return rc;
+
+ return sizeof(*si2q) + rc;
+}
+
static struct gsm48_si_ro_info si_info = {
.selection_params = {
.present = 0,
@@ -510,6 +687,7 @@ static struct gsm48_si_ro_info si_info = {
.ra_colour = 0,
.present = 1,
},
+ .si2quater_indicator = 0,
.lsa_params = {
.present = 0,
},
@@ -545,7 +723,12 @@ static int generate_si3(uint8_t *output, struct gsm_bts *bts)
} else {
si_info.si2ter_indicator = 0;
}
-
+ if ((bts->si_valid & (1 << SYSINFO_TYPE_2quater))) {
+ LOGP(DRR, LOGL_INFO, "SI 2quater is included.\n");
+ si_info.si2quater_indicator = 1;
+ } else {
+ si_info.si2quater_indicator = 0;
+ }
/* SI3 Rest Octets (10.5.2.34), containing
CBQ, CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME
Power Offset, 2ter Indicator, Early Classmark Sending,
@@ -624,7 +807,7 @@ static int generate_si5(uint8_t *output, struct gsm_bts *bts)
si5->rr_protocol_discriminator = GSM48_PDISC_RR;
si5->skip_indicator = 0;
si5->system_information = GSM48_MT_RR_SYSINFO_5;
- rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, 1, 0, 0);
+ rc = generate_bcch_chan_list(si5->bcch_frequency_list, bts, true, false, false);
if (rc < 0)
return rc;
list_arfcn(si5->bcch_frequency_list, 0xce,
@@ -659,7 +842,7 @@ static int generate_si5bis(uint8_t *output, struct gsm_bts *bts)
si5b->rr_protocol_discriminator = GSM48_PDISC_RR;
si5b->skip_indicator = 0;
si5b->system_information = GSM48_MT_RR_SYSINFO_5bis;
- rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, 1, 1, 0);
+ rc = generate_bcch_chan_list(si5b->bcch_frequency_list, bts, true, true, false);
if (rc < 0)
return rc;
n = list_arfcn(si5b->bcch_frequency_list, 0xce,
@@ -703,7 +886,7 @@ static int generate_si5ter(uint8_t *output, struct gsm_bts *bts)
si5t->rr_protocol_discriminator = GSM48_PDISC_RR;
si5t->skip_indicator = 0;
si5t->system_information = GSM48_MT_RR_SYSINFO_5ter;
- rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, 1, 0, 1);
+ rc = generate_bcch_chan_list(si5t->bcch_frequency_list, bts, true, false, true);
if (rc < 0)
return rc;
n = list_arfcn(si5t->bcch_frequency_list, 0x8e,
@@ -824,6 +1007,7 @@ static const gen_si_fn_t gen_si_fn[_MAX_SYSINFO_TYPE] = {
[SYSINFO_TYPE_2] = &generate_si2,
[SYSINFO_TYPE_2bis] = &generate_si2bis,
[SYSINFO_TYPE_2ter] = &generate_si2ter,
+ [SYSINFO_TYPE_2quater] = &generate_si2quater,
[SYSINFO_TYPE_3] = &generate_si3,
[SYSINFO_TYPE_4] = &generate_si4,
[SYSINFO_TYPE_5] = &generate_si5,
diff --git a/openbsc/src/libcommon/Makefile.am b/openbsc/src/libcommon/Makefile.am
index 84c754452..75f40eea7 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 utils.c
+ gsm_subscriber_base.c
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index c852a50f8..2cfca0201 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -283,6 +283,11 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ
bts->neigh_list_manual_mode = 0;
bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
bts->si_common.cell_sel_par.rxlev_acc_min = 0;
+ bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
+ bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
+ bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
+ bts->si_common.si2quater_neigh_list.thresh_hi = 0;
+ osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
bts->si_common.neigh_list.data_len =
sizeof(bts->si_common.data.neigh_list);
diff --git a/openbsc/src/libcommon/gsm_subscriber_base.c b/openbsc/src/libcommon/gsm_subscriber_base.c
index 2bf8c098c..1f98cc66c 100644
--- a/openbsc/src/libcommon/gsm_subscriber_base.c
+++ b/openbsc/src/libcommon/gsm_subscriber_base.c
@@ -115,7 +115,7 @@ struct gsm_subscriber *subscr_get_or_create(struct gsm_subscriber_group *sgrp,
if (!subscr)
return NULL;
- strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
+ strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1);
subscr->group = sgrp;
return subscr;
}
diff --git a/openbsc/src/libcommon/utils.c b/openbsc/src/libcommon/utils.c
deleted file mode 100644
index c47dcaee2..000000000
--- a/openbsc/src/libcommon/utils.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* OpenBSC kitchen sink */
-
-/* (C) 2015 by sysmocom s.m.f.c GmbH <info@sysmocom.de>
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <openbsc/utils.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/bit64gen.h>
-
-/* 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/libiu/iu.c b/openbsc/src/libiu/iu.c
index e19c62b66..16d1fb9ef 100644
--- a/openbsc/src/libiu/iu.c
+++ b/openbsc/src/libiu/iu.c
@@ -244,15 +244,15 @@ int iu_tx_sec_mode_cmd(struct ue_conn_ctx *uectx, struct gsm_auth_tuple *tp,
/* C5 function to derive IK from Kc */
for (i = 0; i < 4; i++)
- ik[i] = tp->kc[i] ^ tp->kc[i+4];
- memcpy(ik+4, tp->kc, 8);
+ ik[i] = tp->vec.kc[i] ^ tp->vec.kc[i+4];
+ memcpy(ik+4, tp->vec.kc, 8);
for (i = 12; i < 16; i++)
ik[i] = ik[i-12];
if (send_ck) {
/* C4 function to derive CK from Kc */
- memcpy(ck, tp->kc, 8);
- memcpy(ck+8, tp->kc, 8);
+ memcpy(ck, tp->vec.kc, 8);
+ memcpy(ck+8, tp->vec.kc, 8);
}
/* create RANAP message */
diff --git a/openbsc/src/libmsc/auth.c b/openbsc/src/libmsc/auth.c
index 2d42c2dfe..cc96e8f28 100644
--- a/openbsc/src/libmsc/auth.c
+++ b/openbsc/src/libmsc/auth.c
@@ -54,9 +54,9 @@ _use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
}
for (i=0; i<4; i++)
- atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
+ atuple->vec.sres[i] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i];
for (i=4; i<12; i++)
- atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
+ atuple->vec.kc[i-4] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i];
return 0;
}
@@ -71,7 +71,7 @@ _use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
return -1;
}
- comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
+ comp128(ainfo->a3a8_ki, atuple->vec.rand, atuple->vec.sres, atuple->vec.kc);
return 0;
}
@@ -120,7 +120,7 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
}
atuple->use_count = 1;
- if (RAND_bytes(atuple->rand, sizeof(atuple->rand)) != 1) {
+ if (RAND_bytes(atuple->vec.rand, sizeof(atuple->vec.rand)) != 1) {
LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n");
return AUTH_ERROR;
}
diff --git a/openbsc/src/libmsc/ctrl_commands.c b/openbsc/src/libmsc/ctrl_commands.c
index e48c6a3e1..0d6a37c96 100644
--- a/openbsc/src/libmsc/ctrl_commands.c
+++ b/openbsc/src/libmsc/ctrl_commands.c
@@ -24,9 +24,25 @@
#include <openbsc/db.h>
#include <openbsc/debug.h>
+static bool alg_supported(const char *alg)
+{
+ /*
+ * TODO: share this with the vty_interface and extend to all
+ * algorithms supported by libosmocore now. Make it table based
+ * as well.
+ */
+ if (strcasecmp(alg, "none") == 0)
+ return true;
+ if (strcasecmp(alg, "xor") == 0)
+ return true;
+ if (strcasecmp(alg, "comp128v1") == 0)
+ return true;
+ return false;
+}
+
static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, void *d)
{
- char *tmp, *imsi, *msisdn, *saveptr = NULL;
+ char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL;
int rc = 0;
tmp = talloc_strdup(cmd, value);
@@ -35,13 +51,21 @@ static int verify_subscriber_modify(struct ctrl_cmd *cmd, const char *value, voi
imsi = strtok_r(tmp, ",", &saveptr);
msisdn = strtok_r(NULL, ",", &saveptr);
+ alg = strtok_r(NULL, ",", &saveptr);
+ ki = strtok_r(NULL, ",", &saveptr);
if (!imsi || !msisdn)
rc = 1;
- else if (strlen(imsi) >= GSM_IMSI_LENGTH)
+ else if (strlen(imsi) > GSM23003_IMSI_MAX_DIGITS)
rc = 1;
else if (strlen(msisdn) >= GSM_EXTENSION_LENGTH)
rc = 1;
+ else if (alg) {
+ if (!alg_supported(alg))
+ rc = 1;
+ else if (strcasecmp(alg, "none") != 0 && !ki)
+ rc = 1;
+ }
talloc_free(tmp);
return rc;
@@ -56,7 +80,7 @@ static int get_subscriber_modify(struct ctrl_cmd *cmd, void *data)
static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
{
struct gsm_network *net = cmd->node;
- char *tmp, *imsi, *msisdn, *saveptr = NULL;
+ char *tmp, *imsi, *msisdn, *alg, *ki, *saveptr = NULL;
struct gsm_subscriber* subscr;
int rc;
@@ -66,6 +90,8 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
imsi = strtok_r(tmp, ",", &saveptr);
msisdn = strtok_r(NULL, ",", &saveptr);
+ alg = strtok_r(NULL, ",", &saveptr);
+ ki = strtok_r(NULL, ",", &saveptr);
subscr = subscr_get_by_imsi(net->subscr_group, imsi);
if (!subscr)
@@ -80,6 +106,36 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
/* put it back to the db */
rc = db_sync_subscriber(subscr);
db_subscriber_update(subscr);
+
+ /* handle optional ciphering */
+ if (alg) {
+ if (strcasecmp(alg, "none") == 0)
+ db_sync_authinfo_for_subscr(NULL, subscr);
+ else {
+ struct gsm_auth_info ainfo = { 0, };
+ /* the verify should make sure that this is okay */
+ OSMO_ASSERT(alg);
+ OSMO_ASSERT(ki);
+
+ if (strcasecmp(alg, "xor") == 0)
+ ainfo.auth_algo = AUTH_ALGO_XOR;
+ else if (strcasecmp(alg, "comp128v1") == 0)
+ ainfo.auth_algo = AUTH_ALGO_COMP128v1;
+
+ rc = osmo_hexparse(ki, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki));
+ if (rc < 0) {
+ subscr_put(subscr);
+ talloc_free(tmp);
+ cmd->reply = "Failed to parse KI";
+ return CTRL_CMD_ERROR;
+ }
+
+ ainfo.a3a8_ki_len = rc;
+ db_sync_authinfo_for_subscr(&ainfo, subscr);
+ rc = 0;
+ }
+ db_sync_lastauthtuple_for_subscr(NULL, subscr);
+ }
subscr_put(subscr);
talloc_free(tmp);
diff --git a/openbsc/src/libmsc/db.c b/openbsc/src/libmsc/db.c
index 8d7d7dc19..b555905ed 100644
--- a/openbsc/src/libmsc/db.c
+++ b/openbsc/src/libmsc/db.c
@@ -34,6 +34,7 @@
#include <openbsc/db.h>
#include <openbsc/debug.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/statistics.h>
#include <osmocom/core/rate_ctr.h>
@@ -508,14 +509,8 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi)
/* Is this subscriber known in the db? */
subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
if (subscr) {
- result = dbi_conn_queryf(conn,
- "UPDATE Subscriber set updated = datetime('now') "
- "WHERE imsi = %s " , imsi);
- if (!result)
- LOGP(DDB, LOGL_ERROR, "failed to update timestamp\n");
- else
- dbi_result_free(result);
- return subscr;
+ subscr_put(subscr);
+ return NULL;
}
subscr = subscr_alloc();
@@ -529,10 +524,13 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi)
"(%s, datetime('now'), datetime('now')) ",
imsi
);
- if (!result)
+ if (!result) {
LOGP(DDB, LOGL_ERROR, "Failed to create Subscriber by IMSI.\n");
+ subscr_put(subscr);
+ return NULL;
+ }
subscr->id = dbi_conn_sequence_last(conn, NULL);
- strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
+ strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1);
dbi_result_free(result);
LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi);
db_subscriber_alloc_exten(subscr);
@@ -703,25 +701,25 @@ int db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
atuple->key_seq = dbi_result_get_ulonglong(result, "key_seq");
len = dbi_result_get_field_length(result, "rand");
- if (len != sizeof(atuple->rand))
+ if (len != sizeof(atuple->vec.rand))
goto err_size;
blob = dbi_result_get_binary(result, "rand");
- memcpy(atuple->rand, blob, len);
+ memcpy(atuple->vec.rand, blob, len);
len = dbi_result_get_field_length(result, "sres");
- if (len != sizeof(atuple->sres))
+ if (len != sizeof(atuple->vec.sres))
goto err_size;
blob = dbi_result_get_binary(result, "sres");
- memcpy(atuple->sres, blob, len);
+ memcpy(atuple->vec.sres, blob, len);
len = dbi_result_get_field_length(result, "kc");
- if (len != sizeof(atuple->kc))
+ if (len != sizeof(atuple->vec.kc))
goto err_size;
blob = dbi_result_get_binary(result, "kc");
- memcpy(atuple->kc, blob, len);
+ memcpy(atuple->vec.kc, blob, len);
dbi_result_free(result);
@@ -762,11 +760,11 @@ int db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
/* Update / Insert */
dbi_conn_quote_binary_copy(conn,
- atuple->rand, sizeof(atuple->rand), &rand_str);
+ atuple->vec.rand, sizeof(atuple->vec.rand), &rand_str);
dbi_conn_quote_binary_copy(conn,
- atuple->sres, sizeof(atuple->sres), &sres_str);
+ atuple->vec.sres, sizeof(atuple->vec.sres), &sres_str);
dbi_conn_quote_binary_copy(conn,
- atuple->kc, sizeof(atuple->kc), &kc_str);
+ atuple->vec.kc, sizeof(atuple->vec.kc), &kc_str);
if (!upd) {
result = dbi_conn_queryf(conn,
@@ -806,7 +804,7 @@ static void db_set_from_query(struct gsm_subscriber *subscr, dbi_conn result)
const char *string;
string = dbi_result_get_string(result, "imsi");
if (string)
- strncpy(subscr->imsi, string, GSM_IMSI_LENGTH-1);
+ strncpy(subscr->imsi, string, sizeof(subscr->imsi)-1);
string = dbi_result_get_string(result, "tmsi");
if (string)
@@ -1320,7 +1318,7 @@ int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t *token
return 0;
}
-int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM_IMEI_LENGTH])
+int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char imei[GSM23003_IMEISV_NUM_DIGITS])
{
unsigned long long equipment_id, watch_id;
dbi_result result;
diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c
index b2ac55c48..8c1cf9adb 100644
--- a/openbsc/src/libmsc/gsm_04_08.c
+++ b/openbsc/src/libmsc/gsm_04_08.c
@@ -60,6 +60,7 @@
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/gsm0480.h>
#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/tlv.h>
@@ -147,7 +148,6 @@ void allocate_security_operation(struct gsm_subscriber_connection *conn)
int iu_hack__get_hardcoded_auth_tuple(struct gsm_auth_tuple *atuple)
{
unsigned char tmp_rand[16];
- struct osmo_auth_vector vec;
/* Ki 000102030405060708090a0b0c0d0e0f */
struct osmo_sub_auth_data auth = {
.type = OSMO_AUTH_TYPE_GSM,
@@ -161,13 +161,10 @@ int iu_hack__get_hardcoded_auth_tuple(struct gsm_auth_tuple *atuple)
RAND_bytes(tmp_rand, sizeof(tmp_rand));
- memset(&vec, 0, sizeof(vec));
- osmo_auth_gen_vec(&vec, &auth, tmp_rand);
+ memset(&atuple->vec, 0, sizeof(atuple->vec));
+ osmo_auth_gen_vec(&atuple->vec, &auth, tmp_rand);
atuple->key_seq = 0;
- memcpy(&atuple->rand, &tmp_rand, sizeof(atuple->rand));
- memcpy(&atuple->sres, &vec.sres, sizeof(atuple->sres));
- memcpy(&atuple->kc, &vec.kc, sizeof(atuple->kc));
return AUTH_DO_AUTH;
}
@@ -260,13 +257,13 @@ int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
/* Start authentication */
DEBUGP(DMM, "gsm48_secure_channel(%s) starting authentication\n",
subscr_name(subscr));
- return gsm48_tx_mm_auth_req(conn, op->atuple.rand, op->atuple.key_seq);
+ return gsm48_tx_mm_auth_req(conn, op->atuple.vec.rand, op->atuple.key_seq);
} else if (rc == AUTH_DO_CIPH) {
/* Start ciphering directly */
DEBUGP(DMM, "gsm48_secure_channel(%s) starting ciphering\n",
subscr_name(subscr));
return gsm0808_cipher_mode(conn, net->a5_encryption,
- op->atuple.kc, 8, 0);
+ op->atuple.vec.kc, 8, 0);
}
return -EINVAL; /* not reached */
@@ -1137,10 +1134,10 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
cb = conn->sec_operation->cb;
/* Validate SRES */
- if (memcmp(conn->sec_operation->atuple.sres, ar->sres,4)) {
+ if (memcmp(conn->sec_operation->atuple.vec.sres, ar->sres,4)) {
int rc;
DEBUGPC(DMM, "Invalid (expected %s)\n",
- osmo_hexdump(conn->sec_operation->atuple.sres, 4));
+ osmo_hexdump(conn->sec_operation->atuple.vec.sres, 4));
if (cb)
cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_AUTH_FAILED,
@@ -1161,7 +1158,7 @@ static int gsm48_rx_mm_auth_resp(struct gsm_subscriber_connection *conn, struct
* As soon as such a receiver exists, it must call
* iu_tx_sec_mode_cmd() as below. */
return gsm0808_cipher_mode(conn, net->a5_encryption,
- conn->sec_operation->atuple.kc, 8, 0);
+ conn->sec_operation->atuple.vec.kc, 8, 0);
if (conn->via_iface == IFACE_IU
&& !conn->iu.integrity_protection) {
@@ -1607,17 +1604,38 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
struct gsm_bts *remote_bts = remote_lchan->ts->trx->bts;
+ enum gsm_chan_t lt = lchan->type, rt = remote_lchan->type;
+ enum gsm48_chan_mode lm = lchan->tch_mode, rm = remote_lchan->tch_mode;
int rc;
- DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u) and (bts=%u,trx=%u,ts=%u)\n",
- bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
- remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr);
+ DEBUGP(DCC, "Setting up TCH map between (bts=%u,trx=%u,ts=%u,%s) and "
+ "(bts=%u,trx=%u,ts=%u,%s)\n",
+ bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
+ get_value_string(gsm_chan_t_names, lt),
+ remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr,
+ get_value_string(gsm_chan_t_names, rt));
if (bts->type != remote_bts->type) {
LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n");
return -EINVAL;
}
+ if (lt != rt) {
+ LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different"
+ " channel types: local = %s, remote = %s\n",
+ get_value_string(gsm_chan_t_names, lt),
+ get_value_string(gsm_chan_t_names, rt));
+ return -EBADSLT;
+ }
+
+ if (lm != rm) {
+ LOGP(DCC, LOGL_ERROR, "Cannot patch through call with different"
+ " channel modes: local = %s, remote = %s\n",
+ get_value_string(gsm48_chan_mode_names, lm),
+ get_value_string(gsm48_chan_mode_names, rm));
+ return -EMEDIUMTYPE;
+ }
+
// todo: map between different bts types
switch (bts->type) {
case GSM_BTS_TYPE_NANOBTS:
@@ -1866,6 +1884,30 @@ static void gsm48_cc_timeout(void *arg)
}
+/* disconnect both calls from the bridge */
+static inline void disconnect_bridge(struct gsm_network *net,
+ struct gsm_mncc_bridge *bridge, int err)
+{
+ struct gsm_trans *trans0 = trans_find_by_callref(net, bridge->callref[0]);
+ struct gsm_trans *trans1 = trans_find_by_callref(net, bridge->callref[1]);
+ struct gsm_mncc mx_rel;
+ if (!trans0 || !trans1)
+ return;
+
+ DEBUGP(DCC, "Failed to bridge TCH for calls %x <-> %x :: %s \n",
+ trans0->callref, trans1->callref, strerror(err));
+
+ memset(&mx_rel, 0, sizeof(struct gsm_mncc));
+ mncc_set_cause(&mx_rel, GSM48_CAUSE_LOC_INN_NET,
+ GSM48_CC_CAUSE_CHAN_UNACCEPT);
+
+ mx_rel.callref = trans0->callref;
+ gsm48_cc_tx_disconnect(trans0, &mx_rel);
+
+ mx_rel.callref = trans1->callref;
+ gsm48_cc_tx_disconnect(trans1, &mx_rel);
+}
+
static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
int sec, int micro)
{
@@ -3031,6 +3073,7 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref)
struct gsm_bts *bts;
struct gsm_lchan *lchan;
struct gsm_trans *trans;
+ enum gsm48_chan_mode m;
/* Find callref */
trans = trans_find_by_callref(net, callref);
@@ -3070,8 +3113,11 @@ static int tch_rtp_create(struct gsm_network *net, uint32_t callref)
*/
if (lchan->tch_mode == GSM48_CMODE_SIGN) {
trans->conn->mncc_rtp_create_pending = 1;
- return gsm0808_assign_req(trans->conn,
- mncc_codec_for_mode(lchan->type),
+ m = mncc_codec_for_mode(lchan->type);
+ LOGP(DMNCC, LOGL_DEBUG, "RTP create: codec=%s, chan_type=%s\n",
+ get_value_string(gsm48_chan_mode_names, m),
+ get_value_string(gsm_chan_t_names, lchan->type));
+ return gsm0808_assign_req(trans->conn, m,
lchan->type != GSM_LCHAN_TCH_H);
}
@@ -3105,6 +3151,10 @@ static int tch_rtp_connect(struct gsm_network *net, void *arg)
}
lchan = trans->conn->lchan;
+ LOGP(DMNCC, LOGL_DEBUG, "RTP connect: codec=%s, chan_type=%s\n",
+ get_value_string(gsm48_chan_mode_names,
+ mncc_codec_for_mode(lchan->type)),
+ get_value_string(gsm_chan_t_names, lchan->type));
/* TODO: Check if payload_msg_type is compatible with what we have */
if (rtp->payload_type != lchan->abis_ip.rtp_payload) {
@@ -3250,7 +3300,10 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg)
/* handle special messages */
switch(msg_type) {
case MNCC_BRIDGE:
- return tch_bridge(net, arg);
+ rc = tch_bridge(net, arg);
+ if (rc < 0)
+ disconnect_bridge(net, arg, -rc);
+ return rc;
case MNCC_FRAME_DROP:
return tch_recv_mncc(net, data->callref, 0);
case MNCC_FRAME_RECV:
diff --git a/openbsc/src/libmsc/mncc_builtin.c b/openbsc/src/libmsc/mncc_builtin.c
index 46f86a15a..c670ed2e5 100644
--- a/openbsc/src/libmsc/mncc_builtin.c
+++ b/openbsc/src/libmsc/mncc_builtin.c
@@ -138,7 +138,8 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type,
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = call->callref;
mncc.lchan_mode = determine_lchan_mode(setup);
- DEBUGP(DMNCC, "(call %x) Modify channel mode.\n", call->callref);
+ DEBUGP(DMNCC, "(call %x) Modify channel mode: %s\n", call->callref,
+ get_value_string(gsm48_chan_mode_names, mncc.lchan_mode));
mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
/* send setup to remote */
diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c
index e4e01d27a..fdc7e8e6f 100644
--- a/openbsc/src/libmsc/vty_interface_layer3.c
+++ b/openbsc/src/libmsc/vty_interface_layer3.c
@@ -92,13 +92,13 @@ static void subscr_dump_full_vty(struct vty *vty, struct gsm_subscriber *subscr)
vty_out(vty, " seq # : %d%s",
atuple.key_seq, VTY_NEWLINE);
vty_out(vty, " RAND : %s%s",
- osmo_hexdump(atuple.rand, sizeof(atuple.rand)),
+ osmo_hexdump(atuple.vec.rand, sizeof(atuple.vec.rand)),
VTY_NEWLINE);
vty_out(vty, " SRES : %s%s",
- osmo_hexdump(atuple.sres, sizeof(atuple.sres)),
+ osmo_hexdump(atuple.vec.sres, sizeof(atuple.vec.sres)),
VTY_NEWLINE);
vty_out(vty, " Kc : %s%s",
- osmo_hexdump(atuple.kc, sizeof(atuple.kc)),
+ osmo_hexdump(atuple.vec.kc, sizeof(atuple.vec.kc)),
VTY_NEWLINE);
}
@@ -235,11 +235,17 @@ DEFUN(subscriber_create,
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
struct gsm_subscriber *subscr;
- subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]);
- if (!subscr) {
- vty_out(vty, "%% No subscriber created for IMSI %s%s",
- argv[0], VTY_NEWLINE);
- return CMD_WARNING;
+ subscr = subscr_get_by_imsi(gsmnet->subscr_group, argv[0]);
+ if (subscr)
+ db_sync_subscriber(subscr);
+ else {
+ subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]);
+
+ if (!subscr) {
+ vty_out(vty, "%% No subscriber created for IMSI %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
/* Show info about the created subscriber. */
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index cacb9199d..f20b2486f 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -34,6 +34,7 @@
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
+#include <libgen.h>
#define _GNU_SOURCE
#include <getopt.h>
@@ -47,7 +48,6 @@
#include <openbsc/abis_nm.h>
#include <openbsc/socket.h>
#include <openbsc/vty.h>
-#include <openbsc/utils.h>
#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
@@ -1022,7 +1022,7 @@ static int verify_key(struct bsc_connection *conn, struct bsc_config *conf, cons
return 0;
}
- return constant_time_cmp(vec.res, key, 8) == 0;
+ return osmo_constant_time_cmp(vec.res, key, 8) == 0;
}
static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
@@ -1152,6 +1152,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
if (!create_sccp_src_ref(bsc, parsed))
goto exit2;
con = patch_sccp_src_ref_to_msc(msg, parsed, bsc);
+ OSMO_ASSERT(con);
con->msc_con = bsc->nat->msc_con;
con_msc = con->msc_con;
con->filter_state.con_type = con_type;
@@ -1320,8 +1321,8 @@ static int ipaccess_bsc_read_cb(struct osmo_fd *bfd)
bsc->cfg ? bsc->cfg->nr : -1);
else
LOGP(DNAT, LOGL_ERROR,
- "Stream error on BSC Nr: %d. Failed to parse ip access message: %d\n",
- bsc->cfg ? bsc->cfg->nr : -1, ret);
+ "Stream error on BSC Nr: %d. Failed to parse ip access message: %d (%s)\n",
+ bsc->cfg ? bsc->cfg->nr : -1, ret, strerror(-ret));
bsc_close_connection(bsc);
return -1;
@@ -1626,6 +1627,8 @@ int main(int argc, char **argv)
local_addr.s_addr = INADDR_ANY;
handle_options(argc, argv);
+ nat->include_base = dirname(talloc_strdup(tall_bsc_ctx, config_file));
+
rate_ctr_init(tall_bsc_ctx);
osmo_stats_init(tall_bsc_ctx);
@@ -1651,7 +1654,7 @@ int main(int argc, char **argv)
/* seed the PRNG */
srand(time(NULL));
-
+ LOGP(DNAT, LOGL_NOTICE, "BSCs configured from %s\n", nat->resolved_path);
/*
* Setup the MGCP code..
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
index cc7d44287..37b01e314 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_utils.c
@@ -155,14 +155,15 @@ struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat)
return con;
}
-struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token)
+struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
+ unsigned int number)
{
struct bsc_config *conf = talloc_zero(nat, struct bsc_config);
if (!conf)
return NULL;
conf->token = talloc_strdup(conf, token);
- conf->nr = nat->num_bsc;
+ conf->nr = number;
conf->nat = nat;
conf->max_endpoints = 32;
conf->paging_group = PAGIN_GROUP_UNASSIGNED;
@@ -205,6 +206,8 @@ void bsc_config_free(struct bsc_config *cfg)
llist_del(&cfg->entry);
rate_ctr_group_free(cfg->stats.ctrg);
talloc_free(cfg);
+ cfg->nat->num_bsc--;
+ OSMO_ASSERT(cfg->nat->num_bsc >= 0)
}
static void _add_lac(void *ctx, struct llist_head *list, int _lac)
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index ce68742fa..706e5074e 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -39,6 +39,7 @@
#include <osmocom/sccp/sccp.h>
#include <stdlib.h>
+#include <stdbool.h>
static struct bsc_nat *_nat;
@@ -96,6 +97,8 @@ static int config_write_nat(struct vty *vty)
vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
+ if (_nat->include_file)
+ vty_out(vty, " bscs-config-file %s%s", _nat->include_file, VTY_NEWLINE);
if (_nat->token)
vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE);
@@ -181,6 +184,14 @@ static int config_write_bsc(struct vty *vty)
return CMD_SUCCESS;
}
+DEFUN(show_bscs, show_bscs_cmd, "show bscs-config",
+ SHOW_STR "Show configured BSCs\n"
+ "Both from included file and vty\n")
+{
+ vty_out(vty, "BSCs configuration loaded from %s:%s", _nat->resolved_path,
+ VTY_NEWLINE);
+ return config_write_bsc(vty);
+}
DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
SHOW_STR "Display information about SCCP\n"
@@ -204,6 +215,14 @@ DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
return CMD_SUCCESS;
}
+DEFUN(show_nat_bsc, show_nat_bsc_cmd, "show nat num-bscs-configured",
+ SHOW_STR "Display NAT configuration details\n"
+ "BSCs-related\n")
+{
+ vty_out(vty, "%d BSCs configured%s", _nat->num_bsc, VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
SHOW_STR BSC_STR
"All active connections\n")
@@ -487,6 +506,55 @@ DEFUN(cfg_nat_acc_lst_name,
return CMD_SUCCESS;
}
+DEFUN(cfg_nat_include,
+ cfg_nat_include_cmd,
+ "bscs-config-file NAME",
+ "Set the filename of the BSC configuration to include.\n"
+ "The filename to be included.")
+{
+ char *path;
+ int rc;
+ struct bsc_config *cf1, *cf2;
+ struct bsc_connection *con1, *con2;
+
+ if ('/' == argv[0][0])
+ bsc_replace_string(_nat, &_nat->resolved_path, argv[0]);
+ else {
+ path = talloc_asprintf(_nat, "%s/%s", _nat->include_base,
+ argv[0]);
+ bsc_replace_string(_nat, &_nat->resolved_path, path);
+ talloc_free(path);
+ }
+
+ llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
+ cf1->remove = true;
+ cf1->token_updated = false;
+ }
+
+ rc = vty_read_config_file(_nat->resolved_path, NULL);
+ if (rc < 0) {
+ vty_out(vty, "Failed to parse the config file %s: %s%s",
+ _nat->resolved_path, strerror(-rc), VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bsc_replace_string(_nat, &_nat->include_file, argv[0]);
+
+ llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections,
+ list_entry) {
+ if (con1->cfg)
+ if (con1->cfg->token_updated || con1->cfg->remove)
+ bsc_close_connection(con1);
+ }
+
+ llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
+ if (cf1->remove)
+ bsc_config_free(cf1);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_nat_no_acc_lst_name,
cfg_nat_no_acc_lst_name_cmd,
"no access-list-name",
@@ -791,21 +859,16 @@ DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR",
"BSC configuration\n" "Identifier of the BSC\n")
{
int bsc_nr = atoi(argv[0]);
- struct bsc_config *bsc;
+ struct bsc_config *bsc = bsc_config_num(_nat, bsc_nr);
- if (bsc_nr > _nat->num_bsc) {
- vty_out(vty, "%% The next unused BSC number is %u%s",
- _nat->num_bsc, VTY_NEWLINE);
- return CMD_WARNING;
- } else if (bsc_nr == _nat->num_bsc) {
- /* allocate a new one */
- bsc = bsc_config_alloc(_nat, "unknown");
- } else
- bsc = bsc_config_num(_nat, bsc_nr);
+ /* allocate a new one */
+ if (!bsc)
+ bsc = bsc_config_alloc(_nat, "unknown", bsc_nr);
if (!bsc)
return CMD_WARNING;
+ bsc->remove = false;
vty->index = bsc;
vty->node = NAT_BSC_NODE;
@@ -818,6 +881,9 @@ DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN",
{
struct bsc_config *conf = vty->index;
+ if (strncmp(conf->token, argv[0], 128) != 0)
+ conf->token_updated = true;
+
bsc_replace_string(conf, &conf->token, argv[0]);
return CMD_SUCCESS;
}
@@ -863,8 +929,11 @@ DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
/* verify that the LACs are unique */
llist_for_each_entry(tmp, &_nat->bsc_configs, entry) {
if (bsc_config_handles_lac(tmp, lac)) {
- vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE);
- return CMD_ERR_INCOMPLETE;
+ if (tmp->nr != conf->nr) {
+ vty_out(vty, "%% LAC %d is already used.%s", lac,
+ VTY_NEWLINE);
+ return CMD_ERR_INCOMPLETE;
+ }
}
}
@@ -1169,6 +1238,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
/* show commands */
install_element_ve(&show_sccp_cmd);
install_element_ve(&show_bsc_cmd);
+ install_element_ve(&show_nat_bsc_cmd);
install_element_ve(&show_bsc_cfg_cmd);
install_element_ve(&show_stats_cmd);
install_element_ve(&show_stats_lac_cmd);
@@ -1176,6 +1246,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element_ve(&show_msc_cmd);
install_element_ve(&test_regex_cmd);
install_element_ve(&show_bsc_mgcp_cmd);
+ install_element_ve(&show_bscs_cmd);
install_element_ve(&show_bar_lst_cmd);
install_element_ve(&show_prefix_tree_cmd);
install_element_ve(&show_ussd_connection_cmd);
@@ -1197,6 +1268,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd);
+ install_element(NAT_NODE, &cfg_nat_include_cmd);
install_element(NAT_NODE, &cfg_nat_imsi_black_list_fn_cmd);
install_element(NAT_NODE, &cfg_nat_no_imsi_black_list_fn_cmd);
install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd);
@@ -1233,7 +1305,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
/* BSC subgroups */
install_element(NAT_NODE, &cfg_bsc_cmd);
- install_node(&bsc_node, config_write_bsc);
+ install_node(&bsc_node, NULL);
vty_install_default(NAT_BSC_NODE);
install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
install_element(NAT_BSC_NODE, &cfg_bsc_auth_key_cmd);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_ussd.c b/openbsc/src/osmo-bsc_nat/bsc_ussd.c
index e0809059a..2f68381ac 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_ussd.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_ussd.c
@@ -400,7 +400,7 @@ int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parse
if (parsed->bssap != BSSAP_MSG_DTAP)
return 0;
- if (strlen(con->filter_state.imsi) >= GSM_IMSI_LENGTH)
+ if (strlen(con->filter_state.imsi) > GSM23003_IMSI_MAX_DIGITS)
return 0;
hdr48 = bsc_unpack_dtap(parsed, msg, &len);
diff --git a/openbsc/src/osmo-cscn/cscn_main.c b/openbsc/src/osmo-cscn/cscn_main.c
index c66873437..eea029de7 100644
--- a/openbsc/src/osmo-cscn/cscn_main.c
+++ b/openbsc/src/osmo-cscn/cscn_main.c
@@ -383,6 +383,8 @@ int main(int argc, char **argv)
cscn_cmdline_config.mncc_sock_path);
if (rc < 0)
exit(1);
+ } else {
+ DEBUGP(DMNCC, "Using internal MNCC handler.\n");
}
/* start telnet after reading config for vty_get_bind_addr() */
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index a4b313c91..a405763bc 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -316,7 +316,7 @@ static void test_contrack()
printf("Testing connection tracking.\n");
nat = bsc_nat_alloc();
con = bsc_connection_alloc(nat);
- con->cfg = bsc_config_alloc(nat, "foo");
+ con->cfg = bsc_config_alloc(nat, "foo", 0);
bsc_config_add_lac(con->cfg, 23);
bsc_config_add_lac(con->cfg, 49);
bsc_config_add_lac(con->cfg, 42);
@@ -434,7 +434,7 @@ static void test_paging(void)
nat = bsc_nat_alloc();
con = bsc_connection_alloc(nat);
- cfg = bsc_config_alloc(nat, "unknown");
+ cfg = bsc_config_alloc(nat, "unknown", 0);
con->cfg = cfg;
bsc_config_add_lac(cfg, 23);
con->authenticated = 1;
@@ -476,7 +476,7 @@ static void test_mgcp_allocations(void)
nat->mgcp_cfg->trunk.number_endpoints = 64;
bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo");
+ bsc->cfg = bsc_config_alloc(nat, "foo", 0);
bsc->cfg->max_endpoints = 60;
bsc_config_add_lac(bsc->cfg, 2323);
bsc->last_endpoint = 0x22;
@@ -522,7 +522,7 @@ static void test_mgcp_ass_tracking(void)
mgcp_endpoints_allocate(&nat->mgcp_cfg->trunk);
bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo");
+ bsc->cfg = bsc_config_alloc(nat, "foo", 0);
bsc_config_add_lac(bsc->cfg, 2323);
bsc->last_endpoint = 0x1e;
con.bsc = bsc;
@@ -874,7 +874,7 @@ static void test_cr_filter()
struct bsc_nat *nat = bsc_nat_alloc();
struct bsc_connection *bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo");
+ bsc->cfg = bsc_config_alloc(nat, "foo", 0);
bsc_config_add_lac(bsc->cfg, 1234);
bsc->cfg->acc_lst_name = "bsc";
nat->acc_lst_name = "nat";
@@ -953,7 +953,7 @@ static void test_dt_filter()
struct bsc_connection *bsc = bsc_connection_alloc(nat);
struct nat_sccp_connection *con = talloc_zero(0, struct nat_sccp_connection);
- bsc->cfg = bsc_config_alloc(nat, "foo");
+ bsc->cfg = bsc_config_alloc(nat, "foo", 0);
bsc_config_add_lac(bsc->cfg, 23);
con->bsc = bsc;
@@ -1525,7 +1525,7 @@ static void test_nat_extract_lac()
/* initialize the testcase */
nat = bsc_nat_alloc();
bsc = bsc_connection_alloc(nat);
- bsc->cfg = bsc_config_alloc(nat, "foo");
+ bsc->cfg = bsc_config_alloc(nat, "foo", 0);
memset(&con, 0, sizeof(con));
con.bsc = bsc;
diff --git a/openbsc/tests/ctrl_test_runner.py b/openbsc/tests/ctrl_test_runner.py
index 21850e348..7a126437c 100644
--- a/openbsc/tests/ctrl_test_runner.py
+++ b/openbsc/tests/ctrl_test_runner.py
@@ -469,6 +469,33 @@ class TestCtrlNITB(TestCtrlBase):
self.assertEquals(r['var'], 'number-of-bts')
self.assertEquals(r['value'], '1')
+ def testSubscriberAddWithKi(self):
+ """Test that we can set the algorithm to none, xor, comp128v1"""
+
+ r = self.do_set('subscriber-modify-v1', '2620345,445566')
+ self.assertEquals(r['mtype'], 'SET_REPLY')
+ self.assertEquals(r['var'], 'subscriber-modify-v1')
+ self.assertEquals(r['value'], 'OK')
+
+ r = self.do_set('subscriber-modify-v1', '2620345,445566,none')
+ self.assertEquals(r['mtype'], 'SET_REPLY')
+ self.assertEquals(r['var'], 'subscriber-modify-v1')
+ self.assertEquals(r['value'], 'OK')
+
+ r = self.do_set('subscriber-modify-v1', '2620345,445566,xor')
+ self.assertEquals(r['mtype'], 'ERROR')
+ self.assertEquals(r['error'], 'Value failed verification.')
+
+ r = self.do_set('subscriber-modify-v1', '2620345,445566,comp128v1,00112233445566778899AABBCCDDEEFF')
+ self.assertEquals(r['mtype'], 'SET_REPLY')
+ self.assertEquals(r['var'], 'subscriber-modify-v1')
+ self.assertEquals(r['value'], 'OK')
+
+ r = self.do_set('subscriber-modify-v1', '2620345,445566,none')
+ self.assertEquals(r['mtype'], 'SET_REPLY')
+ self.assertEquals(r['var'], 'subscriber-modify-v1')
+ self.assertEquals(r['value'], 'OK')
+
def testSubscriberAddRemove(self):
r = self.do_set('subscriber-modify-v1', '2620345,445566')
self.assertEquals(r['mtype'], 'SET_REPLY')
diff --git a/openbsc/tests/db/db_test.c b/openbsc/tests/db/db_test.c
index a02d1f801..fb159a5b1 100644
--- a/openbsc/tests/db/db_test.c
+++ b/openbsc/tests/db/db_test.c
@@ -1,5 +1,5 @@
/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
- * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2016 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2014 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
* All Rights Reserved
*
@@ -246,6 +246,10 @@ int main()
SUBSCR_PUT(alice_db);
SUBSCR_PUT(alice);
+ /* create it again and see it fails */
+ alice = db_create_subscriber(alice_imsi);
+ OSMO_ASSERT(!alice);
+
test_sms();
test_sms_migrate();
diff --git a/openbsc/tests/gbproxy/gbproxy_test.c b/openbsc/tests/gbproxy/gbproxy_test.c
index 0ba827f76..a2ff95b1d 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.c
+++ b/openbsc/tests/gbproxy/gbproxy_test.c
@@ -26,6 +26,7 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gprs/gprs_msgb.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
@@ -34,7 +35,6 @@
#include <openbsc/gprs_utils.h>
#include <openbsc/gprs_llc.h>
#include <openbsc/gprs_gb_parse.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <openbsc/debug.h>
#include <openssl/rand.h>
@@ -1293,6 +1293,7 @@ static int gprs_process_message(struct gprs_ns_inst *nsi, const char *text, stru
}
msg = gprs_ns_msgb_alloc();
+ OSMO_ASSERT(msg);
memmove(msg->data, data, data_len);
msg->l2h = msg->data;
msgb_put(msg, data_len);
diff --git a/openbsc/tests/gprs/Makefile.am b/openbsc/tests/gprs/Makefile.am
index b57977b94..902313f2a 100644
--- a/openbsc/tests/gprs/Makefile.am
+++ b/openbsc/tests/gprs/Makefile.am
@@ -5,8 +5,6 @@ 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/libcommon/utils.c
+gprs_test_SOURCES = gprs_test.c $(top_srcdir)/src/gprs/gprs_utils.c
gprs_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
diff --git a/openbsc/tests/gprs/gprs_test.c b/openbsc/tests/gprs/gprs_test.c
index c78b98ab5..ff7740494 100644
--- a/openbsc/tests/gprs/gprs_test.c
+++ b/openbsc/tests/gprs/gprs_test.c
@@ -5,17 +5,14 @@
#include <openbsc/gprs_llc.h>
#include <openbsc/gprs_utils.h>
-#include <openbsc/gprs_gsup_messages.h>
-
#include <openbsc/debug.h>
#include <osmocom/core/application.h>
+#include <osmocom/gsm/gsup.h>
#define ASSERT_FALSE(x) if (x) { printf("Should have returned false.\n"); abort(); }
#define ASSERT_TRUE(x) if (!x) { printf("Should have returned true.\n"); abort(); }
-#define VERBOSE_FPRINTF(...)
-
/**
* GSM 04.64 8.4.2 Receipt of unacknowledged information
*/
@@ -146,479 +143,6 @@ static void test_gsm_03_03_apn(void)
}
}
-/* TODO: Move tlv testing to libosmocore */
-static void check_tlv_parse(uint8_t **data, size_t *data_len,
- uint8_t exp_tag, size_t exp_len, const uint8_t *exp_val)
-{
- uint8_t *value;
- size_t value_len;
- uint8_t tag;
- int rc;
- uint8_t *saved_data = *data;
- size_t saved_data_len = *data_len;
-
- rc = gprs_match_tlv(data, data_len, exp_tag ^ 1, NULL, NULL);
- OSMO_ASSERT(rc == 0);
-
- rc = gprs_match_tlv(data, data_len, exp_tag, &value, &value_len);
- OSMO_ASSERT(rc == (int)value_len + 2);
- OSMO_ASSERT(value_len == exp_len);
- OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
-
- /* restore data/data_len */
- *data = saved_data;
- *data_len = saved_data_len;
-
- rc = gprs_shift_tlv(data, data_len, &tag, &value, &value_len);
- OSMO_ASSERT(rc == (int)value_len + 2);
- OSMO_ASSERT(tag == exp_tag);
- OSMO_ASSERT(value_len == exp_len);
- OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
-}
-
-static void check_tv_fixed_match(uint8_t **data, size_t *data_len,
- uint8_t tag, size_t len, const uint8_t *exp_val)
-{
- uint8_t *value;
- int rc;
-
- rc = gprs_match_tv_fixed(data, data_len, tag ^ 1, len, NULL);
- OSMO_ASSERT(rc == 0);
-
- rc = gprs_match_tv_fixed(data, data_len, tag, len, &value);
- OSMO_ASSERT(rc == (int)len + 1);
- OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
-}
-
-static void check_v_fixed_shift(uint8_t **data, size_t *data_len,
- size_t len, const uint8_t *exp_val)
-{
- uint8_t *value;
- int rc;
-
- rc = gprs_shift_v_fixed(data, data_len, len, &value);
- OSMO_ASSERT(rc == (int)len);
- OSMO_ASSERT(memcmp(value, exp_val, len) == 0);
-}
-
-static void check_lv_shift(uint8_t **data, size_t *data_len,
- size_t exp_len, const uint8_t *exp_val)
-{
- uint8_t *value;
- size_t value_len;
- int rc;
-
- rc = gprs_shift_lv(data, data_len, &value, &value_len);
- OSMO_ASSERT(rc == (int)value_len + 1);
- OSMO_ASSERT(value_len == exp_len);
- OSMO_ASSERT(memcmp(value, exp_val, exp_len) == 0);
-}
-
-static void check_tlv_match_data_len(size_t data_len, uint8_t tag, size_t len,
- const uint8_t *test_data)
-{
- uint8_t buf[300] = {0};
-
- uint8_t *unchanged_ptr = buf - 1;
- size_t unchanged_len = 0xdead;
- size_t tmp_data_len = data_len;
- uint8_t *value = unchanged_ptr;
- size_t value_len = unchanged_len;
- uint8_t *data = buf;
-
- OSMO_ASSERT(data_len <= sizeof(buf));
-
- tlv_put(data, tag, len, test_data);
- if (data_len < len + 2) {
- OSMO_ASSERT(-1 == gprs_match_tlv(&data, &tmp_data_len,
- tag, &value, &value_len));
- OSMO_ASSERT(tmp_data_len == 0);
- OSMO_ASSERT(data == buf + data_len);
- OSMO_ASSERT(value == unchanged_ptr);
- OSMO_ASSERT(value_len == unchanged_len);
- } else {
- OSMO_ASSERT(0 <= gprs_match_tlv(&data, &tmp_data_len,
- tag, &value, &value_len));
- OSMO_ASSERT(value != unchanged_ptr);
- OSMO_ASSERT(value_len != unchanged_len);
- }
-}
-
-static void check_tv_fixed_match_data_len(size_t data_len,
- uint8_t tag, size_t len,
- const uint8_t *test_data)
-{
- uint8_t buf[300] = {0};
-
- uint8_t *unchanged_ptr = buf - 1;
- size_t tmp_data_len = data_len;
- uint8_t *value = unchanged_ptr;
- uint8_t *data = buf;
-
- OSMO_ASSERT(data_len <= sizeof(buf));
-
- tv_fixed_put(data, tag, len, test_data);
-
- if (data_len < len + 1) {
- OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &tmp_data_len,
- tag, len, &value));
- OSMO_ASSERT(tmp_data_len == 0);
- OSMO_ASSERT(data == buf + data_len);
- OSMO_ASSERT(value == unchanged_ptr);
- } else {
- OSMO_ASSERT(0 <= gprs_match_tv_fixed(&data, &tmp_data_len,
- tag, len, &value));
- OSMO_ASSERT(value != unchanged_ptr);
- }
-}
-
-static void check_v_fixed_shift_data_len(size_t data_len,
- size_t len, const uint8_t *test_data)
-{
- uint8_t buf[300] = {0};
-
- uint8_t *unchanged_ptr = buf - 1;
- size_t tmp_data_len = data_len;
- uint8_t *value = unchanged_ptr;
- uint8_t *data = buf;
-
- OSMO_ASSERT(data_len <= sizeof(buf));
-
- memcpy(data, test_data, len);
-
- if (data_len < len) {
- OSMO_ASSERT(-1 == gprs_shift_v_fixed(&data, &tmp_data_len,
- len, &value));
- OSMO_ASSERT(tmp_data_len == 0);
- OSMO_ASSERT(data == buf + data_len);
- OSMO_ASSERT(value == unchanged_ptr);
- } else {
- OSMO_ASSERT(0 <= gprs_shift_v_fixed(&data, &tmp_data_len,
- len, &value));
- OSMO_ASSERT(value != unchanged_ptr);
- }
-}
-
-static void check_lv_shift_data_len(size_t data_len,
- size_t len, const uint8_t *test_data)
-{
- uint8_t buf[300] = {0};
-
- uint8_t *unchanged_ptr = buf - 1;
- size_t unchanged_len = 0xdead;
- size_t tmp_data_len = data_len;
- uint8_t *value = unchanged_ptr;
- size_t value_len = unchanged_len;
- uint8_t *data = buf;
-
- lv_put(data, len, test_data);
- if (data_len < len + 1) {
- OSMO_ASSERT(-1 == gprs_shift_lv(&data, &tmp_data_len,
- &value, &value_len));
- OSMO_ASSERT(tmp_data_len == 0);
- OSMO_ASSERT(data == buf + data_len);
- OSMO_ASSERT(value == unchanged_ptr);
- OSMO_ASSERT(value_len == unchanged_len);
- } else {
- OSMO_ASSERT(0 <= gprs_shift_lv(&data, &tmp_data_len,
- &value, &value_len));
- OSMO_ASSERT(value != unchanged_ptr);
- OSMO_ASSERT(value_len != unchanged_len);
- }
-}
-
-static void test_tlv_shift_functions()
-{
- uint8_t test_data[1024];
- uint8_t buf[1024];
- uint8_t *data_end;
- unsigned i, len;
- uint8_t *data;
- size_t data_len;
- const uint8_t tag = 0x1a;
-
- printf("Test shift functions\n");
-
- for (i = 0; i < ARRAY_SIZE(test_data); i++)
- test_data[i] = (uint8_t)i;
-
- for (len = 0; len < 256; len++) {
- const unsigned iterations = sizeof(buf) / (len + 2) / 4;
-
- memset(buf, 0xee, sizeof(buf));
- data_end = data = buf;
-
- for (i = 0; i < iterations; i++) {
- data_end = tlv_put(data_end, tag, len, test_data);
- data_end = tv_fixed_put(data_end, tag, len, test_data);
- /* v_fixed_put */
- memcpy(data_end, test_data, len);
- data_end += len;
- data_end = lv_put(data_end, len, test_data);
- }
-
- data_len = data_end - data;
- OSMO_ASSERT(data_len <= sizeof(buf));
-
- for (i = 0; i < iterations; i++) {
- check_tlv_parse(&data, &data_len, tag, len, test_data);
- check_tv_fixed_match(&data, &data_len, tag, len, test_data);
- check_v_fixed_shift(&data, &data_len, len, test_data);
- check_lv_shift(&data, &data_len, len, test_data);
- }
-
- OSMO_ASSERT(data == data_end);
-
- /* Test at end of data */
-
- OSMO_ASSERT(-1 == gprs_match_tlv(&data, &data_len, tag, NULL, NULL));
- OSMO_ASSERT(-1 == gprs_match_tv_fixed(&data, &data_len, tag, len, NULL));
- OSMO_ASSERT((len ? -1 : 0) == gprs_shift_v_fixed(&data, &data_len, len, NULL));
- OSMO_ASSERT(-1 == gprs_shift_lv(&data, &data_len, NULL, NULL));
-
- /* Test invalid data_len */
- for (data_len = 0; data_len <= len + 2 + 1; data_len += 1) {
- check_tlv_match_data_len(data_len, tag, len, test_data);
- check_tv_fixed_match_data_len(data_len, tag, len, test_data);
- check_v_fixed_shift_data_len(data_len, len, test_data);
- check_lv_shift_data_len(data_len, len, test_data);
- }
- }
-}
-
-/* Tests for gprs_gsup_messages.c */
-
-#define TEST_IMSI_IE 0x01, 0x08, 0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0xf5
-#define TEST_IMSI_STR "123456789012345"
-
-static void test_gsup_messages_dec_enc(void)
-{
- int test_idx;
- int rc;
- uint8_t buf[1024];
-
- static const uint8_t send_auth_info_req[] = {
- 0x08,
- TEST_IMSI_IE
- };
-
- static const uint8_t send_auth_info_err[] = {
- 0x09,
- TEST_IMSI_IE,
- 0x02, 0x01, 0x07 /* GPRS no allowed */
- };
-
- static const uint8_t send_auth_info_res[] = {
- 0x0a,
- TEST_IMSI_IE,
- 0x03, 0x22, /* Auth tuple */
- 0x20, 0x10,
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
- 0x21, 0x04,
- 0x21, 0x22, 0x23, 0x24,
- 0x22, 0x08,
- 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x03, 0x22, /* Auth tuple */
- 0x20, 0x10,
- 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
- 0x21, 0x04,
- 0xa1, 0xa2, 0xa3, 0xa4,
- 0x22, 0x08,
- 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8,
- };
-
- static const uint8_t update_location_req[] = {
- 0x04,
- TEST_IMSI_IE,
- };
-
- static const uint8_t update_location_err[] = {
- 0x05,
- TEST_IMSI_IE,
- 0x02, 0x01, 0x07 /* GPRS no allowed */
- };
-
- static const uint8_t update_location_res[] = {
- 0x06,
- TEST_IMSI_IE,
- 0x08, 0x07, /* MSISDN of the subscriber */
- 0x91, 0x94, 0x61, 0x46, 0x32, 0x24, 0x43,
- 0x09, 0x07, /* HLR-Number of the subscriber */
- 0x91, 0x83, 0x52, 0x38, 0x48, 0x83, 0x93,
- 0x04, 0x00, /* PDP info complete */
- 0x05, 0x15,
- 0x10, 0x01, 0x01,
- 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
- 0x12, 0x09, 0x04, 't', 'e', 's', 't', 0x03, 'a', 'p', 'n',
- 0x13, 0x01, 0x02,
- 0x05, 0x11,
- 0x10, 0x01, 0x02,
- 0x11, 0x02, 0xf1, 0x21, /* IPv4 */
- 0x12, 0x08, 0x03, 'f', 'o', 'o', 0x03, 'a', 'p', 'n',
- };
-
- static const uint8_t location_cancellation_req[] = {
- 0x1c,
- TEST_IMSI_IE,
- 0x06, 0x01, 0x00,
- };
-
- static const uint8_t location_cancellation_err[] = {
- 0x1d,
- TEST_IMSI_IE,
- 0x02, 0x01, 0x03 /* Illegal MS */
- };
-
- static const uint8_t location_cancellation_res[] = {
- 0x1e,
- TEST_IMSI_IE,
- };
-
- static const uint8_t purge_ms_req[] = {
- 0x0c,
- TEST_IMSI_IE,
- };
-
- static const uint8_t purge_ms_err[] = {
- 0x0d,
- TEST_IMSI_IE,
- 0x02, 0x01, 0x03, /* Illegal MS */
- };
-
- static const uint8_t purge_ms_res[] = {
- 0x0e,
- TEST_IMSI_IE,
- 0x07, 0x00,
- };
-
- static const struct test {
- char *name;
- const uint8_t *data;
- size_t data_len;
- } test_messages[] = {
- {"Send Authentication Info Request",
- send_auth_info_req, sizeof(send_auth_info_req)},
- {"Send Authentication Info Error",
- send_auth_info_err, sizeof(send_auth_info_err)},
- {"Send Authentication Info Result",
- send_auth_info_res, sizeof(send_auth_info_res)},
- {"Update Location Request",
- update_location_req, sizeof(update_location_req)},
- {"Update Location Error",
- update_location_err, sizeof(update_location_err)},
- {"Update Location Result",
- update_location_res, sizeof(update_location_res)},
- {"Location Cancellation Request",
- location_cancellation_req, sizeof(location_cancellation_req)},
- {"Location Cancellation Error",
- location_cancellation_err, sizeof(location_cancellation_err)},
- {"Location Cancellation Result",
- location_cancellation_res, sizeof(location_cancellation_res)},
- {"Purge MS Request",
- purge_ms_req, sizeof(purge_ms_req)},
- {"Purge MS Error",
- purge_ms_err, sizeof(purge_ms_err)},
- {"Purge MS Result",
- purge_ms_res, sizeof(purge_ms_res)},
- };
-
- printf("Test GSUP message decoding/encoding\n");
-
- for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
- const struct test *t = &test_messages[test_idx];
- struct gprs_gsup_message gm = {0};
- struct msgb *msg = msgb_alloc(4096, "gsup_test");
-
- printf(" Testing %s\n", t->name);
-
- rc = gprs_gsup_decode(t->data, t->data_len, &gm);
- OSMO_ASSERT(rc >= 0);
-
- gprs_gsup_encode(msg, &gm);
-
- fprintf(stderr, " generated message: %s\n", msgb_hexdump(msg));
- fprintf(stderr, " original message: %s\n", osmo_hexdump(t->data, t->data_len));
- fprintf(stderr, " IMSI: %s\n", gm.imsi);
- OSMO_ASSERT(strcmp(gm.imsi, TEST_IMSI_STR) == 0);
- OSMO_ASSERT(msgb_length(msg) == t->data_len);
- OSMO_ASSERT(memcmp(msgb_data(msg), t->data, t->data_len) == 0);
-
- msgb_free(msg);
- }
-
- /* simple truncation test */
- for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
- int j;
- const struct test *t = &test_messages[test_idx];
- int ie_end = t->data_len;
- struct gprs_gsup_message gm = {0};
- int counter = 0;
- int parse_err = 0;
-
- for (j = t->data_len - 1; j >= 0; --j) {
- rc = gprs_gsup_decode(t->data, j, &gm);
- counter += 1;
-
- VERBOSE_FPRINTF(stderr,
- " partial message decoding: "
- "orig_len = %d, trunc = %d, rc = %d, ie_end = %d\n",
- t->data_len, j, rc, ie_end);
- if (rc >= 0) {
- VERBOSE_FPRINTF(stderr,
- " remaing partial message: %s\n",
- osmo_hexdump(t->data + j, ie_end - j));
-
- OSMO_ASSERT(j <= ie_end - 2);
- OSMO_ASSERT(t->data[j+0] <= GPRS_GSUP_KC_IE);
- OSMO_ASSERT(t->data[j+1] <= ie_end - j - 2);
-
- ie_end = j;
- } else {
- parse_err += 1;
- }
- }
-
- fprintf(stderr,
- " message %d: tested %d truncations, %d parse failures\n",
- test_idx, counter, parse_err);
- }
-
- /* message modification test (relies on ASAN or valgrind being used) */
- for (test_idx = 0; test_idx < ARRAY_SIZE(test_messages); test_idx++) {
- int j;
- const struct test *t = &test_messages[test_idx];
- struct gprs_gsup_message gm = {0};
- uint8_t val;
- int counter = 0;
- int parse_err = 0;
-
- OSMO_ASSERT(sizeof(buf) >= t->data_len);
-
- for (j = t->data_len - 1; j >= 0; --j) {
- memcpy(buf, t->data, t->data_len);
- val = 0;
- do {
- VERBOSE_FPRINTF(stderr,
- "t = %d, len = %d, val = %d\n",
- test_idx, j, val);
- buf[j] = val;
- rc = gprs_gsup_decode(buf, t->data_len, &gm);
- counter += 1;
- if (rc < 0)
- parse_err += 1;
-
- val += 1;
- } while (val != (uint8_t)256);
- }
-
- fprintf(stderr,
- " message %d: tested %d modifications, %d parse failures\n",
- test_idx, counter, parse_err);
- }
-}
-
static void test_gprs_timer_enc_dec(void)
{
int i, u, secs, tmr;
@@ -705,8 +229,6 @@ int main(int argc, char **argv)
test_8_4_2();
test_gsm_03_03_apn();
- test_tlv_shift_functions();
- test_gsup_messages_dec_enc();
test_gprs_timer_enc_dec();
printf("Done.\n");
diff --git a/openbsc/tests/gprs/gprs_test.ok b/openbsc/tests/gprs/gprs_test.ok
index cf710769e..da7888c6a 100644
--- a/openbsc/tests/gprs/gprs_test.ok
+++ b/openbsc/tests/gprs/gprs_test.ok
@@ -13,19 +13,5 @@ N(U) = 511, V(UR) = 511 => new
N(U) = 510, V(UR) = 511 => retransmit
N(U) = 481, V(UR) = 511 => retransmit
N(U) = 479, V(UR) = 511 => new
-Test shift functions
-Test GSUP message decoding/encoding
- Testing Send Authentication Info Request
- Testing Send Authentication Info Error
- Testing Send Authentication Info Result
- Testing Update Location Request
- Testing Update Location Error
- Testing Update Location Result
- Testing Location Cancellation Request
- Testing Location Cancellation Error
- Testing Location Cancellation Result
- Testing Purge MS Request
- Testing Purge MS Error
- Testing Purge MS Result
Test GPRS timer decoding/encoding
Done.
diff --git a/openbsc/tests/gsm0408/Makefile.am b/openbsc/tests/gsm0408/Makefile.am
index 619618652..d87913671 100644
--- a/openbsc/tests/gsm0408/Makefile.am
+++ b/openbsc/tests/gsm0408/Makefile.am
@@ -7,5 +7,6 @@ EXTRA_DIST = gsm0408_test.ok
gsm0408_test_SOURCES = gsm0408_test.c
gsm0408_test_LDADD = $(top_builddir)/src/libbsc/libbsc.a \
$(top_builddir)/src/libxsc/libxsc.a \
+ $(top_builddir)/src/libtrau/libtrau.a \
$(top_builddir)/src/libcommon/libcommon.a \
- $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) -ldbi
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOABIS_LIBS) -ldbi
diff --git a/openbsc/tests/gsm0408/gsm0408_test.c b/openbsc/tests/gsm0408/gsm0408_test.c
index 88da271f2..1379c42ce 100644
--- a/openbsc/tests/gsm0408/gsm0408_test.c
+++ b/openbsc/tests/gsm0408/gsm0408_test.c
@@ -29,7 +29,11 @@
#include <openbsc/gsm_subscriber.h>
#include <openbsc/debug.h>
#include <openbsc/arfcn_range_encode.h>
+#include <openbsc/system_information.h>
+#include <openbsc/abis_rsl.h>
+
#include <osmocom/core/application.h>
+#include <osmocom/gsm/sysinfo.h>
#define COMPARE(result, op, value) \
if (!((result) op (value))) {\
@@ -79,6 +83,104 @@ static void test_location_area_identifier(void)
COMPARE(lai48.lac, ==, htons(0x000f));
}
+static inline void add_arfcn_b(struct osmo_earfcn_si2q *e, uint16_t earfcn,
+ uint8_t bw)
+{
+ int r = osmo_earfcn_add(e, earfcn, bw);
+ if (r)
+ printf("failed to add EARFCN %u: %s\n", earfcn, strerror(r));
+ else
+ printf("added EARFCN %u - ", earfcn);
+}
+
+static inline void gen(struct gsm_bts *bts)
+{
+ int r = gsm_generate_si(bts, SYSINFO_TYPE_2quater);
+ if (r > 0)
+ printf("generated SI2quater: [%d] %s\n", r,
+ osmo_hexdump(bts->si_buf[SYSINFO_TYPE_2quater], r));
+ else
+ printf("failed to generate SI2quater: %s\n", strerror(-r));
+}
+
+static inline void _bts_uarfcn_add(struct gsm_bts *bts, uint16_t arfcn,
+ uint16_t scramble, bool diversity)
+{
+ int r = bts_uarfcn_add(bts, arfcn, scramble, diversity);
+ if (r < 0)
+ printf("failed to add UARFCN to SI2quater: %s\n", strerror(-r));
+ else
+ gen(bts);
+}
+
+static inline void test_si2q_u(void)
+{
+ struct gsm_bts *bts;
+ struct gsm_network *network = gsm_network_init(NULL, 1, 1, NULL);
+ printf("Testing SYSINFO_TYPE_2quater UARFCN generation:\n");
+
+ if (!network)
+ exit(1);
+ bts = gsm_bts_alloc(network);
+
+ _bts_uarfcn_add(bts, 1982, 13, 1);
+ _bts_uarfcn_add(bts, 1982, 44, 0);
+ _bts_uarfcn_add(bts, 1982, 61, 1);
+ _bts_uarfcn_add(bts, 1982, 89, 1);
+ _bts_uarfcn_add(bts, 1982, 113, 0);
+ _bts_uarfcn_add(bts, 1982, 123, 0);
+ _bts_uarfcn_add(bts, 1982, 56, 1);
+ _bts_uarfcn_add(bts, 1982, 72, 1);
+ _bts_uarfcn_add(bts, 1982, 223, 1);
+ _bts_uarfcn_add(bts, 1982, 14, 0);
+ _bts_uarfcn_add(bts, 1982, 88, 0);
+ gen(bts);
+}
+
+static inline void test_si2q_e(void)
+{
+ struct gsm_bts *bts;
+ struct gsm_network *network = gsm_network_init(NULL, 1, 1, NULL);
+ printf("Testing SYSINFO_TYPE_2quater EARFCN generation:\n");
+
+ if (!network)
+ exit(1);
+ bts = gsm_bts_alloc(network);
+
+ bts->si_common.si2quater_neigh_list.arfcn =
+ bts->si_common.data.earfcn_list;
+ bts->si_common.si2quater_neigh_list.meas_bw =
+ bts->si_common.data.meas_bw_list;
+ bts->si_common.si2quater_neigh_list.length = MAX_EARFCN_LIST;
+ bts->si_common.si2quater_neigh_list.thresh_hi = 5;
+
+ osmo_earfcn_init(&bts->si_common.si2quater_neigh_list);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1917, 1);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1932,
+ OSMO_EARFCN_MEAS_INVALID);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1937, 2);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1945,
+ OSMO_EARFCN_MEAS_INVALID);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1965,
+ OSMO_EARFCN_MEAS_INVALID);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1967, 4);
+ gen(bts);
+
+ add_arfcn_b(&bts->si_common.si2quater_neigh_list, 1982, 3);
+ gen(bts);
+}
+
static void test_mi_functionality(void)
{
const char *imsi_odd = "987654321098763";
@@ -162,11 +264,7 @@ static int test_single_range_encoding(int range, const int *orig_arfcns,
f0, &f0_included);
memset(w, 0, sizeof(w));
- rc = range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
- if (rc != 0) {
- printf("Cannot compute range W(k), rc = %d\n", rc);
- return 1;
- }
+ range_enc_arfcns(range, arfcns, arfcns_used, w, 0);
if (!silent)
fprintf(stderr, "range=%d, arfcns_used=%d, f0=%d, f0_included=%d\n",
@@ -175,24 +273,20 @@ static int test_single_range_encoding(int range, const int *orig_arfcns,
/* Select the range and the amount of bits needed */
switch (range) {
case ARFCN_RANGE_128:
- rc = range_enc_range128(chan_list, f0, w);
+ range_enc_range128(chan_list, f0, w);
break;
case ARFCN_RANGE_256:
- rc = range_enc_range256(chan_list, f0, w);
+ range_enc_range256(chan_list, f0, w);
break;
case ARFCN_RANGE_512:
- rc = range_enc_range512(chan_list, f0, w);
+ range_enc_range512(chan_list, f0, w);
break;
case ARFCN_RANGE_1024:
- rc = range_enc_range1024(chan_list, f0, f0_included, w);
+ range_enc_range1024(chan_list, f0, f0_included, w);
break;
default:
return 1;
};
- if (rc != 0) {
- printf("Cannot encode range, rc = %d\n", rc);
- return 1;
- }
if (!silent)
printf("chan_list = %s\n",
@@ -403,8 +497,7 @@ static void test_print_encoding()
break;
}
- rc = range_enc_range512(chan_list, (1 << 9) | 0x96, w);
- VERIFY(rc, ==, 0);
+ range_enc_range512(chan_list, (1 << 9) | 0x96, w);
printf("Range512: %s\n", osmo_hexdump(chan_list, ARRAY_SIZE(chan_list)));
}
@@ -428,8 +521,7 @@ static void test_si_range_helpers()
printf("Element is: %d => freqs[i] = %d\n", i, i >= 0 ? freqs3[i] : -1);
VERIFY(i, ==, 0);
- i = range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
- VERIFY(i, ==, 0);
+ range_enc_arfcns(1023, freqs1, ARRAY_SIZE(freqs1), ws, 0);
for (i = 0; i < sizeof(freqs1)/sizeof(freqs1[0]); ++i) {
printf("w[%d]=%d\n", i, ws[i]);
@@ -486,6 +578,8 @@ int main(int argc, char **argv)
test_range_encoding();
test_gsm411_rp_ref_wrap();
+ test_si2q_e();
+ test_si2q_u();
printf("Done.\n");
return EXIT_SUCCESS;
}
diff --git a/openbsc/tests/gsm0408/gsm0408_test.ok b/openbsc/tests/gsm0408/gsm0408_test.ok
index 058563aab..7b7a2cc76 100644
--- a/openbsc/tests/gsm0408/gsm0408_test.ok
+++ b/openbsc/tests/gsm0408/gsm0408_test.ok
@@ -62,4 +62,25 @@ testing RP-Reference wrap
Allocated reference: 255
Allocated reference: 0
Allocated reference: 1
+Testing SYSINFO_TYPE_2quater EARFCN generation:
+added EARFCN 1917 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be c8 50 0b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+added EARFCN 1932 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 30 14 03 2b 2b 2b 2b 2b 2b 2b 2b
+added EARFCN 1937 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a0 a0 2b 2b 2b 2b 2b 2b
+added EARFCN 1945 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c c8 28 0b 2b 2b 2b
+added EARFCN 1965 - generated SI2quater: [23] 59 06 07 c0 00 04 86 59 83 be cc 1e 31 07 91 a8 3c ca 0f 5a 0a 03 2b
+added EARFCN 1967 - failed to generate SI2quater: Cannot allocate memory
+added EARFCN 1982 - failed to generate SI2quater: Cannot allocate memory
+Testing SYSINFO_TYPE_2quater UARFCN generation:
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 0c 1a 10 99 64 00 0b 2b 2b 2b 2b 2b 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 14 1a 1f 00 44 b2 00 03 2b 2b 2b 2b 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 18 58 12 f0 84 86 59 00 03 2b 2b 2b 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 20 58 2e f0 f2 04 86 59 00 03 2b 2b 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 28 58 2e 22 f2 4e 84 86 59 00 03 2b 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 34 1a 64 26 5d f2 05 04 86 59 00 03 2b 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 38 58 12 22 fd ce 8e 05 04 86 59 00 03 2b 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 40 58 1d 22 fa ce 88 85 7b 00 44 b2 00 03 2b
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b
+failed to add UARFCN to SI2quater: No space left on device
+failed to add UARFCN to SI2quater: No space left on device
+generated SI2quater: [23] 59 06 07 c0 00 25 0f 7c 4c 7a 34 0e 64 77 85 43 55 c8 10 99 64 00 0b
Done.
diff --git a/openbsc/tests/gtphub/gtphub_test.c b/openbsc/tests/gtphub/gtphub_test.c
index 8ce83c82e..e24967b85 100644
--- a/openbsc/tests/gtphub/gtphub_test.c
+++ b/openbsc/tests/gtphub/gtphub_test.c
@@ -388,7 +388,7 @@ static void test_expiry(void)
#undef MAP3
}
-char resolve_ggsn_got_imsi[GSM_IMSI_LENGTH];
+char resolve_ggsn_got_imsi[GSM23003_IMSI_MAX_DIGITS+1];
char resolve_ggsn_got_ni[GSM_APN_LENGTH];
struct osmo_sockaddr resolved_ggsn_addr;
diff --git a/openbsc/tests/mm_auth/mm_auth_test.c b/openbsc/tests/mm_auth/mm_auth_test.c
index 34d96f187..b8777a8c5 100644
--- a/openbsc/tests/mm_auth/mm_auth_test.c
+++ b/openbsc/tests/mm_auth/mm_auth_test.c
@@ -26,9 +26,9 @@ static char *auth_tuple_str(struct gsm_auth_tuple *atuple)
print2buf("gsm_auth_tuple {\n");
print2buf(" .use_count = %d\n", atuple->use_count);
print2buf(" .key_seq = %d\n", atuple->key_seq);
- print2buf(" .rand = %s\n", osmo_hexdump(atuple->rand, sizeof(atuple->rand)));
- print2buf(" .sres = %s\n", osmo_hexdump(atuple->sres, sizeof(atuple->sres)));
- print2buf(" .kc = %s\n", osmo_hexdump(atuple->kc, sizeof(atuple->kc)));
+ print2buf(" .rand = %s\n", osmo_hexdump(atuple->vec.rand, sizeof(atuple->vec.rand)));
+ print2buf(" .sres = %s\n", osmo_hexdump(atuple->vec.sres, sizeof(atuple->vec.sres)));
+ print2buf(" .kc = %s\n", osmo_hexdump(atuple->vec.kc, sizeof(atuple->vec.kc)));
print2buf("}\n");
#undef print2buf
diff --git a/openbsc/tests/oap/Makefile.am b/openbsc/tests/oap/Makefile.am
index 3a76b11ad..538e1787e 100644
--- a/openbsc/tests/oap/Makefile.am
+++ b/openbsc/tests/oap/Makefile.am
@@ -15,7 +15,6 @@ 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) \
diff --git a/openbsc/tests/oap/oap_test.c b/openbsc/tests/oap/oap_test.c
index 9a2063bdc..339d77430 100644
--- a/openbsc/tests/oap/oap_test.c
+++ b/openbsc/tests/oap/oap_test.c
@@ -26,6 +26,7 @@
#include <openbsc/oap_messages.h>
#include <stdio.h>
+#include <string.h>
static void test_oap_api(void)
{
@@ -94,8 +95,8 @@ static void test_oap_api(void)
printf(" - AUTN failures\n");
- struct oap_message oap_rx;
- struct oap_message oap_tx;
+ struct osmo_oap_message oap_rx;
+ struct osmo_oap_message oap_tx;
struct msgb *msg_rx;
struct msgb *msg_tx;
@@ -167,7 +168,7 @@ static void test_oap_api(void)
/* 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(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 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)))
@@ -190,7 +191,7 @@ static void test_oap_api(void)
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(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0);
OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST);
OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE);
msgb_free(msg_tx);
diff --git a/openbsc/tests/sgsn/Makefile.am b/openbsc/tests/sgsn/Makefile.am
index 477658c01..6e2416de7 100644
--- a/openbsc/tests/sgsn/Makefile.am
+++ b/openbsc/tests/sgsn/Makefile.am
@@ -23,7 +23,6 @@ sgsn_test_LDADD = \
$(top_builddir)/src/gprs/sgsn_libgtp.o \
$(top_builddir)/src/gprs/sgsn_auth.o \
$(top_builddir)/src/gprs/sgsn_ares.o \
- $(top_builddir)/src/gprs/gprs_gsup_messages.o \
$(top_builddir)/src/gprs/gprs_gsup_client.o \
$(top_builddir)/src/gprs/gprs_utils.o \
$(top_builddir)/src/gprs/gprs_subscriber.o \
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index 2c5e2b429..15c4c17d0 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -24,7 +24,7 @@
#include <openbsc/gprs_gmm.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_subscriber.h>
-#include <openbsc/gprs_gsup_messages.h>
+#include <osmocom/gsm/gsup.h>
#include <openbsc/gprs_gsup_client.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/gprs_gb_parse.h>
@@ -32,7 +32,6 @@
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gsm/gsm_utils.h>
-#include <openbsc/gsm_04_08_gprs.h>
#include <osmocom/core/application.h>
#include <osmocom/core/msgb.h>
@@ -617,8 +616,8 @@ static void test_subscriber_gsup(void)
/* Inject InsertSubscrData GSUP message */
last_updated_subscr = NULL;
rc = rx_gsup_message(insert_data_req, sizeof(insert_data_req));
- OSMO_ASSERT(rc == -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
- OSMO_ASSERT(last_updated_subscr == NULL);
+ OSMO_ASSERT(rc = -ENOTSUP); /* not connected */
+ OSMO_ASSERT(last_updated_subscr == s1);
/* Inject DeleteSubscrData GSUP message */
last_updated_subscr = NULL;
@@ -1138,7 +1137,7 @@ static void test_gmm_attach_subscr_fake_auth(void)
int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
{
struct gsm_auth_tuple at = {
- .sres = {0x51, 0xe5, 0x51, 0xe5},
+ .vec.sres = {0x51, 0xe5, 0x51, 0xe5},
.key_seq = 0
};
@@ -1273,13 +1272,13 @@ static void test_gmm_attach_subscr_gsup_auth(int retry)
int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
{
- struct gprs_gsup_message to_peer = {0};
- struct gprs_gsup_message from_peer = {0};
+ struct osmo_gsup_message to_peer = {0};
+ struct osmo_gsup_message from_peer = {0};
struct msgb *reply_msg;
int rc;
/* Simulate the GSUP peer */
- rc = gprs_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
+ rc = osmo_gsup_decode(msgb_data(msg), msgb_length(msg), &to_peer);
OSMO_ASSERT(rc >= 0);
OSMO_ASSERT(to_peer.imsi[0] != 0);
strncpy(from_peer.imsi, to_peer.imsi, sizeof(from_peer.imsi));
@@ -1288,16 +1287,16 @@ int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
msgb_free(msg);
switch (to_peer.message_type) {
- case GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
+ case OSMO_GSUP_MSGT_UPDATE_LOCATION_REQUEST:
/* Send UPDATE_LOCATION_RESULT */
return my_subscr_request_update_gsup_auth(NULL);
- case GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
+ case OSMO_GSUP_MSGT_SEND_AUTH_INFO_REQUEST:
/* Send SEND_AUTH_INFO_RESULT */
return my_subscr_request_auth_info_gsup_auth(NULL);
- case GPRS_GSUP_MSGT_PURGE_MS_REQUEST:
- from_peer.message_type = GPRS_GSUP_MSGT_PURGE_MS_RESULT;
+ case OSMO_GSUP_MSGT_PURGE_MS_REQUEST:
+ from_peer.message_type = OSMO_GSUP_MSGT_PURGE_MS_RESULT;
break;
default:
@@ -1315,7 +1314,7 @@ int my_gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg)
reply_msg = gprs_gsup_msgb_alloc();
reply_msg->l2h = reply_msg->data;
- gprs_gsup_encode(reply_msg, &from_peer);
+ osmo_gsup_encode(reply_msg, &from_peer);
gprs_subscr_rx_gsup_message(reply_msg);
msgb_free(reply_msg);
diff --git a/openbsc/tests/vty_test_runner.py b/openbsc/tests/vty_test_runner.py
index 8db0825e3..c0888559e 100644
--- a/openbsc/tests/vty_test_runner.py
+++ b/openbsc/tests/vty_test_runner.py
@@ -231,6 +231,43 @@ class TestVTYNITB(TestVTYGenericBSC):
self.assertEquals(self.vty.node(), 'config-mncc-int')
+ def testSi2Q(self):
+ self.vty.enable()
+ self.vty.command("configure terminal")
+ self.vty.command("network")
+ self.vty.command("bts 0")
+ before = self.vty.command("show running-config")
+ self.vty.command("si2quater neighbor-list add earfcn 1911 threshold 11 2")
+ self.vty.command("si2quater neighbor-list add earfcn 1924 threshold 11 3")
+ self.vty.command("si2quater neighbor-list add earfcn 2111 threshold 11")
+ self.vty.command("si2quater neighbor-list del earfcn 1911")
+ self.vty.command("si2quater neighbor-list del earfcn 1924")
+ self.vty.command("si2quater neighbor-list del earfcn 2111")
+ self.assertEquals(before, self.vty.command("show running-config"))
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 13 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 38 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 44 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 120 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 140 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 163 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 166 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 217 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 224 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 225 1")
+ self.vty.command("si2quater neighbor-list add uarfcn 1976 226 1")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 13")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 38")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 44")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 120")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 140")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 163")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 166")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 217")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 224")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 225")
+ self.vty.command("si2quater neighbor-list del uarfcn 1976 226")
+ self.assertEquals(before, self.vty.command("show running-config"))
+
def testEnableDisablePeriodicLU(self):
self.vty.enable()
self.vty.command("configure terminal")
@@ -307,6 +344,42 @@ class TestVTYNITB(TestVTYGenericBSC):
if classNum != 10:
self.assertEquals(res.find("rach access-control-class " + str(classNum) + " barred"), -1)
+ def testSubscriberCreateDeleteTwice(self):
+ """
+ OS#1657 indicates that there might be an issue creating the
+ same subscriber twice. This test will use the VTY command to
+ create a subscriber and then issue a second create command
+ with the same IMSI. The test passes if the VTY continues to
+ respond to VTY commands.
+ """
+ self.vty.enable()
+
+ imsi = "204300854013739"
+
+ # Initially we don't have this subscriber
+ self.vty.verify('show subscriber imsi '+imsi, ['% No subscriber found for imsi '+imsi])
+
+ # Lets create one
+ res = self.vty.command('subscriber create imsi '+imsi)
+ self.assert_(res.find(" IMSI: "+imsi) > 0)
+ # And now create one again.
+ res2 = self.vty.command('subscriber create imsi '+imsi)
+ self.assert_(res2.find(" IMSI: "+imsi) > 0)
+ self.assertEqual(res, res2)
+
+ # Verify it has been created
+ res = self.vty.command('show subscriber imsi '+imsi)
+ self.assert_(res.find(" IMSI: "+imsi) > 0)
+
+ # Delete it
+ res = self.vty.command('subscriber delete imsi '+imsi)
+ self.assert_(res != "")
+
+ # Now it should not be there anymore
+ res = self.vty.command('show subscriber imsi '+imsi)
+ self.assert_(res != '% No subscriber found for imsi '+imsi)
+
+
def testSubscriberCreateDelete(self):
self.vty.enable()
@@ -584,12 +657,63 @@ class TestVTYBSC(TestVTYGenericBSC):
class TestVTYNAT(TestVTYGenericBSC):
def vty_command(self):
- return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-c",
+ return ["./src/osmo-bsc_nat/osmo-bsc_nat", "-l", "127.0.0.1", "-c",
"doc/examples/osmo-bsc_nat/osmo-bsc_nat.cfg"]
def vty_app(self):
return (4244, "src/osmo-bsc_nat/osmo-bsc_nat", "OsmoBSCNAT", "nat")
+ def testBSCreload(self):
+ # Use different port for the mock msc to avoid clashing with
+ # the osmo-bsc_nat itself
+ ip = "127.0.0.1"
+ port = 5522
+ self.vty.enable()
+ bscs1 = self.vty.command("show bscs-config")
+ nat_bsc_reload(self)
+ bscs2 = self.vty.command("show bscs-config")
+ # check that multiple calls to bscs-config-file give the same result
+ self.assertEquals(bscs1, bscs2)
+
+ # add new bsc
+ self.vty.command("configure terminal")
+ self.vty.command("nat")
+ self.vty.command("bsc 5")
+ self.vty.command("token key")
+ self.vty.command("location_area_code 666")
+ self.vty.command("end")
+
+ # update bsc token
+ self.vty.command("configure terminal")
+ self.vty.command("nat")
+ self.vty.command("bsc 1")
+ self.vty.command("token xyu")
+ self.vty.command("end")
+
+ nat_msc_ip(self, ip, port)
+ msc = nat_msc_test(self, ip, port)
+ b0 = nat_bsc_sock_test(0, "lol")
+ b1 = nat_bsc_sock_test(1, "xyu")
+ b2 = nat_bsc_sock_test(5, "key")
+
+ self.assertEquals("3 BSCs configured", self.vty.command("show nat num-bscs-configured"))
+ self.assertTrue(3 == nat_bsc_num_con(self))
+ self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
+
+ nat_bsc_reload(self)
+ bscs2 = self.vty.command("show bscs-config")
+ # check that the reset to initial config succeeded
+ self.assertEquals(bscs1, bscs2)
+
+ self.assertEquals("2 BSCs configured", self.vty.command("show nat num-bscs-configured"))
+ self.assertTrue(1 == nat_bsc_num_con(self))
+ rem = self.vty.command("show bsc connections").split(' ')
+ # remaining connection is for BSC0
+ self.assertEquals('0', rem[2])
+ # remaining connection is authorized
+ self.assertEquals('1', rem[4])
+ self.assertEquals("MSC is connected: 1", self.vty.command("show msc connection"))
+
def testVtyTree(self):
self.vty.enable()
self.assertTrue(self.vty.verify('configure terminal', ['']))
@@ -700,13 +824,13 @@ class TestVTYNAT(TestVTYGenericBSC):
self.assertEqual(data, "\x00\x01\xfe\x04")
print "Going to send ID_RESP response"
- res = ussdSocket.send("\x00\x07\xfe\x05\x00\x04\x01\x6b\x65\x79")
+ res = ipa_send_resp(ussdSocket, "\x6b\x65\x79")
self.assertEqual(res, 10)
# initiating PING/PONG cycle to know, that the ID_RESP message has been processed
print "Going to send PING request"
- res = ussdSocket.send("\x00\x01\xfe\x00")
+ res = ipa_send_ping(ussdSocket)
self.assertEqual(res, 4)
print "Expecting PONG response"
@@ -971,6 +1095,101 @@ def add_nat_test(suite, workdir):
test = unittest.TestLoader().loadTestsFromTestCase(TestVTYNAT)
suite.addTest(test)
+def ipa_send_pong(x, verbose = False):
+ if (verbose):
+ print "\tBSC -> NAT: PONG!"
+ return x.send("\x00\x01\xfe\x01")
+
+def ipa_send_ping(x, verbose = False):
+ if (verbose):
+ print "\tBSC -> NAT: PING?"
+ return x.send("\x00\x01\xfe\x00")
+
+def ipa_send_ack(x, verbose = False):
+ if (verbose):
+ print "\tBSC -> NAT: IPA ID ACK"
+ return x.send("\x00\x01\xfe\x06")
+
+def ipa_send_reset(x, verbose = False):
+ if (verbose):
+ print "\tBSC -> NAT: RESET"
+ return x.send("\x00\x12\xfd\x09\x00\x03\x05\x07\x02\x42\xfe\x02\x42\xfe\x06\x00\x04\x30\x04\x01\x20")
+
+def ipa_send_resp(x, tk, verbose = False):
+ if (verbose):
+ print "\tBSC -> NAT: IPA ID RESP"
+ return x.send("\x00\x07\xfe\x05\x00\x04\x01" + tk)
+
+def nat_bsc_reload(x):
+ x.vty.command("configure terminal")
+ x.vty.command("nat")
+ x.vty.command("bscs-config-file bscs.config")
+ x.vty.command("end")
+
+def nat_msc_ip(x, ip, port):
+ x.vty.command("configure terminal")
+ x.vty.command("nat")
+ x.vty.command("msc ip " + ip)
+ x.vty.command("msc port " + str(port))
+ x.vty.command("end")
+
+def data2str(d):
+ return d.encode('hex').lower()
+
+def nat_msc_test(x, ip, port, verbose = False):
+ msc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ msc.settimeout(32)
+ msc.bind((ip, port))
+ msc.listen(5)
+ if (verbose):
+ print "MSC is ready at " + ip
+ while "MSC is connected: 0" == x.vty.command("show msc connection"):
+ conn, addr = msc.accept()
+ if (verbose):
+ print "MSC got connection from ", addr
+ return conn
+
+def ipa_handle_small(x, verbose = False):
+ s = data2str(x.recv(4))
+ if "0001fe00" == s:
+ if (verbose):
+ print "\tBSC <- NAT: PING?"
+ ipa_send_pong(x, verbose)
+ elif "0001fe06" == s:
+ if (verbose):
+ print "\tBSC <- NAT: IPA ID ACK"
+ ipa_send_ack(x, verbose)
+ elif "0001fe00" == s:
+ if (verbose):
+ print "\tBSC <- NAT: PONG!"
+ else:
+ if (verbose):
+ print "\tBSC <- NAT: ", s
+
+def ipa_handle_resp(x, tk, verbose = False):
+ s = data2str(x.recv(38))
+ if "0023fe040108010701020103010401050101010011" in s:
+ ipa_send_resp(x, tk, verbose)
+ else:
+ if (verbose):
+ print "\tBSC <- NAT: ", s
+
+def nat_bsc_num_con(x):
+ return len(x.vty.command("show bsc connections").split('\n'))
+
+def nat_bsc_sock_test(nr, tk, verbose = False):
+ bsc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ bsc.bind(('127.0.0.1', 0))
+ bsc.connect(('127.0.0.1', 5000))
+ if (verbose):
+ print "BSC%d " %nr
+ print "\tconnected to %s:%d" % bsc.getpeername()
+ ipa_handle_small(bsc, verbose)
+ ipa_handle_resp(bsc, tk, verbose)
+ bsc.recv(27) # MGCP msg
+ ipa_handle_small(bsc, verbose)
+ return bsc
+
def add_bsc_test(suite, workdir):
if not os.path.isfile(os.path.join(workdir, "src/osmo-bsc/osmo-bsc")):
print("Skipping the BSC test")