From 4a62eda225ab7f3c9556990c81a6fc5e19b5eec8 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 18 Mar 2019 18:27:00 +0100 Subject: Add _buf() functions to bypass static string buffers We have a number of static buffers in use in libosmo*. This means the related functions are not usable in a thread-safe way. While we so far don't have many multi-threaded programs in the osmocom universe, the static buffers also prevent us from calling the same e.g. string-ify function twice within a single printf() call. Let's make sure there's an alternative function in all those cases, where the user can pass in a caller-allocated buffer + size, and make the 'classic' function with the static buffer a wrapper around that _buf() variant. Change-Id: Ibf85f79e93244f53b2684ff6f1095c5b41203e05 --- src/gsm/abis_nm.c | 13 +++++-- src/gsm/apn.c | 27 +++++++++---- src/gsm/gsm0808_utils.c | 40 +++++++++++++++---- src/gsm/gsm23003.c | 101 +++++++++++++++++++++++++++++++++++++++--------- src/gsm/gsm48.c | 92 ++++++++++++++++++++++++++++++++----------- src/gsm/gsm_utils.c | 13 +++++-- src/gsm/libosmogsm.map | 18 +++++++++ src/gsm/rsl.c | 40 ++++++++++++------- 8 files changed, 267 insertions(+), 77 deletions(-) (limited to 'src/gsm') diff --git a/src/gsm/abis_nm.c b/src/gsm/abis_nm.c index 49d05ba5..e25fdd03 100644 --- a/src/gsm/abis_nm.c +++ b/src/gsm/abis_nm.c @@ -928,14 +928,19 @@ enum gsm_phys_chan_config abis_nm_pchan4chcomb(uint8_t chcomb) return GSM_PCHAN_NONE; } -const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh) +char *abis_nm_dump_foh_buf(char *buf, size_t buf_len, const struct abis_om_fom_hdr *foh) { - static char foh_buf[128]; - snprintf(foh_buf, sizeof(foh_buf), "OC=%s(%02x) INST=(%02x,%02x,%02x)", + snprintf(buf, buf_len, "OC=%s(%02x) INST=(%02x,%02x,%02x)", get_value_string(abis_nm_obj_class_names, foh->obj_class), foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr, foh->obj_inst.ts_nr); - return foh_buf; + return buf; +} + +const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh) +{ + static char foh_buf[128]; + return abis_nm_dump_foh_buf(foh_buf, sizeof(foh_buf), foh); } /* this is just for compatibility reasons, it is now a macro */ diff --git a/src/gsm/apn.c b/src/gsm/apn.c index 26746631..4ab370c5 100644 --- a/src/gsm/apn.c +++ b/src/gsm/apn.c @@ -32,17 +32,22 @@ static char apn_strbuf[APN_MAXLEN+1]; -char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni) +char *osmo_apn_qualify_buf(char *buf, size_t buf_len, unsigned int mcc, unsigned int mnc, const char *ni) { - snprintf(apn_strbuf, sizeof(apn_strbuf)-1, APN_GPRS_FMT, - ni, mnc, mcc); - apn_strbuf[sizeof(apn_strbuf)-1] = '\0'; + snprintf(buf, buf_len-1, APN_GPRS_FMT, ni, mnc, mcc); + buf[buf_len-1] = '\0'; - return apn_strbuf; + return buf; } -char *osmo_apn_qualify_from_imsi(const char *imsi, - const char *ni, int have_3dig_mnc) +char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni) +{ + return osmo_apn_qualify_buf(apn_strbuf, sizeof(apn_strbuf), mcc, mnc, ni); +} + + +char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi, + const char *ni, int have_3dig_mnc) { char cbuf[3+1], nbuf[3+1]; @@ -56,7 +61,13 @@ char *osmo_apn_qualify_from_imsi(const char *imsi, strncpy(nbuf, imsi+3, 2); nbuf[2] = '\0'; } - return osmo_apn_qualify(atoi(cbuf), atoi(nbuf), ni); + return osmo_apn_qualify_buf(buf, buf_len, atoi(cbuf), atoi(nbuf), ni); +} + +char *osmo_apn_qualify_from_imsi(const char *imsi, + const char *ni, int have_3dig_mnc) +{ + return osmo_apn_qualify_from_imsi_buf(apn_strbuf, sizeof(apn_strbuf), imsi, ni, have_3dig_mnc); } /** diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index e0cdaaf6..52e46743 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -595,11 +595,13 @@ int gsm0808_dec_lcls(struct osmo_lcls *lcls, const struct tlv_parsed *tp) static char dbuf[256]; /*! Dump LCLS parameters (GCR excluded) into string for printing. + * \param[out] buf caller-allocated output string buffer + * \param[in] buf_len size of buf in bytes * \param[in] lcls pointer to the struct to print. * \returns string representation of LCLS or NULL on error. */ -char *osmo_lcls_dump(const struct osmo_lcls *lcls) +char *osmo_lcls_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls) { - struct osmo_strbuf s = { .buf = dbuf, .len = 256 }; + struct osmo_strbuf s = { .buf = buf, .len = buf_len }; if (!lcls) return NULL; @@ -612,12 +614,22 @@ char *osmo_lcls_dump(const struct osmo_lcls *lcls) return dbuf; } +/*! Dump LCLS parameters (GCR excluded) into static string buffer for printing. + * \param[in] lcls pointer to the struct to print. + * \returns string representation of LCLS in static buffer or NULL on error. */ +char *osmo_lcls_dump(const struct osmo_lcls *lcls) +{ + return osmo_lcls_dump_buf(dbuf, sizeof(dbuf), lcls); +} + /*! Dump GCR struct into string for printing. + * \param[out] buf caller-allocated output string buffer + * \param[in] buf_len size of buf in bytes * \param[in] lcls pointer to the struct to print. * \returns string representation of GCR or NULL on error. */ -char *osmo_gcr_dump(const struct osmo_lcls *lcls) +char *osmo_gcr_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls) { - struct osmo_strbuf s = { .buf = dbuf, .len = 256 }; + struct osmo_strbuf s = { .buf = buf, .len = buf_len }; if (!lcls) return NULL; @@ -631,6 +643,15 @@ char *osmo_gcr_dump(const struct osmo_lcls *lcls) return dbuf; } +/*! Dump GCR struct into static string buffer for printing. + * \param[in] lcls pointer to the struct to print. + * \returns string representation of GCR in static buffer or NULL on error. */ +char *osmo_gcr_dump(const struct osmo_lcls *lcls) +{ + return osmo_gcr_dump_buf(dbuf, sizeof(dbuf), lcls); +} + + /*! Encode TS 08.08 Encryption Information IE * \param[out] msg Message Buffer to which IE is to be appended * \param[in] ei Encryption Information to be encoded @@ -1838,13 +1859,18 @@ const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil) #undef APPEND_STR #undef APPEND_CELL_ID_U -const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct) +char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct) { - static char buf[128]; - snprintf(buf, sizeof(buf), "ch_indctr=0x%x ch_rate_type=0x%x perm_spch=%s", + snprintf(buf, buf_len, "ch_indctr=0x%x ch_rate_type=0x%x perm_spch=%s", ct->ch_indctr, ct->ch_rate_type, osmo_hexdump(ct->perm_spch, ct->perm_spch_len)); return buf; } +const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct) +{ + static char buf[128]; + return gsm0808_channel_type_name_buf(buf, sizeof(buf), ct); +} + /*! @} */ diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c index 720c09b6..bbfe236a 100644 --- a/src/gsm/gsm23003.c +++ b/src/gsm/gsm23003.c @@ -89,6 +89,18 @@ bool osmo_imei_str_valid(const char *imei, bool with_15th_digit) return is_n_digits(imei, 14, 14); } +/*! Return MCC string as standardized 3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] mcc MCC value. + * \returns string in user-supplied output buffer + */ +char *osmo_mcc_name_buf(char *buf, size_t buf_len, uint16_t mcc) +{ + snprintf(buf, buf_len, "%03u", mcc); + return buf; +} + /*! Return MCC string as standardized 3-digit with leading zeros. * \param[in] mcc MCC value. * \returns string in static buffer. @@ -96,7 +108,19 @@ bool osmo_imei_str_valid(const char *imei, bool with_15th_digit) const char *osmo_mcc_name(uint16_t mcc) { static char buf[8]; - snprintf(buf, sizeof(buf), "%03u", mcc); + return osmo_mcc_name_buf(buf, sizeof(buf), mcc); +} + +/*! Return MNC string as standardized 2- or 3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] mnc MNC value. + * \param[in] mnc_3_digits True if an MNC should fill three digits, only has an effect if MNC < 100. + * \returns string in static buffer. + */ +char *osmo_mnc_name_buf(char *buf, size_t buf_len, uint16_t mnc, bool mnc_3_digits) +{ + snprintf(buf, buf_len, "%0*u", mnc_3_digits ? 3 : 2, mnc); return buf; } @@ -108,14 +132,21 @@ const char *osmo_mcc_name(uint16_t mcc) const char *osmo_mnc_name(uint16_t mnc, bool mnc_3_digits) { static char buf[8]; - snprintf(buf, sizeof(buf), "%0*u", mnc_3_digits ? 3 : 2, mnc); - return buf; + return osmo_mnc_name_buf(buf, sizeof(buf), mnc, mnc_3_digits); } -static inline void plmn_name(char *buf, size_t buflen, const struct osmo_plmn_id *plmn) +/*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] plmn MCC-MNC value. + * \returns string in static buffer. + */ +char *osmo_plmn_name_buf(char *buf, size_t buf_len, const struct osmo_plmn_id *plmn) { - snprintf(buf, buflen, "%s-%s", osmo_mcc_name(plmn->mcc), - osmo_mnc_name(plmn->mnc, plmn->mnc_3_digits)); + char mcc[8], mnc[8]; + snprintf(buf, buf_len, "%s-%s", osmo_mcc_name_buf(mcc, sizeof(mcc), plmn->mcc), + osmo_mnc_name_buf(mnc, sizeof(mnc), plmn->mnc, plmn->mnc_3_digits)); + return buf; } /*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros. @@ -125,10 +156,10 @@ static inline void plmn_name(char *buf, size_t buflen, const struct osmo_plmn_id const char *osmo_plmn_name(const struct osmo_plmn_id *plmn) { static char buf[16]; - plmn_name(buf, sizeof(buf), plmn); - return buf; + return osmo_plmn_name_buf(buf, sizeof(buf), plmn); } + /*! Same as osmo_plmn_name(), but returning in a different static buffer. * \param[in] plmn MCC-MNC value. * \returns string in static buffer. @@ -136,7 +167,19 @@ const char *osmo_plmn_name(const struct osmo_plmn_id *plmn) const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn) { static char buf[16]; - plmn_name(buf, sizeof(buf), plmn); + return osmo_plmn_name_buf(buf, sizeof(buf), plmn); +} + +/*! Return MCC-MNC-LAC as string, in caller-provided output buffer. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] lai LAI to encode, the rac member is ignored. + * \returns buf + */ +char *osmo_lai_name_buf(char *buf, size_t buf_len, const struct osmo_location_area_id *lai) +{ + char plmn[16]; + snprintf(buf, buf_len, "%s-%u", osmo_plmn_name_buf(plmn, sizeof(plmn), &lai->plmn), lai->lac); return buf; } @@ -147,13 +190,18 @@ const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn) const char *osmo_lai_name(const struct osmo_location_area_id *lai) { static char buf[32]; - snprintf(buf, sizeof(buf), "%s-%u", osmo_plmn_name(&lai->plmn), lai->lac); - return buf; + return osmo_lai_name_buf(buf, sizeof(buf), lai); } -static const char *_cgi_name(const struct osmo_cell_global_id *cgi, char *buf, size_t buflen) +/*! Return MCC-MNC-LAC-CI as string, in caller-provided output buffer. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] cgi CGI to encode. + * \returns buf + */ +char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi) { - snprintf(buf, buflen, "%s-%u", osmo_lai_name(&cgi->lai), cgi->cell_identity); + snprintf(buf, buf_len, "%s-%u", osmo_lai_name(&cgi->lai), cgi->cell_identity); return buf; } @@ -164,7 +212,7 @@ static const char *_cgi_name(const struct osmo_cell_global_id *cgi, char *buf, s const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi) { static char buf[32]; - return _cgi_name(cgi, buf, sizeof(buf)); + return osmo_cgi_name_buf(buf, sizeof(buf), cgi); } /*! Same as osmo_cgi_name(), but uses a different static buffer. @@ -175,7 +223,7 @@ const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi) const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi) { static char buf[32]; - return _cgi_name(cgi, buf, sizeof(buf)); + return osmo_cgi_name_buf(buf, sizeof(buf), cgi); } static void to_bcd(uint8_t *bcd, uint16_t val) @@ -187,14 +235,31 @@ static void to_bcd(uint8_t *bcd, uint16_t val) bcd[0] = val % 10; } -const char *osmo_gummei_name(const struct osmo_gummei *gummei) +/*! Return string representation of GUMMEI in caller-provided output buffer. + * \param[out] buf pointer to caller-provided output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] gummei GUMMEI to be stringified + * \returns buf + */ +char *osmo_gummei_name_buf(char *buf, size_t buf_len, const struct osmo_gummei *gummei) { - static char buf[32]; - snprintf(buf, sizeof(buf), "%s-%04x-%02x", osmo_plmn_name(&gummei->plmn), + char plmn[16]; + snprintf(buf, buf_len, "%s-%04x-%02x", osmo_plmn_name_buf(plmn, sizeof(plmn), &gummei->plmn), gummei->mme.group_id, gummei->mme.code); return buf; } +/*! Return string representation of GUMMEI in static output buffer. + * \param[in] gummei GUMMEI to be stringified + * \returns pointer to static output buffer + */ +const char *osmo_gummei_name(const struct osmo_gummei *gummei) +{ + static char buf[32]; + return osmo_gummei_name_buf(buf, sizeof(buf), gummei); +} + + /* Convert MCC + MNC to BCD representation * \param[out] bcd_dst caller-allocated memory for output * \param[in] mcc Mobile Country Code diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index 5dc30ad0..a45d67bc 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -182,6 +182,20 @@ const char *rr_cause_name(uint8_t cause) return get_value_string(rr_cause_names, cause); } +/*! Return MCC-MNC-LAC-RAC as string, in a caller-provided output buffer. + * \param[out] buf caller-provided output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] rai RAI to encode. + * \returns buf + */ +char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai) +{ + snprintf(buf, buf_len, "%s-%s-%u-%u", + osmo_mcc_name(rai->mcc), osmo_mnc_name(rai->mnc, rai->mnc_3_digits), rai->lac, + rai->rac); + return buf; +} + /*! Return MCC-MNC-LAC-RAC as string, in a static buffer. * \param[in] rai RAI to encode. * \returns Static string buffer. @@ -189,10 +203,7 @@ const char *rr_cause_name(uint8_t cause) const char *osmo_rai_name(const struct gprs_ra_id *rai) { static char buf[32]; - snprintf(buf, sizeof(buf), "%s-%s-%u-%u", - osmo_mcc_name(rai->mcc), osmo_mnc_name(rai->mnc, rai->mnc_3_digits), rai->lac, - rai->rac); - return buf; + return osmo_rai_name_buf(buf, sizeof(buf), rai); } /* FIXME: convert to value_string */ @@ -433,14 +444,15 @@ const char *gsm48_mi_type_name(uint8_t mi) return get_value_string(mi_type_names, mi); } -/*! Return a human readable representation of a Mobile Identity in static buffer. +/*! Return a human readable representation of a Mobile Identity in caller-provided buffer. + * \param[out] buf caller-provided output buffer + * \param[in] buf_len size of buf in bytes * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. * \param[in] mi_len Length of mi. - * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid"... + * \return buf */ -const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) +char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len) { - static char mi_name[10 + GSM48_MI_SIZE + 1]; uint8_t mi_type; uint32_t tmsi; char mi_string[GSM48_MI_SIZE]; @@ -452,8 +464,8 @@ const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { tmsi = osmo_load32be(&mi[1]); - snprintf(mi_name, sizeof(mi_name), "TMSI-0x%08" PRIX32, tmsi); - return mi_name; + snprintf(buf, buf_len, "TMSI-0x%08" PRIX32, tmsi); + return buf; } return "TMSI-invalid"; @@ -461,14 +473,25 @@ const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) case GSM_MI_TYPE_IMEI: case GSM_MI_TYPE_IMEISV: osmo_bcd2str(mi_string, sizeof(mi_string), mi, 1, (mi_len * 2) - (mi[0] & GSM_MI_ODD ? 0 : 1), true); - snprintf(mi_name, sizeof(mi_name), "%s-%s", gsm48_mi_type_name(mi_type), mi_string); - return mi_name; + snprintf(buf, buf_len, "%s-%s", gsm48_mi_type_name(mi_type), mi_string); + return buf; default: return "unknown"; } } +/*! Return a human readable representation of a Mobile Identity in static buffer. + * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. + * \param[in] mi_len Length of mi. + * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid"... + */ +const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) +{ + static char mi_name[10 + GSM48_MI_SIZE + 1]; + return osmo_mi_name_buf(mi_name, sizeof(mi_name), mi, mi_len); +} + /*! Checks is particular message is cipherable in A/Gb mode according to * 3GPP TS 24.008 ยง 4.7.1.2 * \param[in] hdr Message header @@ -1050,16 +1073,17 @@ const struct value_string gsm48_nc_ss_msgtype_names[] = { { 0, NULL } }; -/*! Compose a string naming the message type for given protocol. +/*! Compose a string naming the message type for given protocol, in a caller-provided buffer. * If the message type string is known, return the message type name, otherwise * return ":". + * \param[out] buf caller-allcated output string buffer + * \param[in] buf_len size of buf in bytes * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST - * \returns statically allocated string or string constant. + * \returns buf */ -const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type) +char *gsm48_pdisc_msgtype_name_buf(char *buf, size_t buf_len, uint8_t pdisc, uint8_t msg_type) { - static char namebuf[64]; const struct value_string *msgt_names; switch (pdisc) { @@ -1081,11 +1105,23 @@ const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type) } if (msgt_names) - return get_value_string(msgt_names, msg_type); + snprintf(buf, buf_len, "%s", get_value_string(msgt_names, msg_type)); + else + snprintf(buf, buf_len, "%s:0x%02x", gsm48_pdisc_name(pdisc), msg_type); + return buf; +} - snprintf(namebuf, sizeof(namebuf), "%s:0x%02x", - gsm48_pdisc_name(pdisc), msg_type); - return namebuf; +/*! Compose a string naming the message type for given protocol, in a static buffer. + * If the message type string is known, return the message type name, otherwise + * return ":". + * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM + * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST + * \returns statically allocated string or string constant. + */ +const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type) +{ + static char namebuf[64]; + return gsm48_pdisc_msgtype_name_buf(namebuf, sizeof(namebuf), pdisc, msg_type); } const struct value_string gsm48_reject_value_names[] = { @@ -1187,9 +1223,8 @@ bool osmo_gsm48_classmark_is_r99(const struct osmo_gsm48_classmark *cm) * \param[in] cm Classmarks. * \returns A statically allocated string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3" */ -const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm) +char *osmo_gsm48_classmark_a5_name_buf(char *buf, size_t buf_len, const struct osmo_gsm48_classmark *cm) { - static char buf[128]; char cm1[42] = "no-cm1"; char cm2[42] = " no-cm2"; char cm3[42] = " no-cm3"; @@ -1212,10 +1247,21 @@ const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm) cm->classmark3[0] & (1 << 2) ? " A5/6" : "", cm->classmark3[0] & (1 << 3) ? " A5/7" : ""); - snprintf(buf, sizeof(buf), "%s%s%s", cm1, cm2, cm3); + snprintf(buf, buf_len, "%s%s%s", cm1, cm2, cm3); return buf; } +/*! Return a string representation of A5 cipher algorithms indicated by Classmark 1, 2 and 3. + * \param[in] cm Classmarks. + * \returns A statically allocated string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3" + */ +const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm) +{ + static char buf[128]; + return osmo_gsm48_classmark_a5_name_buf(buf, sizeof(buf), cm); +} + + /*! Overwrite dst with the Classmark information present in src. * Add an new Classmark and overwrite in dst what src has to offer, but where src has no Classmark information, leave * dst unchanged. (For Classmark 2 and 3, dst will exactly match any non-zero Classmark length from src, hence may end diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index c9c15d57..f34d9ea5 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -886,16 +886,21 @@ uint32_t gsm_gsmtime2fn(struct gsm_time *time) return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1)); } -char *osmo_dump_gsmtime(const struct gsm_time *tm) +char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm) { - static char buf[64]; - - snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8, + snprintf(buf, buf_len, "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8, tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52); buf[sizeof(buf)-1] = '\0'; return buf; } +char *osmo_dump_gsmtime(const struct gsm_time *tm) +{ + static char buf[64]; + return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm); +} + + /*! append range1024 encoded data to bit vector * \param[out] bv Caller-provided output bit-vector * \param[in] r Input Range1024 sructure */ diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3fadc5a0..a69fb606 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -9,6 +9,7 @@ abis_nm_fail_evt_vrep; abis_nm_chcomb4pchan; abis_nm_debugp_foh; abis_nm_dump_foh; +abis_nm_dump_foh_buf; abis_nm_event_type_name; abis_nm_nack_cause_name; abis_nm_nack_name; @@ -225,6 +226,7 @@ gsm0808_speech_codec_type_names; gsm0808_permitted_speech_names; gsm0808_chosen_enc_alg_names; gsm0808_channel_type_name; +gsm0808_channel_type_name_buf; gsm0808_lcls_config_names; gsm0808_lcls_control_names; gsm0808_lcls_status_names; @@ -250,7 +252,9 @@ osmo_enc_gcr; osmo_dec_gcr; osmo_gcr_eq; osmo_gcr_dump; +osmo_gcr_dump_buf; osmo_lcls_dump; +osmo_lcls_dump_buf; gsm0858_rsl_ul_meas_enc; @@ -345,6 +349,7 @@ gsm48_set_dtx; gsm48_dtx_mode; gsm48_mi_type_name; osmo_mi_name; +osmo_mi_name_buf; gsm48_mcc_mnc_to_bcd; gsm48_mcc_mnc_from_bcd; gsm48_generate_lai2; @@ -354,14 +359,21 @@ osmo_bts_feature_name; osmo_plmn_to_bcd; osmo_plmn_from_bcd; osmo_mcc_name; +osmo_mcc_name_buf; osmo_mnc_name; +osmo_mnc_name_buf; osmo_plmn_name; +osmo_plmn_name_buf; osmo_plmn_name2; osmo_lai_name; +osmo_lai_name_buf; osmo_rai_name; +osmo_rai_name_buf; osmo_cgi_name; +osmo_cgi_name_buf; osmo_cgi_name2; osmo_gummei_name; +osmo_gummei_name_buf; osmo_mnc_from_str; osmo_mnc_cmp; osmo_plmn_cmp; @@ -378,6 +390,7 @@ gsm48_mm_msgtype_names; gsm48_cc_msgtype_names; gsm48_cc_cause_names; gsm48_pdisc_msgtype_name; +gsm48_pdisc_msgtype_name_buf; gsm48_reject_value_names; gsm_7bit_decode; @@ -403,6 +416,7 @@ gsm_fn_as_gsmtime_str; gsm_get_octet_len; gsm_gsmtime2fn; osmo_dump_gsmtime; +osmo_dump_gsmtime_buf; gsm_milenage; gsm_septet_encode; @@ -472,6 +486,7 @@ rsl_ipac_eie_tlvdef; rsl_ccch_conf_to_bs_cc_chans; rsl_ccch_conf_to_bs_ccch_sdcch_comb; rsl_chan_nr_str; +rsl_chan_nr_str_buf; rsl_dec_chan_nr; rsl_enc_chan_nr; rsl_err_name; @@ -533,7 +548,9 @@ ipa_prepend_header_ext; ipa_send; osmo_apn_qualify; +osmo_apn_qualify_buf; osmo_apn_qualify_from_imsi; +osmo_apn_qualify_from_imsi_buf; osmo_apn_to_str; osmo_apn_from_str; @@ -592,6 +609,7 @@ osmo_gsm48_classmark1_is_r99; osmo_gsm48_classmark2_is_r99; osmo_gsm48_classmark_supports_a5; osmo_gsm48_classmark_a5_name; +osmo_gsm48_classmark_a5_name_buf; osmo_gsm48_classmark_update; local: *; diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c index e610ebf7..7bc60027 100644 --- a/src/gsm/rsl.c +++ b/src/gsm/rsl.c @@ -215,33 +215,47 @@ int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *tim return 0; } -/*! Get human-readable string for RSL channel number */ -const char *rsl_chan_nr_str(uint8_t chan_nr) +/*! Get human-readable string for RSL channel number, in caller-provided buffer. + * \param[out] buf caller-provided output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] chan_nr channel number to be stringified + * \returns buf with string + */ +char *rsl_chan_nr_str_buf(char *buf, size_t buf_len, uint8_t chan_nr) { - static char str[20]; int ts = chan_nr & 7; uint8_t cbits = chan_nr >> 3; if (cbits == 0x01) - sprintf(str, "TCH/F on TS%d", ts); + snprintf(buf, buf_len, "TCH/F on TS%d", ts); else if ((cbits & 0x1e) == 0x02) - sprintf(str, "TCH/H(%u) on TS%d", cbits & 0x01, ts); + snprintf(buf, buf_len, "TCH/H(%u) on TS%d", cbits & 0x01, ts); else if ((cbits & 0x1c) == 0x04) - sprintf(str, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts); + snprintf(buf, buf_len, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts); else if ((cbits & 0x18) == 0x08) - sprintf(str, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts); + snprintf(buf, buf_len, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts); else if (cbits == 0x10) - sprintf(str, "BCCH on TS%d", ts); + snprintf(buf, buf_len, "BCCH on TS%d", ts); else if (cbits == 0x11) - sprintf(str, "RACH on TS%d", ts); + snprintf(buf, buf_len, "RACH on TS%d", ts); else if (cbits == 0x12) - sprintf(str, "PCH/AGCH on TS%d", ts); + snprintf(buf, buf_len, "PCH/AGCH on TS%d", ts); else if (cbits == 0x18) - sprintf(str, "PDCH on TS%d", ts); + snprintf(buf, buf_len, "PDCH on TS%d", ts); else - sprintf(str, "UNKNOWN on TS%d", ts); + snprintf(buf, buf_len, "UNKNOWN on TS%d", ts); + + return buf; +} - return str; +/*! Get human-readable string for RSL channel number, in static buffer. + * \param[in] chan_nr channel number to be stringified + * \returns buf with string + */ +const char *rsl_chan_nr_str(uint8_t chan_nr) +{ + static char str[20]; + return rsl_chan_nr_str_buf(str, sizeof(str), chan_nr); } static const struct value_string rsl_err_vals[] = { -- cgit v1.2.3