From d910a3522782dace466a177a4bea35d6327b2b5f Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Tue, 24 Jul 2018 20:01:26 +0200 Subject: stats_vty: Add asciidoc sections between the different counters Change-Id: Ie37be744abd8c47211d64877bcd17f94465bd423 --- src/vty/stats_vty.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vty/stats_vty.c b/src/vty/stats_vty.c index 8d90945a..5ded7a44 100644 --- a/src/vty/stats_vty.c +++ b/src/vty/stats_vty.c @@ -516,12 +516,15 @@ DEFUN(show_stats_asciidoc_table, host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE); /* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table header * as usual text*/ + vty_out(vty, "=== Rate Counters%s%s", VTY_NEWLINE, VTY_NEWLINE); vty_out(vty, "// generating tables for rate_ctr_group%s", VTY_NEWLINE); rate_ctr_for_each_group(asciidoc_rate_ctr_group_handler, vty); + vty_out(vty, "== Osmo Stat Items%s%s", VTY_NEWLINE, VTY_NEWLINE); vty_out(vty, "// generating tables for osmo_stat_items%s", VTY_NEWLINE); osmo_stat_item_for_each_group(asciidoc_osmo_stat_item_group_handler, vty); + vty_out(vty, "== Osmo Counters%s%s", VTY_NEWLINE, VTY_NEWLINE); vty_out(vty, "// generating tables for osmo_counters%s", VTY_NEWLINE); asciidoc_counter_generate(vty); return CMD_SUCCESS; -- cgit v1.2.3 From 9af7076b01126ae07bb931b17ccb62cd9e48e6e6 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 24 Jul 2018 16:37:54 +0200 Subject: stats_statsd: sanitize statsd name The statsd protocol use ':' as seperator between name and value. It's not allowed to use the seperator in a name. Replace ':' with '.' before sending the packet to the statsd server. Change-Id: Ib46d08481e8ca04afd97cb9ae241e4e39c91ad66 --- src/stats_statsd.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/stats_statsd.c b/src/stats_statsd.c index c11c0132..5ae25702 100644 --- a/src/stats_statsd.c +++ b/src/stats_statsd.c @@ -68,6 +68,25 @@ struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name) return srep; } +/*! Replace all illegal ':' in the stats name, but not when used as value seperator. + * ':' is used as seperator between the name and the value in the statsd protocol. + * \param[inout] buf is a null terminated string containing name, value, unit. */ +static void osmo_stats_reporter_sanitize_name(char *buf) +{ + /* e.g. msc.loc_update_type:normal:1|c -> msc.loc_update_type.normal:1|c + * last is the seperator between name and value */ + char *last = strrchr(buf, ':'); + char *tmp = strchr(buf, ':'); + + if (!last) + return; + + while (tmp < last) { + *tmp = '.'; + tmp = strchr(buf, ':'); + } +} + static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep, const char *name1, unsigned int index1, const char *name2, int64_t value, const char *unit) @@ -134,8 +153,10 @@ static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep, return -EMSGSIZE; } - if (nchars > 0) + if (nchars > 0) { + osmo_stats_reporter_sanitize_name(buf); msgb_trim(srep->buffer, msgb_length(srep->buffer) + nchars); + } if (!srep->agg_enabled) rc = osmo_stats_reporter_send_buffer(srep); -- cgit v1.2.3 From 53a1e49354e8d9b15083d129c10d0f65bff08a83 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 24 Jul 2018 16:26:14 +0200 Subject: logging: log_vty_command_string: Fix undercount of buf alloc size Change-Id: I7aca0ce3d2981001e8081f7cee0dea3e2aaf8f7c --- src/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging.c b/src/logging.c index 1dfd4847..381d3034 100644 --- a/src/logging.c +++ b/src/logging.c @@ -932,7 +932,7 @@ const char *log_vty_command_string() { struct log_info *info = osmo_log_info; int len = 0, offset = 0, ret, i, rem; - int size = strlen("logging level () ()") + 1; + int size = strlen("logging level (all|) ()") + 1; char *str; assert_loginfo(__func__); -- cgit v1.2.3 From d51c98e7bfe5ff2322c5c376f70bbba517b73e2b Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 24 Jul 2018 16:03:49 +0200 Subject: logging_vty: Simplify code in config_write_log_single Since we ignore "logging level CAT everything" in logging_level_cmd, we can never run into the case in which we have loglevel==EVERYTHING, so we can simplify this code and make it esier for later removal of everything keyword. Change-Id: I4e76c65a11cc22616c6dfc632435617ebb861c03 --- src/vty/logging_vty.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 8151fda0..11949144 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -814,15 +814,9 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) /* stupid old osmo logging API uses uppercase strings... */ osmo_str2lower(cat_lower, osmo_log_info->cat[i].name+1); osmo_str2lower(level_lower, log_level_str(cat->loglevel)); - - if (strcmp(level_lower, "everything") != 0) /* FIXME: remove this check once 'everything' is phased out */ - vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE); - else - LOGP(DLSTATS, LOGL_ERROR, "logging level everything is deprecated and should not be used\n"); + vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE); } - /* FIXME: levels */ - return 1; } -- cgit v1.2.3 From 9d4a36e0603d8714498790016629030553daaa1e Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 26 Jul 2018 11:55:33 +0200 Subject: logging.c: Fix whitespace typo Change-Id: I943763e175dca6f3078923a494b052319b78574d --- src/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logging.c b/src/logging.c index 381d3034..edb2b56a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -759,7 +759,7 @@ struct log_target *log_target_create(void) if (!target) return NULL; - target->categories = talloc_zero_array(target, + target->categories = talloc_zero_array(target, struct log_category, osmo_log_info->num_cat); if (!target->categories) { -- cgit v1.2.3 From 924ef0bc72c1be165e8d5c22859f8b4eddbc0f06 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 27 Jul 2018 17:31:47 +0200 Subject: =?UTF-8?q?Bump=20version:=200.11.0.91-9d4a3-dirty=20=E2=86=92=200?= =?UTF-8?q?.12.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7e66432f37e13fd4c31389e3d89593fa0981e58f --- TODO-RELEASE | 3 -- debian/changelog | 117 +++++++++++++++++++++++++++++++++++++++++++ debian/control | 14 +++--- debian/libosmocore10.install | 1 - debian/libosmocore11.install | 1 + debian/libosmogsm10.install | 1 + debian/libosmogsm9.install | 1 - src/Makefile.am | 2 +- src/codec/Makefile.am | 2 +- src/coding/Makefile.am | 2 +- src/ctrl/Makefile.am | 2 +- src/gb/Makefile.am | 3 +- src/gsm/Makefile.am | 2 +- src/vty/Makefile.am | 2 +- 14 files changed, 133 insertions(+), 20 deletions(-) delete mode 100644 debian/libosmocore10.install create mode 100644 debian/libosmocore11.install create mode 100644 debian/libosmogsm10.install delete mode 100644 debian/libosmogsm9.install diff --git a/TODO-RELEASE b/TODO-RELEASE index 7b225cc4..8ccfa491 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,6 +7,3 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line -gsup gsup.h the 'osmo_gsup_message' struct extended with - session information => ABI changed - SS/USSD information => ABI changed diff --git a/debian/changelog b/debian/changelog index 393ea17d..606d923c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,120 @@ +libosmocore (0.12.0) unstable; urgency=medium + + [ Pau Espin Pedrol ] + * control_if: Avoid heap-use-after-free in osmo_wqueue_bfd_cb + * configure: Check separately for lib implementing dlopen and dlsym + * tests: bitrev_test: Fix dynamic-stack-buffer-overflow + * tests: gea_test: Use correct max size for key in buffer + * tests: a5_test: Print wrong buffer correctly on error + * gsm: kasumi: Fix dynamic-stack-buffer-overflow on out buffers not multiple of 64 bits + * gsm: lapdm.c: Add missing new line char in notice log string + * ctrl: Log CMD TYPE on invalid ID number + * ctrl: Fix parsing of ERROR recvd msgs with id=err + * gsm0808: Add value_string for encryption algorithms + * ctrl: Introduce ctrl_cmd_parse3 API + * ctrl: ctrl_handle_msg: Avoid sending back received ERROR msgs + * tests: ctrl: Test received ERROR messages are handled correctly + * libosmocoding: clarify return values for TCH decoding functions + * libosmocodec: FR err concealment: Fix too many silent frames generated + * tests: codec: ecu_fr: Print XMAXC fields + * tests: codec: ecu_fr: Add buffer with unequal XMAXC values + * rate_ctr: Improve logging + * logging: log_vty_command_string: Fix undercount of buf alloc size + * logging_vty: Simplify code in config_write_log_single + * logging.c: Fix whitespace typo + + [ Harald Welte ] + * lapdm: Fix back-pointer from lapdm_entity to lapdm_channel + * lapdm: Implement SABM related constraints + * lapdm: cleanup: send_rslms_rll_l3_ui(): Use msgb_tv_push() + * lapdm: send_rslms_rll_l3_ui(): Don't include B4/SACCH IE unless needed + * lapdm: don't enforce contention resolution on SAPI0/DCCH + * Add osmo_timerfd_* functions for osmo_fd-wrapped timerfd + * import isdn4linux HDLC code from linux kernel + * isdnhdlc: Port from kernel to userspace + * mncc: properly export osmo_mncc_name() + * cosmetic: Whitespace fixes in control_if.c + * ctrl: Introduce libosmoctrl.map to avoid unintended exports + * ctrl: Add doxygen API documentation; generate html from it + * debian: Add libosmoctrl-doc sub-package + * gsm_08_08.h: Add enum for LCLS config, control and status + * gsm0808: Add encoding functions for LCLS BSSMAP messages + * gsm0808: Add value_string for LCLS related IEs + * tlv: Add TLVP_VAL_MINLEN() to obtain value _if_ length is >= minimum + * Add osmo_isqrt32() to compute 32bit integer square root + * fsm: Change semantics of LOGPFSML() log-level + * vty: Don't dump deprecated commands in XML export + * vty: Add logging_vty_add_deprecated_subsys + * gsup: Add osmo_gsup_get_err_msg_type() function + * gsup: Add value_string for Session State IE + * gsm 04.80: Add value_string for component type and op code + * Fix embedded (arm-none-eabi) builds + * jenkins_arm.sh: Don't run 'make check' on embedded builds + * jenkins_arch.sh: Accept "arm-none-eabi" as alias for "arm" + * jenkins_arch.sh: Exit with error on unknown architecture + * Don't call abort() directly, always use osmo_panic() + * osmo_panic(): Annotate as __attribute__ ((noreturn)) + * gprs_ns.h: Declare gprs_ns_cause_str() which already existed in c file + + [ Stefan Sperling ] + * define a constant for the max length of called party BCD IE + * introduce vty_out_rate_ctr_group_fmt() function + * Add a 'show rate-counters' VTY command. + * remove unused argument from pad_append_ctr() helper function + * check bssgp_tlv_parse() return code in bssgp_rcvmsg() + * return error to sender upon bssgp_tlv_parse() failure + + [ Neels Hofmeyr ] + * add gsm0808 channel enum to IE val conversion functions + * add gsm0808_cell_id_to_list() + * add support for gsm0808 HANDOVER REQUIRED message + * add gsm0808_create_handover_request_ack() + * add osmo_fsm_inst_state_chg_keep_timer() + * fix gsm0808_permitted_speech(): don't return HR3 for TCH_F + AMR + * add and tweak inter-BSC HO API + * vty/command.c: talloc from tall_vty_cmd_ctx, not NULL + * vty: cosmetic: cmd_deopt(): use talloc_strndup(), not memcpy() + * vty: fix use-after-free and memleaks in is_cmd_ambiguous() + * utils_test: fix isqrt_test calculation range + * utils_test: check stderr to catch sanitizer issues + * add osmo_sockaddr_to_str_and_uint() + + [ Philipp Maier ] + * fsm: guard action callback + * gsm_04_08: add function to get value string + * gsm_08_08: gsm0808_permitted_speech does not have value strings + + [ Thorsten Alteholz ] + * fix spelling + + [ Keith ] + * Add enum gsm48_cause_coding from GSM 04.08 Section 10.5.4.11 + * Add enum gsm48_progress_desc + + [ Daniel Willmann ] + * ports.h: Add ctrl port for osmo-gbproxy + * Add function gprs_nsvc_state_append + * stats_vty: Add asciidoc sections between the different counters + + [ Vadim Yanitskiy ] + * gsm0480: fix: don't overwrite the data of RELEASE_COMPLETE + * GSUP: implement TCAP-like session management + * GSUP: introduce new messages for SS/USSD payloads + * Doxygen: gitignore generated files for libosmoctrl + * gsm/gsm0480.c: introduce gsm0480_extract_ie_by_tag() + * gsm/gsm0480: refactor and expose gsm0480_parse_facility_ie() + * Don't enforce Python 2 for utilities + + [ Alexander Chemeris ] + * coding: Fix (E)GPRS BER calculation to correctly account for puncturing. + * coding: Documentation typo fix. + + [ Alexander Couzens ] + * vty: initialize termios before using it + * stats_statsd: sanitize statsd name + + -- Pau Espin Pedrol Fri, 27 Jul 2018 17:31:46 +0200 + libosmocore (0.11.0) unstable; urgency=medium [ Max ] diff --git a/debian/control b/debian/control index 1de0ceb2..540a8b5e 100644 --- a/debian/control +++ b/debian/control @@ -27,9 +27,9 @@ Architecture: any Multi-Arch: foreign Depends: libosmocodec0 (= ${binary:Version}), libosmocoding0 (= ${binary:Version}), - libosmocore10 (= ${binary:Version}), + libosmocore11 (= ${binary:Version}), libosmogb6 (= ${binary:Version}), - libosmogsm9 (= ${binary:Version}), + libosmogsm10 (= ${binary:Version}), libosmovty4 (= ${binary:Version}), libosmoctrl0 (= ${binary:Version}), libosmosim0 (= ${binary:Version}), @@ -110,7 +110,7 @@ Description: Documentation for the osmo coding library . This package contains the documentation for the libosmocoding library. -Package: libosmocore10 +Package: libosmocore11 Section: libs Architecture: any Multi-Arch: same @@ -124,14 +124,14 @@ Description: Osmo Core library (at least) other programs that are developed in the sphere of Free Software / Open Source mobile communication. . - The libosmocore10 library in particular is a collection of common code used in + The libosmocore11 library in particular is a collection of common code used in various sub-projects inside the Osmocom family of projects. Package: libosmocore-doc Architecture: all Section: doc Depends: ${misc:Depends}, - libosmocore10, + libosmocore11, libjs-jquery, libosmocodec-doc, libosmocoding-doc, @@ -178,7 +178,7 @@ Description: Documentation for the Osmo GPRS Gb library . This package contains the documentation for the libosmogb library. -Package: libosmogsm9 +Package: libosmogsm10 Section: libs Architecture: any Multi-Arch: same @@ -202,7 +202,7 @@ Package: libosmogsm-doc Architecture: all Section: doc Depends: ${misc:Depends}, - libosmogsm9, + libosmogsm10, libjs-jquery Description: Documentation for the Osmo GSM utility library This is part of the libosmocore "meta"-library. The libosmocore library diff --git a/debian/libosmocore10.install b/debian/libosmocore10.install deleted file mode 100644 index b73331b9..00000000 --- a/debian/libosmocore10.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libosmocore*.so.* diff --git a/debian/libosmocore11.install b/debian/libosmocore11.install new file mode 100644 index 00000000..b73331b9 --- /dev/null +++ b/debian/libosmocore11.install @@ -0,0 +1 @@ +usr/lib/*/libosmocore*.so.* diff --git a/debian/libosmogsm10.install b/debian/libosmogsm10.install new file mode 100644 index 00000000..5e617298 --- /dev/null +++ b/debian/libosmogsm10.install @@ -0,0 +1 @@ +usr/lib/*/libosmogsm*.so.* diff --git a/debian/libosmogsm9.install b/debian/libosmogsm9.install deleted file mode 100644 index 5e617298..00000000 --- a/debian/libosmogsm9.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/*/libosmogsm*.so.* diff --git a/src/Makefile.am b/src/Makefile.am index 45fb89df..e9db32fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=10:0:0 +LIBVERSION=11:0:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall $(TALLOC_CFLAGS) diff --git a/src/codec/Makefile.am b/src/codec/Makefile.am index 60fce5e6..b522d43a 100644 --- a/src/codec/Makefile.am +++ b/src/codec/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=1:0:1 +LIBVERSION=1:1:1 AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS) AM_CFLAGS = -Wall diff --git a/src/coding/Makefile.am b/src/coding/Makefile.am index a17e3d14..c001c139 100644 --- a/src/coding/Makefile.am +++ b/src/coding/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read Chapter 6 "Library interface versions" of the libtool # documentation before making any modification -LIBVERSION = 1:0:1 +LIBVERSION = 1:1:1 AM_CPPFLAGS = \ -I"$(top_srcdir)/include" \ diff --git a/src/ctrl/Makefile.am b/src/ctrl/Makefile.am index a51ae053..fe7c47dd 100644 --- a/src/ctrl/Makefile.am +++ b/src/ctrl/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=2:0:2 +LIBVERSION=3:0:3 AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS) diff --git a/src/gb/Makefile.am b/src/gb/Makefile.am index 70a451d2..03052fa8 100644 --- a/src/gb/Makefile.am +++ b/src/gb/Makefile.am @@ -1,6 +1,6 @@ # This is _NOT_ the library release version, it's an API version. # Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification -LIBVERSION=6:0:0 +LIBVERSION=7:0:1 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN} -fno-strict-aliasing $(TALLOC_CFLAGS) @@ -23,4 +23,3 @@ libosmogb_la_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \ endif EXTRA_DIST = libosmogb.map - diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 5387e3ab..900fcfa1 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=9:0:0 +LIBVERSION=10:0:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS) AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN} diff --git a/src/vty/Makefile.am b/src/vty/Makefile.am index 18d3a842..5d0ded7b 100644 --- a/src/vty/Makefile.am +++ b/src/vty/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=4:1:0 +LIBVERSION=5:0:5 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall $(TALLOC_CFLAGS) -- cgit v1.2.3 From 0bc3b8365427fa4310cd68213b51188201f231fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Thu, 26 Jul 2018 11:30:59 +0200 Subject: GSMTAP: add SIM sub_types In SIMtrace 1 the ATR was sent the same way as an APDU. The ATR is not an APDU, and could be mis-interpreted as valid APDU. This change allows to make the difference between actual APDU and the ATR, but also adds sub_types for future SIMtrace 2 use cases. Change-Id: I5bd0dff5a4a90cfe96d9c4f3dec6657e1d85bf7a --- include/osmocom/core/gsmtap.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h index b4239f8c..9f5049f8 100644 --- a/include/osmocom/core/gsmtap.h +++ b/include/osmocom/core/gsmtap.h @@ -33,7 +33,7 @@ #define GSMTAP_TYPE_UM 0x01 #define GSMTAP_TYPE_ABIS 0x02 #define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ -#define GSMTAP_TYPE_SIM 0x04 +#define GSMTAP_TYPE_SIM 0x04 /* ISO 7816 smart card interface */ #define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */ #define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */ #define GSMTAP_TYPE_WMX_BURST 0x07 /* WiMAX burst */ @@ -103,6 +103,18 @@ /* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ +/* sub-types for GSMTAP_TYPE_SIM */ +#define GSMTAP_SIM_APDU 0x00 /* APDU data (complete APDU) */ +#define GSMTAP_SIM_ATR 0x01 /* card ATR data */ +#define GSMTAP_SIM_PPS_REQ 0x02 /* PPS request data */ +#define GSMTAP_SIM_PPS_RSP 0x03 /* PPS response data */ +#define GSMTAP_SIM_TPDU_HDR 0x04 /* TPDU command header */ +#define GSMTAP_SIM_TPDU_CMD 0x05 /* TPDU command body */ +#define GSMTAP_SIM_TPDU_RSP 0x06 /* TPDU response body */ +#define GSMTAP_SIM_TPDU_SW 0x07 /* TPDU response trailer */ + +/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ + /* sub-types for TYPE_TETRA_AIR */ #define GSMTAP_TETRA_BSCH 0x01 #define GSMTAP_TETRA_AACH 0x02 -- cgit v1.2.3 From ebe4ef738351780bc0b011fc514e257f26bfff6a Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 26 Jul 2018 17:12:07 +0200 Subject: fix strncpy bugs in gsm/ipa.c Change-Id: I423a24c55c9b9aa6fc8f501df94fe54c71ee2b2b --- src/gsm/ipa.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c index 0c7aaad6..aecde831 100644 --- a/src/gsm/ipa.c +++ b/src/gsm/ipa.c @@ -251,23 +251,23 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev, break; case IPAC_IDTAG_LOCATION1: if (dev->location1) - strncpy(str, dev->location1, IPA_STRING_MAX); + osmo_strlcpy(str, dev->location1, sizeof(str)); break; case IPAC_IDTAG_LOCATION2: if (dev->location2) - strncpy(str, dev->location2, IPA_STRING_MAX); + osmo_strlcpy(str, dev->location2, sizeof(str)); break; case IPAC_IDTAG_EQUIPVERS: if (dev->equipvers) - strncpy(str, dev->equipvers, IPA_STRING_MAX); + osmo_strlcpy(str, dev->equipvers, sizeof(str)); break; case IPAC_IDTAG_SWVERSION: if (dev->swversion) - strncpy(str, dev->swversion, IPA_STRING_MAX); + osmo_strlcpy(str, dev->swversion, sizeof(str)); break; case IPAC_IDTAG_UNITNAME: if (dev->unit_name) { - snprintf(str, sizeof(str), dev->unit_name, IPA_STRING_MAX); + snprintf(str, sizeof(str), "%s", dev->unit_name); } else { snprintf(str, sizeof(str), "%02x-%02x-%02x-%02x-%02x-%02x", @@ -278,7 +278,7 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev, break; case IPAC_IDTAG_SERNR: if (dev->serno) - strncpy(str, dev->serno, IPA_STRING_MAX); + osmo_strlcpy(str, dev->serno, sizeof(str)); break; default: LOGP(DLINP, LOGL_NOTICE, @@ -286,7 +286,6 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev, msgb_free(msg); return NULL; } - str[IPA_STRING_MAX-1] = '\0'; LOGP(DLINP, LOGL_INFO, " tag %d: %s\n", ies_req[i], str); tag = msgb_put(msg, 3 + strlen(str) + 1); -- cgit v1.2.3 From 1cea7b5a97a0069eb409bf86e4a67913b687c3bd Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 26 Jul 2018 17:13:50 +0200 Subject: fix strncpy bugs in socket.c Change-Id: Iddf36d26b23dcef4f9b291fd7ead1907e38c3486 --- src/socket.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/socket.c b/src/socket.c index 04058474..dc5590c0 100644 --- a/src/socket.c +++ b/src/socket.c @@ -596,8 +596,7 @@ int osmo_sock_unix_init(uint16_t type, uint8_t proto, return -EINVAL; local.sun_family = AF_UNIX; - strncpy(local.sun_path, socket_path, sizeof(local.sun_path)); - local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + osmo_strlcpy(local.sun_path, socket_path, sizeof(local.sun_path)); #if defined(BSD44SOCKETS) || defined(__UNIXWARE__) local.sun_len = strlen(local.sun_path); -- cgit v1.2.3 From 95fdbc14ffaff5f5dd8fffadc4264f41fc621085 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 26 Jul 2018 17:14:40 +0200 Subject: cosmetic: osmo-sim-test.c: use memcpy instead of strncpy gcc 8.1.0 complains that the terminating \0 is not copied by strncpy, while this code intends to do exactly that. Use memcpy instead. Change-Id: I8d66fa22502c04d11ae153b9856d7e54f3492dd6 --- utils/osmo-sim-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/utils/osmo-sim-test.c b/utils/osmo-sim-test.c index ea241206..5588294a 100644 --- a/utils/osmo-sim-test.c +++ b/utils/osmo-sim-test.c @@ -74,7 +74,8 @@ static int verify_pin(struct osim_chan_hdl *st, uint8_t pin_nr, char *pin) msg = osim_new_apdumsg(0x00, 0x20, 0x00, pin_nr, 8, 0); pindst = (char *) msgb_put(msg, 8); memset(pindst, 0xFF, 8); - strncpy(pindst, pin, strlen(pin)); + /* Do not copy the terminating \0 */ + memcpy(pindst, pin, strlen(pin)); return osim_transceive_apdu(st, msg); } -- cgit v1.2.3 From 49865053bc47c00ea50b6cee2eeecf61c2dd2fdb Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 17 Jul 2018 18:35:05 +0200 Subject: ctrl/vty: fsm: use correct element when iterating over fsm->proc.children Fixes crashes when using vty `show fsm-instances all` when fsm children are present. Change-Id: I4ae0bee7f7f57ec6675cfb52ca6cf0d523d15362 --- src/ctrl/fsm_ctrl_commands.c | 2 +- src/vty/fsm_vty.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ctrl/fsm_ctrl_commands.c b/src/ctrl/fsm_ctrl_commands.c index 3c7e1bd0..c93d3a52 100644 --- a/src/ctrl/fsm_ctrl_commands.c +++ b/src/ctrl/fsm_ctrl_commands.c @@ -156,7 +156,7 @@ static int get_fsm_inst_dump(struct ctrl_cmd *cmd, void *data) if (fi->proc.parent) cmd->reply = talloc_asprintf_append(cmd->reply, ",parent='%s'", fi->proc.parent->name); - llist_for_each_entry(child, &fi->proc.children, list) { + llist_for_each_entry(child, &fi->proc.children, proc.child) { cmd->reply = talloc_asprintf_append(cmd->reply, ",child='%s'", child->name); } diff --git a/src/vty/fsm_vty.c b/src/vty/fsm_vty.c index 8628d159..9bde241c 100644 --- a/src/vty/fsm_vty.c +++ b/src/vty/fsm_vty.c @@ -102,7 +102,7 @@ void vty_out_fsm_inst(struct vty *vty, struct osmo_fsm_inst *fsmi) fsmi->proc.parent_term_event), VTY_NEWLINE); } - llist_for_each_entry(child, &fsmi->proc.children, list) { + llist_for_each_entry(child, &fsmi->proc.children, proc.child) { vty_out(vty, " Child: '%s'%s", child->name, VTY_NEWLINE); } } -- cgit v1.2.3 From 88fa5a3e1ee82f456ad121ddfab65e4d76fc14cb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 28 Jul 2018 22:55:43 +0200 Subject: gsm0480: Factor out msgb allocation helper function Change-Id: If25b467481023eadaaf3f78157eceff4b81d24d2 --- include/osmocom/gsm/gsm0480.h | 2 ++ src/gsm/gsm0480.c | 7 ++++++- src/gsm/libosmogsm.map | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h index e928d83f..6a596ead 100644 --- a/include/osmocom/gsm/gsm0480.h +++ b/include/osmocom/gsm/gsm0480.h @@ -108,6 +108,8 @@ int gsm0480_parse_facility_ie(const uint8_t *facility_ie, uint16_t length, int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request *request); +struct msgb *gsm0480_msgb_alloc_name(const char *name); + struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); struct msgb *gsm0480_create_notifySS(const char *text); diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 165b309f..ac0fa125 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -787,13 +787,18 @@ static int parse_ss_for_bs_req(const uint8_t *ss_req_data, return rc; } +struct msgb *gsm0480_msgb_alloc_name(const char *name) +{ + return msgb_alloc_headroom(1024, 128, name); +} + struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text) { struct msgb *msg; uint8_t *ptr8; int response_len; - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + msg = gsm0480_msgb_alloc_name("TS 04.80 USSD Resp"); if (!msg) return NULL; diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3b403c2b..312c9901 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -97,6 +97,7 @@ gsm0480_wrap_facility; gsm0480_wrap_invoke; gsm0480_comp_type_names; gsm0480_op_code_names; +gsm0480_msgb_alloc_name; gsm0502_calc_paging_group; -- cgit v1.2.3 From b0d95940818abd5cad17c0b503029faee51cecba Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 28 Jul 2018 23:02:48 +0200 Subject: USSD: Introduce gsm0480_gen_ussd_resp_7bit() Contrary to the existing gsm0480_create_ussd_resp(), the new function only generates the value part of the FACILITY IE, and not the IE Tag/Length or the 04.08 L3 header. This is needed in the context of GSUP-encapsulated USSD, as here we don't work with L3 messages, but only pass on the FACILITY IE value. Change-Id: Ide240279240322f643e142229eb7829f538c6314 --- include/osmocom/gsm/gsm0480.h | 1 + src/gsm/gsm0480.c | 23 ++++++++++++++++++++++- src/gsm/libosmogsm.map | 1 + 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h index 6a596ead..9fa84b0b 100644 --- a/include/osmocom/gsm/gsm0480.h +++ b/include/osmocom/gsm/gsm0480.h @@ -109,6 +109,7 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, struct ss_request *request); struct msgb *gsm0480_msgb_alloc_name(const char *name); +struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text); struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index ac0fa125..db28f0dc 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -792,7 +792,11 @@ struct msgb *gsm0480_msgb_alloc_name(const char *name) return msgb_alloc_headroom(1024, 128, name); } -struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text) +/*! Generate a USSD ReturnResult component containing a string in default GSM alphabet. + * \param[in] invoke_id InvokeID of the request to which we respond + * \param[in] text USSD text in ASCII; to be encoded as GSM 7-but alphabet + */ +struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text) { struct msgb *msg; uint8_t *ptr8; @@ -829,6 +833,23 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const /* Wrap this up as a Return Result component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); + return msg; +} + +/*! Legacy helper: Generate USSD response including FACILITY IE + L3 header. + * + * This function is just like \ref gsm0480_gen_ussd_resp_7bit, but it generates + * not only the FACILITY value, but the full L3 message including message header + * and FACILITY IE Tag+Length. + */ +struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text) +{ + struct msgb *msg; + + msg = gsm0480_gen_ussd_resp_7bit(invoke_id, text); + if (!msg) + return NULL; + /* Wrap the component in a Facility message */ msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 312c9901..d21514ca 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -98,6 +98,7 @@ gsm0480_wrap_invoke; gsm0480_comp_type_names; gsm0480_op_code_names; gsm0480_msgb_alloc_name; +gsm0480_gen_ussd_resp_7bit; gsm0502_calc_paging_group; -- cgit v1.2.3 From 7ecc4a31710c6c46ba9327e2708dcba4ae56276d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 28 Jul 2018 23:05:36 +0200 Subject: 04.80: New gsm0480_gen_{reject,return_error}() functions Add functions to generate TS 04.80 (supplementary services) Reject and ReturnError components. Change-Id: I6e5ee39c3d03364f7833ec717593d5ddb0a4c5f9 --- include/osmocom/gsm/gsm0480.h | 2 ++ src/gsm/gsm0480.c | 64 +++++++++++++++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 2 ++ 3 files changed, 68 insertions(+) diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h index 9fa84b0b..246f4b3b 100644 --- a/include/osmocom/gsm/gsm0480.h +++ b/include/osmocom/gsm/gsm0480.h @@ -110,6 +110,8 @@ int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len, struct msgb *gsm0480_msgb_alloc_name(const char *name); struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text); +struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code); +struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t problem_code); struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text); struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text); diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index db28f0dc..2d2df4ad 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -87,6 +87,15 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, return data; } +static inline unsigned char *msgb_push_NULL(struct msgb *msgb) +{ + uint8_t *data = msgb_push(msgb, 2); + + data[0] = ASN1_NULL_TYPE_TAG; + data[1] = 0; + return data; +} + /* wrap an invoke around it... the other way around * * 1.) Invoke Component tag @@ -861,6 +870,61 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const return msg; } +/*! Generate a ReturnError component (see section 3.6.1) and given error code (see section 3.6.6). + * \param[in] invoke_id InvokeID of the request + * \param[in] error_code Error code (section 4.5) + * \return message buffer containing the Reject component + * + * Note: if InvokeID is not available, e.g. when message parsing failed, any incorrect vlue + * can be passed (0x00 > x > 0xff), so the universal NULL-tag (see table 3.6) will be used instead. + */ +struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code) +{ + struct msgb *msg = gsm0480_msgb_alloc_name("TS 04.80 ReturnError"); + + /* First insert the problem code */ + msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code); + + /* Before it, insert the invoke ID */ + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + + /* Wrap this up as a Reject component */ + msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_ERROR); + + /* FIXME: Wrap in Facility + L3? */ + return msg; +} + +/*! Generate a Reject component (see section 3.6.1) and given error code (see section 3.6.7). + * \param[in] invoke_id InvokeID of the request + * \param[in] problem_tag Problem code tag (table 3.13) + * \param[in] problem_code Problem code (table 3.14-3.17) + * \return message buffer containing the Reject component + * + * Note: if InvokeID is not available, e.g. when message parsing failed, any incorrect vlue + * can be passed (0x00 > x > 0xff), so the universal NULL-tag (see table 3.6) will be used instead. + */ +struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t problem_code) +{ + struct msgb *msg = gsm0480_msgb_alloc_name("TS 04.80 Reject"); + + /* First insert the problem code */ + msgb_push_TLV1(msg, problem_tag, problem_code); + + /* If the Invoke ID is not available, Universal NULL (table 3.9) with length=0 shall be used */ + if (invoke_id < 0 || invoke_id > 255) + msgb_push_NULL(msg); + else + msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + + /* Wrap this up as a Reject component */ + msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT); + + /* FIXME: Wrap in Facility + L3? */ + return msg; +} + + struct gsm48_hdr *gsm0480_l3hdr_push(struct msgb *msg, uint8_t proto_discr, uint8_t msg_type) { diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index d21514ca..b44cfd25 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -99,6 +99,8 @@ gsm0480_comp_type_names; gsm0480_op_code_names; gsm0480_msgb_alloc_name; gsm0480_gen_ussd_resp_7bit; +gsm0480_gen_return_error; +gsm0480_gen_reject; gsm0502_calc_paging_group; -- cgit v1.2.3 From baed91709c55956024725d04b1a8e2735ed522a2 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 30 Jul 2018 03:42:45 +0700 Subject: vty/vty.c: remove dead unused tall_bsc_ctx Change-Id: I160728544c0effe45757df22f1ff2314fcb13dd1 --- src/vty/vty.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vty/vty.c b/src/vty/vty.c index 6ca7a154..aab0607d 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -1766,8 +1766,6 @@ void vty_init_vtysh(void) vtyvec = vector_init(VECTOR_MIN_SIZE); } -extern void *tall_bsc_ctx; - /*! Initialize VTY layer * \param[in] app_info application information */ -- cgit v1.2.3 From fdd366ed1b608b2ed8778ca566b3f15e25281281 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 30 Jul 2018 12:04:21 +0200 Subject: import oap_client into libosmogsm This imports the code from osmo-msc 6afef893e17bce67e4d4119acd34d480ed03ba77 with minimal changes to make it compile. Symbol renaming to osmo_ prefix is done separately in a follow-up patch to have a as-clean-as-possible import first. Change-Id: I9bc38102318da02d1fe46ef516df3cfd6bf8e3da --- include/Makefile.am | 1 + include/osmocom/gsm/oap_client.h | 82 ++++++++++++ src/gsm/Makefile.am | 2 +- src/gsm/libosmogsm.map | 5 + src/gsm/oap_client.c | 280 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 369 insertions(+), 1 deletion(-) create mode 100644 include/osmocom/gsm/oap_client.h create mode 100644 src/gsm/oap_client.c diff --git a/include/Makefile.am b/include/Makefile.am index 38ba14cd..ef8ec656 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -100,6 +100,7 @@ nobase_include_HEADERS = \ osmocom/gsm/prim.h \ osmocom/gsm/l1sap.h \ osmocom/gsm/oap.h \ + osmocom/gsm/oap_client.h \ osmocom/gsm/protocol/gsm_03_40.h \ osmocom/gsm/protocol/gsm_03_41.h \ osmocom/gsm/protocol/gsm_04_08.h \ diff --git a/include/osmocom/gsm/oap_client.h b/include/osmocom/gsm/oap_client.h new file mode 100644 index 00000000..80c86d5d --- /dev/null +++ b/include/osmocom/gsm/oap_client.h @@ -0,0 +1,82 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +struct msgb; +struct osmo_oap_message; + +/* This is the config part for vty. It is essentially copied in + * oap_client_state, where values are copied over once the config is + * considered valid. */ +struct oap_client_config { + uint16_t client_id; + int secret_k_present; + uint8_t secret_k[16]; + int secret_opc_present; + uint8_t secret_opc[16]; +}; + +/* The runtime state of the OAP client. client_id and the secrets are in fact + * duplicated from oap_client_config, so that a separate validation of the + * config data is possible, and so that only a struct oap_client_state* is + * passed around. */ +struct oap_client_state { + enum { + OAP_UNINITIALIZED = 0, /* just allocated. */ + OAP_DISABLED, /* disabled by config. */ + OAP_INITIALIZED, /* enabled, config is valid. */ + OAP_REQUESTED_CHALLENGE, + OAP_SENT_CHALLENGE_RESULT, + OAP_REGISTERED + } state; + uint16_t client_id; + uint8_t secret_k[16]; + uint8_t secret_opc[16]; + int registration_failures; +}; + +/* From config, initialize state. Return 0 on success. */ +int oap_client_init(struct oap_client_config *config, + struct oap_client_state *state); + +/* Construct an OAP registration message and return in *msg_tx. Use + * state->client_id and update state->state. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx); + +/* Decode and act on a received OAP message msg_rx. Update state->state. If a + * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP + * server (and freed) by the caller. The received msg_rx is not freed. + * Return 0 on success, or a negative value on error. + * If an error is returned, *msg_tx is guaranteed to be NULL. */ +int oap_client_handle(struct oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx); + +/* Allocate a msgb and in it, return the encoded oap_client_msg. Return + * NULL on error. (Like oap_client_encode(), but also allocates a msgb.) + * About the name: the idea is do_something(oap_client_encoded(my_struct)) + */ +struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg); diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 900fcfa1..29299a64 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -30,7 +30,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \ gsup.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ - gsm23003.c mncc.c bts_features.c + gsm23003.c mncc.c bts_features.c oap_client.c libgsmint_la_LDFLAGS = -no-undefined libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index b44cfd25..6eb60cc2 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -493,5 +493,10 @@ osmo_mncc_stringify; osmo_mncc_names; _osmo_mncc_log; +oap_client_encoded; +oap_client_handle; +oap_client_init; +oap_client_register; + local: *; }; diff --git a/src/gsm/oap_client.c b/src/gsm/oap_client.c new file mode 100644 index 00000000..2227a3ce --- /dev/null +++ b/src/gsm/oap_client.c @@ -0,0 +1,280 @@ +/* Osmocom Authentication Protocol API */ + +/* (C) 2015 by Sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include + +#include +#include +#include +#include + +#include + +int oap_client_init(struct oap_client_config *config, + struct oap_client_state *state) +{ + OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + + if (!config) + goto disable; + + if (config->client_id == 0) + goto disable; + + if (config->secret_k_present == 0) { + LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n"); + goto disable; + } + + if (config->secret_opc_present == 0) { + LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n"); + goto disable; + } + + state->client_id = config->client_id; + memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); + memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); + state->state = OAP_INITIALIZED; + return 0; + +disable: + state->state = OAP_DISABLED; + return 0; +} + +/* From the given state and received RAND and AUTN octets, validate the + * server's authenticity and formulate the matching milenage reply octets in + * *tx_xres. The state is not modified. + * On success, and if tx_res is not NULL, exactly 8 octets will be written to + * *tx_res. If not NULL, tx_res must point at allocated memory of at least 8 + * octets. The caller will want to send XRES back to the server in a challenge + * response message and update the state. + * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail + * the authentication check; -3 for any other errors. */ +static int oap_evaluate_challenge(const struct oap_client_state *state, + const uint8_t *rx_random, + const uint8_t *rx_autn, + uint8_t *tx_xres) +{ + struct osmo_auth_vector vec; + + struct osmo_sub_auth_data auth = { + .type = OSMO_AUTH_TYPE_UMTS, + .algo = OSMO_AUTH_ALG_MILENAGE, + }; + + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k) + == sizeof(state->secret_k), _secret_k_size_match); + osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc) + == sizeof(state->secret_opc), _secret_opc_size_match); + + switch (state->state) { + case OAP_UNINITIALIZED: + case OAP_DISABLED: + return -1; + default: + break; + } + + memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k)); + memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc)); + memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf)); + auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */ + + memset(&vec, 0, sizeof(vec)); + osmo_auth_gen_vec(&vec, &auth, rx_random); + + if (vec.res_len != 8) { + LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n", + vec.res_len); + return -3; + } + + if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) { + LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n"); + LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n", + osmo_hexdump_nospc(rx_autn, sizeof(vec.autn))); + LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected: %s\n", + osmo_hexdump_nospc(vec.autn, sizeof(vec.autn))); + return -2; + } + + if (tx_xres != NULL) + memcpy(tx_xres, vec.res, 8); + return 0; +} + +struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg) +{ + struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); + OSMO_ASSERT(msg); + osmo_oap_encode(msg, oap_msg); + return msg; +} + +/* Create a new msgb containing an OAP registration message. + * On error, return NULL. */ +static struct msgb* oap_msg_register(uint16_t client_id) +{ + struct osmo_oap_message oap_msg = {0}; + + if (client_id < 1) { + LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id); + return NULL; + } + + oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; + oap_msg.client_id = client_id; + return oap_client_encoded(&oap_msg); +} + +int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx) +{ + *msg_tx = oap_msg_register(state->client_id); + if (!(*msg_tx)) + return -1; + + state->state = OAP_REQUESTED_CHALLENGE; + return 0; +} + +/* Create a new msgb containing an OAP challenge response message. + * xres must point at 8 octets to return as challenge response. + * On error, return NULL. */ +static struct msgb* oap_msg_challenge_response(uint8_t *xres) +{ + struct osmo_oap_message oap_reply = {0}; + + oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; + memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); + oap_reply.xres_present = 1; + return oap_client_encoded(&oap_reply); +} + +static int handle_challenge(struct oap_client_state *state, + struct osmo_oap_message *oap_rx, + struct msgb **msg_tx) +{ + int rc; + uint8_t xres[8]; + + if (!(oap_rx->rand_present && oap_rx->autn_present)) { + LOGP(DLOAP, LOGL_ERROR, + "OAP challenge incomplete (rand_present: %d, autn_present: %d)\n", + oap_rx->rand_present, oap_rx->autn_present); + rc = -2; + goto failure; + } + + rc = oap_evaluate_challenge(state, + oap_rx->rand, + oap_rx->autn, + xres); + if (rc < 0) + goto failure; + + *msg_tx = oap_msg_challenge_response(xres); + if ((*msg_tx) == NULL) { + rc = -1; + goto failure; + } + + state->state = OAP_SENT_CHALLENGE_RESULT; + return 0; + +failure: + OSMO_ASSERT(rc < 0); + state->state = OAP_INITIALIZED; + return rc; +} + +int oap_client_handle(struct oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx) +{ + uint8_t *data = msgb_l2(msg_rx); + size_t data_len = msgb_l2len(msg_rx); + struct osmo_oap_message oap_msg = {0}; + int rc = 0; + + *msg_tx = NULL; + + OSMO_ASSERT(data); + + rc = osmo_oap_decode(&oap_msg, data, data_len); + if (rc < 0) { + LOGP(DLOAP, LOGL_ERROR, + "Decoding OAP message failed with error '%s' (%d)\n", + get_value_string(gsm48_gmm_cause_names, -rc), -rc); + return -10; + } + + switch (state->state) { + case OAP_UNINITIALIZED: + LOGP(DLOAP, LOGL_ERROR, + "Received OAP message %d, but the OAP client is" + " not initialized\n", oap_msg.message_type); + return -ENOTCONN; + case OAP_DISABLED: + LOGP(DLOAP, LOGL_ERROR, + "Received OAP message %d, but the OAP client is" + " disabled\n", oap_msg.message_type); + return -ENOTCONN; + default: + break; + } + + switch (oap_msg.message_type) { + case OAP_MSGT_CHALLENGE_REQUEST: + return handle_challenge(state, &oap_msg, msg_tx); + + case OAP_MSGT_REGISTER_RESULT: + /* successfully registered */ + state->state = OAP_REGISTERED; + break; + + case OAP_MSGT_REGISTER_ERROR: + LOGP(DLOAP, LOGL_ERROR, + "OAP registration failed\n"); + state->state = OAP_INITIALIZED; + if (state->registration_failures < 3) { + state->registration_failures++; + return oap_client_register(state, msg_tx); + } + return -11; + + case OAP_MSGT_REGISTER_REQUEST: + case OAP_MSGT_CHALLENGE_RESULT: + LOGP(DLOAP, LOGL_ERROR, + "Received invalid OAP message type for OAP client side: %d\n", + (int)oap_msg.message_type); + return -12; + + default: + LOGP(DLOAP, LOGL_ERROR, + "Unknown OAP message type: %d\n", + (int)oap_msg.message_type); + return -13; + } + + return 0; +} -- cgit v1.2.3 From 9b04c17c7a450fa83282f133283a86f4a0c2fd6f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 30 Jul 2018 12:06:31 +0200 Subject: oap_client: Rename symbols with osmo_ prefix As we're moving this to a common/shared library now, we need to use the osmo_ namespace prefix for symbol names, struct/type names and constants. Change-Id: Ie36729996abd30b84d1c30a09f62ebc6a9794950 --- include/osmocom/gsm/oap_client.h | 28 ++++++++++++------------ src/gsm/libosmogsm.map | 8 +++---- src/gsm/oap_client.c | 46 ++++++++++++++++++++-------------------- 3 files changed, 41 insertions(+), 41 deletions(-) diff --git a/include/osmocom/gsm/oap_client.h b/include/osmocom/gsm/oap_client.h index 80c86d5d..763f982c 100644 --- a/include/osmocom/gsm/oap_client.h +++ b/include/osmocom/gsm/oap_client.h @@ -30,7 +30,7 @@ struct osmo_oap_message; /* This is the config part for vty. It is essentially copied in * oap_client_state, where values are copied over once the config is * considered valid. */ -struct oap_client_config { +struct osmo_oap_client_config { uint16_t client_id; int secret_k_present; uint8_t secret_k[16]; @@ -42,14 +42,14 @@ struct oap_client_config { * duplicated from oap_client_config, so that a separate validation of the * config data is possible, and so that only a struct oap_client_state* is * passed around. */ -struct oap_client_state { +struct osmo_oap_client_state { enum { - OAP_UNINITIALIZED = 0, /* just allocated. */ - OAP_DISABLED, /* disabled by config. */ - OAP_INITIALIZED, /* enabled, config is valid. */ - OAP_REQUESTED_CHALLENGE, - OAP_SENT_CHALLENGE_RESULT, - OAP_REGISTERED + OSMO_OAP_UNINITIALIZED = 0, /* just allocated. */ + OSMO_OAP_DISABLED, /* disabled by config. */ + OSMO_OAP_INITIALIZED, /* enabled, config is valid. */ + OSMO_OAP_REQUESTED_CHALLENGE, + OSMO_OAP_SENT_CHALLENGE_RESULT, + OSMO_OAP_REGISTERED } state; uint16_t client_id; uint8_t secret_k[16]; @@ -58,25 +58,25 @@ struct oap_client_state { }; /* From config, initialize state. Return 0 on success. */ -int oap_client_init(struct oap_client_config *config, - struct oap_client_state *state); +int osmo_oap_client_init(struct osmo_oap_client_config *config, + struct osmo_oap_client_state *state); /* Construct an OAP registration message and return in *msg_tx. Use * state->client_id and update state->state. * Return 0 on success, or a negative value on error. * If an error is returned, *msg_tx is guaranteed to be NULL. */ -int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx); +int osmo_oap_client_register(struct osmo_oap_client_state *state, struct msgb **msg_tx); /* Decode and act on a received OAP message msg_rx. Update state->state. If a * non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP * server (and freed) by the caller. The received msg_rx is not freed. * Return 0 on success, or a negative value on error. * If an error is returned, *msg_tx is guaranteed to be NULL. */ -int oap_client_handle(struct oap_client_state *state, - const struct msgb *msg_rx, struct msgb **msg_tx); +int osmo_oap_client_handle(struct osmo_oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx); /* Allocate a msgb and in it, return the encoded oap_client_msg. Return * NULL on error. (Like oap_client_encode(), but also allocates a msgb.) * About the name: the idea is do_something(oap_client_encoded(my_struct)) */ -struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_client_msg); +struct msgb *osmo_oap_client_encoded(const struct osmo_oap_message *oap_client_msg); diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6eb60cc2..bc9ed528 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -493,10 +493,10 @@ osmo_mncc_stringify; osmo_mncc_names; _osmo_mncc_log; -oap_client_encoded; -oap_client_handle; -oap_client_init; -oap_client_register; +osmo_oap_client_encoded; +osmo_oap_client_handle; +osmo_oap_client_init; +osmo_oap_client_register; local: *; }; diff --git a/src/gsm/oap_client.c b/src/gsm/oap_client.c index 2227a3ce..ea406341 100644 --- a/src/gsm/oap_client.c +++ b/src/gsm/oap_client.c @@ -30,10 +30,10 @@ #include -int oap_client_init(struct oap_client_config *config, - struct oap_client_state *state) +int osmo_oap_client_init(struct osmo_oap_client_config *config, + struct osmo_oap_client_state *state) { - OSMO_ASSERT(state->state == OAP_UNINITIALIZED); + OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED); if (!config) goto disable; @@ -54,11 +54,11 @@ int oap_client_init(struct oap_client_config *config, state->client_id = config->client_id; memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k)); memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc)); - state->state = OAP_INITIALIZED; + state->state = OSMO_OAP_INITIALIZED; return 0; disable: - state->state = OAP_DISABLED; + state->state = OSMO_OAP_DISABLED; return 0; } @@ -71,7 +71,7 @@ disable: * response message and update the state. * Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail * the authentication check; -3 for any other errors. */ -static int oap_evaluate_challenge(const struct oap_client_state *state, +static int oap_evaluate_challenge(const struct osmo_oap_client_state *state, const uint8_t *rx_random, const uint8_t *rx_autn, uint8_t *tx_xres) @@ -89,8 +89,8 @@ static int oap_evaluate_challenge(const struct oap_client_state *state, == sizeof(state->secret_opc), _secret_opc_size_match); switch (state->state) { - case OAP_UNINITIALIZED: - case OAP_DISABLED: + case OSMO_OAP_UNINITIALIZED: + case OSMO_OAP_DISABLED: return -1; default: break; @@ -124,7 +124,7 @@ static int oap_evaluate_challenge(const struct oap_client_state *state, return 0; } -struct msgb *oap_client_encoded(const struct osmo_oap_message *oap_msg) +struct msgb *osmo_oap_client_encoded(const struct osmo_oap_message *oap_msg) { struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__); OSMO_ASSERT(msg); @@ -145,16 +145,16 @@ static struct msgb* oap_msg_register(uint16_t client_id) oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST; oap_msg.client_id = client_id; - return oap_client_encoded(&oap_msg); + return osmo_oap_client_encoded(&oap_msg); } -int oap_client_register(struct oap_client_state *state, struct msgb **msg_tx) +int osmo_oap_client_register(struct osmo_oap_client_state *state, struct msgb **msg_tx) { *msg_tx = oap_msg_register(state->client_id); if (!(*msg_tx)) return -1; - state->state = OAP_REQUESTED_CHALLENGE; + state->state = OSMO_OAP_REQUESTED_CHALLENGE; return 0; } @@ -168,10 +168,10 @@ static struct msgb* oap_msg_challenge_response(uint8_t *xres) oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT; memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres)); oap_reply.xres_present = 1; - return oap_client_encoded(&oap_reply); + return osmo_oap_client_encoded(&oap_reply); } -static int handle_challenge(struct oap_client_state *state, +static int handle_challenge(struct osmo_oap_client_state *state, struct osmo_oap_message *oap_rx, struct msgb **msg_tx) { @@ -199,17 +199,17 @@ static int handle_challenge(struct oap_client_state *state, goto failure; } - state->state = OAP_SENT_CHALLENGE_RESULT; + state->state = OSMO_OAP_SENT_CHALLENGE_RESULT; return 0; failure: OSMO_ASSERT(rc < 0); - state->state = OAP_INITIALIZED; + state->state = OSMO_OAP_INITIALIZED; return rc; } -int oap_client_handle(struct oap_client_state *state, - const struct msgb *msg_rx, struct msgb **msg_tx) +int osmo_oap_client_handle(struct osmo_oap_client_state *state, + const struct msgb *msg_rx, struct msgb **msg_tx) { uint8_t *data = msgb_l2(msg_rx); size_t data_len = msgb_l2len(msg_rx); @@ -229,12 +229,12 @@ int oap_client_handle(struct oap_client_state *state, } switch (state->state) { - case OAP_UNINITIALIZED: + case OSMO_OAP_UNINITIALIZED: LOGP(DLOAP, LOGL_ERROR, "Received OAP message %d, but the OAP client is" " not initialized\n", oap_msg.message_type); return -ENOTCONN; - case OAP_DISABLED: + case OSMO_OAP_DISABLED: LOGP(DLOAP, LOGL_ERROR, "Received OAP message %d, but the OAP client is" " disabled\n", oap_msg.message_type); @@ -249,16 +249,16 @@ int oap_client_handle(struct oap_client_state *state, case OAP_MSGT_REGISTER_RESULT: /* successfully registered */ - state->state = OAP_REGISTERED; + state->state = OSMO_OAP_REGISTERED; break; case OAP_MSGT_REGISTER_ERROR: LOGP(DLOAP, LOGL_ERROR, "OAP registration failed\n"); - state->state = OAP_INITIALIZED; + state->state = OSMO_OAP_INITIALIZED; if (state->registration_failures < 3) { state->registration_failures++; - return oap_client_register(state, msg_tx); + return osmo_oap_client_register(state, msg_tx); } return -11; -- cgit v1.2.3 From 6db529aedd61191e1d574f97d62bebc8bcaf057d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 30 Jul 2018 18:14:45 +0200 Subject: import oap_client_test from osmo-sgsn As oap_client has moved from osmo-sgsn to libosmogsm, it is only fair that the related unit test shall also be moved here. Change-Id: I9d64e10b4bacac9b530cf077841bad762fc6d558 --- tests/Makefile.am | 9 +- tests/oap/Makefile.am | 37 ------ tests/oap/oap_client_test.c | 271 ++++++++++++++++++++++++++++++++++++++++++ tests/oap/oap_client_test.err | 35 ++++++ tests/oap/oap_client_test.ok | 2 + tests/testsuite.at | 7 ++ 6 files changed, 322 insertions(+), 39 deletions(-) delete mode 100644 tests/oap/Makefile.am create mode 100644 tests/oap/oap_client_test.c create mode 100644 tests/oap/oap_client_test.err create mode 100644 tests/oap/oap_client_test.ok diff --git a/tests/Makefile.am b/tests/Makefile.am index eaaa8df2..072bb4a2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,7 +23,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ coding/coding_test conv/conv_gsm0503_test \ abis/abis_test endian/endian_test sercomm/sercomm_test \ prbs/prbs_test gsm23003/gsm23003_test \ - codec/codec_ecu_fr_test timer/clk_override_test + codec/codec_ecu_fr_test timer/clk_override_test \ + oap/oap_client_test if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test @@ -172,6 +173,9 @@ gsup_gsup_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la oap_oap_test_SOURCES = oap/oap_test.c oap_oap_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la +oap_oap_client_test_SOURCES = oap/oap_client_test.c +oap_oap_client_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la + fsm_fsm_test_SOURCES = fsm/fsm_test.c fsm_fsm_test_LDADD = $(LDADD) $(top_builddir)/src/ctrl/libosmoctrl.la @@ -253,7 +257,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ conv/conv_gsm0503_test.ok endian/endian_test.ok \ sercomm/sercomm_test.ok prbs/prbs_test.ok \ gsm23003/gsm23003_test.ok \ - timer/clk_override_test.ok + timer/clk_override_test.ok \ + oap/oap_client_test.ok oap/oap_client_test.err DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c BUILT_SOURCES = conv/gsm0503_test_vectors.c diff --git a/tests/oap/Makefile.am b/tests/oap/Makefile.am deleted file mode 100644 index 06ccf338..00000000 --- a/tests/oap/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - -ggdb3 \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGSM_CFLAGS) \ - $(NULL) - -EXTRA_DIST = \ - oap_test.ok \ - $(NULL) - -if HAVE_LIBGTP -if HAVE_LIBCARES -noinst_PROGRAMS = \ - oap_test \ - $(NULL) -endif -endif - -oap_test_SOURCES = \ - oap_test.c \ - $(NULL) - -oap_test_LDADD = \ - $(top_builddir)/src/gprs/oap.o \ - $(top_builddir)/src/gprs/oap_messages.o \ - $(top_builddir)/src/gprs/gprs_utils.o \ - $(top_builddir)/src/libcommon/libcommon.a \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGSM_LIBS) \ - -lrt - diff --git a/tests/oap/oap_client_test.c b/tests/oap/oap_client_test.c new file mode 100644 index 00000000..a841b381 --- /dev/null +++ b/tests/oap/oap_client_test.c @@ -0,0 +1,271 @@ +/* Test Osmocom Authentication Protocol */ +/* + * (C) 2015 by sysmocom s.f.m.c. GmbH + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include + +#include + +#include +#include + +static void test_oap_api(void) +{ + printf("Testing OAP API\n"); + + struct osmo_oap_client_config _config; + struct osmo_oap_client_config *config = &_config; + + struct osmo_oap_client_state _state; + struct osmo_oap_client_state *state = &_state; + + struct osmo_oap_message oap_rx; + struct msgb *msg_rx; + + struct osmo_oap_message oap_tx; + struct msgb *msg_tx; + + memset(config, 0, sizeof(*config)); + memset(state, 0, sizeof(*state)); + + OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16); + OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16); + + fprintf(stderr, "- make sure filling with zeros means uninitialized\n"); + OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED); + + fprintf(stderr, "- reject messages in uninitialized state\n"); + memset(&oap_rx, 0, sizeof(oap_rx)); + state->client_id = 1; + oap_rx.message_type = OAP_MSGT_REGISTER_ERROR; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0); + OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- NULL config should disable\n"); + OSMO_ASSERT( osmo_oap_client_init(NULL, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + + fprintf(stderr, "- reject messages in disabled state\n"); + memset(state, 0, sizeof(*state)); + memset(&oap_rx, 0, sizeof(oap_rx)); + state->state = OSMO_OAP_DISABLED; + state->client_id = 1; + oap_rx.message_type = OAP_MSGT_REGISTER_ERROR; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- invalid client_id and shared secret\n"); + memset(state, 0, sizeof(*state)); + config->client_id = 0; + config->secret_k_present = 0; + config->secret_opc_present = 0; + OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + + fprintf(stderr, "- reset state\n"); + memset(state, 0, sizeof(*state)); + + fprintf(stderr, "- only client_id is invalid\n"); + config->client_id = 0; + config->secret_k_present = 1; + config->secret_opc_present = 1; + OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + fprintf(stderr, "- valid id, but omitted shared_secret (1/2)\n"); + config->client_id = 12345; + config->secret_k_present = 0; + config->secret_opc_present = 1; + OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + fprintf(stderr, "- valid id, but omitted shared_secret (2/2)\n"); + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 0; + OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_DISABLED); + + memset(state, 0, sizeof(*state)); + + + fprintf(stderr, "- mint configuration\n"); + config->client_id = 12345; + config->secret_k_present = 1; + config->secret_opc_present = 1; + /*config->secret_* buffers are still set from the top */ + OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 ); + OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED); + + + fprintf(stderr, "- Missing challenge data\n"); + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST; + oap_rx.rand_present = 0; + oap_rx.autn_present = 0; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- AUTN missing\n"); + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + oap_rx.rand_present = 1; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- RAND missing\n"); + oap_rx.rand_present = 0; + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.autn_present = 1; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- wrong autn (by one bit)\n"); + osmo_hexparse("0102030405060708090a0b0c0d0e0f10", + oap_rx.rand, 16); + osmo_hexparse("dec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + oap_rx.rand_present = 1; + oap_rx.autn_present = 1; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2); + msgb_free(msg_rx); + OSMO_ASSERT(!msg_tx); + + fprintf(stderr, "- all data correct\n"); + osmo_hexparse("cec4e3848a33000086781158ca40f136", + oap_rx.autn, 16); + msg_rx = osmo_oap_client_encoded(&oap_rx); + + fprintf(stderr, "- but refuse to evaluate in uninitialized state\n"); + OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED); + + state->state = OSMO_OAP_UNINITIALIZED; + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0); + OSMO_ASSERT(!msg_tx); + + state->state = OSMO_OAP_DISABLED; + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0); + OSMO_ASSERT(!msg_tx); + + state->state = OSMO_OAP_INITIALIZED; + + fprintf(stderr, "- now everything is correct\n"); + /* a successful return value here indicates correct autn */ + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0); + msgb_free(msg_rx); + + fprintf(stderr, "- Expect the challenge response in msg_tx\n"); + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT); + OSMO_ASSERT(strcmp("e2d05b598c61d9ba", + osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres))) + == 0); + OSMO_ASSERT(state->state == OSMO_OAP_SENT_CHALLENGE_RESULT); + msgb_free(msg_tx); + msg_tx = 0; + + struct osmo_oap_client_state saved_state = _state; + + fprintf(stderr, "- Receive registration error for the first time.\n"); + + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_ERROR; + oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC; + msg_rx = osmo_oap_client_encoded(&oap_rx); + + OSMO_ASSERT(state->registration_failures == 0); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(state->registration_failures == 1); + OSMO_ASSERT(msg_tx); + OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0); + OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST); + OSMO_ASSERT(state->state == OSMO_OAP_REQUESTED_CHALLENGE); + msgb_free(msg_tx); + msg_tx = 0; + + fprintf(stderr, "- Receive registration error for the Nth time.\n"); + state->registration_failures = 999; + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -11); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED); + msgb_free(msg_tx); + msg_tx = 0; + + msgb_free(msg_rx); + + fprintf(stderr, "- Registration success\n"); + + _state = saved_state; + memset(&oap_rx, 0, sizeof(oap_rx)); + oap_rx.message_type = OAP_MSGT_REGISTER_RESULT; + msg_rx = osmo_oap_client_encoded(&oap_rx); + OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0); + OSMO_ASSERT(!msg_tx); + OSMO_ASSERT(state->state == OSMO_OAP_REGISTERED); + msgb_free(msg_rx); +} + +static struct log_info_cat oap_client_test_categories[] = { +}; + +static struct log_info info = { + .cat = oap_client_test_categories, + .num_cat = ARRAY_SIZE(oap_client_test_categories), +}; + +int main(int argc, char **argv) +{ + void *ctx = talloc_named_const(NULL, 0, "oap_client_test"); + msgb_talloc_ctx_init(ctx, 0); + osmo_init_logging2(ctx, &info); + + OSMO_ASSERT(osmo_stderr_target); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_print_filename(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + log_parse_category_mask(osmo_stderr_target, "DLOAP,1"); + + test_oap_api(); + printf("Done\n"); + + return 0; +} + diff --git a/tests/oap/oap_client_test.err b/tests/oap/oap_client_test.err new file mode 100644 index 00000000..62ddc9ef --- /dev/null +++ b/tests/oap/oap_client_test.err @@ -0,0 +1,35 @@ +- make sure filling with zeros means uninitialized +- reject messages in uninitialized state +DLOAP Received OAP message 5, but the OAP client is not initialized +- NULL config should disable +- reject messages in disabled state +DLOAP Received OAP message 5, but the OAP client is disabled +- invalid client_id and shared secret +- reset state +- only client_id is invalid +- valid id, but omitted shared_secret (1/2) +DLOAP OAP: client ID set, but secret K missing. +- valid id, but omitted shared_secret (2/2) +DLOAP OAP: client ID set, but secret OPC missing. +- mint configuration +- Missing challenge data +DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 0) +- AUTN missing +DLOAP OAP challenge incomplete (rand_present: 1, autn_present: 0) +- RAND missing +DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 1) +- wrong autn (by one bit) +DLOAP OAP: AUTN mismatch! +DLOAP OAP: AUTN from server: dec4e3848a33000086781158ca40f136 +DLOAP OAP: AUTN expected: cec4e3848a33000086781158ca40f136 +- all data correct +- but refuse to evaluate in uninitialized state +DLOAP Received OAP message 8, but the OAP client is not initialized +DLOAP Received OAP message 8, but the OAP client is disabled +- now everything is correct +- Expect the challenge response in msg_tx +- Receive registration error for the first time. +DLOAP OAP registration failed +- Receive registration error for the Nth time. +DLOAP OAP registration failed +- Registration success diff --git a/tests/oap/oap_client_test.ok b/tests/oap/oap_client_test.ok new file mode 100644 index 00000000..59108a79 --- /dev/null +++ b/tests/oap/oap_client_test.ok @@ -0,0 +1,2 @@ +Testing OAP API +Done diff --git a/tests/testsuite.at b/tests/testsuite.at index 43b58e8d..a1cf98ae 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -274,6 +274,13 @@ touch experr AT_CHECK([$abs_top_builddir/tests/oap/oap_test], [0], [expout], [experr]) AT_CLEANUP +AT_SETUP([oap_client]) +AT_KEYWORDS([oap_client]) +cat $abs_srcdir/oap/oap_client_test.ok > expout +cat $abs_srcdir/oap/oap_client_test.err > experr +AT_CHECK([$abs_top_builddir/tests/oap/oap_client_test], [0], [expout], [experr]) +AT_CLEANUP + AT_SETUP([socket]) AT_KEYWORDS([socket]) cat $abs_srcdir/socket/socket_test.ok > expout -- cgit v1.2.3 From 48fd019b43ff2336553f2fe122db6929bea68ae8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 31 Jul 2018 20:19:49 +0200 Subject: cosmetic: More context / naming / comment for test_idtag_parsing() Change-Id: I1ebeba2067549e0dd1541fa84715d44321ff3b43 --- tests/utils/utils_test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index a146190d..eec13ca3 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -175,7 +175,8 @@ static void test_idtag_parsing(void) struct tlv_parsed tvp; int rc; - static uint8_t data[] = { + /* IPA CCM IDENTITY REQUEST message: 8bit length followed by respective value */ + static uint8_t id_get_data[] = { 0x01, 0x08, 0x01, 0x07, 0x01, 0x02, @@ -188,7 +189,7 @@ static void test_idtag_parsing(void) 0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - rc = ipa_ccm_idtag_parse_off(&tvp, data, sizeof(data), 1); + rc = ipa_ccm_idtag_parse_off(&tvp, id_get_data, sizeof(id_get_data), 1); OSMO_ASSERT(rc == 0); OSMO_ASSERT(TLVP_PRESENT(&tvp, 8)); -- cgit v1.2.3 From 7869baf843fd10d0fd28f79395f3e7a01eebb8b7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 31 Jul 2018 20:25:48 +0200 Subject: Deprecate ipa_ccm_idtag_parse() with ipa_ccm_id_{get,resp}_parse() In the past, the function ipa_ccm_idtag_parse() was used to parse the payload of IPA CCM ID RESP packets. However, the function was based on a possible misunderstanding of the message encoding, and callers actually counted the first (upper) length nibble as part of the header and passed a pointer to the second (lower) length nibble of the first TLV into this function. As such, it was unfixable, and had to be replaced with a new function called ipa_ccm_id_resp_parse(). At the same time, we also add ipa_ccm_id_get_parse() to parse the slightly different format of the IPA CCM ID GET payload. We can never be 100% sure what is "correct", as our understanding of the protocol is entirely based on protocol analysis, without any official documentation available. This patch also introduces unit test coverage for both of the new functions. Revert "ipa: Add libosmogsm.map entry for ipa_ccm_idtag_parse_off" This reverts commit 7f31c90b80c08fbfe2d84d70d397402fdb38b94c. Revert "ipa: Properly parse LV stream of a ID_GET request" This reverts commit f558ed4bb9c0f00997b8f97c2b251a574c1a64c4. It introduced a function/behavior that was not originally intended: The parse of IPA CCM ID GET (8bit length followed by 1 byte tag and variable-length payload) instead of the IPA CCM ID RESP (16bit length followed by 1 byte tag and variable-length payload). Change-Id: I1834d90fbcdbfcb05f5b8cfe39bfe9543737ef8f --- include/osmocom/gsm/ipa.h | 10 ++++-- src/gsm/ipa.c | 83 ++++++++++++++++++++++++++++++++++++++++++----- src/gsm/libosmogsm.map | 3 +- tests/utils/utils_test.c | 64 +++++++++++++++++++++++++++++++++--- tests/utils/utils_test.ok | 4 +++ 5 files changed, 149 insertions(+), 15 deletions(-) diff --git a/include/osmocom/gsm/ipa.h b/include/osmocom/gsm/ipa.h index 7e1d7237..ec143d0e 100644 --- a/include/osmocom/gsm/ipa.h +++ b/include/osmocom/gsm/ipa.h @@ -26,8 +26,14 @@ struct ipaccess_unit { /* obtain the human-readable name of an IPA CCM ID TAG */ const char *ipa_ccm_idtag_name(uint8_t tag); -/* parse a buffer of ID tags into a osmocom TLV style representation */ -int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len); +int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) + OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead"); + +/* parse payload of IPA CCM ID GET into a osmocom TLV style representation */ +int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len); + +/* parse payload of IPA CCM ID RESP into a osmocom TLV style representation */ +int ipa_ccm_id_resp_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len); /* Is the TAG included in the length field? */ int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset); diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c index aecde831..3c7c300b 100644 --- a/src/gsm/ipa.c +++ b/src/gsm/ipa.c @@ -100,14 +100,47 @@ const char *ipa_ccm_idtag_name(uint8_t tag) int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) { - return ipa_ccm_idtag_parse_off(dec, buf, len, 0); + uint8_t t_len; + uint8_t t_tag; + uint8_t *cur = buf; + + memset(dec, 0, sizeof(*dec)); + + while (len >= 2) { + len -= 2; + t_len = *cur++; + t_tag = *cur++; + + if (t_len > len + 1) { + LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1); + return -EINVAL; + } + + DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); + + dec->lv[t_tag].len = t_len; + dec->lv[t_tag].val = cur; + + cur += t_len; + len -= t_len; + } + return 0; } -int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset) +/*! Parse the payload part of an IPA CCM ID GET, return \ref tlv_parsed format. + * The odd payload format of those messages is structured as follows: + * * 8bit length value (length of payload *and tag*) + * * 8bit tag value + * * optional, variable-length payload + * \param[out] dec Caller-provided/allocated output structure for parsed payload + * \param[in] buf Buffer containing the payload (excluding 1 byte msg_type) of the message + * \param[in] len Length of \a buf in octets + * \returns 0 on success; negative on error */ +int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len) { uint8_t t_len; uint8_t t_tag; - uint8_t *cur = buf; + const uint8_t *cur = buf; memset(dec, 0, sizeof(*dec)); @@ -116,11 +149,45 @@ int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, t_len = *cur++; t_tag = *cur++; - if (t_len < len_offset) { - LOGP(DLMI, LOGL_ERROR, "minimal offset not included: %d < %d\n", t_len, len_offset); + if (t_len > len + 1) { + LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1); return -EINVAL; } + DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); + + dec->lv[t_tag].len = t_len-1; + dec->lv[t_tag].val = cur; + + cur += t_len-1; + len -= t_len-1; + } + return 0; +} + +/*! Parse the payload part of an IPA CCM ID RESP, return \ref tlv_parsed format. + * The odd payload format of those messages is structured as follows: + * * 16bit length value (length of payload *and tag*) + * * 8bit tag value + * * optional, variable-length payload + * \param[out] dec Caller-provided/allocated output structure for parsed payload + * \param[in] buf Buffer containing the payload (excluding 1 byte msg_type) of the message + * \param[in] len Length of \a buf in octets + * \returns 0 on success; negative on error */ +int ipa_ccm_id_resp_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len) +{ + uint8_t t_len; + uint8_t t_tag; + const uint8_t *cur = buf; + + memset(dec, 0, sizeof(*dec)); + + while (len >= 3) { + len -= 3; + t_len = *cur++ << 8; + t_len += *cur++; + t_tag = *cur++; + if (t_len > len + 1) { LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1); return -EINVAL; @@ -128,11 +195,11 @@ int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); - dec->lv[t_tag].len = t_len - len_offset; + dec->lv[t_tag].len = t_len-1; dec->lv[t_tag].val = cur; - cur += t_len - len_offset; - len -= t_len - len_offset; + cur += t_len-1; + len -= t_len-1; } return 0; } diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index bc9ed528..a1d342aa 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -461,7 +461,8 @@ ipa_ccm_send_pong; ipa_ccm_tlv_to_unitdata; ipa_ccm_idtag_name; ipa_ccm_idtag_parse; -ipa_ccm_idtag_parse_off; +ipa_ccm_id_get_parse; +ipa_ccm_id_resp_parse; ipa_ccm_make_id_resp; ipa_ccm_make_id_resp_from_req; ipa_msg_alloc; diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index eec13ca3..2f1e87da 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -21,6 +21,7 @@ */ #include +#include #include #include @@ -170,13 +171,65 @@ static void hexparse_test(void) printf("rc = %d\n", rc); } -static void test_idtag_parsing(void) +static void test_ipa_ccm_id_resp_parsing(void) +{ + struct tlv_parsed tvp; + int rc; + + static const uint8_t id_resp_data[] = { + 0x00, 0x13, IPAC_IDTAG_MACADDR, + '0','0',':','0','2',':','9','5',':','0','0',':','6','2',':','9','e','\0', + 0x00, 0x11, IPAC_IDTAG_IPADDR, + '1','9','2','.','1','6','8','.','1','0','0','.','1','9','0','\0', + 0x00, 0x0a, IPAC_IDTAG_UNIT, + '1','2','3','4','/','0','/','0','\0', + 0x00, 0x02, IPAC_IDTAG_LOCATION1, + '\0', + 0x00, 0x0d, IPAC_IDTAG_LOCATION2, + 'B','T','S','_','N','B','T','1','3','1','G','\0', + 0x00, 0x0c, IPAC_IDTAG_EQUIPVERS, + '1','6','5','a','0','2','9','_','5','5','\0', + 0x00, 0x14, IPAC_IDTAG_SWVERSION, + '1','6','8','d','4','7','2','_','v','2','0','0','b','4','1','1','d','0','\0', + 0x00, 0x18, IPAC_IDTAG_UNITNAME, + 'n','b','t','s','-','0','0','-','0','2','-','9','5','-','0','0','-','6','2','-','9','E','\0', + 0x00, 0x0a, IPAC_IDTAG_SERNR, + '0','0','1','1','0','7','8','1','\0' + }; + + printf("\nTesting IPA CCM ID RESP parsing\n"); + + rc = ipa_ccm_id_resp_parse(&tvp, (uint8_t *) id_resp_data, sizeof(id_resp_data)); + OSMO_ASSERT(rc == 0); + + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_MACADDR)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_MACADDR) == 0x12); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_IPADDR)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_IPADDR) == 0x10); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNIT)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNIT) == 0x09); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION1)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION1) == 0x01); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION2)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION2) == 0x0c); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_EQUIPVERS)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SWVERSION)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SWVERSION) == 0x13); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNITNAME) == 0x17); + OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SERNR)); + OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SERNR) == 0x09); +} + +static void test_ipa_ccm_id_get_parsing(void) { struct tlv_parsed tvp; int rc; /* IPA CCM IDENTITY REQUEST message: 8bit length followed by respective value */ - static uint8_t id_get_data[] = { + static const uint8_t id_get_data[] = { 0x01, 0x08, 0x01, 0x07, 0x01, 0x02, @@ -189,7 +242,9 @@ static void test_idtag_parsing(void) 0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - rc = ipa_ccm_idtag_parse_off(&tvp, id_get_data, sizeof(id_get_data), 1); + printf("\nTesting IPA CCM ID GET parsing\n"); + + rc = ipa_ccm_id_get_parse(&tvp, id_get_data, sizeof(id_get_data)); OSMO_ASSERT(rc == 0); OSMO_ASSERT(TLVP_PRESENT(&tvp, 8)); @@ -568,7 +623,8 @@ int main(int argc, char **argv) hexdump_test(); hexparse_test(); - test_idtag_parsing(); + test_ipa_ccm_id_get_parsing(); + test_ipa_ccm_id_resp_parsing(); test_is_hexstr(); bcd_test(); str_escape_test(); diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index b158bf7b..abc7317a 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -27,6 +27,10 @@ rc = -1 Hexparse with invalid char rc = -1 +Testing IPA CCM ID GET parsing + +Testing IPA CCM ID RESP parsing + ----- test_is_hexstr 0: pass str='(null)' min=0 max=10 even=0 expect=valid 1: pass str='(null)' min=1 max=10 even=0 expect=invalid -- cgit v1.2.3 From 61650d51179a68186716a7a1583ca6d3a195237d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 1 Aug 2018 17:41:38 +0200 Subject: jenkins_arm.sh: Use same Werror related options as on other builds Change-Id: I45ab11b461a35923853f38b5bedd5025f53cc5b5 --- contrib/jenkins_arm.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/jenkins_arm.sh b/contrib/jenkins_arm.sh index 8229fc85..1d72f2f5 100755 --- a/contrib/jenkins_arm.sh +++ b/contrib/jenkins_arm.sh @@ -2,6 +2,10 @@ . $(dirname "$0")/jenkins_common.sh + +# from ../configure.ac +WERROR_FLAGS="-Werror -Wno-error=deprecated -Wno-error=deprecated-declarations -Wno-error=cpp" + src_dir="$PWD" build() { build_dir="$1" @@ -14,7 +18,7 @@ build() { --enable-embedded \ --disable-doxygen \ --disable-shared \ - CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs -Werror" + CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs $WERROR_FLAGS" $MAKE $PARALLEL_MAKE } -- cgit v1.2.3 From 5a7740d1dbefcb0116a1936da3f96960250fd849 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 1 Aug 2018 17:29:48 +0200 Subject: re-introduce ipa_ccm_idtag_parse_off() In the previous commit we deprecated ipa_ccm_idtag_parse() but also removed ipa_ccm_idtag_parse_off(), for which I couldn't find any users. However, legacy openbsc.git still uses this function, so let's re-introiduce it in its original form. Change-Id: Ibfe53b04340eb355c8bfb8453a2af1522a4b6baf --- include/osmocom/gsm/ipa.h | 5 ++--- src/gsm/ipa.c | 16 +++++++++++++--- src/gsm/libosmogsm.map | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/osmocom/gsm/ipa.h b/include/osmocom/gsm/ipa.h index ec143d0e..93cb1bf1 100644 --- a/include/osmocom/gsm/ipa.h +++ b/include/osmocom/gsm/ipa.h @@ -28,6 +28,8 @@ const char *ipa_ccm_idtag_name(uint8_t tag); int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead"); +int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset) + OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead"); /* parse payload of IPA CCM ID GET into a osmocom TLV style representation */ int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len); @@ -35,9 +37,6 @@ int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned in /* parse payload of IPA CCM ID RESP into a osmocom TLV style representation */ int ipa_ccm_id_resp_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len); -/* Is the TAG included in the length field? */ -int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset); - /* parse an Unit ID in string format into the 'ipaccess_unit' data structure */ int ipa_parse_unitid(const char *str, struct ipaccess_unit *unit_data); diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c index 3c7c300b..508cc13d 100644 --- a/src/gsm/ipa.c +++ b/src/gsm/ipa.c @@ -99,6 +99,11 @@ const char *ipa_ccm_idtag_name(uint8_t tag) } int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) +{ + return ipa_ccm_idtag_parse_off(dec, buf, len, 0); +} + +int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset) { uint8_t t_len; uint8_t t_tag; @@ -111,6 +116,11 @@ int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) t_len = *cur++; t_tag = *cur++; + if (t_len < len_offset) { + LOGP(DLMI, LOGL_ERROR, "minimal offset not included: %d < %d\n", t_len, len_offset); + return -EINVAL; + } + if (t_len > len + 1) { LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1); return -EINVAL; @@ -118,11 +128,11 @@ int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len) DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur); - dec->lv[t_tag].len = t_len; + dec->lv[t_tag].len = t_len - len_offset; dec->lv[t_tag].val = cur; - cur += t_len; - len -= t_len; + cur += t_len - len_offset; + len -= t_len - len_offset; } return 0; } diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index a1d342aa..2bb9d97c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -461,6 +461,7 @@ ipa_ccm_send_pong; ipa_ccm_tlv_to_unitdata; ipa_ccm_idtag_name; ipa_ccm_idtag_parse; +ipa_ccm_idtag_parse_off; ipa_ccm_id_get_parse; ipa_ccm_id_resp_parse; ipa_ccm_make_id_resp; -- cgit v1.2.3 From 0659c5d2f3e7653668838a2162ec72efb67ca68e Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Wed, 1 Aug 2018 12:43:08 +0200 Subject: socket: check return code of setsockopt the return code of the last setsockopt() call in osmo_sock_init() is not checked. Since all other calls to setsockopt are checked, lets check this one as well. - check return code of setsockopt() and close the socket on failure Change-Id: I96dbccc3bcff35bf39979dbe0c44aadc8ce20c83 --- src/socket.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/socket.c b/src/socket.c index dc5590c0..0a4e34cd 100644 --- a/src/socket.c +++ b/src/socket.c @@ -373,7 +373,14 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, return -ENODEV; } - setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (rc < 0) { + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt socket: %s:%u: %s\n", host, port, + strerror(errno)); + close(sfd); + sfd = -1; + } rc = osmo_sock_init_tail(sfd, type, flags); if (rc < 0) { -- cgit v1.2.3 From 99f706d3369d1e3faf6a886b7d6fe1d3145ac15c Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Wed, 1 Aug 2018 12:40:36 +0200 Subject: socket: do not set SO_REUSEADDR for IPPROTO_UDP When UDP is used as protocol (proto=IPPROTO_DUP), then we should not set SO_REUSEADDR in the socket option. Because if we do, we allow two processes to bind on the same UDP port. The errornous situation will be undetectable to both applications. So lets only set SO_REUSEADDR when we do not use UDP. - Add check if we use UDP, if yes do not set SO_REUSEADDR Change-Id: I4a8ffb8d598aca88801a4a0322944d7cdd8d4047 Related: OS#3441 --- src/socket.c | 58 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/socket.c b/src/socket.c index 0a4e34cd..210dbf96 100644 --- a/src/socket.c +++ b/src/socket.c @@ -209,16 +209,20 @@ int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto, if (sfd < 0) continue; - rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)); - if (rc < 0) { - LOGP(DLGLOBAL, LOGL_ERROR, - "cannot setsockopt socket:" - " %s:%u: %s\n", - local_host, local_port, strerror(errno)); - close(sfd); - continue; + if (proto != IPPROTO_UDP) { + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); + if (rc < 0) { + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt socket:" + " %s:%u: %s\n", + local_host, local_port, + strerror(errno)); + close(sfd); + continue; + } } + if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == -1) { LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket: %s:%u: %s\n", local_host, local_port, strerror(errno)); @@ -345,15 +349,17 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, continue; } } else { - rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)); - if (rc < 0) { - LOGP(DLGLOBAL, LOGL_ERROR, - "cannot setsockopt socket:" - " %s:%u: %s\n", - host, port, strerror(errno)); - close(sfd); - continue; + if (proto != IPPROTO_UDP) { + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); + if (rc < 0) { + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt socket:" + " %s:%u: %s\n", + host, port, strerror(errno)); + close(sfd); + continue; + } } if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == -1) { LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket:" @@ -373,13 +379,15 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, return -ENODEV; } - rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (rc < 0) { - LOGP(DLGLOBAL, LOGL_ERROR, - "cannot setsockopt socket: %s:%u: %s\n", host, port, - strerror(errno)); - close(sfd); - sfd = -1; + if (proto != IPPROTO_UDP) { + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (rc < 0) { + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt socket: %s:%u: %s\n", host, + port, strerror(errno)); + close(sfd); + sfd = -1; + } } rc = osmo_sock_init_tail(sfd, type, flags); -- cgit v1.2.3 From 7ecb034f87500271ed4562b8db8185be726bd3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Redon?= Date: Sat, 4 Aug 2018 17:23:07 +0200 Subject: comp128v23 (minor): update original code site and author I was contacted by the (previously unknown) author who provided the new location of the original code. Change-Id: I2dabab20ad018ce473817986bdb250131c010bf1 --- src/gsm/comp128v23.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gsm/comp128v23.c b/src/gsm/comp128v23.c index 68f4b2a3..550f6a49 100644 --- a/src/gsm/comp128v23.c +++ b/src/gsm/comp128v23.c @@ -1,8 +1,10 @@ /*! \file comp128v23.c * COMP128 version 2 and 3 implementation, common algorithm used for GSM Authentication (A3/A8). * - * This code is a C conversion of the original code from - * http://www.hackingprojects.net/ + * This code is a C conversion of the original code by Tamas Jos from: + * - original (out of service): http://www.hackingprojects.net/ + * - original (archive): https://web.archive.org/web/20130730113347/http://www.hackingprojects.net/ + * - new site: https://github.com/skelsec/COMP128 */ /* * (C) 2013 by Kévin Redon -- cgit v1.2.3 From 893e49e99359fb80b25aa3ba5e1c8f03b07e66a3 Mon Sep 17 00:00:00 2001 From: Mykola Shchetinin Date: Fri, 3 Aug 2018 16:44:07 +0300 Subject: vty/vty.c: fix bug in vty_config_write the vty_config_write function should write: line vty login to the configuration file when the login is enabled. Otherwise after saving the configuration the next login will be performed without password checking (password_check variable will be 0 though it must be 1) Change-Id: I39050b6bf617dac10d3fccc3106f67bdcca1d05a --- src/vty/vty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vty/vty.c b/src/vty/vty.c index aab0607d..ad535371 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -1694,6 +1694,8 @@ static int vty_config_write(struct vty *vty) /* login */ if (!password_check) vty_out(vty, " no login%s", VTY_NEWLINE); + else + vty_out(vty, " login%s", VTY_NEWLINE); /* bind */ if (vty_bind_addr && (strcmp(vty_bind_addr, VTY_BIND_ADDR_DEFAULT) != 0)) -- cgit v1.2.3 From 3fc4616224db31d4c4b14d919dd5c719d4ab19f1 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 3 Aug 2018 03:45:06 +0700 Subject: gsm/gsm0480.c: prevent NULL-pointer dereference Change-Id: I444d95941837458b46e581298f76f3a9926c8552 --- src/gsm/gsm0480.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 2d2df4ad..5b51c754 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -880,7 +880,11 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const */ struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code) { - struct msgb *msg = gsm0480_msgb_alloc_name("TS 04.80 ReturnError"); + struct msgb *msg; + + msg = gsm0480_msgb_alloc_name("TS 04.80 ReturnError"); + if (!msg) + return NULL; /* First insert the problem code */ msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code); @@ -906,7 +910,11 @@ struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code) */ struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t problem_code) { - struct msgb *msg = gsm0480_msgb_alloc_name("TS 04.80 Reject"); + struct msgb *msg; + + msg = gsm0480_msgb_alloc_name("TS 04.80 Reject"); + if (!msg) + return NULL; /* First insert the problem code */ msgb_push_TLV1(msg, problem_tag, problem_code); -- cgit v1.2.3 From 39a36d01932867f780474f4b17bf42224cd57edb Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 3 Aug 2018 03:52:16 +0700 Subject: gsm/gsm0480.c: use the local msgb allocator Change-Id: I23b4b0e1c237b9b27c1db1c9a824b5329d41a38b --- src/gsm/gsm0480.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 5b51c754..df640b8e 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -131,7 +131,7 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char * uint8_t *seq_len_ptr, *ussd_len_ptr, *data; int len; - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + msg = gsm0480_msgb_alloc_name("TS 04.80 USSD Notify"); if (!msg) return NULL; @@ -177,7 +177,7 @@ struct msgb *gsm0480_create_notifySS(const char *text) if (len < 1 || len > 160) return NULL; - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80"); + msg = gsm0480_msgb_alloc_name("TS 04.80 NotifySS"); if (!msg) return NULL; @@ -962,7 +962,7 @@ struct msgb *gsm0480_create_ussd_release_complete(void) { struct msgb *msg; - msg = msgb_alloc_headroom(1024, 128, "GSM 04.80 USSD REL COMPL"); + msg = gsm0480_msgb_alloc_name("TS 04.80 USSD REL COMPL"); if (!msg) return NULL; -- cgit v1.2.3 From 30cfeeb4a0a3992b55a48c3ccefc91f727ef079e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Fri, 3 Aug 2018 05:44:00 +0700 Subject: libosmogsm: (re)introduce gsm48_push_l3hdr() There was gsm0480_l3hdr_push() declared in a header file, but not exposed in 'libosmogsm.map'. Furthermore, for some reason it was a part of GSM 04.80 API, what is not actually correct. Let's rename this symbol, and properly expose it as a part of the GSM 04.08 API. Also, let's introduce an auxiliary wrapper for messages, where the transaction identifier is required (see GSM 04.07, section 11.2.3.1.2). Change-Id: I8a045efe8335d83fcbe8d43eb180972e3b1d9dda --- TODO-RELEASE | 3 +++ include/osmocom/gsm/gsm0480.h | 3 --- include/osmocom/gsm/gsm48.h | 8 ++++++++ src/gsm/gsm0411_utils.c | 3 +-- src/gsm/gsm0480.c | 35 ++++++++++++++++------------------- src/gsm/gsm48.c | 20 ++++++++++++++++++++ src/gsm/libosmogsm.map | 1 + 7 files changed, 49 insertions(+), 24 deletions(-) diff --git a/TODO-RELEASE b/TODO-RELEASE index 8ccfa491..64833d23 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,6 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libosmogsm gsm0480_l3hdr_push() removed from gsm/gsm0480.h (was not exposed) +libosmogsm gsm48_push_l3hdr() (re)introduced in gsm/gsm48.h (GSM 04.08 API) +libosmogsm gsm48_push_l3hdr_tid() a wrapper around gsm48_push_l3hdr() diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h index 246f4b3b..827464e1 100644 --- a/include/osmocom/gsm/gsm0480.h +++ b/include/osmocom/gsm/gsm0480.h @@ -121,6 +121,3 @@ struct msgb *gsm0480_create_ussd_release_complete(void); int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id); int gsm0480_wrap_facility(struct msgb *msg); - -struct gsm48_hdr *gsm0480_l3hdr_push(struct msgb *msg, uint8_t proto_discr, - uint8_t msg_type); diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index cfae83da..2b14e6cd 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -4,6 +4,8 @@ #include +#include + #include #include #include @@ -63,3 +65,9 @@ void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc) OSMO_DEPRECATED("Use osmo_plmn_to_bcd() instead, to not lose leading zeros in the MNC"); void gsm48_mcc_mnc_from_bcd(uint8_t *bcd_src, uint16_t *mcc, uint16_t *mnc) OSMO_DEPRECATED("Use osmo_plmn_from_bcd() instead, to not lose leading zeros in the MNC"); + +struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg, + uint8_t pdisc, uint8_t msg_type); + +#define gsm48_push_l3hdr_tid(msg, pdisc, tid, msg_type) \ + gsm48_push_l3hdr(msg, (pdisc & 0x0f) | (tid << 4), msg_type) diff --git a/src/gsm/gsm0411_utils.c b/src/gsm/gsm0411_utils.c index 53d37a43..ccefe546 100644 --- a/src/gsm/gsm0411_utils.c +++ b/src/gsm/gsm0411_utils.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -354,7 +353,7 @@ int gsm411_push_cp_header(struct msgb *msg, uint8_t proto, uint8_t trans, uint8_t msg_type) { /* Outgoing proto_discr needs the highest bit set */ - gsm0480_l3hdr_push(msg, proto | (trans << 4), msg_type); + gsm48_push_l3hdr_tid(msg, proto, trans, msg_type); return 0; } diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index df640b8e..7756ecba 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -25,6 +25,7 @@ * */ +#include #include #include @@ -863,10 +864,11 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY); /* And finally pre-pend the L3 header */ - gsm0480_l3hdr_push(msg, - GSM48_PDISC_NC_SS | trans_id - | (1<<7) /* TI direction = 1 */, - GSM0480_MTYPE_RELEASE_COMPLETE); + gsm48_push_l3hdr_tid(msg, GSM48_PDISC_NC_SS, + /* FIXME: TI direction is always 1 ?!? */ + trans_id | (1 << 7), + GSM0480_MTYPE_RELEASE_COMPLETE); + return msg; } @@ -932,17 +934,6 @@ struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t prob return msg; } - -struct gsm48_hdr *gsm0480_l3hdr_push(struct msgb *msg, uint8_t proto_discr, - uint8_t msg_type) -{ - struct gsm48_hdr *gh; - gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); - gh->proto_discr = proto_discr; - gh->msg_type = msg_type; - return gh; -} - struct msgb *gsm0480_create_ussd_notify(int level, const char *text) { struct msgb *msg; @@ -954,7 +945,11 @@ struct msgb *gsm0480_create_ussd_notify(int level, const char *text) gsm0480_wrap_invoke(msg, GSM0480_OP_CODE_USS_NOTIFY, 0); gsm0480_wrap_facility(msg); - gsm0480_l3hdr_push(msg, GSM48_PDISC_NC_SS, GSM0480_MTYPE_REGISTER); + /* And finally pre-pend the L3 header */ + gsm48_push_l3hdr(msg, GSM48_PDISC_NC_SS, + /* FIXME: no transactionID?!? */ + GSM0480_MTYPE_REGISTER); + return msg; } @@ -966,8 +961,10 @@ struct msgb *gsm0480_create_ussd_release_complete(void) if (!msg) return NULL; - /* FIXME: should this set trans_id and TI direction flag? */ - gsm0480_l3hdr_push(msg, GSM48_PDISC_NC_SS, - GSM0480_MTYPE_RELEASE_COMPLETE); + /* And finally pre-pend the L3 header */ + gsm48_push_l3hdr(msg, GSM48_PDISC_NC_SS, + /* FIXME: no transactionID?!? */ + GSM0480_MTYPE_RELEASE_COMPLETE); + return msg; } diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index b4892dea..136b9375 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -1024,4 +1024,24 @@ const struct value_string gsm48_reject_value_names[] = { { 0, NULL } }; +/*! Wrap a given \ref msg with \ref gsm48_hdr structure + * \param[out] msg A message to be wrapped + * \param[in] pdisc GSM TS 04.07 protocol discriminator 1/2, + * sub-pdisc, trans_id or skip_ind 1/2, + * see section 11.2.3.1 for details + * \param[in] msg_type GSM TS 04.08 message type + * @return pointer to pushed header within \ref msg + */ +struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg, + uint8_t pdisc, uint8_t msg_type) +{ + struct gsm48_hdr *gh; + + gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh)); + gh->proto_discr = pdisc; + gh->msg_type = msg_type; + + return gh; +} + /*! @} */ diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 2bb9d97c..1da398c1 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -241,6 +241,7 @@ gsm411_rp_state_names; gsm414_msgt_names; +gsm48_push_l3hdr; gsm48_att_tlvdef; gsm48_cc_msg_name; gsm48_rr_msg_name; -- cgit v1.2.3 From d14eccd1a70ad721e01346c8351ae90f038b3570 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 6 Aug 2018 11:08:00 +0200 Subject: debian/rules: Don't overwrite .tarball-version The .tarball-version file should contain the *source version* uniquely identifying the git commit, and not the Debian package name. With https://gerrit.osmocom.org/#/c/osmo-ci/+/10343/ there is a correct .tarball-version file in the .tar.xz of the nightly source packages. Change-Id: Ibeb6d273e2d26f37a36cbde4a948ce95395491f8 Related: OS#3449 --- debian/rules | 4 ---- 1 file changed, 4 deletions(-) diff --git a/debian/rules b/debian/rules index 6eb7346c..a9d961c7 100755 --- a/debian/rules +++ b/debian/rules @@ -25,10 +25,6 @@ override_dh_install: override_dh_auto_test: dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false) -override_dh_autoreconf: - echo $(VERSION) > .tarball-version - dh_autoreconf - override_dh_auto_configure: dh_auto_configure -- --enable-static -- cgit v1.2.3 From acc0a070c770eb16aba8ef93780eda5365057b6c Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Tue, 7 Aug 2018 11:22:28 +0200 Subject: bssgp: introduce flush queue functions To reset the state of BSSGP allow to flush the BSSGP queues. When testing (with TTCN3) the test object should be resetted between each test. Introduce the functions: bssgp_fc_flush_queue() - flushs a single flow control object bssgp_flush_all_queues() - flushs queues of all BSSGP connections Change-Id: I29b6ad6742ddf9b0b58b4af37d9a1cf18e019325 --- include/osmocom/gprs/gprs_bssgp.h | 3 +++ src/gb/gprs_bssgp.c | 28 ++++++++++++++++++++++++++++ src/gb/libosmogb.map | 2 ++ 3 files changed, 33 insertions(+) diff --git a/include/osmocom/gprs/gprs_bssgp.h b/include/osmocom/gprs/gprs_bssgp.h index 2dead692..400c3e00 100644 --- a/include/osmocom/gprs/gprs_bssgp.h +++ b/include/osmocom/gprs/gprs_bssgp.h @@ -207,6 +207,9 @@ int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg, int bssgp_fc_ms_init(struct bssgp_flow_control *fc_ms, uint16_t bvci, uint16_t nsei, uint32_t max_queue_depth); +void bssgp_flush_all_queues(); +void bssgp_fc_flush_queue(struct bssgp_flow_control *fc); + /* gprs_bssgp_vty.c */ int bssgp_vty_init(void); void bssgp_set_log_ss(int ss); diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index 5dfce16c..3b9fbf95 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -1263,3 +1263,31 @@ void bssgp_set_log_ss(int ss) { DBSSGP = ss; } + +/*! + * \brief Flush the queue of the bssgp_flow_control + * \param[in] The flow control object which holds the queue. + */ +void bssgp_fc_flush_queue(struct bssgp_flow_control *fc) +{ + struct bssgp_fc_queue_element *element, *tmp; + + llist_for_each_entry_safe(element, tmp, &fc->queue, list) { + msgb_free(element->msg); + llist_del(&element->list); + talloc_free(element); + } +} + +/*! + * \brief Flush the queues of all BSSGP contexts. + */ +void bssgp_flush_all_queues() +{ + struct bssgp_bvc_ctx *bctx; + + llist_for_each_entry(bctx, &bssgp_bvc_ctxts, list) { + if (bctx->fc) + bssgp_fc_flush_queue(bctx->fc); + } +} diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index d56e6514..ec69670e 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -6,6 +6,8 @@ bssgp_pdu_str; bssgp_fc_in; bssgp_fc_init; bssgp_fc_ms_init; +bssgp_fc_flush_queue; +bssgp_flush_all_queues; bssgp_msgb_alloc; bssgp_msgb_copy; bssgp_msgb_tlli_put; -- cgit v1.2.3 From 0b6fcb0349a608023d971d576fe2ee6af18dcb45 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 16 Aug 2018 19:05:19 +0200 Subject: signal: Introduce API osmo_signal_talloc_ctx_init Otherwise applications need to use "extern void* tall_sigh_ctx" and set it manually (that symbol is not exported in any header file) or end up allocating struct signal_handler into the NULL talloc ctx. API created in a similar way as already existing msgb_talloc_ctx_init(), but without the pool_size because it's not considered necessary in this case. Change-Id: Id58ca18eb826b8f4183a7cf0dbb2b38cba702a09 --- include/osmocom/core/signal.h | 1 + src/signal.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/osmocom/core/signal.h b/include/osmocom/core/signal.h index ae78f152..449b9762 100644 --- a/include/osmocom/core/signal.h +++ b/include/osmocom/core/signal.h @@ -34,6 +34,7 @@ typedef int osmo_signal_cbfn(unsigned int subsys, unsigned int signal, void *han /* Management */ +void *osmo_signal_talloc_ctx_init(void *root_ctx); int osmo_signal_register_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data); void osmo_signal_unregister_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data); diff --git a/src/signal.c b/src/signal.c index 745d7c38..188876b8 100644 --- a/src/signal.c +++ b/src/signal.c @@ -46,6 +46,15 @@ struct signal_handler { void *data; }; +/*! Initialize a signal_handler talloc context for \ref osmo_signal_register_handler. + * Create a talloc context called "osmo_signal". + * \param[in] root_ctx talloc context used as parent for the new "osmo_signal" ctx. + * \returns the new osmo_signal talloc context, e.g. for reporting + */ +void *osmo_signal_talloc_ctx_init(void *root_ctx) { + tall_sigh_ctx = talloc_named_const(tall_sigh_ctx, 0, "osmo_signal"); + return tall_sigh_ctx; +} /*! Register a new signal handler * \param[in] subsys Subsystem number -- cgit v1.2.3 From 8ce6f488b6e6bf091e53f49f20bb4f43de82f1d3 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 17 Aug 2018 10:33:57 +0200 Subject: msgb: Introduce msgb_{de,en}queue_count APIs It's a common pattern having a list of msgb and having to maintain its size (for instance, to limit the maximum size of the list). Having the counter updated at the same time that the msgb is enqueued or dequeued helps avoiding introducing new bugs by forgetting to update the size counter at the right places. Change-Id: I33b501e89a8f29e4aa121696bcbb13d4b83db40f --- include/osmocom/core/msgb.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index a8dc205b..b1cb6ec7 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -81,6 +81,40 @@ static inline void msgb_queue_free(struct llist_head *queue) while ((msg = msgb_dequeue(queue))) msgb_free(msg); } +/*! Enqueue message buffer to tail of a queue and increment queue size counter + * \param[in] queue linked list header of queue + * \param[in] msg message buffer to be added to the queue + * \param[in] count pointer to variable holding size of the queue + * + * The function will append the specified message buffer \a msg to the queue + * implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count, + * then increment \a count + */ +static inline void msgb_enqueue_count(struct llist_head *queue, struct msgb *msg, + unsigned int *count) +{ + msgb_enqueue(queue, msg); + (*count)++; +} + +/*! Dequeue message buffer from head of queue and decrement queue size counter + * \param[in] queue linked list header of queue + * \param[in] count pointer to variable holding size of the queue + * \returns message buffer (if any) or NULL if queue empty + * + * The function will remove the first message buffer from the queue + * implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count, + * and decrement \a count, all if queue is not empty. + */ +static inline struct msgb *msgb_dequeue_count(struct llist_head *queue, + unsigned int *count) +{ + struct msgb *msg = msgb_dequeue(queue); + if (msg) + (*count)--; + return msg; +} + #ifdef MSGB_DEBUG #include #define MSGB_ABORT(msg, fmt, args ...) do { \ -- cgit v1.2.3 From b3a9820bfc0723626ba647d096f528aed14d7009 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 20 Aug 2018 15:51:24 +0200 Subject: vty: Makefile: Fix LIBVERSION typo introduced in 0.12.0 release Setting age to 5 is cleary an error, it should be increment by one instead as APIs were added 0.11->0.12 and none modified or removed. Change-Id: I3b3bc808349bc2f949ef9eef64f39e7202ddf946 --- src/vty/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vty/Makefile.am b/src/vty/Makefile.am index 5d0ded7b..49813c51 100644 --- a/src/vty/Makefile.am +++ b/src/vty/Makefile.am @@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=5:0:5 +LIBVERSION=5:0:1 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall $(TALLOC_CFLAGS) -- cgit v1.2.3 From 983dcb9af330a1a401e2d9e388183932f29b7bac Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 20 Aug 2018 12:33:22 +0200 Subject: use __FILE__, not __BASE_FILE__ The intention was to use the file's basename, but __BASE_FILE__ means "the root file that is being parsed and contains #include statements". If we had a function using __BASE_FILE__ and that was defined in an #included file, __BASE_FILE__ would indicate the first file where the #include is, and not the file where the function is defined. __BASE_FILE__ works for us because we don't ever include function definitions that log something, so __BASE_FILE__ always coincides with __FILE__ for our logging; but still __BASE_FILE__ is semantically the wrong constant. Related: OS#2740 Change-Id: Ibc1d3746f1876ac42d6b1faf0e5f83bd2283cdcc --- include/osmocom/core/fsm.h | 10 +++++----- include/osmocom/core/logging.h | 12 ++++++------ include/osmocom/core/utils.h | 2 +- include/osmocom/gsm/mncc.h | 2 +- src/gb/gprs_ns.c | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h index 9e1062f5..54bbad5d 100644 --- a/include/osmocom/core/fsm.h +++ b/include/osmocom/core/fsm.h @@ -178,7 +178,7 @@ static inline const char *osmo_fsm_inst_state_name(struct osmo_fsm_inst *fi) */ #define osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T) \ _osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T, \ - __BASE_FILE__, __LINE__) + __FILE__, __LINE__) int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state, unsigned long timeout_secs, int T, const char *file, int line); @@ -194,7 +194,7 @@ int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state, */ #define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \ _osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \ - __BASE_FILE__, __LINE__) + __FILE__, __LINE__) int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state, const char *file, int line); @@ -205,7 +205,7 @@ int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_s * purposes. See there for documentation. */ #define osmo_fsm_inst_dispatch(fi, event, data) \ - _osmo_fsm_inst_dispatch(fi, event, data, __BASE_FILE__, __LINE__) + _osmo_fsm_inst_dispatch(fi, event, data, __FILE__, __LINE__) int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data, const char *file, int line); @@ -216,7 +216,7 @@ int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data * See there for documentation. */ #define osmo_fsm_inst_term(fi, cause, data) \ - _osmo_fsm_inst_term(fi, cause, data, __BASE_FILE__, __LINE__) + _osmo_fsm_inst_term(fi, cause, data, __FILE__, __LINE__) void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause, void *data, const char *file, int line); @@ -228,7 +228,7 @@ void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi, * purposes. See there for documentation. */ #define osmo_fsm_inst_term_children(fi, cause, data) \ - _osmo_fsm_inst_term_children(fi, cause, data, __BASE_FILE__, __LINE__) + _osmo_fsm_inst_term_children(fi, cause, data, __FILE__, __LINE__) void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause, void *data, diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index e68f6181..3cae63da 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -55,17 +55,17 @@ void logp(int subsys, const char *file, int line, int cont, const char *format, #define LOGPC(ss, level, fmt, args...) \ do { \ if (log_check_level(ss, level)) \ - logp2(ss, level, __BASE_FILE__, __LINE__, 1, fmt, ##args); \ + logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args); \ } while(0) /*! Log through the Osmocom logging framework with explicit source. - * If caller_file is passed as NULL, __BASE_FILE__ and __LINE__ are used + * If caller_file is passed as NULL, __FILE__ and __LINE__ are used * instead of caller_file and caller_line (so that this macro here defines * both cases in the same place, and to catch cases where callers fail to pass * a non-null filename string). * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) * \param[in] level logging level (e.g. \ref LOGL_NOTICE) - * \param[in] caller_file caller's source file string (e.g. __BASE_FILE__) + * \param[in] caller_file caller's source file string (e.g. __FILE__) * \param[in] caller_line caller's source line nr (e.g. __LINE__) * \param[in] fmt format string * \param[in] args variable argument list @@ -74,13 +74,13 @@ void logp(int subsys, const char *file, int line, int cont, const char *format, LOGPSRCC(ss, level, caller_file, caller_line, 0, fmt, ##args) /*! Log through the Osmocom logging framework with explicit source. - * If caller_file is passed as NULL, __BASE_FILE__ and __LINE__ are used + * If caller_file is passed as NULL, __FILE__ and __LINE__ are used * instead of caller_file and caller_line (so that this macro here defines * both cases in the same place, and to catch cases where callers fail to pass * a non-null filename string). * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) * \param[in] level logging level (e.g. \ref LOGL_NOTICE) - * \param[in] caller_file caller's source file string (e.g. __BASE_FILE__) + * \param[in] caller_file caller's source file string (e.g. __FILE__) * \param[in] caller_line caller's source line nr (e.g. __LINE__) * \param[in] cont continuation (1) or new line (0) * \param[in] fmt format string @@ -92,7 +92,7 @@ void logp(int subsys, const char *file, int line, int cont, const char *format, if (caller_file) \ logp2(ss, level, caller_file, caller_line, cont, fmt, ##args); \ else \ - logp2(ss, level, __BASE_FILE__, __LINE__, cont, fmt, ##args); \ + logp2(ss, level, __FILE__, __LINE__, cont, fmt, ##args); \ }\ } while(0) diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index dd4461cc..e2d51349 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -78,7 +78,7 @@ do { \ */ #define OSMO_ASSERT(exp) \ if (!(exp)) { \ - osmo_panic("Assert failed %s %s:%d\n", #exp, __BASE_FILE__, __LINE__); \ + osmo_panic("Assert failed %s %s:%d\n", #exp, __FILE__, __LINE__); \ } /*! duplicate a string using talloc and release its prior content (if any) diff --git a/include/osmocom/gsm/mncc.h b/include/osmocom/gsm/mncc.h index 6b94d469..7e7d12c3 100644 --- a/include/osmocom/gsm/mncc.h +++ b/include/osmocom/gsm/mncc.h @@ -90,7 +90,7 @@ void _osmo_mncc_log(int subsys, int level, const char *file, int line, const cha const uint8_t *msg, unsigned int len); #define osmo_mncc_log(ss, level, prefix, msg, len) \ - _osmo_mncc_log(ss, level, __BASE_FILE__, __LINE__, prefix, msg, len); + _osmo_mncc_log(ss, level, __FILE__, __LINE__, prefix, msg, len); extern const struct value_string osmo_mncc_names[]; static inline const char *osmo_mncc_name(uint32_t msg_type) { diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 75c31415..9b7cc056 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -87,8 +87,8 @@ #include "common_vty.h" -#define ns_set_state(ns_, st_) ns_set_state_with_log(ns_, st_, false, __BASE_FILE__, __LINE__) -#define ns_set_remote_state(ns_, st_) ns_set_state_with_log(ns_, st_, true, __BASE_FILE__, __LINE__) +#define ns_set_state(ns_, st_) ns_set_state_with_log(ns_, st_, false, __FILE__, __LINE__) +#define ns_set_remote_state(ns_, st_) ns_set_state_with_log(ns_, st_, true, __FILE__, __LINE__) #define ns_mark_blocked(ns_) ns_set_state(ns_, (ns_)->state | NSE_S_BLOCKED) #define ns_mark_unblocked(ns_) ns_set_state(ns_, (ns_)->state & (~NSE_S_BLOCKED)); -- cgit v1.2.3 From 8a757d20f714909264eb76d400de529cb75b9fe0 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 22 Aug 2018 14:12:01 +0200 Subject: ipa: Document ipa_msg_recv* functions Change-Id: Ie81e9dd9f9936a414e7cebb2bccffa6f42a302a7 --- src/gsm/ipa.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/gsm/ipa.c b/src/gsm/ipa.c index 508cc13d..d423c262 100644 --- a/src/gsm/ipa.c +++ b/src/gsm/ipa.c @@ -528,6 +528,9 @@ void ipa_prepend_header(struct msgb *msg, int proto) #ifdef HAVE_SYS_SOCKET_H #include +/*! Read one ipa message from socket fd without caching not fully received + * messages. See \ref ipa_msg_recv_buffered for further information. + */ int ipa_msg_recv(int fd, struct msgb **rmsg) { int rc = ipa_msg_recv_buffered(fd, rmsg, NULL); @@ -538,6 +541,25 @@ int ipa_msg_recv(int fd, struct msgb **rmsg) return rc; } +/*! Read one ipa message from socket fd or store part if still not fully received. + * \param[in] fd The fd for the socket to read from. + * \param[out] rmsg internally allocated msgb containing a fully received ipa message. + * \param[inout] tmp_msg internally allocated msgb caching data for not yet fully received message. + * + * As ipa can run on top of stream based protocols such as TCP, there's the + * possibility that such lower layers split ipa messages in several low level + * packets. If a low layer packet is received containing several ipa frames, + * this function will pull from the socket and return only the first one + * available in the stream. As the socket will remain with data, it will + * trigger again during next select() and then this function will fetch the + * next ipa message, and so on. + * + * \returns -EAGAIN and allocated tmp_msg if message was not yet fully + * received. Other negative values indicate an error and cached msgb will be + * freed. 0 if socket is found dead. Positive value indicating l2 msgb len and + * rmsg pointing to internally allocated msgb containing the ipa frame on + * scucess. + */ int ipa_msg_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg) { struct msgb *msg = tmp_msg ? *tmp_msg : NULL; -- cgit v1.2.3 From 73196e77fb28d71f5ab536d4e6265cfcbb169b3d Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 23 Aug 2018 20:11:50 +0200 Subject: socket: add flag to enforce SO_REUSEADDR on UDP sockets When IPPROTO_UDP is used then SO_REUSEADDR omitted since UDP is connection less we do not have to wait until lingering connections time out. There were also negative effects such as that two applicatications could use the same UDP port, normally one of the two applications would get an error, but with SO_REUSEADDR this is supressed. However, there are applications (UDP MULTICAST) where two applications must be able to use the same port. In the osmocom project those are osmo-bts-virtual, virtphy and gsmtap in general. Lets introduce a flag that the API user can supply in order to have SO_REUSEADDR applied. - Add new flag OSMO_SOCK_F_UDP_REUSEADDR Change-Id: I94aaf6d5224ab23bde5ea5c4a83569b6145ab32b Related: OS#3497 --- include/osmocom/core/socket.h | 2 ++ src/socket.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index 20515b99..f23a2436 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -24,6 +24,8 @@ struct osmo_fd; #define OSMO_SOCK_F_NO_MCAST_LOOP (1 << 3) /*! disable receiving all multiast even for non-subscribed groups */ #define OSMO_SOCK_F_NO_MCAST_ALL (1 << 4) +/*! use SO_REUSEADDR on UDP ports (required for multicast) */ +#define OSMO_SOCK_F_UDP_REUSEADDR (1 << 5) int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, const char *host, uint16_t port, unsigned int flags); diff --git a/src/socket.c b/src/socket.c index 210dbf96..7e7f6d96 100644 --- a/src/socket.c +++ b/src/socket.c @@ -209,7 +209,7 @@ int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto, if (sfd < 0) continue; - if (proto != IPPROTO_UDP) { + if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) { rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (rc < 0) { @@ -349,7 +349,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, continue; } } else { - if (proto != IPPROTO_UDP) { + if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) { rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (rc < 0) { @@ -379,7 +379,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, return -ENODEV; } - if (proto != IPPROTO_UDP) { + if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) { rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (rc < 0) { LOGP(DLGLOBAL, LOGL_ERROR, -- cgit v1.2.3 From b8a91625dd974f596214646da345d9d649f4dae3 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 23 Aug 2018 20:18:55 +0200 Subject: gsmtap_util: make sure SO_REUSEADDR is applied for GSMTAP When gsmtap adding a new sink it does not supply OSMO_SOCK_F_UDP_REUSEADDR in order to have SO_REUSEADDR applied. In most cases, the gsmtap sink is just receiving packets to toss them immediately, so having one of them is sufficient. However, in other use cases - particularly virt_phy - we actually want to receve and process GSMTAP messages via multicast Applying SO_REUSEADDR (like we did before disabling it globally for UDP in I4a8ffb8d598aca88801a4a0322944d7cdd8d4047 on August 1st) resolves the issue. Change-Id: I1399a428467ca12f1564a14eb8ffb294d4f59874 Related: OS#3497 --- src/gsmtap_util.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index b21c690b..385b4672 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -254,7 +254,9 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd) if (osmo_sockaddr_is_local((struct sockaddr *)&ss, ss_len) == 1) { rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM, - IPPROTO_UDP, OSMO_SOCK_F_BIND); + IPPROTO_UDP, + OSMO_SOCK_F_BIND | + OSMO_SOCK_F_UDP_REUSEADDR); if (rc >= 0) return rc; } -- cgit v1.2.3 From 77ae45d22f49ee712850e3b5d4c16112dca134d0 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 27 Aug 2018 20:32:36 +0200 Subject: log: add 'last' option to 'logging print file' Allow printing the source file information *after* the log information. Add target->print_filename_pos, log_set_print_filename_pos() and enum log_filename_pos, and the optional 'last' keyword to the 'logging print file' vty command. (An enum in case we want to add other positions later.) Rationale: on log lines, the logging context is usually printed first in the logging text. Without the source file information, this logging context pretty much aligns in an easily readable way. When adding the source file information, each line's logging context info is shifted right by a pretty much random amount and it is hard to spot recurring logging contexts. One solution is to switch off source file info, of course, but that's not an option when actively hacking on bugs and new features. For example, it is unnecessarily hard to spot lchan FSM related log lines in this osmo-bsc log snippet: DRSL NOTICE mgw_endpoint_fsm.c:603 mgw-endpoint(conn0){WAIT_MGW_RESPONSE}: Freeing instance DRSL NOTICE fsm.c:381 mgw-endpoint(conn0){WAIT_MGW_RESPONSE}: Deallocated DMSC NOTICE mgw_endpoint_fsm.c:603 SUBSCR_CONN(conn0){CLEARING}: Received Event FORGET_MGW_ENDPOINT DCHAN DEBUG lchan_rtp_fsm.c:741 lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: Received Event LCHAN_EV_RTP_RELEASED DCHAN DEBUG lchan_rtp_fsm.c:520 lchan_rtp(0-0-1-TCH_F-0){ROLLBACK}: Freeing instance DCHAN DEBUG fsm.c:381 lchan_rtp(0-0-1-TCH_F-0){ROLLBACK}: Deallocated DCHAN DEBUG lchan_rtp_fsm.c:520 lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: Received Event LCHAN_EV_RTP_RELEASED DCHAN DEBUG lchan_fsm.c:1232 lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: state_chg to WAIT_RF_RELEASE_ACK DRSL NOTICE handover_fsm.c:762 handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Terminating (cause = OSMO_FSM_TERM_REGULAR) DRSL NOTICE handover_fsm.c:762 handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Freeing instance DRSL NOTICE fsm.c:381 handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Deallocated DCHAN DEBUG lchan_fsm.c:1196 lchan(0-0-1-TCH_F-0){WAIT_RF_RELEASE_ACK}: state_chg to BORKEN DCHAN DEBUG lchan_fsm.c:354 lchan(0-0-1-TCH_F-0){BORKEN}: (type=TCH_F) Clearing lchan state DLMGCP DEBUG mgcp_client.c:741 Tx MGCP msg to MGCP GW: 'DLCX 3 2@mgw MGCP 1.0' DLMGCP DEBUG mgcp_client.c:743 Sending msg to MGCP GW size: 66 DRLL NOTICE mgcp_client_fsm.c:422 MGCP_CONN(to-BTS){ST_DLCX_RESP}: Received Event EV_DLCX_RESP Placing the source file info behind the log text makes it much easier to follow, while the source file info is still available: DRSL NOTICE mgw-endpoint(conn0){WAIT_MGW_RESPONSE}: Freeing instance (mgw_endpoint_fsm.c:603) DRSL NOTICE mgw-endpoint(conn0){WAIT_MGW_RESPONSE}: Deallocated (fsm.c:381) DMSC NOTICE SUBSCR_CONN(conn0){CLEARING}: Received Event FORGET_MGW_ENDPOINT (mgw_endpoint_fsm.c:603) DCHAN DEBUG lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: Received Event LCHAN_EV_RTP_RELEASED (lchan_rtp_fsm.c:741) DCHAN DEBUG lchan_rtp(0-0-1-TCH_F-0){ROLLBACK}: Freeing instance (lchan_rtp_fsm.c:520) DCHAN DEBUG lchan_rtp(0-0-1-TCH_F-0){ROLLBACK}: Deallocated (fsm.c:381) DCHAN DEBUG lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: Received Event LCHAN_EV_RTP_RELEASED (lchan_rtp_fsm.c:520) DCHAN DEBUG lchan(0-0-1-TCH_F-0){WAIT_RLL_RTP_ESTABLISH}: state_chg to WAIT_RF_RELEASE_ACK (lchan_fsm.c:1232) DRSL NOTICE handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Terminating (cause = OSMO_FSM_TERM_REGULAR) (handover_fsm.c:745) DRSL NOTICE handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Freeing instance (handover_fsm.c:745) DRSL NOTICE handover(interBSCin_conn0){WAIT_RR_HO_DETECT}: Deallocated (fsm.c:381) DCHAN DEBUG lchan(0-0-1-TCH_F-0){WAIT_RF_RELEASE_ACK}: state_chg to BORKEN (lchan_fsm.c:1196) DCHAN DEBUG lchan(0-0-1-TCH_F-0){BORKEN}: (type=TCH_F) Clearing lchan state (lchan_fsm.c:354) DLMGCP DEBUG Tx MGCP msg to MGCP GW: 'DLCX 3 12@mgw MGCP 1.0' (mgcp_client.c:741) DLMGCP DEBUG Sending msg to MGCP GW size: 67 (mgcp_client.c:743) DRLL NOTICE MGCP_CONN(to-BTS){ST_DLCX_RESP}: Received Event EV_DLCX_RESP (mgcp_client_fsm.c:422) Implementation: for 'last', insert source file info only when an '\n' is found at the end of the log line composition buffer, so that LOGP()...LOGPC() constructs also print source file info only when a log line actually ends. Change-Id: I393907b3c9e0cc1145e102328adad0a83ee13a9f --- include/osmocom/core/logging.h | 9 ++++++++ src/logging.c | 51 +++++++++++++++++++++++++++++++++++++----- src/vty/logging_vty.c | 10 +++++++-- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 3cae63da..8464043f 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -228,6 +228,12 @@ enum log_filename_type { LOG_FILENAME_BASENAME, }; +/*! Where on a log line source file and line should be logged. */ +enum log_filename_pos { + LOG_FILENAME_POS_HEADER_END, + LOG_FILENAME_POS_LINE_END, +}; + /*! structure representing a logging target */ struct log_target { struct llist_head entry; /*!< linked list */ @@ -313,6 +319,8 @@ struct log_target { bool print_category_hex; /* Should we print the source file and line, and in which way? */ enum log_filename_type print_filename2; + /* Where on a log line to put the source file info. */ + enum log_filename_pos print_filename_pos; }; /* use the above macros */ @@ -335,6 +343,7 @@ void log_set_print_extended_timestamp(struct log_target *target, int); void log_set_print_timestamp(struct log_target *target, int); void log_set_print_filename(struct log_target *target, int); void log_set_print_filename2(struct log_target *target, enum log_filename_type lft); +void log_set_print_filename_pos(struct log_target *target, enum log_filename_pos pos); void log_set_print_category(struct log_target *target, int); void log_set_print_category_hex(struct log_target *target, int); void log_set_print_level(struct log_target *target, int); diff --git a/src/logging.c b/src/logging.c index edb2b56a..de0f2b0f 100644 --- a/src/logging.c +++ b/src/logging.c @@ -406,27 +406,55 @@ static void _output(struct log_target *target, unsigned int subsys, goto err; OSMO_SNPRINTF_RET(ret, rem, offset, len); } + + if (target->print_filename_pos == LOG_FILENAME_POS_HEADER_END) { + switch (target->print_filename2) { + case LOG_FILENAME_NONE: + break; + case LOG_FILENAME_PATH: + ret = snprintf(buf + offset, rem, "%s:%d ", file, line); + if (ret < 0) + goto err; + OSMO_SNPRINTF_RET(ret, rem, offset, len); + break; + case LOG_FILENAME_BASENAME: + ret = snprintf(buf + offset, rem, "%s:%d ", const_basename(file), line); + if (ret < 0) + goto err; + OSMO_SNPRINTF_RET(ret, rem, offset, len); + break; + } + } + } + ret = vsnprintf(buf + offset, rem, format, ap); + if (ret < 0) + goto err; + OSMO_SNPRINTF_RET(ret, rem, offset, len); + + /* For LOG_FILENAME_POS_LAST, print the source file info only when the caller ended the log + * message in '\n'. If so, nip the last '\n' away, insert the source file info and re-append an + * '\n'. All this to allow LOGP("start..."); LOGPC("...end\n") constructs. */ + if (target->print_filename_pos == LOG_FILENAME_POS_LINE_END + && offset > 0 && buf[offset-1] == '\n') { switch (target->print_filename2) { case LOG_FILENAME_NONE: break; case LOG_FILENAME_PATH: - ret = snprintf(buf + offset, rem, "%s:%d ", file, line); + offset --; + ret = snprintf(buf + offset, rem, " (%s:%d)\n", file, line); if (ret < 0) goto err; OSMO_SNPRINTF_RET(ret, rem, offset, len); break; case LOG_FILENAME_BASENAME: - ret = snprintf(buf + offset, rem, "%s:%d ", const_basename(file), line); + offset --; + ret = snprintf(buf + offset, rem, " (%s:%d)\n", const_basename(file), line); if (ret < 0) goto err; OSMO_SNPRINTF_RET(ret, rem, offset, len); break; } } - ret = vsnprintf(buf + offset, rem, format, ap); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); if (target->use_color) { ret = snprintf(buf + offset, rem, "\033[0;m"); @@ -677,6 +705,17 @@ void log_set_print_filename2(struct log_target *target, enum log_filename_type l target->print_filename2 = lft; } +/*! Set the position where on a log line the source file info should be logged. + * \param[in] target Log target to be affected. + * \param[in] pos A LOG_FILENAME_POS_* enum value. + * LOG_FILENAME_POS_DEFAULT logs just before the caller supplied log message. + * LOG_FILENAME_POS_LAST logs only at the end of a log line, where the caller issued an '\n' to end the + */ +void log_set_print_filename_pos(struct log_target *target, enum log_filename_pos pos) +{ + target->print_filename_pos = pos; +} + /*! Enable or disable printing of the category name * \param[in] target Log target to be affected * \param[in] print_catname Enable (1) or disable (0) filenames diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 11949144..8c8a3326 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -246,12 +246,14 @@ static const struct value_string logging_print_file_args[] = { DEFUN(logging_prnt_file, logging_prnt_file_cmd, - "logging print file (0|1|basename)", + "logging print file (0|1|basename) [last]", LOGGING_STR "Log output settings\n" "Configure log message\n" "Don't prefix each log message\n" "Prefix each log message with the source file and line\n" - "Prefix each log message with the source file's basename (strip leading paths) and line\n") + "Prefix each log message with the source file's basename (strip leading paths) and line\n" + "Log source file info at the end of a log line. If omitted, log source file info just" + " before the log text.\n") { struct log_target *tgt = osmo_log_vty2tgt(vty); @@ -259,6 +261,10 @@ DEFUN(logging_prnt_file, return CMD_WARNING; log_set_print_filename2(tgt, get_string_value(logging_print_file_args, argv[0])); + if (argc > 1) + log_set_print_filename_pos(tgt, LOG_FILENAME_POS_LINE_END); + else + log_set_print_filename_pos(tgt, LOG_FILENAME_POS_HEADER_END); return CMD_SUCCESS; } -- cgit v1.2.3 From 43c266f6c6419e97d8097cb656d1aee4e3eeebea Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 28 Aug 2018 01:08:38 +0200 Subject: gsm0808: inter-bsc HO messages: add missing BSSMAP header, x4 Change-Id: I9e128ba775227de5e4010f024338a78584f777ea --- src/gsm/gsm0808.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index a90aa227..8c2d1436 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -763,6 +763,9 @@ struct msgb *gsm0808_create_handover_request_ack(const uint8_t *l3_info, uint8_t if (chosen_speech_version != 0) msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, chosen_speech_version); + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + return msg; } @@ -780,6 +783,9 @@ struct msgb *gsm0808_create_handover_detect() /* Message Type, 3.2.2.1 */ msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_DETECT); + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + return msg; } @@ -816,6 +822,9 @@ struct msgb *gsm0808_create_handover_complete(const struct gsm0808_handover_comp if (params->lcls_bss_status_present) msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, params->lcls_bss_status); + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + return msg; } @@ -843,6 +852,9 @@ struct msgb *gsm0808_create_handover_failure(const struct gsm0808_handover_failu if (params->codec_list_bss_supported.len) gsm0808_enc_speech_codec_list(msg, ¶ms->codec_list_bss_supported); + /* prepend header with final length */ + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + return msg; } -- cgit v1.2.3 From 3953f41bbd7f1075f8585f6c306d35d095873474 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Tue, 28 Aug 2018 15:06:30 +0200 Subject: properly handle mandatory cli param of gsm0808_create_paging2 The cell identifier list parameter is mandatory. Document it as such, and tweak code which treated it like an optional parameter. No functional change. The existing code already asserts that a non-NULL value is passed for this parameter. Change-Id: I3716f9d5b210e0a7e6f45c9fe3fc34024e5234ad Related: OS#3021 --- src/gsm/gsm0808.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 8c2d1436..e3b10d0c 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -588,7 +588,7 @@ struct msgb *gsm0808_create_clear_rqst(uint8_t cause) /*! Create BSSMAP PAGING message * \param[in] imsi Mandatory paged IMSI in string representation * \param[in] tmsi Optional paged TMSI - * \param[in] cil Cell Identity List (where to page) + * \param[in] cil Mandatory Cell Identity List (where to page) * \param[in] chan_needed Channel Type needed * \returns callee-allocated msgb with BSSMAP PAGING message */ struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi, @@ -615,7 +615,7 @@ struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi, /* Message Type 3.2.2.1 */ msgb_v_put(msg, BSS_MAP_MSG_PAGING); - /* IMSI 3.2.2.6 */ + /* mandatory IMSI 3.2.2.6 */ mid_len = gsm48_generate_mid_from_imsi(mid_buf, imsi); msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2); @@ -626,9 +626,8 @@ struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi, (uint8_t *) & tmsi_sw); } - /* Cell Identifier List 3.2.2.27 */ - if (cil) - gsm0808_enc_cell_id_list2(msg, cil); + /* mandatory Cell Identifier List 3.2.2.27 */ + gsm0808_enc_cell_id_list2(msg, cil); /* Channel Needed 3.2.2.36 */ if (chan_needed) { -- cgit v1.2.3 From 896ff6db161465d506bb9bb5bee2cdeef220dd2e Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Tue, 28 Aug 2018 14:34:17 +0200 Subject: Properly deal with sockaddr_un socket path length limitations. In osmo_sock_unix_init(), add support for non-NUL-terminated unix socket paths and return an error if the supplied socket path exceeds the maximum socket path length supported by the operating system. Change-Id: I19d935e5e3dd7928e6e153c6f5ad7044de726016 Related: OS#2673 --- src/socket.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/socket.c b/src/socket.c index 7e7f6d96..6f56efb5 100644 --- a/src/socket.c +++ b/src/socket.c @@ -605,22 +605,29 @@ int osmo_sock_unix_init(uint16_t type, uint8_t proto, struct sockaddr_un local; int sfd, rc, on = 1; unsigned int namelen; + const size_t socket_path_len = strlen(socket_path); if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) == (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) return -EINVAL; local.sun_family = AF_UNIX; - osmo_strlcpy(local.sun_path, socket_path, sizeof(local.sun_path)); + if (socket_path_len == sizeof(local.sun_path)) { + /* Handle corner-case where sun_path is not NUL-terminated. See the unix(7) man page. */ + memcpy(local.sun_path, socket_path, sizeof(local.sun_path)); + } else if (osmo_strlcpy(local.sun_path, socket_path, sizeof(local.sun_path)) >= sizeof(local.sun_path)) { + LOGP(DLGLOBAL, LOGL_ERROR, "Socket path exceeds maximum length of %zd bytes: %s\n", + sizeof(local.sun_path), socket_path); + return -ENOSPC; + } #if defined(BSD44SOCKETS) || defined(__UNIXWARE__) - local.sun_len = strlen(local.sun_path); + local.sun_len = socket_path_len; #endif #if defined(BSD44SOCKETS) || defined(SUN_LEN) namelen = SUN_LEN(&local); #else - namelen = strlen(local.sun_path) + - offsetof(struct sockaddr_un, sun_path); + namelen = socket_path_len + offsetof(struct sockaddr_un, sun_path); #endif sfd = socket(AF_UNIX, type, proto); -- cgit v1.2.3 From 941fd9be1b00d978b52c902ee0c027bf826df040 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 30 Aug 2018 12:42:37 +0200 Subject: osmo-release.sh: Add quotes to string to fix shellcheck warning Change-Id: I40376c99d44552d9b8023fca8d319a9312b0fbb0 --- osmo-release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osmo-release.sh b/osmo-release.sh index 86b41d89..1e5a203e 100755 --- a/osmo-release.sh +++ b/osmo-release.sh @@ -4,7 +4,7 @@ REL=$2 if [ "z$REL" = "z" ]; then echo "No REL value specified, defaulting to 'patch' release" - REL=patch + REL="patch" fi BUMPVER=`command -v bumpversion` -- cgit v1.2.3 From cf8497cb2f347a4591225f8616c59c0299873838 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 30 Aug 2018 12:56:53 +0200 Subject: osmo-release.sh: Allow forcing release without LIBVERSION bump Sometimes a fix release may be required which only contains fixes to parts not related to a shared library, for instance a fix in the build system. Thus allow releasing without bumping LIBVERSION, but only through env var setting for people who know what they are doing. Change-Id: I91e186d47638038bc2968ea0178879365ffc9512 --- osmo-release.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osmo-release.sh b/osmo-release.sh index 1e5a203e..26ebd337 100755 --- a/osmo-release.sh +++ b/osmo-release.sh @@ -7,6 +7,8 @@ if [ "z$REL" = "z" ]; then REL="patch" fi +ALLOW_NO_LIBVERSION_CHANGE="${ALLOW_NO_LIBVERSION_CHANGE:-0}" + BUMPVER=`command -v bumpversion` NEW_VER=`bumpversion --list --current-version $VERSION $REL --allow-dirty | awk -F '=' '{ print $2 }'` @@ -27,12 +29,13 @@ fi echo "Releasing $VERSION -> $NEW_VER..." if [ "z$LIBVERS" != "z" ]; then - if [ "z$MAKEMOD" = "z" ]; then - echo "Before releasing, please modify some of the libversions: $LIBVERS" + if [ "z$MAKEMOD" = "z" ] && [ "z$ALLOW_NO_LIBVERSION_CHANGE" = "z0" ]; then + echo "ERROR: Before releasing, please modify some of the libversions: $LIBVERS" echo "You should NOT be doing this unless you've read and understood following article:" echo "https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info" exit 1 fi + if [ -f "TODO-RELEASE" ]; then grep '#' TODO-RELEASE > TODO-RELEASE.clean mv TODO-RELEASE.clean TODO-RELEASE -- cgit v1.2.3 From 1a72bafa5df03718bb1c328f3d64078dc5e70feb Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 30 Aug 2018 13:50:33 +0200 Subject: osmo-release.sh: Add checks to help avoid libversion debian major mismatch Change-Id: Ie0f6a2f9d60908b36f90921bfba3fc31606e5027 --- osmo-release.sh | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/osmo-release.sh b/osmo-release.sh index 26ebd337..4d4d080b 100755 --- a/osmo-release.sh +++ b/osmo-release.sh @@ -8,9 +8,19 @@ if [ "z$REL" = "z" ]; then fi ALLOW_NO_LIBVERSION_CHANGE="${ALLOW_NO_LIBVERSION_CHANGE:-0}" +ALLOW_NO_LIBVERSION_DEB_MATCH="${ALLOW_NO_LIBVERSION_DEB_MATCH:-0}" -BUMPVER=`command -v bumpversion` +libversion_to_deb_major() { + libversion="$1" + current="$(echo "$libversion" | cut -d ":" -f 1)" + #revision="$(echo "$libversion" | cut -d ":" -f 2)" + age="$(echo "$libversion" | cut -d ":" -f 3)" + major="$(expr "$current" - "$age")" + echo "$major" +} +BUMPVER=`command -v bumpversion` +GIT_TOPDIR="$(git rev-parse --show-toplevel)" NEW_VER=`bumpversion --list --current-version $VERSION $REL --allow-dirty | awk -F '=' '{ print $2 }'` LIBVERS=`git grep -n LIBVERSION | grep '=' | grep am | grep -v LDFLAGS` MAKEMOD=`git diff --cached -GLIBVERSION --stat | grep Makefile.am` @@ -35,7 +45,34 @@ if [ "z$LIBVERS" != "z" ]; then echo "https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info" exit 1 fi - + if [ "z$ALLOW_NO_LIBVERSION_DEB_MATCH" = "z0" ]; then + echo "$LIBVERS" | while read -r line; do + libversion=$(echo "$line" | cut -d "=" -f 2) + major="$(libversion_to_deb_major "$libversion")" + file_matches="$(find "${GIT_TOPDIR}/debian" -name "lib*${major}.install" | wc -l)" + if [ "z$file_matches" = "z0" ]; then + echo "ERROR: Found no matching debian/lib*$major.install file for LIBVERSION=$libversion" + exit 1 + elif [ "z$file_matches" = "z1" ]; then + echo "OK: Found matching debian/lib*$major.install for LIBVERSION=$libversion" + else + echo "WARN: Found $file_matches files matching debian/lib*$major.install for LIBVERSION=$libversion, manual check required!" + fi + control_matches="$(grep -e "Package" "${GIT_TOPDIR}/debian/control" | grep "lib" | grep "$major$" | wc -l)" + if [ "z$control_matches" = "z0" ]; then + echo "ERROR: Found no matching Package lib*$major in debian/control for LIBVERSION=$libversion" + exit 1 + elif [ "z$control_matches" = "z1" ]; then + echo "OK: Found 'Package: lib*$major' in debian/control for LIBVERSION=$libversion" + else + echo "WARN: Found $file_matches files matching 'Package: lib*$major' in debian/control for LIBVERSION=$libversion, manual check required!" + fi + done + # catch and forward exit from pipe subshell "while read": + if [ $? -ne 0 ]; then + exit 1 + fi + fi if [ -f "TODO-RELEASE" ]; then grep '#' TODO-RELEASE > TODO-RELEASE.clean mv TODO-RELEASE.clean TODO-RELEASE -- cgit v1.2.3