From 3cdaa8d52517093ec846774f4ce0f66a43b17e17 Mon Sep 17 00:00:00 2001 From: Keith Date: Fri, 31 Aug 2018 20:09:18 +0200 Subject: Add CC_CAUSE value_string array Adds a value_string array for GSM 04.08 Call Control cause values Change-Id: I296f208581ce2550805f9d96e20f7319e1199023 --- include/osmocom/gsm/protocol/gsm_04_08.h | 4 +++ src/gsm/gsm48.c | 54 ++++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 1 + 3 files changed, 59 insertions(+) diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h index 46350147..e218295c 100644 --- a/include/osmocom/gsm/protocol/gsm_04_08.h +++ b/include/osmocom/gsm/protocol/gsm_04_08.h @@ -1495,6 +1495,10 @@ enum gsm48_cc_cause { GSM48_CC_CAUSE_INTERWORKING = 127, }; +extern const struct value_string gsm48_cc_cause_names[]; +static inline const char *gsm48_cc_cause_name(enum gsm48_cc_cause val) +{ return get_value_string(gsm48_cc_cause_names, val); } + /* Annex G, GSM specific cause values for mobility management */ enum gsm48_reject_value { GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2, diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index 136b9375..fc3b9734 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -945,6 +945,60 @@ const struct value_string gsm48_cc_msgtype_names[] = { { 0, NULL } }; +/*! TS 04.08 10.5..4.11 Call Control Cause Values */ +const struct value_string gsm48_cc_cause_names[] = { + { GSM48_CC_CAUSE_UNASSIGNED_NR, "UNASSIGNED_NR" }, + { GSM48_CC_CAUSE_NO_ROUTE, "NO_ROUTE" }, + { GSM48_CC_CAUSE_CHAN_UNACCEPT, "CHAN_UNACCEPT" }, + { GSM48_CC_CAUSE_OP_DET_BARRING, "OP_DET_BARRING" }, + { GSM48_CC_CAUSE_NORM_CALL_CLEAR, "NORM_CALL_CLEAR" }, + { GSM48_CC_CAUSE_USER_BUSY, "USER_BUSY" }, + { GSM48_CC_CAUSE_USER_NOTRESPOND, "USER_NOTRESPOND" }, + { GSM48_CC_CAUSE_USER_ALERTING_NA, "USER_ALERTING_NA" }, + { GSM48_CC_CAUSE_CALL_REJECTED, "CALL_REJECTED" }, + { GSM48_CC_CAUSE_NUMBER_CHANGED, "NUMBER_CHANGED" }, + { GSM48_CC_CAUSE_PRE_EMPTION, "PRE_EMPTION" }, + { GSM48_CC_CAUSE_NONSE_USER_CLR, "NONSE_USER_CLR" }, + { GSM48_CC_CAUSE_DEST_OOO, "DEST_OOO" }, + { GSM48_CC_CAUSE_INV_NR_FORMAT, "INV_NR_FORMAT" }, + { GSM48_CC_CAUSE_FACILITY_REJ, "FACILITY_REJ" }, + { GSM48_CC_CAUSE_RESP_STATUS_INQ, "RESP_STATUS_INQ" }, + { GSM48_CC_CAUSE_NORMAL_UNSPEC, "NORMAL_UNSPEC" }, + { GSM48_CC_CAUSE_NO_CIRCUIT_CHAN, "NO_CIRCUIT_CHAN" }, + { GSM48_CC_CAUSE_NETWORK_OOO, "NETWORK_OOO" }, + { GSM48_CC_CAUSE_TEMP_FAILURE, "TEMP_FAILURE" }, + { GSM48_CC_CAUSE_SWITCH_CONG, "SWITCH_CONG" }, + { GSM48_CC_CAUSE_ACC_INF_DISCARD, "ACC_INF_DISCARD" }, + { GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL, "REQ_CHAN_UNAVAIL" }, + { GSM48_CC_CAUSE_RESOURCE_UNAVAIL, "RESOURCE_UNAVAIL" }, + { GSM48_CC_CAUSE_QOS_UNAVAIL, "QOS_UNAVAIL" }, + { GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC, "REQ_FAC_NOT_SUBSC" }, + { GSM48_CC_CAUSE_INC_BARRED_CUG, "INC_BARRED_CUG" }, + { GSM48_CC_CAUSE_BEARER_CAP_UNAUTH, "BEARER_CAP_UNAUTH" }, + { GSM48_CC_CAUSE_BEARER_CA_UNAVAIL, "BEARER_CA_UNAVAIL" }, + { GSM48_CC_CAUSE_SERV_OPT_UNAVAIL, "SERV_OPT_UNAVAIL" }, + { GSM48_CC_CAUSE_BEARERSERV_UNIMPL, "BEARERSERV_UNIMPL" }, + { GSM48_CC_CAUSE_ACM_GE_ACM_MAX, "ACM_GE_ACM_MAX" }, + { GSM48_CC_CAUSE_REQ_FAC_NOTIMPL, "REQ_FAC_NOTIMPL" }, + { GSM48_CC_CAUSE_RESTR_BCAP_AVAIL, "RESTR_BCAP_AVAIL" }, + { GSM48_CC_CAUSE_SERV_OPT_UNIMPL, "SERV_OPT_UNIMPL" }, + { GSM48_CC_CAUSE_INVAL_TRANS_ID, "INVAL_TRANS_ID" }, + { GSM48_CC_CAUSE_USER_NOT_IN_CUG, "USER_NOT_IN_CUG" }, + { GSM48_CC_CAUSE_INCOMPAT_DEST, "INCOMPAT_DEST" }, + { GSM48_CC_CAUSE_INVAL_TRANS_NET, "INVAL_TRANS_NET" }, + { GSM48_CC_CAUSE_SEMANTIC_INCORR, "SEMANTIC_INCORR" }, + { GSM48_CC_CAUSE_INVAL_MAND_INF, "INVAL_MAND_INF" }, + { GSM48_CC_CAUSE_MSGTYPE_NOTEXIST, "MSGTYPE_NOTEXIST" }, + { GSM48_CC_CAUSE_MSGTYPE_INCOMPAT, "MSGTYPE_INCOMPAT" }, + { GSM48_CC_CAUSE_IE_NOTEXIST, "IE_NOTEXIST" }, + { GSM48_CC_CAUSE_COND_IE_ERR, "COND_IE_ERR" }, + { GSM48_CC_CAUSE_MSG_INCOMP_STATE, "MSG_INCOMP_STATE" }, + { GSM48_CC_CAUSE_RECOVERY_TIMER, "RECOVERY_TIMER" }, + { GSM48_CC_CAUSE_PROTO_ERR, "PROTO_ERR" }, + { GSM48_CC_CAUSE_INTERWORKING, "INTERWORKING" }, + { 0 , NULL } +}; + /*! TS 04.80, section 3.4 Messages for supplementary services control */ const struct value_string gsm48_nc_ss_msgtype_names[] = { OSMO_VALUE_STRING(GSM0480_MTYPE_RELEASE_COMPLETE), diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 1da398c1..60d6ed84 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -321,6 +321,7 @@ gsm48_pdisc_names; gsm48_rr_msgtype_names; gsm48_mm_msgtype_names; gsm48_cc_msgtype_names; +gsm48_cc_cause_names; gsm48_pdisc_msgtype_name; gsm48_reject_value_names; -- cgit v1.2.3 From b99ed7ff187283eff83dfb647bdddd09bd9b8a59 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 13 Aug 2018 20:54:44 +0200 Subject: Add RSPRO support to IPA and logging definitions Change-Id: Iee79f5273f32cb9ce4bd7a984e7f0625542e776f --- include/osmocom/core/logging.h | 3 ++- include/osmocom/gsm/protocol/ipaccess.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index 8464043f..c60143d9 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -122,7 +122,8 @@ void logp(int subsys, const char *file, int line, int cont, const char *format, #define DLM3UA -16 /*!< Osmocom M3UA */ #define DLMGCP -17 /*!< Osmocom MGCP */ #define DLJIBUF -18 /*!< Osmocom Jitter Buffer */ -#define OSMO_NUM_DLIB 18 /*!< Number of logging sub-systems in libraries */ +#define DLRSPRO -19 /*!< Osmocom Remote SIM Protocol */ +#define OSMO_NUM_DLIB 19 /*!< Number of logging sub-systems in libraries */ /*! Configuration of single log category / sub-system */ struct log_category { diff --git a/include/osmocom/gsm/protocol/ipaccess.h b/include/osmocom/gsm/protocol/ipaccess.h index 0f5d54f2..80413d10 100644 --- a/include/osmocom/gsm/protocol/ipaccess.h +++ b/include/osmocom/gsm/protocol/ipaccess.h @@ -38,6 +38,7 @@ enum ipaccess_proto_ext { IPAC_PROTO_EXT_ORC = 0x04, /* OML Router Control */ IPAC_PROTO_EXT_GSUP = 0x05, /* GSUP GPRS extension */ IPAC_PROTO_EXT_OAP = 0x06, /* Osmocom Authn Protocol */ + IPAC_PROTO_EXT_RSPRO = 0x07, /* Remote SIM protocol */ }; enum ipaccess_msgtype { -- cgit v1.2.3 From 80f4ff9368cc02273fbe556893957f5b081d7cb1 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 5 Sep 2018 02:57:25 +0700 Subject: core/utils.h: drop duplicate '' include Change-Id: I0979ddda91c4c0aa080b714cf2a698d7634f5091 --- include/osmocom/core/utils.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index e2d51349..10063cbb 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -30,7 +30,6 @@ /*! Copy a C-string into a sized buffer using sizeof to detect buffer's size */ #define OSMO_STRLCPY_ARRAY(array, src) osmo_strlcpy(array, src, sizeof(array)) -#include #include #include -- cgit v1.2.3 From 559443040567c5def8fdb84dd43504202e2ae7df Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 5 Sep 2018 02:58:03 +0700 Subject: core/utils.h: move includes to the top Having all inculdes listed in one place is a common good practice, which prevents one from adding duplicates. Change-Id: I3f52189d5e8f9afafc39525e95385a085f8f850a --- include/osmocom/core/utils.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 10063cbb..976d4a85 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include #include @@ -30,9 +32,6 @@ /*! Copy a C-string into a sized buffer using sizeof to detect buffer's size */ #define OSMO_STRLCPY_ARRAY(array, src) osmo_strlcpy(array, src, sizeof(array)) -#include -#include - /*! A mapping between human-readable string and numeric value */ struct value_string { unsigned int value; /*!< numeric value */ -- cgit v1.2.3 From 94443261586312967ae7eb0cce8953977de457f1 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Sat, 14 Jul 2018 21:09:54 +0200 Subject: coding: Correctly count bits when decoding EDGE bursts with MCS >= 7. They consist of two blocks, so we should count both blocks. Change-Id: I560de192212dae4705054a1665726369b83d213a --- src/coding/gsm0503_coding.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coding/gsm0503_coding.c b/src/coding/gsm0503_coding.c index c72aabc0..088b8bba 100644 --- a/src/coding/gsm0503_coding.c +++ b/src/coding/gsm0503_coding.c @@ -979,6 +979,9 @@ int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t if (rc < 0) return -EFAULT; } else { + /* Bit counters for the second block */ + int n_errors2, n_bits_total2; + /* MCS-7,8,9 block 1 */ rc = egprs_decode_data(l2_data, c1, cps.mcs, cps.p[0], 0, n_errors, n_bits_total); @@ -987,7 +990,11 @@ int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t /* MCS-7,8,9 block 2 */ rc = egprs_decode_data(l2_data, c2, cps.mcs, cps.p[1], - 1, n_errors, n_bits_total); + 1, &n_errors2, &n_bits_total2); + if (n_errors) + *n_errors += n_errors2; + if (n_bits_total) + *n_bits_total += n_bits_total2; if (rc < 0) return -EFAULT; } -- cgit v1.2.3 From 50f7d74fca2b5e4121321e8411a2841bd8821eab Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Sat, 14 Jul 2018 21:07:27 +0200 Subject: coding: Always initialize bit counters in gsm0503_pdtch_egprs_decode(). Previsouly there were a lot of valid code paths which returned from the function before setting bit counters which led to bogus BER output in osmo-bts-trx logs when those code paths were hit. Change-Id: I4722cae3794ccbb12001113c991d9cf345a52a96 --- src/coding/gsm0503_coding.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coding/gsm0503_coding.c b/src/coding/gsm0503_coding.c index 088b8bba..7385d233 100644 --- a/src/coding/gsm0503_coding.c +++ b/src/coding/gsm0503_coding.c @@ -938,6 +938,11 @@ int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t struct egprs_cps cps; union gprs_rlc_ul_hdr_egprs *hdr; + if (n_errors) + *n_errors = 0; + if (n_bits_total) + *n_bits_total = 0; + if ((nbits != GSM0503_GPRS_BURSTS_NBITS) && (nbits != GSM0503_EGPRS_BURSTS_NBITS)) { /* Invalid EGPRS bit length */ -- cgit v1.2.3 From 03e7553cba06145004748aba597636c5342ef89e Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Fri, 7 Sep 2018 03:12:05 +0200 Subject: api doc: fix osmo_quote_str_* Change-Id: Ibfd8ff213630e34009936b0fcb3ee50dda65fb70 --- src/utils.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index ea0bbde0..3f40f2ef 100644 --- a/src/utils.c +++ b/src/utils.c @@ -557,8 +557,8 @@ const char *osmo_escape_str(const char *str, int in_len) /*! Like osmo_escape_str(), but returns double-quotes around a string, or "NULL" for a NULL string. * This allows passing any char* value and get its C representation as string. * \param[in] str A string that may contain any characters. - * \param[in] len Pass -1 to print until nul char, or >= 0 to force a length. - * \returns buf containing an escaped representation, possibly truncated, or str itself. + * \param[in] in_len Pass -1 to print until nul char, or >= 0 to force a length. + * \returns buf containing a quoted and escaped representation, possibly truncated. */ const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize) { @@ -587,6 +587,12 @@ const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bu return buf; } +/*! Like osmo_quote_str_buf() but returns the result in a static buffer. + * The static buffer is shared with get_value_string() and osmo_escape_str(). + * \param[in] str A string that may contain any characters. + * \param[in] in_len Pass -1 to print until nul char, or >= 0 to force a length. + * \returns static buffer containing a quoted and escaped representation, possibly truncated. + */ const char *osmo_quote_str(const char *str, int in_len) { return osmo_quote_str_buf(str, in_len, namebuf, sizeof(namebuf)); -- cgit v1.2.3 From 7c749893bfcf9f1a117ee6a2d35a6c8f0f05909d Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Fri, 7 Sep 2018 03:01:38 +0200 Subject: add osmo_str_tolower() and _toupper() with test We already have osmo_str2lower() and osmo_str2upper(), but these lack: * proper destination buffer bounds checking, * ability to call directly as printf() argument. Deprecate osmo_str2upper() and osmo_str2lower() because of missing bounds checking. Introduce osmo_str_tolower_buf(), osmo_str_toupper_buf() to provide bounds-safe conversion, also able to safely convert a buffer in-place. Introduce osmo_str_tolower(), osmo_str_toupper() that call the above _buf() equivalents using a static buffer[128] and returning the resulting string directly, convenient for direct printing. Possibly truncated but always safe. Add unit tests to utils_test.c. Replace all libosmocore uses of now deprecated osmo_str2lower(). Naming: the ctype.h API is called tolower() and toupper(), so just prepend 'osmo_str_' and don't separate 'to_lower'. Change-Id: Ib0ee1206b9f31d7ba25c31f8008119ac55440797 --- include/osmocom/core/utils.h | 15 +++- src/utils.c | 86 ++++++++++++++++++++ src/vty/logging_vty.c | 11 +-- tests/utils/utils_test.c | 184 +++++++++++++++++++++++++++++++++++++++++++ tests/utils/utils_test.ok | 46 +++++++++++ 5 files changed, 333 insertions(+), 9 deletions(-) diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index 976d4a85..0b54c880 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -7,6 +7,7 @@ #include #include #include +#include /*! \defgroup utils General-purpose utility functions * @{ @@ -57,8 +58,18 @@ char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len) __attribute__(( #define osmo_static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1] __attribute__((__unused__)); -void osmo_str2lower(char *out, const char *in); -void osmo_str2upper(char *out, const char *in); +void osmo_str2lower(char *out, const char *in) + OSMO_DEPRECATED("Use osmo_str_tolower() or osmo_str_tolower_buf() instead," + " to properly check target memory bounds"); +void osmo_str2upper(char *out, const char *in) + OSMO_DEPRECATED("Use osmo_str_toupper() or osmo_str_toupper_buf() instead," + " to properly check target memory bounds"); + +size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src); +const char *osmo_str_tolower(const char *src); + +size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src); +const char *osmo_str_toupper(const char *src); #define OSMO_SNPRINTF_RET(ret, rem, offset, len) \ do { \ diff --git a/src/utils.c b/src/utils.c index 3f40f2ef..e6adcf86 100644 --- a/src/utils.c +++ b/src/utils.c @@ -638,4 +638,90 @@ uint32_t osmo_isqrt32(uint32_t x) return g0; } +/*! Convert a string to lowercase, while checking buffer size boundaries. + * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0. + * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters + * length as well as nul terminated. + * Note: similar osmo_str2lower(), but safe to use for src strings of arbitrary length. + * \param[out] dest Target buffer to write lowercase string. + * \param[in] dest_len Maximum buffer size of dest (e.g. sizeof(dest)). + * \param[in] src String to convert to lowercase. + * \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1. + */ +size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src) +{ + size_t rc; + if (dest == src) { + if (dest_len < 1) + return 0; + dest[dest_len - 1] = '\0'; + rc = strlen(dest); + } else { + if (dest_len < 1) + return strlen(src); + rc = osmo_strlcpy(dest, src, dest_len); + } + for (; *dest; dest++) + *dest = tolower(*dest); + return rc; +} + +/*! Convert a string to lowercase, using a static buffer. + * The resulting string may be truncated if the internally used static buffer is shorter than src. + * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a + * terminating nul. + * See also osmo_str_tolower_buf(). + * \param[in] src String to convert to lowercase. + * \returns Resulting lowercase string in a static buffer, always nul terminated. + */ +const char *osmo_str_tolower(const char *src) +{ + static char buf[128]; + osmo_str_tolower_buf(buf, sizeof(buf), src); + return buf; +} + +/*! Convert a string to uppercase, while checking buffer size boundaries. + * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0. + * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters + * length as well as nul terminated. + * Note: similar osmo_str2upper(), but safe to use for src strings of arbitrary length. + * \param[out] dest Target buffer to write uppercase string. + * \param[in] dest_len Maximum buffer size of dest (e.g. sizeof(dest)). + * \param[in] src String to convert to uppercase. + * \returns Length of \a src, like osmo_strlcpy(), but if \a dest == \a src at most \a dest_len - 1. + */ +size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src) +{ + size_t rc; + if (dest == src) { + if (dest_len < 1) + return 0; + dest[dest_len - 1] = '\0'; + rc = strlen(dest); + } else { + if (dest_len < 1) + return strlen(src); + rc = osmo_strlcpy(dest, src, dest_len); + } + for (; *dest; dest++) + *dest = toupper(*dest); + return rc; +} + +/*! Convert a string to uppercase, using a static buffer. + * The resulting string may be truncated if the internally used static buffer is shorter than src. + * The internal buffer is at least 128 bytes long, i.e. guaranteed to hold at least 127 characters and a + * terminating nul. + * See also osmo_str_toupper_buf(). + * \param[in] src String to convert to uppercase. + * \returns Resulting uppercase string in a static buffer, always nul terminated. + */ +const char *osmo_str_toupper(const char *src) +{ + static char buf[128]; + osmo_str_toupper_buf(buf, sizeof(buf), src); + return buf; +} + /*! @} */ diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 8c8a3326..7d97bb1d 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -754,7 +754,6 @@ DEFUN(cfg_no_log_alarms, cfg_no_log_alarms_cmd, static int config_write_log_single(struct vty *vty, struct log_target *tgt) { int i; - char level_lower[32]; switch (tgt->type) { case LOG_TGT_TYPE_VTY: @@ -806,21 +805,19 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) VTY_NEWLINE); /* stupid old osmo logging API uses uppercase strings... */ - osmo_str2lower(level_lower, log_level_str(tgt->loglevel)); - vty_out(vty, " logging level all %s%s", level_lower, VTY_NEWLINE); + vty_out(vty, " logging level all %s%s", osmo_str_tolower(log_level_str(tgt->loglevel)), + VTY_NEWLINE); for (i = 0; i < osmo_log_info->num_cat; i++) { const struct log_category *cat = &tgt->categories[i]; - char cat_lower[32]; /* skip empty entries in the array */ if (!osmo_log_info->cat[i].name) continue; /* 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)); - vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE); + vty_out(vty, " logging level %s", osmo_str_tolower(osmo_log_info->cat[i].name+1)); + vty_out(vty, " %s%s", osmo_str_tolower(log_level_str(cat->loglevel)), VTY_NEWLINE); } return 1; diff --git a/tests/utils/utils_test.c b/tests/utils/utils_test.c index 2f1e87da..2bb1f9ca 100644 --- a/tests/utils/utils_test.c +++ b/tests/utils/utils_test.c @@ -616,6 +616,189 @@ static void osmo_sockaddr_to_str_and_uint_test(void) } } +struct osmo_str_tolowupper_test_data { + const char *in; + bool use_static_buf; + size_t buflen; + const char *expect_lower; + const char *expect_upper; + size_t expect_rc; + size_t expect_rc_inplace; +}; + +struct osmo_str_tolowupper_test_data osmo_str_tolowupper_tests[] = { + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .use_static_buf = true, + .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()", + .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + }, + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .buflen = 99, + .expect_lower = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()", + .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .expect_rc = 62, + .expect_rc_inplace = 62, + }, + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .buflen = 0, + .expect_lower = "Unset", + .expect_upper = "Unset", + .expect_rc = 62, + .expect_rc_inplace = 0, + }, + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .buflen = 1, + .expect_lower = "", + .expect_upper = "", + .expect_rc = 62, + .expect_rc_inplace = 0, + }, + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .buflen = 2, + .expect_lower = "a", + .expect_upper = "A", + .expect_rc = 62, + .expect_rc_inplace = 1, + }, + { + .in = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", + .buflen = 28, + .expect_lower = "abcdefghijklmnopqrstuvwxyza", + .expect_upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZA", + .expect_rc = 62, + .expect_rc_inplace = 27, + }, +}; + + +static void osmo_str_tolowupper_test() +{ + int i; + char buf[128]; + bool ok = true; + printf("\n%s\n", __func__); + + for (i = 0; i < ARRAY_SIZE(osmo_str_tolowupper_tests); i++) { + struct osmo_str_tolowupper_test_data *d = &osmo_str_tolowupper_tests[i]; + size_t rc = 0; + const char *res; + + /* tolower */ + if (d->use_static_buf) { + res = osmo_str_tolower(d->in); + printf("osmo_str_tolower(%s)\n", osmo_quote_str(d->in, -1)); + printf(" = %s\n", osmo_quote_str(res, -1)); + } else { + OSMO_ASSERT(sizeof(buf) >= d->buflen); + osmo_strlcpy(buf, "Unset", sizeof(buf)); + rc = osmo_str_tolower_buf(buf, d->buflen, d->in); + res = buf; + printf("osmo_str_tolower_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1)); + printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1)); + } + + if (strcmp(res, d->expect_lower)) { + printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n" + " got %s\n", i, osmo_quote_str(res, -1)); + printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1)); + ok = false; + } + + if (!d->use_static_buf && d->expect_rc != rc) { + printf("ERROR: osmo_str_tolowupper_test[%d] tolower\n" + " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc); + ok = false; + } + + /* tolower, in-place */ + if (!d->use_static_buf) { + osmo_strlcpy(buf, + d->buflen ? d->in : "Unset", + sizeof(buf)); + rc = osmo_str_tolower_buf(buf, d->buflen, buf); + res = buf; + printf("osmo_str_tolower_buf(%zu, %s, in-place)\n", + d->buflen, osmo_quote_str(d->in, -1)); + printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1)); + + if (strcmp(res, d->expect_lower)) { + printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n" + " got %s\n", i, osmo_quote_str(res, -1)); + printf(" expected %s\n", osmo_quote_str(d->expect_lower, -1)); + ok = false; + } + + if (d->expect_rc_inplace != rc) { + printf("ERROR: osmo_str_tolowupper_test[%d] tolower in-place\n" + " got rc=%zu, expected rc=%zu\n", + i, rc, d->expect_rc_inplace); + ok = false; + } + } + + /* toupper */ + if (d->use_static_buf) { + res = osmo_str_toupper(d->in); + printf("osmo_str_toupper(%s)\n", osmo_quote_str(d->in, -1)); + printf(" = %s\n", osmo_quote_str(res, -1)); + } else { + OSMO_ASSERT(sizeof(buf) >= d->buflen); + osmo_strlcpy(buf, "Unset", sizeof(buf)); + rc = osmo_str_toupper_buf(buf, d->buflen, d->in); + res = buf; + printf("osmo_str_toupper_buf(%zu, %s)\n", d->buflen, osmo_quote_str(d->in, -1)); + printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1)); + } + + if (strcmp(res, d->expect_upper)) { + printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n" + " got %s\n", i, osmo_quote_str(res, -1)); + printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1)); + ok = false; + } + + if (!d->use_static_buf && d->expect_rc != rc) { + printf("ERROR: osmo_str_tolowupper_test[%d] toupper\n" + " got rc=%zu, expected rc=%zu\n", i, rc, d->expect_rc); + ok = false; + } + + /* toupper, in-place */ + if (!d->use_static_buf) { + osmo_strlcpy(buf, + d->buflen ? d->in : "Unset", + sizeof(buf)); + rc = osmo_str_toupper_buf(buf, d->buflen, buf); + res = buf; + printf("osmo_str_toupper_buf(%zu, %s, in-place)\n", + d->buflen, osmo_quote_str(d->in, -1)); + printf(" = %zu, %s\n", rc, osmo_quote_str(res, -1)); + + if (strcmp(res, d->expect_upper)) { + printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n" + " got %s\n", i, osmo_quote_str(res, -1)); + printf(" expected %s\n", osmo_quote_str(d->expect_upper, -1)); + ok = false; + } + + if (d->expect_rc_inplace != rc) { + printf("ERROR: osmo_str_tolowupper_test[%d] toupper in-place\n" + " got rc=%zu, expected rc=%zu\n", + i, rc, d->expect_rc_inplace); + ok = false; + } + } + } + + OSMO_ASSERT(ok); +} + + int main(int argc, char **argv) { static const struct log_info log_info = {}; @@ -631,5 +814,6 @@ int main(int argc, char **argv) str_quote_test(); isqrt_test(); osmo_sockaddr_to_str_and_uint_test(); + osmo_str_tolowupper_test(); return 0; } diff --git a/tests/utils/utils_test.ok b/tests/utils/utils_test.ok index abc7317a..3ea8ec6a 100644 --- a/tests/utils/utils_test.ok +++ b/tests/utils/utils_test.ok @@ -153,3 +153,49 @@ osmo_sockaddr_to_str_and_uint_test [5] 234.23.42.123:1234 (omit addr) addr_len=0 --> :1234 rc=0 [6] 234.23.42.123:1234 addr_len=0 --> :1234 rc=13 [7] 234.23.42.123:1234 (omit addr) (omit port) addr_len=0 --> :0 rc=0 + +osmo_str_tolowupper_test +osmo_str_tolower("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()" +osmo_str_toupper("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()" +osmo_str_tolower_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()" +osmo_str_tolower_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 62, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz!@#$%^&*()" +osmo_str_toupper_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()" +osmo_str_toupper_buf(99, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()" +osmo_str_tolower_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "Unset" +osmo_str_tolower_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 0, "Unset" +osmo_str_toupper_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "Unset" +osmo_str_toupper_buf(0, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 0, "Unset" +osmo_str_tolower_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "" +osmo_str_tolower_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 0, "" +osmo_str_toupper_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "" +osmo_str_toupper_buf(1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 0, "" +osmo_str_tolower_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "a" +osmo_str_tolower_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 1, "a" +osmo_str_toupper_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "A" +osmo_str_toupper_buf(2, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 1, "A" +osmo_str_tolower_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "abcdefghijklmnopqrstuvwxyza" +osmo_str_tolower_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 27, "abcdefghijklmnopqrstuvwxyza" +osmo_str_toupper_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()") + = 62, "ABCDEFGHIJKLMNOPQRSTUVWXYZA" +osmo_str_toupper_buf(28, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()", in-place) + = 27, "ABCDEFGHIJKLMNOPQRSTUVWXYZA" -- cgit v1.2.3 From ec6fdbb128361fb374c8c21843c9f8223ac7a39d Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 17 Jan 2018 13:07:16 +0100 Subject: fix tests linking: don't use system installed libs Do not link against the system-wide installed libosmo* libs when building the regression test programs. Always use the locally built ones. Linking some libosmo libraries causes libtool to pull in other libosmo libs even though they were not explicitly named. For example, ctrl_test explicitly links libosmoctrl, but this also has dependencies to libosmovty and libosmogsm: ldd src/ctrl/.libs/libosmoctrl.so | grep osmo libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f26c26d4000) libosmogsm.so.10 => /usr/local/lib/libosmogsm.so.10 (0x00007f26c22bb000) libosmovty.so.4 => /usr/local/lib/libosmovty.so.4 (0x00007f26c2171000) If we omit explicit LDADD of these dependencies in the Makefile.am, libtool will take the first canonical place to find them, which may just be the already installed older versions of the same libs, which may or may not be compatible with the current build. In any case, it is never intended to link installed libs. All library dependencies are listed by this quick script: cd libosmocore for l in $(find . -name "*.so") ; do echo; echo "$l"; ldd $l | grep libosmo; done ./.libs/libosmocore.so ./coding/.libs/libosmocoding.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f25fc3c2000) libosmogsm.so.10 => /usr/local/lib/libosmogsm.so.10 (0x00007f25fbfa9000) libosmocodec.so.0 => /usr/local/lib/libosmocodec.so.0 (0x00007f25fbf9b000) ./codec/.libs/libosmocodec.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007fb4c900d000) ./ctrl/.libs/libosmoctrl.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f5df5129000) libosmogsm.so.10 => /usr/local/lib/libosmogsm.so.10 (0x00007f5df4d10000) libosmovty.so.4 => /usr/local/lib/libosmovty.so.4 (0x00007f5df4bc6000) ./gb/.libs/libosmogb.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f788e536000) libosmovty.so.4 => /usr/local/lib/libosmovty.so.4 (0x00007f788e3ec000) libosmogsm.so.10 => /usr/local/lib/libosmogsm.so.10 (0x00007f788dfd3000) ./vty/.libs/libosmovty.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f3b7ed21000) ./gsm/.libs/libosmogsm.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007fc69472e000) ./sim/.libs/libosmosim.so libosmocore.so.11 => /usr/local/lib/libosmocore.so.11 (0x00007f2f6412d000) libosmogsm.so.10 => /usr/local/lib/libosmogsm.so.10 (0x00007f2f63d14000) Add all explicit linking of all required library dependencies in all regression test programs, as shown by above listing. Example for reproducing a problem: In libosmocore.a, introduce a new function, and call that from libosmovty code. For example, I made loglevel_strs non-static in logging.c, and used that in logging_vty.c. Build and install this in a place where libtool can find it. Then go back to before this change and rebuild. You will see that linking ctrl_test (before this patch) then complains about libosmovty requiring the loglevel_strs symbol which it cannot find in libosmocore.so. Change-Id: Id084e6e6efd25cd62b1bd7a4fc7c5985c39130c6 --- tests/Makefile.am | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 072bb4a2..5d07695a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -76,7 +76,10 @@ abis_abis_test_SOURCES = abis/abis_test.c abis_abis_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la ctrl_ctrl_test_SOURCES = ctrl/ctrl_test.c -ctrl_ctrl_test_LDADD = $(LDADD) $(top_builddir)/src/ctrl/libosmoctrl.la +ctrl_ctrl_test_LDADD = $(LDADD) \ + $(top_builddir)/src/ctrl/libosmoctrl.la \ + $(top_builddir)/src/gsm/libosmogsm.la \ + $(top_builddir)/src/vty/libosmovty.la gea_gea_test_SOURCES = gea/gea_test.c gea_gea_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la @@ -130,20 +133,24 @@ ussd_ussd_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la gb_bssgp_fc_test_SOURCES = gb/bssgp_fc_test.c gb_bssgp_fc_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la \ + $(top_builddir)/src/vty/libosmovty.la \ $(top_builddir)/src/gsm/libosmogsm.la gb_gprs_bssgp_test_SOURCES = gb/gprs_bssgp_test.c gb_gprs_bssgp_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ + $(top_builddir)/src/vty/libosmovty.la \ $(top_builddir)/src/gsm/libosmogsm.la gb_gprs_ns_test_SOURCES = gb/gprs_ns_test.c gb_gprs_ns_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ + $(top_builddir)/src/vty/libosmovty.la \ $(top_builddir)/src/gsm/libosmogsm.la logging_logging_test_SOURCES = logging/logging_test.c fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ + $(top_builddir)/src/vty/libosmovty.la \ $(top_builddir)/src/gsm/libosmogsm.la codec_codec_test_SOURCES = codec/codec_test.c @@ -177,7 +184,11 @@ 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 +fsm_fsm_test_LDADD = \ + $(LDADD) \ + $(top_builddir)/src/ctrl/libosmoctrl.la \ + $(top_builddir)/src/gsm/libosmogsm.la \ + $(top_builddir)/src/vty/libosmovty.la write_queue_wqueue_test_SOURCES = write_queue/wqueue_test.c -- cgit v1.2.3 From 3a9ff11e574fa7ee19b1062b2c90151dbf7f0e27 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 10 Sep 2018 17:18:28 +0200 Subject: logging vty: add VTY transcript test I am setting out to refactor various details about logging. To show the effect, I am first adding this new test to illustrate the exact effects on the various osmo programs. Add logging_vty_test.c as a standalone program that simply defines a few logging categories and opens a telnet vty to play with. Add logging_vty_test.vty, as an osmo_verify_transcript_vty.py test script. Add --enable-external-tests to configure.ac, to enable running logging_vty_test.vty during 'make check'. Also allow running 'make vty-test' without the need to first configure with --enable-external-tests (a flexibility I've missed many times over in the other osmo source trees). Add a Makefile.am stub for external CTRL tests, basically a copy-paste from osmo-msc.git. I doubt that libosmocore will get python driven CTRL interface testing any time soon, but if so we will know to not run it concurrently. Change-Id: I948e832a33131f8eab98651d6010ceb0ccbc9a9c --- configure.ac | 15 ++ tests/Makefile.am | 30 +++- tests/logging/logging_vty_test.c | 296 +++++++++++++++++++++++++++++++++++++ tests/logging/logging_vty_test.vty | 190 ++++++++++++++++++++++++ 4 files changed, 530 insertions(+), 1 deletion(-) create mode 100644 tests/logging/logging_vty_test.c create mode 100644 tests/logging/logging_vty_test.vty diff --git a/configure.ac b/configure.ac index dd5f15bc..bc3358a0 100644 --- a/configure.ac +++ b/configure.ac @@ -296,6 +296,21 @@ then CPPFLAGS="$CPPFLAGS $WERROR_FLAGS" fi +AC_ARG_ENABLE([external_tests], + AC_HELP_STRING([--enable-external-tests], + [Include the VTY/CTRL tests in make check [default=no]]), + [enable_ext_tests="$enableval"],[enable_ext_tests="no"]) +if test "x$enable_ext_tests" = "xyes" ; then + AM_PATH_PYTHON + AC_CHECK_PROG(OSMOTESTEXT_CHECK,osmo_verify_transcript_vty.py,yes) + if test "x$OSMOTESTEXT_CHECK" != "xyes" ; then + AC_MSG_ERROR([Please install git://osmocom.org/python/osmo-python-tests to run the VTY/CTRL tests.]) + fi +fi +AC_MSG_CHECKING([whether to enable VTY/CTRL tests]) +AC_MSG_RESULT([$enable_ext_tests]) +AM_CONDITIONAL(ENABLE_EXT_TESTS, test "x$enable_ext_tests" = "xyes") + CFLAGS="$CFLAGS -DBUILDING_LIBOSMOCORE -Wall" CPPFLAGS="$CPPFLAGS -DBUILDING_LIBOSMOCORE -Wall" diff --git a/tests/Makefile.am b/tests/Makefile.am index 5d07695a..18d4bb4a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,7 +24,9 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_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 \ - oap/oap_client_test + oap/oap_client_test \ + logging/logging_vty_test \ + $(NULL) if ENABLE_MSGFILE check_PROGRAMS += msgfile/msgfile_test @@ -148,6 +150,9 @@ gb_gprs_ns_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_D logging_logging_test_SOURCES = logging/logging_test.c +logging_logging_vty_test_SOURCES = logging/logging_vty_test.c +logging_logging_vty_test_LDADD = $(LDADD) $(top_builddir)/src/vty/libosmovty.la + fr_fr_test_SOURCES = fr/fr_test.c fr_fr_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ $(top_builddir)/src/vty/libosmovty.la \ @@ -280,6 +285,7 @@ TESTSUITE = $(srcdir)/testsuite check-local: atconfig $(TESTSUITE) cat /proc/cpuinfo $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) + $(MAKE) $(AM_MAKEFLAGS) ext-tests installcheck-local: atconfig $(TESTSUITE) $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ @@ -298,3 +304,25 @@ $(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 conv/gsm0503_test_vectors.c: $(top_srcdir)/utils/conv_gen.py $(top_srcdir)/utils/conv_codes_gsm.py $(AM_V_GEN)python $(top_srcdir)/utils/conv_gen.py gen_vectors gsm \ --target-path $(builddir)/conv + +if ENABLE_EXT_TESTS +ext-tests: +# don't run vty and ctrl tests concurrently so that the ports don't conflict + $(MAKE) vty-test + $(MAKE) ctrl-test +else +ext-tests: + echo "Not running python-based external tests (determined at configure-time)" +endif + +# To update the VTY script from current application behavior, +# pass -u to osmo_verify_transcript_vty.py by doing: +# make vty-test U=-u +vty-test: + osmo_verify_transcript_vty.py -v \ + -p 42042 \ + -r "$(top_builddir)/tests/logging/logging_vty_test" \ + $(U) $(srcdir)/logging/*.vty + +ctrl-test: + echo "No CTRL tests exist currently" diff --git a/tests/logging/logging_vty_test.c b/tests/logging/logging_vty_test.c new file mode 100644 index 00000000..806a460c --- /dev/null +++ b/tests/logging/logging_vty_test.c @@ -0,0 +1,296 @@ +/* test program with a vty interface to test logging behavior */ +/* + * (C) 2018 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 General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#define _GNU_SOURCE +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "config.h" + +void *root_ctx = NULL; + +enum { + DAA, + DBB, + DCCC, + DDDDD, + DEEE, +}; + +DEFUN(log_sweep, log_sweep_cmd, + "log-sweep [CATEGORY]", + "Log once for all categories on all levels\n") +{ + int only_category = argc ? log_parse_category(argv[0]) : -1; + + if (argc && only_category < 0) { + vty_out(vty, "%% Error: unknown category: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + +#define LOG_LEVEL(CAT, LEVEL) \ + if (only_category < 0 || only_category == CAT) \ + LOGP(CAT, LEVEL, "Log message for " #CAT " on level " #LEVEL "\n") + +#define LOG_ALL_LEVELS(CAT) \ + LOG_LEVEL(CAT, LOGL_DEBUG); \ + LOG_LEVEL(CAT, LOGL_INFO); \ + LOG_LEVEL(CAT, LOGL_NOTICE); \ + LOG_LEVEL(CAT, LOGL_ERROR); \ + LOG_LEVEL(CAT, LOGL_FATAL) + + LOG_ALL_LEVELS(DAA); + LOG_ALL_LEVELS(DBB); + LOG_ALL_LEVELS(DCCC); + LOG_ALL_LEVELS(DDDDD); + LOG_ALL_LEVELS(DEEE); + + vty_out(vty, "%s", VTY_NEWLINE); + + return CMD_SUCCESS; +} + +static void vty_commands_init() +{ + install_element_ve(&log_sweep_cmd); +} + +static const struct log_info_cat default_categories[] = { + [DAA] = { + .name = "DAA", + .description = "Antropomorphic Armadillos (AA)", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, + [DBB] = { + .name = "DBB", + .description = "Bidirectional Breadspread (BB)", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_INFO, + }, + [DCCC] = { + .name = "DCCC", + .description = "Chaos Communication Congress (CCC)", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DDDDD] = { + .name = "DDDDD", + .description = "Dehydrated Dribbling Duck Dunkers (DDDD)", + .color = "\033[1;34m", + .enabled = 1, .loglevel = LOGL_ERROR, + }, + [DEEE] = { + .name = "DEEE", + .description = "Exhaustive Entropy Extraction (EEE)", + .color = "\033[1;35m", + .enabled = 1, .loglevel = LOGL_FATAL, + }, +}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +static void print_help() +{ + printf( "options:\n" + " -h --help this text\n" + " -d --debug MASK Enable debugging (e.g. -d DRSL:DOML:DLAPDM)\n" + " -D --daemonize For the process into a background daemon\n" + " -c --config-file Specify the filename of the config file\n" + " -s --disable-color Don't use colors in stderr log output\n" + " -T --timestamp Prefix every log line with a timestamp\n" + " -V --version Print version information and exit\n" + " -e --log-level Set a global log-level\n" + ); +} + +static struct { + const char *config_file; + int daemonize; +} cmdline_config = {}; + +static void handle_options(int argc, char **argv) +{ + while (1) { + int option_idx = 0, c; + static const struct option long_options[] = { + { "help", 0, 0, 'h' }, + { "debug", 1, 0, 'd' }, + { "daemonize", 0, 0, 'D' }, + { "config-file", 1, 0, 'c' }, + { "disable-color", 0, 0, 's' }, + { "timestamp", 0, 0, 'T' }, + { "version", 0, 0, 'V' }, + { "log-level", 1, 0, 'e' }, + {} + }; + + c = getopt_long(argc, argv, "hc:d:Dc:sTVe:", + long_options, &option_idx); + if (c == -1) + break; + + switch (c) { + case 'h': + print_help(); + exit(0); + case 's': + log_set_use_color(osmo_stderr_target, 0); + break; + case 'd': + log_parse_category_mask(osmo_stderr_target, optarg); + break; + case 'D': + cmdline_config.daemonize = 1; + break; + case 'c': + cmdline_config.config_file = optarg; + break; + case 'T': + log_set_print_timestamp(osmo_stderr_target, 1); + break; + case 'e': + log_set_log_level(osmo_stderr_target, atoi(optarg)); + break; + case 'V': + print_version(1); + exit(0); + break; + default: + /* catch unknown options *as well as* missing arguments. */ + fprintf(stderr, "Error in command line options. Exiting.\n"); + exit(-1); + } + } +} + +static int quit = 0; + +static void signal_handler(int signal) +{ + fprintf(stdout, "signal %u received\n", signal); + + switch (signal) { + case SIGINT: + case SIGTERM: + quit++; + break; + case SIGABRT: + osmo_generate_backtrace(); + /* in case of abort, we want to obtain a talloc report + * and then return to the caller, who will abort the process */ + case SIGUSR1: + talloc_report(tall_vty_ctx, stderr); + talloc_report_full(root_ctx, stderr); + break; + case SIGUSR2: + talloc_report_full(tall_vty_ctx, stderr); + break; + default: + break; + } +} + +static struct vty_app_info vty_info = { + .name = "logging_vty_test", + .version = PACKAGE_VERSION, +}; + +int main(int argc, char **argv) +{ + int rc; + + root_ctx = talloc_named_const(NULL, 0, "logging_vty_test"); + + vty_info.tall_ctx = root_ctx; + vty_init(&vty_info); + + osmo_init_logging2(root_ctx, &log_info); + + vty_commands_init(); + + handle_options(argc, argv); + + logging_vty_add_cmds(&log_info); + osmo_talloc_vty_add_cmds(); + + log_set_print_category(osmo_stderr_target, 1); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_print_level(osmo_stderr_target, 1); + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + + if (cmdline_config.config_file) { + rc = vty_read_config_file(cmdline_config.config_file, NULL); + if (rc < 0) { + LOGP(DLGLOBAL, LOGL_FATAL, "Failed to parse the config file: '%s'\n", + cmdline_config.config_file); + return 1; + } + } + + rc = telnet_init_dynif(root_ctx, NULL, vty_get_bind_addr(), 42042); + if (rc < 0) + return 2; + + signal(SIGINT, &signal_handler); + signal(SIGTERM, &signal_handler); + signal(SIGABRT, &signal_handler); + signal(SIGUSR1, &signal_handler); + signal(SIGUSR2, &signal_handler); + osmo_init_ignore_signals(); + + if (cmdline_config.daemonize) { + rc = osmo_daemonize(); + if (rc < 0) { + perror("Error during daemonize"); + return 6; + } + } + + while (!quit) { + log_reset_context(); + osmo_select_main(0); + } + + log_fini(); + + talloc_free(root_ctx); + talloc_free(tall_vty_ctx); + + return 0; +} diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty new file mode 100644 index 00000000..c57b70f8 --- /dev/null +++ b/tests/logging/logging_vty_test.vty @@ -0,0 +1,190 @@ +logging_vty_test> enable + +logging_vty_test# ! Note that 'logging level all everything' is still printed! +logging_vty_test# show running-config +... +log stderr +... + logging level all everything + logging level aa debug + logging level bb info + logging level ccc notice + logging level dddd error + logging level eee fatal +... + +logging_vty_test# configure terminal +logging_vty_test(config)# no log stderr +logging_vty_test(config)# exit + +logging_vty_test# logging enable +logging_vty_test# logging filter all 1 +logging_vty_test# logging print category-hex 0 +logging_vty_test# logging print category 1 +logging_vty_test# logging print level 1 +logging_vty_test# logging color 0 +logging_vty_test# logging print file 0 + + +logging_vty_test# list +... !logging + logging enable + logging disable + logging filter all (0|1) + logging color (0|1) + logging timestamp (0|1) + logging print extended-timestamp (0|1) + logging print category (0|1) + logging print category-hex (0|1) + logging print level (0|1) + logging print file (0|1|basename) [last] + logging set-log-mask MASK + logging level (all|aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (everything|debug|info|notice|error|fatal) + show logging vty +... !logging + +logging_vty_test# logging ? + enable Enables logging to this vty + disable Disables logging to this vty + filter Filter log messages + color Configure color-printing for log messages + timestamp Configure log message timestamping + print Log output settings + set-log-mask Set the logmask of this logging target + level Set the log level for a specified category + +logging_vty_test# logging level ? + all Global setting for all subsystems + aa Antropomorphic Armadillos (AA) + bb Bidirectional Breadspread (BB) + ccc Chaos Communication Congress (CCC) + dddd Dehydrated Dribbling Duck Dunkers (DDDD) + eee Exhaustive Entropy Extraction (EEE) + lglobal Library-internal global log family +... + +logging_vty_test# logging level aa ? + everything Don't use. It doesn't log anything + debug Log debug messages and higher levels + info Log informational messages and higher levels + notice Log noticeable messages and higher levels + error Log error messages and higher levels + fatal Log only fatal messages + +logging_vty_test# logging level all ? + everything Don't use. It doesn't log anything + debug Log debug messages and higher levels + info Log informational messages and higher levels + notice Log noticeable messages and higher levels + error Log error messages and higher levels + fatal Log only fatal messages + + +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level all fatal +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level all error +logging_vty_test# log-sweep +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level all notice +logging_vty_test# log-sweep +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level all debug +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB DEBUG Log message for DBB on level LOGL_DEBUG +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC DEBUG Log message for DCCC on level LOGL_DEBUG +DCCC INFO Log message for DCCC on level LOGL_INFO +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD DEBUG Log message for DDDDD on level LOGL_DEBUG +DDDDD INFO Log message for DDDDD on level LOGL_INFO +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE DEBUG Log message for DEEE on level LOGL_DEBUG +DEEE INFO Log message for DEEE on level LOGL_INFO +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# ! 'logging level all' overrides everything, be it stronger or weaker +logging_vty_test# logging level all notice +logging_vty_test# logging level eee debug +logging_vty_test# log-sweep eee +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level all notice +logging_vty_test# logging level eee fatal +logging_vty_test# log-sweep eee +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# ! Old 'logging level all everything' has no effect +logging_vty_test# logging level all everything +% Ignoring deprecated logging level everything +logging_vty_test# log-sweep eee +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# ! There is currently no way to remove the 'logging level all' level! -- cgit v1.2.3 From 2c79d55934f033dd18a61c309c0487f3c5d81961 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 13 Sep 2018 05:36:32 +0200 Subject: gsm0808: implement BSSMAP Classmark Request Related: OS#3043 Change-Id: I4a2e1d3923e33912579c4180aa1ff8e8f5abb7e7 --- include/osmocom/gsm/gsm0808.h | 1 + src/gsm/gsm0808.c | 13 +++++++++++++ src/gsm/libosmogsm.map | 1 + 3 files changed, 15 insertions(+) diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 5ae0af83..f4fc7c4c 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -51,6 +51,7 @@ struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei, const uint8_t *cipher_response_mode); struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); struct msgb *gsm0808_create_cipher_reject(uint8_t cause); +struct msgb *gsm0808_create_classmark_request(); struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len, const uint8_t *cm3, uint8_t cm3_len); struct msgb *gsm0808_create_sapi_reject(uint8_t link_id); diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index e3b10d0c..9a9f70ee 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -341,6 +341,19 @@ struct msgb *gsm0808_create_lcls_notification(enum gsm0808_lcls_status status, b return msg; } +/*! Create BSSMAP Classmark Request message + * \returns callee-allocated msgb with BSSMAP Classmark Request message */ +struct msgb *gsm0808_create_classmark_request() +{ + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "classmark-request"); + if (!msg) + return NULL; + + msgb_v_put(msg, BSS_MAP_MSG_CLASSMARK_RQST); + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + return msg; +} /*! Create BSSMAP Classmark Update message * \param[in] cm2 Classmark 2 diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 60d6ed84..0c40c88c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -156,6 +156,7 @@ gsm0808_create_ass_fail; gsm0808_create_cipher; gsm0808_create_cipher_complete; gsm0808_create_cipher_reject; +gsm0808_create_classmark_request; gsm0808_create_classmark_update; gsm0808_create_clear_command; gsm0808_create_clear_complete; -- cgit v1.2.3 From d79f01e0a610260524e976149d31a5c2d3b83c94 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 12 Sep 2018 02:53:54 +0200 Subject: jenkins: add --enable-external-tests Run the new logging_vty_test.vty VTY transcript test in our CI. Change-Id: Ic4ec1f6c131da50b3956f16f0b49375f387196b3 --- contrib/jenkins_amd64.sh | 3 ++- contrib/jenkins_arm.sh | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/contrib/jenkins_amd64.sh b/contrib/jenkins_amd64.sh index c3af378c..cd7b6661 100755 --- a/contrib/jenkins_amd64.sh +++ b/contrib/jenkins_amd64.sh @@ -15,7 +15,8 @@ build() { prep_build "$src_dir" "$build_dir" - "$src_dir"/configure --disable-silent-rules --enable-static $ENABLE_SANITIZE --enable-werror + "$src_dir"/configure --disable-silent-rules --enable-static $ENABLE_SANITIZE --enable-werror \ + --enable-external-tests run_make } diff --git a/contrib/jenkins_arm.sh b/contrib/jenkins_arm.sh index 1d72f2f5..e3a6cd14 100755 --- a/contrib/jenkins_arm.sh +++ b/contrib/jenkins_arm.sh @@ -18,6 +18,7 @@ build() { --enable-embedded \ --disable-doxygen \ --disable-shared \ + --enable-external-tests \ CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs $WERROR_FLAGS" $MAKE $PARALLEL_MAKE -- cgit v1.2.3 From ba0762d6cbcb8204212d28261e71b57bbc9ba5bc Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 10 Sep 2018 13:56:03 +0200 Subject: logging vty: rewrite 'logging level' vty cmd generation Completely drop the implementations of log_vty_command_{str,description}(). These functions have been public API once, marked as deprecated since c65c5b4ea075ef6cef11fff9442ae0b15c1d6af7 (March 2017). I considered to keep them, or reduce them to useless stubs, but it is quite silly, really. These functions are completely and utterly useless outside of libosmocore. Any program linking these deserves to fail. Re-implement vty logging level command gen, in logging_vty.c. logging.c is simply the wrong place for that. Introduce logging_internal.h to share logging definitions to logging_vty.c without publishing as API. Introduce static gen_logging_level_cmd_strs() to compose a list of category arguments with their descriptions for VTY commands. Use osmo_talloc_asprintf() instead of the previous error prone and chaotic strlen() counting method. Do not dynamically generate log level arguments, just keep static strings. We are super unlikely to ever change the log levels we have. No changes in logging_vty_test.vty: proves that there is no functional change. All of this, besides introducing basic sanity, is cosmetic preparation to be able to re-use the generic command generation code for arbitrary commands with category or level args (for deprecated and new keywords). Rationale: I want to hide 'all' and 'everything' from the VTY command documentation, by means of deprecating. I first tried to simply define a deprecated 'logging level CAT everything' command: logging level (all|rsl|rr|...) (debug|info|notice|error|fatal) logging level CAT everything # <- deprecated and hidden But unfortunately, command matching doesn't work as intended when the CAT argument reflects a valid category; I want it to invoke the deprecated function as soon as the 'everything' keyword follows, but it stays stuck to the "valid" command when the category argument matches an explicit keyword in that list, and will throw an error on the following 'everything' keyword. I.e.: logging level rsl everything % Unknown command # <-- leads to config file parse error logging level unknown_string everything % Ignoring deprecated 'everything' # <-- works only for invalid categories So I need to define 'everything' separately, again with a list of each valid category instead of a generic CAT arg. Change-Id: I3b083f27e3d751ccec258880ae7676e9af959a63 --- include/Makefile.am | 5 +- include/osmocom/core/logging.h | 4 - include/osmocom/core/logging_internal.h | 14 +++ src/logging.c | 164 +------------------------------- src/vty/logging_vty.c | 67 +++++++++++-- 5 files changed, 82 insertions(+), 172 deletions(-) create mode 100644 include/osmocom/core/logging_internal.h diff --git a/include/Makefile.am b/include/Makefile.am index ef8ec656..19695d1b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -152,7 +152,10 @@ nobase_include_HEADERS += \ endif noinst_HEADERS = \ - osmocom/gsm/kasumi.h osmocom/gsm/gea.h + osmocom/gsm/kasumi.h \ + osmocom/gsm/gea.h \ + osmocom/core/logging_internal.h \ + $(NULL) osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl $(AM_V_GEN)$(MKDIR_P) $(dir $@) diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index c60143d9..295e5a85 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -374,10 +374,6 @@ int log_targets_reopen(void); void log_add_target(struct log_target *target); void log_del_target(struct log_target *target); -/* Generate command string for VTY use */ -const char *log_vty_command_string() OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; -const char *log_vty_command_description() OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; - struct log_target *log_target_find(int type, const char *fname); extern struct llist_head osmo_log_target_list; diff --git a/include/osmocom/core/logging_internal.h b/include/osmocom/core/logging_internal.h new file mode 100644 index 00000000..55b1bbd8 --- /dev/null +++ b/include/osmocom/core/logging_internal.h @@ -0,0 +1,14 @@ +#pragma once + +/*! \defgroup logging_internal Osmocom logging internals + * @{ + * \file logging_internal.h */ + +#include + +extern void *tall_log_ctx; +extern const struct log_info *osmo_log_info; + +void assert_loginfo(const char *src); + +/*! @} */ diff --git a/src/logging.c b/src/logging.c index de0f2b0f..7c2d61ff 100644 --- a/src/logging.c +++ b/src/logging.c @@ -35,7 +35,6 @@ #include #include #include -#include #ifdef HAVE_STRINGS_H #include @@ -61,12 +60,10 @@ osmo_static_assert(_LOG_FLT_COUNT <= 8*sizeof(((struct log_target*)NULL)->filter struct log_info *osmo_log_info; static struct log_context log_context; -static void *tall_log_ctx = NULL; +void *tall_log_ctx = NULL; LLIST_HEAD(osmo_log_target_list); -#define LOGLEVEL_DEFS 6 /* Number of loglevels.*/ - -static const struct value_string loglevel_strs[LOGLEVEL_DEFS+1] = { +static const struct value_string loglevel_strs[] = { { 0, "EVERYTHING" }, { LOGL_DEBUG, "DEBUG" }, { LOGL_INFO, "INFO" }, @@ -175,19 +172,7 @@ static const struct log_info_cat internal_cat[OSMO_NUM_DLIB] = { }, }; -/*! descriptive string for each log level */ -/* You have to keep this in sync with the structure loglevel_strs. */ -static const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { - "Don't use. It doesn't log anything", - "Log debug messages and higher levels", - "Log informational messages and higher levels", - "Log noticeable messages and higher levels", - "Log error messages and higher levels", - "Log only fatal messages", - NULL, -}; - -static void assert_loginfo(const char *src) +void assert_loginfo(const char *src) { if (!osmo_log_info) { fprintf(stderr, "ERROR: osmo_log_info == NULL! " @@ -963,149 +948,6 @@ int log_targets_reopen(void) return rc; } -/*! Generates the logging command string for VTY - * \param[in] unused_info Deprecated parameter, no longer used! - * \returns vty command string for use by VTY command node - */ -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 (all|) ()") + 1; - char *str; - - assert_loginfo(__func__); - - for (i = 0; i < info->num_cat; i++) { - if (info->cat[i].name == NULL) - continue; - size += strlen(info->cat[i].name) + 1; - } - - for (i = 0; i < LOGLEVEL_DEFS; i++) - size += strlen(loglevel_strs[i].str) + 1; - - rem = size; - str = talloc_zero_size(tall_log_ctx, size); - if (!str) - return NULL; - - ret = snprintf(str + offset, rem, "logging level (all|"); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - - for (i = 0; i < info->num_cat; i++) { - if (info->cat[i].name) { - int j, name_len = strlen(info->cat[i].name)+1; - char name[name_len]; - - for (j = 0; j < name_len; j++) - name[j] = tolower((unsigned char)info->cat[i].name[j]); - - name[name_len-1] = '\0'; - ret = snprintf(str + offset, rem, "%s|", name+1); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - } - offset--; /* to remove the trailing | */ - rem++; - - ret = snprintf(str + offset, rem, ") ("); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - - for (i = 0; i < LOGLEVEL_DEFS; i++) { - int j, loglevel_str_len = strlen(loglevel_strs[i].str)+1; - char loglevel_str[loglevel_str_len]; - - for (j = 0; j < loglevel_str_len; j++) - loglevel_str[j] = tolower((unsigned char)loglevel_strs[i].str[j]); - - loglevel_str[loglevel_str_len-1] = '\0'; - ret = snprintf(str + offset, rem, "%s|", loglevel_str); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - offset--; /* to remove the trailing | */ - rem++; - - ret = snprintf(str + offset, rem, ")"); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); -err: - str[size-1] = '\0'; - return str; -} - -/*! Generates the logging command description for VTY - * \param[in] unused_info Deprecated parameter, no longer used! - * \returns logging command description for use by VTY command node - */ -const char *log_vty_command_description() -{ - struct log_info *info = osmo_log_info; - char *str; - int i, ret, len = 0, offset = 0, rem; - unsigned int size = - strlen(LOGGING_STR - "Set the log level for a specified category\n") + 1; - - assert_loginfo(__func__); - - for (i = 0; i < info->num_cat; i++) { - if (info->cat[i].name == NULL) - continue; - size += strlen(info->cat[i].description) + 1; - } - - for (i = 0; i < LOGLEVEL_DEFS; i++) - size += strlen(loglevel_descriptions[i]) + 1; - - size += strlen("Global setting for all subsystems") + 1; - rem = size; - str = talloc_zero_size(tall_log_ctx, size); - if (!str) - return NULL; - - ret = snprintf(str + offset, rem, LOGGING_STR - "Set the log level for a specified category\n"); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - - ret = snprintf(str + offset, rem, - "Global setting for all subsystems\n"); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - - for (i = 0; i < info->num_cat; i++) { - if (info->cat[i].name == NULL) - continue; - ret = snprintf(str + offset, rem, "%s\n", - info->cat[i].description); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - for (i = 0; i < LOGLEVEL_DEFS; i++) { - ret = snprintf(str + offset, rem, "%s\n", - loglevel_descriptions[i]); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } -err: - str[size-1] = '\0'; - return str; -} - /*! Initialize the Osmocom logging core * \param[in] inf Information regarding logging categories * \param[in] ctx \ref talloc context for logging allocations diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 7d97bb1d..2b001bc9 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,19 @@ #include #define LOG_STR "Configure logging sub-system\n" +#define LEVEL_STR "Set the log level for a specified category\n" + +#define CATEGORY_ALL_STR "Global setting for all subsystems\n" + +#define LOG_LEVEL_ARGS "debug|info|notice|error|fatal" +#define LOG_LEVEL_STRS \ + "Log debug messages and higher levels\n" \ + "Log informational messages and higher levels\n" \ + "Log noticeable messages and higher levels\n" \ + "Log error messages and higher levels\n" \ + "Log only fatal messages\n" + +#define EVERYTHING_STR "Don't use. It doesn't log anything\n" /*! \file logging_vty.c * Configuration of logging from VTY @@ -58,8 +72,6 @@ * */ -extern const struct log_info *osmo_log_info; - static void _vty_output(struct log_target *tgt, unsigned int level, const char *line) { @@ -268,6 +280,47 @@ DEFUN(logging_prnt_file, return CMD_SUCCESS; } +static void add_category_strings(char **cmd_str_p, char **doc_str_p, + const struct log_info *categories) +{ + int i; + for (i = 0; i < categories->num_cat; i++) { + if (categories->cat[i].name == NULL) + continue; + /* skip the leading 'D' in each category name, hence '+ 1' */ + osmo_talloc_asprintf(tall_log_ctx, *cmd_str_p, "%s%s", + i ? "|" : "", + osmo_str_tolower(categories->cat[i].name + 1)); + osmo_talloc_asprintf(tall_log_ctx, *doc_str_p, "%s\n", + categories->cat[i].description); + } +} + +static void gen_logging_level_cmd_strs(struct cmd_element *cmd, + const char *level_args, const char *level_strs) +{ + char *cmd_str = NULL; + char *doc_str = NULL; + + assert_loginfo(__func__); + + OSMO_ASSERT(cmd->string == NULL); + OSMO_ASSERT(cmd->doc == NULL); + + osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logging level (all|"); + osmo_talloc_asprintf(tall_log_ctx, doc_str, + LOGGING_STR + LEVEL_STR + CATEGORY_ALL_STR); + add_category_strings(&cmd_str, &doc_str, osmo_log_info); + osmo_talloc_asprintf(tall_log_ctx, cmd_str, ") %s", level_args); + osmo_talloc_asprintf(tall_log_ctx, doc_str, "%s", level_strs); + + cmd->string = cmd_str; + cmd->doc = doc_str; +} + +/* logging level (all|) (everything|debug|...|fatal) */ DEFUN(logging_level, logging_level_cmd, NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ @@ -847,7 +900,7 @@ void logging_vty_add_deprecated_subsys(void *ctx, const char *name) name); printf("%s\n", cmd->string); cmd->func = log_deprecated_func; - cmd->doc = "Set the log level for a specified category\n" + cmd->doc = LEVEL_STR "Deprecated Category\n"; cmd->attr = CMD_ATTR_DEPRECATED; @@ -871,9 +924,11 @@ void logging_vty_add_cmds() install_element_ve(&logging_set_category_mask_cmd); install_element_ve(&logging_set_category_mask_old_cmd); - /* Logging level strings are generated dynamically. */ - logging_level_cmd.string = log_vty_command_string(); - logging_level_cmd.doc = log_vty_command_description(); + /* logging level (all|) (everything|debug|...|fatal) */ + gen_logging_level_cmd_strs(&logging_level_cmd, + "(everything|" LOG_LEVEL_ARGS ")", + EVERYTHING_STR LOG_LEVEL_STRS); + install_element_ve(&logging_level_cmd); install_element_ve(&show_logging_vty_cmd); install_element_ve(&show_alarms_cmd); -- cgit v1.2.3 From 7e0686c6b4b456ec4e6e15689694b1bcf96c301f Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 10 Sep 2018 20:58:52 +0200 Subject: logging vty: deprecate the 'everything' keyword The 'logging level all everything' has not had an effect for some time now. The plan is to bring back its old functionality, but to keep it deprecated and rather define a less confusing name. * Deprecate 'everything'. * Do not write 'everything' during 'write file' or 'show running-config', which we curiously still do until now. BTW, the reason why we need to compose a complete list of categories for the deprecated 'everything' command is explained in detail in the commit log for I3b083f27e3d751ccec258880ae7676e9af959a63 Change-Id: Ib75fedb0572570a61bb34ee729a2af86cf5f16da --- src/logging.c | 1 - src/vty/logging_vty.c | 34 ++++++++++++++++++++++------------ tests/logging/logging_vty_test.vty | 30 +++++++++++++----------------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/logging.c b/src/logging.c index 7c2d61ff..67470a5d 100644 --- a/src/logging.c +++ b/src/logging.c @@ -64,7 +64,6 @@ void *tall_log_ctx = NULL; LLIST_HEAD(osmo_log_target_list); static const struct value_string loglevel_strs[] = { - { 0, "EVERYTHING" }, { LOGL_DEBUG, "DEBUG" }, { LOGL_INFO, "INFO" }, { LOGL_NOTICE, "NOTICE" }, diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 2b001bc9..6758dd22 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -320,7 +320,7 @@ static void gen_logging_level_cmd_strs(struct cmd_element *cmd, cmd->doc = doc_str; } -/* logging level (all|) (everything|debug|...|fatal) */ +/* logging level (all|) (debug|...|fatal) */ DEFUN(logging_level, logging_level_cmd, NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ @@ -338,11 +338,6 @@ DEFUN(logging_level, return CMD_WARNING; } - if (strcmp(argv[1], "everything") == 0) { /* FIXME: remove this check once 'everything' is phased out */ - vty_out(vty, "%% Ignoring deprecated logging level %s%s", argv[1], VTY_NEWLINE); - return CMD_SUCCESS; - } - /* Check for special case where we want to set global log level */ if (!strcmp(argv[0], "all")) { log_set_log_level(tgt, level); @@ -360,6 +355,15 @@ DEFUN(logging_level, return CMD_SUCCESS; } +/* logging level (all|) everything */ +DEFUN_DEPRECATED(deprecated_logging_level_everything, deprecated_logging_level_everything_cmd, + NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ + NULL) /* same thing for helpstr. */ +{ + vty_out(vty, "%% Ignoring deprecated logging level 'everything' keyword%s", VTY_NEWLINE); + return CMD_SUCCESS; +} + DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, "logging set-log-mask MASK", @@ -858,8 +862,9 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) VTY_NEWLINE); /* stupid old osmo logging API uses uppercase strings... */ - vty_out(vty, " logging level all %s%s", osmo_str_tolower(log_level_str(tgt->loglevel)), - VTY_NEWLINE); + if (tgt->loglevel) + vty_out(vty, " logging level all %s%s", osmo_str_tolower(log_level_str(tgt->loglevel)), + VTY_NEWLINE); for (i = 0; i < osmo_log_info->num_cat; i++) { const struct log_category *cat = &tgt->categories[i]; @@ -896,7 +901,7 @@ void logging_vty_add_deprecated_subsys(void *ctx, const char *name) { struct cmd_element *cmd = talloc_zero(ctx, struct cmd_element); OSMO_ASSERT(cmd); - cmd->string = talloc_asprintf(cmd, "logging level %s (everything|debug|info|notice|error|fatal)", + cmd->string = talloc_asprintf(cmd, "logging level %s (debug|info|notice|error|fatal)", name); printf("%s\n", cmd->string); cmd->func = log_deprecated_func; @@ -924,12 +929,16 @@ void logging_vty_add_cmds() install_element_ve(&logging_set_category_mask_cmd); install_element_ve(&logging_set_category_mask_old_cmd); - /* logging level (all|) (everything|debug|...|fatal) */ + /* logging level (all|) (debug|...|fatal) */ gen_logging_level_cmd_strs(&logging_level_cmd, - "(everything|" LOG_LEVEL_ARGS ")", - EVERYTHING_STR LOG_LEVEL_STRS); + "(" LOG_LEVEL_ARGS ")", + LOG_LEVEL_STRS); + /* logging level (all|) everything */ + gen_logging_level_cmd_strs(&deprecated_logging_level_everything_cmd, + "everything", EVERYTHING_STR); install_element_ve(&logging_level_cmd); + install_element_ve(&deprecated_logging_level_everything_cmd); install_element_ve(&show_logging_vty_cmd); install_element_ve(&show_alarms_cmd); @@ -943,6 +952,7 @@ void logging_vty_add_cmds() install_element(CFG_LOG_NODE, &logging_prnt_level_cmd); install_element(CFG_LOG_NODE, &logging_prnt_file_cmd); install_element(CFG_LOG_NODE, &logging_level_cmd); + install_element(CFG_LOG_NODE, &deprecated_logging_level_everything_cmd); install_element(CONFIG_NODE, &cfg_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index c57b70f8..a2c1e74b 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -1,11 +1,9 @@ logging_vty_test> enable -logging_vty_test# ! Note that 'logging level all everything' is still printed! logging_vty_test# show running-config ... log stderr -... - logging level all everything +... !logging level all logging level aa debug logging level bb info logging level ccc notice @@ -39,7 +37,7 @@ logging_vty_test# list logging print level (0|1) logging print file (0|1|basename) [last] logging set-log-mask MASK - logging level (all|aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (everything|debug|info|notice|error|fatal) + logging level (all|aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal) show logging vty ... !logging @@ -64,20 +62,18 @@ logging_vty_test# logging level ? ... logging_vty_test# logging level aa ? - everything Don't use. It doesn't log anything - debug Log debug messages and higher levels - info Log informational messages and higher levels - notice Log noticeable messages and higher levels - error Log error messages and higher levels - fatal Log only fatal messages + debug Log debug messages and higher levels + info Log informational messages and higher levels + notice Log noticeable messages and higher levels + error Log error messages and higher levels + fatal Log only fatal messages logging_vty_test# logging level all ? - everything Don't use. It doesn't log anything - debug Log debug messages and higher levels - info Log informational messages and higher levels - notice Log noticeable messages and higher levels - error Log error messages and higher levels - fatal Log only fatal messages + debug Log debug messages and higher levels + info Log informational messages and higher levels + notice Log noticeable messages and higher levels + error Log error messages and higher levels + fatal Log only fatal messages logging_vty_test# log-sweep @@ -181,7 +177,7 @@ DEEE FATAL Log message for DEEE on level LOGL_FATAL logging_vty_test# ! Old 'logging level all everything' has no effect logging_vty_test# logging level all everything -% Ignoring deprecated logging level everything +% Ignoring deprecated logging level 'everything' keyword logging_vty_test# log-sweep eee DEEE NOTICE Log message for DEEE on level LOGL_NOTICE DEEE ERROR Log message for DEEE on level LOGL_ERROR -- cgit v1.2.3 From 098038ab181a24d6050413a409b1bcb327d21ea6 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 11 Sep 2018 23:49:13 +0200 Subject: logging vty: write: check logging levels validity Change-Id: If683b1272ad2d5b402b91c52c496aa7975bc6315 --- include/osmocom/core/logging_internal.h | 1 + src/logging.c | 2 +- src/vty/logging_vty.c | 30 +++++++++++++++++++++++------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/osmocom/core/logging_internal.h b/include/osmocom/core/logging_internal.h index 55b1bbd8..a510f83e 100644 --- a/include/osmocom/core/logging_internal.h +++ b/include/osmocom/core/logging_internal.h @@ -8,6 +8,7 @@ extern void *tall_log_ctx; extern const struct log_info *osmo_log_info; +extern const struct value_string loglevel_strs[]; void assert_loginfo(const char *src); diff --git a/src/logging.c b/src/logging.c index 67470a5d..e7cc4729 100644 --- a/src/logging.c +++ b/src/logging.c @@ -63,7 +63,7 @@ static struct log_context log_context; void *tall_log_ctx = NULL; LLIST_HEAD(osmo_log_target_list); -static const struct value_string loglevel_strs[] = { +const struct value_string loglevel_strs[] = { { LOGL_DEBUG, "DEBUG" }, { LOGL_INFO, "INFO" }, { LOGL_NOTICE, "NOTICE" }, diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 6758dd22..c8e85209 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -861,21 +861,37 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) get_value_string(logging_print_file_args, tgt->print_filename2), VTY_NEWLINE); - /* stupid old osmo logging API uses uppercase strings... */ - if (tgt->loglevel) - vty_out(vty, " logging level all %s%s", osmo_str_tolower(log_level_str(tgt->loglevel)), - VTY_NEWLINE); + if (tgt->loglevel) { + const char *level_str = get_value_string_or_null(loglevel_strs, tgt->loglevel); + level_str = osmo_str_tolower(level_str); + if (!level_str) + vty_out(vty, "%% Invalid log level %u for 'all'%s", tgt->loglevel, VTY_NEWLINE); + else + vty_out(vty, " logging level all %s%s", level_str, VTY_NEWLINE); + } for (i = 0; i < osmo_log_info->num_cat; i++) { const struct log_category *cat = &tgt->categories[i]; + const char *cat_name; + const char *level_str; /* skip empty entries in the array */ if (!osmo_log_info->cat[i].name) continue; - /* stupid old osmo logging API uses uppercase strings... */ - vty_out(vty, " logging level %s", osmo_str_tolower(osmo_log_info->cat[i].name+1)); - vty_out(vty, " %s%s", osmo_str_tolower(log_level_str(cat->loglevel)), VTY_NEWLINE); + /* Note: cat_name references the static buffer returned by osmo_str_tolower(), will + * become invalid after next osmo_str_tolower() invocation. */ + cat_name = osmo_str_tolower(osmo_log_info->cat[i].name+1); + + level_str = get_value_string_or_null(loglevel_strs, cat->loglevel); + if (!level_str) { + vty_out(vty, "%% Invalid log level %u for %s%s", cat->loglevel, cat_name, + VTY_NEWLINE); + continue; + } + + vty_out(vty, " logging level %s", cat_name); + vty_out(vty, " %s%s", osmo_str_tolower(level_str), VTY_NEWLINE); } return 1; -- cgit v1.2.3 From 9540c24058c9c6ad1425b820b9f3c458d177a345 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 12 Sep 2018 00:20:50 +0200 Subject: logging vty: deprecate 'all', introduce 'force-all' Add 'logging level force-all ' and 'no logging level force-all' as new names for 'logging level all ' and 'logging level all everything'. Resurrect the functionality of 'logging level all everything' -- even if it is still deprecated because the name is confusing, it is now just an alias for 'no logging level force-all'. Show in logging_vty_test.vty that we can now again lift the global logging clamp, both with the new commands as well as with the deprecated ones. Also show that 'force-all' is written back properly, if set. Change-Id: I36f17c131cc70ce5a1aef62fd9693097de230cd4 --- src/vty/logging_vty.c | 77 ++++++++++++++----- tests/logging/logging_vty_test.vty | 148 +++++++++++++++++++++++++++++++++---- 2 files changed, 191 insertions(+), 34 deletions(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index c8e85209..3b1d8c65 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -43,9 +43,15 @@ #define LOG_STR "Configure logging sub-system\n" #define LEVEL_STR "Set the log level for a specified category\n" -#define CATEGORY_ALL_STR "Global setting for all subsystems\n" - -#define LOG_LEVEL_ARGS "debug|info|notice|error|fatal" +#define CATEGORY_ALL_STR "Deprecated alias for 'force-all'\n" +#define FORCE_ALL_STR \ + "Globally force all logging categories to a specific level. This is released by the" \ + " 'no logging level force-all' command. Note: any 'logging level '" \ + " commands will have no visible effect after this, until the forced level is released.\n" +#define NO_FORCE_ALL_STR \ + "Release any globally forced log level set with 'logging level force-all '\n" + +#define LOG_LEVEL_ARGS "(debug|info|notice|error|fatal)" #define LOG_LEVEL_STRS \ "Log debug messages and higher levels\n" \ "Log informational messages and higher levels\n" \ @@ -53,7 +59,7 @@ "Log error messages and higher levels\n" \ "Log only fatal messages\n" -#define EVERYTHING_STR "Don't use. It doesn't log anything\n" +#define EVERYTHING_STR "Deprecated alias for 'no logging level force-all'\n" /*! \file logging_vty.c * Configuration of logging from VTY @@ -307,11 +313,10 @@ static void gen_logging_level_cmd_strs(struct cmd_element *cmd, OSMO_ASSERT(cmd->string == NULL); OSMO_ASSERT(cmd->doc == NULL); - osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logging level (all|"); + osmo_talloc_asprintf(tall_log_ctx, cmd_str, "logging level ("); osmo_talloc_asprintf(tall_log_ctx, doc_str, LOGGING_STR - LEVEL_STR - CATEGORY_ALL_STR); + LEVEL_STR); add_category_strings(&cmd_str, &doc_str, osmo_log_info); osmo_talloc_asprintf(tall_log_ctx, cmd_str, ") %s", level_args); osmo_talloc_asprintf(tall_log_ctx, doc_str, "%s", level_strs); @@ -320,7 +325,7 @@ static void gen_logging_level_cmd_strs(struct cmd_element *cmd, cmd->doc = doc_str; } -/* logging level (all|) (debug|...|fatal) */ +/* logging level () (debug|...|fatal) */ DEFUN(logging_level, logging_level_cmd, NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ @@ -338,12 +343,6 @@ DEFUN(logging_level, return CMD_WARNING; } - /* Check for special case where we want to set global log level */ - if (!strcmp(argv[0], "all")) { - log_set_log_level(tgt, level); - return CMD_SUCCESS; - } - if (category < 0) { vty_out(vty, "Invalid category `%s'%s", argv[0], VTY_NEWLINE); return CMD_WARNING; @@ -355,7 +354,7 @@ DEFUN(logging_level, return CMD_SUCCESS; } -/* logging level (all|) everything */ +/* logging level () everything */ DEFUN_DEPRECATED(deprecated_logging_level_everything, deprecated_logging_level_everything_cmd, NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ NULL) /* same thing for helpstr. */ @@ -364,6 +363,35 @@ DEFUN_DEPRECATED(deprecated_logging_level_everything, deprecated_logging_level_e return CMD_SUCCESS; } +DEFUN(logging_level_force_all, logging_level_force_all_cmd, + "logging level force-all " LOG_LEVEL_ARGS, + LOGGING_STR LEVEL_STR FORCE_ALL_STR LOG_LEVEL_STRS) +{ + struct log_target *tgt = osmo_log_vty2tgt(vty); + int level = log_parse_level(argv[0]); + log_set_log_level(tgt, level); + return CMD_SUCCESS; +} + +DEFUN(no_logging_level_force_all, no_logging_level_force_all_cmd, + "no logging level force-all", + NO_STR LOGGING_STR LEVEL_STR NO_FORCE_ALL_STR) +{ + struct log_target *tgt = osmo_log_vty2tgt(vty); + log_set_log_level(tgt, 0); + return CMD_SUCCESS; +} + +/* 'logging level all (debug|...|fatal)' */ +ALIAS_DEPRECATED(logging_level_force_all, deprecated_logging_level_all_cmd, + "logging level all " LOG_LEVEL_ARGS, + LOGGING_STR LEVEL_STR CATEGORY_ALL_STR LOG_LEVEL_STRS); + +/* 'logging level all everything' */ +ALIAS_DEPRECATED(no_logging_level_force_all, deprecated_logging_level_all_everything_cmd, + "logging level all everything", + LOGGING_STR LEVEL_STR CATEGORY_ALL_STR EVERYTHING_STR); + DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, "logging set-log-mask MASK", @@ -865,9 +893,10 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) const char *level_str = get_value_string_or_null(loglevel_strs, tgt->loglevel); level_str = osmo_str_tolower(level_str); if (!level_str) - vty_out(vty, "%% Invalid log level %u for 'all'%s", tgt->loglevel, VTY_NEWLINE); + vty_out(vty, "%% Invalid log level %u for 'force-all'%s", + tgt->loglevel, VTY_NEWLINE); else - vty_out(vty, " logging level all %s%s", level_str, VTY_NEWLINE); + vty_out(vty, " logging level force-all %s%s", level_str, VTY_NEWLINE); } for (i = 0; i < osmo_log_info->num_cat; i++) { @@ -945,16 +974,20 @@ void logging_vty_add_cmds() install_element_ve(&logging_set_category_mask_cmd); install_element_ve(&logging_set_category_mask_old_cmd); - /* logging level (all|) (debug|...|fatal) */ + /* logging level () (debug|...|fatal) */ gen_logging_level_cmd_strs(&logging_level_cmd, - "(" LOG_LEVEL_ARGS ")", + LOG_LEVEL_ARGS, LOG_LEVEL_STRS); - /* logging level (all|) everything */ + /* logging level () everything */ gen_logging_level_cmd_strs(&deprecated_logging_level_everything_cmd, "everything", EVERYTHING_STR); install_element_ve(&logging_level_cmd); + install_element_ve(&logging_level_force_all_cmd); + install_element_ve(&no_logging_level_force_all_cmd); install_element_ve(&deprecated_logging_level_everything_cmd); + install_element_ve(&deprecated_logging_level_all_cmd); + install_element_ve(&deprecated_logging_level_all_everything_cmd); install_element_ve(&show_logging_vty_cmd); install_element_ve(&show_alarms_cmd); @@ -968,7 +1001,11 @@ void logging_vty_add_cmds() install_element(CFG_LOG_NODE, &logging_prnt_level_cmd); install_element(CFG_LOG_NODE, &logging_prnt_file_cmd); install_element(CFG_LOG_NODE, &logging_level_cmd); + install_element(CFG_LOG_NODE, &logging_level_force_all_cmd); + install_element(CFG_LOG_NODE, &no_logging_level_force_all_cmd); install_element(CFG_LOG_NODE, &deprecated_logging_level_everything_cmd); + install_element(CFG_LOG_NODE, &deprecated_logging_level_all_cmd); + install_element(CFG_LOG_NODE, &deprecated_logging_level_all_everything_cmd); install_element(CONFIG_NODE, &cfg_log_stderr_cmd); install_element(CONFIG_NODE, &cfg_no_log_stderr_cmd); diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index a2c1e74b..03b0c4ae 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -12,6 +12,19 @@ log stderr ... logging_vty_test# configure terminal +logging_vty_test(config)# log stderr + +logging_vty_test(config-log)# logging level force-all notice +logging_vty_test(config-log)# show running-config +... !logging level all + logging level force-all notice +... !logging level all + +logging_vty_test(config-log)# no logging level force-all +logging_vty_test(config-log)# show running-config +... !logging level force-all + +logging_vty_test(config-log)# exit logging_vty_test(config)# no log stderr logging_vty_test(config)# exit @@ -37,9 +50,10 @@ logging_vty_test# list logging print level (0|1) logging print file (0|1|basename) [last] logging set-log-mask MASK - logging level (all|aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal) - show logging vty -... !logging + logging level (aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal) + logging level force-all (debug|info|notice|error|fatal) + no logging level force-all +... !^ logging logging_vty_test# logging ? enable Enables logging to this vty @@ -52,14 +66,15 @@ logging_vty_test# logging ? level Set the log level for a specified category logging_vty_test# logging level ? - all Global setting for all subsystems - aa Antropomorphic Armadillos (AA) - bb Bidirectional Breadspread (BB) - ccc Chaos Communication Congress (CCC) - dddd Dehydrated Dribbling Duck Dunkers (DDDD) - eee Exhaustive Entropy Extraction (EEE) - lglobal Library-internal global log family -... +... ! all + aa Antropomorphic Armadillos (AA) + bb Bidirectional Breadspread (BB) + ccc Chaos Communication Congress (CCC) + dddd Dehydrated Dribbling Duck Dunkers (DDDD) + eee Exhaustive Entropy Extraction (EEE) + lglobal Library-internal global log family +... ! all + force-all Globally force all logging categories to a specific level. This is released by the 'no logging level force-all' command. Note: any 'logging level ' commands will have no visible effect after this, until the forced level is released. logging_vty_test# logging level aa ? debug Log debug messages and higher levels @@ -69,12 +84,18 @@ logging_vty_test# logging level aa ? fatal Log only fatal messages logging_vty_test# logging level all ? +% There is no matched command. + +logging_vty_test# logging level force-all ? debug Log debug messages and higher levels info Log informational messages and higher levels notice Log noticeable messages and higher levels error Log error messages and higher levels fatal Log only fatal messages +logging_vty_test# no logging level ? + force-all Release any globally forced log level set with 'logging level force-all ' + logging_vty_test# log-sweep DAA DEBUG Log message for DAA on level LOGL_DEBUG @@ -93,6 +114,7 @@ DDDDD ERROR Log message for DDDDD on level LOGL_ERROR DDDDD FATAL Log message for DDDDD on level LOGL_FATAL DEEE FATAL Log message for DEEE on level LOGL_FATAL +logging_vty_test# ! The deprecated 'logging level all' still does what it did logging_vty_test# logging level all fatal logging_vty_test# log-sweep DAA FATAL Log message for DAA on level LOGL_FATAL @@ -175,12 +197,110 @@ DEEE NOTICE Log message for DEEE on level LOGL_NOTICE DEEE ERROR Log message for DEEE on level LOGL_ERROR DEEE FATAL Log message for DEEE on level LOGL_FATAL -logging_vty_test# ! Old 'logging level all everything' has no effect +logging_vty_test# ! Deprecated 'logging level all everything' lifts the globally forced level logging_vty_test# logging level all everything -% Ignoring deprecated logging level 'everything' keyword logging_vty_test# log-sweep eee +DEEE FATAL Log message for DEEE on level LOGL_FATAL + + +logging_vty_test# ! Now do the same dance with the new 'logging level force-all' commands +logging_vty_test# logging level force-all fatal +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level force-all error +logging_vty_test# log-sweep +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level force-all notice +logging_vty_test# log-sweep +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL DEEE NOTICE Log message for DEEE on level LOGL_NOTICE DEEE ERROR Log message for DEEE on level LOGL_ERROR DEEE FATAL Log message for DEEE on level LOGL_FATAL -logging_vty_test# ! There is currently no way to remove the 'logging level all' level! +logging_vty_test# logging level force-all debug +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB DEBUG Log message for DBB on level LOGL_DEBUG +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC DEBUG Log message for DCCC on level LOGL_DEBUG +DCCC INFO Log message for DCCC on level LOGL_INFO +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD DEBUG Log message for DDDDD on level LOGL_DEBUG +DDDDD INFO Log message for DDDDD on level LOGL_INFO +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE DEBUG Log message for DEEE on level LOGL_DEBUG +DEEE INFO Log message for DEEE on level LOGL_INFO +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# ! 'force-all' overrides everything, be it stronger or weaker +logging_vty_test# logging level force-all notice +logging_vty_test# logging level eee debug +logging_vty_test# log-sweep eee +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level force-all notice +logging_vty_test# logging level eee fatal +logging_vty_test# log-sweep eee +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# ! lift the globally forced level +logging_vty_test# no logging level force-all +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL -- cgit v1.2.3 From 4b081b1d8862114f59af433b943dea86ce47ac71 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 13 Sep 2018 15:01:55 +0200 Subject: gsm0808: fix wrong codec defaults for OFR_AMR_WB 3GPP TS 48.008 chapter 3.2.2.103 states that the configuration bits of OFR_AMR_WB are coded as follows: "S0, S2, S4 indicates the supported Codec Configurations. S1, S3, S5, S6, S7 are reserved and coded with zeroes." The current default setting of 0x3F violates this requirement. Lets set the "forbidden" settings zu zero and keep only the allowed ones. Change-Id: I4a481def59e9c98cfdcafc2b80c0ac7df0c14130 --- include/osmocom/gsm/protocol/gsm_08_08.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 69007b5c..94338178 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -499,7 +499,7 @@ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_HR_AMR = 0x073f, GSM0808_SC_CFG_DEFAULT_OHR_AMR = 0x57ff, GSM0808_SC_CFG_DEFAULT_FR_AMR_WB = 0x01, - GSM0808_SC_CFG_DEFAULT_OFR_AMR_WB = 0x3f, + GSM0808_SC_CFG_DEFAULT_OFR_AMR_WB = 0x15, GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01, }; -- cgit v1.2.3 From 2fd4fe6aa109c8df50baac465f0393a303a64dd2 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Fri, 14 Sep 2018 09:13:36 +0200 Subject: gsm0808: add function to convert amr gsm0408 setings to gsm0808 Add a function to convert struct gsm48_multi_rate_conf, which holds the codec settings for AMR, to S0-S15 bit representation as defined in 3GPP TS 48.008 3.2.2.49 Change-Id: I4e656731b16621736c7a2f4e64d9ce63b1064e98 Related: OS#3548 --- include/osmocom/gsm/gsm0808_utils.h | 1 + include/osmocom/gsm/protocol/gsm_08_08.h | 14 ++ src/gsm/gsm0808_utils.c | 43 ++++++ src/gsm/libosmogsm.map | 1 + tests/gsm0808/gsm0808_test.c | 196 +++++++++++++++++++++++++++ tests/gsm0808/gsm0808_test.ok | 225 +++++++++++++++++++++++++++++++ 6 files changed, 480 insertions(+) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 242bce94..0a7429e9 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -104,6 +104,7 @@ int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch); int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint8_t perm_spch); +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, bool fr); /*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 94338178..8431ace5 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -503,6 +503,20 @@ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01, }; +/*! Default speech codec configurations broken down by reate. + * See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for + * the Adaptive Multi-Rate Codec Types. */ +enum gsm0808_speech_codec_rate_defaults { + GSM0808_SC_CFG_DEFAULT_AMR_4_75 = 0xff03, + GSM0808_SC_CFG_DEFAULT_AMR_5_15 = 0x0000, + GSM0808_SC_CFG_DEFAULT_AMR_5_90 = 0xff06, + GSM0808_SC_CFG_DEFAULT_AMR_6_70 = 0x3e08, + GSM0808_SC_CFG_DEFAULT_AMR_7_40 = 0x0c12, + GSM0808_SC_CFG_DEFAULT_AMR_7_95 = 0xc020, + GSM0808_SC_CFG_DEFAULT_AMR_10_2 = 0x3040, + GSM0808_SC_CFG_DEFAULT_AMR_12_2 = 0xc082 +}; + /* 3GPP TS 48.008 3.2.2.103 Speech Codec List */ #define SPEECH_CODEC_MAXLEN 255 struct gsm0808_speech_codec_list { diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 73f02341..4b2a5f56 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1161,6 +1161,49 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, return 0; } +/*! Determine a set of AMR speech codec configuration bits (S0-S15) from a + * given GSM 04.08 AMR configuration struct. + * \param[in] cfg AMR configuration in GSM 04.08 format. + * \param[in] hint if the resulting configuration shall be used with a FR or HR TCH. + * \returns configuration bits (S0-S15) */ +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, + bool fr) +{ + uint16_t s15_s0 = 0; + + /* Check each rate bit in the AMR multirate configuration and pick the + * matching default configuration as specified in 3GPP TS 28.062, + * Table 7.11.3.1.3-2. */ + if (cfg->m4_75) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_4_75; + if (cfg->m5_15) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_15; + if (cfg->m5_90) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_90; + if (cfg->m6_70) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_6_70; + if (cfg->m7_40) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_40; + if (cfg->m7_95) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_95; + if (cfg->m10_2) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_10_2; + if (cfg->m12_2) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_12_2; + + /* Note: 3GPP TS 48.008, chapter 3GPP TS 48.008 states that for AMR + * some of the configuration bits must be coded as zeros. The applied + * bitmask matches the default codec settings. See also the definition + * of enum gsm0808_speech_codec_defaults in gsm_08_08.h and + * 3GPP TS 28.062, Table 7.11.3.1.3-2. */ + if (fr) + s15_s0 &= GSM0808_SC_CFG_DEFAULT_FR_AMR; + else + s15_s0 &= GSM0808_SC_CFG_DEFAULT_HR_AMR; + + return s15_s0; +} + /*! Print a human readable name of the cell identifier to the char buffer. * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2. * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 0c40c88c..3d08232c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -205,6 +205,7 @@ gsm0808_cell_id_discr_names; gsm0808_cell_id_u_name; gsm0808_chan_type_to_speech_codec; gsm0808_speech_codec_from_chan_type; +gsm0808_sc_cfg_from_gsm48_mr_cfg; gsm0808_speech_codec_type_names; gsm0808_permitted_speech_names; gsm0808_chosen_enc_alg_names; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index ae138be8..29cecb2e 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -1444,6 +1444,200 @@ static void test_gsm0808_enc_dec_cell_id_global() msgb_free(msg); } +static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg) +{ + uint16_t s15_s0; + + printf("Input:\n"); + printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod); + printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare); + printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi); + printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb); + printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver); + printf(" m7_95= %u\n", cfg->m7_95); + printf(" m10_2= %u\n", cfg->m10_2); + printf(" m12_2= %u\n", cfg->m12_2); + + s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true); + printf("Result (fr):\n"); + printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, + OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); + + s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false); + printf("Result (hr):\n"); + printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, + OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); + + printf("\n"); +} + +static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void) +{ + struct gsm48_multi_rate_conf cfg; + + printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n"); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); +} + int main(int argc, char **argv) { printf("Testing generation of GSM0808 messages\n"); @@ -1495,6 +1689,8 @@ int main(int argc, char **argv) test_gsm0808_enc_dec_cell_id_lac_and_ci(); test_gsm0808_enc_dec_cell_id_global(); + test_gsm0808_sc_cfg_from_gsm48_mr_cfg(); + printf("Done\n"); return EXIT_SUCCESS; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index 6cd7982b..dc1debac 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -74,4 +74,229 @@ test_gsm0808_enc_dec_cell_id_lai_and_lac: encoded: 05 06 04 21 63 54 23 42 (rc = test_gsm0808_enc_dec_cell_id_ci: encoded: 05 03 02 04 23 (rc = 5) test_gsm0808_enc_dec_cell_id_lac_and_ci: encoded: 05 05 01 04 23 02 35 (rc = 7) test_gsm0808_enc_dec_cell_id_global: encoded: 05 08 00 21 63 54 23 42 04 23 (rc = 10) +Testing gsm0808_sc_cfg_from_gsm48_mr_cfg(): +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0000 = 0b0000000000000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 1 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5703 = 0b0101011100000011 +Result (hr): + S15-S0 = 0703 = 0b0000011100000011 + +Input: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0000 = 0b0000000000000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5706 = 0b0101011100000110 +Result (hr): + S15-S0 = 0706 = 0b0000011100000110 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 1608 = 0b0001011000001000 +Result (hr): + S15-S0 = 0608 = 0b0000011000001000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0412 = 0b0000010000010010 +Result (hr): + S15-S0 = 0412 = 0b0000010000010010 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 4020 = 0b0100000000100000 +Result (hr): + S15-S0 = 0020 = 0b0000000000100000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 0 +Result (fr): + S15-S0 = 1040 = 0b0001000001000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 1 +Result (fr): + S15-S0 = 4082 = 0b0100000010000010 +Result (hr): + S15-S0 = 0002 = 0b0000000000000010 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 570f = 0b0101011100001111 +Result (hr): + S15-S0 = 070f = 0b0000011100001111 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 54f2 = 0b0101010011110010 +Result (hr): + S15-S0 = 0432 = 0b0000010000110010 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 57ce = 0b0101011111001110 +Result (hr): + S15-S0 = 070e = 0b0000011100001110 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5733 = 0b0101011100110011 +Result (hr): + S15-S0 = 0733 = 0b0000011100110011 + +Input: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 1 +Result (fr): + S15-S0 = 56aa = 0b0101011010101010 +Result (hr): + S15-S0 = 062a = 0b0000011000101010 + +Input: + m4_75= 1 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 0 +Result (fr): + S15-S0 = 5757 = 0b0101011101010111 +Result (hr): + S15-S0 = 0717 = 0b0000011100010111 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 57ff = 0b0101011111111111 +Result (hr): + S15-S0 = 073f = 0b0000011100111111 + Done -- cgit v1.2.3 From dd8c73cc6da6e8bdc027bc9f05126aad60a71f72 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Sun, 16 Sep 2018 21:02:25 +0000 Subject: Revert "gsm0808: add function to convert amr gsm0408 setings to gsm0808" This reverts commit 2fd4fe6aa109c8df50baac465f0393a303a64dd2. As shown in https://jenkins.osmocom.org/jenkins/view/master/job/master-libosmocore/475/a2=default,a3=default,arch=amd64,label=osmocom-master-debian9/console This commit breaks gsm0808_test with: stderr: --- expout 2018-09-16 22:37:31.382280438 +0200 +++ /n/s/dev/make/libosmocore/tests/testsuite.dir/at-groups/21/stdout 2018-09-16 22:37:31.426281372 +0200 @@ -78,9 +78,9 @@ Input: m4_75= 0 smod= 0 m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 + m5_90= 0 icmi= 1 m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 + m7_40= 0 ver= 6 m7_95= 0 m10_2= 0 m12_2= 0 @@ -92,9 +92,9 @@ Input: m4_75= 1 smod= 0 m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 + m5_90= 0 icmi= 1 m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 + m7_40= 0 ver= 6 m7_95= 0 m10_2= 0 m12_2= 0 @@ -106,9 +106,9 @@ Input: m4_75= 0 smod= 0 m5_15= 1 spare= 0 - m5_90= 0 icmi= 0 + m5_90= 0 icmi= 1 [...] Change-Id: I9e0d405e303ed86d23703ca6362e958dddb2f861 --- include/osmocom/gsm/gsm0808_utils.h | 1 - include/osmocom/gsm/protocol/gsm_08_08.h | 14 -- src/gsm/gsm0808_utils.c | 43 ------ src/gsm/libosmogsm.map | 1 - tests/gsm0808/gsm0808_test.c | 196 --------------------------- tests/gsm0808/gsm0808_test.ok | 225 ------------------------------- 6 files changed, 480 deletions(-) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 0a7429e9..242bce94 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -104,7 +104,6 @@ int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch); int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint8_t perm_spch); -uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, bool fr); /*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 8431ace5..94338178 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -503,20 +503,6 @@ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01, }; -/*! Default speech codec configurations broken down by reate. - * See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for - * the Adaptive Multi-Rate Codec Types. */ -enum gsm0808_speech_codec_rate_defaults { - GSM0808_SC_CFG_DEFAULT_AMR_4_75 = 0xff03, - GSM0808_SC_CFG_DEFAULT_AMR_5_15 = 0x0000, - GSM0808_SC_CFG_DEFAULT_AMR_5_90 = 0xff06, - GSM0808_SC_CFG_DEFAULT_AMR_6_70 = 0x3e08, - GSM0808_SC_CFG_DEFAULT_AMR_7_40 = 0x0c12, - GSM0808_SC_CFG_DEFAULT_AMR_7_95 = 0xc020, - GSM0808_SC_CFG_DEFAULT_AMR_10_2 = 0x3040, - GSM0808_SC_CFG_DEFAULT_AMR_12_2 = 0xc082 -}; - /* 3GPP TS 48.008 3.2.2.103 Speech Codec List */ #define SPEECH_CODEC_MAXLEN 255 struct gsm0808_speech_codec_list { diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 4b2a5f56..73f02341 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1161,49 +1161,6 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, return 0; } -/*! Determine a set of AMR speech codec configuration bits (S0-S15) from a - * given GSM 04.08 AMR configuration struct. - * \param[in] cfg AMR configuration in GSM 04.08 format. - * \param[in] hint if the resulting configuration shall be used with a FR or HR TCH. - * \returns configuration bits (S0-S15) */ -uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, - bool fr) -{ - uint16_t s15_s0 = 0; - - /* Check each rate bit in the AMR multirate configuration and pick the - * matching default configuration as specified in 3GPP TS 28.062, - * Table 7.11.3.1.3-2. */ - if (cfg->m4_75) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_4_75; - if (cfg->m5_15) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_15; - if (cfg->m5_90) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_90; - if (cfg->m6_70) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_6_70; - if (cfg->m7_40) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_40; - if (cfg->m7_95) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_95; - if (cfg->m10_2) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_10_2; - if (cfg->m12_2) - s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_12_2; - - /* Note: 3GPP TS 48.008, chapter 3GPP TS 48.008 states that for AMR - * some of the configuration bits must be coded as zeros. The applied - * bitmask matches the default codec settings. See also the definition - * of enum gsm0808_speech_codec_defaults in gsm_08_08.h and - * 3GPP TS 28.062, Table 7.11.3.1.3-2. */ - if (fr) - s15_s0 &= GSM0808_SC_CFG_DEFAULT_FR_AMR; - else - s15_s0 &= GSM0808_SC_CFG_DEFAULT_HR_AMR; - - return s15_s0; -} - /*! Print a human readable name of the cell identifier to the char buffer. * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2. * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3d08232c..0c40c88c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -205,7 +205,6 @@ gsm0808_cell_id_discr_names; gsm0808_cell_id_u_name; gsm0808_chan_type_to_speech_codec; gsm0808_speech_codec_from_chan_type; -gsm0808_sc_cfg_from_gsm48_mr_cfg; gsm0808_speech_codec_type_names; gsm0808_permitted_speech_names; gsm0808_chosen_enc_alg_names; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 29cecb2e..ae138be8 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -1444,200 +1444,6 @@ static void test_gsm0808_enc_dec_cell_id_global() msgb_free(msg); } -static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg) -{ - uint16_t s15_s0; - - printf("Input:\n"); - printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod); - printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare); - printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi); - printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb); - printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver); - printf(" m7_95= %u\n", cfg->m7_95); - printf(" m10_2= %u\n", cfg->m10_2); - printf(" m12_2= %u\n", cfg->m12_2); - - s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true); - printf("Result (fr):\n"); - printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, - OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); - - s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false); - printf("Result (hr):\n"); - printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, - OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); - - printf("\n"); -} - -static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void) -{ - struct gsm48_multi_rate_conf cfg; - - printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n"); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 1; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 1; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 1; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 1; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 1; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 1; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 1; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 1; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 1; - cfg.m5_15 = 1; - cfg.m5_90 = 1; - cfg.m6_70 = 1; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 1; - cfg.m7_95 = 1; - cfg.m10_2 = 1; - cfg.m12_2 = 1; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 0; - cfg.m5_90 = 1; - cfg.m6_70 = 1; - cfg.m7_40 = 0; - cfg.m7_95 = 0; - cfg.m10_2 = 1; - cfg.m12_2 = 1; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 1; - cfg.m5_15 = 1; - cfg.m5_90 = 0; - cfg.m6_70 = 0; - cfg.m7_40 = 1; - cfg.m7_95 = 1; - cfg.m10_2 = 0; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 0; - cfg.m5_15 = 1; - cfg.m5_90 = 0; - cfg.m6_70 = 1; - cfg.m7_40 = 0; - cfg.m7_95 = 1; - cfg.m10_2 = 0; - cfg.m12_2 = 1; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 1; - cfg.m5_15 = 0; - cfg.m5_90 = 1; - cfg.m6_70 = 0; - cfg.m7_40 = 1; - cfg.m7_95 = 0; - cfg.m10_2 = 1; - cfg.m12_2 = 0; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); - - cfg.m4_75 = 1; - cfg.m5_15 = 1; - cfg.m5_90 = 1; - cfg.m6_70 = 1; - cfg.m7_40 = 1; - cfg.m7_95 = 1; - cfg.m10_2 = 1; - cfg.m12_2 = 1; - test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); -} - int main(int argc, char **argv) { printf("Testing generation of GSM0808 messages\n"); @@ -1689,8 +1495,6 @@ int main(int argc, char **argv) test_gsm0808_enc_dec_cell_id_lac_and_ci(); test_gsm0808_enc_dec_cell_id_global(); - test_gsm0808_sc_cfg_from_gsm48_mr_cfg(); - printf("Done\n"); return EXIT_SUCCESS; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index dc1debac..6cd7982b 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -74,229 +74,4 @@ test_gsm0808_enc_dec_cell_id_lai_and_lac: encoded: 05 06 04 21 63 54 23 42 (rc = test_gsm0808_enc_dec_cell_id_ci: encoded: 05 03 02 04 23 (rc = 5) test_gsm0808_enc_dec_cell_id_lac_and_ci: encoded: 05 05 01 04 23 02 35 (rc = 7) test_gsm0808_enc_dec_cell_id_global: encoded: 05 08 00 21 63 54 23 42 04 23 (rc = 10) -Testing gsm0808_sc_cfg_from_gsm48_mr_cfg(): -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 0000 = 0b0000000000000000 -Result (hr): - S15-S0 = 0000 = 0b0000000000000000 - -Input: - m4_75= 1 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 5703 = 0b0101011100000011 -Result (hr): - S15-S0 = 0703 = 0b0000011100000011 - -Input: - m4_75= 0 smod= 0 - m5_15= 1 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 0000 = 0b0000000000000000 -Result (hr): - S15-S0 = 0000 = 0b0000000000000000 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 1 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 5706 = 0b0101011100000110 -Result (hr): - S15-S0 = 0706 = 0b0000011100000110 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 1 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 1608 = 0b0001011000001000 -Result (hr): - S15-S0 = 0608 = 0b0000011000001000 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 1 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 0412 = 0b0000010000010010 -Result (hr): - S15-S0 = 0412 = 0b0000010000010010 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 1 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 4020 = 0b0100000000100000 -Result (hr): - S15-S0 = 0020 = 0b0000000000100000 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 1 - m12_2= 0 -Result (fr): - S15-S0 = 1040 = 0b0001000001000000 -Result (hr): - S15-S0 = 0000 = 0b0000000000000000 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 1 -Result (fr): - S15-S0 = 4082 = 0b0100000010000010 -Result (hr): - S15-S0 = 0002 = 0b0000000000000010 - -Input: - m4_75= 1 smod= 0 - m5_15= 1 spare= 0 - m5_90= 1 icmi= 0 - m6_70= 1 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 570f = 0b0101011100001111 -Result (hr): - S15-S0 = 070f = 0b0000011100001111 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 1 ver= 0 - m7_95= 1 - m10_2= 1 - m12_2= 1 -Result (fr): - S15-S0 = 54f2 = 0b0101010011110010 -Result (hr): - S15-S0 = 0432 = 0b0000010000110010 - -Input: - m4_75= 0 smod= 0 - m5_15= 0 spare= 0 - m5_90= 1 icmi= 0 - m6_70= 1 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 0 - m10_2= 1 - m12_2= 1 -Result (fr): - S15-S0 = 57ce = 0b0101011111001110 -Result (hr): - S15-S0 = 070e = 0b0000011100001110 - -Input: - m4_75= 1 smod= 0 - m5_15= 1 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 1 ver= 0 - m7_95= 1 - m10_2= 0 - m12_2= 0 -Result (fr): - S15-S0 = 5733 = 0b0101011100110011 -Result (hr): - S15-S0 = 0733 = 0b0000011100110011 - -Input: - m4_75= 0 smod= 0 - m5_15= 1 spare= 0 - m5_90= 0 icmi= 0 - m6_70= 1 nscb= 0 - m7_40= 0 ver= 0 - m7_95= 1 - m10_2= 0 - m12_2= 1 -Result (fr): - S15-S0 = 56aa = 0b0101011010101010 -Result (hr): - S15-S0 = 062a = 0b0000011000101010 - -Input: - m4_75= 1 smod= 0 - m5_15= 0 spare= 0 - m5_90= 1 icmi= 0 - m6_70= 0 nscb= 0 - m7_40= 1 ver= 0 - m7_95= 0 - m10_2= 1 - m12_2= 0 -Result (fr): - S15-S0 = 5757 = 0b0101011101010111 -Result (hr): - S15-S0 = 0717 = 0b0000011100010111 - -Input: - m4_75= 1 smod= 0 - m5_15= 1 spare= 0 - m5_90= 1 icmi= 0 - m6_70= 1 nscb= 0 - m7_40= 1 ver= 0 - m7_95= 1 - m10_2= 1 - m12_2= 1 -Result (fr): - S15-S0 = 57ff = 0b0101011111111111 -Result (hr): - S15-S0 = 073f = 0b0000011100111111 - Done -- cgit v1.2.3 From 28fc078f9cc02b6c731b0d2e5813857d2ec03ea1 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Wed, 12 Sep 2018 02:32:02 +0200 Subject: logging vty: add 'logging level set-all ' Add new command to once-off set each and every category to the given log level, as discussed at length on the openbsc@ mailing list. Show that it works in logging_vty_test.vty. Change-Id: I4c3e4f786476cb813fdc0a7c64f30ee04758309d --- src/vty/logging_vty.c | 24 ++++++ tests/logging/logging_vty_test.vty | 161 +++++++++++++++++++++++++++++++++++++ 2 files changed, 185 insertions(+) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 3b1d8c65..b2637a5f 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -354,6 +354,28 @@ DEFUN(logging_level, return CMD_SUCCESS; } +DEFUN(logging_level_set_all, logging_level_set_all_cmd, + "logging level set-all " LOG_LEVEL_ARGS, + LOGGING_STR LEVEL_STR + "Once-off set all categories to the given log level. There is no single command" + " to take back these changes -- each category is set to the given level, period.\n" + LOG_LEVEL_STRS) +{ + struct log_target *tgt = osmo_log_vty2tgt(vty); + int level = log_parse_level(argv[0]); + int i; + for (i = 0; i < osmo_log_info->num_cat; i++) { + struct log_category *cat = &tgt->categories[i]; + /* skip empty entries in the array */ + if (!osmo_log_info->cat[i].name) + continue; + + cat->enabled = 1; + cat->loglevel = level; + } + return CMD_SUCCESS; +} + /* logging level () everything */ DEFUN_DEPRECATED(deprecated_logging_level_everything, deprecated_logging_level_everything_cmd, NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ @@ -983,6 +1005,7 @@ void logging_vty_add_cmds() "everything", EVERYTHING_STR); install_element_ve(&logging_level_cmd); + install_element_ve(&logging_level_set_all_cmd); install_element_ve(&logging_level_force_all_cmd); install_element_ve(&no_logging_level_force_all_cmd); install_element_ve(&deprecated_logging_level_everything_cmd); @@ -1001,6 +1024,7 @@ void logging_vty_add_cmds() install_element(CFG_LOG_NODE, &logging_prnt_level_cmd); install_element(CFG_LOG_NODE, &logging_prnt_file_cmd); install_element(CFG_LOG_NODE, &logging_level_cmd); + install_element(CFG_LOG_NODE, &logging_level_set_all_cmd); install_element(CFG_LOG_NODE, &logging_level_force_all_cmd); install_element(CFG_LOG_NODE, &no_logging_level_force_all_cmd); install_element(CFG_LOG_NODE, &deprecated_logging_level_everything_cmd); diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index 03b0c4ae..0c552a58 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -51,6 +51,7 @@ logging_vty_test# list logging print file (0|1|basename) [last] logging set-log-mask MASK logging level (aa|bb|ccc|dddd|eee|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf) (debug|info|notice|error|fatal) + logging level set-all (debug|info|notice|error|fatal) logging level force-all (debug|info|notice|error|fatal) no logging level force-all ... !^ logging @@ -74,6 +75,7 @@ logging_vty_test# logging level ? eee Exhaustive Entropy Extraction (EEE) lglobal Library-internal global log family ... ! all + set-all Once-off set all categories to the given log level. There is no single command to take back these changes -- each category is set to the given level, period. force-all Globally force all logging categories to a specific level. This is released by the 'no logging level force-all' command. Note: any 'logging level ' commands will have no visible effect after this, until the forced level is released. logging_vty_test# logging level aa ? @@ -96,6 +98,13 @@ logging_vty_test# logging level force-all ? logging_vty_test# no logging level ? force-all Release any globally forced log level set with 'logging level force-all ' +logging_vty_test# logging level set-all ? + debug Log debug messages and higher levels + info Log informational messages and higher levels + notice Log noticeable messages and higher levels + error Log error messages and higher levels + fatal Log only fatal messages + logging_vty_test# log-sweep DAA DEBUG Log message for DAA on level LOGL_DEBUG @@ -304,3 +313,155 @@ DCCC FATAL Log message for DCCC on level LOGL_FATAL DDDDD ERROR Log message for DDDDD on level LOGL_ERROR DDDDD FATAL Log message for DDDDD on level LOGL_FATAL DEEE FATAL Log message for DEEE on level LOGL_FATAL + + +logging_vty_test# ! test 'set-all' +logging_vty_test# logging level set-all fatal +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level set-all error +logging_vty_test# log-sweep +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level set-all notice +logging_vty_test# log-sweep +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level set-all info +logging_vty_test# log-sweep +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC INFO Log message for DCCC on level LOGL_INFO +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD INFO Log message for DDDDD on level LOGL_INFO +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE INFO Log message for DEEE on level LOGL_INFO +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level set-all debug +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB DEBUG Log message for DBB on level LOGL_DEBUG +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC DEBUG Log message for DCCC on level LOGL_DEBUG +DCCC INFO Log message for DCCC on level LOGL_INFO +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD DEBUG Log message for DDDDD on level LOGL_DEBUG +DDDDD INFO Log message for DDDDD on level LOGL_INFO +DDDDD NOTICE Log message for DDDDD on level LOGL_NOTICE +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE DEBUG Log message for DEEE on level LOGL_DEBUG +DEEE INFO Log message for DEEE on level LOGL_INFO +DEEE NOTICE Log message for DEEE on level LOGL_NOTICE +DEEE ERROR Log message for DEEE on level LOGL_ERROR +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level set-all fatal +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level dddd error +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level ccc notice +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level bb info +logging_vty_test# log-sweep +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL + +logging_vty_test# logging level aa debug +logging_vty_test# log-sweep +DAA DEBUG Log message for DAA on level LOGL_DEBUG +DAA INFO Log message for DAA on level LOGL_INFO +DAA NOTICE Log message for DAA on level LOGL_NOTICE +DAA ERROR Log message for DAA on level LOGL_ERROR +DAA FATAL Log message for DAA on level LOGL_FATAL +DBB INFO Log message for DBB on level LOGL_INFO +DBB NOTICE Log message for DBB on level LOGL_NOTICE +DBB ERROR Log message for DBB on level LOGL_ERROR +DBB FATAL Log message for DBB on level LOGL_FATAL +DCCC NOTICE Log message for DCCC on level LOGL_NOTICE +DCCC ERROR Log message for DCCC on level LOGL_ERROR +DCCC FATAL Log message for DCCC on level LOGL_FATAL +DDDDD ERROR Log message for DDDDD on level LOGL_ERROR +DDDDD FATAL Log message for DDDDD on level LOGL_FATAL +DEEE FATAL Log message for DEEE on level LOGL_FATAL -- cgit v1.2.3 From 5f2eb150742bd793f2f61fb5cfe2b2df707c0093 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Wed, 19 Sep 2018 13:40:21 +0200 Subject: gsm0808: add function to convert amr gsm0408 setings to gsm0808 Add a function to convert struct gsm48_multi_rate_conf, which holds the codec settings for AMR, to S0-S15 bit representation as defined in 3GPP TS 48.008 3.2.2.49 This resurrects change-id I4e656731b16621736c7a2f4e64d9ce63b1064e98 which was reverted in I9e0d405e303ed86d23703ca6362e958dddb2f861 due to gsm0808_test failing. The test failure is fixed by properly clearing the struct gsm48_multirate_cfg prior to running tests (add memset(0)). Change-Id: Ia782e21c206c15e840226d79b4209d13658ee916 Related: OS#3548 --- include/osmocom/gsm/gsm0808_utils.h | 1 + include/osmocom/gsm/protocol/gsm_08_08.h | 14 ++ src/gsm/gsm0808_utils.c | 43 ++++++ src/gsm/libosmogsm.map | 1 + tests/gsm0808/gsm0808_test.c | 198 +++++++++++++++++++++++++++ tests/gsm0808/gsm0808_test.ok | 225 +++++++++++++++++++++++++++++++ 6 files changed, 482 insertions(+) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 242bce94..0a7429e9 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -104,6 +104,7 @@ int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch); int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint8_t perm_spch); +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, bool fr); /*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 94338178..8431ace5 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -503,6 +503,20 @@ enum gsm0808_speech_codec_defaults { GSM0808_SC_CFG_DEFAULT_OHR_AMR_WB = 0x01, }; +/*! Default speech codec configurations broken down by reate. + * See also: 3GPP TS 28.062, Table 7.11.3.1.3-2: Preferred Configurations for + * the Adaptive Multi-Rate Codec Types. */ +enum gsm0808_speech_codec_rate_defaults { + GSM0808_SC_CFG_DEFAULT_AMR_4_75 = 0xff03, + GSM0808_SC_CFG_DEFAULT_AMR_5_15 = 0x0000, + GSM0808_SC_CFG_DEFAULT_AMR_5_90 = 0xff06, + GSM0808_SC_CFG_DEFAULT_AMR_6_70 = 0x3e08, + GSM0808_SC_CFG_DEFAULT_AMR_7_40 = 0x0c12, + GSM0808_SC_CFG_DEFAULT_AMR_7_95 = 0xc020, + GSM0808_SC_CFG_DEFAULT_AMR_10_2 = 0x3040, + GSM0808_SC_CFG_DEFAULT_AMR_12_2 = 0xc082 +}; + /* 3GPP TS 48.008 3.2.2.103 Speech Codec List */ #define SPEECH_CODEC_MAXLEN 255 struct gsm0808_speech_codec_list { diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 73f02341..4b2a5f56 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1161,6 +1161,49 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, return 0; } +/*! Determine a set of AMR speech codec configuration bits (S0-S15) from a + * given GSM 04.08 AMR configuration struct. + * \param[in] cfg AMR configuration in GSM 04.08 format. + * \param[in] hint if the resulting configuration shall be used with a FR or HR TCH. + * \returns configuration bits (S0-S15) */ +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, + bool fr) +{ + uint16_t s15_s0 = 0; + + /* Check each rate bit in the AMR multirate configuration and pick the + * matching default configuration as specified in 3GPP TS 28.062, + * Table 7.11.3.1.3-2. */ + if (cfg->m4_75) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_4_75; + if (cfg->m5_15) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_15; + if (cfg->m5_90) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_5_90; + if (cfg->m6_70) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_6_70; + if (cfg->m7_40) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_40; + if (cfg->m7_95) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_7_95; + if (cfg->m10_2) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_10_2; + if (cfg->m12_2) + s15_s0 |= GSM0808_SC_CFG_DEFAULT_AMR_12_2; + + /* Note: 3GPP TS 48.008, chapter 3GPP TS 48.008 states that for AMR + * some of the configuration bits must be coded as zeros. The applied + * bitmask matches the default codec settings. See also the definition + * of enum gsm0808_speech_codec_defaults in gsm_08_08.h and + * 3GPP TS 28.062, Table 7.11.3.1.3-2. */ + if (fr) + s15_s0 &= GSM0808_SC_CFG_DEFAULT_FR_AMR; + else + s15_s0 &= GSM0808_SC_CFG_DEFAULT_HR_AMR; + + return s15_s0; +} + /*! Print a human readable name of the cell identifier to the char buffer. * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2. * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 0c40c88c..3d08232c 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -205,6 +205,7 @@ gsm0808_cell_id_discr_names; gsm0808_cell_id_u_name; gsm0808_chan_type_to_speech_codec; gsm0808_speech_codec_from_chan_type; +gsm0808_sc_cfg_from_gsm48_mr_cfg; gsm0808_speech_codec_type_names; gsm0808_permitted_speech_names; gsm0808_chosen_enc_alg_names; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index ae138be8..6faa6890 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -1444,6 +1444,202 @@ static void test_gsm0808_enc_dec_cell_id_global() msgb_free(msg); } +static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(struct gsm48_multi_rate_conf *cfg) +{ + uint16_t s15_s0; + + printf("Input:\n"); + printf(" m4_75= %u smod= %u\n", cfg->m4_75, cfg->smod); + printf(" m5_15= %u spare= %u\n", cfg->m5_15, cfg->spare); + printf(" m5_90= %u icmi= %u\n", cfg->m5_90, cfg->icmi); + printf(" m6_70= %u nscb= %u\n", cfg->m6_70, cfg->nscb); + printf(" m7_40= %u ver= %u\n", cfg->m7_40, cfg->ver); + printf(" m7_95= %u\n", cfg->m7_95); + printf(" m10_2= %u\n", cfg->m10_2); + printf(" m12_2= %u\n", cfg->m12_2); + + s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, true); + printf("Result (fr):\n"); + printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, + OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); + + s15_s0 = gsm0808_sc_cfg_from_gsm48_mr_cfg(cfg, false); + printf("Result (hr):\n"); + printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, + OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); + + printf("\n"); +} + +static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void) +{ + struct gsm48_multi_rate_conf cfg; + + printf("Testing gsm0808_sc_cfg_from_gsm48_mr_cfg():\n"); + + memset(&cfg, 0, sizeof(cfg)); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 0; + cfg.m5_15 = 1; + cfg.m5_90 = 0; + cfg.m6_70 = 1; + cfg.m7_40 = 0; + cfg.m7_95 = 1; + cfg.m10_2 = 0; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 0; + cfg.m5_90 = 1; + cfg.m6_70 = 0; + cfg.m7_40 = 1; + cfg.m7_95 = 0; + cfg.m10_2 = 1; + cfg.m12_2 = 0; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); + + cfg.m4_75 = 1; + cfg.m5_15 = 1; + cfg.m5_90 = 1; + cfg.m6_70 = 1; + cfg.m7_40 = 1; + cfg.m7_95 = 1; + cfg.m10_2 = 1; + cfg.m12_2 = 1; + test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); +} + int main(int argc, char **argv) { printf("Testing generation of GSM0808 messages\n"); @@ -1495,6 +1691,8 @@ int main(int argc, char **argv) test_gsm0808_enc_dec_cell_id_lac_and_ci(); test_gsm0808_enc_dec_cell_id_global(); + test_gsm0808_sc_cfg_from_gsm48_mr_cfg(); + printf("Done\n"); return EXIT_SUCCESS; } diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index 6cd7982b..dc1debac 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -74,4 +74,229 @@ test_gsm0808_enc_dec_cell_id_lai_and_lac: encoded: 05 06 04 21 63 54 23 42 (rc = test_gsm0808_enc_dec_cell_id_ci: encoded: 05 03 02 04 23 (rc = 5) test_gsm0808_enc_dec_cell_id_lac_and_ci: encoded: 05 05 01 04 23 02 35 (rc = 7) test_gsm0808_enc_dec_cell_id_global: encoded: 05 08 00 21 63 54 23 42 04 23 (rc = 10) +Testing gsm0808_sc_cfg_from_gsm48_mr_cfg(): +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0000 = 0b0000000000000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 1 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5703 = 0b0101011100000011 +Result (hr): + S15-S0 = 0703 = 0b0000011100000011 + +Input: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0000 = 0b0000000000000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5706 = 0b0101011100000110 +Result (hr): + S15-S0 = 0706 = 0b0000011100000110 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 1608 = 0b0001011000001000 +Result (hr): + S15-S0 = 0608 = 0b0000011000001000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 0412 = 0b0000010000010010 +Result (hr): + S15-S0 = 0412 = 0b0000010000010010 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 4020 = 0b0100000000100000 +Result (hr): + S15-S0 = 0020 = 0b0000000000100000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 0 +Result (fr): + S15-S0 = 1040 = 0b0001000001000000 +Result (hr): + S15-S0 = 0000 = 0b0000000000000000 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 1 +Result (fr): + S15-S0 = 4082 = 0b0100000010000010 +Result (hr): + S15-S0 = 0002 = 0b0000000000000010 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 570f = 0b0101011100001111 +Result (hr): + S15-S0 = 070f = 0b0000011100001111 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 54f2 = 0b0101010011110010 +Result (hr): + S15-S0 = 0432 = 0b0000010000110010 + +Input: + m4_75= 0 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 57ce = 0b0101011111001110 +Result (hr): + S15-S0 = 070e = 0b0000011100001110 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 0 +Result (fr): + S15-S0 = 5733 = 0b0101011100110011 +Result (hr): + S15-S0 = 0733 = 0b0000011100110011 + +Input: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 0 + m7_95= 1 + m10_2= 0 + m12_2= 1 +Result (fr): + S15-S0 = 56aa = 0b0101011010101010 +Result (hr): + S15-S0 = 062a = 0b0000011000101010 + +Input: + m4_75= 1 smod= 0 + m5_15= 0 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 0 + m10_2= 1 + m12_2= 0 +Result (fr): + S15-S0 = 5757 = 0b0101011101010111 +Result (hr): + S15-S0 = 0717 = 0b0000011100010111 + +Input: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 1 icmi= 0 + m6_70= 1 nscb= 0 + m7_40= 1 ver= 0 + m7_95= 1 + m10_2= 1 + m12_2= 1 +Result (fr): + S15-S0 = 57ff = 0b0101011111111111 +Result (hr): + S15-S0 = 073f = 0b0000011100111111 + Done -- cgit v1.2.3 From 369015c53545f2f67d8610e5d821ee75289122e5 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Fri, 21 Sep 2018 09:07:20 +0200 Subject: gsm0808_utils: constify parameter parameter cfg in gsm0808_sc_cfg_from_gsm48_mr_cfg() is used read only. Lets add a const to make this clear to the compiler. Change-Id: I31e8d273b070b0afc446a298299d4f502d6c396b --- include/osmocom/gsm/gsm0808_utils.h | 2 +- src/gsm/gsm0808_utils.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 0a7429e9..8746ceba 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -104,7 +104,7 @@ int gsm0808_dec_cell_id(struct gsm0808_cell_id *ci, const uint8_t *elem, uint8_t int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch); int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint8_t perm_spch); -uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, bool fr); +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr); /*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 4b2a5f56..0d6938ef 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1166,7 +1166,7 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, * \param[in] cfg AMR configuration in GSM 04.08 format. * \param[in] hint if the resulting configuration shall be used with a FR or HR TCH. * \returns configuration bits (S0-S15) */ -uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(struct gsm48_multi_rate_conf *cfg, +uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr) { uint16_t s15_s0 = 0; -- cgit v1.2.3 From e65c8bad46a190f3de7594d545aa4954ad17b85f Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Mon, 24 Sep 2018 12:56:31 +0700 Subject: vty/command.h: document and prettify CMD_ATTR_* flags Since the CMD_ATTR_* flags are intended to be used in bitwise operations, let's assign them proper values. Adding a new flag (e.g. CMD_ATTR_FOO_BAR) could actually result in assigning 0x03 instead of expected (0x01 << 2). Change-Id: I3b1badef830f7e6436a67673b5709ec33c060c68 Related: OS#3584 --- include/osmocom/vty/command.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h index 13d6e89d..d63dbdef 100644 --- a/include/osmocom/vty/command.h +++ b/include/osmocom/vty/command.h @@ -132,9 +132,10 @@ struct cmd_node { char name[64]; }; +/*! Attributes (flags) for \ref cmd_element */ enum { - CMD_ATTR_DEPRECATED = 1, - CMD_ATTR_HIDDEN, + CMD_ATTR_DEPRECATED = (1 << 0), + CMD_ATTR_HIDDEN = (1 << 1), }; /*! Structure of a command element */ -- cgit v1.2.3 From cf8def25d59f4453620e109c9f7f033d01fe4583 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 24 Sep 2018 04:15:20 +0200 Subject: vty reference: fix deprecation bit evaluation In vty_dump_nodes(), make sure the bitwise & is evaluated first. For the deprecation flag (0x1), the practical effect is most likely identical, assuming that the boolean ! operator flips the first bit, so I expect no visible functional difference. It still was confusing and wrong to look at. Related: OS#3584 Change-Id: I1f18e0e41da4772d092d71261b9e489dc1598923 --- src/vty/command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vty/command.c b/src/vty/command.c index 43f974ce..900680f7 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -679,7 +679,7 @@ static int vty_dump_nodes(struct vty *vty) elem = vector_slot(cnode->cmd_vector, j); if (!vty_command_is_common(elem)) continue; - if (!elem->attr & CMD_ATTR_DEPRECATED) + if (!(elem->attr & CMD_ATTR_DEPRECATED)) vty_dump_element(elem, vty); } } @@ -717,7 +717,7 @@ static int vty_dump_nodes(struct vty *vty) elem = vector_slot(cnode->cmd_vector, j); if (vty_command_is_common(elem)) continue; - if (!elem->attr & CMD_ATTR_DEPRECATED) + if (!(elem->attr & CMD_ATTR_DEPRECATED)) vty_dump_element(elem, vty); } -- cgit v1.2.3 From a7557fe0f59873f0d50553e2dec5f2903ddaeca6 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 24 Sep 2018 04:16:42 +0200 Subject: vty list: fix deprecation/hidden bit logic If a command is both hidden and deprecated, still don't show it for the 'list' command. We currently have no such nodes, as it seems, though. Related: OS#3584 Change-Id: I07ec15cab057a3e09064e0420a69121ee8eb4253 --- src/vty/command.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vty/command.c b/src/vty/command.c index 900680f7..1e77d13f 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -2728,8 +2728,7 @@ gDEFUN(config_list, config_list_cmd, "list", "Print command list\n") for (i = 0; i < vector_active(cnode->cmd_vector); i++) if ((cmd = vector_slot(cnode->cmd_vector, i)) != NULL - && !(cmd->attr == CMD_ATTR_DEPRECATED - || cmd->attr == CMD_ATTR_HIDDEN)) + && !(cmd->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) vty_out(vty, " %s%s", cmd->string, VTY_NEWLINE); return CMD_SUCCESS; } -- cgit v1.2.3 From 5398911ddb03f994de8bbda73d41810c40fb0245 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 24 Sep 2018 18:39:00 +0200 Subject: vty: omit HIDDEN from vty reference During 'show online help', the XML vty node dump, omit all commands marked HIDDEN. These commands were already hidden from the VTY reference prior to commit I1f18e0e41da4772d092d71261b9e489dc1598923, because of broken/confusing bit and boolean logic mixup. After that commit, HIDDEN commands end up in the doc. So practically, this patch here brings back the status quo of before above commit, even though the previous code clearly "intended" to list HIDDEN commands in the reference but failed to have that effect. AFAICT the complete list of commands currently hidden is: * osmo-bsc: bts/"training_sequence_code <0-7>", * osmo-bsc: ts/"phys_chan_config PCHAN" for uppercase pchans; * osmo-bts: bts/"rtp bind-ip A.B.C.D" which actually says vty_out(vty, "%% rtp bind-ip is now deprecated%s", VTY_NEWLINE); * osmo-sgsn: 'reset sgsn state' used for SGSN testing. Note that the osmo-sgsn build was broken by including hidden commands in the vty reference, since one of its hidden commands had missing doc strings and made osmotestconfig.py signal failure. This would fix that from the hide-hidden-commands angle, and so would osmo-sgsn commit I8b6e8615e409266910f2f76a10ced9ab33e4de91 from the fix-the-doc-strings angle. Change-Id: I92c3c66ff69c186234276c64478d6342e061d25e --- src/vty/command.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vty/command.c b/src/vty/command.c index 1e77d13f..a540cd5b 100644 --- a/src/vty/command.c +++ b/src/vty/command.c @@ -679,7 +679,7 @@ static int vty_dump_nodes(struct vty *vty) elem = vector_slot(cnode->cmd_vector, j); if (!vty_command_is_common(elem)) continue; - if (!(elem->attr & CMD_ATTR_DEPRECATED)) + if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) vty_dump_element(elem, vty); } } @@ -717,7 +717,7 @@ static int vty_dump_nodes(struct vty *vty) elem = vector_slot(cnode->cmd_vector, j); if (vty_command_is_common(elem)) continue; - if (!(elem->attr & CMD_ATTR_DEPRECATED)) + if (!(elem->attr & (CMD_ATTR_DEPRECATED | CMD_ATTR_HIDDEN))) vty_dump_element(elem, vty); } -- cgit v1.2.3 From b066305016141606e7f031065dc71c2002a6af0a Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 25 Sep 2018 13:05:40 +0200 Subject: gsm_utils: add function to get value strings for gsm48_chan_mode The enum gsm48_chan_mode has value strings, but no function to retrieve those strings. Lets add one. Change-Id: If715705e1ebdfcfdfae1c2099932f7bb8b3861a7 --- include/osmocom/gsm/gsm_utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h index 6ff44598..7eda5b9f 100644 --- a/include/osmocom/gsm/gsm_utils.h +++ b/include/osmocom/gsm/gsm_utils.h @@ -228,6 +228,8 @@ enum gsm_chan_t { }; extern const struct value_string gsm_chan_t_names[]; +static inline const char *gsm_chan_t_name(enum gsm48_chan_mode val) +{ return get_value_string(gsm_chan_t_names, val); } /* Deprectated functions */ /* Limit encoding and decoding to use no more than this amount of buffer bytes */ -- cgit v1.2.3 From 8515d035ae09edf3ad4d6e0dcbe526eee8bce3eb Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 25 Sep 2018 15:57:49 +0200 Subject: gsm0808: add function to convert AMR S15-S0 to gsm0408 settings Add a function to convert S0-S15 bits to struct gsm48_multi_rate_conf, which hold the codec settings for AMR. Change-Id: I973736273c236eee84decf15868190e339c3fed4 Related: OS#3548 --- include/osmocom/gsm/gsm0808_utils.h | 1 + src/gsm/gsm0808_utils.c | 41 +++++++++++ src/gsm/libosmogsm.map | 1 + tests/gsm0808/gsm0808_test.c | 57 ++++++++++++++++ tests/gsm0808/gsm0808_test.ok | 133 ++++++++++++++++++++++++++++++++++++ 5 files changed, 233 insertions(+) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 8746ceba..f70dbdb6 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -105,6 +105,7 @@ int gsm0808_chan_type_to_speech_codec(uint8_t perm_spch); int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint8_t perm_spch); uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr); +void gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t s15_s0); /*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 0d6938ef..886f546a 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1204,6 +1204,47 @@ uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cf return s15_s0; } +/*! Determine a GSM 04.08 AMR configuration struct from a set of speech codec + * configuration bits (S0-S15) + * \param[out] cfg AMR configuration in GSM 04.08 format. + * \param[in] s15_s0 configuration bits (S0-S15). */ +void gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, + uint16_t s15_s0) +{ + memset(cfg, 0, sizeof(*cfg)); + + /* Strip option bits */ + s15_s0 &= 0x00ff; + + /* Rate 5,15k must always be present */ + cfg->m5_15 = 1; + + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_4_75 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_4_75 & 0xff)) + cfg->m4_75 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_5_90 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_5_90 & 0xff)) + cfg->m5_90 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_6_70 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_6_70 & 0xff)) + cfg->m6_70 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_7_40 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_7_40 & 0xff)) + cfg->m7_40 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_7_95 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_7_95 & 0xff)) + cfg->m7_95 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_10_2 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_10_2 & 0xff)) + cfg->m10_2 = 1; + if ((s15_s0 & GSM0808_SC_CFG_DEFAULT_AMR_12_2 & 0xff) == + (GSM0808_SC_CFG_DEFAULT_AMR_12_2 & 0xff)) + cfg->m12_2 = 1; + + cfg->ver = 1; + cfg->icmi = 1; +} + /*! Print a human readable name of the cell identifier to the char buffer. * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2. * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3d08232c..dcc491d7 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -206,6 +206,7 @@ gsm0808_cell_id_u_name; gsm0808_chan_type_to_speech_codec; gsm0808_speech_codec_from_chan_type; gsm0808_sc_cfg_from_gsm48_mr_cfg; +gsm48_mr_cfg_from_gsm0808_sc_cfg; gsm0808_speech_codec_type_names; gsm0808_permitted_speech_names; gsm0808_chosen_enc_alg_names; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 6faa6890..8cf1cf4c 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -1640,6 +1640,62 @@ static void test_gsm0808_sc_cfg_from_gsm48_mr_cfg(void) test_gsm0808_sc_cfg_from_gsm48_mr_cfg_single(&cfg); } +static void test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single(uint16_t s15_s0) +{ + struct gsm48_multi_rate_conf cfg; + + printf("Input:\n"); + printf(" S15-S0 = %04x = 0b" OSMO_BIN_SPEC OSMO_BIN_SPEC "\n", s15_s0, + OSMO_BIN_PRINT(s15_s0 >> 8), OSMO_BIN_PRINT(s15_s0)); + + gsm48_mr_cfg_from_gsm0808_sc_cfg(&cfg, s15_s0); + + printf("Output:\n"); + printf(" m4_75= %u smod= %u\n", cfg.m4_75, cfg.smod); + printf(" m5_15= %u spare= %u\n", cfg.m5_15, cfg.spare); + printf(" m5_90= %u icmi= %u\n", cfg.m5_90, cfg.icmi); + printf(" m6_70= %u nscb= %u\n", cfg.m6_70, cfg.nscb); + printf(" m7_40= %u ver= %u\n", cfg.m7_40, cfg.ver); + printf(" m7_95= %u\n", cfg.m7_95); + printf(" m10_2= %u\n", cfg.m10_2); + printf(" m12_2= %u\n", cfg.m12_2); + + printf("\n"); +} + +void test_gsm48_mr_cfg_from_gsm0808_sc_cfg() +{ + printf("Testing gsm48_mr_cfg_from_gsm0808_sc_cfg():\n"); + + /* Only one codec per setting */ + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_4_75); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_5_15); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_5_90); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_6_70); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_7_40); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_7_95); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_10_2); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_12_2); + + /* Combinations */ + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_4_75 | GSM0808_SC_CFG_DEFAULT_AMR_6_70 | + GSM0808_SC_CFG_DEFAULT_AMR_10_2); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_10_2 | GSM0808_SC_CFG_DEFAULT_AMR_12_2 | + GSM0808_SC_CFG_DEFAULT_AMR_7_40); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg_single + (GSM0808_SC_CFG_DEFAULT_AMR_7_95 | GSM0808_SC_CFG_DEFAULT_AMR_12_2); +} + int main(int argc, char **argv) { printf("Testing generation of GSM0808 messages\n"); @@ -1692,6 +1748,7 @@ int main(int argc, char **argv) test_gsm0808_enc_dec_cell_id_global(); test_gsm0808_sc_cfg_from_gsm48_mr_cfg(); + test_gsm48_mr_cfg_from_gsm0808_sc_cfg(); printf("Done\n"); return EXIT_SUCCESS; diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index dc1debac..58bc5099 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -299,4 +299,137 @@ Result (fr): Result (hr): S15-S0 = 073f = 0b0000011100111111 +Testing gsm48_mr_cfg_from_gsm0808_sc_cfg(): +Input: + S15-S0 = ff03 = 0b1111111100000011 +Output: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = 0000 = 0b0000000000000000 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = ff06 = 0b1111111100000110 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 1 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = 3e08 = 0b0011111000001000 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = 0c12 = 0b0000110000010010 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = c020 = 0b1100000000100000 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 1 + m10_2= 0 + m12_2= 0 + +Input: + S15-S0 = 3040 = 0b0011000001000000 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 1 + m12_2= 0 + +Input: + S15-S0 = c082 = 0b1100000010000010 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 0 + m12_2= 1 + +Input: + S15-S0 = ff4b = 0b1111111101001011 +Output: + m4_75= 1 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 1 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 0 + m10_2= 1 + m12_2= 0 + +Input: + S15-S0 = fcd2 = 0b1111110011010010 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 1 ver= 1 + m7_95= 0 + m10_2= 1 + m12_2= 1 + +Input: + S15-S0 = c0a2 = 0b1100000010100010 +Output: + m4_75= 0 smod= 0 + m5_15= 1 spare= 0 + m5_90= 0 icmi= 1 + m6_70= 0 nscb= 0 + m7_40= 0 ver= 1 + m7_95= 1 + m10_2= 0 + m12_2= 1 + Done -- cgit v1.2.3 From 81bfef931a35771bcf1b7164b3370ae851821678 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 25 Sep 2018 16:34:19 +0200 Subject: Add new osmo-config-merge utility This utility allows you to merge an incremental config "patch" into an osmocom-style config file. The patch file follows the same syntax as the original config file. It works by appending the leaf nodes of the patch file to the respective nodes of the input config file. This process allows configuration file changes/updates to be performed in a more stable/reliable way than by means of [unified] diff files, as they break every time the context lines break. osmo-config-merge doesn't suffer from this problem, as it understands the tree-like nature of VTY config files. NITE: This only works with configuration files that have proper indenting, i.e. every level in the hierarchy must be indented excatly one character, not multiple. Change-Id: I61997a3668cc3a40d12ca023272f6d782e6fbefe --- .gitignore | 1 + debian/control | 3 +- debian/libosmocore-utils.install | 1 + utils/Makefile.am | 6 +- utils/osmo-config-merge.c | 266 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 utils/osmo-config-merge.c diff --git a/.gitignore b/.gitignore index 369277c3..451c8831 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ tests/*/*_test utils/osmo-arfcn utils/osmo-auc-gen +utils/osmo-config-merge utils/osmo-sim-test doc/codec diff --git a/debian/control b/debian/control index 540a8b5e..33ae2d42 100644 --- a/debian/control +++ b/debian/control @@ -315,7 +315,8 @@ Multi-Arch: same Description: Utilities for gsm This package contains a program for frequency calculation for GSM called 'osmo-arfcn' and a program called 'osmo-auc-gen' that is used for testing GSM - authentication. + authentication, as well as 'osmo-config-merge', a tool for merging Osmocom + configuration files. . They use the libosmocore library. The libosmocore library contain various utility functions that were originally developed as part of the OpenBSC diff --git a/debian/libosmocore-utils.install b/debian/libosmocore-utils.install index 9c3b8dce..d23cc73a 100644 --- a/debian/libosmocore-utils.install +++ b/debian/libosmocore-utils.install @@ -1,2 +1,3 @@ usr/bin/osmo-arfcn usr/bin/osmo-auc-gen +usr/bin/osmo-config-merge diff --git a/utils/Makefile.am b/utils/Makefile.am index d4999bde..fb791906 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -5,12 +5,16 @@ LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la EXTRA_DIST = conv_gen.py conv_codes_gsm.py -bin_PROGRAMS = osmo-arfcn osmo-auc-gen +bin_PROGRAMS = osmo-arfcn osmo-auc-gen osmo-config-merge osmo_arfcn_SOURCES = osmo-arfcn.c osmo_auc_gen_SOURCES = osmo-auc-gen.c +osmo_config_merge_SOURCES = osmo-config-merge.c +osmo_config_merge_LDADD = $(LDADD) $(TALLOC_LIBS) +osmo_config_merge_CFLAGS = $(TALLOC_CFLAGS) + if ENABLE_PCSC noinst_PROGRAMS = osmo-sim-test osmo_sim_test_SOURCES = osmo-sim-test.c diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c new file mode 100644 index 00000000..131486c1 --- /dev/null +++ b/utils/osmo-config-merge.c @@ -0,0 +1,266 @@ +/*! \file osmo-config-merge.c + * Utility program for merging config files with patches */ +/* + * (C) 2018 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* + This utility allows you to merge an incremental config "patch" + into an osmocom-style config file. + + The patch file follows the same syntax as the original config file. + + It works by appending the leaf nodes of the patch file to the respective + nodes of the input config file. + + This process allows configuration file changes/updates to be performed + in a more stable/reliable way than by means of [unified] diff files, + as they break every time the context lines break. + + osmo-config-merge doesn't suffer from this problem, as it understands + the tree-like nature of VTY config files. + + NITE: This only works with configuration files that have proper + indenting, i.e. every level in the hierarchy must be indented excatly + one character, not multiple. + */ + +#include +#include + +#include +#include +#include + +struct node { + struct node *parent; /* back-pointer */ + struct llist_head list; /* part of parent->children */ + struct llist_head children; /* our own children */ + char *line; +}; + +/* allocate a new node */ +static struct node *node_alloc(void *ctx) +{ + struct node *node = talloc_zero(ctx, struct node); + OSMO_ASSERT(node); + INIT_LLIST_HEAD(&node->children); + return node; +} + +/* allocate a new node as child of given parent */ +static struct node *node_alloc_child(struct node *parent) +{ + struct node *node = node_alloc(parent); + node->parent = parent; + llist_add_tail(&node->list, &parent->children); + return node; +} + +/* find a given child specified by name/line string within given parent */ +static struct node *node_find_child(struct node *parent, const char *line) +{ + struct node *n; + + llist_for_each_entry(n, &parent->children, list) { + if (!strcmp(line, n->line)) + return n; + } + return NULL; +} + +/* count the number of spaces / indent level */ +static int count_indent(const char *line) +{ + int i; + + for (i = 0; i < strlen(line); i++) { + if (line[i] != ' ') + return i; + } + return i; +} + +/* strip any triling CR / LF */ +static void chomp(char *line) +{ + while (1) { + int len = strlen(line); + if (len == 0) + return; + char *lastch = &line[len-1]; + switch (*lastch) { + case '\n': + case '\r': + *lastch = '\0'; + default: + return; + } + } +} + +/* read a config file and parse it into a tree of nodes */ +static struct node *file_read(void *ctx, const char *fname) +{ + struct node *root, *last; + FILE *infile; + char line[1024]; + int cur_indent = -1; + unsigned int line_num = 0; + + infile = fopen(fname, "r"); + if (!infile) + return NULL; + + root = node_alloc(ctx); + last = root; + while (fgets(line, sizeof(line), infile)) { + line_num++; + chomp(line); + int indent = count_indent(line); + struct node *n; + if (indent > cur_indent) { + if (indent > cur_indent+1) { + fprintf(stderr, "File '%s' isn't well-formed in line %u, aborting!\n", + fname, line_num); + exit(2); + } + /* new child to last node */ + n = node_alloc_child(last); + } else if (indent < cur_indent) { + for (int i = 0; i < cur_indent - indent; i++) { + /* go to parent, add another sibling */ + if (last->parent) + last = last->parent; + } + n = node_alloc_child(last->parent); + } else { + /* add a new sibling (child of parent) */ + n = node_alloc_child(last->parent); + } + n->line = talloc_strdup(n, line); + + last = n; + cur_indent = indent; + } + + return root; +} + +static void append_patch(struct node *cfg, struct node *patch) +{ + struct node *n; + + llist_for_each_entry(n, &patch->children, list) { + if (llist_empty(&n->children)) { + struct node *t; + /* we are an end-node, i.e. something that needs to be + * patched into the original tree. We do this by simply + * appending it to the list of siblings */ + t = node_alloc_child(cfg); + t->line = talloc_strdup(t, n->line); + } else { + struct node *c; + /* we need to iterate / recurse further */ + + /* try to find the matching original node */ + c = node_find_child(cfg, n->line); + if (!c) { + /* create it, if it's missing */ + c = node_alloc_child(cfg); + c->line = talloc_strdup(c, n->line); + } + append_patch(c, n); + } + } +} + + +static int level = -1; + +static void dump_node(struct node *root, FILE *out, bool print_node_depth) +{ + struct node *n; + level++; + + if (root->line) { + if (print_node_depth) { + for (int i = 0; i < level; i++) + fputc('*', out); + } + + fprintf(out, "%s\n", root->line); + } + + llist_for_each_entry(n, &root->children, list) { + dump_node(n, out, print_node_depth); + } + level--; +} + +static void exit_usage(int rc) +{ + fprintf(stderr, "Usage: osmo-config-merge [--debug]\n"); + exit(rc); +} + + +int main(int argc, char **argv) +{ + const char *base_fname, *patch_fname; + struct node *base_tree, *patch_tree; + bool debug_enabled = false; + + void *ctx = talloc_named_const(NULL, 0, "root"); + + if (argc < 3) + exit_usage(1); + + base_fname = argv[1]; + patch_fname = argv[2]; + + if (argc > 3) { + if (!strcmp(argv[3], "--debug")) + debug_enabled = true; + else + exit_usage(1); + } + + base_tree = file_read(ctx, base_fname); + patch_tree = file_read(ctx, patch_fname); + + if (debug_enabled) { + fprintf(stderr, "====== dumping tree (base)\n"); + dump_node(base_tree, stderr, true); + fprintf(stderr, "====== dumping tree (patch)\n"); + dump_node(patch_tree, stderr, true); + } + + append_patch(base_tree, patch_tree); + + if (debug_enabled) + fprintf(stderr, "====== dumping tree (patched)\n"); + dump_node(base_tree, stdout, false); + fflush(stdout); + + /* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */ + talloc_free(patch_tree); + talloc_free(base_tree); +} -- cgit v1.2.3 From 0d67f483e2d240089105a4d241cb8c9085e245af Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 25 Sep 2018 20:16:14 +0200 Subject: logging_vty: Ensure writing well-formed config files We want to have well-formed config files that print exactly one space per VTY/config node level, and not two. Change-Id: Ia75c7067284ea225cffe13ca71bad05a7747ae66 --- src/vty/logging_vty.c | 18 +++++++++--------- tests/logging/logging_vty_test.vty | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index b2637a5f..31edb528 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -890,24 +890,24 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) break; } - vty_out(vty, " logging filter all %u%s", + vty_out(vty, " logging filter all %u%s", tgt->filter_map & (1 << LOG_FLT_ALL) ? 1 : 0, VTY_NEWLINE); /* save filters outside of libosmocore, i.e. in app code */ if (osmo_log_info->save_fn) osmo_log_info->save_fn(vty, osmo_log_info, tgt); - vty_out(vty, " logging color %u%s", tgt->use_color ? 1 : 0, + vty_out(vty, " logging color %u%s", tgt->use_color ? 1 : 0, VTY_NEWLINE); - vty_out(vty, " logging print category %d%s", + vty_out(vty, " logging print category %d%s", tgt->print_category ? 1 : 0, VTY_NEWLINE); if (tgt->print_ext_timestamp) - vty_out(vty, " logging print extended-timestamp 1%s", VTY_NEWLINE); + vty_out(vty, " logging print extended-timestamp 1%s", VTY_NEWLINE); else - vty_out(vty, " logging timestamp %u%s", + vty_out(vty, " logging timestamp %u%s", tgt->print_timestamp ? 1 : 0, VTY_NEWLINE); if (tgt->print_level) - vty_out(vty, " logging print level 1%s", VTY_NEWLINE); - vty_out(vty, " logging print file %s%s", + vty_out(vty, " logging print level 1%s", VTY_NEWLINE); + vty_out(vty, " logging print file %s%s", get_value_string(logging_print_file_args, tgt->print_filename2), VTY_NEWLINE); @@ -918,7 +918,7 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) vty_out(vty, "%% Invalid log level %u for 'force-all'%s", tgt->loglevel, VTY_NEWLINE); else - vty_out(vty, " logging level force-all %s%s", level_str, VTY_NEWLINE); + vty_out(vty, " logging level force-all %s%s", level_str, VTY_NEWLINE); } for (i = 0; i < osmo_log_info->num_cat; i++) { @@ -941,7 +941,7 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt) continue; } - vty_out(vty, " logging level %s", cat_name); + vty_out(vty, " logging level %s", cat_name); vty_out(vty, " %s%s", osmo_str_tolower(level_str), VTY_NEWLINE); } diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index 0c552a58..0eedbe35 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -4,11 +4,11 @@ logging_vty_test# show running-config ... log stderr ... !logging level all - logging level aa debug - logging level bb info - logging level ccc notice - logging level dddd error - logging level eee fatal + logging level aa debug + logging level bb info + logging level ccc notice + logging level dddd error + logging level eee fatal ... logging_vty_test# configure terminal @@ -17,7 +17,7 @@ logging_vty_test(config)# log stderr logging_vty_test(config-log)# logging level force-all notice logging_vty_test(config-log)# show running-config ... !logging level all - logging level force-all notice + logging level force-all notice ... !logging level all logging_vty_test(config-log)# no logging level force-all -- cgit v1.2.3 From eda6fe42a5ad33d27e305c1a9b1304ac1f1cc247 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 25 Sep 2018 22:51:20 +0200 Subject: osmo-config-merge: Don't use C99 'for' loop initial declarations The existing code passed gerrit build verification but failed the master builds with the following error: osmo-config-merge.c:148:4: error: 'for' loop initial declarations are only allowed in C99 or C11 mode for (int i = 0; i < cur_indent - indent; i++) { ^ osmo-config-merge.c:148:4: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code Change-Id: Ia29e85b648c1a427be88242306634efe890e250d --- utils/osmo-config-merge.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c index 131486c1..3762c679 100644 --- a/utils/osmo-config-merge.c +++ b/utils/osmo-config-merge.c @@ -145,7 +145,8 @@ static struct node *file_read(void *ctx, const char *fname) /* new child to last node */ n = node_alloc_child(last); } else if (indent < cur_indent) { - for (int i = 0; i < cur_indent - indent; i++) { + int i; + for (i = 0; i < cur_indent - indent; i++) { /* go to parent, add another sibling */ if (last->parent) last = last->parent; @@ -202,7 +203,8 @@ static void dump_node(struct node *root, FILE *out, bool print_node_depth) if (root->line) { if (print_node_depth) { - for (int i = 0; i < level; i++) + int i; + for (i = 0; i < level; i++) fputc('*', out); } -- cgit v1.2.3 From 6afb3f50317e694e7482bbd774243dc130e3f936 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Thu, 20 Sep 2018 17:21:05 +0200 Subject: ensure unix socket paths are NUL-terminated for bind/connect The unix(7) man page recommends that sun_path is NUL-terminated when struct sockaddr_un is passed to a bind() or connect() call. Non-NUL-terminated paths only need to be dealt with at the receiving end of a UNIX domain socket. Commit 896ff6d erroneously assumed otherwise. This commit almost reverts 896ff6d: It only leaves the added osmo_strlcpy() overflow check in place. Change-Id: I6c4ac6b0a0eef4842beae4107f6f09f6cd29172a Fixes: 896ff6db161465d506bb9bb5bee2cdeef220dd2e Related: OS#2673 --- src/socket.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/socket.c b/src/socket.c index 6f56efb5..a85edb73 100644 --- a/src/socket.c +++ b/src/socket.c @@ -605,29 +605,27 @@ 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; - 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)) { + /* When an AF_UNIX socket is bound, sun_path should be NUL-terminated. See unix(7) man page. */ + 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 = socket_path_len; + local.sun_len = strlen(local.sun_path); #endif #if defined(BSD44SOCKETS) || defined(SUN_LEN) namelen = SUN_LEN(&local); #else - namelen = socket_path_len + offsetof(struct sockaddr_un, sun_path); + namelen = strlen(local.sun_path) + + offsetof(struct sockaddr_un, sun_path); #endif sfd = socket(AF_UNIX, type, proto); -- cgit v1.2.3 From f7aec792f7826a40c598bb887f953a0f96e4d54d Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Thu, 27 Sep 2018 04:43:12 +0700 Subject: utils/osmo-config-merge: explicitly return from main() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes the following compiler warning: osmo-config-merge.c: In function ‘main’: osmo-config-merge.c:268:1: warning: control reaches end of non-void function [-Wreturn-type] Despite it isn't critical, let's get rid of this warning. Change-Id: I7a80a85c8b3180dc086cd9fd20356aab16ea8100 --- utils/osmo-config-merge.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c index 3762c679..c76e42d5 100644 --- a/utils/osmo-config-merge.c +++ b/utils/osmo-config-merge.c @@ -265,4 +265,6 @@ int main(int argc, char **argv) /* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */ talloc_free(patch_tree); talloc_free(base_tree); + + return 0; } -- cgit v1.2.3 From 83c7134c7a9cbc9ef493a8c82071fb2cda24546c Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 27 Sep 2018 17:16:00 +0200 Subject: osmo-config-merge: Fix some small issues Allocate NULL context after exit_usage() calls and free it before exit so * sanitizer is happy. Also handle the error cases gracefully when a file is unreadable or formatted wrong. Change-Id: I966e63a3f7d0ff71ee0b88922aa3807d073aa232 --- utils/osmo-config-merge.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c index c76e42d5..a872d646 100644 --- a/utils/osmo-config-merge.c +++ b/utils/osmo-config-merge.c @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -126,8 +127,11 @@ static struct node *file_read(void *ctx, const char *fname) unsigned int line_num = 0; infile = fopen(fname, "r"); - if (!infile) + if (!infile) { + fprintf(stderr, "Could not open file '%s': %s\n", + fname, strerror(errno)); return NULL; + } root = node_alloc(ctx); last = root; @@ -140,7 +144,7 @@ static struct node *file_read(void *ctx, const char *fname) if (indent > cur_indent+1) { fprintf(stderr, "File '%s' isn't well-formed in line %u, aborting!\n", fname, line_num); - exit(2); + return NULL; } /* new child to last node */ n = node_alloc_child(last); @@ -229,8 +233,7 @@ int main(int argc, char **argv) const char *base_fname, *patch_fname; struct node *base_tree, *patch_tree; bool debug_enabled = false; - - void *ctx = talloc_named_const(NULL, 0, "root"); + void *ctx; if (argc < 3) exit_usage(1); @@ -245,9 +248,16 @@ int main(int argc, char **argv) exit_usage(1); } + ctx = talloc_named_const(NULL, 0, "root"); + base_tree = file_read(ctx, base_fname); patch_tree = file_read(ctx, patch_fname); + if (!base_tree || ! patch_tree) { + talloc_free(ctx); + return 2; + } + if (debug_enabled) { fprintf(stderr, "====== dumping tree (base)\n"); dump_node(base_tree, stderr, true); @@ -265,6 +275,7 @@ int main(int argc, char **argv) /* make AddressSanitizer / LeakSanitizer happy by recursively freeing the trees */ talloc_free(patch_tree); talloc_free(base_tree); + talloc_free(ctx); return 0; } -- cgit v1.2.3 From 6dd00d876e2b947e070f776f90fbb8305a237d21 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 27 Sep 2018 17:20:44 +0200 Subject: osmo-config-merge: Add manual page Change-Id: Ifaa5afe28779a805764caf76a89efb0a3169942e --- .gitignore | 1 + Makefile.am | 2 +- configure.ac | 14 ++++++++++ man/Makefile.am | 15 +++++++++++ man/osmo-config-merge.adoc | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 man/Makefile.am create mode 100644 man/osmo-config-merge.adoc diff --git a/.gitignore b/.gitignore index 451c8831..cb2ce683 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,7 @@ doc/gsm doc/gb doc/html.tar doc/*.tag +man/*.8 tags src/crc*gen.c diff --git a/Makefile.am b/Makefile.am index de5eb35d..745d482c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc utils tests +SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc utils tests man pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc \ diff --git a/configure.ac b/configure.ac index bc3358a0..529aad1d 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,19 @@ AC_ARG_ENABLE(doxygen, AC_PATH_PROG(DOXYGEN,doxygen,false) AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false && test "x$doxygen" = "xyes") +AC_ARG_ENABLE([man-doc], + [AS_HELP_STRING([--disable-man-doc], [Disable man page documentation])], + [ BUILD_MAN=$enableval ], [ BUILD_MAN="yes" ]) + +AS_IF([test "x$BUILD_MAN" = "xyes"], [ + AC_CHECK_PROG(A2X, [a2x], [yes]) + AS_IF([test "$A2X" != "yes"], + [AC_MSG_ERROR([a2x not found, please install asciidoc or use the + option --disable-man-doc])]) +]) +AM_CONDITIONAL(BUILD_MAN, test "x$BUILD_MAN" = "xyes") +AC_SUBST(BUILD_MAN) + # check for syscal fallback on glibc < 2.25 - can be removed once glibc version requirement is bumped AC_CHECK_DECLS([SYS_getrandom], [], [], [[#include ]]) @@ -370,6 +383,7 @@ AC_OUTPUT( libosmoctrl.pc libosmosim.pc include/Makefile + man/Makefile src/Makefile src/vty/Makefile src/codec/Makefile diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 00000000..b2877148 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,15 @@ +if BUILD_MAN +man_MANS = osmo-config-merge.8 +endif + +ASCIIDOCS = osmo-config-merge.adoc + +A2X_OPTS_MANPAGE = --doctype manpage --format manpage -D ${builddir} + +%.8 : %.adoc + a2x ${A2X_OPTS_MANPAGE} $< + +EXTRA_DIST = ${ASCIIDOCS} + +CLEANFILES = \ + osmo-config-merge.8 diff --git a/man/osmo-config-merge.adoc b/man/osmo-config-merge.adoc new file mode 100644 index 00000000..205fb502 --- /dev/null +++ b/man/osmo-config-merge.adoc @@ -0,0 +1,64 @@ +osmo-config-merge(8) +===================== + +NAME +---- +osmo-config-merge - Merge osmocom config snippets into an existing config + +SYNOPSIS +-------- +[verse] +*osmo-config-merge* [--debug] + +DESCRIPTION +----------- +This utility allows you to merge an incremental config "patch" +into an osmocom-style config file. + +The patch file follows the same syntax as the original config file. + +It works by appending the leaf nodes of the patch file to the respective +nodes of the input config file. + +This process allows configuration file changes/updates to be performed +in a more stable/reliable way than by means of (unified) diff files, +as they break every time the context lines break. + +osmo-config-merge doesn't suffer from this problem, as it understands +the tree-like nature of VTY config files. + +The resulting config is printed to stdout. + +NOTE: This only works with configuration files that have proper +indenting, i.e. every level in the hierarchy must be indented excatly +one character, not multiple. + +OPTIONS +------- +*--debug*:: + Show debugging output when parsing the config tree. Needs to be the last argument. + +EXAMPLE USAGE +------------- +[verse] +$ osmo-config-merge osmo-msc.cfg.base osmo-msc_change_network.cfg > osmo-msc.cfg + +EXIT STATUS +----------- +Exit status is 0 if the command was successful, and 1 in case of a +wrong/missing argument. If the tool detects an error in the patch file the +exit status is 2. + +SEE ALSO +-------- +The official Osmocom documentation including the VTY config refernce can be +found at: http://ftp.osmocom.org/docs/latest/ + +The Osmocom wiki is located at: http://projects.osmocom.org/ + + +AUTHORS +------- +osmo-config-merge was written by Harald Welte. + +The man page was written by Daniel Willmann. -- cgit v1.2.3 From 40f35212c71e8926b0dfe7463af959f00c56cd82 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 29 Sep 2018 01:41:58 +0200 Subject: Revert "osmo-config-merge: Add manual page" This reverts commit 6dd00d876e2b947e070f776f90fbb8305a237d21. Unfortunately, it seems older a2x versions don't support "-D" for manpage generation: All the osmocom master builds started to fail with: make[2]: Entering directory '/build/deps/libosmocore/man' a2x --doctype manpage --format manpage -D . osmo-config-merge.adoc a2x: WARNING: --destination-dir option is only applicable to HTML based outputs a2x: ERROR: "xmllint" --nonet --noout --valid "/build/deps/libosmocore/man/osmo-config-merge.xml" returned non-zero exit status 127 Makefile:545: recipe for target 'osmo-config-merge.8' failed Change-Id: I0f45362d3e978c328d962a5c0d883eade27b875c --- .gitignore | 1 - Makefile.am | 2 +- configure.ac | 14 ---------- man/Makefile.am | 15 ----------- man/osmo-config-merge.adoc | 64 ---------------------------------------------- 5 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 man/Makefile.am delete mode 100644 man/osmo-config-merge.adoc diff --git a/.gitignore b/.gitignore index cb2ce683..451c8831 100644 --- a/.gitignore +++ b/.gitignore @@ -81,7 +81,6 @@ doc/gsm doc/gb doc/html.tar doc/*.tag -man/*.8 tags src/crc*gen.c diff --git a/Makefile.am b/Makefile.am index 745d482c..de5eb35d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc utils tests man +SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc utils tests pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc \ diff --git a/configure.ac b/configure.ac index 529aad1d..bc3358a0 100644 --- a/configure.ac +++ b/configure.ac @@ -77,19 +77,6 @@ AC_ARG_ENABLE(doxygen, AC_PATH_PROG(DOXYGEN,doxygen,false) AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false && test "x$doxygen" = "xyes") -AC_ARG_ENABLE([man-doc], - [AS_HELP_STRING([--disable-man-doc], [Disable man page documentation])], - [ BUILD_MAN=$enableval ], [ BUILD_MAN="yes" ]) - -AS_IF([test "x$BUILD_MAN" = "xyes"], [ - AC_CHECK_PROG(A2X, [a2x], [yes]) - AS_IF([test "$A2X" != "yes"], - [AC_MSG_ERROR([a2x not found, please install asciidoc or use the - option --disable-man-doc])]) -]) -AM_CONDITIONAL(BUILD_MAN, test "x$BUILD_MAN" = "xyes") -AC_SUBST(BUILD_MAN) - # check for syscal fallback on glibc < 2.25 - can be removed once glibc version requirement is bumped AC_CHECK_DECLS([SYS_getrandom], [], [], [[#include ]]) @@ -383,7 +370,6 @@ AC_OUTPUT( libosmoctrl.pc libosmosim.pc include/Makefile - man/Makefile src/Makefile src/vty/Makefile src/codec/Makefile diff --git a/man/Makefile.am b/man/Makefile.am deleted file mode 100644 index b2877148..00000000 --- a/man/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -if BUILD_MAN -man_MANS = osmo-config-merge.8 -endif - -ASCIIDOCS = osmo-config-merge.adoc - -A2X_OPTS_MANPAGE = --doctype manpage --format manpage -D ${builddir} - -%.8 : %.adoc - a2x ${A2X_OPTS_MANPAGE} $< - -EXTRA_DIST = ${ASCIIDOCS} - -CLEANFILES = \ - osmo-config-merge.8 diff --git a/man/osmo-config-merge.adoc b/man/osmo-config-merge.adoc deleted file mode 100644 index 205fb502..00000000 --- a/man/osmo-config-merge.adoc +++ /dev/null @@ -1,64 +0,0 @@ -osmo-config-merge(8) -===================== - -NAME ----- -osmo-config-merge - Merge osmocom config snippets into an existing config - -SYNOPSIS --------- -[verse] -*osmo-config-merge* [--debug] - -DESCRIPTION ------------ -This utility allows you to merge an incremental config "patch" -into an osmocom-style config file. - -The patch file follows the same syntax as the original config file. - -It works by appending the leaf nodes of the patch file to the respective -nodes of the input config file. - -This process allows configuration file changes/updates to be performed -in a more stable/reliable way than by means of (unified) diff files, -as they break every time the context lines break. - -osmo-config-merge doesn't suffer from this problem, as it understands -the tree-like nature of VTY config files. - -The resulting config is printed to stdout. - -NOTE: This only works with configuration files that have proper -indenting, i.e. every level in the hierarchy must be indented excatly -one character, not multiple. - -OPTIONS -------- -*--debug*:: - Show debugging output when parsing the config tree. Needs to be the last argument. - -EXAMPLE USAGE -------------- -[verse] -$ osmo-config-merge osmo-msc.cfg.base osmo-msc_change_network.cfg > osmo-msc.cfg - -EXIT STATUS ------------ -Exit status is 0 if the command was successful, and 1 in case of a -wrong/missing argument. If the tool detects an error in the patch file the -exit status is 2. - -SEE ALSO --------- -The official Osmocom documentation including the VTY config refernce can be -found at: http://ftp.osmocom.org/docs/latest/ - -The Osmocom wiki is located at: http://projects.osmocom.org/ - - -AUTHORS -------- -osmo-config-merge was written by Harald Welte. - -The man page was written by Daniel Willmann. -- cgit v1.2.3 From ea6f519ff84c31acd2689e92adb4dc1688dd9a7a Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Mon, 1 Oct 2018 15:51:18 +0200 Subject: vty logging: fix crash when missing 'logging enable' We must explicitly check the return value of osmo_log_vty2tgt(), or may run into a segfault. I wasn't aware of this and introduced numerous such cases in I36f17c131cc70ce5a1aef62fd9693097de230cd4. Reproduce: on the VTY, do not issue 'logging enable', invoke 'logging level force-all LEVEL' first. Show in logging_vty_test.vty that this situation is now again amended by telling the user that logging was not enabled. Related: OS#3611 Change-Id: Id11702d1801d6654ca5e5a51b597a0d802e2e8dd --- src/vty/logging_vty.c | 8 ++++++++ tests/logging/logging_vty_test.vty | 3 +++ 2 files changed, 11 insertions(+) diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 31edb528..f3e1419c 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -364,6 +364,10 @@ DEFUN(logging_level_set_all, logging_level_set_all_cmd, struct log_target *tgt = osmo_log_vty2tgt(vty); int level = log_parse_level(argv[0]); int i; + + if (!tgt) + return CMD_WARNING; + for (i = 0; i < osmo_log_info->num_cat; i++) { struct log_category *cat = &tgt->categories[i]; /* skip empty entries in the array */ @@ -391,6 +395,8 @@ DEFUN(logging_level_force_all, logging_level_force_all_cmd, { struct log_target *tgt = osmo_log_vty2tgt(vty); int level = log_parse_level(argv[0]); + if (!tgt) + return CMD_WARNING; log_set_log_level(tgt, level); return CMD_SUCCESS; } @@ -400,6 +406,8 @@ DEFUN(no_logging_level_force_all, no_logging_level_force_all_cmd, NO_STR LOGGING_STR LEVEL_STR NO_FORCE_ALL_STR) { struct log_target *tgt = osmo_log_vty2tgt(vty); + if (!tgt) + return CMD_WARNING; log_set_log_level(tgt, 0); return CMD_SUCCESS; } diff --git a/tests/logging/logging_vty_test.vty b/tests/logging/logging_vty_test.vty index 0eedbe35..b1909271 100644 --- a/tests/logging/logging_vty_test.vty +++ b/tests/logging/logging_vty_test.vty @@ -28,6 +28,9 @@ logging_vty_test(config-log)# exit logging_vty_test(config)# no log stderr logging_vty_test(config)# exit +logging_vty_test# logging level force-all notice +Logging was not enabled. + logging_vty_test# logging enable logging_vty_test# logging filter all 1 logging_vty_test# logging print category-hex 0 -- cgit v1.2.3 From d741b783153455010338e70ffaf52653e76584b6 Mon Sep 17 00:00:00 2001 From: Shinjo Park Date: Sun, 7 Oct 2018 20:20:32 +0200 Subject: GSMTAP: add definitions for new LTE RRC channels Later release of 3GPP TS 36.331 added new LTE RRC channels. This commit additionally defines LTE RRC message types existing in Release V15.3.0. Change-Id: Ifa48b2227be15af04c9a4702d2025abcc660f0df --- include/osmocom/core/gsmtap.h | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h index 9f5049f8..9e3db0b9 100644 --- a/include/osmocom/core/gsmtap.h +++ b/include/osmocom/core/gsmtap.h @@ -245,16 +245,31 @@ enum { /* LTE RRC message types */ enum { - GSMTAP_LTE_RRC_SUB_DL_CCCH_Message = 0, - GSMTAP_LTE_RRC_SUB_DL_DCCH_Message, - GSMTAP_LTE_RRC_SUB_UL_CCCH_Message, - GSMTAP_LTE_RRC_SUB_UL_DCCH_Message, - GSMTAP_LTE_RRC_SUB_BCCH_BCH_Message, - GSMTAP_LTE_RRC_SUB_BCCH_DL_SCH_Message, - GSMTAP_LTE_RRC_SUB_PCCH_Message, - GSMTAP_LTE_RRC_SUB_MCCH_Message, - - GSMTAP_LTE_RRC_SUB_MAX + GSMTAP_LTE_RRC_SUB_DL_CCCH_Message = 0, + GSMTAP_LTE_RRC_SUB_DL_DCCH_Message, + GSMTAP_LTE_RRC_SUB_UL_CCCH_Message, + GSMTAP_LTE_RRC_SUB_UL_DCCH_Message, + GSMTAP_LTE_RRC_SUB_BCCH_BCH_Message, + GSMTAP_LTE_RRC_SUB_BCCH_DL_SCH_Message, + GSMTAP_LTE_RRC_SUB_PCCH_Message, + GSMTAP_LTE_RRC_SUB_MCCH_Message, + GSMTAP_LTE_RRC_SUB_BCCH_BCH_Message_MBMS, + GSMTAP_LTE_RRC_SUB_BCCH_DL_SCH_Message_BR, + GSMTAP_LTE_RRC_SUB_BCCH_DL_SCH_Message_MBMS, + GSMTAP_LTE_RRC_SUB_SC_MCCH_Message, + GSMTAP_LTE_RRC_SUB_SBCCH_SL_BCH_Message, + GSMTAP_LTE_RRC_SUB_SBCCH_SL_BCH_Message_V2X, + GSMTAP_LTE_RRC_SUB_DL_CCCH_Message_NB, + GSMTAP_LTE_RRC_SUB_DL_DCCH_Message_NB, + GSMTAP_LTE_RRC_SUB_UL_CCCH_Message_NB, + GSMTAP_LTE_RRC_SUB_UL_DCCH_Message_NB, + GSMTAP_LTE_RRC_SUB_BCCH_BCH_Message_NB, + GSMTAP_LTE_RRC_SUB_BCCH_BCH_Message_TDD_NB, + GSMTAP_LTE_RRC_SUB_BCCH_DL_SCH_Message_NB, + GSMTAP_LTE_RRC_SUB_PCCH_Message_NB, + GSMTAP_LTE_RRC_SUB_SC_MCCH_Message_NB, + + GSMTAP_LTE_RRC_SUB_MAX }; /* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ -- cgit v1.2.3 From f589cbbdee7f78256af3a33f962faa1349f4791d Mon Sep 17 00:00:00 2001 From: Shinjo Park Date: Sun, 7 Oct 2018 20:23:32 +0200 Subject: GSMTAP: add definitions for LTE NAS subtypes Wireshark GSMTAP dissector has LTE NAS subtypes for plain NAS messages and NAS messages with security header. This commit adds definition for these subtypes. Change-Id: I49d15fb13299c1bcbe0fb7e50bf222294c7a49ef --- include/osmocom/core/gsmtap.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h index 9e3db0b9..9c2965be 100644 --- a/include/osmocom/core/gsmtap.h +++ b/include/osmocom/core/gsmtap.h @@ -272,6 +272,14 @@ enum { GSMTAP_LTE_RRC_SUB_MAX }; +/* LTE NAS message types */ +enum { + GSMTAP_LTE_NAS_PLAIN = 0, + GSMTAP_LTE_NAS_SEC_HEADER, + + GSMTAP_LTE_NAS_SUB_MAX +}; + /* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ /*! Structure of the GTMTAP pseudo-header */ struct gsmtap_hdr { -- cgit v1.2.3 From 0903fce28be85f28b1c9e803df8cec69fefa2de9 Mon Sep 17 00:00:00 2001 From: Shinjo Park Date: Sun, 7 Oct 2018 20:25:06 +0200 Subject: GSMTAP: fix typos in comments Change-Id: I2e710141ee90ddc8b5336d5f81e99bd918d10106 --- include/osmocom/core/gsmtap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h index 9c2965be..35ba71e5 100644 --- a/include/osmocom/core/gsmtap.h +++ b/include/osmocom/core/gsmtap.h @@ -281,7 +281,7 @@ enum { }; /* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ -/*! Structure of the GTMTAP pseudo-header */ +/*! Structure of the GSMTAP pseudo-header */ struct gsmtap_hdr { uint8_t version; /*!< version, set to 0x01 currently */ uint8_t hdr_len; /*!< length in number of 32bit words */ @@ -301,7 +301,7 @@ struct gsmtap_hdr { } __attribute__((packed)); -/*! Structure of the GTMTAP libosmocore logging header */ +/*! Structure of the GSMTAP libosmocore logging header */ struct gsmtap_osmocore_log_hdr { struct { uint32_t sec; -- cgit v1.2.3 From f653821fb30f511be6cb775403ae3a5fc9e8ccd6 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Wed, 10 Oct 2018 16:09:32 +0200 Subject: fix error handling gprs_ns_nsip_listen() If we cannot bind the listening socket, reset related fields in the osmo fd structure to NULL again. Otherwise our caller might eventually try to use an uninitialized osmo fd. Change-Id: Ia953b2eff54cac0bd980944291f75db14df09a34 Related: OS#3643 --- src/gb/gprs_ns.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 9b7cc056..198ead19 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1628,8 +1628,11 @@ int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi) LOGP(DNS, LOGL_NOTICE, "Listening for nsip packets on %s:%u\n", inet_ntoa(in), nsi->nsip.local_port); } - if (ret < 0) + if (ret < 0) { + nsi->nsip.fd.cb = NULL; + nsi->nsip.fd.data = NULL; return ret; + } ret = setsockopt(nsi->nsip.fd.fd, IPPROTO_IP, IP_TOS, &nsi->nsip.dscp, sizeof(nsi->nsip.dscp)); -- cgit v1.2.3 From 4290803d89d129c1eb8b762b9b547e5df6204401 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 10 Oct 2018 17:04:28 +0200 Subject: gsm_08_58.h: Introduce struct abis_rsl_link_id It will allow to make code handling link_id values more easier to read and less prone to errors. union is used to be able to get the full octet in case we need to pass it somewhere else or encode it. An extra union is used in struct abis_rsl_common_hdr to allow using fields directly while keeping API compatibility. Change-Id: Ibd75a493bcfdf46c028ea466867d0c0d83d46343 --- include/osmocom/gsm/protocol/gsm_08_58.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h index e5ff4646..c7a7d8aa 100644 --- a/include/osmocom/gsm/protocol/gsm_08_58.h +++ b/include/osmocom/gsm/protocol/gsm_08_58.h @@ -25,10 +25,30 @@ #include +#include + /*! \addtogroup rsl * @{ * \file gsm_08_58.h */ +/* Link Identifier 9.3.2 */ +union abis_rsl_link_id { +#if OSMO_IS_BIG_ENDIAN + uint8_t cbits:2, + na:1, + reserved:2; + sapi:3; +#elif OSMO_IS_LITTLE_ENDIAN + uint8_t sapi:3, + reserved:2, + na:1, + cbits:2; +#endif + uint8_t link_id; +} __attribute__ ((packed)); +#define ABIS_RSL_LINK_ID_CBITS_FACCH_SDCCH 0x00 +#define ABIS_RSL_LINK_ID_CBITS_SACCH 0x01 + /*! RSL common header */ struct abis_rsl_common_hdr { uint8_t msg_discr; /*!< message discriminator (ABIS_RSL_MDISC_*) */ @@ -42,7 +62,10 @@ struct abis_rsl_rll_hdr { uint8_t ie_chan; /*!< \ref RSL_IE_CHAN_NR (tag) */ uint8_t chan_nr; /*!< RSL channel number (value) */ uint8_t ie_link_id; /*!< \ref RSL_IE_LINK_IDENT (tag) */ - uint8_t link_id; /*!< RSL link identifier (value) */ + union { + uint8_t link_id; /* API backward compat */ + union abis_rsl_link_id link_id_fields; /*!< RSL link identifier (value) */ + }; uint8_t data[0]; /*!< message payload data */ } __attribute__ ((packed)); -- cgit v1.2.3 From e484d42bf2bdbc4e4add056a6564faa7c856e46b Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Tue, 9 Oct 2018 14:09:04 +0200 Subject: add support for ipaccess messages on the ctrl interface In ctrl_handle_msg(), check for IPACCESS protocol messages and respond to such messages in the same way as ipa_ccm_rcvmsg_base() does. This will allow the TTCN3 IPA "chopped ping" test to pass on control interfaces. Change-Id: I9d7137c830981ccad03806b30b776e2b1f1b4699 Related: OS#2010 --- src/ctrl/control_if.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/ctrl/control_if.c b/src/ctrl/control_if.c index 5962f7eb..ed18a2fc 100644 --- a/src/ctrl/control_if.c +++ b/src/ctrl/control_if.c @@ -389,20 +389,44 @@ int ctrl_handle_msg(struct ctrl_handle *ctrl, struct ctrl_connection *ccon, stru struct ipaccess_head_ext *iph_ext; int result; - if (msg->len < sizeof(*iph) + sizeof(*iph_ext)) { + if (msg->len < sizeof(*iph)) { LOGP(DLCTRL, LOGL_ERROR, "The message is too short.\n"); return -EINVAL; } - iph = (struct ipaccess_head *) msg->data; + if (iph->proto == IPAC_PROTO_IPACCESS) { + uint8_t msg_type = *(msg->l2h); + switch (msg_type) { + case IPAC_MSGT_PING: + if (ipa_ccm_send_pong(ccon->write_queue.bfd.fd) < 0) + LOGP(DLINP, LOGL_ERROR, "Cannot send PONG message. Reason: %s\n", strerror(errno)); + break; + case IPAC_MSGT_PONG: + break; + case IPAC_MSGT_ID_ACK: + if (ipa_ccm_send_id_ack(ccon->write_queue.bfd.fd) < 0) + LOGP(DLINP, LOGL_ERROR, "Cannot send ID_ACK message. Reason: %s\n", strerror(errno)); + break; + default: + LOGP(DLCTRL, LOGL_DEBUG, "Received unhandled IPACCESS protocol message of type 0x%x: %s\n", + msg_type, msgb_hexdump(msg)); + break; + } + return 0; + } if (iph->proto != IPAC_PROTO_OSMO) { - LOGP(DLCTRL, LOGL_ERROR, "Protocol mismatch. We got 0x%x\n", iph->proto); + LOGP(DLCTRL, LOGL_ERROR, "Protocol mismatch. Received protocol 0x%x message: %s\n", + iph->proto, msgb_hexdump(msg)); + return -EINVAL; + } + if (msg->len < sizeof(*iph) + sizeof(*iph_ext)) { + LOGP(DLCTRL, LOGL_ERROR, "The message is too short.\n"); return -EINVAL; } - iph_ext = (struct ipaccess_head_ext *) iph->data; if (iph_ext->proto != IPAC_PROTO_EXT_CTRL) { - LOGP(DLCTRL, LOGL_ERROR, "Extended protocol mismatch. We got 0x%x\n", iph_ext->proto); + LOGP(DLCTRL, LOGL_ERROR, "Extended protocol mismatch. Received protocol 0x%x message: %s\n", + iph_ext->proto, msgb_hexdump(msg)); return -EINVAL; } -- cgit v1.2.3 From f6c369fb8c1b2b6a567da277f35285284b43b089 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 16 Oct 2018 15:24:47 +0200 Subject: gsm0808: allow decoding of zero length speech codec lists. 3GPP_TS_48.008, 3.2.2.103 Speech Codec List states the following: "The length indicator (octet 2) is a binary number indicating the absolute length of the contents after the length indicator. The length depends on the number and type of Speech Codec Elements to be included. The minimum length of one Speech Codec Element is 1 octet and the maximum length is 3 octets. The maximum number of Speech Codec Elements within the Speech Codec List is not defined." This clearly refers only to the length of a single speech codec element but not on the overall list. So speech codec lists with length 0 are indeed permitted by the spec. - Remove the assertion that checks on zero length speech codec lists. Change-Id: I1eb1f4466b98bdd26d765b0e4cc690b5e89e9dd6 Related: OS#3657 --- src/gsm/gsm0808_utils.c | 10 ---------- tests/gsm0808/gsm0808_test.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 886f546a..2348105d 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -349,9 +349,6 @@ uint8_t gsm0808_enc_speech_codec_list(struct msgb *msg, OSMO_ASSERT(msg); OSMO_ASSERT(scl); - /* Empty list */ - OSMO_ASSERT(scl->len >= 1); - msgb_put_u8(msg, GSM0808_IE_SPEECH_CODEC_LIST); tlv_len = msgb_put(msg, 1); old_tail = msg->tail; @@ -384,8 +381,6 @@ int gsm0808_dec_speech_codec_list(struct gsm0808_speech_codec_list *scl, OSMO_ASSERT(scl); if (!elem) return -EINVAL; - if (len == 0) - return -EINVAL; memset(scl, 0, sizeof(*scl)); @@ -404,11 +399,6 @@ int gsm0808_dec_speech_codec_list(struct gsm0808_speech_codec_list *scl, scl->len = decoded; - /* Empty list */ - if (decoded < 1) { - return -EINVAL; - } - return (int)(elem - old_elem); } diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 8cf1cf4c..0b2794f1 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -695,6 +695,28 @@ static void test_gsm0808_enc_dec_speech_codec_list() msgb_free(msg); } +static void test_gsm0808_enc_dec_empty_speech_codec_list() +{ + struct gsm0808_speech_codec_list enc_scl = { + .len = 0, + }; + struct gsm0808_speech_codec_list dec_scl = {}; + struct msgb *msg; + uint8_t rc_enc; + int rc_dec; + + msg = msgb_alloc(1024, "output buffer"); + rc_enc = gsm0808_enc_speech_codec_list(msg, &enc_scl); + OSMO_ASSERT(rc_enc == 2); + + rc_dec = gsm0808_dec_speech_codec_list(&dec_scl, msg->data + 2, msg->len - 2); + OSMO_ASSERT(rc_dec == 0); + + OSMO_ASSERT(memcmp(&enc_scl, &dec_scl, sizeof(enc_scl)) == 0); + + msgb_free(msg); +} + static void test_gsm0808_enc_dec_channel_type() { struct gsm0808_channel_type enc_ct = { @@ -1725,6 +1747,7 @@ int main(int argc, char **argv) test_gsm0808_enc_dec_speech_codec_ext_with_cfg(); test_gsm0808_enc_dec_speech_codec_with_cfg(); test_gsm0808_enc_dec_speech_codec_list(); + test_gsm0808_enc_dec_empty_speech_codec_list(); test_gsm0808_enc_dec_channel_type(); test_gsm0808_enc_dec_encrypt_info(); -- cgit v1.2.3 From 41b6b5e3fc0ff9928052ce7183aebe8fe4810553 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Oct 2018 10:57:36 +0200 Subject: osmo-config-merge: fclose() what we fopen() Change-Id: Ib44f902e5bca2277f1b340d34fabbd2a298d683e Fixes: Coverity CID#188851 --- utils/osmo-config-merge.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/osmo-config-merge.c b/utils/osmo-config-merge.c index a872d646..afaf86b5 100644 --- a/utils/osmo-config-merge.c +++ b/utils/osmo-config-merge.c @@ -144,6 +144,7 @@ static struct node *file_read(void *ctx, const char *fname) if (indent > cur_indent+1) { fprintf(stderr, "File '%s' isn't well-formed in line %u, aborting!\n", fname, line_num); + fclose(infile); return NULL; } /* new child to last node */ @@ -166,6 +167,7 @@ static struct node *file_read(void *ctx, const char *fname) cur_indent = indent; } + fclose(infile); return root; } -- cgit v1.2.3 From 37608f911d6d046c968795e051f2ead8d04e58c0 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Oct 2018 12:32:55 +0200 Subject: timerfd_create(): Fix error handling of osmo_fd_register() Change-Id: Ia2528cc3e3155bbc9cb32dee0e3af99cc6e1c654 Closes: Coverity CID#188853 --- src/select.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/select.c b/src/select.c index 0b115c61..b594ca55 100644 --- a/src/select.c +++ b/src/select.c @@ -324,11 +324,18 @@ int osmo_timerfd_setup(struct osmo_fd *ofd, int (*cb)(struct osmo_fd *, unsigned ofd->when = BSC_FD_READ; if (ofd->fd < 0) { + int rc; + ofd->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); if (ofd->fd < 0) return ofd->fd; - osmo_fd_register(ofd); + rc = osmo_fd_register(ofd); + if (rc < 0) { + close(ofd->fd); + ofd->fd = -1; + return rc; + } } return 0; } -- cgit v1.2.3 From e8e4322bc91ba8e2591d128dce01b00406dc0aa2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Oct 2018 13:22:31 +0200 Subject: telnet_interface: avoid double-close of fd() Change-Id: Ibd81f29fa22d53553bd73c055d6a1f5255a69bad Fixes: Coverity CID#135238 --- src/vty/telnet_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vty/telnet_interface.c b/src/vty/telnet_interface.c index 0ccf8dc6..fdd88c1f 100644 --- a/src/vty/telnet_interface.c +++ b/src/vty/telnet_interface.c @@ -177,7 +177,7 @@ static int telnet_new_connection(struct osmo_fd *fd, unsigned int what) connection->vty = vty_create(new_connection, connection); if (!connection->vty) { LOGP(0, LOGL_ERROR, "couldn't create VTY\n"); - close(new_connection); + /* vty_create() is already closing the fd if it returns NULL */ talloc_free(connection); return -1; } -- cgit v1.2.3 From 2e0a945d3d2bc6ea795e7148311c07c1073053b1 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 21 Oct 2018 13:22:52 +0200 Subject: vty.c: Set vty->fd to -1 after closing the FD Change-Id: I07d105f4a810dd809fbf6feb5c04e7410020c887 --- src/vty/vty.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vty/vty.c b/src/vty/vty.c index ad535371..70f6811a 100644 --- a/src/vty/vty.c +++ b/src/vty/vty.c @@ -221,8 +221,10 @@ void vty_close(struct vty *vty) vector_unset(vtyvec, vty->fd); /* Close socket. */ - if (vty->fd > 0) + if (vty->fd > 0) { close(vty->fd); + vty->fd = -1; + } if (vty->buf) { talloc_free(vty->buf); -- cgit v1.2.3 From fb97e72e52008da2667599a458bb435129510646 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 10 Oct 2018 20:41:40 +0200 Subject: gsm_08_58.h: Introduce struct abis_rsl_chan_nr It will allow to make code handling chan_nr values more easier to read and less prone to errors. union is used to be able to get the full octet in case we need to pass it somewhere else or encode it. An extra union is used in struct abis_rsl_common_hdr and others to allow using fields directly while keeping API compatibility. Change-Id: Icd6822021207270a00106c50f8ca6b93c1250df9 --- include/osmocom/gsm/protocol/gsm_08_58.h | 35 +++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h index c7a7d8aa..cd28caf8 100644 --- a/include/osmocom/gsm/protocol/gsm_08_58.h +++ b/include/osmocom/gsm/protocol/gsm_08_58.h @@ -31,6 +31,26 @@ * @{ * \file gsm_08_58.h */ +/* Channel Number 9.3.1 */ +union abis_rsl_chan_nr { +#if OSMO_IS_BIG_ENDIAN + uint8_t cbits:5, + tn:3; +#elif OSMO_IS_LITTLE_ENDIAN + uint8_t tn:3, + cbits:5; +#endif + uint8_t chan_nr; +} __attribute__ ((packed)); +#define ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs 0x01 +#define ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(ss) (0x02 + (ss)) +#define ABIS_RSL_CHAN_NR_CBITS_SDCCH4_ACCH(ss) (0x04 + (ss)) +#define ABIS_RSL_CHAN_NR_CBITS_SDCCH8_ACCH(ss) (0x08 + (ss)) +#define ABIS_RSL_CHAN_NR_CBITS_BCCH 0x10 +#define ABIS_RSL_CHAN_NR_CBITS_RACH 0x11 +#define ABIS_RSL_CHAN_NR_CBITS_PCH_AGCH 0x12 +#define ABIS_RSL_CHAN_NR_CBITS_OSMO_PDCH 0x18 /*< non-standard, for dyn TS */ + /* Link Identifier 9.3.2 */ union abis_rsl_link_id { #if OSMO_IS_BIG_ENDIAN @@ -60,7 +80,10 @@ struct abis_rsl_common_hdr { struct abis_rsl_rll_hdr { struct abis_rsl_common_hdr c; uint8_t ie_chan; /*!< \ref RSL_IE_CHAN_NR (tag) */ - uint8_t chan_nr; /*!< RSL channel number (value) */ + union { + uint8_t chan_nr; /* API backward compat */ + union abis_rsl_chan_nr chan_nr_fields; /*!< RSL channel number (value) */ + }; uint8_t ie_link_id; /*!< \ref RSL_IE_LINK_IDENT (tag) */ union { uint8_t link_id; /* API backward compat */ @@ -73,7 +96,10 @@ struct abis_rsl_rll_hdr { struct abis_rsl_dchan_hdr { struct abis_rsl_common_hdr c; uint8_t ie_chan; /*!< \ref RSL_IE_CHAN_NR (tag) */ - uint8_t chan_nr; /*!< RSL channel number (value) */ + union { + uint8_t chan_nr; /* API backward compat */ + union abis_rsl_chan_nr chan_nr_fields; /*!< RSL channel number (value) */ + }; uint8_t data[0]; /*!< message payload data */ } __attribute__ ((packed)); @@ -81,7 +107,10 @@ struct abis_rsl_dchan_hdr { struct abis_rsl_cchan_hdr { struct abis_rsl_common_hdr c; uint8_t ie_chan; /*!< \ref RSL_IE_CHAN_NR (tag) */ - uint8_t chan_nr; /*!< RSL channel number (value) */ + union { + uint8_t chan_nr; /* API backward compat */ + union abis_rsl_chan_nr chan_nr_fields; /*!< RSL channel number (value) */ + }; uint8_t data[0]; /*!< message payload data */ } __attribute__ ((packed)); -- cgit v1.2.3 From 6721144c80c1160e28a2da86b0f33e050fe9adaf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 7 Oct 2018 20:10:57 +0200 Subject: SGsAP protocol definitions (header + C file) Change-Id: Idddfc9b851eb4c2fa7dd661a9ce1b03a04883109 --- include/Makefile.am | 1 + include/osmocom/gsm/protocol/gsm_29_118.h | 169 ++++++++++++++++++++++++++++++ src/gsm/Makefile.am | 3 +- src/gsm/gsm29118.c | 123 ++++++++++++++++++++++ src/gsm/libosmogsm.map | 9 ++ 5 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 include/osmocom/gsm/protocol/gsm_29_118.h create mode 100644 src/gsm/gsm29118.c diff --git a/include/Makefile.am b/include/Makefile.am index 19695d1b..59a5feda 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -114,6 +114,7 @@ nobase_include_HEADERS = \ osmocom/gsm/protocol/gsm_09_02.h \ osmocom/gsm/protocol/gsm_12_21.h \ osmocom/gsm/protocol/gsm_23_003.h \ + osmocom/gsm/protocol/gsm_29_118.h \ osmocom/gsm/protocol/gsm_44_318.h \ osmocom/gsm/protocol/ipaccess.h \ osmocom/gsm/protocol/smpp34_osmocom.h \ diff --git a/include/osmocom/gsm/protocol/gsm_29_118.h b/include/osmocom/gsm/protocol/gsm_29_118.h new file mode 100644 index 00000000..24e9de2e --- /dev/null +++ b/include/osmocom/gsm/protocol/gsm_29_118.h @@ -0,0 +1,169 @@ +#pragma once + + +/* TS 29.118 Section 9.2 */ +enum sgsap_msg_type { + /* unassigned */ + SGSAP_MSGT_PAGING_REQ = 0x01, + SGSAP_MSGT_PAGING_REJ = 0x02, + /* unassigned */ + SGSAP_MSGT_SERVICE_REQ = 0x06, + SGSAP_MSGT_DL_UD = 0x07, + SGSAP_MSGT_UL_UD = 0x08, + SGSAP_MSGT_LOC_UPD_REQ = 0x09, + SGSAP_MSGT_LOC_UPD_ACK = 0x0a, + SGSAP_MSGT_LOC_UPD_REJ = 0x0b, + SGSAP_MSGT_TMSI_REALL_CMPL = 0x0c, + SGSAP_MSGT_ALERT_REQ = 0x0d, + SGSAP_MSGT_ALERT_ACK = 0x0e, + SGSAP_MSGT_ALERT_REJ = 0x0f, + SGSAP_MSGT_UE_ACT_IND = 0x10, + SGSAP_MSGT_EPS_DET_IND = 0x11, + SGSAP_MSGT_EPS_DET_ACK = 0x12, + SGSAP_MSGT_IMSI_DET_IND = 0x13, + SGSAP_MSGT_IMSI_DET_ACK = 0x14, + SGSAP_MSGT_RESET_IND = 0x15, + SGSAP_MSGT_RESET_ACK = 0x16, + SGSAP_MSGT_SERVICE_ABORT_REQ = 0x17, + SGSAP_MSGT_MO_CSFB_IND = 0x18, + /* unassigned */ + SGSAP_MSGT_MM_INFO_REQ = 0x1a, + SGSAP_MSGT_RELEASE_REQ = 0x1b, + /* unassigned */ + SGSAP_MSGT_STATUS = 0x1d, + /* unassigned */ + SGSAP_MSGT_UE_UNREACHABLE = 0x1f, +}; +const struct value_string sgsap_msg_type_names[]; +static inline const char *sgsap_msg_type_name(enum sgsap_msg_type msgt) { + return get_value_string(sgsap_msg_type_names, msgt); +} + +/* TS 29.118 Section 9.3 */ +enum sgsap_iei { + SGSAP_IE_IMSI = 0x01, + SGSAP_IE_VLR_NAME = 0x02, + SGSAP_IE_TMSI = 0x03, + SGSAP_IE_LAI = 0x04, + SGSAP_IE_CHAN_NEEDED = 0x05, + SGSAP_IE_EMLPP_PRIORITY = 0x06, + SGSAP_IE_TMSI_STATUS = 0x07, + SGSAP_IE_SGS_CAUSE = 0x08, + SGSAP_IE_MME_NAME = 0x09, + SGSAP_IE_EPS_LU_TYPE = 0x0a, + SGSAP_IE_GLOBAL_CN_ID = 0x0b, + SGSAP_IE_MOBILE_ID = 0x0e, + SGSAP_IE_REJECT_CAUSE = 0x0f, + SGSAP_IE_IMSI_DET_EPS_TYPE = 0x10, + SGSAP_IE_IMSI_DET_NONEPS_TYPE = 0x11, + SGSAP_IE_IMEISV = 0x15, + SGSAP_IE_NAS_MSG_CONTAINER = 0x16, + SGSAP_IE_MM_INFO = 0x17, + SGSAP_IE_ERR_MSG = 0x1b, + SGSAP_IE_CLI = 0x1c, + SGSAP_IE_LCS_CLIENT_ID = 0x1d, + SGSAP_IE_LCS_INDICATOR = 0x1e, + SGSAP_IE_SS_CODE = 0x1f, + SGSAP_IE_SERVICE_INDICATOR = 0x20, + SGSAP_IE_UE_TIMEZONE = 0x21, + SGSAP_IE_MS_CLASSMARK2 = 0x22, + SGSAP_IE_TAI = 0x23, + SGSAP_IE_EUTRAN_CGI = 0x24, + SGSAP_IE_UE_EMM_MODE = 0x25, + SGSAP_IE_ADDL_PAGING_INDICATORS = 0x26, + SGSAP_IE_TMSI_BASED_NRI_CONT = 0x27, +}; + + +/* TS 29.118 Section 9.4.2 */ +enum sgsap_eps_lu_type { + SGSAP_EPS_LUT_IMSI_ATTACH = 0x01, + SGSAP_EPS_LUT_NORMAL = 0x02, +}; +const struct value_string sgsap_eps_lu_type_names[]; +static inline const char *sgsap_eps_lu_type_name(enum sgsap_eps_lu_type lut) { + return get_value_string(sgsap_eps_lu_type_names, lut); +} + +/* TS 29.118 Section 9.4.7 */ +enum sgsap_imsi_det_eps_type { + SGSAP_ID_EPS_T_NETWORK_INITIATED = 0x01, + SGSAP_ID_EPS_T_UE_INITIATED = 0x02, + SGSAP_ID_EPS_T_EPS_NOT_ALLOWED = 0x03, +}; +const struct value_string sgsap_ismi_det_eps_type_names[]; +static inline const char *sgsap_imsi_det_eps_type_name(enum sgsap_imsi_det_eps_type idt) { + return get_value_string(sgsap_ismi_det_eps_type_names, idt); +} + +/* TS 29.118 Section 9.4.8 */ +enum sgsap_imsi_det_noneps_type { + SGSAP_ID_NONEPS_T_EXPLICIT_UE_NONEPS = 0x01, + SGSAP_ID_NONEPS_T_COMBINED_UE_EPS_NONEPS = 0x02, + SGSAP_ID_NONEPS_T_IMPLICIT_UE_EPS_NONEPS = 0x03, +}; +const struct value_string sgsap_ismi_det_noneps_type_names[]; +static inline const char *sgsap_imsi_det_noneps_type_name(enum sgsap_imsi_det_noneps_type idt) { + return get_value_string(sgsap_ismi_det_noneps_type_names, idt); +} + +/* TS 29.118 Section 9.4.17 */ +enum sgsap_service_ind { + SGSAP_SERV_IND_CS_CALL = 0x01, + SGSAP_SERV_IND_SMS = 0x02, +}; +const struct value_string sgsap_service_ind_names[]; +static inline const char *sgsap_service_ind_name(enum sgsap_service_ind si) { + return get_value_string(sgsap_service_ind_names, si); +} + +/* TS 29.118 Section 9.4.18 */ +enum sgsap_sgs_cause { + SGSAP_SGS_CAUSE_IMSI_DET_EPS = 0x01, + SGSAP_SGS_CAUSE_IMSI_DET_EPS_NONEPS = 0x02, + SGSAP_SGS_CAUSE_IMSI_UNKNOWN = 0x03, + SGSAP_SGS_CAUSE_IMSI_DET_NON_EPS = 0x04, + SGSAP_SGS_CAUSE_IMSI_IMPL_DET_NON_EPS = 0x05, + SGSAP_SGS_CAUSE_UE_UNREACHABLE = 0x06, + SGSAP_SGS_CAUSE_MSG_INCOMP_STATE = 0x07, + SGSAP_SGS_CAUSE_MISSING_MAND_IE = 0x08, + SGSAP_SGS_CAUSE_INVALID_MAND_IE = 0x09, + SGSAP_SGS_CAUSE_COND_IE_ERROR = 0x0a, + SGSAP_SGS_CAUSE_SEMANT_INCORR_MSG = 0x0b, + SGSAP_SGS_CAUSE_MSG_UNKNOWN = 0x0c, + SGSAP_SGS_CAUSE_MT_CSFB_REJ_USER = 0x0d, + SGSAP_SGS_CAUSE_UE_TEMP_UNREACHABLE = 0x0e, +}; +const struct value_string sgsap_sgs_cause_names[]; +static inline const char *sgsap_sgs_cause_name(enum sgsap_sgs_cause cause) { + return get_value_string(sgsap_sgs_cause_names, cause); +} + +/* TS 29.118 Section 9.4.21c */ +enum sgsap_ue_emm_mode { + SGSAP_UE_EMM_MODE_IDLE = 0x00, + SGSAP_UE_EMM_MODE_CONNECTED = 0x01, +}; +const struct value_string sgsap_ue_emm_mode_names[]; +static inline const char *sgsap_ue_emm_mode_name(enum sgsap_ue_emm_mode mode) { + return get_value_string(sgsap_ue_emm_mode_names, mode); +} + +/* TS 29.118 Section 10.1 Table 10.1.2 */ +#define SGS_TS5_DEFAULT 10 /* Guards the Paging Procedure at the VLR */ +#define SGS_TS6_2_DEFAULT 40 /* Guards the TMSI reallocation procedure */ +#define SGS_TS7_DEFAULT 4 /* Guards the non-EPS alert procedure */ +#define SGS_TS11_DEFAULT 4 /* Guards the VLR reset procedure */ +#define SGS_TS14_DEFAULT 10 /* Guards the UE fallback to UTRAN/GERAN */ +#define SGS_TS15_DEFAULT 10 /* Guards the MO UE fallback to UTRAN/GERAN */ + +/* TS 29.118 Section 10.2 Table 10.2.1 */ +#define SGS_NS7_DEFAULT 2 +#define SGS_NS11_DEFAULT 2 +/* TS 29.118 Section 10.2 Table 10.2.2 */ +#define SGS_NS8_DEFAULT 2 +#define SGS_NS9_DEFAULT 2 +#define SGS_NS10_DEFAULT 2 +#define SGS_NS12_DEFAULT 2 + +const struct tlv_definition sgsap_ie_tlvdef; diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index 29299a64..e28ea335 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -30,7 +30,8 @@ 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 oap_client.c + gsm23003.c mncc.c bts_features.c oap_client.c \ + gsm29118.c libgsmint_la_LDFLAGS = -no-undefined libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la diff --git a/src/gsm/gsm29118.c b/src/gsm/gsm29118.c new file mode 100644 index 00000000..de625a90 --- /dev/null +++ b/src/gsm/gsm29118.c @@ -0,0 +1,123 @@ +#include +#include + +#include + +const struct value_string sgsap_msg_type_names[] = { + { SGSAP_MSGT_PAGING_REQ, "PAGING-REQUEST" }, + { SGSAP_MSGT_PAGING_REJ, "PAGING-REJECT" }, + { SGSAP_MSGT_SERVICE_REQ, "SERVICE-REQUEST" }, + { SGSAP_MSGT_DL_UD, "DOWNLINK-UNITDATA" }, + { SGSAP_MSGT_UL_UD, "UPLINK-UNITDATA" }, + { SGSAP_MSGT_LOC_UPD_REQ, "LOCATION-UPDATE-REQUEST" }, + { SGSAP_MSGT_LOC_UPD_ACK, "LOCATION-UPDATE-ACCEPT" }, + { SGSAP_MSGT_LOC_UPD_REJ, "LOCATION-UPDATE-REJECT" }, + { SGSAP_MSGT_TMSI_REALL_CMPL, "TMSI-REALLOCATION-COMPLETE" }, + { SGSAP_MSGT_ALERT_REQ, "ALERT-REQQUEST" }, + { SGSAP_MSGT_ALERT_ACK, "ALERT-ACK" }, + { SGSAP_MSGT_ALERT_REJ, "ALERT-REJECT" }, + { SGSAP_MSGT_UE_ACT_IND, "UE-ACTIVITY-INDICATION" }, + { SGSAP_MSGT_EPS_DET_IND, "EPS-DETACH-INDICATION" }, + { SGSAP_MSGT_EPS_DET_ACK, "EPS-DETACH-ACK" }, + { SGSAP_MSGT_IMSI_DET_IND, "IMSI-DETACH-INDICATION" }, + { SGSAP_MSGT_IMSI_DET_ACK, "IMSI-DETACH-ACK" }, + { SGSAP_MSGT_RESET_IND, "RESET-INDICATION" }, + { SGSAP_MSGT_RESET_ACK, "RESET-ACK" }, + { SGSAP_MSGT_SERVICE_ABORT_REQ, "SERVICE-ABORT-REQUEST" }, + { SGSAP_MSGT_MO_CSFB_IND, "MO-CSFB-INDICATION" }, + { SGSAP_MSGT_MM_INFO_REQ, "MM-INFO-REQUEST" }, + { SGSAP_MSGT_RELEASE_REQ, "RELEASE-REQUEST" }, + { SGSAP_MSGT_STATUS, "STATUS" }, + { SGSAP_MSGT_UE_UNREACHABLE, "UE-UNREACHABLE" }, + { 0, NULL } +}; + +const struct value_string sgsap_eps_lu_type_names[] = { + { SGSAP_EPS_LUT_IMSI_ATTACH, "IMSI Attach" }, + { SGSAP_EPS_LUT_NORMAL, "Normal" }, + { 0, NULL } +}; + +const struct value_string sgsap_ismi_det_eps_type_names[] = { + { SGSAP_ID_EPS_T_NETWORK_INITIATED, "Network initiated IMSI detach from EPS" }, + { SGSAP_ID_EPS_T_UE_INITIATED, "UE initiated IMSI detach from EPS" }, + { SGSAP_ID_EPS_T_EPS_NOT_ALLOWED, "EPS not allowed" }, + { 0, NULL } +}; + +const struct value_string sgsap_ismi_det_noneps_type_names[] = { + { SGSAP_ID_NONEPS_T_EXPLICIT_UE_NONEPS, + "Explicit UE initiated IMSI detach from non-EPS" }, + { SGSAP_ID_NONEPS_T_COMBINED_UE_EPS_NONEPS, + "Combined UE initiated IMSI detach from EPS and non-EPS" }, + { SGSAP_ID_NONEPS_T_IMPLICIT_UE_EPS_NONEPS, + "Implicit network initiated IMSI detach from EPS and non-EPS" }, + { 0, NULL } +}; + +const struct value_string sgsap_service_ind_names[] = { + { SGSAP_SERV_IND_CS_CALL, "CS Call" }, + { SGSAP_SERV_IND_SMS, "SMS" }, + { 0, NULL } +}; + +const struct value_string sgsap_sgs_cause_names[] = { + { SGSAP_SGS_CAUSE_IMSI_DET_EPS, "IMSI detached for EPS" }, + { SGSAP_SGS_CAUSE_IMSI_DET_EPS_NONEPS, "IMSI detached for EPS and non-EPS" }, + { SGSAP_SGS_CAUSE_IMSI_UNKNOWN, "IMSI unknown" }, + { SGSAP_SGS_CAUSE_IMSI_DET_NON_EPS, "IMSI detached for non-EPS" }, + { SGSAP_SGS_CAUSE_IMSI_IMPL_DET_NON_EPS,"IMSI implicitly detached for non-EPS" }, + { SGSAP_SGS_CAUSE_UE_UNREACHABLE, "UE unreachable" }, + { SGSAP_SGS_CAUSE_MSG_INCOMP_STATE, "Message not compatible with protocol state" }, + { SGSAP_SGS_CAUSE_MISSING_MAND_IE, "Missing mandatory IE" }, + { SGSAP_SGS_CAUSE_INVALID_MAND_IE, "Invalid mandatory IE" }, + { SGSAP_SGS_CAUSE_COND_IE_ERROR, "Conditional IE error" }, + { SGSAP_SGS_CAUSE_SEMANT_INCORR_MSG, "Semantically incorrect message" }, + { SGSAP_SGS_CAUSE_MSG_UNKNOWN, "Message unknown" }, + { SGSAP_SGS_CAUSE_MT_CSFB_REJ_USER, "MT CSFB call rejected by user" }, + { SGSAP_SGS_CAUSE_UE_TEMP_UNREACHABLE, "UE temporarily unreachable" }, + { 0, NULL } +}; + + +const struct value_string sgsap_ue_emm_mode_names[] = { + { SGSAP_UE_EMM_MODE_IDLE, "EMM-IDLE" }, + { SGSAP_UE_EMM_MODE_CONNECTED, "EMM-CONNECTED" }, + { 0, NULL } +}; + +const struct tlv_definition sgsap_ie_tlvdef = { + .def = { + [SGSAP_IE_IMSI] = { TLV_TYPE_TLV }, + [SGSAP_IE_VLR_NAME] = { TLV_TYPE_TLV }, + [SGSAP_IE_TMSI] = { TLV_TYPE_TLV }, + [SGSAP_IE_LAI] = { TLV_TYPE_TLV }, + [SGSAP_IE_CHAN_NEEDED] = { TLV_TYPE_TLV }, + [SGSAP_IE_EMLPP_PRIORITY] = { TLV_TYPE_TLV }, + [SGSAP_IE_TMSI_STATUS] = { TLV_TYPE_TLV }, + [SGSAP_IE_SGS_CAUSE] = { TLV_TYPE_TLV }, + [SGSAP_IE_MME_NAME] = { TLV_TYPE_TLV }, + [SGSAP_IE_EPS_LU_TYPE] = { TLV_TYPE_TLV }, + [SGSAP_IE_GLOBAL_CN_ID] = { TLV_TYPE_TLV }, + [SGSAP_IE_MOBILE_ID] = { TLV_TYPE_TLV }, + [SGSAP_IE_REJECT_CAUSE] = { TLV_TYPE_TLV }, + [SGSAP_IE_IMSI_DET_EPS_TYPE] = { TLV_TYPE_TLV }, + [SGSAP_IE_IMSI_DET_NONEPS_TYPE] = { TLV_TYPE_TLV }, + [SGSAP_IE_IMEISV] = { TLV_TYPE_TLV }, + [SGSAP_IE_NAS_MSG_CONTAINER] = { TLV_TYPE_TLV }, + [SGSAP_IE_MM_INFO] = { TLV_TYPE_TLV }, + [SGSAP_IE_ERR_MSG] = { TLV_TYPE_TLV }, + [SGSAP_IE_CLI] = { TLV_TYPE_TLV }, + [SGSAP_IE_LCS_CLIENT_ID] = { TLV_TYPE_TLV }, + [SGSAP_IE_LCS_INDICATOR] = { TLV_TYPE_TLV }, + [SGSAP_IE_SS_CODE] = { TLV_TYPE_TLV }, + [SGSAP_IE_SERVICE_INDICATOR] = { TLV_TYPE_TLV }, + [SGSAP_IE_UE_TIMEZONE] = { TLV_TYPE_TLV }, + [SGSAP_IE_MS_CLASSMARK2] = { TLV_TYPE_TLV }, + [SGSAP_IE_TAI] = { TLV_TYPE_TLV }, + [SGSAP_IE_EUTRAN_CGI] = { TLV_TYPE_TLV }, + [SGSAP_IE_UE_EMM_MODE] = { TLV_TYPE_TLV }, + [SGSAP_IE_ADDL_PAGING_INDICATORS]={ TLV_TYPE_TLV }, + [SGSAP_IE_TMSI_BASED_NRI_CONT] = { TLV_TYPE_TLV }, + }, +}; diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index dcc491d7..3cc2ec5f 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -505,5 +505,14 @@ osmo_oap_client_handle; osmo_oap_client_init; osmo_oap_client_register; +sgsap_msg_type_names; +sgsap_eps_lu_type_names; +sgsap_ismi_det_eps_type_names; +sgsap_ismi_det_noneps_type_names; +sgsap_service_ind_names; +sgsap_sgs_cause_names; +sgsap_ue_emm_mode_names; +sgsap_ie_tlvdef; + local: *; }; -- cgit v1.2.3 From ee86b0488332b7d863cfbe64298d86895d11ea05 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 25 Sep 2018 18:09:01 +0700 Subject: libosmogsm/gsup.c: fix error code in osmo_gsup_encode() Missing (unset) type of to be encoded message is not a memory allocation failure (-ENOMEM), this is definitely a mistake. Change-Id: Ibbac18e2b68b765c17c2bc959c4c085037953a7f --- src/gsm/gsup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gsm/gsup.c b/src/gsm/gsup.c index 9c2f8175..18b35806 100644 --- a/src/gsm/gsup.c +++ b/src/gsm/gsup.c @@ -535,7 +535,7 @@ int osmo_gsup_encode(struct msgb *msg, const struct osmo_gsup_message *gsup_msg) /* generic part */ if(!gsup_msg->message_type) - return -ENOMEM; + return -EINVAL; msgb_v_put(msg, gsup_msg->message_type); -- cgit v1.2.3 From 7a2ec6e118275da360efb3d36cdac730b6bcb437 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 24 Oct 2018 11:29:31 +0200 Subject: vty: adjust telnet log Adjust wording so telnet command can be directly copy-pasted from the log to access the interface without the need for further editing. Change-Id: I1876447f9285adcd1b09937a6121afabd0b32e52 --- src/vty/telnet_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vty/telnet_interface.c b/src/vty/telnet_interface.c index fdd88c1f..fcb4c8db 100644 --- a/src/vty/telnet_interface.c +++ b/src/vty/telnet_interface.c @@ -101,7 +101,7 @@ int telnet_init_dynif(void *tall_ctx, void *priv, const char *ip, int port) return -1; } - LOGP(DLGLOBAL, LOGL_NOTICE, "telnet at %s %d\n", ip, port); + LOGP(DLGLOBAL, LOGL_NOTICE, "Available via telnet %s %d\n", ip, port); return 0; } -- cgit v1.2.3 From 0c878fd4f5b5029704b57fee63ecf8f07c8fdedf Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 11 Oct 2018 17:55:28 +0200 Subject: stats_statsd: Send all stat_items as gauges When sending a statsd metric we need to specify a type which can be a "g"auge, "c"ounter, "t"imer, "h"istogram, and "m"eter. We used to just pass the stat_item unit into this field, but that is the unit of the metric (Seconds for a timer, % for utilization, ...). Change the type field so stat_items are sent as "g"auges. Note that negative values don't seem to be supported by statsd. Change-Id: Ia16270d36c9a14521594de4b99a48c83e4ac07d4 --- src/stats_statsd.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/stats_statsd.c b/src/stats_statsd.c index 5ae25702..c3f739e2 100644 --- a/src/stats_statsd.c +++ b/src/stats_statsd.c @@ -184,20 +184,17 @@ static int osmo_stats_reporter_statsd_send_item(struct osmo_stats_reporter *srep const struct osmo_stat_item_group *statg, const struct osmo_stat_item_desc *desc, int64_t value) { - const char *unit = desc->unit; - - if (unit == OSMO_STAT_ITEM_NO_UNIT) { - unit = "g"; - if (value < 0) - osmo_stats_reporter_statsd_send(srep, + if (value < 0) { + return osmo_stats_reporter_statsd_send(srep, statg->desc->group_name_prefix, statg->idx, - desc->name, 0, unit); + desc->name, 0, "g"); + } else { + return osmo_stats_reporter_statsd_send(srep, + statg->desc->group_name_prefix, + statg->idx, + desc->name, value, "g"); } - return osmo_stats_reporter_statsd_send(srep, - statg->desc->group_name_prefix, - statg->idx, - desc->name, value, unit); } #endif /* !EMBEDDED */ -- cgit v1.2.3 From e74f49d973da4d6dce741deee0d249e5848d06ce Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Thu, 25 Oct 2018 11:49:21 +0200 Subject: cosmetic: fix typo (soocket -> socket) Change-Id: I2184bf12398902d933f3744bc094418cc6961e86 --- src/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/socket.c b/src/socket.c index a85edb73..bb5505f9 100644 --- a/src/socket.c +++ b/src/socket.c @@ -682,7 +682,7 @@ int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto, return osmo_fd_init_ofd(ofd, osmo_sock_unix_init(type, proto, socket_path, flags)); } -/*! Get address/port information on soocket in dyn-alloc string +/*! Get address/port information on socket in dyn-alloc string * \param[in] ctx talloc context from which to allocate string buffer * \param[in] fd file descriptor of socket * \returns string identifying the connection of this socket -- cgit v1.2.3 From 7acd5d039491a14a05b6aa08890d28590dde8b96 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Thu, 25 Oct 2018 11:16:36 +0200 Subject: add osmo_sock_get_{local,remote}_ip{,_port}() Return only the IP or port of either the local or remote connection, not the whole set of IP and port of both the local and remote connection like osmo_sock_get_name() does it. This is needed for OS#2841, where we only want to print the remote IP. Related: OS#2841 Change-Id: I6803c204771c59a2002bc6a0e6b79c83c35f87e1 --- include/osmocom/core/socket.h | 6 +++ src/socket.c | 111 ++++++++++++++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 25 deletions(-) diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index f23a2436..28f89a50 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -9,6 +9,7 @@ #include #include +#include struct sockaddr; struct osmo_fd; @@ -56,6 +57,11 @@ int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto, const char *socket_path, unsigned int flags); char *osmo_sock_get_name(void *ctx, int fd); +int osmo_sock_get_local_ip(int fd, char *host, size_t len); +int osmo_sock_get_local_ip_port(int fd, char *port, size_t len); +int osmo_sock_get_remote_ip(int fd, char *host, size_t len); +int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len); + int osmo_sock_mcast_loop_set(int fd, bool enable); int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl); diff --git a/src/socket.c b/src/socket.c index bb5505f9..c7e1c9dd 100644 --- a/src/socket.c +++ b/src/socket.c @@ -682,44 +682,105 @@ int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto, return osmo_fd_init_ofd(ofd, osmo_sock_unix_init(type, proto, socket_path, flags)); } -/*! Get address/port information on socket in dyn-alloc string - * \param[in] ctx talloc context from which to allocate string buffer +/*! Get the IP and/or port number on socket. This is for internal usage. + * Convenience wrappers: osmo_sock_get_local_ip(), + * osmo_sock_get_local_ip_port(), osmo_sock_get_remote_ip(), + * osmo_sock_get_remote_ip_port() and osmo_sock_get_name() * \param[in] fd file descriptor of socket - * \returns string identifying the connection of this socket + * \param[out] ip IP address (will be filled in when not NULL) + * \param[in] ip_len length of the ip buffer + * \param[out] port number (will be filled in when not NULL) + * \param[in] port_len length of the port buffer + * \param[in] local (true) or remote (false) name will get looked at + * \returns 0 on success; negative otherwise */ -char *osmo_sock_get_name(void *ctx, int fd) +static int osmo_sock_get_name2(int fd, char *ip, size_t ip_len, char *port, size_t port_len, bool local) { - struct sockaddr sa_l, sa_r; - socklen_t sa_len_l = sizeof(sa_l); - socklen_t sa_len_r = sizeof(sa_r); - char hostbuf_l[64], hostbuf_r[64]; - char portbuf_l[16], portbuf_r[16]; + struct sockaddr sa; + socklen_t len = sizeof(sa); + char ipbuf[64], portbuf[16]; int rc; - rc = getsockname(fd, &sa_l, &sa_len_l); + rc = local ? getsockname(fd, &sa, &len) : getpeername(fd, &sa, &len); if (rc < 0) - return NULL; + return rc; - rc = getnameinfo(&sa_l, sa_len_l, hostbuf_l, sizeof(hostbuf_l), - portbuf_l, sizeof(portbuf_l), + rc = getnameinfo(&sa, len, ipbuf, sizeof(ipbuf), + portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (rc < 0) - return NULL; + return rc; - rc = getpeername(fd, &sa_r, &sa_len_r); - if (rc < 0) - goto local_only; + if (ip) + strncpy(ip, ipbuf, ip_len); + if (port) + strncpy(port, portbuf, port_len); + return 0; +} - rc = getnameinfo(&sa_r, sa_len_r, hostbuf_r, sizeof(hostbuf_r), - portbuf_r, sizeof(portbuf_r), - NI_NUMERICHOST | NI_NUMERICSERV); - if (rc < 0) - goto local_only; +/*! Get local IP address on socket + * \param[in] fd file descriptor of socket + * \param[out] ip IP address (will be filled in) + * \param[in] len length of the output buffer + * \returns 0 on success; negative otherwise + */ +int osmo_sock_get_local_ip(int fd, char *ip, size_t len) +{ + return osmo_sock_get_name2(fd, ip, len, NULL, 0, true); +} + +/*! Get local port on socket + * \param[in] fd file descriptor of socket + * \param[out] port number (will be filled in) + * \param[in] len length of the output buffer + * \returns 0 on success; negative otherwise + */ +int osmo_sock_get_local_ip_port(int fd, char *port, size_t len) +{ + return osmo_sock_get_name2(fd, NULL, 0, port, len, true); +} + +/*! Get remote IP address on socket + * \param[in] fd file descriptor of socket + * \param[out] ip IP address (will be filled in) + * \param[in] len length of the output buffer + * \returns 0 on success; negative otherwise + */ +int osmo_sock_get_remote_ip(int fd, char *ip, size_t len) +{ + return osmo_sock_get_name2(fd, ip, len, NULL, 0, false); +} + +/*! Get remote port on socket + * \param[in] fd file descriptor of socket + * \param[out] port number (will be filled in) + * \param[in] len length of the output buffer + * \returns 0 on success; negative otherwise + */ +int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len) +{ + return osmo_sock_get_name2(fd, NULL, 0, port, len, false); +} + +/*! Get address/port information on socket in dyn-alloc string + * \param[in] ctx talloc context from which to allocate string buffer + * \param[in] fd file descriptor of socket + * \returns string identifying the connection of this socket + */ +char *osmo_sock_get_name(void *ctx, int fd) +{ + char hostbuf_l[64], hostbuf_r[64]; + char portbuf_l[16], portbuf_r[16]; + + /* get local */ + if (osmo_sock_get_name2(fd, hostbuf_l, sizeof(hostbuf_l), portbuf_l, sizeof(portbuf_l), true)) + return NULL; - return talloc_asprintf(ctx, "(r=%s:%s<->l=%s:%s)", hostbuf_r, portbuf_r, - hostbuf_l, portbuf_l); + /* get remote */ + if (!osmo_sock_get_name2(fd, hostbuf_r, sizeof(hostbuf_r), portbuf_r, sizeof(portbuf_r), false)) + return talloc_asprintf(ctx, "(r=%s:%s<->l=%s:%s)", hostbuf_r, portbuf_r, hostbuf_l, portbuf_l); -local_only: + /* local only: different format */ return talloc_asprintf(ctx, "(r=NULL<->l=%s:%s)", hostbuf_l, portbuf_l); } -- cgit v1.2.3 From de1da35d51555648b331a7fd619ad02a1630987a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 8 Oct 2018 22:27:04 +0200 Subject: gsm23003: Add MME domain name related helper functions osmo_gen_mme_group_domain(), osmo_gen_mme_group_domain() and osmo_gen_home_network_domain() Change-Id: Ia882d9db05ec0037e593aeebea21bc31adb680bb --- include/osmocom/gsm/gsm23003.h | 7 +++ include/osmocom/gsm/protocol/gsm_23_003.h | 6 +++ src/gsm/gsm23003.c | 86 +++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 6 +++ tests/gsm23003/gsm23003_test.c | 75 +++++++++++++++++++++++++++ tests/gsm23003/gsm23003_test.ok | 5 ++ 6 files changed, 185 insertions(+) diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index fd4f3694..2f380aec 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -101,6 +101,7 @@ const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn); const char *osmo_lai_name(const struct osmo_location_area_id *lai); const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi); const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi); +const char *osmo_gummei_name(const struct osmo_gummei *gummei); void osmo_plmn_to_bcd(uint8_t *bcd_dst, const struct osmo_plmn_id *plmn); void osmo_plmn_from_bcd(const uint8_t *bcd_src, struct osmo_plmn_id *plmn); @@ -120,3 +121,9 @@ static inline int osmo_mcc_from_str(const char *mcc_str, uint16_t *mcc) int osmo_mnc_cmp(uint16_t a_mnc, bool a_mnc_3_digits, uint16_t b_mnc, bool b_mnc_3_digits); int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b); + +int osmo_gen_home_network_domain(char *out, const struct osmo_plmn_id *plmn); +int osmo_parse_home_network_domain(struct osmo_plmn_id *out, const char *in); +int osmo_gen_mme_domain(char *out, const struct osmo_gummei *gummei); +int osmo_gen_mme_group_domain(char *out, uint16_t mmegi, const struct osmo_plmn_id *plmn); +int osmo_parse_mme_domain(struct osmo_gummei *out, const char *in); diff --git a/include/osmocom/gsm/protocol/gsm_23_003.h b/include/osmocom/gsm/protocol/gsm_23_003.h index 0e669399..ee697ff4 100644 --- a/include/osmocom/gsm/protocol/gsm_23_003.h +++ b/include/osmocom/gsm/protocol/gsm_23_003.h @@ -24,3 +24,9 @@ GSM23003_IMEI_SNR_NUM_DIGITS + 1) #define GSM23003_IMEISV_NUM_DIGITS (GSM23003_IMEI_TAC_NUM_DIGITS + \ GSM23003_IMEI_SNR_NUM_DIGITS + 2) + +/* Chapter 19.2 "epc.mnc000.mcc000.3gppnetwork.org" */ +#define GSM23003_HOME_NETWORK_DOMAIN_LEN 33 + +/* Chapter 19.4.2.4: "mmec00.mmegi0000.mme.epc.mnc000.mcc000.3gppnetwork.org" */ +#define GSM23003_MME_DOMAIN_LEN 55 diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c index 2c3b21e6..4fdad48a 100644 --- a/src/gsm/gsm23003.c +++ b/src/gsm/gsm23003.c @@ -169,6 +169,14 @@ static void to_bcd(uint8_t *bcd, uint16_t val) bcd[0] = val % 10; } +const char *osmo_gummei_name(const struct osmo_gummei *gummei) +{ + static char buf[32]; + snprintf(buf, sizeof(buf), "%s-%04x-%02x", osmo_plmn_name(&gummei->plmn), + gummei->mme.group_id, gummei->mme.code); + return buf; +} + /* Convert MCC + MNC to BCD representation * \param[out] bcd_dst caller-allocated memory for output * \param[in] mcc Mobile Country Code @@ -297,3 +305,81 @@ int osmo_plmn_cmp(const struct osmo_plmn_id *a, const struct osmo_plmn_id *b) return 1; return osmo_mnc_cmp(a->mnc, a->mnc_3_digits, b->mnc, b->mnc_3_digits); } + +/*! Generate TS 23.003 Section 19.2 Home Network Realm/Domain (text form) + * \param out[out] caller-provided output buffer, at least 33 bytes long + * \param plmn[in] Osmocom representation of PLMN ID (MCC + MNC) + * \returns number of characters printed (excluding NUL); negative on error */ +int osmo_gen_home_network_domain(char *out, const struct osmo_plmn_id *plmn) +{ + if (plmn->mcc > 999) + return -EINVAL; + if (plmn->mnc > 999) + return -EINVAL; + return sprintf(out, "epc.mnc%03u.mcc%03u.3gppnetwork.org", plmn->mnc, plmn->mcc); +} + +/*! Parse a TS 23.003 Section 19.2 Home Network Realm/Domain (text form) into a \ref osmo_plmn_id + * \param out[out] caller-allocated output structure + * \param in[in] character string representation to be parsed + * \returns 0 on success; negative on error */ +int osmo_parse_home_network_domain(struct osmo_plmn_id *out, const char *in) +{ + int rc; + + memset(out, 0, sizeof(*out)); + rc = sscanf(in, "epc.mnc%03hu.mcc%03hu.3gppnetwork.org", &out->mnc, &out->mcc); + if (rc < 0) + return rc; + if (rc != 2) + return -EINVAL; + return 0; +} + +/*! Generate TS 23.003 Section 19.4.2.4 MME Domain (text form) + * \param out[out] caller-provided output buffer, at least 56 bytes long + * \param gummei[in] Structure representing the Globally Unique MME Identifier + * \returns number of characters printed (excluding NUL); negative on error */ +int osmo_gen_mme_domain(char *out, const struct osmo_gummei *gummei) +{ + char domain[GSM23003_HOME_NETWORK_DOMAIN_LEN+1]; + int rc; + rc = osmo_gen_home_network_domain(domain, &gummei->plmn); + if (rc < 0) + return rc; + return sprintf(out, "mmec%02x.mmegi%04x.mme.%s", gummei->mme.code, gummei->mme.group_id, domain); +} + +/*! Parse a TS 23.003 Section 19.4.2.4 MME Domain (text form) into a \ref osmo_gummei + * \param out[out] caller-allocated output GUMMEI structure + * \param in[in] character string representation to be parsed + * \returns 0 on success; negative on error */ +int osmo_parse_mme_domain(struct osmo_gummei *out, const char *in) +{ + int rc; + + memset(out, 0, sizeof(*out)); + rc = sscanf(in, "mmec%02hhx.mmegi%04hx.mme.epc.mnc%03hu.mcc%03hu.3gppnetwork.org", + &out->mme.code, &out->mme.group_id, + &out->plmn.mnc, &out->plmn.mcc); + if (rc < 0) + return rc; + if (rc != 4) + return -EINVAL; + return 0; +} + +/*! Generate TS 23.003 Section 19.4.2.4 MME Group Domain (text form) + * \param out[out] caller-provided output buffer, at least 56 bytes long + * \param mmegi[in] MME Group Identifier + * \param plmn[in] Osmocom representation of PLMN ID (MCC + MNC) + * \returns number of characters printed (excluding NUL); negative on error */ +int osmo_gen_mme_group_domain(char *out, uint16_t mmegi, const struct osmo_plmn_id *plmn) +{ + char domain[GSM23003_HOME_NETWORK_DOMAIN_LEN+1]; + int rc; + rc = osmo_gen_home_network_domain(domain, plmn); + if (rc < 0) + return rc; + return sprintf(out, "mmegi%04x.mme.%s", mmegi, domain); +} diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3cc2ec5f..4813e135 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -315,9 +315,15 @@ osmo_lai_name; osmo_rai_name; osmo_cgi_name; osmo_cgi_name2; +osmo_gummei_name; osmo_mnc_from_str; osmo_mnc_cmp; osmo_plmn_cmp; +osmo_gen_home_network_domain; +osmo_parse_home_network_domain; +osmo_gen_mme_domain; +osmo_parse_mme_domain; +osmo_gen_mme_group_domain; gsm48_chan_mode_names; gsm_chan_t_names; gsm48_pdisc_names; diff --git a/tests/gsm23003/gsm23003_test.c b/tests/gsm23003/gsm23003_test.c index 947aa18d..79965cfb 100644 --- a/tests/gsm23003/gsm23003_test.c +++ b/tests/gsm23003/gsm23003_test.c @@ -24,8 +24,10 @@ #include #include #include +#include #include +#include #include #define BOOL_STR(b) ((b)? "true" : "false") @@ -170,6 +172,76 @@ static bool test_mnc_from_str() return pass; } +static bool test_gummei_name() +{ + static const struct osmo_gummei gummei = { + .plmn = { .mcc = 901, .mnc = 70 }, + .mme = { .group_id = 0xA123, .code = 0xB1 } + }; + const char *out; + bool pass = true; + + out = osmo_gummei_name(&gummei); + printf("%s\n", out); + if (strcmp(out, "901-70-a123-b1")) + pass = false; + + return pass; +} + +static bool test_domain_gen() +{ + static const struct osmo_gummei gummei = { + .plmn = { .mcc = 901, .mnc = 70 }, + .mme = { .group_id = 0xA123, .code = 0xB1 } + }; + char out[GSM23003_MME_DOMAIN_LEN]; + bool pass = true; + int rc; + + rc = osmo_gen_home_network_domain(out, &gummei.plmn); + if (rc < 0) + pass = false; + printf("%s -> %s\n", osmo_plmn_name(&gummei.plmn), out); + if (strcmp(out, "epc.mnc070.mcc901.3gppnetwork.org")) + pass = false; + + rc = osmo_gen_mme_domain(out, &gummei); + printf("%s -> %s\n", osmo_gummei_name(&gummei), out); + if (strcmp(out, "mmecb1.mmegia123.mme.epc.mnc070.mcc901.3gppnetwork.org")) + pass = false; + + return pass; +} + + +static bool test_domain_parse() +{ + static const char *mme_dom_valid = "mmec01.mmegiA001.mme.epc.mnc070.mcc901.3gppnetwork.org"; + static const char *home_dom_valid = "epc.mnc070.mcc901.3gppnetwork.org"; + struct osmo_gummei gummei; + struct osmo_plmn_id plmn; + bool pass = true; + int rc; + + rc = osmo_parse_home_network_domain(&plmn, home_dom_valid); + if (rc < 0) + pass = false; + printf("%s -> %s\n", home_dom_valid, osmo_plmn_name(&plmn)); + if (plmn.mcc != 901 || plmn.mnc != 70) + pass = false; + + rc = osmo_parse_mme_domain(&gummei, mme_dom_valid); + if (rc < 0) + pass = false; + printf("%s -> %s\n", mme_dom_valid, osmo_gummei_name(&gummei)); + if (gummei.plmn.mcc != 901 || gummei.plmn.mnc != 70 || + gummei.mme.group_id != 0xA001 || gummei.mme.code != 1) + pass = false; + + return pass; +} + int main(int argc, char **argv) { bool pass = true; @@ -177,6 +249,9 @@ int main(int argc, char **argv) pass = pass && test_valid_imsi(); pass = pass && test_valid_msisdn(); pass = pass && test_mnc_from_str(); + pass = pass && test_gummei_name(); + pass = pass && test_domain_gen(); + pass = pass && test_domain_parse(); OSMO_ASSERT(pass); diff --git a/tests/gsm23003/gsm23003_test.ok b/tests/gsm23003/gsm23003_test.ok index b435f450..c64f515c 100644 --- a/tests/gsm23003/gsm23003_test.ok +++ b/tests/gsm23003/gsm23003_test.ok @@ -59,3 +59,8 @@ 13: " 023" rc=-22 mnc=0 mnc_3_digits=0 pass 14: "023 " rc=-22 mnc=0 mnc_3_digits=0 pass 15: "023 " rc=-22 mnc=0 mnc_3_digits=0 pass +901-70-a123-b1 +901-70 -> epc.mnc070.mcc901.3gppnetwork.org +901-70-a123-b1 -> mmecb1.mmegia123.mme.epc.mnc070.mcc901.3gppnetwork.org +epc.mnc070.mcc901.3gppnetwork.org -> 901-70 +mmec01.mmegiA001.mme.epc.mnc070.mcc901.3gppnetwork.org -> 901-70-a001-01 -- cgit v1.2.3 From 7c75ffb563cbfba352330003ba5de20c586b14b8 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Fri, 26 Oct 2018 15:14:19 +0200 Subject: stop printing group description in vty_out_rate_ctr_group_fmt() When vty_out_rate_ctr_group_fmt() prints the description of a counter group, it assumes this description should appear at the beginning of a line. However, the caller might be printing counters in an indented context. So just let the caller worry about printing the group title if necessary (there is currently only one known caller, which is updated in this commit). Note that printing of the group title was an undocumented feature. Change-Id: I2c55cb54e8b7a7c8c6cf72f22287083767ed0201 Related: OS#2660 --- src/vty/stats_vty.c | 1 + src/vty/utils.c | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/vty/stats_vty.c b/src/vty/stats_vty.c index 5ded7a44..62153f3c 100644 --- a/src/vty/stats_vty.c +++ b/src/vty/stats_vty.c @@ -533,6 +533,7 @@ DEFUN(show_stats_asciidoc_table, static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_) { struct vty *vty = sctx_; + vty_out(vty, "%s:%s", ctrg->desc->group_description, VTY_NEWLINE); vty_out_rate_ctr_group_fmt(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg); return 0; } diff --git a/src/vty/utils.c b/src/vty/utils.c index 0d663c6e..0358d9bd 100644 --- a/src/vty/utils.c +++ b/src/vty/utils.c @@ -214,9 +214,6 @@ void vty_out_rate_ctr_group_fmt(struct vty *vty, const char *fmt, struct rate_ctr_group *ctrg) { struct vty_out_context vctx = {vty, fmt}; - - vty_out(vty, "%s:%s", ctrg->desc->group_description, VTY_NEWLINE); - rate_ctr_for_each_counter(ctrg, rate_ctr_handler_fmt, &vctx); } -- cgit v1.2.3 From 84eb1ab1535237865cba646feef154e7919bc784 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Mon, 29 Oct 2018 17:50:30 +0100 Subject: make 'show rate-counters' show group index Show each rate counter group's index in the output of the 'show rate-counters' command, to provide some way of telling apart distinct instances of the same rate counter group. This is not a very user-friendly UI because these indices are generated internally by libosmocore and/or applications, so users cannot easily assign meaning to these indices. However, the current rate counter implementation doesn't allow for more. Change-Id: Ieb151239407e4b2f8859fefec8d0670f5ddf908a Related: OS#3674 --- src/vty/stats_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vty/stats_vty.c b/src/vty/stats_vty.c index 62153f3c..c9110879 100644 --- a/src/vty/stats_vty.c +++ b/src/vty/stats_vty.c @@ -533,7 +533,7 @@ DEFUN(show_stats_asciidoc_table, static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_) { struct vty *vty = sctx_; - vty_out(vty, "%s:%s", ctrg->desc->group_description, VTY_NEWLINE); + vty_out(vty, "%s %u:%s", ctrg->desc->group_description, ctrg->idx, VTY_NEWLINE); vty_out_rate_ctr_group_fmt(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg); return 0; } -- cgit v1.2.3 From b254daf64f110ad6912a1303b3724cde3e3dfe47 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 30 Oct 2018 09:33:47 +0100 Subject: gsm0808: fix doxygen apidoc The api documentation names a parametery by a different name than it is listed in the parameter list of the function. Lets make the apidoc coherent. Change-Id: Id21ed1e920fb64522a734f206efbe2871ec05b06 --- src/gsm/gsm0808.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 9a9f70ee..ad900083 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -265,7 +265,7 @@ struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id) } /*! Create BSSMAP Cipher Mode Reject message - * \param[in] reason TS 08.08 cause value + * \param[in] cause TS 08.08 cause value * \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */ struct msgb *gsm0808_create_cipher_reject(uint8_t cause) { -- cgit v1.2.3 From 1a146c89e2a27dee11326593697790823141488e Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 30 Oct 2018 09:36:49 +0100 Subject: gsm0808: cosmetic: rename parameter "reason" to "cause" The function that generates the clear command takes a parameter "reason", which is the cause code. Lets give it the name "cause" to have a coherent naming scheme that matches the other functions and the 3gpp specs. Change-Id: I7b6c15e8fa8db13deef5041095944ca1c58fb99f --- include/osmocom/gsm/gsm0808.h | 2 +- src/gsm/gsm0808.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index f4fc7c4c..cdbb2734 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -45,7 +45,7 @@ struct msgb *gsm0808_create_layer3_2(const struct msgb *msg_l3, const struct osm const struct gsm0808_speech_codec_list *scl); struct msgb *gsm0808_create_reset(void); struct msgb *gsm0808_create_reset_ack(void); -struct msgb *gsm0808_create_clear_command(uint8_t reason); +struct msgb *gsm0808_create_clear_command(uint8_t cause); struct msgb *gsm0808_create_clear_complete(void); struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei, const uint8_t *cipher_response_mode); diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index ad900083..9ccca4d6 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -182,9 +182,9 @@ struct msgb *gsm0808_create_clear_complete(void) } /*! Create BSSMAP Clear Command message - * \param[in] reason TS 08.08 cause value + * \param[in] cause TS 08.08 cause value * \returns callee-allocated msgb with BSSMAP Clear Command message */ -struct msgb *gsm0808_create_clear_command(uint8_t reason) +struct msgb *gsm0808_create_clear_command(uint8_t cause) { struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, "bssmap: clear command"); @@ -193,7 +193,7 @@ struct msgb *gsm0808_create_clear_command(uint8_t reason) msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4); msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD); - msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &reason); + msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); return msg; } -- cgit v1.2.3 From 2b4a67a412ace101f2e3fe893f8b2724c6fd5062 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 2 Nov 2018 16:12:03 +0100 Subject: Update cipher reject function * add note about (yet) unsupported standard feature * use enum constant instead of hex value Change-Id: I5cc5fc1ae8d5474dbc8d3385a493adf6420a3c98 Related: OS#3187 --- src/gsm/gsm0808.c | 1 + tests/gsm0808/gsm0808_test.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 9ccca4d6..e5c3e30a 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -275,6 +275,7 @@ struct msgb *gsm0808_create_cipher_reject(uint8_t cause) return NULL; msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); + /* FIXME: support 2-byte cause value as per 3GPP TS 08.08 §3.2.2.5 */ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 0b2794f1..7111db9b 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -248,7 +248,7 @@ static void test_create_cipher_reject() struct msgb *msg; printf("Testing creating Cipher Reject\n"); - msg = gsm0808_create_cipher_reject(0x23); + msg = gsm0808_create_cipher_reject(GSM0808_CAUSE_CCCH_OVERLOAD); VERIFY(msg, res, ARRAY_SIZE(res)); msgb_free(msg); } -- cgit v1.2.3 From a75e349b289be089ef3871b8299104eedfdfdfa6 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Fri, 2 Nov 2018 11:46:42 +0100 Subject: gsm48: correct apidoc for gsm48_generate_mid() The API documentation lacks the the description for the last parameter, lets add a description for it. Change-Id: Ibcd25d3a7ddd7075eb15daff6dba42236d14d945 --- src/gsm/gsm48.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index fc3b9734..ae9a1cf6 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -604,6 +604,7 @@ int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi) /*! Generate TS 24.008 §10.5.1.4 Mobile ID * \param[out] buf Caller-provided output buffer * \param[in] id Identity to be encoded + * \param[in] mi_type Type of identity (e.g. GSM_MI_TYPE_TMSI) * \returns number of bytes used in \a buf */ uint8_t gsm48_generate_mid(uint8_t *buf, const char *id, uint8_t mi_type) { -- cgit v1.2.3 From 5a7b465b09a5446dba32961801cd392ca6617e7b Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Tue, 6 Nov 2018 18:24:49 +0700 Subject: gsm/gsup.h: cosmetic: use tab for comment alignment Change-Id: Id71d4b45e2b9f42da5e23e709ad97d4d0abfc3d9 --- include/osmocom/gsm/gsup.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/gsm/gsup.h b/include/osmocom/gsm/gsup.h index 0ef5a759..cd6fd31f 100644 --- a/include/osmocom/gsm/gsup.h +++ b/include/osmocom/gsm/gsup.h @@ -207,7 +207,7 @@ struct osmo_gsup_message { /*! Session state \ref osmo_gsup_session_state */ enum osmo_gsup_session_state session_state; /*! Unique session identifier and origination flag. - * Encoded only when \ref session_state != 0x00 */ + * Encoded only when \ref session_state != 0x00 */ uint32_t session_id; /*! ASN.1 encoded MAP payload for Supplementary Services */ -- cgit v1.2.3 From fa3b48227796e66d9dd05a53ff4b3062b2c19b46 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 5 Nov 2018 14:59:54 +0100 Subject: Fix deprecation warning in gsm0808_test Use gsm0808_create_layer3_2() directly instead of deprecated wrapper. Change-Id: I44772666c929dfd94d25953379cf51b371ce202c --- tests/gsm0808/gsm0808_test.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 7111db9b..671b8399 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -102,7 +102,16 @@ static void test_create_layer3_aoip() 0xef, 0xcd, GSM0808_SCT_FR2 | 0xa0, 0x9f, GSM0808_SCT_CSD | 0x90, 0xc0 }; - + struct osmo_cell_global_id cgi = { + .lai = { + .plmn = { + .mcc = 0x2244, + .mnc = 0x1122, + }, + .lac = 0x3366, + }, + .cell_identity = 0x4488, + }; struct msgb *msg, *in_msg; struct gsm0808_speech_codec_list sc_list; printf("Testing creating Layer3 (AoIP)\n"); @@ -113,9 +122,8 @@ static void test_create_layer3_aoip() in_msg->l3h = in_msg->data; msgb_v_put(in_msg, 0x23); - msg = - gsm0808_create_layer3_aoip(in_msg, 0x1122, 0x2244, 0x3366, 0x4488, - &sc_list); + msg = gsm0808_create_layer3_2(in_msg, &cgi, &sc_list); + VERIFY(msg, res, ARRAY_SIZE(res)); msgb_free(msg); -- cgit v1.2.3 From e521edefdaa69d1b78b3d4318e046bb8457123b0 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 7 Nov 2018 03:53:03 +0700 Subject: core/msgb.h: introduce msgb_l4len() helper There is already a group of similar functions for L1, L2 and L3, but L4 was missing. The L4 is usually used for parsing of complex L3 messages, such as SS/USSD and SMS. This change introduces a similar halper for L4. Change-Id: I755f2d654bbdad2a8b4f94df9023bdd370b07ae6 --- TODO-RELEASE | 1 + include/osmocom/core/msgb.h | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/TODO-RELEASE b/TODO-RELEASE index 64833d23..5222ec96 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -10,3 +10,4 @@ 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() +libosmocore msgb_l4len new symbol (exposed as 'static inline' in msgb.h) diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index b1cb6ec7..8843db01 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -169,6 +169,18 @@ static inline unsigned int msgb_l3len(const struct msgb *msgb) return msgb->tail - (uint8_t *)msgb_l3(msgb); } +/*! determine length of L4 message + * \param[in] msgb message buffer + * \returns size of L4 message in bytes + * + * This function computes the number of bytes between the tail of the + * message and the layer 4 header. + */ +static inline unsigned int msgb_l4len(const struct msgb *msgb) +{ + return msgb->tail - (uint8_t *)msgb_sms(msgb); +} + /*! determine the length of the header * \param[in] msgb message buffer * \returns number of bytes between start of buffer and start of msg -- cgit v1.2.3 From ba2bd2eeb18ed361a0ee6038c8a3f114748aa576 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Tue, 6 Nov 2018 21:16:37 +0100 Subject: jenkins: print gcc version in log Change-Id: I8dfac78868f64213413e80cc52ac585d9d4a2c93 --- contrib/jenkins_arch.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contrib/jenkins_arch.sh b/contrib/jenkins_arch.sh index 99ce5c1a..93dd8bb4 100755 --- a/contrib/jenkins_arch.sh +++ b/contrib/jenkins_arch.sh @@ -14,7 +14,11 @@ if [ ! -d "./contrib" ]; then exit 1 fi -set -x -e +set -x + +gcc --version + +set -e case "$arch" in -- cgit v1.2.3 From 860651ebd89072fa6fdcdd2dceeee96e5f088c18 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Tue, 30 Oct 2018 14:31:57 +0100 Subject: socket.c: fix IP and port buffer sizes Use INET6_ADDRSTRLEN (46) instead of 64 for IP address buffers, and 6 instead of 16 for port buffers (the highest possible port number is 65535). Change-Id: Ia25e2f3277ad2f60df31c08d12f42c1e6d2a14a6 --- src/socket.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/socket.c b/src/socket.c index c7e1c9dd..0e17a28d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -57,7 +57,7 @@ static struct addrinfo *addrinfo_helper(uint16_t family, uint16_t type, uint8_t const char *host, uint16_t port, bool passive) { struct addrinfo hints, *result; - char portbuf[16]; + char portbuf[6]; int rc; snprintf(portbuf, sizeof(portbuf), "%u", port); @@ -698,7 +698,7 @@ static int osmo_sock_get_name2(int fd, char *ip, size_t ip_len, char *port, size { struct sockaddr sa; socklen_t len = sizeof(sa); - char ipbuf[64], portbuf[16]; + char ipbuf[INET6_ADDRSTRLEN], portbuf[6]; int rc; rc = local ? getsockname(fd, &sa, &len) : getpeername(fd, &sa, &len); @@ -769,8 +769,8 @@ int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len) */ char *osmo_sock_get_name(void *ctx, int fd) { - char hostbuf_l[64], hostbuf_r[64]; - char portbuf_l[16], portbuf_r[16]; + char hostbuf_l[INET6_ADDRSTRLEN], hostbuf_r[INET6_ADDRSTRLEN]; + char portbuf_l[6], portbuf_r[6]; /* get local */ if (osmo_sock_get_name2(fd, hostbuf_l, sizeof(hostbuf_l), portbuf_l, sizeof(portbuf_l), true)) -- cgit v1.2.3 From 534a4b28977e1ab780e843b9ad25e2f3da463f6d Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 6 Nov 2018 17:10:31 +0100 Subject: gsm_29_118: add missing include to header file The header file gsm_29_118.h is defining variables of type struct value_string, which is declared in core/utils.h. We should add an include to utils.h to prevent confusion when the header is used. Change-Id: I9f9bb62d29cd068820ad5aa677717bd448de3f4a Related: OS#3615 --- include/osmocom/gsm/protocol/gsm_29_118.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/osmocom/gsm/protocol/gsm_29_118.h b/include/osmocom/gsm/protocol/gsm_29_118.h index 24e9de2e..c344f040 100644 --- a/include/osmocom/gsm/protocol/gsm_29_118.h +++ b/include/osmocom/gsm/protocol/gsm_29_118.h @@ -1,5 +1,6 @@ #pragma once +#include /* TS 29.118 Section 9.2 */ enum sgsap_msg_type { -- cgit v1.2.3 From 4c9d1479a6e1653b49649116ffef9af337f332b5 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Mon, 12 Nov 2018 11:17:15 +0100 Subject: merge_doc.xsl: move to osmo-gsm-manuals.git Allows building the manuals without the checked out libosmocore source. Related: OS#3385 Depends: I8e7036fae062ee783cb132b14608827a82c5e7c7 (osmo-gsm-manuals) Change-Id: Ifb81b18422987cdf36b75993d2782abf93b5f48c --- doc/vty/merge_doc.xsl | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) delete mode 100644 doc/vty/merge_doc.xsl diff --git a/doc/vty/merge_doc.xsl b/doc/vty/merge_doc.xsl deleted file mode 100644 index d75c4994..00000000 --- a/doc/vty/merge_doc.xsl +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.2.3 From e63b8873586b575af433c0d4213fc71c746dd7e1 Mon Sep 17 00:00:00 2001 From: Martin Hauke Date: Thu, 15 Nov 2018 14:53:13 +0100 Subject: gsm/protocol/gsm_08_58.h: Fix typo Fix a typo that prevents building on ppc64 (Power8, Big Endian). Tested with gcc version: 8.2.1+r265487 /bin/sh ../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I.. -I../include -I../include -DBUILDING_LIBOSMOCORE -Wall -Wall -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -DBUILDING_LIBOSMOCORE -Wall -c -o panic.lo panic.c In file included from ../include/osmocom/gsm/rsl.h:6, from gsmtap_util.c:37: ../include/osmocom/gsm/protocol/gsm_08_58.h:60:4: error: expected specifier-qualifier-list before 'sapi' sapi:3; ^~~~ Change-Id: I4a40fc68cb6dfdfadfcc34213c4ecdabbbc356f2 --- include/osmocom/gsm/protocol/gsm_08_58.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/osmocom/gsm/protocol/gsm_08_58.h b/include/osmocom/gsm/protocol/gsm_08_58.h index cd28caf8..363f33d7 100644 --- a/include/osmocom/gsm/protocol/gsm_08_58.h +++ b/include/osmocom/gsm/protocol/gsm_08_58.h @@ -56,7 +56,7 @@ union abis_rsl_link_id { #if OSMO_IS_BIG_ENDIAN uint8_t cbits:2, na:1, - reserved:2; + reserved:2, sapi:3; #elif OSMO_IS_LITTLE_ENDIAN uint8_t sapi:3, -- cgit v1.2.3 From 086b345414ef17b305b5c624fbdbc4bf0f855042 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 15 Nov 2018 15:04:29 +0100 Subject: gsm29118: add value strings for SGSAP IEI The value strings for the SGSAP IEI are missing, lets add a set of value strings and a function to retrieve them. Change-Id: I2787303174f74ffba86675bce2c12f680d8ea708 Related: OS#3615 --- include/osmocom/gsm/protocol/gsm_29_118.h | 5 ++++- src/gsm/gsm29118.c | 35 +++++++++++++++++++++++++++++++ src/gsm/libosmogsm.map | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/protocol/gsm_29_118.h b/include/osmocom/gsm/protocol/gsm_29_118.h index c344f040..bf210ad0 100644 --- a/include/osmocom/gsm/protocol/gsm_29_118.h +++ b/include/osmocom/gsm/protocol/gsm_29_118.h @@ -74,7 +74,10 @@ enum sgsap_iei { SGSAP_IE_ADDL_PAGING_INDICATORS = 0x26, SGSAP_IE_TMSI_BASED_NRI_CONT = 0x27, }; - +const struct value_string sgsap_iei_names[]; +static inline const char *sgsap_iei_name(enum sgsap_iei iei) { + return get_value_string(sgsap_iei_names, iei); +} /* TS 29.118 Section 9.4.2 */ enum sgsap_eps_lu_type { diff --git a/src/gsm/gsm29118.c b/src/gsm/gsm29118.c index de625a90..3898be64 100644 --- a/src/gsm/gsm29118.c +++ b/src/gsm/gsm29118.c @@ -32,6 +32,41 @@ const struct value_string sgsap_msg_type_names[] = { { 0, NULL } }; +const struct value_string sgsap_iei_names[] = { + { SGSAP_IE_IMSI, "IMSI" }, + { SGSAP_IE_VLR_NAME, "VLR-NAME" }, + { SGSAP_IE_TMSI, "TMSI" }, + { SGSAP_IE_LAI, "LAI" }, + { SGSAP_IE_CHAN_NEEDED, "CHAN-NEEDED" }, + { SGSAP_IE_EMLPP_PRIORITY, "EMLPP-PRIORITY" }, + { SGSAP_IE_TMSI_STATUS, "TMSI-STATUS" }, + { SGSAP_IE_SGS_CAUSE, "SGS-CAUSE" }, + { SGSAP_IE_MME_NAME, "MME-NAME" }, + { SGSAP_IE_EPS_LU_TYPE, "EPS-LU-TYPE" }, + { SGSAP_IE_GLOBAL_CN_ID, "GLOBAL-CN-ID" }, + { SGSAP_IE_MOBILE_ID, "MOBILE-ID" }, + { SGSAP_IE_REJECT_CAUSE, "REJECT-CAUSE" }, + { SGSAP_IE_IMSI_DET_EPS_TYPE, "IMSI-DET-EPS-TYPE" }, + { SGSAP_IE_IMSI_DET_NONEPS_TYPE, "IMSI-DET-NONEPS-TYPE" }, + { SGSAP_IE_IMEISV, "IMEISV" }, + { SGSAP_IE_NAS_MSG_CONTAINER, "NAS-MSG-CONTAINER" }, + { SGSAP_IE_MM_INFO, "MM-INFO" }, + { SGSAP_IE_ERR_MSG, "ERR-MSG" }, + { SGSAP_IE_CLI, "CLI" }, + { SGSAP_IE_LCS_CLIENT_ID, "LCS-CLIENT-ID" }, + { SGSAP_IE_LCS_INDICATOR, "LCS-INDICATOR" }, + { SGSAP_IE_SS_CODE, "SS-CODE" }, + { SGSAP_IE_SERVICE_INDICATOR, "SERVICE-INDICATOR" }, + { SGSAP_IE_UE_TIMEZONE, "UE-TIMEZONE" }, + { SGSAP_IE_MS_CLASSMARK2, "MS-CLASSMARK2" }, + { SGSAP_IE_TAI, "TAI" }, + { SGSAP_IE_EUTRAN_CGI, "EUTRAN-CGI" }, + { SGSAP_IE_UE_EMM_MODE, "UE-EMM-MODE" }, + { SGSAP_IE_ADDL_PAGING_INDICATORS, "ADDL-PAGING-INDICATORS" }, + { SGSAP_IE_TMSI_BASED_NRI_CONT, "TMSI-BASED-NRI-CONT" }, + { 0, NULL } +}; + const struct value_string sgsap_eps_lu_type_names[] = { { SGSAP_EPS_LUT_IMSI_ATTACH, "IMSI Attach" }, { SGSAP_EPS_LUT_NORMAL, "Normal" }, diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 4813e135..6234d949 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -512,6 +512,7 @@ osmo_oap_client_init; osmo_oap_client_register; sgsap_msg_type_names; +sgsap_iei_names; sgsap_eps_lu_type_names; sgsap_ismi_det_eps_type_names; sgsap_ismi_det_noneps_type_names; -- cgit v1.2.3 From af6710f4d433d138c5d1ea57d1e4ab22c86d4385 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Fri, 16 Nov 2018 17:45:40 +0100 Subject: fsm: fix apidoc of osmo_fsm_state_name() The api documentation of osmo_fsm_state_name() refers to an FSM instance, but it really means the state of an FSM. Change-Id: I88ddd6048426d380c49170e66f57b3843398c046 --- src/fsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fsm.c b/src/fsm.c index b5af2e7a..1f6141fa 100644 --- a/src/fsm.c +++ b/src/fsm.c @@ -414,7 +414,7 @@ const char *osmo_fsm_inst_name(struct osmo_fsm_inst *fi) return fi->fsm->name; } -/*! get human-readable name of FSM instance +/*! get human-readable name of FSM state * \param[in] fsm FSM descriptor * \param[in] state FSM state number * \returns string rendering of the FSM state -- cgit v1.2.3 From c0d1de36f3e378364b1c02e98a3870394e3d457e Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 7 Nov 2018 15:24:11 +0100 Subject: Add helper wrapper for BSSAP TLV parsing Change-Id: Ib228368901ce90a02a5664f2510593371c7d29cd --- include/osmocom/gsm/gsm0808.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index cdbb2734..652aae99 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -173,6 +173,9 @@ void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id); const struct tlv_definition *gsm0808_att_tlvdef(void); +/*! Parse BSSAP TLV structure using \ref tlv_parse */ +#define osmo_bssap_tlv_parse(dec, buf, len) tlv_parse(dec, gsm0808_att_tlvdef(), buf, len, 0, 0) + const char *gsm0808_bssmap_name(uint8_t msg_type); const char *gsm0808_bssap_name(uint8_t msg_type); const char *gsm0808_cause_name(uint8_t cause); -- cgit v1.2.3 From aa934630530af05a84b62b204ce4da7688c5e3ad Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 7 Nov 2018 13:16:54 +0100 Subject: Update 3GPP TS 08.08 Cause handling * add Class definitions * add helper to check for extended bit * add helper to get Cause's Class * use enum in gsm0808_cause_name() and gsm0808_create_cipher_reject() to avoid confusion between class and cause * update gsm0808_create_cipher_reject() comments Change-Id: I31b31dfc22eb4b6b07089e1255246ac458125340 Related: OS#3187 --- TODO-RELEASE | 5 +++++ include/osmocom/gsm/gsm0808.h | 5 +++-- include/osmocom/gsm/gsm0808_utils.h | 15 ++++++++++++++- include/osmocom/gsm/protocol/gsm_08_08.h | 12 ++++++++++++ src/gsm/gsm0808.c | 30 ++++++++++++++++++++++++------ src/gsm/libosmogsm.map | 1 + 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/TODO-RELEASE b/TODO-RELEASE index 5222ec96..00720f64 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -11,3 +11,8 @@ 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() libosmocore msgb_l4len new symbol (exposed as 'static inline' in msgb.h) +libosmogsm gsm0808_cause_class_name() getter for class description +libosmogsm gsm0808_cause_class() getter for cause class +libosmogsm gsm0808_cause_ext() check for cause extended bit +libosmogsm gsm0808_cause_name() use enum as parameter +libosmogsm gsm0808_create_cipher_reject() use enum as parameter diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 652aae99..66f7c277 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -50,7 +50,7 @@ struct msgb *gsm0808_create_clear_complete(void); struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei, const uint8_t *cipher_response_mode); struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); -struct msgb *gsm0808_create_cipher_reject(uint8_t cause); +struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause); struct msgb *gsm0808_create_classmark_request(); struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len, const uint8_t *cm3, uint8_t cm3_len); @@ -178,7 +178,8 @@ const struct tlv_definition *gsm0808_att_tlvdef(void); const char *gsm0808_bssmap_name(uint8_t msg_type); const char *gsm0808_bssap_name(uint8_t msg_type); -const char *gsm0808_cause_name(uint8_t cause); +const char *gsm0808_cause_name(enum gsm0808_cause cause); +const char *gsm0808_cause_class_name(enum gsm0808_cause_class class); extern const struct value_string gsm0808_lcls_config_names[]; extern const struct value_string gsm0808_lcls_control_names[]; diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index f70dbdb6..b56e2635 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -107,7 +107,20 @@ int gsm0808_speech_codec_from_chan_type(struct gsm0808_speech_codec *sc, uint16_t gsm0808_sc_cfg_from_gsm48_mr_cfg(const struct gsm48_multi_rate_conf *cfg, bool fr); void gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, uint16_t s15_s0); -/*! Return 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ +/*! \returns 3GPP TS 08.08 §3.2.2.5 Class of a given Cause */ +static inline enum gsm0808_cause_class gsm0808_cause_class(enum gsm0808_cause cause) +{ + return (cause << 1) >> 4; +} + +/*! \returns true if 3GPP TS 08.08 §3.2.2.5 Class has extended bit set */ +static inline bool gsm0808_cause_ext(enum gsm0808_cause cause) +{ + /* check that cause looks like 1XXX0000 where XXX represent class */ + return (cause & 0x80) && !(cause & 0x0F); +} + +/*! \returns 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) { switch (type) { diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 8431ace5..2317e784 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -384,6 +384,18 @@ enum gsm0808_cause { GSM0808_CAUSE_DTM_HO_TIMER_EXPIRY = 0x62, }; +/* 3GPP TS 08.08 §3.2.2.5 Cause Class */ +enum gsm0808_cause_class { + GSM0808_CAUSE_CLASS_NORM0 = 0, + GSM0808_CAUSE_CLASS_NORM1 = 1, + GSM0808_CAUSE_CLASS_RES_UNAVAIL = 2, + GSM0808_CAUSE_CLASS_SRV_OPT_NA = 3, + GSM0808_CAUSE_CLASS_SRV_OPT_NIMPL = 4, + GSM0808_CAUSE_CLASS_INVAL = 5, + GSM0808_CAUSE_CLASS_PERR = 6, + GSM0808_CAUSE_CLASS_INTW = 7, +}; + /* GSM 08.08 3.2.2.11 Channel Type */ enum gsm0808_chan_indicator { GSM0808_CHAN_SPEECH = 1, diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index e5c3e30a..791ebc2c 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -265,18 +265,18 @@ struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id) } /*! Create BSSMAP Cipher Mode Reject message - * \param[in] cause TS 08.08 cause value + * \param[in] cause 3GPP TS 08.08 §3.2.2.5 cause value * \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */ -struct msgb *gsm0808_create_cipher_reject(uint8_t cause) +struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause) { struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, - "bssmap: clear complete"); + "bssmap: cipher mode reject"); if (!msg) return NULL; msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); - /* FIXME: support 2-byte cause value as per 3GPP TS 08.08 §3.2.2.5 */ - msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); + + msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, (const uint8_t *)&cause); msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); @@ -1271,8 +1271,26 @@ static const struct value_string gsm0808_cause_names[] = { { 0, NULL } }; +static const struct value_string gsm0808_cause_class_names[] = { + { GSM0808_CAUSE_CLASS_NORM0, "Normal event" }, + { GSM0808_CAUSE_CLASS_NORM1, "Normal event" }, + { GSM0808_CAUSE_CLASS_RES_UNAVAIL, "Resource unavailable" }, + { GSM0808_CAUSE_CLASS_SRV_OPT_NA, "Service or option not available" }, + { GSM0808_CAUSE_CLASS_SRV_OPT_NIMPL, "Service or option not implemented" }, + { GSM0808_CAUSE_CLASS_INVAL, "Invalid message" }, + { GSM0808_CAUSE_CLASS_PERR, "Protocol error" }, + { GSM0808_CAUSE_CLASS_INTW, "Interworking" }, + { 0, NULL } +}; + +/*! Return string name of BSSMAP Cause Class name */ +const char *gsm0808_cause_class_name(enum gsm0808_cause_class class) +{ + return get_value_string(gsm0808_cause_class_names, class); +} + /*! Return string name of BSSMAP Cause name */ -const char *gsm0808_cause_name(uint8_t cause) +const char *gsm0808_cause_name(enum gsm0808_cause cause) { return get_value_string(gsm0808_cause_names, cause); } diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 6234d949..32e4ce95 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -148,6 +148,7 @@ gsm0808_att_tlvdef; gsm0808_bssap_name; gsm0808_bssmap_name; gsm0808_cause_name; +gsm0808_cause_class_name; gsm0808_create_ass; gsm0808_create_assignment_completed; gsm0808_create_ass_compl; -- cgit v1.2.3 From 961db7c270e47de91b04ae444f2e4c319b389ce2 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 8 Nov 2018 11:40:23 +0100 Subject: Update GSM0808_LCLS enums Add values indicating that LCLS control/config/status value has not been received yet. Change-Id: I52dc6a52f5ee043ed2c1625ffecfd495e3c746b1 Related: OS#2487 --- include/osmocom/gsm/protocol/gsm_08_08.h | 3 +++ src/gsm/gsm0808.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/osmocom/gsm/protocol/gsm_08_08.h b/include/osmocom/gsm/protocol/gsm_08_08.h index 2317e784..cb9fe011 100644 --- a/include/osmocom/gsm/protocol/gsm_08_08.h +++ b/include/osmocom/gsm/protocol/gsm_08_08.h @@ -576,6 +576,7 @@ enum gsm0808_lcls_config { GSM0808_LCLS_CFG_BOTH_WAY_AND_SEND_DL_BLOCK_LOCAL_DL = 0x03, GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL_SEND_DL = 0x04, GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL_SEND_DL_BLOCK_LOCAL_DL = 0x05, + GSM0808_LCLS_CFG_NA = 0xFF }; /* TS 48.008 3.2.2.117 */ @@ -585,6 +586,7 @@ enum gsm0808_lcls_control { GSM0808_LCLS_CSC_RELEASE_LCLS = 0x02, GSM0808_LCLS_CSC_BICAST_UL_AT_HANDOVER = 0x03, GSM0808_LCLS_CSC_BICAST_UL_AND_RECV_DL_AT_HANDOVER = 0x04, + GSM0808_LCLS_CSC_NA = 0xFF }; /* TS 48.008 3.2.2.119 */ @@ -594,4 +596,5 @@ enum gsm0808_lcls_status { GSM0808_LCLS_STS_NO_LONGER_LS = 0x02, GSM0808_LCLS_STS_REQ_LCLS_NOT_SUPP = 0x03, GSM0808_LCLS_STS_LOCALLY_SWITCHED = 0x04, + GSM0808_LCLS_STS_NA = 0xFF }; diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index 791ebc2c..c413688c 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -1307,6 +1307,7 @@ const struct value_string gsm0808_lcls_config_names[] = { "Connect both-way, bi-cast UL to CN, send access DL from CN" }, { GSM0808_LCLS_CFG_BOTH_WAY_AND_BICAST_UL_SEND_DL_BLOCK_LOCAL_DL, "Connect both-way, bi-cast UL to CN, send access DL from CN, block local DL" }, + { GSM0808_LCLS_CFG_NA, "Not available" }, { 0, NULL } }; @@ -1316,6 +1317,7 @@ const struct value_string gsm0808_lcls_control_names[] = { { GSM0808_LCLS_CSC_RELEASE_LCLS, "Release LCLS" }, { GSM0808_LCLS_CSC_BICAST_UL_AT_HANDOVER, "Bi-cast UL at Handover" }, { GSM0808_LCLS_CSC_BICAST_UL_AND_RECV_DL_AT_HANDOVER, "Bi-cast UL and receive DL at Handover" }, + { GSM0808_LCLS_CSC_NA, "Not available" }, { 0, NULL } }; @@ -1325,6 +1327,7 @@ const struct value_string gsm0808_lcls_status_names[] = { { GSM0808_LCLS_STS_NO_LONGER_LS, "Call is no longer locally switched" }, { GSM0808_LCLS_STS_REQ_LCLS_NOT_SUPP, "Requested LCLS configuration is not supported" }, { GSM0808_LCLS_STS_LOCALLY_SWITCHED, "Call is locally switched with requested LCLS config" }, + { GSM0808_LCLS_STS_NA, "Not available" }, { 0, NULL } }; -- cgit v1.2.3 From d8d0c3e2d14588f8ae863b36f496f20775777619 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Thu, 15 Nov 2018 18:26:01 +0100 Subject: gsm48: gsm48_decode_freq_list: Improve documentation of paramter f Change-Id: Id8e3afff737211ded3c5689f2c83b1a544b42f9d --- src/gsm/gsm48_ie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gsm/gsm48_ie.c b/src/gsm/gsm48_ie.c index 1baf2879..ffe3ebae 100644 --- a/src/gsm/gsm48_ie.c +++ b/src/gsm/gsm48_ie.c @@ -807,7 +807,7 @@ static int32_t smod(int32_t n, int32_t m) } /*! Decode TS 04.08 Cell Channel Description IE (10.5.2.1b) and other frequency lists - * \param[out] f Caller-provided output memory + * \param[out] f Caller-provided output memory, an array of 1024 elements * \param[in] cd Cell Channel Description IE * \param[in] len Length of \a cd in bytes * \returns 0 on success; negative on error */ -- cgit v1.2.3 From 84fb5bb6a09a6a358f98c654c84c3b99a0f24eef Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 8 Nov 2018 13:23:59 +0100 Subject: Move msgb_push helpers to public header The msgb_wrap_with_TL() is generally useful so it make sense to make it public to facilitate code re-use. Other helpers can be implemented as trivial wrappers over existing tlv.h functions. Update headers and code accordingly. Change-Id: I37e91d031fba28cf1c6735b8069b0265746f55e6 --- include/osmocom/core/msgb.h | 9 +++++++++ include/osmocom/gsm/tlv.h | 6 ++++++ src/gsm/gsm0480.c | 49 +++++++++------------------------------------ 3 files changed, 25 insertions(+), 39 deletions(-) diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index 8843db01..2449151d 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -366,6 +366,15 @@ static inline void msgb_push_u32(struct msgb *msg, uint32_t word) osmo_store32be(word, space); } +static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) +{ + uint8_t *data = msgb_push(msgb, 2); + + data[0] = tag; + data[1] = msgb->len - 2; + return data; +} + /*! remove (pull) a header from the front of the message buffer * \param[in] msgb message buffer * \param[in] len number of octets to be pulled diff --git a/include/osmocom/gsm/tlv.h b/include/osmocom/gsm/tlv.h index 84fd511e..1ab964ad 100644 --- a/include/osmocom/gsm/tlv.h +++ b/include/osmocom/gsm/tlv.h @@ -341,6 +341,12 @@ static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, return buf; } +/*! push 1-byte tagged value */ +static inline uint8_t *msgb_tlv1_push(struct msgb *msg, uint8_t tag, uint8_t val) +{ + return msgb_tlv_push(msg, tag, 1, &val); +} + /*! push (prepend) a TV field to a \ref msgb * \returns pointer to first byte of newly-pushed information */ static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val) diff --git a/src/gsm/gsm0480.c b/src/gsm/gsm0480.c index 7756ecba..021db62f 100644 --- a/src/gsm/gsm0480.c +++ b/src/gsm/gsm0480.c @@ -68,35 +68,6 @@ const struct value_string gsm0480_op_code_names[] = { { 0, NULL } }; -static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag) -{ - uint8_t *data = msgb_push(msgb, 2); - - data[0] = tag; - data[1] = msgb->len - 2; - return data; -} - -static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag, - uint8_t value) -{ - uint8_t *data = msgb_push(msgb, 3); - - data[0] = tag; - data[1] = 1; - data[2] = value; - 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 @@ -107,10 +78,10 @@ static inline unsigned char *msgb_push_NULL(struct msgb *msgb) int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id) { /* 3. operation */ - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, op); + msgb_tlv1_push(msg, GSM0480_OPERATION_CODE, op); /* 2. invoke id tag */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, link_id); + msgb_tlv1_push(msg, GSM0480_COMPIDTAG_INVOKE_ID, link_id); /* 1. component tag */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_INVOKE); @@ -825,20 +796,20 @@ struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text) msgb_wrap_with_TL(msg, ASN1_OCTET_STRING_TAG); /* Pre-pend the DCS octet string */ - msgb_push_TLV1(msg, ASN1_OCTET_STRING_TAG, 0x0F); + msgb_tlv1_push(msg, ASN1_OCTET_STRING_TAG, 0x0F); /* Then wrap these as a Sequence */ msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); /* Pre-pend the operation code */ - msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, + msgb_tlv1_push(msg, GSM0480_OPERATION_CODE, GSM0480_OP_CODE_PROCESS_USS_REQ); /* Wrap the operation code and IA5 string as a sequence */ msgb_wrap_with_TL(msg, GSM_0480_SEQUENCE_TAG); /* Pre-pend the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + msgb_tlv1_push(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); /* Wrap this up as a Return Result component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT); @@ -889,10 +860,10 @@ struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code) return NULL; /* First insert the problem code */ - msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code); + msgb_tlv1_push(msg, GSM_0480_ERROR_CODE_TAG, error_code); /* Before it, insert the invoke ID */ - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + msgb_tlv1_push(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); /* Wrap this up as a Reject component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_ERROR); @@ -919,13 +890,13 @@ struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t prob return NULL; /* First insert the problem code */ - msgb_push_TLV1(msg, problem_tag, problem_code); + msgb_tlv1_push(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); + msgb_tv_push(msg, ASN1_NULL_TYPE_TAG, 0); else - msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); + msgb_tlv1_push(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id); /* Wrap this up as a Reject component */ msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT); -- cgit v1.2.3 From ed651d2485a51b57bf6090f4f58fd356118c6835 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 7 Nov 2018 15:25:05 +0100 Subject: Support cipher mode reject with extended cause * add function to generate cipher mode reject with extended (2-byte) Cause IE * add function to get (extended) Cause value * add corresponding (extended cause) test * update existing (non-extended cause) test * use enum as a parameter for existing non-extended version to make interface more unified Change-Id: Id5509b94a18180a44f45300caaa02b843c166fa3 Related: OS#3187 --- include/osmocom/gsm/gsm0808.h | 1 + include/osmocom/gsm/gsm0808_utils.h | 2 ++ src/gsm/gsm0808.c | 24 ++++++++++++++++++++ src/gsm/gsm0808_utils.c | 16 ++++++++++++++ src/gsm/libosmogsm.map | 2 ++ tests/gsm0808/gsm0808_test.c | 44 ++++++++++++++++++++++++++++++++++++- tests/gsm0808/gsm0808_test.ok | 1 + 7 files changed, 89 insertions(+), 1 deletion(-) diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 66f7c277..9b19d691 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -51,6 +51,7 @@ struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei, const uint8_t *cipher_response_mode); struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id); struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause); +struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext); struct msgb *gsm0808_create_classmark_request(); struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len, const uint8_t *cm3, uint8_t cm3_len); diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index b56e2635..c22d0a9b 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -120,6 +120,8 @@ static inline bool gsm0808_cause_ext(enum gsm0808_cause cause) return (cause & 0x80) && !(cause & 0x0F); } +int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp); + /*! \returns 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */ static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type) { diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index c413688c..a84e717d 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -283,6 +283,30 @@ struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause) return msg; } +/*! Create BSSMAP Cipher Mode Reject message + * \param[in] class 3GPP TS 08.08 §3.2.2.5 cause's class + * \param[in] ext 3GPP TS 08.08 §3.2.2.5 cause value (national application extension) + * \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */ +struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext) +{ + uint8_t c[2]; + struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM, + "bssmap: cipher mode reject"); + if (!msg) + return NULL; + + c[0] = 0x80 | (class << 4); /* set the high bit to indicate extended cause */ + c[1] = ext; + + msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); + + msgb_tlv_put(msg, GSM0808_IE_CAUSE, 2, c); + + msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + + return msg; +} + /*! Create BSSMAP LCLS CONNECT CONTROL message (TS 48.008 3.2.1.91). * \param[in] config LCLS Configuration * \param[in] control LCLS Connection Status Control diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 2348105d..c58d8284 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1235,6 +1235,22 @@ void gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg, cfg->icmi = 1; } +int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp) +{ + const uint8_t *buf = TLVP_VAL_MINLEN(tp, GSM0808_IE_CAUSE, 1); + + if (!buf) + return -EBADMSG; + + if (TLVP_LEN(tp, GSM0808_IE_CAUSE) > 1) { + if (!gsm0808_cause_ext(buf[0])) + return -EINVAL; + return buf[1]; + } + + return buf[0]; +} + /*! Print a human readable name of the cell identifier to the char buffer. * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2. * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 32e4ce95..217dcc39 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -157,6 +157,8 @@ gsm0808_create_ass_fail; gsm0808_create_cipher; gsm0808_create_cipher_complete; gsm0808_create_cipher_reject; +gsm0808_create_cipher_reject_ext; +gsm0808_get_cipher_reject_cause; gsm0808_create_classmark_request; gsm0808_create_classmark_update; gsm0808_create_clear_command; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 671b8399..197ec06d 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -250,14 +250,55 @@ static void test_create_cipher_complete() msgb_free(l3); } +static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp) +{ + struct tlv_parsed tp; + int rc; + + /* skip header and message type so we can parse Cause IE directly */ + msg->l2h = msgb_data(msg) + sizeof(struct bssmap_header) + 1; + + rc = osmo_bssap_tlv_parse(&tp, msg->l2h, msgb_l2len(msg)); + if (rc < 0) + printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg)); + + rc = gsm0808_get_cipher_reject_cause(&tp); + if (rc < 0) + printf("FIXME: failed (%s) to extract Cause from created message %s\n", + strerror(-rc), msgb_hexdump(msg)); + + if (exp != (enum gsm0808_cause)rc) + printf("FIXME: wrong Cause %d != %u (" OSMO_BIN_SPEC ") extracted from created message %s\n", + rc, exp, OSMO_BIT_PRINT(exp), msgb_hexdump(msg)); +} + static void test_create_cipher_reject() { static const uint8_t res[] = { 0x00, 0x04, 0x59, 0x04, 0x01, 0x23 }; + enum gsm0808_cause cause = GSM0808_CAUSE_CCCH_OVERLOAD; struct msgb *msg; printf("Testing creating Cipher Reject\n"); - msg = gsm0808_create_cipher_reject(GSM0808_CAUSE_CCCH_OVERLOAD); + msg = gsm0808_create_cipher_reject(cause); + VERIFY(msg, res, ARRAY_SIZE(res)); + + parse_cipher_reject(msg, cause); + + msgb_free(msg); +} + +static void test_create_cipher_reject_ext() +{ + static const uint8_t res[] = { 0x00, 0x05, 0x59, 0x04, 0x02, 0xd0, 0xFA }; + uint8_t cause = 0xFA; + struct msgb *msg; + + printf("Testing creating Cipher Reject (extended)\n"); + msg = gsm0808_create_cipher_reject_ext(GSM0808_CAUSE_CLASS_INVAL, cause); VERIFY(msg, res, ARRAY_SIZE(res)); + + parse_cipher_reject(msg, cause); + msgb_free(msg); } @@ -1738,6 +1779,7 @@ int main(int argc, char **argv) test_create_cipher(); test_create_cipher_complete(); test_create_cipher_reject(); + test_create_cipher_reject_ext(); test_create_cm_u(); test_create_sapi_reject(); test_create_ass(); diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index 58bc5099..a48cf1d5 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -8,6 +8,7 @@ Testing creating Clear Complete Testing creating Chipher Mode Command Testing creating Cipher Complete Testing creating Cipher Reject +Testing creating Cipher Reject (extended) Testing creating CM U Testing creating SAPI Reject Testing creating Assignment Request -- cgit v1.2.3 From adc4172fe3c18cb93809c5f4e46e9fbdf213025e Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 19 Nov 2018 10:44:55 +0100 Subject: Add missing header include That's necessary for 'struct tlv_parsed' definition although lack of it does not cause build failure in libosmocore for me but does so for osmo-bsc. Change-Id: I3b2d3955d02b07dc7ec5e9f0c66cc477196703ed --- include/osmocom/gsm/gsm0808_utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index c22d0a9b..edae8530 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -29,6 +29,7 @@ struct sockaddr_storage; #include #include #include +#include /*! (225-1)/2 is the maximum number of elements in a cell identifier list. */ #define GSM0808_CELL_ID_LIST2_MAXLEN 127 -- cgit v1.2.3 From 5a25c3ec4dcb6d3789c6ce94e3c3a165cc5c04d8 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Fri, 16 Nov 2018 01:21:46 +0100 Subject: gsm_44_318.h: remove #if 0 from struct gan_cch_desc_ie These are actually parts of the struct in big endian order, which will soon be done automatically by struct_endianess.py. Change-Id: I9bc694f10fa9cef0bb7fc791bb40e7602459b16b --- include/osmocom/gsm/protocol/gsm_44_318.h | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/include/osmocom/gsm/protocol/gsm_44_318.h b/include/osmocom/gsm/protocol/gsm_44_318.h index 76e8396c..6ac02cfd 100644 --- a/include/osmocom/gsm/protocol/gsm_44_318.h +++ b/include/osmocom/gsm/protocol/gsm_44_318.h @@ -170,15 +170,6 @@ struct gan_cch_desc_ie { dtm:1, att:1, mscr:1; -#if 0 - uint8_t mscr:1, - att:1, - dtm:1, - gprs:1, - nmo:2, - ecmc:1, - spare:1; -#endif uint8_t t3212; uint8_t rac; uint8_t sgsnr:1, @@ -187,13 +178,5 @@ struct gan_cch_desc_ie { pfcfm:1, tgecs:2, spare2:2; -#if 0 - uint8_t spare2:2, - tgecs:2, - pfcfm:1, - re:1, - ecmp:1, - sgsnr:1; -#endif uint8_t access_class[2]; } __attribute__((packed)); -- cgit v1.2.3 From 797558ea1768e464f9559c5f7a4f3f4285c5de25 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Mon, 19 Nov 2018 17:18:41 +0100 Subject: send NS_POUT_UNBLOCK_ACK before signalling S_NS_UNBLOCK In gprs_ns_process_msg(), we were dispatching the S_NS_UNBLOCK signal before sending out the NS_POUT_UNBLOCK_ACK message. Signal handlers might send messages to the other side, assuming that NS is now unblocked. However, since such messages will arrive before the UNBLOCK_ACK message the receiver might discard them. This problem has been observed with our TTCN3 BSSGP_Emulation as a peer to osmo-pcu. This patch makes TTCN3 PCU TC_paging() test pass regardless of whether the test or osmo-pcu is started first. Before this patch, this test would only pass if the test was started before osmo-pcu. A remaining problem is that the test does not yet keep passing reliably unless osmo-pcu is restarted between test runs. Change-Id: I3af54a14bb6bcfa167c9a9d9f67835e7f5b9f1bb Related: OS#2890 Related: OS#2388 --- src/gb/gprs_ns.c | 4 +++- tests/gb/gprs_ns_test.ok | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 198ead19..0780f2bb 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1413,8 +1413,10 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, /* Section 7.2: unblocking procedure */ LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK\n", (*nsvc)->nsei); ns_mark_unblocked(*nsvc); - ns_osmo_signal_dispatch(*nsvc, S_NS_UNBLOCK, 0); rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_UNBLOCK_ACK); + if (rc < 0) + break; + ns_osmo_signal_dispatch(*nsvc, S_NS_UNBLOCK, 0); break; case NS_PDUT_UNBLOCK_ACK: LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK ACK\n", (*nsvc)->nsei); diff --git a/tests/gb/gprs_ns_test.ok b/tests/gb/gprs_ns_test.ok index 669e1824..3cb1dfcf 100644 --- a/tests/gb/gprs_ns_test.ok +++ b/tests/gb/gprs_ns_test.ok @@ -133,10 +133,10 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:1111 06 -==> got signal NS_UNBLOCK, NS-VC 0x1122/1.2.3.4:1111 MESSAGE to BSS, msg length 1 07 +==> got signal NS_UNBLOCK, NS-VC 0x1122/1.2.3.4:1111 result (UNBLOCK) = 1 PROCESSING ALIVE_ACK from 0x01020304:1111 @@ -277,10 +277,10 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:1111 06 -==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 MESSAGE to BSS, msg length 1 07 +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:1111 result (UNBLOCK) = 1 PROCESSING ALIVE_ACK from 0x01020304:1111 @@ -318,10 +318,10 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:2222 06 -==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 MESSAGE to BSS, msg length 1 07 +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:2222 result (UNBLOCK) = 1 PROCESSING ALIVE_ACK from 0x01020304:2222 @@ -421,10 +421,10 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:1111 06 -==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 MESSAGE to BSS, msg length 1 07 +==> got signal NS_UNBLOCK, NS-VC 0x2001/1.2.3.4:1111 result (UNBLOCK) = 1 PROCESSING ALIVE_ACK from 0x01020304:1111 @@ -597,10 +597,10 @@ result (ALIVE) = 1 PROCESSING UNBLOCK from 0x01020304:2222 06 -==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:2222 MESSAGE to BSS, msg length 1 07 +==> got signal NS_UNBLOCK, NS-VC 0x1001/1.2.3.4:2222 result (UNBLOCK) = 1 PROCESSING ALIVE_ACK from 0x01020304:2222 -- cgit v1.2.3 From c6bfc63d10f971fbca8e2fd617ffc6b18ab16748 Mon Sep 17 00:00:00 2001 From: Stefan Sperling Date: Tue, 20 Nov 2018 11:01:36 +0100 Subject: document unblock-ack vs. signalling in gprs_ns_process_msg() Since commit 797558ea1768e464f9559c5f7a4f3f4285c5de25 we send the NS_UNBLOCK_ACK message before dispatching the NS_UNBLOCK signal, instead of afterwards. Add comments which explain the intended order of events. Suggested-by: Pau Related: OS#2388 Change-Id: I4b93853c952a97302f8afc14f462f22c3e487564 --- src/gb/gprs_ns.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index 0780f2bb..1281c9f4 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1413,9 +1413,15 @@ int gprs_ns_process_msg(struct gprs_ns_inst *nsi, struct msgb *msg, /* Section 7.2: unblocking procedure */ LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK\n", (*nsvc)->nsei); ns_mark_unblocked(*nsvc); + /* This UNBLOCK_ACK message will cause our peer to move us into NS_UNBLOCKED state. */ rc = gprs_ns_tx_simple(*nsvc, NS_PDUT_UNBLOCK_ACK); if (rc < 0) break; + /* + * UNBLOCK_ACK has been transmitted. + * Signal handlers may send additional messages following UNBLOCK_ACK under + * the assumption that NS is now in UNBLOCKED state at our peer's end. + */ ns_osmo_signal_dispatch(*nsvc, S_NS_UNBLOCK, 0); break; case NS_PDUT_UNBLOCK_ACK: -- cgit v1.2.3 From 738782467f70e13b1c6667aceb6747c2f3755f61 Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 9 Nov 2018 12:35:03 +0100 Subject: LCLS: add 48.008 parameter structure It's convenient to hold all LCLS-related parameters from 3GPP TS 48.008 in a single structure. This will be used in follow-up patch handling Assignment Request with extended parameters as well as corresponding BSC code working with LCLS. Change-Id: I4b873f9a3c5a5d33b438382971b3d92e40d48d62 Related: OS#2487 --- include/osmocom/gsm/gsm0808_utils.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index edae8530..c5bf2803 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -58,6 +58,14 @@ struct gsm0808_cell_id_list2 { unsigned int id_list_len; }; +/*! LCLS-related parameters from 3GPP TS 48.008 */ +struct osmo_lcls { + enum gsm0808_lcls_config config; /* §3.2.2.116 Configuration */ + enum gsm0808_lcls_control control; /* §3.2.2.117 Connection Status Control */ + struct gsm0808_gcr *gcr; /* §3.2.2.115 Global Call Reference */ + bool corr_needed; /* §3.2.2.118 Correlation-Not-Needed */ +}; + extern const struct value_string gsm0808_cell_id_discr_names[]; static inline const char *gsm0808_cell_id_discr_name(enum CELL_IDENT id_discr) { return get_value_string(gsm0808_cell_id_discr_names, id_discr); } -- cgit v1.2.3 From c8772517d9dc32da7c5e8741155e4ab638c2d01e Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Fri, 16 Nov 2018 12:59:46 +0100 Subject: gsm: Deprecate buggy gsm_arfcn2band API and introduce gsm_arfcn2band_rc ARFCNs are values in well defined ranges. Until this patch, ARFCNs not belonging to any band were blindly assigned to DCS1800 by gsm_arfcn2band, causing unnoticed bugs and misconfigurations in osmo-bsc. Previous API gsm_arfcn2band cannot accomodate this kind of check easily, so let's deprecate it to tell people to use a new API gsm_arfcn2band_rc which performs this kind of checks and allows callers to log failures, misconfigurations, etc. At the same time, modify implementation of gsm_arfcn2band to abort if an invalid ARFCN is passed, this way users of this API can notice they are passing wrong data to it that most probably will produce unexpected results. Related: OS#3063 Change-Id: I780d452dcebce385469e32ef2fd844df6033393a --- include/osmocom/gsm/gsm_utils.h | 3 +- src/gsm/gsm_utils.c | 71 ++++++++++++++++++++++++++++------------- src/gsm/libosmogsm.map | 1 + utils/osmo-arfcn.c | 8 ++++- 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h index 7eda5b9f..fe5903db 100644 --- a/include/osmocom/gsm/gsm_utils.h +++ b/include/osmocom/gsm/gsm_utils.h @@ -161,7 +161,8 @@ static inline int rach_max_trans_raw2val(int raw) { #define ARFCN_UPLINK 0x4000 #define ARFCN_FLAG_MASK 0xf000 /* Reserve the upper 5 bits for flags */ -enum gsm_band gsm_arfcn2band(uint16_t arfcn); +int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band); +enum gsm_band gsm_arfcn2band(uint16_t arfcn) OSMO_DEPRECATED("Use gsm_arfcn2band_rc() instead"); /* Convert an ARFCN to the frequency in MHz * 10 */ uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink); diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index 7e6c7947..8b4b5586 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -706,36 +706,61 @@ enum gsm_band gsm_band_parse(const char* mhz) } } -/*! Resolve GSM band from ARFCN +/*! Resolve GSM band from ARFCN. * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode - * \returns GSM Band */ -enum gsm_band gsm_arfcn2band(uint16_t arfcn) + * \param[out] band GSM Band containing \arfcn if arfcn is valid, undetermined otherwise + * \returns 0 if arfcn is valid and \a band was set, negative on error */ +int gsm_arfcn2band_rc(uint16_t arfcn, enum gsm_band *band) { int is_pcs = arfcn & ARFCN_PCS; arfcn &= ~ARFCN_FLAG_MASK; - if (is_pcs) - return GSM_BAND_1900; - else if (arfcn <= 124) - return GSM_BAND_900; - else if (arfcn >= 955 && arfcn <= 1023) - return GSM_BAND_900; - else if (arfcn >= 128 && arfcn <= 251) - return GSM_BAND_850; - else if (arfcn >= 512 && arfcn <= 885) - return GSM_BAND_1800; - else if (arfcn >= 259 && arfcn <= 293) - return GSM_BAND_450; - else if (arfcn >= 306 && arfcn <= 340) - return GSM_BAND_480; - else if (arfcn >= 350 && arfcn <= 425) - return GSM_BAND_810; - else if (arfcn >= 438 && arfcn <= 511) - return GSM_BAND_750; - else - return GSM_BAND_1800; + if (is_pcs) { + *band = GSM_BAND_1900; + return 0; + } else if (arfcn <= 124) { + *band = GSM_BAND_900; + return 0; + } else if (arfcn >= 955 && arfcn <= 1023) { + *band = GSM_BAND_900; + return 0; + } else if (arfcn >= 128 && arfcn <= 251) { + *band = GSM_BAND_850; + return 0; + } else if (arfcn >= 512 && arfcn <= 885) { + *band = GSM_BAND_1800; + return 0; + } else if (arfcn >= 259 && arfcn <= 293) { + *band = GSM_BAND_450; + return 0; + } else if (arfcn >= 306 && arfcn <= 340) { + *band = GSM_BAND_480; + return 0; + } else if (arfcn >= 350 && arfcn <= 425) { + *band = GSM_BAND_810; + return 0; + } else if (arfcn >= 438 && arfcn <= 511) { + *band = GSM_BAND_750; + return 0; + } + return -1; +} + +/*! Resolve GSM band from ARFCN, aborts process on invalid ARFCN. + * In Osmocom, we use the highest bit of the \a arfcn to indicate PCS. + * DEPRECATED: Use gsm_arfcn2band_rc instead. + * \param[in] arfcn Osmocom ARFCN, highest bit determines PCS mode + * \returns GSM Band if ARFCN is valid (part of any valid band), aborts otherwise */ +enum gsm_band gsm_arfcn2band(uint16_t arfcn) +{ + enum gsm_band band; + if (gsm_arfcn2band_rc(arfcn, &band) == 0) + return band; + + osmo_panic("%s:%d Invalid arfcn %" PRIu16 " passed to gsm_arfcn2band\n", + __FILE__, __LINE__, arfcn); } struct gsm_freq_range { diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 217dcc39..3fe9dfcf 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -349,6 +349,7 @@ gsm_7bit_decode_n_hdr; gsm_7bit_encode_n; gsm_7bit_encode_n_ussd; +gsm_arfcn2band_rc; gsm_arfcn2band; gsm_arfcn2freq10; gsm_freq102arfcn; diff --git a/utils/osmo-arfcn.c b/utils/osmo-arfcn.c index 61108f8d..aee132c7 100644 --- a/utils/osmo-arfcn.c +++ b/utils/osmo-arfcn.c @@ -62,6 +62,7 @@ static int arfcn2freq(int arfcn) static int freq2arfcn(int freq10, int uplink) { uint16_t arfcn; + enum gsm_band band; if (uplink != 0 && uplink != 1) { fprintf(stderr, "Need to specify uplink or downlink\n"); @@ -75,8 +76,13 @@ static int freq2arfcn(int freq10, int uplink) return -EINVAL; } + if (gsm_arfcn2band_rc(arfcn, &band) < 0) { + fprintf(stderr, "ARFCN contains no valid band\n"); + return -EINVAL; + } + printf("%s: ARFCN %4d\n", - gsm_band_name(gsm_arfcn2band(arfcn)), + gsm_band_name(band), arfcn & ~ARFCN_FLAG_MASK); return 0; } -- cgit v1.2.3 From 49c06680e762cdf751ae592449985e2c65687248 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 21 Nov 2018 22:10:26 +0100 Subject: Update gsm0808_create_ass() doxygen * add spec reference * remove LCLS note: CI parameter is optional but have nothing to do with LCLS It's pretty hard to decipher from the spec what CI is useful for and we have not used it anyway so let's just keep it as "Optional" for now. Change-Id: I5552732afcec48047d993ae6ffb73a3e5d7c9202 --- src/gsm/gsm0808.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index a84e717d..fe7bc2ca 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -424,12 +424,12 @@ struct msgb *gsm0808_create_sapi_reject(uint8_t link_id) return msg; } -/*! Create BSSMAP Assignment Request message +/*! Create BSSMAP Assignment Request message, 3GPP TS 48.008 §3.2.1.1 * \param[in] ct Channel Type * \param[in] cic Circuit Identity Code (Classic A only) * \param[in] ss Socket Address of MSC-side RTP socket (AoIP only) * \param[in] scl Speech Codec List (AoIP only) - * \param[in] ci Call Identifier (Optional, LCLS) + * \param[in] ci Call Identifier (Optional), §3.2.2.105 * \returns callee-allocated msgb with BSSMAP Assignment Request message */ struct msgb *gsm0808_create_ass(const struct gsm0808_channel_type *ct, const uint16_t *cic, -- cgit v1.2.3 From 7ab5fc1f3b373fadc644448442b985c12597f8f0 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Thu, 15 Nov 2018 23:29:56 +0100 Subject: add contrib/struct_endianess.py In libosmocore (and likely elsewhere) we have scores of packed structs with sub-byte integer members that lack the necessary member reversal shims to be able to work on big endian architectures. Instead of manually editing each one of them and probably introduce errors in the process, this script handles the change automatically, and in the future allows us to verify correctness in gerrit verifications. Change-Id: I8e75b17d8071c7b3a2a171ba776fb76854b28a53 --- contrib/struct_endianess.py | 369 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100755 contrib/struct_endianess.py diff --git a/contrib/struct_endianess.py b/contrib/struct_endianess.py new file mode 100755 index 00000000..be73fbe2 --- /dev/null +++ b/contrib/struct_endianess.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python3 + +'''Using mad regexes, automatically make sure that all structs with sub-byte +integers have matching big-endian definitions. The idea is to save a lot of +manual effort, and to automatically verify that there are no errors. +This script most certainly has numerous holes and shortcomings, but actually, +if you hit problems with it, rather adjust your coding style so that this +script can deal with it...''' + +import re +import sys +import codecs +import os.path + +re_struct_start = re.compile(r'^struct\s*[a-zA-Z_][a-zA-Z_0-9]*\s*{\s*$') +re_struct_end = re.compile(r'^}[^;]*;\s*$') + +re_substruct_start = re.compile(r'^\s+struct\s*{\s*$') +re_substruct_end = re.compile(r'^\s+}\s*([^;]*\s)[a-zA-Z_][a-zA-Z_0-9]*\s*;\s*$') + +re_int_def = re.compile(r'(^\s*((const|unsigned|signed|char|int|long|int[0-9]+_t|uint[0-9]_t)\s+)+\s*)([^;]*;)', + re.DOTALL | re.MULTILINE) +re_int_members = re.compile(r'([a-zA-Z_][a-zA-Z_0-9]*|[a-zA-Z_][a-zA-Z_0-9]*\s*:\s*[0-9]+)\s*[,;]\s*', re.DOTALL | re.MULTILINE) + +re_little_endian_ifdef = re.compile(r'#\s*(if|elif)\s+OSMO_IS_LITTLE_ENDIAN\s*(==\s*1\s*|)'); +re_big_endian_ifdef = re.compile(r'#\s*(if|elif)\s+OSMO_IS_BIG_ENDIAN\s*'); +re_else = re.compile(r'#\s*else\s*'); +re_endif = re.compile(r'#\s*endif\s*'); + +re_c_comment = re.compile(r'(/\*[^*]+\*/|//.?$)') + +def remove_c_comments(code_str): + return ''.join(re_c_comment.split(code_str)[::2]) + +def section_struct_body(struct_body_lines): + '''divide a top-level-struct body into sections of + ['arbitrary string', ['body;\n', 'lines;\n'], 'arbitrary string', ...] + Aim: handle each sub-struct on its own, and if there already are ifdefs for + little and big endian, keep just the little endian bit and derive big + endian from it. + An arbitrary string is anything other than struct member definitions, like + a 'struct {', '} sub_name;', ... + "body lines" are lines that define struct members (possibly with comments). + Return: list of alternate arbitrary strings and variable definitions. + ''' + + # these globals are needed so that end_def() can change them from inside + # the function. Not very nice style, but easiest implementation. + global struct_body_parts + global arbitrary_part + global def_part + + struct_body_parts = [] + arbitrary_part = [] + def_part = [] + + def end_def(): + '''if there is any content, flush out recorded parts (def_part, + arbitrary_part) and start a new part. In short, cut a section + boundary.''' + global struct_body_parts + global arbitrary_part + global def_part + + if def_part: + struct_body_parts.append(arbitrary_part) + arbitrary_part = [] + struct_body_parts.append(def_part) + def_part = [] + + j = 0 + while j < len(struct_body_lines): + line = struct_body_lines[j] + + if (re_substruct_start.fullmatch(line) + or re_substruct_end.fullmatch(line)): + end_def() + arbitrary_part.append(line) + j += 1 + continue + + if re_big_endian_ifdef.fullmatch(line): + end_def() + # discard big endian section + j += 1 + while j < len(struct_body_lines): + line = struct_body_lines[j] + if re_endif.fullmatch(line): + end_def() + j += 1 + break; + if re_little_endian_ifdef.fullmatch(line): + end_def() + # keep that start of little endian section, not j++ + break; + if re_else.fullmatch(line): + # there's an '#else' after big-endian. Shim a little-endian header in just for the loop. + struct_body_lines[j] = '#if OSMO_IS_LITTLE_ENDIAN\n' + break; + j += 1 + continue + + if re_little_endian_ifdef.fullmatch(line): + end_def() + j += 1 + while j < len(struct_body_lines): + line = struct_body_lines[j] + if re_endif.fullmatch(line): + end_def() + j += 1 + break; + if re_big_endian_ifdef.fullmatch(line): + end_def() + # keep that start of big endian section, not j++ + break; + if re_else.fullmatch(line): + # there's an '#else' after little-endian. Shim a big-endian header in just for the loop. + struct_body_lines[j] = '#if OSMO_IS_BIG_ENDIAN\n' + break; + def_part.append(line) + j += 1 + + continue + + def_part.append(line) + j += 1 + + # flush the last section remaining that didn't see an explicit end + end_def() + # end_def() only flushes arbitrary_part if there was a def_part, so: + if arbitrary_part: + struct_body_parts.append(arbitrary_part) + + return struct_body_parts + +def struct_body_to_big_endian(body_str): + '''Input: a multi-line string containing the body of a struct, i.e. without + sub-structs and without #if OSMO_IS_BIG_ENDIAN. like + + '\tconst char *foo;\n\tuint8_t moo:3, goo:2;\n\tuint8_t loo:3;\n\tvoid *baz;\n' + + Return None to indicate that there is no little/big endian split + required, or return a multi-line string of the big-endian version of this + same struct body, where sub-byte ints are reversed at byte boundaries, and + all others are copied 1:1. If there are no sub-byte integers, return None, + to indicate that there is no little/big endian split required.''' + + # kick comments out of the code analysis. They will end up being stripped + # from big-endian only. + body_str = remove_c_comments(body_str) + + def_strs = body_str.split(';') + def_strs = ('%s;' % def_str for def_str in def_strs if def_str.strip()) + + # classify defs as containing sub-byte members or not + # defs = [ (true, 'uint8_t ', ('foo:3', 'bar:5')), + # (false, 'int baz;'),...] + defs = [] + any_sub_byte_ints = False + for one_def in def_strs: + + # does it have sub-string integers? + int_def = re_int_def.fullmatch(one_def) + if not int_def: + # not even a number, same for big and little endian + defs.append((False, one_def)) + continue + + int_type = int_def.group(1) + members_str = int_def.groups()[-1] + has_sub_byte_ints = False + + members = [] + for int_member in re_int_members.finditer(members_str): + member = int_member.group(1) + members.append(member) + if ':' in member: + has_sub_byte_ints = True + + if not has_sub_byte_ints: + defs.append((False, one_def)) + else: + defs.append((True, one_def, int_type, members)) + any_sub_byte_ints = True + + if not any_sub_byte_ints: + return None + + # now the interesting part, go over the defs, and reverse the sub-byte ints + # at byte boundaries. + + i = 0 + got_bits = 0 + byte_type = None + members_within_a_byte = [] + big_endian_defs = [] + + big_defs = [] + for classified_def in defs: + has_sub_byte_ints = classified_def[0] + + # now the big endian part + if has_sub_byte_ints: + _, one_def, int_type, members = classified_def + + if byte_type and byte_type.strip() != int_type.strip(): + raise Exception('mismatching type continuation after incomplete byte: %r %r to %r' + % (byte_type, members_within_a_byte, int_type)) + byte_type = int_type + + for member in members: + member_name, bits_str = member.split(':') + member_name = member_name.strip() + bits = int(bits_str) + member = '%s:%d' % (member_name, bits) + members_within_a_byte.append(member) + got_bits += bits + + if got_bits == 8: + # reverse these. + big_endian_defs.append('%s%s;' % (byte_type, ', '.join(reversed(members_within_a_byte)))) + members_within_a_byte = [] + byte_type = None + got_bits = 0 + + elif got_bits > 8: + raise Exception('sub-byte int breaks clean byte bounds: %s -- %d + %d = %d bits' + % (member, got_bits - bits, bits, got_bits)) + + elif not has_sub_byte_ints: + if got_bits: + raise Exception('sub-byte members do not add up to clean byte bounds: %r' % members_within_a_byte) + + big_endian_defs.append(classified_def[1]) + + # strip empty lines + lines = [l for l in (''.join(big_endian_defs).split('\n')) if l.strip()] + # clean lines' whitespace errors we might have taken in with the type names + for i in range(len(lines)): + line = lines[i] + while len(line) and line[-1] in ' \t': + line = line[:-1] + lines[i] = line + return '\n'.join(lines) + +def handle_struct_body(body_str): + + big_endian_body_str = struct_body_to_big_endian(body_str) + + if big_endian_body_str: + new_lines = ['#if OSMO_IS_LITTLE_ENDIAN\n'] + new_lines.append(body_str) + new_lines.append('#elif OSMO_IS_BIG_ENDIAN\n' + '/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */\n') + new_lines.append(big_endian_body_str) + new_lines.append('\n#endif\n') + return ''.join(new_lines) + else: + return body_str + +def _check_file(f): + if not (f.endswith('.h') or f.endswith('.c') or f.endswith('.cpp')): + return + + # section the file into + # [ ["no struct def"], ["struct {...};"], ["no struct def"], ... ] + sections = [] + in_struct = False + buf = [] + for line in codecs.open(f, "r", "utf-8").readlines(): + + if not in_struct and re_struct_start.fullmatch(line): + # flush whatever might still be in buf from before + sections.append(buf) + # start an in_struct section + buf = [line] + in_struct = True + elif in_struct and re_struct_end.fullmatch(line): + # add this end to the in_struct section and then start a non-struct section + buf.append(line) + sections.append(buf) + in_struct = False + buf = [] + else: + buf.append(line) + # flush any leftovers in buf + if buf: + sections.append(buf) + + # examine each struct, i.e. every second item in 'sections' + for i in range(len(sections)): + if not (i & 1): + continue + + struct = sections[i] + + # If the struct isn't packed, we need not bother. + # The practical use of this: in some structs we have booleans in the + # form of + # integer flag:1; + # and these don't add up to bytes, and cause errors. So let's skip all + # non-packed structs, then all of those are out of the picture. + if not 'packed' in struct[-1]: + continue + + try: + + # assume the 'struct foo {' is on the first line, the closing brace + # '} __attribute...;' on the last, and the rest are individual + # definitions split by ';'. + struct_body_lines = struct[1:-1] + struct_body_parts = section_struct_body(struct_body_lines) + + new_struct_body_parts = [] + for j in range(len(struct_body_parts)): + part = ''.join(struct_body_parts[j]) + if not (j & 1): + new_struct_body_parts.append(part) + else: + new_struct_body_parts.append(handle_struct_body(part)) + + new_struct = [struct[0], ''.join(new_struct_body_parts), struct[-1]] + sections[i] = new_struct + except Exception as e: + raise Exception('ERROR in struct %r' % struct[0]) + + # phew. result. + result = ''.join((''.join(s) for s in sections)) + + # see if osmocom/core/endian.h is needed and included. + if (not f.endswith('endian.h') + and 'OSMO_IS_LITTLE_ENDIAN' in result + and '#include ' not in result): + # add the include after the last 'osmocom/core' include + last_include_start = result.rfind('#include ' + result[insert_at:] + + with codecs.open(f, "w", "utf-8") as fd: + fd.write(result) + +def check_file(f): + try: + _check_file(f) + except Exception as e: + raise Exception('ERROR IN FILE %r' % f) + +args = sys.argv[1:] +if not args: + args = ['.'] + +for f in args: + if os.path.isdir(f): + for parent_path, subdirs, files in os.walk(f, None, None): + for ff in files: + check_file(os.path.join(parent_path, ff)) + else: + check_file(f) + +# vim: tabstop=4 shiftwidth=4 expandtab -- cgit v1.2.3