summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-03-18 18:27:00 +0100
committerHarald Welte <laforge@gnumonks.org>2019-04-03 18:03:14 +0200
commit4a62eda225ab7f3c9556990c81a6fc5e19b5eec8 (patch)
tree5eab6ad641d4411ff31a15a51f6d0c14bccdb6f3
parent98ed3393cdfdf35ad0bb79f454474f2b27bf3d56 (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.h1
-rw-r--r--include/osmocom/core/utils.h3
-rw-r--r--include/osmocom/gprs/gprs_ns.h2
-rw-r--r--include/osmocom/gsm/abis_nm.h1
-rw-r--r--include/osmocom/gsm/apn.h3
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h3
-rw-r--r--include/osmocom/gsm/gsm23003.h6
-rw-r--r--include/osmocom/gsm/gsm48.h2
-rw-r--r--include/osmocom/gsm/gsm_utils.h1
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h2
-rw-r--r--include/osmocom/gsm/rsl.h1
-rw-r--r--include/osmocom/sim/sim.h1
-rw-r--r--src/gb/gprs_ns.c16
-rw-r--r--src/gb/libosmogb.map1
-rw-r--r--src/gsm/abis_nm.c13
-rw-r--r--src/gsm/apn.c27
-rw-r--r--src/gsm/gsm0808_utils.c40
-rw-r--r--src/gsm/gsm23003.c101
-rw-r--r--src/gsm/gsm48.c92
-rw-r--r--src/gsm/gsm_utils.c13
-rw-r--r--src/gsm/libosmogsm.map18
-rw-r--r--src/gsm/rsl.c40
-rw-r--r--src/msgb.c38
-rw-r--r--src/sim/core.c24
-rw-r--r--src/utils.c31
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.
+