diff options
author | Harald Welte <laforge@gnumonks.org> | 2019-03-18 18:27:00 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2019-04-03 18:03:14 +0200 |
commit | 4a62eda225ab7f3c9556990c81a6fc5e19b5eec8 (patch) | |
tree | 5eab6ad641d4411ff31a15a51f6d0c14bccdb6f3 | |
parent | 98ed3393cdfdf35ad0bb79f454474f2b27bf3d56 (diff) |
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
-rw-r--r-- | include/osmocom/core/msgb.h | 1 | ||||
-rw-r--r-- | include/osmocom/core/utils.h | 3 | ||||
-rw-r--r-- | include/osmocom/gprs/gprs_ns.h | 2 | ||||
-rw-r--r-- | include/osmocom/gsm/abis_nm.h | 1 | ||||
-rw-r--r-- | include/osmocom/gsm/apn.h | 3 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm0808_utils.h | 3 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm23003.h | 6 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm48.h | 2 | ||||
-rw-r--r-- | include/osmocom/gsm/gsm_utils.h | 1 | ||||
-rw-r--r-- | include/osmocom/gsm/protocol/gsm_04_08.h | 2 | ||||
-rw-r--r-- | include/osmocom/gsm/rsl.h | 1 | ||||
-rw-r--r-- | include/osmocom/sim/sim.h | 1 | ||||
-rw-r--r-- | src/gb/gprs_ns.c | 16 | ||||
-rw-r--r-- | src/gb/libosmogb.map | 1 | ||||
-rw-r--r-- | src/gsm/abis_nm.c | 13 | ||||
-rw-r--r-- | src/gsm/apn.c | 27 | ||||
-rw-r--r-- | src/gsm/gsm0808_utils.c | 40 | ||||
-rw-r--r-- | src/gsm/gsm23003.c | 101 | ||||
-rw-r--r-- | src/gsm/gsm48.c | 92 | ||||
-rw-r--r-- | src/gsm/gsm_utils.c | 13 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 18 | ||||
-rw-r--r-- | src/gsm/rsl.c | 40 | ||||
-rw-r--r-- | src/msgb.c | 38 | ||||
-rw-r--r-- | src/sim/core.c | 24 | ||||
-rw-r--r-- | src/utils.c | 31 |
25 files changed, 362 insertions, 118 deletions
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h index 5029225e..0c51ce26 100644 --- a/include/osmocom/core/msgb.h +++ b/include/osmocom/core/msgb.h @@ -67,6 +67,7 @@ extern struct msgb *msgb_dequeue(struct llist_head *queue); extern void msgb_reset(struct msgb *m); uint16_t msgb_length(const struct msgb *msg); extern const char *msgb_hexdump(const struct msgb *msg); +char *msgb_hexdump_buf(char *buf, size_t buf_len, const struct msgb *msg); extern int msgb_resize_area(struct msgb *msg, uint8_t *area, int old_size, int new_size); extern struct msgb *msgb_copy(const struct msgb *msg, const char *name); diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h index e3728cd0..6a2b7d5b 100644 --- a/include/osmocom/core/utils.h +++ b/include/osmocom/core/utils.h @@ -53,6 +53,7 @@ int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibbl int osmo_hexparse(const char *str, uint8_t *b, int max_len); +char *osmo_ubit_dump_buf(char *buf, size_t buf_len, const uint8_t *bits, unsigned int len); char *osmo_ubit_dump(const uint8_t *bits, unsigned int len); char *osmo_hexdump(const unsigned char *buf, int len); char *osmo_hexdump_nospc(const unsigned char *buf, int len); @@ -139,7 +140,7 @@ bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars); const char *osmo_escape_str(const char *str, int len); char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize); const char *osmo_quote_str(const char *str, int in_len); -const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize); +char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize); uint32_t osmo_isqrt32(uint32_t x); diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h index c62ef98a..ed155ffe 100644 --- a/include/osmocom/gprs/gprs_ns.h +++ b/include/osmocom/gprs/gprs_ns.h @@ -211,6 +211,8 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi); /* Resturn peer info as string (NOTE: the buffer is allocated statically) */ const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc); +/* Return peer info in user-supplied buffer */ +char *gprs_ns_ll_str_buf(char *buf, size_t buf_len, const struct gprs_nsvc *nsvc); /* Copy the link layer info from other into nsvc */ void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other); diff --git a/include/osmocom/gsm/abis_nm.h b/include/osmocom/gsm/abis_nm.h index 823b5a45..788727cd 100644 --- a/include/osmocom/gsm/abis_nm.h +++ b/include/osmocom/gsm/abis_nm.h @@ -42,6 +42,7 @@ extern const struct tlv_definition abis_nm_osmo_att_tlvdef; extern const struct tlv_definition abis_nm_att_tlvdef_ipa; 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); /*! write a human-readable OML header to the debug log * \param[in] ss Logging sub-system diff --git a/include/osmocom/gsm/apn.h b/include/osmocom/gsm/apn.h index 288b229e..7899bb28 100644 --- a/include/osmocom/gsm/apn.h +++ b/include/osmocom/gsm/apn.h @@ -11,11 +11,14 @@ #define APN_MAXLEN 100 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); /* Compose a string of the form '<ni>.mnc001.mcc002.gprs\0', returned in a * static buffer. */ char *osmo_apn_qualify_from_imsi(const char *imsi, const char *ni, int have_3dig_mnc); +char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi, + const char *ni, int have_3dig_mnc); int osmo_apn_from_str(uint8_t *apn_enc, size_t max_apn_enc_len, const char *str); char *osmo_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t apn_enc_len); diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index dedb0298..e2469670 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -69,7 +69,9 @@ struct osmo_lcls { }; 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); 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); extern const struct value_string gsm0808_cell_id_discr_names[]; static inline const char *gsm0808_cell_id_discr_name(enum CELL_IDENT id_discr) @@ -251,5 +253,6 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch } 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); /*! @} */ diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h index cf622ce0..88c4f3c2 100644 --- a/include/osmocom/gsm/gsm23003.h +++ b/include/osmocom/gsm/gsm23003.h @@ -105,13 +105,19 @@ bool osmo_msisdn_str_valid(const char *msisdn); bool osmo_imei_str_valid(const char *imei, bool with_15th_digit); const char *osmo_mcc_name(uint16_t mcc); +char *osmo_mcc_name_buf(char *buf, size_t buf_len, uint16_t mcc); const char *osmo_mnc_name(uint16_t mnc, bool mnc_3_digits); +char *osmo_mnc_name_buf(char *buf, size_t buf_len, uint16_t mnc, bool mnc_3_digits); const char *osmo_plmn_name(const struct osmo_plmn_id *plmn); const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn); +char *osmo_plmn_name_buf(char *buf, size_t buf_len, const struct osmo_plmn_id *plmn); const char *osmo_lai_name(const struct osmo_location_area_id *lai); +char *osmo_lai_name_buf(char *buf, size_t buf_len, 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); +char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi); const char *osmo_gummei_name(const struct osmo_gummei *gummei); +char *osmo_gummei_name_buf(char *buf, size_t buf_len, 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); diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h index 7e0e5c48..81b2bf0d 100644 --- a/include/osmocom/gsm/gsm48.h +++ b/include/osmocom/gsm/gsm48.h @@ -35,6 +35,7 @@ const char *gsm48_cc_msg_name(uint8_t msgtype); const char *gsm48_rr_msg_name(uint8_t msgtype); const char *rr_cause_name(uint8_t cause); const char *osmo_rai_name(const struct gprs_ra_id *rai); +char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai); int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc, uint16_t *mnc, uint16_t *lac) @@ -55,6 +56,7 @@ int gsm48_mi_to_string(char *string, const int str_len, const uint8_t *mi, const int mi_len); const char *gsm48_mi_type_name(uint8_t mi); const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len); +char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len); /* Parse Routeing Area Identifier */ void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf); diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h index f8f72a7f..f48cc68f 100644 --- a/include/osmocom/gsm/gsm_utils.h +++ b/include/osmocom/gsm/gsm_utils.h @@ -180,6 +180,7 @@ uint32_t gsm_gsmtime2fn(struct gsm_time *time); /* Returns static buffer with string representation of a GSM Time */ 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); /* GSM TS 03.03 Chapter 2.6 */ enum gprs_tlli_type { diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h index c052e4c8..c97df168 100644 --- a/include/osmocom/gsm/protocol/gsm_04_08.h +++ b/include/osmocom/gsm/protocol/gsm_04_08.h @@ -70,6 +70,7 @@ bool osmo_gsm48_classmark1_is_r99(const struct gsm48_classmark1 *cm1); bool osmo_gsm48_classmark2_is_r99(const struct gsm48_classmark2 *cm2, uint8_t cm2_len); int osmo_gsm48_classmark_supports_a5(const struct osmo_gsm48_classmark *cm, uint8_t a5); 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); void osmo_gsm48_classmark_update(struct osmo_gsm48_classmark *dst, const struct osmo_gsm48_classmark *src); /* Chapter 10.5.2.1b.3 */ @@ -1643,6 +1644,7 @@ extern const struct value_string gsm48_rr_msgtype_names[]; extern const struct value_string gsm48_mm_msgtype_names[]; extern const struct value_string gsm48_cc_msgtype_names[]; 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); /* FIXME: Table 10.4 / 10.4a (GPRS) */ diff --git a/include/osmocom/gsm/rsl.h b/include/osmocom/gsm/rsl.h index be0fa797..4a1da3a6 100644 --- a/include/osmocom/gsm/rsl.h +++ b/include/osmocom/gsm/rsl.h @@ -30,6 +30,7 @@ uint8_t rsl_enc_chan_nr(uint8_t type, uint8_t subch, uint8_t timeslot); /* decode channel number as per Section 9.3.1 */ int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *timeslot); /* Turns channel number into a string */ +char *rsl_chan_nr_str_buf(char *buf, size_t buf_len, uint8_t chan_nr); const char *rsl_chan_nr_str(uint8_t chan_nr); diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h index 680cad15..0490dcd4 100644 --- a/include/osmocom/sim/sim.h +++ b/include/osmocom/sim/sim.h @@ -296,6 +296,7 @@ enum osim_card_sw_class osim_sw_class(const struct osim_card_profile *cp, uint16_t sw_in); struct osim_card_hdl; +char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_card_hdl *ch, uint16_t sw_in); char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in); extern const struct tlv_definition ts102221_fcp_tlv_def; diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index c7ff78ed..fc120cec 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1525,17 +1525,15 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg, return rc; } -const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc) +char *gprs_ns_ll_str_buf(char *buf, size_t buf_len, const struct gprs_nsvc *nsvc) { - static char buf[80]; - switch(nsvc->ll) { case GPRS_NS_LL_UDP: - snprintf(buf, sizeof(buf), "%s:%u", + snprintf(buf, buf_len, "%s:%u", inet_ntoa(nsvc->ip.bts_addr.sin_addr), osmo_ntohs(nsvc->ip.bts_addr.sin_port)); break; case GPRS_NS_LL_FR_GRE: - snprintf(buf, sizeof(buf), "%s:%u", + snprintf(buf, buf_len, "%s:%u", inet_ntoa(nsvc->frgre.bts_addr.sin_addr), osmo_ntohs(nsvc->frgre.bts_addr.sin_port)); break; default: @@ -1543,11 +1541,17 @@ const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc) break; } - buf[sizeof(buf) - 1] = '\0'; + buf[buf_len - 1] = '\0'; return buf; } +const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc) +{ + static char buf[80]; + return gprs_ns_ll_str_buf(buf, sizeof(buf), nsvc); +} + void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other) { nsvc->ll = other->ll; diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 2ad3ff71..21929da1 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -64,6 +64,7 @@ gprs_ns_tx_status; gprs_ns_tx_unblock; gprs_ns_vty_init; gprs_ns_ll_str; +gprs_ns_ll_str_buf; gprs_ns_ll_copy; gprs_ns_ll_clear; gprs_ns_msgb_alloc; 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 @@ -90,13 +90,37 @@ bool osmo_imei_str_valid(const char *imei, bool with_15th_digit) } /*! 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. */ 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 "<protocol discriminator name>:<message type in hex>". + * \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. + |