aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am20
-rw-r--r--include/osmocom/codec/codec.h6
-rw-r--r--include/osmocom/codec/ecu.h64
-rw-r--r--include/osmocom/coding/gsm0503_amr_dtx.h40
-rw-r--r--include/osmocom/coding/gsm0503_coding.h6
-rw-r--r--include/osmocom/coding/gsm0503_parity.h19
-rw-r--r--include/osmocom/core/application.h9
-rw-r--r--include/osmocom/core/bitXXgen.h.tpl27
-rw-r--r--include/osmocom/core/defs.h2
-rw-r--r--include/osmocom/core/exec.h29
-rw-r--r--include/osmocom/core/fsm.h2
-rw-r--r--include/osmocom/core/gsmtap.h40
-rw-r--r--include/osmocom/core/gsmtap_util.h6
-rw-r--r--include/osmocom/core/logging.h48
-rw-r--r--include/osmocom/core/logging_internal.h3
-rw-r--r--include/osmocom/core/msgb.h19
-rw-r--r--include/osmocom/core/rate_ctr.h3
-rw-r--r--include/osmocom/core/select.h40
-rw-r--r--include/osmocom/core/sockaddr_str.h21
-rw-r--r--include/osmocom/core/socket.h43
-rw-r--r--include/osmocom/core/stat_item.h4
-rw-r--r--include/osmocom/core/stats.h5
-rw-r--r--include/osmocom/core/talloc.h28
-rw-r--r--include/osmocom/core/tdef.h7
-rw-r--r--include/osmocom/core/timer.h1
-rw-r--r--include/osmocom/core/use_count.h5
-rw-r--r--include/osmocom/core/utils.h73
-rw-r--r--include/osmocom/core/write_queue.h1
-rw-r--r--include/osmocom/ctrl/ports.h3
-rw-r--r--include/osmocom/gprs/gprs_bssgp.h5
-rw-r--r--include/osmocom/gprs/gprs_bssgp_bss.h1
-rw-r--r--include/osmocom/gprs/gprs_ns.h8
-rw-r--r--include/osmocom/gprs/gprs_ns2.h206
-rw-r--r--include/osmocom/gprs/gprs_ns_frgre.h3
-rw-r--r--include/osmocom/gprs/protocol/gsm_04_60.h153
-rw-r--r--include/osmocom/gprs/protocol/gsm_08_16.h10
-rw-r--r--include/osmocom/gsm/bsslap.h57
-rw-r--r--include/osmocom/gsm/bssmap_le.h81
-rw-r--r--include/osmocom/gsm/bts_features.h11
-rw-r--r--include/osmocom/gsm/cbsp.h4
-rw-r--r--include/osmocom/gsm/gad.h190
-rw-r--r--include/osmocom/gsm/gsm0502.h40
-rw-r--r--include/osmocom/gsm/gsm0808.h14
-rw-r--r--include/osmocom/gsm/gsm0808_lcs.h52
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h6
-rw-r--r--include/osmocom/gsm/gsm23236.h60
-rw-r--r--include/osmocom/gsm/gsm48.h57
-rw-r--r--include/osmocom/gsm/gsm48_ie.h3
-rw-r--r--include/osmocom/gsm/gsm48_rest_octets.h3
-rw-r--r--include/osmocom/gsm/gsm_utils.h4
-rw-r--r--include/osmocom/gsm/gsup.h15
-rw-r--r--include/osmocom/gsm/i460_mux.h121
-rw-r--r--include/osmocom/gsm/l1sap.h15
-rw-r--r--include/osmocom/gsm/lapd_core.h10
-rw-r--r--include/osmocom/gsm/lapdm.h12
-rw-r--r--include/osmocom/gsm/mncc.h8
-rw-r--r--include/osmocom/gsm/prim.h2
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h281
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_08.h40
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_58.h5
-rw-r--r--include/osmocom/gsm/protocol/gsm_12_21.h8
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_032.h172
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_041.h8
-rw-r--r--include/osmocom/gsm/protocol/gsm_29_118.h2
-rw-r--r--include/osmocom/gsm/protocol/gsm_48_071.h122
-rw-r--r--include/osmocom/gsm/protocol/gsm_49_031.h212
-rw-r--r--include/osmocom/gsm/protocol/ipaccess.h37
-rw-r--r--include/osmocom/gsm/tlv.h45
-rw-r--r--include/osmocom/sim/sim.h66
-rw-r--r--include/osmocom/usb/libusb.h119
-rw-r--r--include/osmocom/vty/command.h75
-rw-r--r--include/osmocom/vty/cpu_sched_vty.h37
-rw-r--r--include/osmocom/vty/ports.h3
-rw-r--r--include/osmocom/vty/tdef_vty.h5
-rw-r--r--include/osmocom/vty/vty.h27
75 files changed, 2475 insertions, 514 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index a82d6ac4..44ff3789 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -23,6 +23,7 @@ nobase_include_HEADERS = \
osmocom/core/crcgen.h \
osmocom/core/endian.h \
osmocom/core/defs.h \
+ osmocom/core/exec.h \
osmocom/core/fsm.h \
osmocom/core/gsmtap.h \
osmocom/core/gsmtap_util.h \
@@ -64,6 +65,7 @@ nobase_include_HEADERS = \
osmocom/gprs/gprs_msgb.h \
osmocom/gprs/gprs_ns.h \
osmocom/gprs/gprs_ns_frgre.h \
+ osmocom/gprs/gprs_ns2.h \
osmocom/gprs/gprs_rlc.h \
osmocom/gprs/protocol/gsm_04_60.h \
osmocom/gprs/protocol/gsm_08_16.h \
@@ -89,10 +91,16 @@ nobase_include_HEADERS = \
osmocom/coding/gsm0503_mapping.h \
osmocom/coding/gsm0503_interleaving.h \
osmocom/coding/gsm0503_coding.h \
+ osmocom/coding/gsm0503_amr_dtx.h \
+ osmocom/gsm/bsslap.h \
+ osmocom/gsm/bssmap_le.h \
+ osmocom/gsm/gad.h \
osmocom/gsm/gsm0808.h \
+ osmocom/gsm/gsm0808_lcs.h \
osmocom/gsm/gsm29205.h \
osmocom/gsm/gsm0808_utils.h \
osmocom/gsm/gsm23003.h \
+ osmocom/gsm/gsm23236.h \
osmocom/gsm/gsm29118.h \
osmocom/gsm/gsm48.h \
osmocom/gsm/gsm48_arfcn_range_encode.h \
@@ -101,6 +109,7 @@ nobase_include_HEADERS = \
osmocom/gsm/gsm_utils.h \
osmocom/gsm/gsup.h \
osmocom/gsm/gsup_sms.h \
+ osmocom/gsm/i460_mux.h \
osmocom/gsm/ipa.h \
osmocom/gsm/lapd_core.h \
osmocom/gsm/lapdm.h \
@@ -110,6 +119,7 @@ nobase_include_HEADERS = \
osmocom/gsm/l1sap.h \
osmocom/gsm/oap.h \
osmocom/gsm/oap_client.h \
+ osmocom/gsm/protocol/gsm_23_032.h \
osmocom/gsm/protocol/gsm_03_40.h \
osmocom/gsm/protocol/gsm_03_41.h \
osmocom/gsm/protocol/gsm_04_08.h \
@@ -127,6 +137,8 @@ nobase_include_HEADERS = \
osmocom/gsm/protocol/gsm_29_118.h \
osmocom/gsm/protocol/gsm_44_318.h \
osmocom/gsm/protocol/gsm_48_049.h \
+ osmocom/gsm/protocol/gsm_48_071.h \
+ osmocom/gsm/protocol/gsm_49_031.h \
osmocom/gsm/protocol/ipaccess.h \
osmocom/gsm/protocol/smpp34_osmocom.h \
osmocom/gsm/rsl.h \
@@ -160,10 +172,16 @@ nobase_include_HEADERS += \
osmocom/vty/vector.h \
osmocom/vty/vty.h \
osmocom/vty/ports.h \
+ osmocom/vty/cpu_sched_vty.h \
osmocom/vty/tdef_vty.h \
osmocom/ctrl/control_vty.h
endif
+if ENABLE_LIBUSB
+nobase_include_HEADERS += \
+ osmocom/usb/libusb.h
+endif
+
noinst_HEADERS = \
osmocom/gsm/kasumi.h \
osmocom/gsm/gea.h \
@@ -179,7 +197,7 @@ osmocom/core/crc%gen.h: osmocom/core/crcXXgen.h.tpl
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
osmocom/gsm/gsm0503.h: $(top_srcdir)/utils/conv_gen.py $(top_srcdir)/utils/conv_codes_gsm.py
- $(AM_V_GEN)python $(top_srcdir)/utils/conv_gen.py gen_header gsm \
+ $(AM_V_GEN)python3 $(top_srcdir)/utils/conv_gen.py gen_header gsm \
--target-path $(builddir)/osmocom/gsm
CLEANFILES = osmocom/gsm/gsm0503.h
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h
index 6a1bf9fb..cbdad75e 100644
--- a/include/osmocom/codec/codec.h
+++ b/include/osmocom/codec/codec.h
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
/* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
#define GSM_FR_BYTES 33
@@ -51,6 +52,11 @@ enum osmo_amr_quality {
AMR_GOOD = 1
};
+extern const uint8_t gsm690_bitlength[AMR_NO_DATA+1];
+
+int osmo_amr_s_to_d(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);
+int osmo_amr_d_to_s(ubit_t *out, const ubit_t *in, uint16_t n_bits, enum osmo_amr_type amr_mode);
+
/*! Check if given AMR Frame Type is a speech frame
* \param[in] ft AMR Frame Type
* \returns true if AMR with given Frame Type contains voice, false otherwise
diff --git a/include/osmocom/codec/ecu.h b/include/osmocom/codec/ecu.h
index ec0a2f8d..668df367 100644
--- a/include/osmocom/codec/ecu.h
+++ b/include/osmocom/codec/ecu.h
@@ -3,13 +3,71 @@
#include <stdint.h>
#include <stdbool.h>
+#include <osmocom/core/defs.h>
#include <osmocom/codec/codec.h>
-/* Codec independent ECU state */
+/* ECU state for GSM-FR */
struct osmo_ecu_fr_state {
bool subsequent_lost_frame;
uint8_t frame_backup[GSM_FR_BYTES];
};
-void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, const uint8_t *frame);
-int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame);
+void osmo_ecu_fr_reset(struct osmo_ecu_fr_state *state, const uint8_t *frame)
+ OSMO_DEPRECATED_OUTSIDE("Use generic ECU abstraction layer instead");
+int osmo_ecu_fr_conceal(struct osmo_ecu_fr_state *state, uint8_t *frame)
+ OSMO_DEPRECATED_OUTSIDE("Use generic ECU abstraction layer instead");
+
+enum osmo_ecu_codec {
+ OSMO_ECU_CODEC_HR,
+ OSMO_ECU_CODEC_FR,
+ OSMO_ECU_CODEC_EFR,
+ OSMO_ECU_CODEC_AMR,
+ _NUM_OSMO_ECU_CODECS
+};
+
+/***********************************************************************
+ * Generic ECU abstraction layer below
+ ***********************************************************************/
+
+/* As the developer and copyright holder of the related code, I hereby
+ * state that any ECU implementation using 'struct osmo_ecu_ops' and
+ * registering with the 'osmo_ecu_register()' function shall not be
+ * considered as a derivative work under any applicable copyright law;
+ * the copyleft terms of GPLv2 shall hence not apply to any such ECU
+ * implementation.
+ *
+ * The intent of the above exception is to allow anyone to combine third
+ * party Error Concealment Unit implementations with libosmocodec.
+ * including but not limited to such published by ETSI.
+ *
+ * -- Harald Welte <laforge@gnumonks.org> on August 1, 2019.
+ */
+
+/* Codec independent ECU state */
+struct osmo_ecu_state {
+ enum osmo_ecu_codec codec;
+ uint8_t data[0];
+};
+
+/* initialize an ECU instance */
+struct osmo_ecu_state *osmo_ecu_init(void *ctx, enum osmo_ecu_codec codec);
+
+/* destroy an ECU instance */
+void osmo_ecu_destroy(struct osmo_ecu_state *st);
+
+/* process a received frame a substitute/erroneous frame */
+int osmo_ecu_frame_in(struct osmo_ecu_state *st, bool bfi,
+ const uint8_t *frame, unsigned int frame_bytes);
+
+/* generate output data for a substitute/erroneous frame */
+int osmo_ecu_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out);
+
+struct osmo_ecu_ops {
+ struct osmo_ecu_state * (*init)(void *ctx, enum osmo_ecu_codec codec);
+ void (*destroy)(struct osmo_ecu_state *);
+ int (*frame_in)(struct osmo_ecu_state *st, bool bfi,
+ const uint8_t *frame, unsigned int frame_bytes);
+ int (*frame_out)(struct osmo_ecu_state *st, uint8_t *frame_out);
+};
+
+int osmo_ecu_register(const struct osmo_ecu_ops *ops, enum osmo_ecu_codec codec);
diff --git a/include/osmocom/coding/gsm0503_amr_dtx.h b/include/osmocom/coding/gsm0503_amr_dtx.h
new file mode 100644
index 00000000..f048a6e3
--- /dev/null
+++ b/include/osmocom/coding/gsm0503_amr_dtx.h
@@ -0,0 +1,40 @@
+/*! \file gsm0503_amr_dtx.h
+ * GSM TS 05.03 coding
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <osmocom/core/defs.h>
+#include <osmocom/core/bits.h>
+
+/*! \addtogroup coding
+ * @{
+ * \file gsm0503_amr_dtx.h */
+
+enum gsm0503_amr_dtx_frames {
+ AMR_OTHER,
+ AFS_SID_FIRST,
+ AFS_SID_UPDATE,
+ AFS_SID_UPDATE_CN,
+ AFS_ONSET,
+ AHS_SID_UPDATE,
+ AHS_SID_UPDATE_CN,
+ AHS_SID_FIRST_P1,
+ AHS_SID_FIRST_P2,
+ AHS_ONSET,
+ AHS_SID_FIRST_INH,
+ AHS_SID_UPDATE_INH,
+};
+
+extern const struct value_string gsm0503_amr_dtx_frame_names[];
+static inline const char *gsm0503_amr_dtx_frame_name(enum gsm0503_amr_dtx_frames frame)
+{
+ return get_value_string(gsm0503_amr_dtx_frame_names, frame);
+}
+
+enum gsm0503_amr_dtx_frames gsm0503_detect_afs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t *ubits);
+enum gsm0503_amr_dtx_frames gsm0503_detect_ahs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t *ubits);
+
+/*! @} */
diff --git a/include/osmocom/coding/gsm0503_coding.h b/include/osmocom/coding/gsm0503_coding.h
index 98038f8f..2afa049b 100644
--- a/include/osmocom/coding/gsm0503_coding.h
+++ b/include/osmocom/coding/gsm0503_coding.h
@@ -58,12 +58,18 @@ int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,
int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
uint8_t *cmr, int *n_errors, int *n_bits_total);
+int gsm0503_tch_afs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx);
int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr);
int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
uint8_t *cmr, int *n_errors, int *n_bits_total);
+int gsm0503_tch_ahs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts, int odd,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx);
int gsm0503_rach_ext_encode(ubit_t *burst, uint16_t ra, uint8_t bsic, bool is_11bit);
int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic) OSMO_DEPRECATED("Use gsm0503_rach_ext_encode() instead");
diff --git a/include/osmocom/coding/gsm0503_parity.h b/include/osmocom/coding/gsm0503_parity.h
index 28a54443..bda5f99e 100644
--- a/include/osmocom/coding/gsm0503_parity.h
+++ b/include/osmocom/coding/gsm0503_parity.h
@@ -10,14 +10,15 @@
* @{
* \file gsm0503_parity.h */
-const struct osmo_crc64gen_code gsm0503_fire_crc40;
-const struct osmo_crc16gen_code gsm0503_cs234_crc16;
-const struct osmo_crc8gen_code gsm0503_mcs_crc8_hdr;
-const struct osmo_crc16gen_code gsm0503_mcs_crc12;
-const struct osmo_crc8gen_code gsm0503_rach_crc6;
-const struct osmo_crc16gen_code gsm0503_sch_crc10;
-const struct osmo_crc8gen_code gsm0503_tch_fr_crc3;
-const struct osmo_crc8gen_code gsm0503_tch_efr_crc8;
-const struct osmo_crc8gen_code gsm0503_amr_crc6;
+extern const struct osmo_crc64gen_code gsm0503_fire_crc40;
+extern const struct osmo_crc16gen_code gsm0503_cs234_crc16;
+extern const struct osmo_crc8gen_code gsm0503_mcs_crc8_hdr;
+extern const struct osmo_crc16gen_code gsm0503_mcs_crc12;
+extern const struct osmo_crc8gen_code gsm0503_rach_crc6;
+extern const struct osmo_crc16gen_code gsm0503_sch_crc10;
+extern const struct osmo_crc8gen_code gsm0503_tch_fr_crc3;
+extern const struct osmo_crc8gen_code gsm0503_tch_efr_crc8;
+extern const struct osmo_crc8gen_code gsm0503_amr_crc6;
+extern const struct osmo_crc16gen_code gsm0503_amr_crc14;
/*! @} */
diff --git a/include/osmocom/core/application.h b/include/osmocom/core/application.h
index edf59ed4..67a59088 100644
--- a/include/osmocom/core/application.h
+++ b/include/osmocom/core/application.h
@@ -2,17 +2,14 @@
#include <osmocom/core/defs.h>
+struct log_info;
+struct log_target;
+
/*!
* \file application.h
* Routines for helping with the osmocom application setup.
*/
-/*! information containing the available logging subsystems */
-struct log_info;
-
-/*! one instance of a logging target (file, stderr, ...) */
-struct log_target;
-
/*! the default logging target, logging to stderr */
extern struct log_target *osmo_stderr_target;
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
index 6881d87d..258fccb6 100644
--- a/include/osmocom/core/bitXXgen.h.tpl
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -22,7 +22,9 @@
#pragma once
-/*! load unaligned n-byte integer (little-endian encoding) into uintXX_t
+#include <osmocom/core/utils.h>
+
+/*! load unaligned n-byte integer (little-endian encoding) into uintXX_t, into the least significant octets.
* \param[in] p Buffer where integer is stored
* \param[in] n Number of bytes stored in p
* \returns XX bit unsigned integer
@@ -32,11 +34,14 @@ static inline uintXX_t osmo_loadXXle_ext(const void *p, uint8_t n)
uint8_t i;
uintXX_t r = 0;
const uint8_t *q = (uint8_t *)p;
+ OSMO_ASSERT(n <= sizeof(r));
for(i = 0; i < n; r |= ((uintXX_t)q[i] << (8 * i)), i++);
return r;
}
-/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t
+/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t, into the MOST significant octets.
+ * WARNING: for n < sizeof(uintXX_t), the result is not returned in the least significant octets, as one might expect.
+ * To always return the same value as fed to osmo_storeXXbe_ext() before, use osmo_loadXXbe_ext_2().
* \param[in] p Buffer where integer is stored
* \param[in] n Number of bytes stored in p
* \returns XX bit unsigned integer
@@ -46,10 +51,26 @@ static inline uintXX_t osmo_loadXXbe_ext(const void *p, uint8_t n)
uint8_t i;
uintXX_t r = 0;
const uint8_t *q = (uint8_t *)p;
+ OSMO_ASSERT(n <= sizeof(r));
for(i = 0; i < n; r |= ((uintXX_t)q[i] << (XX - 8* (1 + i))), i++);
return r;
}
+/*! load unaligned n-byte integer (big-endian encoding) into uintXX_t, into the least significant octets.
+ * \param[in] p Buffer where integer is stored
+ * \param[in] n Number of bytes stored in p
+ * \returns XX bit unsigned integer
+ */
+static inline uintXX_t osmo_loadXXbe_ext_2(const void *p, uint8_t n)
+{
+ uint8_t i;
+ uintXX_t r = 0;
+ const uint8_t *q = (uint8_t *)p;
+ OSMO_ASSERT(n <= sizeof(r));
+ for(i = 0; i < n; r |= ((uintXX_t)q[i] << (XX - 8* (1 + i + (sizeof(r) - n)))), i++);
+ return r;
+}
+
/*! store unaligned n-byte integer (little-endian encoding) from uintXX_t
* \param[in] x unsigned XX bit integer
@@ -60,6 +81,7 @@ static inline void osmo_storeXXle_ext(uintXX_t x, void *p, uint8_t n)
{
uint8_t i;
uint8_t *q = (uint8_t *)p;
+ OSMO_ASSERT(n <= sizeof(x));
for(i = 0; i < n; q[i] = (x >> i * 8) & 0xFF, i++);
}
@@ -72,6 +94,7 @@ static inline void osmo_storeXXbe_ext(uintXX_t x, void *p, uint8_t n)
{
uint8_t i;
uint8_t *q = (uint8_t *)p;
+ OSMO_ASSERT(n <= sizeof(x));
for(i = 0; i < n; q[i] = (x >> ((n - 1 - i) * 8)) & 0xFF, i++);
}
diff --git a/include/osmocom/core/defs.h b/include/osmocom/core/defs.h
index 5e5aa90f..33ffb7bb 100644
--- a/include/osmocom/core/defs.h
+++ b/include/osmocom/core/defs.h
@@ -43,8 +43,10 @@
#if BUILDING_LIBOSMOCORE
# define OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE
+# define OSMO_DEPRECATED_OUTSIDE(text)
#else
# define OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE OSMO_DEPRECATED("For internal use inside libosmocore only.")
+# define OSMO_DEPRECATED_OUTSIDE(text) OSMO_DEPRECATED(text)
#endif
#undef _OSMO_HAS_ATTRIBUTE_DEPRECATED_WITH_MESSAGE
diff --git a/include/osmocom/core/exec.h b/include/osmocom/core/exec.h
new file mode 100644
index 00000000..e63ec114
--- /dev/null
+++ b/include/osmocom/core/exec.h
@@ -0,0 +1,29 @@
+#pragma once
+/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+extern const char *osmo_environment_whitelist[];
+
+int osmo_environment_filter(char **out, size_t out_len, char **in, const char **whitelist);
+int osmo_environment_append(char **out, size_t out_len, char **in);
+int osmo_close_all_fds_above(int last_fd_to_keep);
+int osmo_system_nowait2(const char *command, const char **env_whitelist, char **addl_env, const char *user);
+int osmo_system_nowait(const char *command, const char **env_whitelist, char **addl_env);
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index 1701c45e..7b262c71 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -10,6 +10,7 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
/*! \defgroup fsm Finite State Machine abstraction
* @{
@@ -122,6 +123,7 @@ struct osmo_fsm_inst {
void osmo_fsm_log_addr(bool log_addr);
void osmo_fsm_log_timeouts(bool log_timeouts);
void osmo_fsm_term_safely(bool term_safely);
+void osmo_fsm_set_dealloc_ctx(void *ctx);
/*! Log using FSM instance's context, on explicit logging subsystem and level.
* \param fi An osmo_fsm_inst.
diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h
index 35ba71e5..11b2d137 100644
--- a/include/osmocom/core/gsmtap.h
+++ b/include/osmocom/core/gsmtap.h
@@ -48,6 +48,7 @@
#define GSMTAP_TYPE_OSMOCORE_LOG 0x10 /* libosmocore logging */
#define GSMTAP_TYPE_QC_DIAG 0x11 /* Qualcomm DIAG frame */
#define GSMTAP_TYPE_LTE_NAS 0x12 /* LTE Non-Access Stratum */
+#define GSMTAP_TYPE_E1T1 0x13 /* E1/T1 Lines */
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
@@ -82,8 +83,8 @@
#define GSMTAP_CHANNEL_SDCCH 0x06
#define GSMTAP_CHANNEL_SDCCH4 0x07
#define GSMTAP_CHANNEL_SDCCH8 0x08
-#define GSMTAP_CHANNEL_TCH_F 0x09
-#define GSMTAP_CHANNEL_TCH_H 0x0a
+#define GSMTAP_CHANNEL_FACCH_F 0x09 /* Actually, it's FACCH/F (signaling) */
+#define GSMTAP_CHANNEL_FACCH_H 0x0a /* Actually, it's FACCH/H (signaling) */
#define GSMTAP_CHANNEL_PACCH 0x0b
#define GSMTAP_CHANNEL_CBCH52 0x0c
#define GSMTAP_CHANNEL_PDTCH 0x0d
@@ -91,6 +92,10 @@
#define GSMTAP_CHANNEL_PDCH GSMTAP_CHANNEL_PDTCH
#define GSMTAP_CHANNEL_PTCCH 0x0e
#define GSMTAP_CHANNEL_CBCH51 0x0f
+#define GSMTAP_CHANNEL_VOICE_F 0x10 /* voice codec payload (FR/EFR/AMR) */
+#define GSMTAP_CHANNEL_VOICE_H 0x11 /* voice codec payload (HR/AMR) */
+#define GSMTAP_CHANNEL_TCH_F GSMTAP_CHANNEL_FACCH_F /* We used the wrong naming in 2008 when we were young */
+#define GSMTAP_CHANNEL_TCH_H GSMTAP_CHANNEL_FACCH_H /* We used the wrong naming in 2008 when we were young */
/* GPRS Coding Scheme CS1..4 */
#define GSMTAP_GPRS_CS_BASE 0x20
@@ -167,6 +172,14 @@
#define GSMTAP_LTE_CH_DTCH 0x06
#define GSMTAP_LTE_CH_MTCH 0x07
+/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
+/* sub-types for TYPE_E1T1 */
+#define GSMTAP_E1T1_LAPD 0x01 /* Q.921 LAPD */
+#define GSMTAP_E1T1_FR 0x02 /* Frame Relay */
+#define GSMTAP_E1T1_RAW 0x03 /* raw/transparent B-channel */
+#define GSMTAP_E1T1_TRAU16 0x04 /* 16k TRAU frames; sub-slot 0-3 */
+#define GSMTAP_E1T1_TRAU8 0x05 /* 8k TRAU frames; sub-slot 0-7 */
+
/* flags for the ARFCN */
#define GSMTAP_ARFCN_F_PCS 0x8000
#define GSMTAP_ARFCN_F_UPLINK 0x4000
@@ -318,3 +331,26 @@ struct gsmtap_osmocore_log_hdr {
uint32_t line_nr;/*!< line number */
} src_file;
} __attribute__((packed));
+
+/*! First byte of type==GSMTAP_TYPE_UM sub_type==GSMTAP_CHANNEL_VOICE payload */
+enum gsmtap_um_voice_type {
+ /*! 1 byte TOC + 112 bits (14 octets) = 15 octets payload;
+ * Reference is RFC5993 Section 5.2.1 + 3GPP TS 46.030 Annex B */
+ GSMTAP_UM_VOICE_HR,
+ /*! 33 payload bytes; Reference is RFC3551 Section 4.5.8.1 */
+ GSMTAP_UM_VOICE_FR,
+ /*! 31 payload bytes; Reference is RFC3551 Section 4.5.9 + ETSI TS 101 318 */
+ GSMTAP_UM_VOICE_EFR,
+ /*! 1 byte TOC + 5..31 bytes = 6..32 bytes payload; RFC4867 octet-aligned */
+ GSMTAP_UM_VOICE_AMR,
+ /* TODO: Revisit the types below; their usage; ... */
+ GSMTAP_UM_VOICE_AMR_SID_BAD,
+ GSMTAP_UM_VOICE_AMR_ONSET,
+ GSMTAP_UM_VOICE_AMR_RATSCCH,
+ GSMTAP_UM_VOICE_AMR_SID_UPDATE_INH,
+ GSMTAP_UM_VOICE_AMR_SID_FIRST_P1,
+ GSMTAP_UM_VOICE_AMR_SID_FIRST_P2,
+ GSMTAP_UM_VOICE_AMR_SID_FIRST_INH,
+ GSMTAP_UM_VOICE_AMR_RATSCCH_MARKER,
+ GSMTAP_UM_VOICE_AMR_RATSCCH_DATA,
+};
diff --git a/include/osmocom/core/gsmtap_util.h b/include/osmocom/core/gsmtap_util.h
index f8a12a60..9b215be3 100644
--- a/include/osmocom/core/gsmtap_util.h
+++ b/include/osmocom/core/gsmtap_util.h
@@ -8,7 +8,11 @@
* @{
* \file gsmtap_util.h */
-uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id);
+uint8_t chantype_rsl2gsmtap2(uint8_t rsl_chantype, uint8_t rsl_link_id, bool user_plane);
+
+uint8_t chantype_rsl2gsmtap(uint8_t rsl_chantype, uint8_t rsl_link_id)
+ OSMO_DEPRECATED("Use chantype_rsl2gsmtap2() instead");
+
void chantype_gsmtap2rsl(uint8_t gsmtap_chantype, uint8_t *rsl_chantype, uint8_t *link_id);
struct msgb *gsmtap_makemsg_ex(uint8_t type, uint16_t arfcn, uint8_t ts, uint8_t chan_type,
diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h
index 803b4a94..6d0d5a3a 100644
--- a/include/osmocom/core/logging.h
+++ b/include/osmocom/core/logging.h
@@ -105,7 +105,7 @@ void logp(int subsys, const char *file, int line, int cont, const char *format,
#define LOGL_ERROR 7 /*!< error condition, requires user action */
#define LOGL_FATAL 8 /*!< fatal, program aborted */
-/* logging levels defined by the library itself */
+/* logging subsystems defined by the library itself */
#define DLGLOBAL -1 /*!< global logging */
#define DLLAPD -2 /*!< LAPD implementation */
#define DLINP -3 /*!< (A-bis) Input sub-system */
@@ -125,7 +125,27 @@ void logp(int subsys, const char *file, int line, int cont, const char *format,
#define DLMGCP -17 /*!< Osmocom MGCP */
#define DLJIBUF -18 /*!< Osmocom Jitter Buffer */
#define DLRSPRO -19 /*!< Osmocom Remote SIM Protocol */
-#define OSMO_NUM_DLIB 19 /*!< Number of logging sub-systems in libraries */
+#define DLNS -20 /*!< Osmocom NS layer */
+#define OSMO_NUM_DLIB 20 /*!< Number of logging sub-systems in libraries */
+
+/* Colors that can be used in log_info_cat.color */
+#define OSMO_LOGCOLOR_NORMAL NULL
+#define OSMO_LOGCOLOR_RED "\033[1;31m"
+#define OSMO_LOGCOLOR_GREEN "\033[1;32m"
+#define OSMO_LOGCOLOR_YELLOW "\033[1;33m"
+#define OSMO_LOGCOLOR_BLUE "\033[1;34m"
+#define OSMO_LOGCOLOR_PURPLE "\033[1;35m"
+#define OSMO_LOGCOLOR_CYAN "\033[1;36m"
+#define OSMO_LOGCOLOR_DARKRED "\033[31m"
+#define OSMO_LOGCOLOR_DARKGREEN "\033[32m"
+#define OSMO_LOGCOLOR_DARKYELLOW "\033[33m"
+#define OSMO_LOGCOLOR_DARKBLUE "\033[34m"
+#define OSMO_LOGCOLOR_DARKPURPLE "\033[35m"
+#define OSMO_LOGCOLOR_DARKCYAN "\033[36m"
+#define OSMO_LOGCOLOR_DARKGREY "\033[1;30m"
+#define OSMO_LOGCOLOR_GREY "\033[37m"
+#define OSMO_LOGCOLOR_BRIGHTWHITE "\033[1;37m"
+#define OSMO_LOGCOLOR_END "\033[0;m"
/*! Configuration of single log category / sub-system */
struct log_category {
@@ -154,6 +174,7 @@ enum log_ctx_index {
LOG_CTX_GB_BVC,
LOG_CTX_BSC_SUBSCR,
LOG_CTX_VLR_SUBSCR,
+ LOG_CTX_L1_SAPI,
_LOG_CTX_COUNT
};
@@ -166,6 +187,7 @@ enum log_filter_index {
LOG_FLT_GB_BVC,
LOG_FLT_BSC_SUBSCR,
LOG_FLT_VLR_SUBSCR,
+ LOG_FLT_L1_SAPI,
_LOG_FLT_COUNT
};
@@ -222,6 +244,7 @@ enum log_target_type {
LOG_TGT_TYPE_STDERR, /*!< stderr logging */
LOG_TGT_TYPE_STRRB, /*!< osmo_strrb-backed logging */
LOG_TGT_TYPE_GSMTAP, /*!< GSMTAP network logging */
+ LOG_TGT_TYPE_SYSTEMD, /*!< systemd journal logging */
};
/*! Whether/how to log the source filename (and line number). */
@@ -289,6 +312,10 @@ struct log_target {
const char *ident;
const char *hostname;
} tgt_gsmtap;
+
+ struct {
+ bool raw;
+ } sd_journal;
};
/*! call-back function to be called when the logging framework
@@ -370,6 +397,8 @@ struct log_target *log_target_create_gsmtap(const char *host, uint16_t port,
const char *ident,
bool ofd_wq_mode,
bool add_sink);
+struct log_target *log_target_create_systemd(bool raw);
+void log_target_systemd_set_raw(struct log_target *target, bool raw);
int log_target_file_reopen(struct log_target *tgt);
int log_targets_reopen(void);
@@ -377,6 +406,19 @@ void log_add_target(struct log_target *target);
void log_del_target(struct log_target *target);
struct log_target *log_target_find(int type, const char *fname);
-extern struct llist_head osmo_log_target_list;
+
+void log_enable_multithread(void);
+
+void log_tgt_mutex_lock_impl(void);
+void log_tgt_mutex_unlock_impl(void);
+#define LOG_MTX_DEBUG 0
+#if LOG_MTX_DEBUG
+ #include <pthread.h>
+ #define log_tgt_mutex_lock() do { fprintf(stderr, "[%lu] %s:%d [%s] lock\n", pthread_self(), __FILE__, __LINE__, __func__); log_tgt_mutex_lock_impl(); } while (0)
+ #define log_tgt_mutex_unlock() do { fprintf(stderr, "[%lu] %s:%d [%s] unlock\n", pthread_self(), __FILE__, __LINE__, __func__); log_tgt_mutex_unlock_impl(); } while (0)
+#else
+ #define log_tgt_mutex_lock() log_tgt_mutex_lock_impl()
+ #define log_tgt_mutex_unlock() log_tgt_mutex_unlock_impl()
+#endif
/*! @} */
diff --git a/include/osmocom/core/logging_internal.h b/include/osmocom/core/logging_internal.h
index a510f83e..2e656603 100644
--- a/include/osmocom/core/logging_internal.h
+++ b/include/osmocom/core/logging_internal.h
@@ -7,8 +7,9 @@
#include <osmocom/core/utils.h>
extern void *tall_log_ctx;
-extern const struct log_info *osmo_log_info;
+extern struct log_info *osmo_log_info;
extern const struct value_string loglevel_strs[];
+extern struct llist_head osmo_log_target_list;
void assert_loginfo(const char *src);
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index e05d37f0..cc76e3ad 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -239,7 +239,11 @@ static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len)
{
unsigned char *tmp = msgb->tail;
if (msgb_tailroom(msgb) < (int) len)
- MSGB_ABORT(msgb, "Not enough tailroom msgb_put (%u < %u)\n",
+ MSGB_ABORT(msgb, "Not enough tailroom msgb_put"
+ " (allocated %u, head at %u, len %u, tailroom %u < want tailroom %u)\n",
+ msgb->data_len - sizeof(struct msgb),
+ msgb->head - msgb->_data,
+ msgb->len,
msgb_tailroom(msgb), len);
msgb->tail += len;
msgb->len += len;
@@ -335,8 +339,13 @@ static inline uint32_t msgb_get_u32(struct msgb *msgb)
static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
{
if (msgb_headroom(msgb) < (int) len)
- MSGB_ABORT(msgb, "Not enough headroom msgb_push (%u < %u)\n",
- msgb_headroom(msgb), len);
+ MSGB_ABORT(msgb, "Not enough headroom msgb_push"
+ " (allocated %u, head at %u < want headroom %u, len %u, tailroom %u)\n",
+ msgb->data_len - sizeof(struct msgb),
+ msgb->head - msgb->_data,
+ len,
+ msgb->len,
+ msgb_tailroom(msgb));
msgb->data -= len;
msgb->len += len;
return msgb->data;
@@ -518,7 +527,7 @@ static inline int msgb_l3trim(struct msgb *msg, int l3len)
static inline struct msgb *msgb_alloc_headroom_c(const void *ctx, int size, int headroom,
const char *name)
{
- osmo_static_assert(size > headroom, headroom_bigger);
+ osmo_static_assert(size >= headroom, headroom_bigger);
struct msgb *msg = msgb_alloc_c(ctx, size, name);
if (msg)
@@ -540,7 +549,7 @@ static inline struct msgb *msgb_alloc_headroom_c(const void *ctx, int size, int
static inline struct msgb *msgb_alloc_headroom(int size, int headroom,
const char *name)
{
- osmo_static_assert(size > headroom, headroom_bigger);
+ osmo_static_assert(size >= headroom, headroom_bigger);
struct msgb *msg = msgb_alloc(size, name);
if (msg)
diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h
index f7e6e225..1669ce49 100644
--- a/include/osmocom/core/rate_ctr.h
+++ b/include/osmocom/core/rate_ctr.h
@@ -116,4 +116,7 @@ int rate_ctr_for_each_counter(struct rate_ctr_group *ctrg,
int rate_ctr_for_each_group(rate_ctr_group_handler_t handle_group, void *data);
+void rate_ctr_reset(struct rate_ctr *ctr);
+void rate_ctr_group_reset(struct rate_ctr_group *ctrg);
+
/*! @} */
diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h
index e4787b09..b4101998 100644
--- a/include/osmocom/core/select.h
+++ b/include/osmocom/core/select.h
@@ -7,6 +7,7 @@
#include <osmocom/core/linuxlist.h>
#include <stdbool.h>
#include <time.h>
+#include <signal.h>
/*! \defgroup select Select loop abstraction
* @{
@@ -18,6 +19,8 @@
#define OSMO_FD_WRITE 0x0002
/*! Indicate interest in exceptions from the file descriptor */
#define OSMO_FD_EXCEPT 0x0004
+/*! Used as when_mask in osmo_fd_update_when() */
+#define OSMO_FD_MASK 0xFFFF
/* legacy naming dating back to early OpenBSC / bsc_hack of 2008 */
#define BSC_FD_READ OSMO_FD_READ
@@ -46,11 +49,31 @@ void osmo_fd_setup(struct osmo_fd *ofd, int fd, unsigned int when,
int (*cb)(struct osmo_fd *fd, unsigned int what),
void *data, unsigned int priv_nr);
+void osmo_fd_update_when(struct osmo_fd *ofd, unsigned int when_mask, unsigned int when);
+
+static inline void osmo_fd_read_enable(struct osmo_fd *ofd) {
+ osmo_fd_update_when(ofd, OSMO_FD_MASK, OSMO_FD_READ);
+}
+
+static inline void osmo_fd_read_disable(struct osmo_fd *ofd) {
+ osmo_fd_update_when(ofd, ~OSMO_FD_READ, 0);
+}
+
+static inline void osmo_fd_write_enable(struct osmo_fd *ofd) {
+ osmo_fd_update_when(ofd, OSMO_FD_MASK, OSMO_FD_WRITE);
+}
+
+static inline void osmo_fd_write_disable(struct osmo_fd *ofd) {
+ osmo_fd_update_when(ofd, ~OSMO_FD_WRITE, 0);
+}
+
bool osmo_fd_is_registered(struct osmo_fd *fd);
int osmo_fd_register(struct osmo_fd *fd);
void osmo_fd_unregister(struct osmo_fd *fd);
void osmo_fd_close(struct osmo_fd *fd);
int osmo_select_main(int polling);
+int osmo_select_main_ctx(int polling);
+void osmo_select_init(void);
struct osmo_fd *osmo_fd_get_by_fd(int fd);
@@ -66,4 +89,21 @@ int osmo_timerfd_schedule(struct osmo_fd *ofd, const struct timespec *first,
const struct timespec *interval);
int osmo_timerfd_setup(struct osmo_fd *ofd, int (*cb)(struct osmo_fd *, unsigned int), void *data);
+/* signalfd integration */
+struct osmo_signalfd;
+struct signalfd_siginfo;
+
+typedef void osmo_signalfd_cb(struct osmo_signalfd *osfd, const struct signalfd_siginfo *fdsi);
+
+struct osmo_signalfd {
+ struct osmo_fd ofd;
+ sigset_t sigset;
+ osmo_signalfd_cb *cb;
+ void *data;
+};
+
+struct osmo_signalfd *
+osmo_signalfd_setup(void *ctx, sigset_t set, osmo_signalfd_cb *cb, void *data);
+
+
/*! @} */
diff --git a/include/osmocom/core/sockaddr_str.h b/include/osmocom/core/sockaddr_str.h
index 253b755f..d96b7434 100644
--- a/include/osmocom/core/sockaddr_str.h
+++ b/include/osmocom/core/sockaddr_str.h
@@ -31,6 +31,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <arpa/inet.h>
+#include <osmocom/core/defs.h>
struct in_addr;
struct in6_addr;
@@ -61,17 +62,24 @@ struct osmo_sockaddr_str {
* struct osmo_sockaddr_str *my_sockaddr_str = ...;
* printf("got " OSMO_SOCKADDR_STR_FMT "\n", OSMO_SOCKADDR_STR_FMT_ARGS(my_sockaddr_str));
*/
-#define OSMO_SOCKADDR_STR_FMT "%s:%u"
-#define OSMO_SOCKADDR_STR_FMT_ARGS(R) ((R)->ip ? : ""), (R)->port
+#define OSMO_SOCKADDR_STR_FMT "%s%s%s:%u"
+#define OSMO_SOCKADDR_STR_FMT_ARGS(R) \
+ ((R) && (R)->af == AF_INET6)? "[" : "", \
+ (R)? (R)->ip : "NULL", \
+ ((R) && (R)->af == AF_INET6)? "]" : "", \
+ (R)? (R)->port : 0
bool osmo_sockaddr_str_is_set(const struct osmo_sockaddr_str *sockaddr_str);
+bool osmo_sockaddr_str_is_nonzero(const struct osmo_sockaddr_str *sockaddr_str);
+int osmo_sockaddr_str_cmp(const struct osmo_sockaddr_str *a, const struct osmo_sockaddr_str *b);
int osmo_sockaddr_str_from_str(struct osmo_sockaddr_str *sockaddr_str, const char *ip, uint16_t port);
+int osmo_sockaddr_str_from_str2(struct osmo_sockaddr_str *sockaddr_str, const char *ip);
int osmo_sockaddr_str_from_in_addr(struct osmo_sockaddr_str *sockaddr_str, const struct in_addr *addr, uint16_t port);
int osmo_sockaddr_str_from_in6_addr(struct osmo_sockaddr_str *sockaddr_str, const struct in6_addr *addr, uint16_t port);
int osmo_sockaddr_str_from_32(struct osmo_sockaddr_str *sockaddr_str, uint32_t ip, uint16_t port);
-int osmo_sockaddr_str_from_32n(struct osmo_sockaddr_str *sockaddr_str, uint32_t ip, uint16_t port);
+int osmo_sockaddr_str_from_32h(struct osmo_sockaddr_str *sockaddr_str, uint32_t ip, uint16_t port);
int osmo_sockaddr_str_from_sockaddr_in(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_in *src);
int osmo_sockaddr_str_from_sockaddr_in6(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_in6 *src);
int osmo_sockaddr_str_from_sockaddr(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_storage *src);
@@ -79,9 +87,14 @@ int osmo_sockaddr_str_from_sockaddr(struct osmo_sockaddr_str *sockaddr_str, cons
int osmo_sockaddr_str_to_in_addr(const struct osmo_sockaddr_str *sockaddr_str, struct in_addr *dst);
int osmo_sockaddr_str_to_in6_addr(const struct osmo_sockaddr_str *sockaddr_str, struct in6_addr *dst);
int osmo_sockaddr_str_to_32(const struct osmo_sockaddr_str *sockaddr_str, uint32_t *ip);
-int osmo_sockaddr_str_to_32n(const struct osmo_sockaddr_str *sockaddr_str, uint32_t *ip);
+int osmo_sockaddr_str_to_32h(const struct osmo_sockaddr_str *sockaddr_str, uint32_t *ip);
int osmo_sockaddr_str_to_sockaddr_in(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_in *dst);
int osmo_sockaddr_str_to_sockaddr_in6(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_in6 *dst);
int osmo_sockaddr_str_to_sockaddr(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_storage *dst);
+int osmo_sockaddr_str_from_32n(struct osmo_sockaddr_str *sockaddr_str, uint32_t ip, uint16_t port)
+ OSMO_DEPRECATED("osmo_sockaddr_str_from_32n() actually uses *host* byte order. Use osmo_sockaddr_str_from_32h() instead");
+int osmo_sockaddr_str_to_32n(const struct osmo_sockaddr_str *sockaddr_str, uint32_t *ip)
+ OSMO_DEPRECATED("osmo_sockaddr_str_to_32n() actually uses *host* byte order. Use osmo_sockaddr_str_to_32h() instead");
+
/*! @} */
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index 37b1eaef..0443c06e 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -2,6 +2,7 @@
* Osmocom socket convenience functions. */
#pragma once
+#if (!EMBEDDED)
/*! \defgroup socket Socket convenience functions
* @{
@@ -11,17 +12,24 @@
#include <stdbool.h>
#include <stddef.h>
-#if (!EMBEDDED)
#include <arpa/inet.h>
/*! maximum length of a socket name ("r=1.2.3.4:123<->l=5.6.7.8:987") */
#define OSMO_SOCK_NAME_MAXLEN (2 + INET6_ADDRSTRLEN + 1 + 5 + 3 + 2 + INET6_ADDRSTRLEN + 1 + 5 + 1)
-#endif
struct sockaddr_in;
struct sockaddr;
struct osmo_fd;
+struct osmo_sockaddr {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_storage sas;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } u;
+};
+
/* flags for osmo_sock_init. */
/*! connect the socket to a remote peer */
#define OSMO_SOCK_F_CONNECT (1 << 0)
@@ -36,6 +44,9 @@ struct osmo_fd;
/*! use SO_REUSEADDR on UDP ports (required for multicast) */
#define OSMO_SOCK_F_UDP_REUSEADDR (1 << 5)
+/*! maximum number of local or remote addresses supported by an osmo_sock instance */
+#define OSMO_SOCK_MAX_ADDRS 32
+
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
const char *host, uint16_t port, unsigned int flags);
@@ -43,6 +54,15 @@ int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto,
const char *local_host, uint16_t local_port,
const char *remote_host, uint16_t remote_port, unsigned int flags);
+int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
+ const char **local_hosts, size_t local_hosts_cnt, uint16_t local_port,
+ const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags);
+
+int osmo_sock_init_osa(uint16_t type, uint8_t proto,
+ const struct osmo_sockaddr *local,
+ const struct osmo_sockaddr *remote,
+ unsigned int flags);
+
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
const char *host, uint16_t port, unsigned int flags);
@@ -50,6 +70,11 @@ int osmo_sock_init2_ofd(struct osmo_fd *ofd, int family, int type, int proto,
const char *local_host, uint16_t local_port,
const char *remote_host, uint16_t remote_port, unsigned int flags);
+int osmo_sock_init_osa_ofd(struct osmo_fd *ofd, int type, int proto,
+ const struct osmo_sockaddr *local,
+ const struct osmo_sockaddr *remote,
+ unsigned int flags);
+
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
uint8_t proto, unsigned int flags);
@@ -60,6 +85,9 @@ unsigned int osmo_sockaddr_to_str_and_uint(char *addr, unsigned int addr_len, ui
size_t osmo_sockaddr_in_to_str_and_uint(char *addr, unsigned int addr_len, uint16_t *port,
const struct sockaddr_in *sin);
+const char *osmo_sockaddr_ntop(const struct sockaddr *sa, char *dst);
+uint16_t osmo_sockaddr_port(const struct sockaddr *sa);
+
int osmo_sock_unix_init(uint16_t type, uint8_t proto,
const char *socket_path, unsigned int flags);
@@ -80,8 +108,19 @@ int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len);
int osmo_sock_mcast_loop_set(int fd, bool enable);
int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl);
int osmo_sock_mcast_all_set(int fd, bool enable);
+int osmo_sock_mcast_iface_set(int fd, const char *ifname);
int osmo_sock_mcast_subscribe(int fd, const char *grp_addr);
int osmo_sock_local_ip(char *local_ip, const char *remote_ip);
+int osmo_sockaddr_local_ip(struct osmo_sockaddr *local_ip,
+ const struct osmo_sockaddr *remote_ip);
+int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
+ const struct osmo_sockaddr *b);
+
+const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *sockaddr);
+char *osmo_sockaddr_to_str_buf(char *buf, size_t buf_len,
+ const struct osmo_sockaddr *sockaddr);
+
+#endif /* (!EMBEDDED) */
/*! @} */
diff --git a/include/osmocom/core/stat_item.h b/include/osmocom/core/stat_item.h
index 806173ab..4710dba7 100644
--- a/include/osmocom/core/stat_item.h
+++ b/include/osmocom/core/stat_item.h
@@ -114,4 +114,8 @@ static inline int32_t osmo_stat_item_get_last(const struct osmo_stat_item *item)
{
return item->values[item->last_offs].value;
}
+
+void osmo_stat_item_reset(struct osmo_stat_item *item);
+void osmo_stat_item_group_reset(struct osmo_stat_item_group *statg);
+
/*! @} */
diff --git a/include/osmocom/core/stats.h b/include/osmocom/core/stats.h
index e01016d4..b9edac2a 100644
--- a/include/osmocom/core/stats.h
+++ b/include/osmocom/core/stats.h
@@ -73,6 +73,7 @@ struct osmo_stats_reporter {
char *bind_addr_str; /*!< local bind IP address */
int dest_port; /*!< destination (UDP) port */
int mtu; /*!< Maximum Transmission Unit */
+ unsigned int flush_period; /*!< period between regular flushes */
/*! Maximum class/index to report. FIXME: More details! */
enum osmo_stats_class max_class;
@@ -87,7 +88,8 @@ struct osmo_stats_reporter {
int fd; /*!< file descriptor of socket */
struct msgb *buffer; /*!< message buffer for log output */
int agg_enabled; /*!< is aggregation enabled? */
- int force_single_flush;
+ int force_single_flush; /*!< set to 1 to force a flush (send even unchanged stats values) */
+ unsigned int flush_period_counter; /*!< count sends between forced flushes */
struct llist_head list;
int (*open)(struct osmo_stats_reporter *srep);
@@ -129,6 +131,7 @@ int osmo_stats_reporter_set_max_class(struct osmo_stats_reporter *srep,
int osmo_stats_reporter_set_name_prefix(struct osmo_stats_reporter *srep, const char *prefix);
int osmo_stats_reporter_enable(struct osmo_stats_reporter *srep);
int osmo_stats_reporter_disable(struct osmo_stats_reporter *srep);
+int osmo_stats_reporter_set_flush_period(struct osmo_stats_reporter *srep, unsigned int period);
/* reporter creation */
struct osmo_stats_reporter *osmo_stats_reporter_create_log(const char *name);
diff --git a/include/osmocom/core/talloc.h b/include/osmocom/core/talloc.h
index 191a463f..c68a56cf 100644
--- a/include/osmocom/core/talloc.h
+++ b/include/osmocom/core/talloc.h
@@ -1,5 +1,27 @@
-/*! \file talloc.h
- * Convenience wrapper. libosmocore used to ship its own internal copy of
- * talloc, before libtalloc became a standard component on most systems */
+/*! \file talloc.h */
#pragma once
#include <talloc.h>
+
+/*! per-thread talloc contexts. This works around the problem that talloc is not
+ * thread-safe. However, one can simply have a different set of talloc contexts for each
+ * thread, and ensure that allocations made on one thread are always only free'd on that
+ * very same thread.
+ * WARNING: Users must make sure they free() on the same thread as they allocate!! */
+struct osmo_talloc_contexts {
+ /*! global per-thread talloc context. */
+ void *global;
+ /*! volatile select-dispatch context. This context is completely free'd and
+ * re-created every time the main select loop in osmo_select_main() returns from
+ * select(2) and calls per-fd callback functions. This allows users of this
+ * facility to allocate temporary objects like string buffers, message buffers
+ * and the like which are automatically free'd when going into the next select()
+ * system call */
+ void *select;
+};
+
+extern __thread struct osmo_talloc_contexts *osmo_ctx;
+
+/* short-hand #defines for the osmo talloc contexts (OTC) that can be used to pass
+ * to the various _c functions like msgb_alloc_c() */
+#define OTC_GLOBAL (osmo_ctx->global)
+#define OTC_SELECT (osmo_ctx->select)
diff --git a/include/osmocom/core/tdef.h b/include/osmocom/core/tdef.h
index 566f5dd3..54819d95 100644
--- a/include/osmocom/core/tdef.h
+++ b/include/osmocom/core/tdef.h
@@ -77,6 +77,10 @@ struct osmo_tdef {
/*! Currently active timeout value, e.g. set by user config. This is the only mutable member: a user may
* configure the timeout value, but neither unit nor any other field. */
unsigned long val;
+ /*! Minimum timer value (in this tdef unit), checked if set (not zero). */
+ unsigned long min_val;
+ /*! Maximum timer value (in this tdef unit), checked if set (not zero). */
+ unsigned long max_val;
};
/*! Iterate an array of struct osmo_tdef, the last item should be fully zero, i.e. "{}".
@@ -97,6 +101,9 @@ void osmo_tdefs_reset(struct osmo_tdef *tdefs);
unsigned long osmo_tdef_get(const struct osmo_tdef *tdefs, int T, enum osmo_tdef_unit as_unit,
long val_if_not_present);
struct osmo_tdef *osmo_tdef_get_entry(struct osmo_tdef *tdefs, int T);
+int osmo_tdef_set(struct osmo_tdef *tdefs, int T, unsigned long val, enum osmo_tdef_unit val_unit);
+bool osmo_tdef_val_in_range(struct osmo_tdef *tdef, unsigned long new_val);
+int osmo_tdef_range_str_buf(char *buf, size_t buf_len, struct osmo_tdef *t);
/*! Using osmo_tdef for osmo_fsm_inst: array entry for a mapping of state numbers to timeout definitions.
* For a usage example, see osmo_tdef_get_state_timeout() and test_tdef_state_timeout() in tdef_test.c. */
diff --git a/include/osmocom/core/timer.h b/include/osmocom/core/timer.h
index 19797662..6ffc3b17 100644
--- a/include/osmocom/core/timer.h
+++ b/include/osmocom/core/timer.h
@@ -84,6 +84,7 @@ int osmo_timer_remaining(const struct osmo_timer_list *timer,
* internal timer list management
*/
struct timeval *osmo_timers_nearest(void);
+int osmo_timers_nearest_ms(void);
void osmo_timers_prepare(void);
int osmo_timers_update(void);
int osmo_timers_check(void);
diff --git a/include/osmocom/core/use_count.h b/include/osmocom/core/use_count.h
index 6a4bf1f3..cc5493c7 100644
--- a/include/osmocom/core/use_count.h
+++ b/include/osmocom/core/use_count.h
@@ -130,8 +130,9 @@ typedef int (* osmo_use_count_cb_t )(struct osmo_use_count_entry *use_count_entr
* int foo_use_cb(struct osmo_use_count_entry *use_count_entry, int32_t old_use_count, const char *file, int line)
* {
* struct foo *foo = use_count_entry->use_count->talloc_object;
- * if (osmo_use_count_total(&use_count_entry->use_count) == 0)
+ * if (osmo_use_count_total(use_count_entry->use_count) == 0)
* talloc_free(foo);
+ * return 0;
* }
*
* // The function name is a convenient use token:
@@ -215,6 +216,8 @@ int _osmo_use_count_get_put(struct osmo_use_count *uc, const char *use, int32_t
const char *file, int line);
const char *osmo_use_count_name_buf(char *buf, size_t buf_len, const struct osmo_use_count *uc);
+int osmo_use_count_to_str_buf(char *buf, size_t buf_len, const struct osmo_use_count *uc);
+char *osmo_use_count_to_str_c(void *ctx, const struct osmo_use_count *uc);
int32_t osmo_use_count_total(const struct osmo_use_count *uc);
int32_t osmo_use_count_by(const struct osmo_use_count *uc, const char *use);
diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index 601bb565..c9d5560d 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include <osmocom/core/backtrace.h>
#include <osmocom/core/talloc.h>
@@ -21,6 +22,8 @@
#define OSMO_MAX(a, b) ((a) >= (b) ? (a) : (b))
/*! Return the minimum of two specified values */
#define OSMO_MIN(a, b) ((a) >= (b) ? (b) : (a))
+/*! Return a typical cmp result for comparable entities a and b. */
+#define OSMO_CMP(a, b) ((a) < (b)? -1 : ((a) > (b)? 1 : 0))
/*! Stringify the name of a macro x, e.g. an FSM event name.
* Note: if nested within another preprocessor macro, this will
* stringify the value of x instead of its name. */
@@ -37,7 +40,7 @@
/*! A mapping between human-readable string and numeric value */
struct value_string {
- unsigned int value; /*!< numeric value */
+ int value; /*!< numeric value */
const char *str; /*!< human-readable string */
};
@@ -52,6 +55,7 @@ char osmo_bcd2char(uint8_t bcd);
uint8_t osmo_char2bcd(char c);
int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibble, int end_nibble, bool allow_hex);
+int osmo_str2bcd(uint8_t *dst, size_t dst_size, const char *digits, int start_nibble, int end_nibble, bool allow_hex);
int osmo_hexparse(const char *str, uint8_t *b, int max_len);
@@ -136,6 +140,7 @@ uint64_t osmo_decode_big_endian(const uint8_t *data, size_t data_len);
uint8_t *osmo_encode_big_endian(uint64_t value, size_t data_len);
size_t osmo_strlcpy(char *dst, const char *src, size_t siz);
+const char *osmo_strnchr(const char *str, size_t str_size, char c);
bool osmo_is_hexstr(const char *str, int min_digits, int max_digits,
bool require_even);
@@ -144,6 +149,11 @@ bool osmo_identifier_valid(const char *str);
bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars);
void osmo_identifier_sanitize_buf(char *str, const char *sep_chars, char replace_with);
+size_t osmo_escape_cstr_buf(char *buf, size_t bufsize, const char *str, int in_len);
+char *osmo_escape_cstr_c(void *ctx, const char *str, int in_len);
+size_t osmo_quote_cstr_buf(char *buf, size_t bufsize, const char *str, int in_len);
+char *osmo_quote_cstr_c(void *ctx, const char *str, int in_len);
+
const char *osmo_escape_str(const char *str, int len);
char *osmo_escape_str_buf2(char *buf, size_t bufsize, const char *str, int in_len);
const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize);
@@ -269,4 +279,65 @@ struct osmo_strbuf {
bool osmo_str_startswith(const char *str, const char *startswith_str);
+int osmo_float_str_to_int(int64_t *val, const char *str, unsigned int precision);
+int osmo_int_to_float_str_buf(char *buf, size_t buflen, int64_t val, unsigned int precision);
+char *osmo_int_to_float_str_c(void *ctx, int64_t val, unsigned int precision);
+
+/*! Translate a buffer function to a talloc context function.
+ * This is the full function body of a char *foo_name_c(void *ctx, val...) function, implemented by an
+ * int foo_name_buf(buf, buflen, val...) function:
+ *
+ * char *foo_name_c(void *ctx, example_t arg)
+ * {
+ * OSMO_NAME_C_IMPL(ctx, 64, "ERROR", foo_name_buf, arg)
+ * }
+ *
+ * Return a talloc'd string containing the result of the given foo_name_buf() function, or ON_ERROR on error in the called
+ * foo_name_buf() function.
+ *
+ * If ON_ERROR is NULL, the function returns NULL on error rc from FUNC_BUF. Take care: returning NULL in printf() like
+ * formats (LOGP()) makes the program crash. If ON_ERROR is non-NULL, it must be a string constant, which is not
+ * returned directly, but written to an allocated string buffer first.
+ *
+ * \param[in] INITIAL_BUFSIZE Which size to first talloc from ctx -- a larger size makes a reallocation less likely, a
+ * smaller size allocates less unused bytes, zero allocates once but still runs the string composition twice.
+ * \param[in] ON_ERROR String constant to copy on error rc returned by FUNC_BUF, or NULL to return NULL.
+ * \param[in] FUNC_BUF Name of a function with signature int foo_buf(char *buf, size_t buflen, ...).
+ * The function must return the strlen() that it would write to a sufficiently large buffer or
+ * negative on error, like snprintf().
+ * \param[in] FUNC_BUF_ARGS Additional arguments to pass to FUNC_BUF after the buf and buflen.
+ */
+#define OSMO_NAME_C_IMPL(CTX, INITIAL_BUFSIZE, ON_ERROR, FUNC_BUF, FUNC_BUF_ARGS...) \
+ size_t _len = INITIAL_BUFSIZE; \
+ int _needed; \
+ char *_str = NULL; \
+ if ((INITIAL_BUFSIZE) > 0) { \
+ _str = (char*)talloc_named_const(CTX, _len, __func__); \
+ OSMO_ASSERT(_str); \
+ } \
+ _needed = FUNC_BUF(_str, _len, ## FUNC_BUF_ARGS); \
+ if (_needed < 0) \
+ goto OSMO_NAME_C_on_error; \
+ if (_needed < _len) \
+ return _str; \
+ _len = _needed + 1; \
+ if (_str) \
+ talloc_free(_str); \
+ _str = (char*)talloc_named_const(CTX, _len, __func__); \
+ OSMO_ASSERT(_str); \
+ _needed = FUNC_BUF(_str, _len, ## FUNC_BUF_ARGS); \
+ if (_needed < 0) \
+ goto OSMO_NAME_C_on_error; \
+ return _str; \
+OSMO_NAME_C_on_error: \
+ /* Re-using and re-sizing above allocated buf ends up in very complex code. Just free and strdup. */ \
+ if (_str) \
+ talloc_free(_str); \
+ if (!(ON_ERROR)) \
+ return NULL; \
+ _str = talloc_strdup(CTX, ON_ERROR); \
+ OSMO_ASSERT(_str); \
+ talloc_set_name_const(_str, __func__); \
+ return _str;
+
/*! @} */
diff --git a/include/osmocom/core/write_queue.h b/include/osmocom/core/write_queue.h
index 071621d1..75d5d8fb 100644
--- a/include/osmocom/core/write_queue.h
+++ b/include/osmocom/core/write_queue.h
@@ -53,6 +53,7 @@ struct osmo_wqueue {
void osmo_wqueue_init(struct osmo_wqueue *queue, int max_length);
void osmo_wqueue_clear(struct osmo_wqueue *queue);
int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data);
+int osmo_wqueue_enqueue_quiet(struct osmo_wqueue *queue, struct msgb *data);
int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what);
/*! @} */
diff --git a/include/osmocom/ctrl/ports.h b/include/osmocom/ctrl/ports.h
index 25d2491b..9759dc1e 100644
--- a/include/osmocom/ctrl/ports.h
+++ b/include/osmocom/ctrl/ports.h
@@ -24,4 +24,7 @@
#define OSMO_CTRL_PORT_GBPROXY 4263
/* 4264 used by VTY interface */
#define OSMO_CTRL_PORT_CBC 4265
+/* 4266 used by D-GSM mDNS */
+#define OSMO_CTRL_PORT_MGW 4267
+#define OSMO_CTRL_PORT_SMLC 4272
/* When adding/changing port numbers, keep docs and wiki in sync. See above. */
diff --git a/include/osmocom/gprs/gprs_bssgp.h b/include/osmocom/gprs/gprs_bssgp.h
index 400c3e00..b9d251cc 100644
--- a/include/osmocom/gprs/gprs_bssgp.h
+++ b/include/osmocom/gprs/gprs_bssgp.h
@@ -12,7 +12,10 @@
#include <osmocom/gprs/protocol/gsm_08_18.h>
/* gprs_bssgp_util.c */
+typedef int (*bssgp_bvc_send)(void *ctx, struct msgb *msg);
+
extern struct gprs_ns_inst *bssgp_nsi;
+void bssgp_set_bssgp_callback(bssgp_bvc_send ns_send, void *data);
struct msgb *bssgp_msgb_alloc(void);
struct msgb *bssgp_msgb_copy(const struct msgb *msg, const char *name);
const char *bssgp_cause_str(enum gprs_bssgp_cause cause);
@@ -112,6 +115,8 @@ extern struct llist_head bssgp_bvc_ctxts;
struct bssgp_bvc_ctx *btsctx_by_raid_cid(const struct gprs_ra_id *raid, uint16_t cid);
/* Find a BTS context based on BVCI+NSEI tuple */
struct bssgp_bvc_ctx *btsctx_by_bvci_nsei(uint16_t bvci, uint16_t nsei);
+/* Free a given BTS context */
+void bssgp_bvc_ctx_free(struct bssgp_bvc_ctx *ctx);
#define BVC_F_BLOCKED 0x0001
diff --git a/include/osmocom/gprs/gprs_bssgp_bss.h b/include/osmocom/gprs/gprs_bssgp_bss.h
index f07ab526..ab62b669 100644
--- a/include/osmocom/gprs/gprs_bssgp_bss.h
+++ b/include/osmocom/gprs/gprs_bssgp_bss.h
@@ -57,6 +57,7 @@ int bssgp_tx_bvc_block(struct bssgp_bvc_ctx *bctx, uint8_t cause);
int bssgp_tx_bvc_unblock(struct bssgp_bvc_ctx *bctx);
int bssgp_tx_bvc_reset(struct bssgp_bvc_ctx *bctx, uint16_t bvci, uint8_t cause);
+int bssgp_tx_bvc_reset2(struct bssgp_bvc_ctx *bctx, uint16_t bvci, uint8_t cause, bool add_cell_id);
int bssgp_tx_ul_ud(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
const uint8_t *qos_profile, struct msgb *llc_pdu);
diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h
index 02faa506..af25825e 100644
--- a/include/osmocom/gprs/gprs_ns.h
+++ b/include/osmocom/gprs/gprs_ns.h
@@ -97,6 +97,8 @@ struct gprs_ns_inst {
uint32_t remote_ip;
uint16_t remote_port;
int dscp;
+ /*! IPA compatibility: NS-RESET/BLOCK/UNBLOCK even on IP-SNS */
+ bool use_reset_block_unblock;
} nsip;
/*! NS-over-FR-over-GRE-over-IP specific bits */
struct {
@@ -186,6 +188,11 @@ struct sockaddr_in;
/* main function for higher layers (BSSGP) to send NS messages */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
+/* Receive incoming NS message from underlying transport layer */
+int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,
+ struct sockaddr_in *saddr, enum gprs_ns_ll ll);
+
+
int gprs_ns_tx_alive(struct gprs_nsvc *nsvc);
int gprs_ns_tx_alive_ack(struct gprs_nsvc *nsvc);
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
@@ -195,7 +202,6 @@ int gprs_ns_tx_unblock(struct gprs_nsvc *nsvc);
/* Listen for incoming GPRS packets via NS/FR/GRE */
int gprs_ns_frgre_listen(struct gprs_ns_inst *nsi);
-struct gprs_nsvc *gprs_nsvc_create(struct gprs_ns_inst *nsi, uint16_t nsvci);
struct gprs_nsvc *gprs_nsvc_create2(struct gprs_ns_inst *nsi, uint16_t nsvci,
uint8_t sig_weight, uint8_t data_weight);
void gprs_nsvc_delete(struct gprs_nsvc *nsvc);
diff --git a/include/osmocom/gprs/gprs_ns2.h b/include/osmocom/gprs/gprs_ns2.h
new file mode 100644
index 00000000..ffc2ad8e
--- /dev/null
+++ b/include/osmocom/gprs/gprs_ns2.h
@@ -0,0 +1,206 @@
+/*! \file gprs_ns2.h */
+
+
+#pragma once
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+#include <osmocom/core/prim.h>
+#include <osmocom/gprs/protocol/gsm_08_16.h>
+
+struct osmo_sockaddr;
+struct osmo_sockaddr_str;
+
+struct gprs_ns2_inst;
+struct gprs_ns2_nse;
+struct gprs_ns2_vc;
+struct gprs_ns2_vc_bind;
+struct gprs_ns2_vc_driver;
+struct gprs_ns_ie_ip4_elem;
+struct gprs_ns_ie_ip6_elem;
+
+enum gprs_ns2_vc_mode {
+ /*! The VC will use RESET/BLOCK/UNBLOCK to start the connection and do ALIVE/ACK.
+ * This is what is needed for Frame Relay transport, and if you use a R97/R99 Gb
+ * interface over an IP transport (never standardized by 3GPP) */
+ NS2_VC_MODE_BLOCKRESET,
+ /*! The VC will only use ALIVE/ACK (no RESET/BLOCK/UNBLOCK), which is for Gb-IP
+ * interface compliant to 3GPP Rel=4 or later. */
+ NS2_VC_MODE_ALIVE,
+};
+
+/*! Osmocom NS primitives according to 48.016 5.2 Service primitves */
+enum gprs_ns2_prim {
+ PRIM_NS_UNIT_DATA,
+ PRIM_NS_CONGESTION,
+ PRIM_NS_STATUS,
+};
+
+extern const struct value_string ns2_prim_strs[];
+
+/*! Obtain a human-readable string for NS primitives */
+static inline const char *gprs_ns2_prim_str(enum gprs_ns2_prim val)
+{ return get_value_string(ns2_prim_strs, val); }
+
+/*! Osmocom NS primitives according to 48.016 5.2.2.4 Service primitves */
+enum gprs_ns2_congestion_cause {
+ NS_CONG_CAUSE_BACKWARD_BEGIN,
+ NS_CONG_CAUSE_BACKWARD_END,
+ NS_CONG_CAUSE_FORWARD_BEGIN,
+ NS_CONG_CAUSE_FORWARD_END,
+};
+
+/*! Osmocom NS primitives according to 48.016 5.2.2.6 Service primitves */
+enum gprs_ns2_affecting_cause {
+ NS_AFF_CAUSE_VC_FAILURE,
+ NS_AFF_CAUSE_VC_RECOVERY,
+ NS_AFF_CAUSE_FAILURE,
+ NS_AFF_CAUSE_RECOVERY,
+ /* osmocom own causes */
+ NS_AFF_CAUSE_SNS_CONFIGURED,
+ NS_AFF_CAUSE_SNS_FAILURE,
+};
+
+extern const struct value_string gprs_ns2_aff_cause_prim_strs[];
+
+/*! Obtain a human-readable string for NS affective cause in primitives */
+static inline const char *gprs_ns2_aff_cause_prim_str(enum gprs_ns2_affecting_cause val)
+{ return get_value_string(gprs_ns2_aff_cause_prim_strs, val); }
+
+/*! Osmocom NS primitives according to 48.016 5.2.2.7 Service primitves */
+enum gprs_ns2_change_ip_endpoint {
+ NS_ENDPOINT_NO_CHANGE,
+ NS_ENDPOINT_REQUEST_CHANGE,
+ NS_ENDPOINT_CONFIRM_CHANGE,
+};
+
+extern const struct value_string gprs_ns2_cause_strs[];
+
+/*! Obtain a human-readable string for NS primitives */
+static inline const char *gprs_ns2_cause_str(enum ns_cause val)
+{ return get_value_string(gprs_ns2_cause_strs, val); }
+
+struct osmo_gprs_ns2_prim {
+ struct osmo_prim_hdr oph;
+
+ uint16_t nsei;
+ uint16_t bvci;
+
+ union {
+ struct {
+ enum gprs_ns2_change_ip_endpoint change;
+ /* TODO: implement resource distribution
+ * add place holder for the link selector */
+ long long _resource_distribution_placeholder1;
+ long long _resource_distribution_placeholder2;
+ long long _resource_distribution_placeholder3;
+ } unitdata;
+ struct {
+ enum gprs_ns2_congestion_cause cause;
+ } congestion;
+ struct {
+ enum gprs_ns2_affecting_cause cause;
+ /* 48.016 5.2.2.6 transfer capability */
+ int transfer;
+ /* osmocom specific */
+ /* Persistent NSE/NSVC are configured by vty */
+ bool persistent;
+ /* Only true on the first time it's available.
+ * Allow the BSSGP layer to reset persistent NSE */
+ bool first;
+ } status;
+ } u;
+};
+
+/* instance */
+struct gprs_ns2_inst *gprs_ns2_instantiate(void *ctx, osmo_prim_cb cb, void *cb_data);
+void gprs_ns2_free(struct gprs_ns2_inst *inst);
+int gprs_ns2_dynamic_create_nse(struct gprs_ns2_inst *nsi, bool create_nse);
+
+/* Entrypoint for primitives from the NS USER */
+int gprs_ns2_recv_prim(struct gprs_ns2_inst *nsi, struct osmo_prim_hdr *oph);
+
+/*! a callback to iterate over all NSVC */
+typedef int (*gprs_ns2_foreach_nsvc_cb)(struct gprs_ns2_vc *nsvc, void *ctx);
+
+int gprs_ns2_nse_foreach_nsvc(struct gprs_ns2_nse *nse,
+ gprs_ns2_foreach_nsvc_cb cb, void *cb_data);
+struct gprs_ns2_nse *gprs_ns2_nse_by_nsei(struct gprs_ns2_inst *nsi, uint16_t nsei);
+struct gprs_ns2_nse *gprs_ns2_create_nse(struct gprs_ns2_inst *nsi, uint16_t nsei);
+uint16_t gprs_ns2_nse_nsei(struct gprs_ns2_nse *nse);
+void gprs_ns2_free_nse(struct gprs_ns2_nse *nse);
+void gprs_ns2_free_nses(struct gprs_ns2_inst *nsi);
+
+/* create vc */
+void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc);
+struct gprs_ns2_vc *gprs_ns2_nsvc_by_nsvci(struct gprs_ns2_inst *nsi, uint16_t nsvci);
+
+/* IP VL driver */
+int gprs_ns2_ip_bind(struct gprs_ns2_inst *nsi,
+ const struct osmo_sockaddr *local,
+ int dscp,
+ struct gprs_ns2_vc_bind **result);
+struct gprs_ns2_vc_bind *gprs_ns2_ip_bind_by_sockaddr(struct gprs_ns2_inst *nsi,
+ const struct osmo_sockaddr *sockaddr);
+void gprs_ns2_bind_set_mode(struct gprs_ns2_vc_bind *bind, enum gprs_ns2_vc_mode mode);
+
+/* create a VC connection */
+struct gprs_ns2_vc *gprs_ns2_ip_connect(struct gprs_ns2_vc_bind *bind,
+ const struct osmo_sockaddr *remote,
+ struct gprs_ns2_nse *nse,
+ uint16_t nsvci);
+
+struct gprs_ns2_vc *gprs_ns2_ip_connect2(struct gprs_ns2_vc_bind *bind,
+ const struct osmo_sockaddr *remote,
+ uint16_t nsei,
+ uint16_t nsvci);
+struct gprs_ns2_vc *gprs_ns2_ip_connect_inactive(struct gprs_ns2_vc_bind *bind,
+ const struct osmo_sockaddr *remote,
+ struct gprs_ns2_nse *nse,
+ uint16_t nsvci);
+
+void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind);
+void gprs_ns2_free_binds(struct gprs_ns2_inst *nsi);
+
+/* create a VC SNS connection */
+int gprs_ns2_ip_connect_sns(struct gprs_ns2_vc_bind *bind,
+ const struct osmo_sockaddr *remote,
+ uint16_t nsei);
+const struct osmo_sockaddr *gprs_ns2_nse_sns_remote(struct gprs_ns2_nse *nse);
+
+const struct osmo_sockaddr *gprs_ns2_ip_vc_remote(const struct gprs_ns2_vc *nsvc);
+const struct osmo_sockaddr *gprs_ns2_ip_vc_local(const struct gprs_ns2_vc *nsvc);
+bool gprs_ns2_ip_vc_equal(const struct gprs_ns2_vc *nsvc,
+ const struct osmo_sockaddr *local,
+ const struct osmo_sockaddr *remote,
+ uint16_t nsvci);
+const struct osmo_sockaddr *gprs_ns2_ip_bind_sockaddr(struct gprs_ns2_vc_bind *bind);
+int gprs_ns2_is_ip_bind(struct gprs_ns2_vc_bind *bind);
+int gprs_ns2_ip_bind_set_dscp(struct gprs_ns2_vc_bind *bind, int dscp);
+struct gprs_ns2_vc *gprs_ns2_nsvc_by_sockaddr_bind(
+ struct gprs_ns2_vc_bind *bind,
+ const struct osmo_sockaddr *saddr);
+
+int gprs_ns2_frgre_bind(struct gprs_ns2_inst *nsi,
+ const struct osmo_sockaddr *local,
+ int dscp,
+ struct gprs_ns2_vc_bind **result);
+int gprs_ns2_is_frgre_bind(struct gprs_ns2_vc_bind *bind);
+
+struct gprs_ns2_vc *gprs_ns2_nsvc_by_sockaddr_nse(
+ struct gprs_ns2_nse *nse,
+ const struct osmo_sockaddr *sockaddr);
+void gprs_ns2_start_alive_all_nsvcs(struct gprs_ns2_nse *nse);
+const char *gprs_ns2_ll_str(struct gprs_ns2_vc *nsvc);
+char *gprs_ns2_ll_str_buf(char *buf, size_t buf_len, struct gprs_ns2_vc *nsvc);
+char *gprs_ns2_ll_str_c(const void *ctx, struct gprs_ns2_vc *nsvc);
+
+/* vty */
+int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
+ const struct osmo_sockaddr_str *default_bind);
+int gprs_ns2_vty_create();
+void gprs_ns2_vty_force_vc_mode(bool force, enum gprs_ns2_vc_mode mode, const char *reason);
+
+
+/*! @} */
diff --git a/include/osmocom/gprs/gprs_ns_frgre.h b/include/osmocom/gprs/gprs_ns_frgre.h
index d48ce086..8cf54c76 100644
--- a/include/osmocom/gprs/gprs_ns_frgre.h
+++ b/include/osmocom/gprs/gprs_ns_frgre.h
@@ -2,4 +2,7 @@
#pragma once
+struct gprs_nsvc;
+struct msgb;
+
int gprs_ns_frgre_sendmsg(struct gprs_nsvc *nsvc, struct msgb *msg);
diff --git a/include/osmocom/gprs/protocol/gsm_04_60.h b/include/osmocom/gprs/protocol/gsm_04_60.h
index f592b14f..05728f49 100644
--- a/include/osmocom/gprs/protocol/gsm_04_60.h
+++ b/include/osmocom/gprs/protocol/gsm_04_60.h
@@ -9,7 +9,6 @@
#include <stdint.h>
#include <osmocom/core/endian.h>
-#if OSMO_IS_LITTLE_ENDIAN == 1
/* TS 04.60 10.3a.4.1.1 */
struct gprs_rlc_ul_header_egprs_1 {
#if OSMO_IS_LITTLE_ENDIAN
@@ -160,158 +159,6 @@ struct gprs_rlc_dl_header_egprs_3 {
uint8_t dummy:1, spb:2, cps:4, bsn1_lo:1;
#endif
} __attribute__ ((packed));
-#else
-/* TS 04.60 10.3a.4.1.1 */
-struct gprs_rlc_ul_header_egprs_1 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:2,
- cv:4,
- si:1,
- r:1;
- uint8_t bsn1_hi:5,
- tfi_lo:3;
- uint8_t bsn2_hi:2,
- bsn1_lo:6;
- uint8_t bsn2_lo:8;
- uint8_t spare_hi:1,
- pi:1,
- rsb:1,
- cps:5;
- uint8_t dummy:2,
- spare_lo:6;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t r:1, si:1, cv:4, tfi_hi:2;
- uint8_t tfi_lo:3, bsn1_hi:5;
- uint8_t bsn1_lo:6, bsn2_hi:2;
- uint8_t bsn2_lo:8;
- uint8_t cps:5, rsb:1, pi:1, spare_hi:1;
- uint8_t spare_lo:6, dummy:2;
-#endif
-} __attribute__ ((packed));
-
-/* TS 04.60 10.3a.4.2.1 */
-struct gprs_rlc_ul_header_egprs_2 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:2,
- cv:4,
- si:1,
- r:1;
- uint8_t bsn1_hi:5,
- tfi_lo:3;
- uint8_t cps_hi:2,
- bsn1_lo:6;
- uint8_t spare_hi:5,
- pi:1,
- rsb:1,
- cps_lo:1;
- uint8_t dummy:3,
- spare_lo:5;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t r:1, si:1, cv:4, tfi_hi:2;
- uint8_t tfi_lo:3, bsn1_hi:5;
- uint8_t bsn1_lo:6, cps_hi:2;
- uint8_t cps_lo:1, rsb:1, pi:1, spare_hi:5;
- uint8_t spare_lo:5, dummy:3;
-#endif
-} __attribute__ ((packed));
-
-/* TS 04.60 10.3a.4.3.1 */
-struct gprs_rlc_ul_header_egprs_3 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:2,
- cv:4,
- si:1,
- r:1;
- uint8_t bsn1_hi:5,
- tfi_lo:3;
- uint8_t cps_hi:2,
- bsn1_lo:6;
- uint8_t dummy:1,
- spare:1,
- pi:1,
- rsb:1,
- spb:2,
- cps_lo:2;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t r:1, si:1, cv:4, tfi_hi:2;
- uint8_t tfi_lo:3, bsn1_hi:5;
- uint8_t bsn1_lo:6, cps_hi:2;
- uint8_t cps_lo:2, spb:2, rsb:1, pi:1, spare:1, dummy:1;
-#endif
-} __attribute__ ((packed));
-
-struct gprs_rlc_dl_header_egprs_1 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:1,
- rrbp:2,
- es_p:2,
- usf:3;
- uint8_t bsn1_hi:2,
- pr:2,
- tfi_lo:4;
- uint8_t bsn1_mid:8;
- uint8_t bsn2_hi:7,
- bsn1_lo:1;
- uint8_t cps:5,
- bsn2_lo:3;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t usf:3, es_p:2, rrbp:2, tfi_hi:1;
- uint8_t tfi_lo:4, pr:2, bsn1_hi:2;
- uint8_t bsn1_mid:8;
- uint8_t bsn1_lo:1, bsn2_hi:7;
- uint8_t bsn2_lo:3, cps:5;
-#endif
-} __attribute__ ((packed));
-
-struct gprs_rlc_dl_header_egprs_2 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:1,
- rrbp:2,
- es_p:2,
- usf:3;
- uint8_t bsn1_hi:2,
- pr:2,
- tfi_lo:4;
- uint8_t bsn1_mid:8;
- uint8_t dummy:4,
- cps:3,
- bsn1_lo:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t usf:3, es_p:2, rrbp:2, tfi_hi:1;
- uint8_t tfi_lo:4, pr:2, bsn1_hi:2;
- uint8_t bsn1_mid:8;
- uint8_t bsn1_lo:1, cps:3, dummy:4;
-#endif
-} __attribute__ ((packed));
-
-struct gprs_rlc_dl_header_egprs_3 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t tfi_hi:1,
- rrbp:2,
- es_p:2,
- usf:3;
- uint8_t bsn1_hi:2,
- pr:2,
- tfi_lo:4;
- uint8_t bsn1_mid:8;
- uint8_t dummy:1,
- spb:2,
- cps:4,
- bsn1_lo:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t usf:3, es_p:2, rrbp:2, tfi_hi:1;
- uint8_t tfi_lo:4, pr:2, bsn1_hi:2;
- uint8_t bsn1_mid:8;
- uint8_t bsn1_lo:1, cps:4, spb:2, dummy:1;
-#endif
-} __attribute__ ((packed));
-#endif
/* TS 03.60 Chapter 6.3.3.1: Network Mode of Operation */
enum osmo_gprs_nmo {
diff --git a/include/osmocom/gprs/protocol/gsm_08_16.h b/include/osmocom/gprs/protocol/gsm_08_16.h
index 95efcb6d..f98f68dd 100644
--- a/include/osmocom/gprs/protocol/gsm_08_16.h
+++ b/include/osmocom/gprs/protocol/gsm_08_16.h
@@ -6,6 +6,8 @@
#pragma once
#include <stdint.h>
+#include <arpa/inet.h>
+#include <osmocom/core/utils.h>
/*! \addtogroup libgb
* @{
@@ -26,6 +28,14 @@ struct gprs_ns_ie_ip4_elem {
uint8_t data_weight;
} __attribute__ ((packed));
+/*! Section 10.3.2d List of IP6 Elements */
+struct gprs_ns_ie_ip6_elem {
+ struct in6_addr ip_addr;
+ uint16_t udp_port;
+ uint8_t sig_weight;
+ uint8_t data_weight;
+} __attribute__ ((packed));
+
extern const struct value_string gprs_ns_pdu_strings[];
/*! NS PDU Type (TS 08.16, Section 10.3.7, Table 14) */
diff --git a/include/osmocom/gsm/bsslap.h b/include/osmocom/gsm/bsslap.h
new file mode 100644
index 00000000..b2174b3a
--- /dev/null
+++ b/include/osmocom/gsm/bsslap.h
@@ -0,0 +1,57 @@
+/*! \addtogroup bsslap
+ * @{
+ * \file bsslap.h
+ * Message encoding and decoding for 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_48_071.h>
+#include <osmocom/gsm/protocol/gsm_49_031.h>
+
+struct msgb;
+
+struct osmo_bsslap_err {
+ int rc;
+ enum bsslap_msgt msg_type;
+ enum bsslap_iei iei;
+ enum lcs_cause cause;
+ char *logmsg;
+};
+
+extern const struct value_string osmo_bsslap_msgt_names[];
+static inline const char *osmo_bsslap_msgt_name(enum bsslap_msgt val)
+{ return get_value_string(osmo_bsslap_msgt_names, val); }
+
+extern const struct value_string osmo_bsslap_iei_names[];
+static inline const char *osmo_bsslap_iei_name(enum bsslap_iei val)
+{ return get_value_string(osmo_bsslap_iei_names, val); }
+
+int osmo_bsslap_enc(struct msgb *msg, const struct bsslap_pdu *pdu);
+int osmo_bsslap_dec(struct bsslap_pdu *pdu,
+ struct osmo_bsslap_err **err, void *err_ctx,
+ const uint8_t *data, size_t len);
+
+/*! @} */
diff --git a/include/osmocom/gsm/bssmap_le.h b/include/osmocom/gsm/bssmap_le.h
new file mode 100644
index 00000000..1c750c8a
--- /dev/null
+++ b/include/osmocom/gsm/bssmap_le.h
@@ -0,0 +1,81 @@
+/*! \addtogroup bssmap_le
+ * @{
+ * \file bssmap_le.h
+ * Message encoding and decoding for 3GPP TS 49.031 BSSMAP-LE.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_49_031.h>
+
+struct osmo_bsslap_err;
+struct osmo_gad_err;
+
+struct osmo_bssmap_le_err {
+ int rc;
+ enum bssmap_le_msgt msg_type;
+ enum bssmap_le_iei iei;
+ enum lcs_cause cause;
+ struct osmo_bsslap_err *bsslap_err;
+ struct osmo_gad_err *gad_err;
+ char *logmsg;
+};
+
+struct osmo_bssap_le_err {
+ int rc;
+ struct osmo_bssmap_le_err *bssmap_le_err;
+ void *dtap_err;
+ char *logmsg;
+};
+
+enum bssmap_le_msgt osmo_bssmap_le_msgt(const uint8_t *data, uint8_t len);
+
+extern const struct value_string osmo_bssmap_le_msgt_names[];
+static inline const char *osmo_bssmap_le_msgt_name(enum bssmap_le_msgt val)
+{ return get_value_string(osmo_bssmap_le_msgt_names, val); }
+
+extern const struct value_string osmo_bssmap_le_iei_names[];
+static inline const char *osmo_bssmap_le_iei_name(enum bssmap_le_iei val)
+{ return get_value_string(osmo_bssmap_le_iei_names, val); }
+
+int osmo_lcs_cause_enc(struct msgb *msg, const struct lcs_cause_ie *lcs_cause);
+int osmo_lcs_cause_dec(struct lcs_cause_ie *lcs_cause,
+ enum bssmap_le_msgt msgt, enum bssmap_le_iei iei,
+ struct osmo_bssmap_le_err **err, void *err_ctx,
+ const uint8_t *data, uint8_t len);
+
+int osmo_bssap_le_pdu_to_str_buf(char *buf, size_t buflen, const struct bssap_le_pdu *bssap_le);
+char *osmo_bssap_le_pdu_to_str_c(void *ctx, const struct bssap_le_pdu *bssap_le);
+
+struct msgb *osmo_bssap_le_enc(const struct bssap_le_pdu *pdu);
+int osmo_bssap_le_dec(struct bssap_le_pdu *pdu, struct osmo_bssap_le_err **err, void *err_ctx, struct msgb *msg);
+
+uint8_t osmo_bssmap_le_ie_enc_location_type(struct msgb *msg, const struct bssmap_le_location_type *location_type);
+int osmo_bssmap_le_ie_dec_location_type(struct bssmap_le_location_type *lt,
+ enum bssmap_le_msgt msgt, enum bssmap_le_iei iei,
+ struct osmo_bssmap_le_err **err, void *err_ctx,
+ const uint8_t *elem, uint8_t len);
+
+/*! @} */
diff --git a/include/osmocom/gsm/bts_features.h b/include/osmocom/gsm/bts_features.h
index e84f95b6..341ba405 100644
--- a/include/osmocom/gsm/bts_features.h
+++ b/include/osmocom/gsm/bts_features.h
@@ -23,6 +23,9 @@ enum osmo_bts_features {
BTS_FEAT_SPEECH_F_EFR,
BTS_FEAT_SPEECH_F_AMR,
BTS_FEAT_SPEECH_H_AMR,
+ BTS_FEAT_ETWS_PN,
+ BTS_FEAT_PAGING_COORDINATION, /* BTS hands CS paging to PCU/PACCH */
+ BTS_FEAT_IPV6_NSVC,
_NUM_BTS_FEAT
};
@@ -36,8 +39,14 @@ static inline int osmo_bts_set_feature(struct bitvec *features, enum osmo_bts_fe
return bitvec_set_bit_pos(features, feature, 1);
}
+static inline int osmo_bts_unset_feature(struct bitvec *features, enum osmo_bts_features feature)
+{
+ OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
+ return bitvec_set_bit_pos(features, feature, 0);
+}
+
static inline bool osmo_bts_has_feature(const struct bitvec *features, enum osmo_bts_features feature)
{
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
- return bitvec_get_bit_pos(features, feature);
+ return bitvec_get_bit_pos(features, feature) == ONE;
}
diff --git a/include/osmocom/gsm/cbsp.h b/include/osmocom/gsm/cbsp.h
index 90516cb7..d456ce2f 100644
--- a/include/osmocom/gsm/cbsp.h
+++ b/include/osmocom/gsm/cbsp.h
@@ -6,8 +6,8 @@
#include <osmocom/gsm/gsm0808_utils.h>
/* Definitions for parsed / abstract representation of messages in the
- * CBSP (Cell Broadcast Service Protocol). Data here is *not* formatted
- * like the * on-the-wire format. Any similarities are coincidetial ;) */
+ * CBSP (Cell Broadcast Service Protocol, 3GPP TS 48.049). Data here is *not* formatted
+ * like the on-the-wire format. Any similarities are coincidential ;) */
/* Copyright (C) 2019 Harald Welte <laforge@gnumonks.org>
*
diff --git a/include/osmocom/gsm/gad.h b/include/osmocom/gsm/gad.h
new file mode 100644
index 00000000..57d0e37a
--- /dev/null
+++ b/include/osmocom/gsm/gad.h
@@ -0,0 +1,190 @@
+/*! \addtogroup gad
+ * @{
+ * \file gad.h
+ * Message encoding and decoding for 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * 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 <osmocom/gsm/protocol/gsm_23_032.h>
+#include <osmocom/core/utils.h>
+
+struct msgb;
+
+struct osmo_gad_ell_point {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+};
+
+struct osmo_gad_ell_point_unc_circle {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty circle radius in millimeters (m * 1e3), 0 .. 18'000'000. */
+ uint32_t unc;
+};
+
+struct osmo_gad_ell_point_unc_ellipse {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_polygon {
+ uint8_t num_points;
+ struct osmo_gad_ell_point point[15];
+};
+
+struct osmo_gad_ell_point_alt {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+};
+
+struct osmo_gad_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Uncertainty altitude in millimeters, 0 .. 990'000.
+ * Coding of uncertainty altitude is non-linear, and distinct from the non-altitude uncertainty coding. Use
+ * osmo_gad_dec_unc_alt(osmo_gad_enc_unc_alt(val)) to clamp. */
+ int32_t unc_alt;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ell_arc {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! inner circle radius in mm (m * 1e3) */
+ uint32_t inner_r;
+ /*! Uncertainty circle radius in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_r;
+ /*! Offset angle of first arc edge in degrees from North clockwise (eastwards), 0..359.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t ofs_angle;
+ /*! Included angle defining the angular width of the arc, in degrees clockwise, 1..360.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t incl_angle;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ha_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in millimeters, -500'000 (depth) .. 10'000'000 (height) */
+ int32_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Horizontal confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t h_confidence;
+ /*! High-Accuracy uncertainty altitude */
+ int32_t unc_alt;
+ /*! Vertical confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t v_confidence;
+};
+
+struct osmo_gad {
+ enum gad_type type;
+ union {
+ struct osmo_gad_ell_point ell_point;
+ struct osmo_gad_ell_point_unc_circle ell_point_unc_circle;
+ struct osmo_gad_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct osmo_gad_polygon polygon;
+ struct osmo_gad_ell_point_alt ell_point_alt;
+ struct osmo_gad_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct osmo_gad_ell_arc ell_arc;
+ struct osmo_gad_ell_point_unc_ellipse ha_ell_point_unc_ellipse;
+ struct osmo_gad_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+ };
+};
+
+struct osmo_gad_err {
+ int rc;
+ enum gad_type type;
+ char *logmsg;
+};
+
+extern const struct value_string osmo_gad_type_names[];
+static inline const char *osmo_gad_type_name(enum gad_type val)
+{ return get_value_string(osmo_gad_type_names, val); }
+
+int osmo_gad_raw_write(struct msgb *msg, const union gad_raw *gad_raw);
+int osmo_gad_raw_read(union gad_raw *gad_raw, struct osmo_gad_err **err, void *err_ctx, const uint8_t *data, uint8_t len);
+
+int osmo_gad_enc(union gad_raw *gad_raw, const struct osmo_gad *gad);
+int osmo_gad_dec(struct osmo_gad *gad, struct osmo_gad_err **err, void *err_ctx, const union gad_raw *gad_raw);
+
+int osmo_gad_to_str_buf(char *buf, size_t buflen, const struct osmo_gad *gad);
+char *osmo_gad_to_str_c(void *ctx, const struct osmo_gad *gad);
+
+uint32_t osmo_gad_enc_lat(int32_t deg_1e6);
+int32_t osmo_gad_dec_lat(uint32_t lat);
+uint32_t osmo_gad_enc_lon(int32_t deg_1e6);
+int32_t osmo_gad_dec_lon(uint32_t lon);
+uint8_t osmo_gad_enc_unc(uint32_t mm);
+uint32_t osmo_gad_dec_unc(uint8_t unc);
+/*! @} */
diff --git a/include/osmocom/gsm/gsm0502.h b/include/osmocom/gsm/gsm0502.h
index fe5cf7e1..1be2cc39 100644
--- a/include/osmocom/gsm/gsm0502.h
+++ b/include/osmocom/gsm/gsm0502.h
@@ -7,6 +7,30 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
+/* 4.3.3 TDMA frame number : constants and modular arithmetic */
+#define GSM_TDMA_FN_DURATION_nS 4615384 /* in 1e−9 seconds (approx) */
+#define GSM_TDMA_FN_DURATION_uS 4615 /* in 1e-6 seconds (approx) */
+
+#define GSM_TDMA_SUPERFRAME (26 * 51)
+#define GSM_TDMA_HYPERFRAME (2048 * GSM_TDMA_SUPERFRAME)
+
+/*! Return the sum of two specified TDMA frame numbers (summation) */
+#define GSM_TDMA_FN_SUM(a, b) \
+ ((a + b) % GSM_TDMA_HYPERFRAME)
+/*! Return the difference of two specified TDMA frame numbers (subtraction) */
+#define GSM_TDMA_FN_SUB(a, b) \
+ ((a + GSM_TDMA_HYPERFRAME - b) % GSM_TDMA_HYPERFRAME)
+/*! Return the *minimum* difference of two specified TDMA frame numbers (distance) */
+#define GSM_TDMA_FN_DIFF(a, b) \
+ OSMO_MIN(GSM_TDMA_FN_SUB(a, b), GSM_TDMA_FN_SUB(b, a))
+
+/*! Increment the given TDMA frame number by 1 and return the result (like ++fn) */
+#define GSM_TDMA_FN_INC(fn) \
+ ((fn) = GSM_TDMA_FN_SUM((fn), 1))
+/*! Decrement the given TDMA frame number by 1 and return the result (like --fn) */
+#define GSM_TDMA_FN_DEC(fn) \
+ ((fn) = GSM_TDMA_FN_SUB((fn), 1))
+
/* Table 5 Clause 7 TS 05.02 */
static inline unsigned int
gsm0502_get_n_pag_blocks(struct gsm48_control_channel_descr *chan_desc)
@@ -35,3 +59,19 @@ gsm0502_get_paging_group(uint64_t imsi, unsigned int bs_cc_chans,
unsigned int
gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi);
+
+enum gsm0502_fn_remap_channel {
+ FN_REMAP_TCH_F,
+ FN_REMAP_TCH_H0,
+ FN_REMAP_TCH_H1,
+ FN_REMAP_FACCH_F,
+ FN_REMAP_FACCH_H0,
+ FN_REMAP_FACCH_H1,
+ FN_REMAP_MAX,
+};
+
+uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel);
+
+uint16_t gsm0502_hop_seq_gen(const struct gsm_time *t,
+ uint8_t hsn, uint8_t maio,
+ size_t n, const uint16_t *ma);
diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
index 373b4341..20137daf 100644
--- a/include/osmocom/gsm/gsm0808.h
+++ b/include/osmocom/gsm/gsm0808.h
@@ -60,7 +60,9 @@ struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, ui
struct msgb *gsm0808_create_classmark_request();
struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
const uint8_t *cm3, uint8_t cm3_len);
-struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
+struct msgb *gsm0808_create_sapi_reject_cause(uint8_t link_id, uint16_t cause);
+struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
+ OSMO_DEPRECATED("Use gsm0808_create_sapi_reject_cause() instead");
struct msgb *gsm0808_create_ass(const struct gsm0808_channel_type *ct,
const uint16_t *cic,
const struct sockaddr_storage *ss,
@@ -104,6 +106,9 @@ struct msgb *gsm0808_create_lcls_conn_ctrl(enum gsm0808_lcls_config config,
enum gsm0808_lcls_control control);
struct msgb *gsm0808_create_lcls_conn_ctrl_ack(enum gsm0808_lcls_status status);
struct msgb *gsm0808_create_lcls_notification(enum gsm0808_lcls_status status, bool break_req);
+struct msgb *gsm0808_create_common_id(const char *imsi,
+ const struct osmo_plmn_id *selected_plmn_id,
+ const struct osmo_plmn_id *last_used_eutran_plnm_id);
/*! 3GPP TS 48.008 §3.2.2.5.8 Old BSS to New BSS information */
@@ -315,6 +320,13 @@ const char *gsm0808_bssap_name(uint8_t msg_type);
const char *gsm0808_cause_name(enum gsm0808_cause cause);
const char *gsm0808_cause_class_name(enum gsm0808_cause_class class);
+/*! Parse Cause TLV 3GPP TS 08.08 §3.2.2.5
+ * \returns Cause value */
+enum gsm0808_cause gsm0808_get_cause(const struct tlv_parsed *tp);
+
+const char *gsm0808_diagnostics_octet_location_str(uint8_t pointer);
+const char *gsm0808_diagnostics_bit_location_str(uint8_t bit_pointer);
+
extern const struct value_string gsm0808_lcls_config_names[];
extern const struct value_string gsm0808_lcls_control_names[];
extern const struct value_string gsm0808_lcls_status_names[];
diff --git a/include/osmocom/gsm/gsm0808_lcs.h b/include/osmocom/gsm/gsm0808_lcs.h
new file mode 100644
index 00000000..8fcbe380
--- /dev/null
+++ b/include/osmocom/gsm/gsm0808_lcs.h
@@ -0,0 +1,52 @@
+/*! \addtogroup gsm0808
+ * @{
+ * \file gsm0808_lcs.h
+ *
+ * Declarations that depend on both gsm0808.h and bssmap_le.h: LCS related message coding.
+ * (This file prevents circular dependency between struct definitions for BSSMAP messages, since BSSMAP references
+ * struct lcs_cause and struct bssmap_le_location_type, and BSSMAP-LE references gsm0808_cause.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.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 General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/gsm0808.h>
+#include <osmocom/gsm/bssmap_le.h>
+
+struct gsm0808_perform_location_request {
+ struct bssmap_le_location_type location_type;
+ struct osmo_mobile_identity imsi;
+
+ bool more_items; /*!< always set this to false */
+};
+struct msgb *gsm0808_create_perform_location_request(const struct gsm0808_perform_location_request *params);
+
+struct gsm0808_perform_location_response {
+ bool location_estimate_present;
+ union gad_raw location_estimate;
+
+ struct lcs_cause_ie lcs_cause;
+};
+struct msgb *gsm0808_create_perform_location_response(const struct gsm0808_perform_location_response *params);
+
+int gsm0808_enc_lcs_cause(struct msgb *msg, const struct lcs_cause_ie *lcs_cause);
+struct msgb *gsm0808_create_perform_location_abort(const struct lcs_cause_ie *lcs_cause);
+
+/*! @} */
diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h
index 76db2b6d..59db6edc 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -95,6 +95,7 @@ void gsm0808_cell_id_from_cgi(struct gsm0808_cell_id *cid, enum CELL_IDENT id_di
int gsm0808_cell_id_to_cgi(struct osmo_cell_global_id *cgi, const struct gsm0808_cell_id *cid);
void gsm0808_msgb_put_cell_id_u(struct msgb *msg, enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u);
int gsm0808_decode_cell_id_u(union gsm0808_cell_id_u *out, enum CELL_IDENT discr, const uint8_t *buf, unsigned int len);
+int gsm0808_cell_id_size(enum CELL_IDENT discr);
uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause);
uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg,
@@ -144,7 +145,7 @@ int gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t
/*! \returns 3GPP TS 08.08 §3.2.2.5 Class of a given Cause */
static inline enum gsm0808_cause_class gsm0808_cause_class(enum gsm0808_cause cause)
{
- return (cause << 1) >> 4;
+ return (cause >> 4) & 0x7;
}
/*! \returns true if 3GPP TS 08.08 §3.2.2.5 Class has extended bit set */
@@ -154,7 +155,8 @@ static inline bool gsm0808_cause_ext(enum gsm0808_cause cause)
return (cause & 0x80) && !(cause & 0x0F);
}
-int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp);
+int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp)
+OSMO_DEPRECATED("Use gsm0808_get_cause() instead");
/*! \returns 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */
static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type)
diff --git a/include/osmocom/gsm/gsm23236.h b/include/osmocom/gsm/gsm23236.h
new file mode 100644
index 00000000..23b003a1
--- /dev/null
+++ b/include/osmocom/gsm/gsm23236.h
@@ -0,0 +1,60 @@
+/*! \file gsm23236.h
+ * API to handle Network Resource Indicator (NRI) values and ranges for MSC pooling, as in 3GPP TS 23.236.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <osmocom/core/linuxlist.h>
+
+#define OSMO_NRI_BITLEN_MIN 1
+#define OSMO_NRI_BITLEN_MAX 15
+#define OSMO_NRI_BITLEN_DEFAULT 10
+
+/*! One range of NRI values. An NRI is a Network Resource Indicator, a number of a configured bit length (typically 10
+ * bit). In an MSC pool for load balancing, it is used to indicate which MSC has issued a TMSI: the NRI is located with
+ * its most significant bit located on the TMSI's second octet's most significant bit. See 3GPP TS 23.236. */
+struct osmo_nri_range {
+ struct llist_head entry;
+
+ /*! First value of the NRI range, i.e. inclusive. */
+ int16_t first;
+ /*! Last value of the NRI range, i.e. inclusive. */
+ int16_t last;
+};
+
+/*! A list of struct osmo_nri_range. Use osmo_nri_ranges_alloc() to create, and osmo_nri_ranges_free() (or talloc_free()
+ * on the parent context) to destroy. Always use osmo_nri_ranges_add() to insert entries, to ensure that the list
+ * remains sorted by 'first' values, which some of the osmo_nri_ranges API assumes to always be true.
+ *
+ * This struct serves as talloc context for the osmo_nri_range entries in the list, simplifying function signatures. It
+ * also makes the API future proof, to easily accomodate possible future additions.
+ */
+struct osmo_nri_ranges {
+ /* List of struct osmo_nri_range entries, talloc allocated from the parent struct osmo_nri_ranges. */
+ struct llist_head entries;
+};
+
+int osmo_nri_v_validate(int16_t nri_v, uint8_t nri_bitlen);
+bool osmo_nri_v_matches_ranges(int16_t nri_v, const struct osmo_nri_ranges *nri_ranges);
+int osmo_nri_v_limit_by_ranges(int16_t *nri_v, const struct osmo_nri_ranges *nri_ranges, uint32_t nri_bitlen);
+
+int osmo_tmsi_nri_v_get(int16_t *nri_v, uint32_t tmsi, uint8_t nri_bitlen);
+int osmo_tmsi_nri_v_set(uint32_t *tmsi, int16_t nri_v, uint8_t nri_bitlen);
+int osmo_tmsi_nri_v_limit_by_ranges(uint32_t *tmsi, const struct osmo_nri_ranges *nri_ranges, uint8_t nri_bitlen);
+
+int osmo_nri_range_validate(const struct osmo_nri_range *range, uint8_t nri_bitlen);
+bool osmo_nri_range_overlaps_ranges(const struct osmo_nri_range *range, const struct osmo_nri_ranges *nri_ranges);
+
+struct osmo_nri_ranges *osmo_nri_ranges_alloc(void *ctx);
+void osmo_nri_ranges_free(struct osmo_nri_ranges *nri_ranges);
+int osmo_nri_ranges_add(struct osmo_nri_ranges *nri_ranges, const struct osmo_nri_range *add);
+int osmo_nri_ranges_del(struct osmo_nri_ranges *nri_ranges, const struct osmo_nri_range *del);
+int osmo_nri_ranges_vty_add(const char **message, struct osmo_nri_range *added_range,
+ struct osmo_nri_ranges *nri_ranges, int argc, const char **argv, uint8_t nri_bitlen);
+int osmo_nri_ranges_vty_del(const char **message, struct osmo_nri_range *removed_range,
+ struct osmo_nri_ranges *nri_ranges, int argc, const char **argv);
+int osmo_nri_ranges_to_str_buf(char *buf, size_t buflen, const struct osmo_nri_ranges *nri_ranges);
+char *osmo_nri_ranges_to_str_c(void *ctx, const struct osmo_nri_ranges *nri_ranges);
diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h
index 7c68b1d2..f772f4a1 100644
--- a/include/osmocom/gsm/gsm48.h
+++ b/include/osmocom/gsm/gsm48.h
@@ -4,10 +4,12 @@
#include <stdbool.h>
+#include <osmocom/core/defs.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsm23003.h>
@@ -48,16 +50,55 @@ void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
void gsm48_generate_lai2(struct gsm48_loc_area_id *lai48, const struct osmo_location_area_id *lai);
#define GSM48_MID_MAX_SIZE 11
-int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
-int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
-uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type);
+int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi)
+ OSMO_DEPRECATED_OUTSIDE("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);"
+ " *l = osmo_mobile_identity_encode_msgb(...)");
+int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi)
+ OSMO_DEPRECATED_OUTSIDE("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);"
+ " *l = osmo_mobile_identity_encode_msgb(...)");
+uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type)
+ OSMO_DEPRECATED_OUTSIDE("Instead use: l = msgb_tl_put(msg, GSM48_IE_MOBILE_ID);"
+ " *l = osmo_mobile_identity_encode_msgb(...)");
-/* Convert Mobile Identity (10.5.1.4) to string */
-int gsm48_mi_to_string(char *string, int str_len, const uint8_t *mi, int mi_len);
const char *gsm48_mi_type_name(uint8_t mi);
-const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len);
-char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len);
-char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len);
+/* Convert encoded Mobile Identity (10.5.1.4) to string */
+int gsm48_mi_to_string(char *string, int str_len, const uint8_t *mi, int mi_len)
+ OSMO_DEPRECATED_OUTSIDE("Instead use osmo_mobile_identity_decode()");
+const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len)
+ OSMO_DEPRECATED_OUTSIDE("Instead use osmo_mobile_identity_to_str_c()");
+char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len)
+ OSMO_DEPRECATED_OUTSIDE("Instead use osmo_mobile_identity_to_str_buf()");
+char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len)
+ OSMO_DEPRECATED_OUTSIDE("Instead use osmo_mobile_identity_to_str_c()");
+
+/*! Decoded representation of a Mobile Identity (3GPP TS 24.008 10.5.1.4).
+ * See osmo_mobile_identity_decode() and osmo_mobile_identity_from_l3(). */
+struct osmo_mobile_identity {
+ /*! A GSM_MI_TYPE_* constant (like GSM_MI_TYPE_IMSI). */
+ uint8_t type;
+ /*! Decoded Mobile Identity digits or TMSI value. IMSI, IMEI and IMEISV as digits like
+ * "12345678", and TMSI is represented as raw uint32_t. */
+ union {
+ /*! type == GSM_MI_TYPE_IMSI. */
+ char imsi[GSM23003_IMSI_MAX_DIGITS + 1];
+ /*! type == GSM_MI_TYPE_IMEI. */
+ char imei[GSM23003_IMEI_NUM_DIGITS + 1];
+ /*! type == GSM_MI_TYPE_IMEISV. */
+ char imeisv[GSM23003_IMEISV_NUM_DIGITS + 1];
+ /*! TMSI / P-TMSI / M-TMSI integer value if type == GSM_MI_TYPE_TMSI. */
+ uint32_t tmsi;
+ };
+};
+
+int osmo_mobile_identity_to_str_buf(char *buf, size_t buflen, const struct osmo_mobile_identity *mi);
+char *osmo_mobile_identity_to_str_c(void *ctx, const struct osmo_mobile_identity *mi);
+int osmo_mobile_identity_cmp(const struct osmo_mobile_identity *a, const struct osmo_mobile_identity *b);
+int osmo_mobile_identity_decode(struct osmo_mobile_identity *mi, const uint8_t *mi_data, uint8_t mi_len,
+ bool allow_hex);
+int osmo_mobile_identity_decode_from_l3(struct osmo_mobile_identity *mi, struct msgb *msg, bool allow_hex);
+int osmo_mobile_identity_encoded_len(const struct osmo_mobile_identity *mi, int *mi_digits);
+int osmo_mobile_identity_encode_buf(uint8_t *buf, size_t buflen, const struct osmo_mobile_identity *mi, bool allow_hex);
+int osmo_mobile_identity_encode_msgb(struct msgb *msg, const struct osmo_mobile_identity *mi, bool allow_hex);
/* Parse Routeing Area Identifier */
void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf);
diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
index 71050df5..339aa136 100644
--- a/include/osmocom/gsm/gsm48_ie.h
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -7,6 +7,7 @@
#include <errno.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/defs.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/mncc.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
@@ -14,7 +15,7 @@
/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
int gsm48_decode_bcd_number(char *output, int output_len,
const uint8_t *bcd_lv, int h_len)
- OSMO_DEPRECATED("Use gsm48_decode_bcd_number2() for improved bounds checking");
+ OSMO_DEPRECATED_OUTSIDE("Use gsm48_decode_bcd_number2() for improved bounds checking");
int gsm48_decode_bcd_number2(char *output, size_t output_len,
const uint8_t *bcd_lv, size_t input_len,
size_t h_len);
diff --git a/include/osmocom/gsm/gsm48_rest_octets.h b/include/osmocom/gsm/gsm48_rest_octets.h
index d3bb878e..8f143be7 100644
--- a/include/osmocom/gsm/gsm48_rest_octets.h
+++ b/include/osmocom/gsm/gsm48_rest_octets.h
@@ -125,3 +125,6 @@ int osmo_gsm48_rest_octets_si13_encode(uint8_t *data, const struct osmo_gsm48_si
/* Parse SI3 Rest Octets */
void osmo_gsm48_rest_octets_si3_decode(struct osmo_gsm48_si_ro_info *si3, const uint8_t *data);
+
+/* Parse SI4 Rest Octets */
+void osmo_gsm48_rest_octets_si4_decode(struct osmo_gsm48_si_ro_info *si4, const uint8_t *data, int len);
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index 7a5da9a6..de634348 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -30,7 +30,6 @@
#include <osmocom/core/defs.h>
#include <osmocom/core/utils.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
#define ADD_MODULO(sum, delta, modulo) do { \
if ((sum += delta) >= modulo) \
@@ -116,8 +115,7 @@ int gsm_septet_encode(uint8_t *result, const char *data);
uint8_t gsm_get_octet_len(const uint8_t sept_len);
int gsm_7bit_decode_n_hdr(char *decoded, size_t n, const uint8_t *user_data, uint8_t length, uint8_t ud_hdr_ind);
-unsigned int ms_class_gmsk_dbm(enum gsm_band band, int ms_class);
-
+int ms_class_gmsk_dbm(enum gsm_band band, int ms_class);
int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
int ms_pwr_dbm(enum gsm_band band, uint8_t lvl);
diff --git a/include/osmocom/gsm/gsup.h b/include/osmocom/gsm/gsup.h
index be856620..56d7a309 100644
--- a/include/osmocom/gsm/gsup.h
+++ b/include/osmocom/gsm/gsup.h
@@ -45,6 +45,7 @@
#include <osmocom/gsm/protocol/gsm_03_40.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/protocol/gsm_08_08.h>
+#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/crypt/auth.h>
#define OSMO_GSUP_PORT 4222
@@ -86,6 +87,8 @@ enum osmo_gsup_iei {
OSMO_GSUP_AUTS_IE = 0x26,
OSMO_GSUP_RES_IE = 0x27,
OSMO_GSUP_CN_DOMAIN_IE = 0x28,
+ OSMO_GSUP_SUPPORTED_RAT_TYPES_IE = 0x29, /* supported RAT types */
+ OSMO_GSUP_CURRENT_RAT_TYPE_IE = 0x2a, /* currently used RAT type */
OSMO_GSUP_SESSION_ID_IE = 0x30,
OSMO_GSUP_SESSION_STATE_IE = 0x31,
@@ -104,6 +107,7 @@ enum osmo_gsup_iei {
OSMO_GSUP_IMEI_IE = 0x50,
OSMO_GSUP_IMEI_RESULT_IE = 0x51,
+ OSMO_GSUP_NUM_VECTORS_REQ_IE = 0x52,
/* Inter-MSC handover related */
OSMO_GSUP_SOURCE_NAME_IE = 0x60,
@@ -193,12 +197,17 @@ enum osmo_gsup_message_type {
OSMO_GSUP_MSGT_E_CLOSE = 0b01000111,
OSMO_GSUP_MSGT_E_ABORT = 0b01001011,
- OSMO_GSUP_MSGT_E_ROUTING_ERROR = 0b01001110,
+ OSMO_GSUP_MSGT_ROUTING_ERROR = 0b01001110,
};
+#define OSMO_GSUP_MSGT_E_ROUTING_ERROR OSMO_GSUP_MSGT_ROUTING_ERROR
+
#define OSMO_GSUP_IS_MSGT_REQUEST(msgt) (((msgt) & 0b00000011) == 0b00)
#define OSMO_GSUP_IS_MSGT_ERROR(msgt) (((msgt) & 0b00000011) == 0b01)
+#define OSMO_GSUP_IS_MSGT_RESULT(msgt) (((msgt) & 0b00000011) == 0b10)
+#define OSMO_GSUP_TO_MSGT_REQUEST(msgt) (((msgt) & 0b11111100))
#define OSMO_GSUP_TO_MSGT_ERROR(msgt) (((msgt) & 0b11111100) | 0b01)
+#define OSMO_GSUP_TO_MSGT_RESULT(msgt) (((msgt) & 0b11111100) | 0b10)
extern const struct value_string osmo_gsup_message_type_names[];
static inline const char *
@@ -373,6 +382,10 @@ struct osmo_gsup_message {
/*! Session Management cause as of 3GPP TS 24.008 10.5.6.6 / Table 10.5.157. */
enum gsm48_gsm_cause cause_sm;
+
+ enum osmo_rat_type current_rat_type;
+ enum osmo_rat_type supported_rat_types[8]; /*!< arbitrary choice */
+ size_t supported_rat_types_len;
};
int osmo_gsup_decode(const uint8_t *data, size_t data_len,
diff --git a/include/osmocom/gsm/i460_mux.h b/include/osmocom/gsm/i460_mux.h
new file mode 100644
index 00000000..8e392434
--- /dev/null
+++ b/include/osmocom/gsm/i460_mux.h
@@ -0,0 +1,121 @@
+/*! \file i460_mux.h
+ * ITU-T I.460 sub-channel multiplexer + demultiplexer */
+/*
+ * (C) 2020 by Harald Welte <laforge@gnumonks.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#pragma once
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/msgb.h>
+
+/* I.460 sub-slot rate */
+enum osmo_i460_rate {
+ OSMO_I460_RATE_NONE, /* disabled */
+ OSMO_I460_RATE_64k,
+ OSMO_I460_RATE_32k,
+ OSMO_I460_RATE_16k,
+ OSMO_I460_RATE_8k,
+};
+
+struct osmo_i460_subchan;
+
+typedef void (*out_cb_bits_t)(struct osmo_i460_subchan *schan, void *user_data,
+ const ubit_t *bits, unsigned int num_bits);
+typedef void (*out_cb_bytes_t)(struct osmo_i460_subchan *schan, void *user_data,
+ const uint8_t *bytes, unsigned int num_bytes);
+
+struct osmo_i460_subchan_demux {
+ /*! bit-buffer for output bits */
+ uint8_t *out_bitbuf;
+ /*! size of out_bitbuf in bytes */
+ unsigned int out_bitbuf_size;
+ /*! offset of next bit to be written in out_bitbuf */
+ unsigned int out_idx;
+ /*! callback to be called once we have received out_bitbuf_size bits */
+ out_cb_bits_t out_cb_bits;
+ out_cb_bytes_t out_cb_bytes;
+ void *user_data;
+};
+
+typedef void (*in_cb_queue_empty_t)(struct osmo_i460_subchan *schan, void *user_data);
+
+struct osmo_i460_subchan_mux {
+ /*! list of to-be-transmitted message buffers */
+ struct llist_head tx_queue;
+ in_cb_queue_empty_t in_cb_queue_empty;
+ void *user_data;
+};
+
+struct osmo_i460_subchan {
+ struct osmo_i460_timeslot *ts; /* back-pointer */
+ enum osmo_i460_rate rate; /* 8/16/32/64k */
+ uint8_t bit_offset; /* bit offset inside each byte of the B-channel */
+ struct osmo_i460_subchan_demux demux;
+ struct osmo_i460_subchan_mux mux;
+};
+
+struct osmo_i460_timeslot {
+ struct osmo_i460_subchan schan[8];
+};
+
+/*! description of a sub-channel; passed by caller */
+struct osmo_i460_schan_desc {
+ enum osmo_i460_rate rate;
+ uint8_t bit_offset;
+ struct {
+ /* size (in bits) of the internal buffer; determines granularity */
+ size_t num_bits;
+ /*! call-back function called whenever we received num_bits */
+ out_cb_bits_t out_cb_bits;
+ /*! out_cb_bytes call-back function called whenever we received num_bits.
+ * The user is usually expected to provide either out_cb_bits or out_cb_bytes. If only
+ * out_cb_bits is provided, output data will always be provided as unpacked bits; if only
+ * out_cb_bytes is provided, output data will always be provided as packet bits (bytes). If
+ * both are provided, it is up to the I.460 multiplex to decide if it calls either of the two,
+ * depending on what can be provided without extra conversion. */
+ out_cb_bytes_t out_cb_bytes;
+ /* opaque user data pointer to pass to out_cb */
+ void *user_data;
+ } demux;
+
+ struct {
+ /* call-back function whenever the muxer requires more input data from the sub-channels,
+ * but has nothing enqueued yet. A typical function would then call osmo_i460_mux_enqueue() */
+ in_cb_queue_empty_t in_cb_queue_empty;
+ /* opaque user data pointer to pass to in_cb */
+ void *user_data;
+ } mux;
+};
+
+void osmo_i460_demux_in(struct osmo_i460_timeslot *ts, const uint8_t *data, size_t data_len);
+
+void osmo_i460_mux_enqueue(struct osmo_i460_subchan *schan, struct msgb *msg);
+int osmo_i460_mux_out(struct osmo_i460_timeslot *ts, uint8_t *out, size_t out_len);
+
+void osmo_i460_ts_init(struct osmo_i460_timeslot *ts);
+
+struct osmo_i460_subchan *
+osmo_i460_subchan_add(void *ctx, struct osmo_i460_timeslot *ts, const struct osmo_i460_schan_desc *chd);
+
+void osmo_i460_subchan_del(struct osmo_i460_subchan *schan);
+
+/*! @} */
diff --git a/include/osmocom/gsm/l1sap.h b/include/osmocom/gsm/l1sap.h
index 19cc87a3..d1396908 100644
--- a/include/osmocom/gsm/l1sap.h
+++ b/include/osmocom/gsm/l1sap.h
@@ -67,8 +67,8 @@ struct ph_rach_ind_param {
/* elements added on 2018-02-26 */
int8_t rssi; /*!< RSSI of RACH indication */
uint16_t ber10k; /*!< BER in units of 0.01% */
- int16_t acc_delay_256bits;/* !< Burst TA Offset in 1/256th bits */
- int16_t lqual_cb; /* !< Link quality in centiBel */
+ int16_t acc_delay_256bits;/*!< Burst TA Offset in 1/256th bits */
+ int16_t lqual_cb; /*!< Link quality in centiBel */
};
/*! for PH-[UNIT]DATA.{req,ind} | PH-RTS.ind */
@@ -79,11 +79,12 @@ struct ph_data_param {
int8_t rssi; /*!< RSSI of receivedindication */
uint16_t ber10k; /*!< BER in units of 0.01% */
union {
- int16_t ta_offs_qbits; /* !< Burst TA Offset in quarter bits */
+ int16_t ta_offs_qbits; /*!< Burst TA Offset in quarter bits */
int16_t ta_offs_256bits;/*!< timing advance offset (in 1/256th bits) */
};
- int16_t lqual_cb; /* !< Link quality in centiBel */
+ int16_t lqual_cb; /*!< Link quality in centiBel */
enum osmo_ph_pres_info_type pdch_presence_info; /*!< Info regarding presence/validity of header and data parts */
+ uint8_t is_sub:1; /*!< flags */
};
/*! for TCH.{req,ind} | TCH-RTS.ind */
@@ -93,7 +94,9 @@ struct ph_tch_param {
int8_t rssi; /*!< RSSI of received indication */
uint8_t marker; /*!< RTP Marker bit (speech onset indicator) */
uint16_t ber10k; /*!< BER in units of 0.01% */
- int16_t lqual_cb; /* !< Link quality in centiBel */
+ int16_t lqual_cb; /*!< Link quality in centiBel */
+ int16_t ta_offs_256bits;/*!< timing advance offset (in 1/256th bits) */
+ uint8_t is_sub:1; /*!< flags */
};
/*! for PH-CONN.ind */
@@ -123,7 +126,7 @@ struct info_meas_ind_param {
/*! for {ACTIVATE,DEACTIVATE,MODIFY} MPH-INFO.req */
struct info_act_req_param {
uint8_t chan_nr; /*!< Channel Number (Like RSL) */
- uint8_t sacch_only; /*!< \breif Only deactivate SACCH */
+ uint8_t sacch_only; /*!< \brief Only deactivate SACCH */
};
/*! for {ACTIVATE,DEACTIVATE} MPH-INFO.cnf */
diff --git a/include/osmocom/gsm/lapd_core.h b/include/osmocom/gsm/lapd_core.h
index cfc357a7..69e10875 100644
--- a/include/osmocom/gsm/lapd_core.h
+++ b/include/osmocom/gsm/lapd_core.h
@@ -14,6 +14,9 @@
* \file lapd_core.h
*/
+#define LOGDL(dl, level, fmt, args...) \
+ LOGP(DLLAPD, level, "(%s) " fmt, (dl)->name, ## args)
+
/*! LAPD related primitives (L2<->L3 SAP)*/
enum osmo_dl_prim {
PRIM_DL_UNIT_DATA, /*!< DL-UNIT-DATA */
@@ -158,10 +161,13 @@ struct lapd_datalink {
uint8_t range_hist; /*!< range of history buffer 2..2^n */
struct msgb *rcv_buffer; /*!< buffer to assemble the received message */
struct msgb *cont_res; /*!< buffer to store content resolution data on network side, to detect multiple phones on same channel */
+ char *name; /*!< user-provided name */
};
-void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range,
- int maxf);
+void lapd_dl_init(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf)
+ OSMO_DEPRECATED("Use lapd_dl_init2() instead");
+void lapd_dl_init2(struct lapd_datalink *dl, uint8_t k, uint8_t v_range, int maxf, const char *name);
+void lapd_dl_set_name(struct lapd_datalink *dl, const char *name);
void lapd_dl_exit(struct lapd_datalink *dl);
void lapd_dl_reset(struct lapd_datalink *dl);
int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode);
diff --git a/include/osmocom/gsm/lapdm.h b/include/osmocom/gsm/lapdm.h
index 931de80a..633df1ad 100644
--- a/include/osmocom/gsm/lapdm.h
+++ b/include/osmocom/gsm/lapdm.h
@@ -83,13 +83,19 @@ struct lapdm_datalink *lapdm_datalink_for_sapi(struct lapdm_entity *le, uint8_t
/* initialize a LAPDm entity */
void lapdm_entity_init(struct lapdm_entity *le, enum lapdm_mode mode, int t200)
- OSMO_DEPRECATED("Use lapdm_entity_init2() instead");
+ OSMO_DEPRECATED("Use lapdm_entity_init3() instead");
void lapdm_entity_init2(struct lapdm_entity *le, enum lapdm_mode mode,
- const int *t200_ms, int n200);
+ const int *t200_ms, int n200)
+ OSMO_DEPRECATED("Use lapdm_entity_init3() instead");
+void lapdm_entity_init3(struct lapdm_entity *le, enum lapdm_mode mode,
+ const int *t200_ms, int n200, const char *name_pfx);
void lapdm_channel_init(struct lapdm_channel *lc, enum lapdm_mode mode)
- OSMO_DEPRECATED("Use lapdm_channel_init2() instead");
+ OSMO_DEPRECATED("Use lapdm_channel_init3() instead");
int lapdm_channel_init2(struct lapdm_channel *lc, enum lapdm_mode mode,
const int *t200_ms_dcch, const int *t200_ms_acch, enum gsm_chan_t chan_t);
+int lapdm_channel_init3(struct lapdm_channel *lc, enum lapdm_mode mode,
+ const int *t200_ms_dcch, const int *t200_ms_acch, enum gsm_chan_t chan_t,
+ const char *name_pfx);
/* deinitialize a LAPDm entity */
void lapdm_entity_exit(struct lapdm_entity *le);
void lapdm_channel_exit(struct lapdm_channel *lc);
diff --git a/include/osmocom/gsm/mncc.h b/include/osmocom/gsm/mncc.h
index e5e96074..db70235c 100644
--- a/include/osmocom/gsm/mncc.h
+++ b/include/osmocom/gsm/mncc.h
@@ -10,10 +10,10 @@
/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
struct gsm_mncc_bearer_cap {
- int transfer; /* Information Transfer Capability */
- int mode; /* Transfer Mode */
- int coding; /* Coding Standard */
- int radio; /* Radio Channel Requirement */
+ int transfer; /* Information Transfer Capability, see enum gsm48_bcap_itcap. */
+ int mode; /* Transfer Mode, see enum gsm48_bcap_tmod. */
+ int coding; /* Coding Standard, see enum gsm48_bcap_coding.*/
+ int radio; /* Radio Channel Requirement, see enum gsm48_bcap_rrq. */
int speech_ctm; /* CTM text telephony indication */
int speech_ver[8]; /* Speech version indication, see enum gsm48_bcap_speech_ver; -1 marks end */
struct {
diff --git a/include/osmocom/gsm/prim.h b/include/osmocom/gsm/prim.h
index 386b7d89..e7a60e30 100644
--- a/include/osmocom/gsm/prim.h
+++ b/include/osmocom/gsm/prim.h
@@ -14,4 +14,6 @@ enum osmo_gsm_sap {
SAP_BSSGP_LL,
SAP_BSSGP_NM,
SAP_BSSGP_PFM,
+
+ SAP_NS,
};
diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
index 2be6ed34..f8f2eabd 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -9,6 +9,8 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/endian.h>
+#include <osmocom/gsm/gsm_utils.h>
+
struct gsm_lchan;
/* Chapter 10.5.1.5 */
@@ -73,9 +75,8 @@ const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm);
char *osmo_gsm48_classmark_a5_name_buf(char *buf, size_t buf_len, const struct osmo_gsm48_classmark *cm);
char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_classmark *cm);
void osmo_gsm48_classmark_update(struct osmo_gsm48_classmark *dst, const struct osmo_gsm48_classmark *src);
-
+int8_t osmo_gsm48_rfpowercap2powerclass(enum gsm_band band, uint8_t rf_power_cap);
/* Chapter 10.5.2.1b.3 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_1024 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t w1_hi:2,
@@ -129,64 +130,8 @@ struct gsm48_range_1024 {
uint8_t w15_lo:2, w16:6;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_1024 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:5,
- f0:1,
- w1_hi:2;
- uint8_t w1_lo;
- uint8_t w2_hi;
- uint8_t w2_lo:1,
- w3_hi:7;
- uint8_t w3_lo:2,
- w4_hi:6;
- uint8_t w4_lo:2,
- w5_hi:6;
- uint8_t w5_lo:2,
- w6_hi:6;
- uint8_t w6_lo:2,
- w7_hi:6;
- uint8_t w7_lo:2,
- w8_hi:6;
- uint8_t w8_lo:1,
- w9:7;
- uint8_t w10:7,
- w11_hi:1;
- uint8_t w11_lo:6,
- w12_hi:2;
- uint8_t w12_lo:5,
- w13_hi:3;
- uint8_t w13_lo:4,
- w14_hi:4;
- uint8_t w14_lo:3,
- w15_hi:5;
- uint8_t w15_lo:2,
- w16:6;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t w1_hi:2, f0:1, form_id:5;
- uint8_t w1_lo;
- uint8_t w2_hi;
- uint8_t w3_hi:7, w2_lo:1;
- uint8_t w4_hi:6, w3_lo:2;
- uint8_t w5_hi:6, w4_lo:2;
- uint8_t w6_hi:6, w5_lo:2;
- uint8_t w7_hi:6, w6_lo:2;
- uint8_t w8_hi:6, w7_lo:2;
- uint8_t w9:7, w8_lo:1;
- uint8_t w11_hi:1, w10:7;
- uint8_t w12_hi:2, w11_lo:6;
- uint8_t w13_hi:3, w12_lo:5;
- uint8_t w14_hi:4, w13_lo:4;
- uint8_t w15_hi:5, w14_lo:3;
- uint8_t w16:6, w15_lo:2;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.4 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_512 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -240,64 +185,8 @@ struct gsm48_range_512 {
uint8_t w16_lo:3, w17:5;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_512 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1_hi:7;
- uint8_t w1_lo:2,
- w2_hi:6;
- uint8_t w2_lo:2,
- w3_hi:6;
- uint8_t w3_lo:2,
- w4_hi:6;
- uint8_t w4_lo:1,
- w5:7;
- uint8_t w6:7,
- w7_hi:1;
- uint8_t w7_lo:6,
- w8_hi:2;
- uint8_t w8_lo:4,
- w9_hi:4;
- uint8_t w9_lo:2,
- w10:6;
- uint8_t w11:6,
- w12_hi:2;
- uint8_t w12_lo:4,
- w13_hi:4;
- uint8_t w13_lo:2,
- w14:6;
- uint8_t w15:6,
- w16_hi:2;
- uint8_t w16_lo:3,
- w17:5;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1_hi:7, orig_arfcn_lo:1;
- uint8_t w2_hi:6, w1_lo:2;
- uint8_t w3_hi:6, w2_lo:2;
- uint8_t w4_hi:6, w3_lo:2;
- uint8_t w5:7, w4_lo:1;
- uint8_t w7_hi:1, w6:7;
- uint8_t w8_hi:2, w7_lo:6;
- uint8_t w9_hi:4, w8_lo:4;
- uint8_t w10:6, w9_lo:2;
- uint8_t w12_hi:2, w11:6;
- uint8_t w13_hi:4, w12_lo:4;
- uint8_t w14:6, w13_lo:2;
- uint8_t w16_hi:2, w15:6;
- uint8_t w17:5, w16_lo:3;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.5 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_256 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -357,70 +246,8 @@ struct gsm48_range_256 {
uint8_t w20_lo:3, w21:4, spare:1;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_256 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1_hi:7;
- uint8_t w1_lo:1,
- w2:7;
- uint8_t w3:7,
- w4_hi:1;
- uint8_t w4_lo:5,
- w5_hi:3;
- uint8_t w5_lo:3,
- w6_hi:5;
- uint8_t w6_lo:1,
- w7:6,
- w8_hi:1;
- uint8_t w8_lo:4,
- w9_hi:4;
- uint8_t w9_lo:1,
- w10:5,
- w11_hi:2;
- uint8_t w11_lo:3,
- w12:5;
- uint8_t w13:5,
- w14_hi:3;
- uint8_t w14_lo:2,
- w15:5,
- w16_hi:1;
- uint8_t w16_lo:3,
- w17:4,
- w18_hi:1;
- uint8_t w18_lo:3,
- w19:4,
- w20_hi:1;
- uint8_t w20_lo:3,
- w21:4,
- spare:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1_hi:7, orig_arfcn_lo:1;
- uint8_t w2:7, w1_lo:1;
- uint8_t w4_hi:1, w3:7;
- uint8_t w5_hi:3, w4_lo:5;
- uint8_t w6_hi:5, w5_lo:3;
- uint8_t w8_hi:1, w7:6, w6_lo:1;
- uint8_t w9_hi:4, w8_lo:4;
- uint8_t w11_hi:2, w10:5, w9_lo:1;
- uint8_t w12:5, w11_lo:3;
- uint8_t w14_hi:3, w13:5;
- uint8_t w16_hi:1, w15:5, w14_lo:2;
- uint8_t w18_hi:1, w17:4, w16_lo:3;
- uint8_t w20_hi:1, w19:4, w18_lo:3;
- uint8_t spare:1, w21:4, w20_lo:3;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.6 */
-#if OSMO_IS_LITTLE_ENDIAN == 1
struct gsm48_range_128 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t orig_arfcn_hi:1,
@@ -482,69 +309,6 @@ struct gsm48_range_128 {
uint8_t w26_lo:1, w27:3, w28:3, spare:1;
#endif
} __attribute__ ((packed));
-#else
-struct gsm48_range_128 {
-#if OSMO_IS_LITTLE_ENDIAN
- uint8_t form_id:7,
- orig_arfcn_hi:1;
- uint8_t orig_arfcn_mid;
- uint8_t orig_arfcn_lo:1,
- w1:7;
- uint8_t w2:6,
- w3_hi:2;
- uint8_t w3_lo:4,
- w4_hi:4;
- uint8_t w4_lo:1,
- w5:5,
- w6_hi:2;
- uint8_t w6_lo:3,
- w7:5;
- uint8_t w8:4,
- w9:4;
- uint8_t w10:4,
- w11:4;
- uint8_t w12:4,
- w13:4;
- uint8_t w14:4,
- w15:4;
- uint8_t w16:3,
- w17:3,
- w18_hi:2;
- uint8_t w18_lo:1,
- w19:3,
- w20:3,
- w21_hi:1;
- uint8_t w21_lo:2,
- w22:3,
- w23:3;
- uint8_t w24:3,
- w25:3,
- w26_hi:2;
- uint8_t w26_lo:1,
- w27:3,
- w28:3,
- spare:1;
-#elif OSMO_IS_BIG_ENDIAN
-/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
- uint8_t orig_arfcn_hi:1, form_id:7;
- uint8_t orig_arfcn_mid;
- uint8_t w1:7, orig_arfcn_lo:1;
- uint8_t w3_hi:2, w2:6;
- uint8_t w4_hi:4, w3_lo:4;
- uint8_t w6_hi:2, w5:5, w4_lo:1;
- uint8_t w7:5, w6_lo:3;
- uint8_t w9:4, w8:4;
- uint8_t w11:4, w10:4;
- uint8_t w13:4, w12:4;
- uint8_t w15:4, w14:4;
- uint8_t w18_hi:2, w17:3, w16:3;
- uint8_t w21_hi:1, w20:3, w19:3, w18_lo:1;
- uint8_t w23:3, w22:3, w21_lo:2;
- uint8_t w26_hi:2, w25:3, w24:3;
- uint8_t spare:1, w28:3, w27:3, w26_lo:1;
-#endif
-} __attribute__ ((packed));
-#endif
/* Chapter 10.5.2.1b.7 */
struct gsm48_var_bit {
@@ -887,13 +651,25 @@ struct gsm48_pag_resp {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t spare:4,
key_seq:4;
- uint32_t classmark2;
+ union {
+ uint32_t classmark2; /* Backward compatibility */
+ struct {
+ uint8_t cm2_len;
+ struct gsm48_classmark2 cm2;
+ };
+ };
uint8_t mi_len;
uint8_t mi[0];
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
uint8_t key_seq:4, spare:4;
- uint32_t classmark2;
+ union {
+ uint32_t classmark2;
+ struct {
+ uint8_t cm2_len;
+ struct gsm48_classmark2 cm2;
+ };
+ };
uint8_t mi_len;
uint8_t mi[0];
#endif
@@ -954,7 +730,7 @@ struct gsm48_system_information_type_header {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t l2_plen;
uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
+ skip_indicator:4;
uint8_t system_information;
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
@@ -1025,15 +801,26 @@ struct gsm48_service_request {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t cm_service_type : 4,
cipher_key_seq : 4;
- /* length + 3 bytes */
- uint32_t classmark;
+ union {
+ uint32_t classmark; /* Backward compatibility */
+ struct {
+ uint8_t cm2_len;
+ struct gsm48_classmark2 classmark2;
+ };
+ };
uint8_t mi_len;
uint8_t mi[0];
/* optional priority level */
#elif OSMO_IS_BIG_ENDIAN
/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
uint8_t cipher_key_seq:4, cm_service_type:4;
- uint32_t classmark;
+ union {
+ uint32_t classmark;
+ struct {
+ uint8_t cm2_len;
+ struct gsm48_classmark2 classmark2;
+ };
+ };
uint8_t mi_len;
uint8_t mi[0];
#endif
@@ -1104,7 +891,7 @@ struct gsm48_system_information_type_4 {
struct gsm48_system_information_type_5 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
+ skip_indicator:4;
uint8_t system_information;
uint8_t bcch_frequency_list[16];
#elif OSMO_IS_BIG_ENDIAN
@@ -1149,7 +936,7 @@ struct gsm48_system_information_type_5ter {
struct gsm48_system_information_type_6 {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t rr_protocol_discriminator :4,
- skip_indicator:4;
+ skip_indicator:4;
uint8_t system_information;
uint16_t cell_identity;
struct gsm48_loc_area_id lai;
diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h
index 9806e083..1390f0e8 100644
--- a/include/osmocom/gsm/protocol/gsm_08_08.h
+++ b/include/osmocom/gsm/protocol/gsm_08_08.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/endian.h>
/*
* this is from GSM 03.03 CGI but is copied in GSM 08.08
@@ -41,10 +42,30 @@ struct bssmap_header {
struct dtap_header {
uint8_t type;
- uint8_t link_id;
+ union {
+ uint8_t link_id; /* Backward compatibility */
+ struct {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t dlci_cc:2,
+ dlci_spare:3,
+ dlci_sapi:3; /* enum gsm0406_dlc_sapi */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+ uint8_t dlci_sapi:3, dlci_spare:3, dlci_cc:2;
+#endif
+ };
+ };
uint8_t length;
} __attribute__((packed));
+/* Data Link Control SAPI, GSM 08.06 § 6.3.2, GSM 04.06 § 3.3.3 */
+enum gsm0406_dlci_sapi {
+ DLCI_SAPI_RR_MM_CC = 0x0,
+ DLCI_SAPI_SMS = 0x3,
+};
+extern const struct value_string gsm0406_dlci_sapi_names[];
+static inline const char *gsm0406_dlci_sapi_name(enum gsm0406_dlci_sapi val)
+{ return get_value_string(gsm0406_dlci_sapi_names, val); }
enum BSS_MAP_MSG_TYPE {
BSS_MAP_MSG_RESERVED_0 = 0,
@@ -512,13 +533,15 @@ enum gsm0808_paging_info {
GSM0808_PAGINF_FOR_USSD = 0x02,
};
-/* 3GPP TS 48.008 3.2.2.104 Speech Codec */
+/*! 3GPP TS 48.008 3.2.2.104 Speech Codec */
struct gsm0808_speech_codec {
bool fi;
bool pi;
bool pt;
bool tf;
+ /*! See enum gsm0808_speech_codec_type. */
uint8_t type;
+ /*! For examples, see enum gsm0808_speech_codec_defaults. */
uint16_t cfg;
};
@@ -640,3 +663,16 @@ enum gsm0808_lcls_status {
GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04,
GSM0808_LCLS_STS_NA = 0xFF
};
+
+/* 3GPP TS 48.008 3.2.2.32 Diagnostics */
+struct gsm0808_diagnostics {
+ uint8_t error_pointer_octet;
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t error_pointer_bit_spare:4,
+ error_pointer_bit:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+ uint8_t error_pointer_bit:4, error_pointer_bit_spare:4;
+#endif
+ uint8_t msg[0]; /*! received message which provoked the error */
+} __attribute__((packed));
diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h
index 1d4530d1..cd13a7dc 100644
--- a/include/osmocom/gsm/protocol/gsm_08_58.h
+++ b/include/osmocom/gsm/protocol/gsm_08_58.h
@@ -236,6 +236,8 @@ enum abis_rsl_msgtype {
RSL_MT_IPAC_DLCX = 0x77,
RSL_MT_IPAC_DLCX_ACK,
RSL_MT_IPAC_DLCX_NACK,
+
+ RSL_MT_OSMO_ETWS_CMD = 0x7f,
};
/*! Siemens vendor-specific RSL message types */
@@ -540,6 +542,9 @@ struct rsl_ie_chan_ident {
#define RSL_ERR_CCCH_OVERLOAD 0x23
#define RSL_ERR_ACCH_OVERLOAD 0x24
#define RSL_ERR_PROCESSOR_OVERLOAD 0x25
+#define RSL_ERR_BTS_NOT_EQUIPPED 0x27
+#define RSL_ERR_REMOTE_TRANSC_FAIL 0x28
+#define RSL_ERR_NOTIFICATION_OVERFL 0x29
#define RSL_ERR_RES_UNAVAIL 0x2f
/* service or option not available */
#define RSL_ERR_TRANSC_UNAVAIL 0x30
diff --git a/include/osmocom/gsm/protocol/gsm_12_21.h b/include/osmocom/gsm/protocol/gsm_12_21.h
index 86d12ea7..34622b33 100644
--- a/include/osmocom/gsm/protocol/gsm_12_21.h
+++ b/include/osmocom/gsm/protocol/gsm_12_21.h
@@ -511,6 +511,7 @@ enum abis_nm_attr {
/* osmocom (osmo-bts) specific attributes, used in combination
* with the "org.osmocom" manufacturer identification */
+ NM_ATT_OSMO_NS_LINK_CFG = 0xfd, /* osmocom version supports IPv4 & IPv6 in difference to IPACC */
NM_ATT_OSMO_REDUCEPOWER = 0xfe, /* TLV_TYPE_TV */
};
#define NM_ATT_BS11_FILE_DATA NM_ATT_EVENT_TYPE
@@ -788,6 +789,13 @@ enum ipac_bcch_info_type {
IPAC_BINF_CELL_ALLOC = (1 << 2),
};
+/*! Osmocom NSVC address type for NM_ATT_OSMO_NS_LINK_CFG */
+enum osmo_oml_nsvc_address_type {
+ OSMO_NSVC_ADDR_UNSPEC = 0x00,
+ OSMO_NSVC_ADDR_IPV4 = 0x04,
+ OSMO_NSVC_ADDR_IPV6 = 0x29,
+};
+
/*! 3GPP TS 52.021 §9.4.62 SW Description */
struct abis_nm_sw_desc {
uint8_t file_id[UINT8_MAX];
diff --git a/include/osmocom/gsm/protocol/gsm_23_032.h b/include/osmocom/gsm/protocol/gsm_23_032.h
new file mode 100644
index 00000000..5be98a29
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_23_032.h
@@ -0,0 +1,172 @@
+/*! \defgroup gad 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ * @{
+ * \file gsm_23_032.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * 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 <osmocom/core/endian.h>
+
+enum gad_type {
+ /*! Ellipsoid point */
+ GAD_TYPE_ELL_POINT = 0,
+ /*! Ellipsoid point with uncertainty circle. */
+ GAD_TYPE_ELL_POINT_UNC_CIRCLE = 1,
+ /*! Ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_ELL_POINT_UNC_ELLIPSE = 3,
+ GAD_TYPE_POLYGON = 5,
+ /*! Ellipsoid point with altitude. */
+ GAD_TYPE_ELL_POINT_ALT = 8,
+ /*! Ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_ELL_POINT_ALT_UNC_ELL = 9,
+ /*! Ellipsoid arc */
+ GAD_TYPE_ELL_ARC = 10,
+ /*! High accuracy ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE = 11,
+ /*! High accuracy ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL = 12,
+};
+
+struct gad_raw_head {
+ uint8_t spare:4,
+ type:4;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_circle {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_CIRCLE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_ellipse {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare3:1;
+} __attribute__ ((packed));
+
+struct gad_raw_polygon {
+ struct {
+ uint8_t num_points:4;
+ uint8_t type:4; /*!< type = GAD_TYPE_POLYGON */
+ } h;
+ struct {
+ uint8_t lat[3];
+ uint8_t lon[3];
+ } point[15];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t unc_alt:7,
+ spare3:1;
+ uint8_t confidence:7,
+ spare4:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_arc {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_ARC */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t inner_r[2];
+ uint8_t unc_r:7,
+ spare1:1;
+ uint8_t ofs_angle;
+ uint8_t incl_angle;
+ uint8_t confidence:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare1:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_alt_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t h_confidence:7,
+ spare1:1;
+ uint8_t unc_alt;
+ uint8_t v_confidence:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+/*! GAD PDU in network-byte-order according to 3GPP TS 23.032 GAD: Universal Geographical Area Description. */
+union gad_raw {
+ struct gad_raw_head h;
+ struct gad_raw_ell_point ell_point;
+ struct gad_raw_ell_point_unc_circle ell_point_unc_circle;
+ struct gad_raw_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct gad_raw_polygon polygon;
+ struct gad_raw_ell_point_alt ell_point_alt;
+ struct gad_raw_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct gad_raw_ell_arc ell_arc;
+ struct gad_raw_ha_ell_point_unc_ell ha_ell_point_unc_ell;
+ struct gad_raw_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+} __attribute__ ((packed));
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_23_041.h b/include/osmocom/gsm/protocol/gsm_23_041.h
index c75c0883..e726cff2 100644
--- a/include/osmocom/gsm/protocol/gsm_23_041.h
+++ b/include/osmocom/gsm/protocol/gsm_23_041.h
@@ -1,5 +1,7 @@
#pragma once
+#include <osmocom/core/endian.h>
+
/* Section 9.4.1.2: GSM Message Format */
struct gsm23041_msg_param_gsm {
uint16_t serial_nr;
@@ -9,9 +11,9 @@ struct gsm23041_msg_param_gsm {
#if OSMO_IS_LITTLE_ENDIAN
uint8_t num_pages:4,
page_nr:4;
-#else
- uint8_t page_nr:4,
- num_pages:4;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+ uint8_t page_nr:4, num_pages:4;
#endif
} page_param;
uint8_t content[0];
diff --git a/include/osmocom/gsm/protocol/gsm_29_118.h b/include/osmocom/gsm/protocol/gsm_29_118.h
index 9adb90f5..15835888 100644
--- a/include/osmocom/gsm/protocol/gsm_29_118.h
+++ b/include/osmocom/gsm/protocol/gsm_29_118.h
@@ -181,4 +181,4 @@ static inline const char *sgsap_ue_emm_mode_name(enum sgsap_ue_emm_mode mode) {
* See also: RFC1123 Section 2.1 Host Names and Numbers */
#define SGS_VLR_NAME_MAXLEN 255
-const struct tlv_definition sgsap_ie_tlvdef;
+extern const struct tlv_definition sgsap_ie_tlvdef;
diff --git a/include/osmocom/gsm/protocol/gsm_48_071.h b/include/osmocom/gsm/protocol/gsm_48_071.h
new file mode 100644
index 00000000..fb9653ab
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_48_071.h
@@ -0,0 +1,122 @@
+/*! \defgroup bsslap 3GPP TS 48.071 BSS LCS Assistance Protocol (BSSLAP).
+ * @{
+ * \file gsm_48_071.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+enum bsslap_msgt {
+ BSSLAP_MSGT_TA_REQUEST = 0x1,
+ BSSLAP_MSGT_TA_RESPONSE = 0x2,
+ BSSLAP_MSGT_REJECT = 0xa,
+ BSSLAP_MSGT_RESET = 0xb,
+ BSSLAP_MSGT_ABORT = 0xc,
+ BSSLAP_MSGT_TA_LAYER3 = 0xd,
+ BSSLAP_MSGT_MS_POS_CMD = 0xf,
+ BSSLAP_MSGT_MS_POS_RESP = 0x10,
+ BSSLAP_MSGT_UTDOA_REQ = 0x11,
+ BSSLAP_MSGT_UTDOA_RESP = 0x12,
+};
+
+enum bsslap_cause {
+ BSSLAP_CAUSE_CONGESTION = 0x0,
+ BSSLAP_CAUSE_CHAN_MODE_NOT_SUPP = 0x1,
+ BSSLAP_CAUSE_POS_PROC_NOT_SUPP = 0x2,
+ BSSLAP_CAUSE_OTHER_RADIO_EVT_FAIL = 0x3,
+ BSSLAP_CAUSE_INTRA_BSS_HO = 0x4,
+ BSSLAP_CAUSE_SUPERV_TIMER_EXPIRED = 0x5,
+ BSSLAP_CAUSE_INTER_BSS_HO = 0x6,
+ BSSLAP_CAUSE_LOSS_SIG_CONN_MS = 0x7,
+ BSSLAP_CAUSE_INCORR_SERV_CELL_ID = 0x8,
+ BSSLAP_CAUSE_BSSAP_LE_SEGMENT_ERR = 0x9,
+ BSSLAP_CAUSE_CONCUR_POS_PROC_NOT_EN = 0xa,
+};
+
+enum bsslap_iei {
+ BSSLAP_IEI_TA = 0x1,
+ BSSLAP_IEI_CELL_ID = 0x9,
+ BSSLAP_IEI_CHAN_DESC = 0x10,
+ BSSLAP_IEI_MEAS_REP = 0x14,
+ BSSLAP_IEI_CAUSE = 0x18,
+ BSSLAP_IEI_RRLP_FLAG = 0x19,
+ BSSLAP_IEI_RRLP = 0x1b,
+ BSSLAP_IEI_CELL_ID_LIST = 0x1c,
+ BSSLAP_IEI_ENH_MEAS_REP = 0x1d,
+ BSSLAP_IEI_LAC = 0x1e,
+ BSSLAP_IEI_FREQ_LIST = 0x21,
+ BSSLAP_IEI_MS_POWER = 0x22,
+ BSSLAP_IEI_DELTA_TIMER = 0x23,
+ BSSLAP_IEI_SERVING_CELL_ID = 0x24,
+ BSSLAP_IEI_ENCR_KEY = 0x25,
+ BSSLAP_IEI_CIPH_MODE_SET = 0x26,
+ BSSLAP_IEI_CHAN_MODE = 0x27,
+ BSSLAP_IEI_MR_CONFIG = 0x28,
+ BSSLAP_IEI_POLLING_REPETITION = 0x29,
+ BSSLAP_IEI_PACKET_CHAN_DESC = 0x2a,
+ BSSLAP_IEI_TLLI = 0x2b,
+ BSSLAP_IEI_TFI = 0x2c,
+ BSSLAP_IEI_TBF_START_TIME = 0x2d,
+ BSSLAP_IEI_PWRUP_START_TIME = 0x2e,
+ BSSLAP_IEI_LONG_ENCR_KEY = 0x2f,
+ BSSLAP_IEI_CONCUR_POS_PROC_F = 0x30,
+};
+
+struct bsslap_ta_response {
+ uint16_t cell_id;
+ uint8_t ta;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_ta_layer3 {
+ uint8_t ta;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_reset {
+ uint16_t cell_id;
+ uint8_t ta;
+ struct gsm48_chan_desc chan_desc;
+ enum bsslap_cause cause;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bsslap_pdu {
+ enum bsslap_msgt msg_type;
+ union {
+ /* ta_request: a TA Request message consists only of the message type. */
+ struct bsslap_ta_response ta_response;
+ enum bsslap_cause reject;
+ struct bsslap_reset reset;
+ enum bsslap_cause abort;
+ struct bsslap_ta_layer3 ta_layer3;
+ };
+};
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_49_031.h b/include/osmocom/gsm/protocol/gsm_49_031.h
new file mode 100644
index 00000000..c6152e17
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_49_031.h
@@ -0,0 +1,212 @@
+/*! \defgroup bssmap_le 3GPP TS 49.031 BSSMAP-LE.
+ * @{
+ * \file gsm_49_031.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <osmocom/gsm/protocol/gsm_48_071.h>
+#include <osmocom/gsm/protocol/gsm_23_032.h>
+#include <osmocom/gsm/gsm0808_utils.h>
+#include <osmocom/gsm/gsm48.h>
+
+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */
+enum lcs_cause {
+ LCS_CAUSE_UNSPECIFIED = 0,
+ LCS_CAUSE_SYSTEM_FAILURE = 1,
+ LCS_CAUSE_PROTOCOL_ERROR = 2,
+ LCS_CAUSE_DATA_MISSING_IN_REQ = 3,
+ LCS_CAUSE_UNEXP_DATA_IN_REQ = 4,
+ LCS_CAUSE_POS_METH_FAILURE = 5,
+ LCS_CAUSE_TGT_MS_UNREACHABLE = 6,
+ LCS_CAUSE_REQUEST_ABORTED = 7,
+ LCS_CAUSE_FACILITY_NOTSUPP = 8,
+ LCS_CAUSE_INTER_BSC_HO = 9,
+ LCS_CAUSE_INTRA_BSC_HO = 10,
+ LCS_CAUSE_CONGESTION = 11,
+ LCS_CAUSE_INTER_NSE_CHG = 12,
+ LCS_CAUSE_RA_UPDAT = 13,
+ LCS_CAUSE_PTMSI_REALLOC = 14,
+ LCS_CAUSE_GPRS_SUSPENSION = 15,
+};
+
+/*! 3GPP TS 49.031 10.13 LCS Cause, also in 3GPP TS 48.008 3.2.2.66, which simply refers to the former. */
+struct lcs_cause_ie {
+ bool present;
+ enum lcs_cause cause_val;
+ bool diag_val_present;
+ uint8_t diag_val;
+};
+
+enum bssap_le_msg_discr {
+ BSSAP_LE_MSG_DISCR_BSSMAP_LE = 0,
+};
+
+enum bssmap_le_msgt {
+ BSSMAP_LE_MSGT_PERFORM_LOC_REQ = 0x2b,
+ BSSMAP_LE_MSGT_PERFORM_LOC_RESP = 0x2d,
+ BSSMAP_LE_MSGT_PERFORM_LOC_ABORT = 0x2e,
+ BSSMAP_LE_MSGT_PERFORM_LOC_INFO = 0x2f,
+ BSSMAP_LE_MSGT_ASSIST_INFO_REQ = 0x20,
+ BSSMAP_LE_MSGT_ASSIST_INFO_RESP = 0x21,
+ BSSMAP_LE_MSGT_CONN_ORIENTED_INFO = 0x2a,
+ BSSMAP_LE_MSGT_CONN_LESS_INFO = 0x3a,
+ BSSMAP_LE_MSGT_RESET = 0x30,
+ BSSMAP_LE_MSGT_RESET_ACK = 0x31,
+};
+
+enum bssmap_le_iei {
+ BSSMAP_LE_IEI_LCS_QoS = 0x3e,
+ BSSMAP_LE_IEI_LCS_PRIORITY = 0x43,
+ BSSMAP_LE_IEI_LOCATION_TYPE = 0x44,
+ BSSMAP_LE_IEI_GANSS_LOCATION_TYPE = 0x82,
+ BSSMAP_LE_IEI_GEO_LOCATION = 0x45,
+ BSSMAP_LE_IEI_POSITIONING_DATA = 0x46,
+ BSSMAP_LE_IEI_GANSS_POS_DATA = 0x83,
+ BSSMAP_LE_IEI_VELOCITY_DATA = 0x55,
+ BSSMAP_LE_IEI_LCS_CAUSE = 0x47,
+ BSSMAP_LE_IEI_LCS_CLIENT_TYPE = 0x48,
+ BSSMAP_LE_IEI_APDU = 0x49,
+ BSSMAP_LE_IEI_NET_ELEM_ID = 0x4a,
+ BSSMAP_LE_IEI_REQ_GPS_ASS_D = 0x4b,
+ BSSMAP_LE_IEI_REQ_GANSS_ASS_D = 0x41,
+ BSSMAP_LE_IEI_DECIPH_KEYS = 0x4c,
+ BSSMAP_LE_IEI_RET_ERR_REQ = 0x4d,
+ BSSMAP_LE_IEI_RET_ERR_CAUSE = 0x4e,
+ BSSMAP_LE_IEI_SEGMENTATION = 0x4f,
+ BSSMAP_LE_IEI_CLASSMARK3_INFO = 0x13,
+ BSSMAP_LE_IEI_CAUSE = 0x4,
+ BSSMAP_LE_IEI_CELL_ID = 0x5,
+ BSSMAP_LE_IEI_CHOSEN_CHAN = 0x21,
+ BSSMAP_LE_IEI_IMSI = 0x0,
+ BSSMAP_LE_IEI_LCS_CAPABILITY = 0x50,
+ BSSMAP_LE_IEI_PKT_MEAS_REP = 0x51,
+ BSSMAP_LE_IEI_CELL_ID_LIST = 0x52,
+ BSSMAP_LE_IEI_IMEI = 0x80,
+ BSSMAP_LE_IEI_BSS_MLAT_CAP = 0x84,
+ BSSMAP_LE_IEI_CELL_INFO_LIST = 0x85,
+ BSSMAP_LE_IEI_BTS_RX_ACC_LVL = 0x86,
+ BSSMAP_LE_IEI_MLAT_METHOD = 0x87,
+ BSSMAP_LE_IEI_MLAT_TA = 0x88,
+ BSSMAP_LE_IEI_MS_SYNC_ACC = 0x89,
+ BSSMAP_LE_IEI_SHORT_ID_SET = 0x8a,
+ BSSMAP_LE_IEI_RANDOM_ID_SET = 0x8b,
+ BSSMAP_LE_IEI_SHORT_BSS_ID = 0x8c,
+ BSSMAP_LE_IEI_RANDOM_ID = 0x8d,
+ BSSMAP_LE_IEI_SHORT_ID = 0x8e,
+ BSSMAP_LE_IEI_COVERAGE_CLASS = 0x8f,
+ BSSMAP_LE_IEI_MTA_ACC_SEC_RQD = 0x90,
+};
+
+enum bssmap_le_apdu_proto {
+ BSSMAP_LE_APDU_PROT_RESERVED = 0,
+ BSSMAP_LE_APDU_PROT_BSSLAP = 1,
+ BSSMAP_LE_APDU_PROT_LLP = 2,
+ BSSMAP_LE_APDU_PROT_SMLCPP = 3,
+};
+
+enum bssmap_le_location_information {
+ BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC = 0x0,
+ BSSMAP_LE_LOC_INFO_ASSIST_TARGET_MS = 0x1,
+ BSSMAP_LE_LOC_INFO_BC_DECIPHER_KEYS = 0x2,
+};
+
+enum bssmap_le_positioning_method {
+ BSSMAP_LE_POS_METHOD_OMITTED = 0x0,
+ BSSMAP_LE_POS_METHOD_MOBILE_ASSISTED_E_OTD = 0x1,
+ BSSMAP_LE_POS_METHOD_MOBILE_BASED_E_OTD = 0x2,
+ BSSMAP_LE_POS_METHOD_ASSISTED_GPS = 0x3,
+};
+
+struct bssmap_le_location_type {
+ enum bssmap_le_location_information location_information;
+ enum bssmap_le_positioning_method positioning_method;
+};
+
+enum bssmap_le_lcs_client_type {
+ BSSMAP_LE_LCS_CTYPE_VALUE_ADDED_UNSPECIFIED = 0x0,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_UNSPECIFIED = 0x20,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_BCAST_SERVICE = 0x21,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_OAM = 0x22,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_ANON_STATS = 0x23,
+ BSSMAP_LE_LCS_CTYPE_PLMN_OPER_TGT_MS_SVC = 0x24,
+ BSSMAP_LE_LCS_CTYPE_EMERG_SVC_UNSPECIFIED = 0x30,
+ BSSMAP_LE_LCS_CTYPE_LI_UNSPECIFIED = 0x40,
+};
+
+struct bssmap_le_perform_loc_req {
+ struct bssmap_le_location_type location_type;
+ struct gsm0808_cell_id cell_id;
+
+ bool lcs_client_type_present;
+ enum bssmap_le_lcs_client_type lcs_client_type;
+
+ struct osmo_mobile_identity imsi;
+ struct osmo_mobile_identity imei;
+
+ bool apdu_present;
+ struct bsslap_pdu apdu;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bssmap_le_perform_loc_resp {
+ bool location_estimate_present;
+ union gad_raw location_estimate;
+
+ struct lcs_cause_ie lcs_cause;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bssmap_le_conn_oriented_info {
+ struct bsslap_pdu apdu;
+
+ bool more_items; /*!< always set this to false */
+};
+
+struct bssmap_le_pdu {
+ enum bssmap_le_msgt msg_type;
+ union {
+ enum gsm0808_cause reset;
+ /* reset_ack consists only of the message type */
+ struct bssmap_le_perform_loc_req perform_loc_req;
+ struct bssmap_le_perform_loc_resp perform_loc_resp;
+ struct lcs_cause_ie perform_loc_abort;
+ struct bssmap_le_conn_oriented_info conn_oriented_info;
+ };
+};
+
+struct bssap_le_pdu {
+ enum bssap_le_msg_discr discr;
+ union {
+ struct bssmap_le_pdu bssmap_le;
+ /* future: add DTAP PDU, currently not implemented */
+ };
+};
+
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/ipaccess.h b/include/osmocom/gsm/protocol/ipaccess.h
index 80413d10..4f1d0b16 100644
--- a/include/osmocom/gsm/protocol/ipaccess.h
+++ b/include/osmocom/gsm/protocol/ipaccess.h
@@ -42,26 +42,35 @@ enum ipaccess_proto_ext {
};
enum ipaccess_msgtype {
- IPAC_MSGT_PING = 0x00,
- IPAC_MSGT_PONG = 0x01,
- IPAC_MSGT_ID_GET = 0x04,
- IPAC_MSGT_ID_RESP = 0x05,
- IPAC_MSGT_ID_ACK = 0x06,
+ IPAC_MSGT_PING = 0x00, /* Heartbeet */
+ IPAC_MSGT_PONG = 0x01, /* Heartbeat Ack */
+ IPAC_MSGT_ID_GET = 0x04, /* Identity Request */
+ IPAC_MSGT_ID_RESP = 0x05, /* Identity */
+ IPAC_MSGT_ID_ACK = 0x06, /* Identity Ack */
+ IPAC_MSGT_ID_NACK = 0x07, /* Identity Nack */
+ IPAC_MSGT_PROXY = 0x08, /* Proxy */
+ IPAC_MSGT_PROXY_ACK = 0x09, /* Proxy Ack */
+ IPAC_MSGT_PROXY_NACK = 0x0a, /* Proxy Nack */
+ IPAC_MSGT_SSL_INFO = 0x0b, /* SSL Info */
/* OpenBSC extension */
IPAC_MSGT_SCCP_OLD = 0xff,
};
enum ipaccess_id_tags {
- IPAC_IDTAG_SERNR = 0x00,
- IPAC_IDTAG_UNITNAME = 0x01,
- IPAC_IDTAG_LOCATION1 = 0x02,
- IPAC_IDTAG_LOCATION2 = 0x03,
- IPAC_IDTAG_EQUIPVERS = 0x04,
- IPAC_IDTAG_SWVERSION = 0x05,
- IPAC_IDTAG_IPADDR = 0x06,
- IPAC_IDTAG_MACADDR = 0x07,
- IPAC_IDTAG_UNIT = 0x08,
+ IPAC_IDTAG_SERNR = 0x00, /* Unit Serial Number */
+ IPAC_IDTAG_UNITNAME = 0x01, /* Unit Name */
+ IPAC_IDTAG_LOCATION1 = 0x02, /* Unit Location */
+ IPAC_IDTAG_LOCATION2 = 0x03, /* Unit Type */
+ IPAC_IDTAG_EQUIPVERS = 0x04, /* Hardware Version */
+ IPAC_IDTAG_SWVERSION = 0x05, /* Software Version */
+ IPAC_IDTAG_IPADDR = 0x06, /* IP Address */
+ IPAC_IDTAG_MACADDR = 0x07, /* Ethernet Address */
+ IPAC_IDTAG_UNIT = 0x08, /* Unit ID */
+ IPAC_IDTAG_USERNAME = 0x09, /* User Name */
+ IPAC_IDTAG_PASSWORD = 0x0a, /* Password */
+ IPAC_IDTAG_ACCESS_CLASS = 0x0b, /* Access Class */
+ IPAC_IDTG_APP_PROTO_VER = 0x0c, /* Application Protocol Version */
};
/*
diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h
index bb0e8fc9..254c21bc 100644
--- a/include/osmocom/gsm/tlv.h
+++ b/include/osmocom/gsm/tlv.h
@@ -111,6 +111,14 @@ static inline uint8_t *tlv_put(uint8_t *buf, uint8_t tag, uint8_t len,
return buf + len;
}
+/*! put (append) a TL field (a TLV field but omitting the value part). */
+static inline uint8_t *tl_put(uint8_t *buf, uint8_t tag, uint8_t len)
+{
+ *buf++ = tag;
+ *buf++ = len;
+ return buf;
+}
+
/*! put (append) a TLV16 field */
static inline uint8_t *tlv16_put(uint8_t *buf, uint8_t tag, uint8_t len,
const uint16_t *val)
@@ -132,6 +140,15 @@ static inline uint8_t *tl16v_put(uint8_t *buf, uint8_t tag, uint16_t len,
return buf + len*2;
}
+/*! put (append) a TL16 field. */
+static inline uint8_t *tl16_put(uint8_t *buf, uint8_t tag, uint16_t len)
+{
+ *buf++ = tag;
+ *buf++ = len >> 8;
+ *buf++ = len & 0xff;
+ return buf;
+}
+
/*! put (append) a TL16V field */
static inline uint8_t *t16lv_put(uint8_t *buf, uint16_t tag, uint8_t len,
const uint8_t *val)
@@ -158,6 +175,23 @@ static inline uint8_t *tvlv_put(uint8_t *buf, uint8_t tag, uint16_t len,
return ret;
}
+/*! put (append) a TvL field (a TvLV with variable-size length, where the value part's length is already known, but will
+ * be put() later).
+ * \returns pointer to the value's start position.
+ */
+static inline uint8_t *tvl_put(uint8_t *buf, uint8_t tag, uint16_t len)
+{
+ uint8_t *ret;
+
+ if (len <= TVLV_MAX_ONEBYTE) {
+ ret = tl_put(buf, tag, len);
+ buf[1] |= 0x80;
+ } else
+ ret = tl16_put(buf, tag, len);
+
+ return ret;
+}
+
/*! put (append) a variable-length tag or variable-length length * */
static inline uint8_t *vt_gan_put(uint8_t *buf, uint16_t tag)
{
@@ -215,6 +249,17 @@ static inline uint8_t *msgb_t16lv_put(struct msgb *msg, uint16_t tag, uint8_t le
return t16lv_put(buf, tag, len, val);
}
+/*! put (append) a TvL field to \ref msgb, i.e. a TvLV with variable-size length, where the value's length is already
+ * known, but will be put() later. The value section is not yet reserved, only tag and variable-length are put in the
+ * msgb.
+ * \returns pointer to the value's start position and end of the msgb.
+ */
+static inline uint8_t *msgb_tvl_put(struct msgb *msg, uint8_t tag, uint16_t len)
+{
+ uint8_t *buf = msgb_put(msg, TVLV_GROSS_LEN(len));
+ return tvl_put(buf, tag, len);
+}
+
/*! put (append) a TvLV field to \ref msgb */
static inline uint8_t *msgb_tvlv_put(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h
index 2bc47153..bfd1ac94 100644
--- a/include/osmocom/sim/sim.h
+++ b/include/osmocom/sim/sim.h
@@ -9,6 +9,7 @@
#include <osmocom/core/linuxlist.h>
#define APDU_HDR_LEN 5
+#define MAX_AID_LEN 16 /* Table 13.2 of TS 102 221 */
/*! command-response pairs cases
*
@@ -66,6 +67,8 @@ struct osim_msgb_cb {
#define msgb_apdu_dc(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr))
#define msgb_apdu_de(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr) + msgb_apdu_lc(__x))
+int osim_init(void *ctx);
+
/* FILES */
struct osim_file;
@@ -135,6 +138,7 @@ enum osim_file_type {
TYPE_ADF, /*!< Application Dedicated File */
TYPE_EF, /*!< Entry File */
TYPE_EF_INT, /*!< Internal Entry File */
+ TYPE_MF, /*!< Master File */
};
enum osim_ef_type {
@@ -242,6 +246,9 @@ struct osim_file_desc *
osim_file_desc_find_name(struct osim_file_desc *parent, const char *name);
struct osim_file_desc *
+osim_file_desc_find_aid(struct osim_file_desc *parent, const uint8_t *aid, uint8_t aid_len);
+
+struct osim_file_desc *
osim_file_desc_find_fid(struct osim_file_desc *parent, uint16_t fid);
struct osim_file_desc *
@@ -281,6 +288,29 @@ struct osim_card_sw {
.class = SW_CLS_NONE, .u.str = NULL \
}
+/*! A card application (e.g. USIM, ISIM, HPSIM) */
+struct osim_card_app_profile {
+ /*! entry in the global list of card application profiles */
+ struct llist_head list;
+ /*! human-readable name */
+ const char *name;
+ /*! AID of this application, as used in EF.DIR */
+ uint8_t aid[MAX_AID_LEN];
+ uint8_t aid_len;
+ /*! file system description */
+ struct osim_file_desc *adf;
+ /*! Status words defined by application */
+ const struct osim_card_sw *sw;
+};
+
+const struct osim_card_app_profile *
+osim_app_profile_find_by_name(const char *name);
+
+const struct osim_card_app_profile *
+osim_app_profile_find_by_aid(const uint8_t *aid, uint8_t aid_len);
+
+const struct osim_card_sw *osim_app_profile_find_sw(const struct osim_card_app_profile *ap, uint16_t sw_in);
+
/*! A card profile (e.g. SIM card */
struct osim_card_profile {
const char *name;
@@ -290,15 +320,13 @@ struct osim_card_profile {
const struct osim_card_sw **sws;
};
-const struct osim_card_sw *osim_find_sw(const struct osim_card_profile *cp,
- uint16_t sw);
-enum osim_card_sw_class osim_sw_class(const struct osim_card_profile *cp,
- uint16_t sw_in);
+const struct osim_card_sw *osim_cprof_find_sw(const struct osim_card_profile *cp, uint16_t sw_in);
-struct osim_card_hdl;
-char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_card_hdl *ch, uint16_t sw_in);
-char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in);
-char *osim_print_sw_c(const void *ctx, const struct osim_card_hdl *ch, uint16_t sw_in);
+struct osim_chan_hdl;
+enum osim_card_sw_class osim_sw_class(const struct osim_chan_hdl *ch, uint16_t sw_in);
+char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_chan_hdl *ch, uint16_t sw_in);
+char *osim_print_sw(const struct osim_chan_hdl *ch, uint16_t sw_in);
+char *osim_print_sw_c(const void *ctx, const struct osim_chan_hdl *ch, uint16_t sw_in);
extern const struct tlv_definition ts102221_fcp_tlv_def;
extern const struct value_string ts102221_fcp_vals[14];
@@ -353,6 +381,19 @@ struct osim_reader_hdl {
struct osim_card_hdl *card;
};
+/*! descriptor for a given application present on a card */
+struct osim_card_app_hdl {
+ /*! member in card list of applications */
+ struct llist_head list;
+ /*! AID of the application */
+ uint8_t aid[MAX_AID_LEN];
+ uint8_t aid_len;
+ /*! application label from EF_DIR */
+ char *label;
+ /*! application profile (if any known) */
+ const struct osim_card_app_profile *prof;
+};
+
struct osim_card_hdl {
/*! member in global list of cards */
struct llist_head list;
@@ -365,6 +406,9 @@ struct osim_card_hdl {
/*! list of channels for this card */
struct llist_head channels;
+
+ /*! list of applications found on card */
+ struct llist_head apps;
};
struct osim_chan_hdl {
@@ -372,9 +416,15 @@ struct osim_chan_hdl {
struct llist_head list;
/*! card to which this channel belongs */
struct osim_card_hdl *card;
+ /*! current working directory */
const struct osim_file_desc *cwd;
+ /*! currently selected application (if any) */
+ struct osim_card_app_hdl *cur_app;
};
+int osim_card_hdl_add_app(struct osim_card_hdl *ch, const uint8_t *aid, uint8_t aid_len,
+ const char *label);
+
/* reader.c */
int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg);
struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver drv, int idx,
diff --git a/include/osmocom/usb/libusb.h b/include/osmocom/usb/libusb.h
new file mode 100644
index 00000000..9ad3f71a
--- /dev/null
+++ b/include/osmocom/usb/libusb.h
@@ -0,0 +1,119 @@
+#pragma once
+/* libusb utilities
+ *
+ * (C) 2010-2019 by Harald Welte <hwelte@hmw-consulting.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <libusb.h>
+
+#define USB_MAX_PATH_LEN 20
+
+struct dev_id {
+ uint16_t vendor_id;
+ uint16_t product_id;
+};
+
+/* structure describing a single matching interface found */
+struct usb_interface_match {
+ /* libusb device E*/
+ libusb_device *usb_dev;
+ /* Vendor ID of the device running matching interface */
+ uint16_t vendor;
+ /* Product ID of the device running matching interface */
+ uint16_t product;
+ /* USB Bus Address */
+ uint8_t addr;
+ /* physical path */
+ char path[USB_MAX_PATH_LEN];
+ /* configuration of matching interface */
+ uint8_t configuration;
+ /* interface number of matching interface */
+ uint8_t interface;
+ /* altsetting of matching interface */
+ uint8_t altsetting;
+ /* bInterfaceClass of matching interface */
+ uint8_t class;
+ /* bInterfaceSubClass of matching interface */
+ uint8_t sub_class;
+ /* bInterfaceProtocol of matching interface */
+ uint8_t protocol;
+ /* index of string descriptor of matching interface */
+ uint8_t string_idx;
+};
+
+/*! Description of the USB device+interface we're looking for */
+struct osmo_usb_matchspec {
+ /*! specify the USB device */
+ struct {
+ int vendor_id; /*!< typically -1 for compile time defaults */
+ int product_id; /*!< typically -1 for compile time defaults */
+ char *path; /*!< used for disambiguation when multiple matches; can be NULL */
+ } dev;
+
+ /*! specify the USB configuration */
+ int config_id; /*!< typically -1 unless user selects specific configuration */
+
+ /*! specify the USB interface */
+ struct {
+ /* typically those three are set to application defaults */
+ int class; /*!< -1 or a user-specified class */
+ int subclass; /*!< -1 or a user-specified subclass */
+ int proto; /*!< -1 or a user-specified protocol */
+
+ /* typically those two are -1; but user can override them */
+ int num;
+ int altsetting;
+ } intf;
+};
+
+
+char *osmo_libusb_dev_get_path_buf(char *buf, size_t bufsize, libusb_device *dev);
+char *osmo_libusb_dev_get_path_c(void *ctx, libusb_device *dev);
+
+libusb_device **osmo_libusb_find_matching_usb_devs(void *ctx, struct libusb_context *luctx,
+ const struct dev_id *dev_ids);
+
+libusb_device *osmo_libusb_find_matching_dev_path(struct libusb_context *luctx,
+ const struct dev_id *dev_ids,
+ const char *path);
+
+libusb_device *osmo_libusb_find_matching_dev_serial(struct libusb_context *luctx,
+ const struct dev_id *dev_ids,
+ const char *serial);
+
+int osmo_libusb_dev_find_matching_interfaces(libusb_device *dev, int class, int sub_class,
+ int protocol, struct usb_interface_match *out,
+ unsigned int out_len);
+
+int osmo_libusb_find_matching_interfaces(libusb_context *luctx, const struct dev_id *dev_ids,
+ int class, int sub_class, int protocol,
+ struct usb_interface_match *out, unsigned int out_len);
+
+libusb_device_handle *osmo_libusb_open_claim_interface(void *ctx, libusb_context *luctx,
+ const struct usb_interface_match *ifm);
+
+void osmo_libusb_match_init(struct osmo_usb_matchspec *cfg, int if_class, int if_subclass, int if_proto);
+
+libusb_device_handle *osmo_libusb_find_open_claim(const struct osmo_usb_matchspec *cfg,
+ const struct dev_id *default_dev_ids);
+
+int osmo_libusb_get_ep_addrs(libusb_device_handle *devh, unsigned int if_num,
+ uint8_t *out, uint8_t *in, uint8_t *irq);
+
+
+int osmo_libusb_init(libusb_context **luctx);
+void osmo_libusb_exit(libusb_context *luctx);
diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h
index d63dbdef..b6088482 100644
--- a/include/osmocom/vty/command.h
+++ b/include/osmocom/vty/command.h
@@ -24,10 +24,12 @@
#pragma once
#include <stdio.h>
+#include <stdbool.h>
#include <sys/types.h>
#include "vector.h"
#include <osmocom/core/defs.h>
+#include <osmocom/core/utils.h>
/*! \defgroup command VTY Command
* @{
@@ -97,6 +99,7 @@ enum node_type {
L_CS7_SCCPADDR_NODE, /*!< SS7 SCCP Address */
L_CS7_SCCPADDR_GT_NODE, /*!< SS7 SCCP Global Title */
+ L_CPU_SCHED_NODE, /*!< CPU Sched related options node */
/*
* When adding new nodes to the libosmocore project, these nodes can be
* used to avoid ABI changes for unrelated projects.
@@ -136,6 +139,27 @@ struct cmd_node {
enum {
CMD_ATTR_DEPRECATED = (1 << 0),
CMD_ATTR_HIDDEN = (1 << 1),
+ CMD_ATTR_IMMEDIATE = (1 << 2),
+ CMD_ATTR_NODE_EXIT = (1 << 3),
+ CMD_ATTR_LIB_COMMAND = (1 << 4),
+};
+
+/*! Attributes shared between libraries (up to 32 entries). */
+enum {
+ /* The entries of this enum shall conform the following requirements:
+ * 1. Naming format: 'OSMO_' + <LIBNAME> + '_LIB_ATTR_' + <ATTRNAME>,
+ * where LIBNAME is a short name of the library, e.g. 'ABIS', 'MGCP',
+ * and ATTRNAME is a brief name of the attribute, e.g. RTP_CONN_EST;
+ * for example: 'OSMO_ABIS_LIB_ATTR_RSL_LINK_UP'.
+ * 2. Brevity: shortenings and abbreviations are welcome!
+ * 3. Values are not flags but indexes, unlike CMD_ATTR_*.
+ * 4. Ordering: new entries added before _OSMO_CORE_LIB_ATTR_COUNT. */
+ OSMO_SCCP_LIB_ATTR_RSTRT_ASP,
+ OSMO_ABIS_LIB_ATTR_IPA_NEW_LNK,
+ OSMO_ABIS_LIB_ATTR_LINE_UPD,
+
+ /* Keep this floating entry last, it's needed for count check. */
+ _OSMO_CORE_LIB_ATTR_COUNT
};
/*! Structure of a command element */
@@ -148,7 +172,8 @@ struct cmd_element {
unsigned int cmdsize; /*!< Command index count. */
char *config; /*!< Configuration string */
vector subconfig; /*!< Sub configuration string */
- unsigned char attr; /*!< Command attributes */
+ unsigned char attr; /*!< Command attributes (global) */
+ unsigned int usrattr; /*!< Command attributes (program specific) */
};
/*! Command description structure. */
@@ -199,6 +224,16 @@ struct desc {
.daemon = dnum, \
};
+#define DEFUN_CMD_ELEMENT_ATTR_USRATTR(funcname, cmdname, cmdstr, helpstr, attrs, usrattrs) \
+ static struct cmd_element cmdname = \
+ { \
+ .string = cmdstr, \
+ .func = funcname, \
+ .doc = helpstr, \
+ .attr = attrs, \
+ .usrattr = usrattrs, \
+ };
+
#define DEFUN_CMD_FUNC_DECL(funcname) \
static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
@@ -237,7 +272,23 @@ struct desc {
DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
- DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
+ DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
+
+/*! Macro for defining a VTY node and function with global & program specific attributes.
+ * \param[in] funcname Name of the function implementing the node.
+ * \param[in] cmdname Name of the command node.
+ * \param[in] attr Global attributes (see CMD_ATTR_*).
+ * \param[in] usrattr Program specific attributes.
+ * \param[in] cmdstr String with syntax of node.
+ * \param[in] helpstr String with help message of node.
+ */
+#define DEFUN_ATTR_USRATTR(funcname, cmdname, attr, usrattr, cmdstr, helpstr) \
+ DEFUN_CMD_FUNC_DECL(funcname) \
+ DEFUN_CMD_ELEMENT_ATTR_USRATTR(funcname, cmdname, cmdstr, helpstr, attr, usrattr) \
+ DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUN_USRATTR(funcname, cmdname, usrattr, cmdstr, helpstr) \
+ DEFUN_ATTR_USRATTR(funcname, cmdname, 0, usrattr, cmdstr, helpstr)
/* DEFUN_NOSH for commands that vtysh should ignore */
#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
@@ -304,6 +355,10 @@ struct desc {
#define CMD_IPV6(S) ((strcmp ((S), "X:X::X:X") == 0))
#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
+#define VTY_IPV4_CMD "A.B.C.D"
+#define VTY_IPV6_CMD "X:X::X:X"
+#define VTY_IPV46_CMD "(" VTY_IPV4_CMD "|" VTY_IPV6_CMD ")"
+
/* Common descriptions. */
#define SHOW_STR "Show running system information\n"
#define IP_STR "IP information\n"
@@ -363,7 +418,9 @@ struct desc {
void install_node(struct cmd_node *, int (*)(struct vty *));
void install_default(int node_type) OSMO_DEPRECATED("Now happens implicitly with install_node()");
void install_element(int node_type, struct cmd_element *);
+void install_lib_element(int node_type, struct cmd_element *);
void install_element_ve(struct cmd_element *cmd);
+void install_lib_element_ve(struct cmd_element *cmd);
void sort_node(void);
void vty_install_default(int node_type) OSMO_DEPRECATED("Now happens implicitly with install_node()");
@@ -401,4 +458,18 @@ void print_version(int print_copyright);
extern void *tall_vty_cmd_ctx;
+/*! VTY reference generation mode. */
+enum vty_ref_gen_mode {
+ /*! Default mode: all commands except deprecated and hidden. */
+ VTY_REF_GEN_MODE_DEFAULT = 0,
+ /*! Expert mode: all commands including hidden, excluding deprecated. */
+ VTY_REF_GEN_MODE_EXPERT,
+};
+
+extern const struct value_string vty_ref_gen_mode_names[];
+extern const struct value_string vty_ref_gen_mode_desc[];
+
+int vty_dump_xml_ref_mode(FILE *stream, enum vty_ref_gen_mode mode);
+int vty_dump_xml_ref(FILE *stream) OSMO_DEPRECATED("Use vty_dump_xml_ref_mode() instead");
+
/*! @} */
diff --git a/include/osmocom/vty/cpu_sched_vty.h b/include/osmocom/vty/cpu_sched_vty.h
new file mode 100644
index 00000000..171f1687
--- /dev/null
+++ b/include/osmocom/vty/cpu_sched_vty.h
@@ -0,0 +1,37 @@
+/*! \file cpu_sched_vty.h
+ * API to CPU / Threading / Scheduler properties from VTY configuration.
+ */
+/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#pragma once
+
+#include <osmocom/vty/command.h>
+
+/*! \defgroup cpu_sched_VTY Configuration
+ * @{
+ * \file cpu_sched_vty.h
+ */
+
+void osmo_cpu_sched_vty_init(void *tall_ctx);
+int osmo_cpu_sched_vty_apply_localthread(void);
+
+/*! @} */
diff --git a/include/osmocom/vty/ports.h b/include/osmocom/vty/ports.h
index 201e1157..b3550d15 100644
--- a/include/osmocom/vty/ports.h
+++ b/include/osmocom/vty/ports.h
@@ -34,4 +34,7 @@
#define OSMO_VTY_PORT_HNBGW 4261
/* 4262-4263 used by control interface */
#define OSMO_VTY_PORT_CBC 4264
+#define OSMO_VTY_PORT_UECUPS 4268
+#define OSMO_VTY_PORT_E1D 4269
+#define OSMO_VTY_PORT_SMLC 4271
/* When adding/changing port numbers, keep docs and wiki in sync. See above. */
diff --git a/include/osmocom/vty/tdef_vty.h b/include/osmocom/vty/tdef_vty.h
index 3027913d..800af7d7 100644
--- a/include/osmocom/vty/tdef_vty.h
+++ b/include/osmocom/vty/tdef_vty.h
@@ -25,6 +25,9 @@
#pragma once
#include <stdint.h>
+#include <stdarg.h>
+
+#include <osmocom/vty/command.h>
struct vty;
@@ -65,7 +68,7 @@ void osmo_tdef_vty_out_all_va(struct vty *vty, struct osmo_tdef *tdefs, const ch
struct osmo_tdef *osmo_tdef_vty_parse_T_arg(struct vty *vty, struct osmo_tdef *tdefs, const char *osmo_tdef_str);
unsigned long osmo_tdef_vty_parse_val_arg(const char *val_arg, unsigned long default_val);
-void osmo_tdef_vty_groups_init(enum node_type parent_node, struct osmo_tdef_group *groups);
+void osmo_tdef_vty_groups_init(unsigned int parent_cfg_node, struct osmo_tdef_group *groups);
void osmo_tdef_vty_groups_write(struct vty *vty, const char *indent);
/*! @} */
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h
index 03a29248..d34433fa 100644
--- a/include/osmocom/vty/vty.h
+++ b/include/osmocom/vty/vty.h
@@ -5,6 +5,7 @@
#include <stdbool.h>
#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/defs.h>
/*! \defgroup vty VTY (Virtual TTY) interface
* @{
@@ -27,6 +28,12 @@
#define VTY_BUFSIZ 512
#define VTY_MAXHIST 20
+/* Number of application / library specific VTY attributes */
+#define VTY_CMD_USR_ATTR_NUM 32
+/* Flag characters reserved for global VTY attributes */
+#define VTY_CMD_ATTR_FLAGS_RESERVED \
+ { '.', '!', '@', '^' }
+
/*! VTY events */
enum event {
VTY_SERV,
@@ -158,6 +165,9 @@ struct vty {
/*! When reading from a config file, these are the indenting characters expected for children of
* the current VTY node. */
char *indent;
+
+ /*! Whether the expert mode is enabled. */
+ bool expert_mode;
};
/* Small macro to determine newline is newline only or linefeed needed. */
@@ -178,12 +188,23 @@ struct vty_app_info {
const char *copyright;
/*! \ref talloc context */
void *tall_ctx;
- /*! call-back for returning to parent n ode */
+ /*! Call-back for taking actions upon exiting a node.
+ * The return value is ignored, and changes to vty->node and vty->index made in this callback are ignored.
+ * Implicit parent node tracking always sets the correct parent node and vty->index after this callback exits,
+ * so this callback can handle only those nodes that should take specific actions upon node exit, or can be left
+ * NULL entirely. */
int (*go_parent_cb)(struct vty *vty);
- /*! call-back to determine if node is config node */
- int (*is_config_node)(struct vty *vty, int node);
+ /*! OBSOLETED: Implicit parent node tracking has replaced the use of this callback. This callback is no longer
+ * called, ever, and can be left NULL. */
+ int (*is_config_node)(struct vty *vty, int node)
+ OSMO_DEPRECATED("Implicit parent node tracking has replaced the use of this callback. This callback is"
+ " no longer called, ever, and can be left NULL.");
/*! Check if the config is consistent before write */
int (*config_is_consistent)(struct vty *vty);
+ /*! Description of the application specific VTY attributes (optional). */
+ const char * usr_attr_desc[VTY_CMD_USR_ATTR_NUM];
+ /*! Flag letters of the application specific VTY attributes (optional). */
+ char usr_attr_letters[VTY_CMD_USR_ATTR_NUM];
};
/* Prototypes. */