<p>Harald Welte has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13311">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add _c versions of functions that otherwise return static buffers<br><br>We have a habit of returning static buffers from some functions,<br>particularly when generating some kind of string values.  This is<br>convenient in terms of memory management, but it comes at the expense<br>of not being thread-safe, and not allowing for two calls of the<br>related function within one printf() statement.<br><br>Let's introduce _c suffix versions of those functions where the<br>caller passes in a talloc context from which the output buffer shall<br>be allocated.<br><br>Change-Id: I8481c19b68ff67cfa22abb93c405ebcfcb0ab19b<br>---<br>M include/osmocom/core/msgb.h<br>M include/osmocom/core/socket.h<br>M include/osmocom/core/utils.h<br>M include/osmocom/gprs/gprs_ns.h<br>M include/osmocom/gsm/abis_nm.h<br>M include/osmocom/gsm/apn.h<br>M include/osmocom/gsm/gsm0808_utils.h<br>M include/osmocom/gsm/gsm23003.h<br>M include/osmocom/gsm/gsm48.h<br>M include/osmocom/gsm/gsm_utils.h<br>M include/osmocom/gsm/protocol/gsm_04_08.h<br>M include/osmocom/gsm/rsl.h<br>M include/osmocom/sim/sim.h<br>M src/gb/gprs_ns.c<br>M src/gb/libosmogb.map<br>M src/gsm/abis_nm.c<br>M src/gsm/apn.c<br>M src/gsm/gsm0808_utils.c<br>M src/gsm/gsm23003.c<br>M src/gsm/gsm48.c<br>M src/gsm/gsm_utils.c<br>M src/gsm/libosmogsm.map<br>M src/gsm/rsl.c<br>M src/msgb.c<br>M src/sim/core.c<br>M src/socket.c<br>M src/utils.c<br>27 files changed, 474 insertions(+), 11 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/11/13311/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h</span><br><span>index 4299fb8..63bc151 100644</span><br><span>--- a/include/osmocom/core/msgb.h</span><br><span>+++ b/include/osmocom/core/msgb.h</span><br><span>@@ -60,6 +60,7 @@</span><br><span>  unsigned char _data[0]; /*!< optional immediate data array */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+extern struct msgb *msgb_alloc_c(const void *ctx, uint16_t size, const char *name);</span><br><span> extern struct msgb *msgb_alloc(uint16_t size, const char *name);</span><br><span> extern void msgb_free(struct msgb *m);</span><br><span> extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);</span><br><span>@@ -68,9 +69,11 @@</span><br><span> uint16_t msgb_length(const struct msgb *msg);</span><br><span> extern const char *msgb_hexdump(const struct msgb *msg);</span><br><span> char *msgb_hexdump_buf(char *buf, size_t buf_len, const struct msgb *msg);</span><br><span style="color: hsl(120, 100%, 40%);">+char *msgb_hexdump_c(const void *ctx, const struct msgb *msg);</span><br><span> extern int msgb_resize_area(struct msgb *msg, uint8_t *area,</span><br><span>       int old_size, int new_size);</span><br><span> extern struct msgb *msgb_copy(const struct msgb *msg, const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+extern struct msgb *msgb_copy_c(const void *ctx, const struct msgb *msg, const char *name);</span><br><span> static int msgb_test_invariant(const struct msgb *msg) __attribute__((pure));</span><br><span> </span><br><span> /*! Free all msgbs from a queue built with msgb_enqueue().</span><br><span>@@ -501,6 +504,29 @@</span><br><span>      return msgb_trim(msg, (msg->l3h - msg->data) + l3len);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Allocate message buffer with specified headroom from specified talloc context.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from which to allocate</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] size size in bytes, including headroom</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] headroom headroom in bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] name human-readable name</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns allocated message buffer with specified headroom</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function is a convenience wrapper around \ref msgb_alloc</span><br><span style="color: hsl(120, 100%, 40%);">+ * followed by \ref msgb_reserve in order to create a new \ref msgb with</span><br><span style="color: hsl(120, 100%, 40%);">+ * user-specified amount of headroom.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct msgb *msgb_alloc_headroom_c(const void *ctx, int size, int headroom,</span><br><span style="color: hsl(120, 100%, 40%);">+                                           const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_static_assert(size > headroom, headroom_bigger);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    struct msgb *msg = msgb_alloc_c(ctx, size, name);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (msg)</span><br><span style="color: hsl(120, 100%, 40%);">+              msgb_reserve(msg, headroom);</span><br><span style="color: hsl(120, 100%, 40%);">+  return msg;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Allocate message buffer with specified headroom</span><br><span>  *  \param[in] size size in bytes, including headroom</span><br><span>  *  \param[in] headroom headroom in bytes</span><br><span>diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h</span><br><span>index 4f6ed72..37b1eae 100644</span><br><span>--- a/include/osmocom/core/socket.h</span><br><span>+++ b/include/osmocom/core/socket.h</span><br><span>@@ -68,6 +68,7 @@</span><br><span> </span><br><span> char *osmo_sock_get_name(const void *ctx, int fd);</span><br><span> const char *osmo_sock_get_name2(int fd);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_sock_get_name2_c(const void *ctx, int fd);</span><br><span> int osmo_sock_get_name_buf(char *str, size_t str_len, int fd);</span><br><span> int osmo_sock_get_ip_and_port(int fd, char *ip, size_t ip_len, char *port, size_t port_len, bool local);</span><br><span> int osmo_sock_get_local_ip(int fd, char *host, size_t len);</span><br><span>diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h</span><br><span>index 22b2ca5..ddb4672 100644</span><br><span>--- a/include/osmocom/core/utils.h</span><br><span>+++ b/include/osmocom/core/utils.h</span><br><span>@@ -56,7 +56,9 @@</span><br><span> char *osmo_ubit_dump_buf(char *buf, size_t buf_len, const uint8_t *bits, unsigned int len);</span><br><span> char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);</span><br><span> char *osmo_hexdump(const unsigned char *buf, int len);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_hexdump_c(const void *ctx, const unsigned char *buf, int len);</span><br><span> char *osmo_hexdump_nospc(const unsigned char *buf, int len);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_hexdump_nospc_c(const void *ctx, const unsigned char *buf, int len);</span><br><span> const char *osmo_hexdump_buf(char *out_buf, size_t out_buf_size, const unsigned char *buf, int len, const char *delim,</span><br><span>                            bool delim_after_last);</span><br><span> </span><br><span>@@ -73,9 +75,11 @@</span><br><span> </span><br><span> size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src);</span><br><span> const char *osmo_str_tolower(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_str_tolower_c(const void *ctx, const char *src);</span><br><span> </span><br><span> size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src);</span><br><span> const char *osmo_str_toupper(const char *src);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_str_toupper_c(const void *ctx, const char *src);</span><br><span> </span><br><span> #define OSMO_SNPRINTF_RET(ret, rem, offset, len)         \</span><br><span> do {                                                               \</span><br><span>@@ -139,8 +143,10 @@</span><br><span> </span><br><span> const char *osmo_escape_str(const char *str, int len);</span><br><span> const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_escape_str_c(const void *ctx, const char *str, int in_len);</span><br><span> const char *osmo_quote_str(const char *str, int in_len);</span><br><span> const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_quote_str_c(const void *ctx, const char *str, int in_len);</span><br><span> </span><br><span> uint32_t osmo_isqrt32(uint32_t x);</span><br><span> </span><br><span>diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h</span><br><span>index ed155ff..02faa50 100644</span><br><span>--- a/include/osmocom/gprs/gprs_ns.h</span><br><span>+++ b/include/osmocom/gprs/gprs_ns.h</span><br><span>@@ -213,6 +213,7 @@</span><br><span> const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc);</span><br><span> /* Return peer info in user-supplied buffer */</span><br><span> char *gprs_ns_ll_str_buf(char *buf, size_t buf_len, const struct gprs_nsvc *nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gprs_ns_ll_str_c(const void *ctx, const struct gprs_nsvc *nsvc);</span><br><span> </span><br><span> /* Copy the link layer info from other into nsvc */</span><br><span> void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other);</span><br><span>diff --git a/include/osmocom/gsm/abis_nm.h b/include/osmocom/gsm/abis_nm.h</span><br><span>index 788727c..ab5a5d5 100644</span><br><span>--- a/include/osmocom/gsm/abis_nm.h</span><br><span>+++ b/include/osmocom/gsm/abis_nm.h</span><br><span>@@ -43,6 +43,7 @@</span><br><span> </span><br><span> const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh);</span><br><span> char *abis_nm_dump_foh_buf(char *buf, size_t buf_len, const struct abis_om_fom_hdr *foh);</span><br><span style="color: hsl(120, 100%, 40%);">+char *abis_nm_dump_foh_c(void *ctx, const struct abis_om_fom_hdr *foh);</span><br><span> </span><br><span> /*! write a human-readable OML header to the debug log</span><br><span>  *  \param[in] ss Logging sub-system</span><br><span>diff --git a/include/osmocom/gsm/apn.h b/include/osmocom/gsm/apn.h</span><br><span>index 7899bb2..ab5f493 100644</span><br><span>--- a/include/osmocom/gsm/apn.h</span><br><span>+++ b/include/osmocom/gsm/apn.h</span><br><span>@@ -12,6 +12,7 @@</span><br><span> </span><br><span> char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni);</span><br><span> char *osmo_apn_qualify_buf(char *buf, size_t buf_len, unsigned int mcc, unsigned int mnc, const char *ni);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_apn_qualify_c(const void *ctx, unsigned int mcc, unsigned int mnc, const char *ni);</span><br><span> </span><br><span> /* Compose a string of the form '<ni>.mnc001.mcc002.gprs\0', returned in a</span><br><span>  * static buffer. */</span><br><span>@@ -19,6 +20,7 @@</span><br><span>                                const char *ni, int have_3dig_mnc);</span><br><span> char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi,</span><br><span>                                 const char *ni, int have_3dig_mnc);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_apn_qualify_from_imsi_c(const void *ctx, const char *imsi, const char *ni, int have_3dig_mnc);</span><br><span> </span><br><span> int osmo_apn_from_str(uint8_t *apn_enc, size_t max_apn_enc_len, const char *str);</span><br><span> char *osmo_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t apn_enc_len);</span><br><span>diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h</span><br><span>index e246967..47c4e95 100644</span><br><span>--- a/include/osmocom/gsm/gsm0808_utils.h</span><br><span>+++ b/include/osmocom/gsm/gsm0808_utils.h</span><br><span>@@ -70,6 +70,7 @@</span><br><span> </span><br><span> char *osmo_lcls_dump(const struct osmo_lcls *lcls);</span><br><span> char *osmo_lcls_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_lcls_dump_c(void *ctx, const struct osmo_lcls *lcls);</span><br><span> char *osmo_gcr_dump(const struct osmo_lcls *lcls);</span><br><span> char *osmo_gcr_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls);</span><br><span> </span><br><span>@@ -79,8 +80,11 @@</span><br><span> </span><br><span> const char *gsm0808_cell_id_name(const struct gsm0808_cell_id *cid);</span><br><span> const char *gsm0808_cell_id_name2(const struct gsm0808_cell_id *cid);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id *cid);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_name_c(const void *ctx, const struct gsm0808_cell_id *cid);</span><br><span> const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil);</span><br><span> int gsm0808_cell_id_list_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id_list2 *cil);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_list_name_c(const void *ctx, const struct gsm0808_cell_id_list2 *cil);</span><br><span> int gsm0808_cell_id_u_name(char *buf, size_t buflen,</span><br><span>                           enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u);</span><br><span> bool gsm0808_cell_ids_match(const struct gsm0808_cell_id *id1, const struct gsm0808_cell_id *id2, bool exact_match);</span><br><span>@@ -254,5 +258,6 @@</span><br><span> </span><br><span> const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct);</span><br><span> char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type *ct);</span><br><span> </span><br><span> /*! @} */</span><br><span>diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h</span><br><span>index 88c4f3c..69f00f6 100644</span><br><span>--- a/include/osmocom/gsm/gsm23003.h</span><br><span>+++ b/include/osmocom/gsm/gsm23003.h</span><br><span>@@ -106,18 +106,24 @@</span><br><span> </span><br><span> const char *osmo_mcc_name(uint16_t mcc);</span><br><span> char *osmo_mcc_name_buf(char *buf, size_t buf_len, uint16_t mcc);</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_mcc_name_c(const void *ctx, uint16_t mcc);</span><br><span> const char *osmo_mnc_name(uint16_t mnc, bool mnc_3_digits);</span><br><span> char *osmo_mnc_name_buf(char *buf, size_t buf_len, uint16_t mnc, bool mnc_3_digits);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mnc_name_c(const void *ctx, uint16_t mnc, bool mnc_3_digits);</span><br><span> const char *osmo_plmn_name(const struct osmo_plmn_id *plmn);</span><br><span> const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn);</span><br><span> char *osmo_plmn_name_buf(char *buf, size_t buf_len, const struct osmo_plmn_id *plmn);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_plmn_name_c(const void *ctx, const struct osmo_plmn_id *plmn);</span><br><span> const char *osmo_lai_name(const struct osmo_location_area_id *lai);</span><br><span> char *osmo_lai_name_buf(char *buf, size_t buf_len, const struct osmo_location_area_id *lai);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_lai_name_c(const void *ctx, const struct osmo_location_area_id *lai);</span><br><span> const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi);</span><br><span> const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi);</span><br><span> char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_cgi_name_c(const void *ctx, const struct osmo_cell_global_id *cgi);</span><br><span> const char *osmo_gummei_name(const struct osmo_gummei *gummei);</span><br><span> char *osmo_gummei_name_buf(char *buf, size_t buf_len, const struct osmo_gummei *gummei);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_gummei_name_c(const void *ctx, const struct osmo_gummei *gummei);</span><br><span> </span><br><span> void osmo_plmn_to_bcd(uint8_t *bcd_dst, const struct osmo_plmn_id *plmn);</span><br><span> void osmo_plmn_from_bcd(const uint8_t *bcd_src, struct osmo_plmn_id *plmn);</span><br><span>diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h</span><br><span>index 81b2bf0..786fbc9 100644</span><br><span>--- a/include/osmocom/gsm/gsm48.h</span><br><span>+++ b/include/osmocom/gsm/gsm48.h</span><br><span>@@ -36,6 +36,7 @@</span><br><span> const char *rr_cause_name(uint8_t cause);</span><br><span> const char *osmo_rai_name(const struct gprs_ra_id *rai);</span><br><span> char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_rai_name_c(const void *ctx, const struct gprs_ra_id *rai);</span><br><span> </span><br><span> int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,</span><br><span>                 uint16_t *mnc, uint16_t *lac)</span><br><span>@@ -57,6 +58,7 @@</span><br><span> const char *gsm48_mi_type_name(uint8_t mi);</span><br><span> const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len);</span><br><span> char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len);</span><br><span> </span><br><span> /* Parse Routeing Area Identifier */</span><br><span> void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf);</span><br><span>diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h</span><br><span>index 7de0623..aa5e79a 100644</span><br><span>--- a/include/osmocom/gsm/gsm_utils.h</span><br><span>+++ b/include/osmocom/gsm/gsm_utils.h</span><br><span>@@ -182,6 +182,7 @@</span><br><span> /* Returns static buffer with string representation of a GSM Time */</span><br><span> char *osmo_dump_gsmtime(const struct gsm_time *tm);</span><br><span> char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm);</span><br><span> </span><br><span> /* GSM TS 03.03 Chapter 2.6 */</span><br><span> enum gprs_tlli_type {</span><br><span>diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h</span><br><span>index c97df16..16910c3 100644</span><br><span>--- a/include/osmocom/gsm/protocol/gsm_04_08.h</span><br><span>+++ b/include/osmocom/gsm/protocol/gsm_04_08.h</span><br><span>@@ -71,6 +71,7 @@</span><br><span> int osmo_gsm48_classmark_supports_a5(const struct osmo_gsm48_classmark *cm, uint8_t a5);</span><br><span> const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm);</span><br><span> char *osmo_gsm48_classmark_a5_name_buf(char *buf, size_t buf_len, const struct osmo_gsm48_classmark *cm);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_classmark *cm);</span><br><span> void osmo_gsm48_classmark_update(struct osmo_gsm48_classmark *dst, const struct osmo_gsm48_classmark *src);</span><br><span> </span><br><span> /* Chapter 10.5.2.1b.3 */</span><br><span>@@ -1645,6 +1646,7 @@</span><br><span> extern const struct value_string gsm48_cc_msgtype_names[];</span><br><span> const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type);</span><br><span> char *gsm48_pdisc_msgtype_name_buf(char *buf, size_t buf_len, uint8_t pdisc, uint8_t msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm48_pdisc_msgtype_name_c(const void *ctx, uint8_t pdisc, uint8_t msg_type);</span><br><span> </span><br><span> /* FIXME: Table 10.4 / 10.4a (GPRS) */</span><br><span> </span><br><span>diff --git a/include/osmocom/gsm/rsl.h b/include/osmocom/gsm/rsl.h</span><br><span>index 4a1da3a..285dbc2 100644</span><br><span>--- a/include/osmocom/gsm/rsl.h</span><br><span>+++ b/include/osmocom/gsm/rsl.h</span><br><span>@@ -32,6 +32,7 @@</span><br><span> /* Turns channel number into a string */</span><br><span> char *rsl_chan_nr_str_buf(char *buf, size_t buf_len, uint8_t chan_nr);</span><br><span> const char *rsl_chan_nr_str(uint8_t chan_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+char *rsl_chan_nr_str_c(const void *ctx, uint8_t chan_nr);</span><br><span> </span><br><span> </span><br><span> const char *rsl_err_name(uint8_t err);</span><br><span>diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h</span><br><span>index 0490dcd..2bc4715 100644</span><br><span>--- a/include/osmocom/sim/sim.h</span><br><span>+++ b/include/osmocom/sim/sim.h</span><br><span>@@ -298,6 +298,7 @@</span><br><span> struct osim_card_hdl;</span><br><span> char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_card_hdl *ch, uint16_t sw_in);</span><br><span> char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in);</span><br><span style="color: hsl(120, 100%, 40%);">+char *osim_print_sw_c(const void *ctx, const struct osim_card_hdl *ch, uint16_t sw_in);</span><br><span> </span><br><span> extern const struct tlv_definition ts102221_fcp_tlv_def;</span><br><span> extern const struct value_string ts102221_fcp_vals[14];</span><br><span>diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c</span><br><span>index ea889ef..d126bc7 100644</span><br><span>--- a/src/gb/gprs_ns.c</span><br><span>+++ b/src/gb/gprs_ns.c</span><br><span>@@ -1552,6 +1552,14 @@</span><br><span>      return gprs_ns_ll_str_buf(buf, sizeof(buf), nsvc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *gprs_ns_ll_str_c(const void *ctx, const struct gprs_nsvc *nsvc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, INET6_ADDRSTRLEN+10);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+   return gprs_ns_ll_str_buf(buf, INET6_ADDRSTRLEN+10, nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other)</span><br><span> {</span><br><span>        nsvc->ll = other->ll;</span><br><span>diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map</span><br><span>index 21929da..5e675a6 100644</span><br><span>--- a/src/gb/libosmogb.map</span><br><span>+++ b/src/gb/libosmogb.map</span><br><span>@@ -65,6 +65,7 @@</span><br><span> gprs_ns_vty_init;</span><br><span> gprs_ns_ll_str;</span><br><span> gprs_ns_ll_str_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+gprs_ns_ll_str_c;</span><br><span> gprs_ns_ll_copy;</span><br><span> gprs_ns_ll_clear;</span><br><span> gprs_ns_msgb_alloc;</span><br><span>diff --git a/src/gsm/abis_nm.c b/src/gsm/abis_nm.c</span><br><span>index e25fdd0..a4c0e41 100644</span><br><span>--- a/src/gsm/abis_nm.c</span><br><span>+++ b/src/gsm/abis_nm.c</span><br><span>@@ -943,6 +943,15 @@</span><br><span>       return abis_nm_dump_foh_buf(foh_buf, sizeof(foh_buf), foh);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *abis_nm_dump_foh_c(void *ctx, const struct abis_om_fom_hdr *foh)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       size_t len = 15 /* format */ + 22 /* obj_class_name */+ 4*3 /* uint8 */ + 1 /*nul*/;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf = talloc_size(ctx, len);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return abis_nm_dump_foh_buf(buf, len, foh);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* this is just for compatibility reasons, it is now a macro */</span><br><span> #undef abis_nm_debugp_foh</span><br><span> OSMO_DEPRECATED("Use abis_nm_debugp_foh macro instead")</span><br><span>diff --git a/src/gsm/apn.c b/src/gsm/apn.c</span><br><span>index 4ab370c..88b45a4 100644</span><br><span>--- a/src/gsm/apn.c</span><br><span>+++ b/src/gsm/apn.c</span><br><span>@@ -24,6 +24,7 @@</span><br><span> #include <stdint.h></span><br><span> #include <stdlib.h></span><br><span> #include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <talloc.h></span><br><span> </span><br><span> #include <osmocom/gsm/apn.h></span><br><span> </span><br><span>@@ -45,6 +46,13 @@</span><br><span>      return osmo_apn_qualify_buf(apn_strbuf, sizeof(apn_strbuf), mcc, mnc, ni);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_apn_qualify_c(const void *ctx, unsigned int mcc, unsigned int mnc, const char *ni)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, APN_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_apn_qualify_buf(buf, APN_MAXLEN, mcc, mnc, ni);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi,</span><br><span>                                   const char *ni, int have_3dig_mnc)</span><br><span>@@ -70,6 +78,14 @@</span><br><span>         return osmo_apn_qualify_from_imsi_buf(apn_strbuf, sizeof(apn_strbuf), imsi, ni, have_3dig_mnc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_apn_qualify_from_imsi_c(const void *ctx, const char *imsi, const char *ni, int have_3dig_mnc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, APN_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_apn_qualify_from_imsi_buf(buf, APN_MAXLEN, imsi, ni, have_3dig_mnc);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /**</span><br><span>  * Convert an encoded APN into a dot-separated string.</span><br><span>  *</span><br><span>diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c</span><br><span>index 52e4674..99cf188 100644</span><br><span>--- a/src/gsm/gsm0808_utils.c</span><br><span>+++ b/src/gsm/gsm0808_utils.c</span><br><span>@@ -622,6 +622,14 @@</span><br><span>         return osmo_lcls_dump_buf(dbuf, sizeof(dbuf), lcls);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_lcls_dump_c(void *ctx, const struct osmo_lcls *lcls)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     char *buf = talloc_size(ctx, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_lcls_dump_buf(buf, 256, lcls);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Dump GCR struct into string for printing.</span><br><span>  *  \param[out] buf caller-allocated output string buffer</span><br><span>  *  \param[in] buf_len size of buf in bytes</span><br><span>@@ -1775,8 +1783,7 @@</span><br><span> #define APPEND_STR(fmt, args...) APPEND_THING(snprintf, fmt, ##args)</span><br><span> #define APPEND_CELL_ID_U(DISCR, U) APPEND_THING(gsm0808_cell_id_u_name, DISCR, U)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char *gsm0808_cell_id_name_buf(const struct gsm0808_cell_id *cid,</span><br><span style="color: hsl(0, 100%, 40%);">-                                         char *buf, size_t buflen)</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id *cid)</span><br><span> {</span><br><span>      char *pos = buf;</span><br><span>     int total_len = 0;</span><br><span>@@ -1793,7 +1800,7 @@</span><br><span> const char *gsm0808_cell_id_name(const struct gsm0808_cell_id *cid)</span><br><span> {</span><br><span>       static char buf[64];</span><br><span style="color: hsl(0, 100%, 40%);">-    return gsm0808_cell_id_name_buf(cid, buf, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+       return gsm0808_cell_id_name_buf(buf, sizeof(buf), cid);</span><br><span> }</span><br><span> </span><br><span> /*! Like gsm0808_cell_id_name() but uses a different static buffer.</span><br><span>@@ -1803,7 +1810,15 @@</span><br><span> const char *gsm0808_cell_id_name2(const struct gsm0808_cell_id *cid)</span><br><span> {</span><br><span>        static char buf[64];</span><br><span style="color: hsl(0, 100%, 40%);">-    return gsm0808_cell_id_name_buf(cid, buf, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+       return gsm0808_cell_id_name_buf(buf, sizeof(buf), cid);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_name_c(const void *ctx, const struct gsm0808_cell_id *cid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     char *buf = talloc_size(ctx, 64);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return gsm0808_cell_id_name_buf(buf, 64, cid);</span><br><span> }</span><br><span> </span><br><span> /*! Return a human readable representation of the Cell Identifier List, like</span><br><span>@@ -1856,6 +1871,15 @@</span><br><span>     return buf;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_cell_id_list_name_c(const void *ctx, const struct gsm0808_cell_id_list2 *cil)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf = talloc_size(ctx, 1024);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  gsm0808_cell_id_list_name_buf(buf, 1024, cil);</span><br><span style="color: hsl(120, 100%, 40%);">+        return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #undef APPEND_STR</span><br><span> #undef APPEND_CELL_ID_U</span><br><span> </span><br><span>@@ -1873,4 +1897,12 @@</span><br><span>        return gsm0808_channel_type_name_buf(buf, sizeof(buf), ct);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type *ct)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *buf = talloc_size(ctx, 128);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return gsm0808_channel_type_name_buf(buf, 128, ct);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! @} */</span><br><span>diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c</span><br><span>index b189cce..b317d47 100644</span><br><span>--- a/src/gsm/gsm23003.c</span><br><span>+++ b/src/gsm/gsm23003.c</span><br><span>@@ -111,6 +111,19 @@</span><br><span>    return osmo_mcc_name_buf(buf, sizeof(buf), mcc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MCC string as standardized 3-digit with leading zeros, into a talloc-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mcc  MCC value.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string in dynamically allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+const char *osmo_mcc_name_c(const void *ctx, uint16_t mcc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   char *buf = talloc_size(ctx, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_mcc_name_buf(buf, 8, mcc);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Return MNC string as standardized 2- or 3-digit with leading zeros.</span><br><span>  * \param[out] buf caller-allocated output buffer</span><br><span>  * \param[in] buf_len size of buf in bytes</span><br><span>@@ -124,6 +137,20 @@</span><br><span>     return buf;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MNC string as standardized 2- or 3-digit with leading zeros, into a talloc-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mnc  MNC value.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mnc_3_digits  True if an MNC should fill three digits, only has an effect if MNC < 100.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string in dynamically allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mnc_name_c(const void *ctx, uint16_t mnc, bool mnc_3_digits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   char *buf = talloc_size(ctx, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+   return osmo_mnc_name_buf(buf, 8, mnc, mnc_3_digitis);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Return MNC string as standardized 2- or 3-digit with leading zeros.</span><br><span>  * \param[in] mnc  MNC value.</span><br><span>  * \param[in] mnc_3_digits  True if an MNC should fill three digits, only has an effect if MNC < 100.</span><br><span>@@ -170,6 +197,20 @@</span><br><span>    return osmo_plmn_name_buf(buf, sizeof(buf), plmn);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros, into</span><br><span style="color: hsl(120, 100%, 40%);">+ *  a dynamically-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] plmn  MCC-MNC value.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string in dynamically allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_plmn_name_c(const void *ctx, const struct osmo_plmn_id *plmn)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf = talloc_size(ctx, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_plmn_name_buf(buf, 16, plmn);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Return MCC-MNC-LAC as string, in caller-provided output buffer</span><br><span>  * \param[out] buf caller-allocated output buffer</span><br><span>  * \param[in] buf_len size of buf in bytes</span><br><span>@@ -193,6 +234,19 @@</span><br><span>       return osmo_lai_name_buf(buf, sizeof(buf), lai);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MCC-MNC-LAC as string, in a talloc-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] lai  LAI to encode, the rac member is ignored.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string representation of lai in dynamically allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_lai_name_c(const void *ctx, const struct osmo_location_area_id *lai)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *buf = talloc_size(ctx, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_lai_name_buf(buf, 32, lai);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Return MCC-MNC-LAC-CI as string, in caller-provided output buffer</span><br><span>  * \param[out] buf caller-allocated output buffer</span><br><span>  * \param[in] buf_len size of buf in bytes</span><br><span>@@ -226,6 +280,17 @@</span><br><span>      return osmo_cgi_name_buf(buf, sizeof(buf), cgi);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MCC-MNC-LAC-CI as string, in a talloc-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cgi  CGI to encode.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string representation of CGI in dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_cgi_name_c(const void *ctx, const struct osmo_cell_global_id *cgi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      char *buf = talloc_size(ctx, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+     return osmo_cgi_name_buf(buf, 32, cgi);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void to_bcd(uint8_t *bcd, uint16_t val)</span><br><span> {</span><br><span>  bcd[2] = val % 10;</span><br><span>@@ -259,6 +324,19 @@</span><br><span>    return osmo_gummei_name_buf(buf, sizeof(buf), gummei);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return string representation of GUMMEI in static output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[out] buf pointer to caller-provided output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] buf_len size of buf in bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] gummei GUMMEI to be stringified</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns pointer to static output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_gummei_name_c(const void *ctx, const struct osmo_gummei *gummei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_gummei_name_buf(buf, 32, gummei);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /* Convert MCC + MNC to BCD representation</span><br><span>  * \param[out] bcd_dst caller-allocated memory for output</span><br><span>diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c</span><br><span>index a45d67b..c2c19cf 100644</span><br><span>--- a/src/gsm/gsm48.c</span><br><span>+++ b/src/gsm/gsm48.c</span><br><span>@@ -36,6 +36,7 @@</span><br><span> #include <osmocom/core/byteswap.h></span><br><span> #include <osmocom/core/bit16gen.h></span><br><span> #include <osmocom/core/bit32gen.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span> #include <osmocom/gsm/tlv.h></span><br><span> #include <osmocom/gsm/gsm48.h></span><br><span> #include <osmocom/gsm/gsm0502.h></span><br><span>@@ -206,6 +207,19 @@</span><br><span>      return osmo_rai_name_buf(buf, sizeof(buf), rai);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return MCC-MNC-LAC-RAC as string, in dynamically-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] rai  RAI to encode.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string representation in dynamically-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_rai_name_c(const void *ctx, const struct gprs_ra_id *rai)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   char *buf = talloc_size(ctx, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_rai_name_buf(buf, 32, rai);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* FIXME: convert to value_string */</span><br><span> static const char *cc_state_names[32] = {</span><br><span>    "NULL",</span><br><span>@@ -492,6 +506,22 @@</span><br><span>     return osmo_mi_name_buf(mi_name, sizeof(mi_name), mi, mi_len);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return a human readable representation of a Mobile Identity in dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi  Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] mi_len  Length of mi.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid" in a</span><br><span style="color: hsl(120, 100%, 40%);">+ *         dynamically-allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t buf_len = 10 + GSM48_MI_SIZE + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *mi_name = talloc_size(ctx, buf_len);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!mi_name)</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_mi_name_buf(mi_name, buf_len, mi, mi_len);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Checks is particular message is cipherable in A/Gb mode according to</span><br><span>  *         3GPP TS 24.008 ยง 4.7.1.2</span><br><span>  *  \param[in] hdr Message header</span><br><span>@@ -1124,6 +1154,22 @@</span><br><span>        return gsm48_pdisc_msgtype_name_buf(namebuf, sizeof(namebuf), pdisc, msg_type);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Compose a string naming the message type for given protocol, in a dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * If the message type string is known, return the message type name, otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+ * return "<protocol discriminator name>:<message type in hex>".</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string representation in dynamically allocated output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *gsm48_pdisc_msgtype_name_c(const void *ctx, uint8_t pdisc, uint8_t msg_type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *namebuf = talloc_size(ctx, 64);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!namebuf)</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return gsm48_pdisc_msgtype_name_buf(namebuf, 64, pdisc, msg_type);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const struct value_string gsm48_reject_value_names[] = {</span><br><span>   { GSM48_REJECT_IMSI_UNKNOWN_IN_HLR, "IMSI_UNKNOWN_IN_HLR" },</span><br><span>       { GSM48_REJECT_ILLEGAL_MS, "ILLEGAL_MS" },</span><br><span>@@ -1261,6 +1307,19 @@</span><br><span>       return osmo_gsm48_classmark_a5_name_buf(buf, sizeof(buf), cm);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return a string representation of A5 cipher algorithms indicated by Classmark 1, 2 and 3.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] cm  Classmarks.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3" in dynamically-allocated</span><br><span style="color: hsl(120, 100%, 40%);">+ *          output buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_classmark *cm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf = talloc_size(ctx, 128);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_gsm48_classmark_a5_name_buf(buf, 128, cm);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /*! Overwrite dst with the Classmark information present in src.</span><br><span>  * Add an new Classmark and overwrite in dst what src has to offer, but where src has no Classmark information, leave</span><br><span>diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c</span><br><span>index f34d9ea..6619177 100644</span><br><span>--- a/src/gsm/gsm_utils.c</span><br><span>+++ b/src/gsm/gsm_utils.c</span><br><span>@@ -900,6 +900,13 @@</span><br><span>   return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *buf = talloc_size(ctx, 64);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_dump_gsmtime_buf(buf, 64, tm);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /*! append range1024 encoded data to bit vector</span><br><span>  *  \param[out] bv Caller-provided output bit-vector</span><br><span>diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map</span><br><span>index a69fb60..56481fd 100644</span><br><span>--- a/src/gsm/libosmogsm.map</span><br><span>+++ b/src/gsm/libosmogsm.map</span><br><span>@@ -10,6 +10,7 @@</span><br><span> abis_nm_debugp_foh;</span><br><span> abis_nm_dump_foh;</span><br><span> abis_nm_dump_foh_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+abis_nm_dump_foh_c;</span><br><span> abis_nm_event_type_name;</span><br><span> abis_nm_nack_cause_name;</span><br><span> abis_nm_nack_name;</span><br><span>@@ -212,8 +213,11 @@</span><br><span> gsm0808_dec_cell_id;</span><br><span> gsm0808_cell_id_name;</span><br><span> gsm0808_cell_id_name2;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_cell_id_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_cell_id_name_c;</span><br><span> gsm0808_cell_id_list_name;</span><br><span> gsm0808_cell_id_list_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_cell_id_list_name_c;</span><br><span> gsm0808_cell_id_discr_names;</span><br><span> gsm0808_cell_id_u_name;</span><br><span> gsm0808_cell_ids_match;</span><br><span>@@ -227,6 +231,7 @@</span><br><span> gsm0808_chosen_enc_alg_names;</span><br><span> gsm0808_channel_type_name;</span><br><span> gsm0808_channel_type_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm0808_channel_type_name_c;</span><br><span> gsm0808_lcls_config_names;</span><br><span> gsm0808_lcls_control_names;</span><br><span> gsm0808_lcls_status_names;</span><br><span>@@ -255,6 +260,7 @@</span><br><span> osmo_gcr_dump_buf;</span><br><span> osmo_lcls_dump;</span><br><span> osmo_lcls_dump_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_lcls_dump_c;</span><br><span> </span><br><span> gsm0858_rsl_ul_meas_enc;</span><br><span> </span><br><span>@@ -350,6 +356,7 @@</span><br><span> gsm48_mi_type_name;</span><br><span> osmo_mi_name;</span><br><span> osmo_mi_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mi_name_c;</span><br><span> gsm48_mcc_mnc_to_bcd;</span><br><span> gsm48_mcc_mnc_from_bcd;</span><br><span> gsm48_generate_lai2;</span><br><span>@@ -360,20 +367,27 @@</span><br><span> osmo_plmn_from_bcd;</span><br><span> osmo_mcc_name;</span><br><span> osmo_mcc_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mcc_name_c;</span><br><span> osmo_mnc_name;</span><br><span> osmo_mnc_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_mnc_name_c;</span><br><span> osmo_plmn_name;</span><br><span> osmo_plmn_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_plmn_name_c;</span><br><span> osmo_plmn_name2;</span><br><span> osmo_lai_name;</span><br><span> osmo_lai_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_lai_name_c;</span><br><span> osmo_rai_name;</span><br><span> osmo_rai_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_rai_name_c;</span><br><span> osmo_cgi_name;</span><br><span> osmo_cgi_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_cgi_name_c;</span><br><span> osmo_cgi_name2;</span><br><span> osmo_gummei_name;</span><br><span> osmo_gummei_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_gummei_name_c;</span><br><span> osmo_mnc_from_str;</span><br><span> osmo_mnc_cmp;</span><br><span> osmo_plmn_cmp;</span><br><span>@@ -391,6 +405,7 @@</span><br><span> gsm48_cc_cause_names;</span><br><span> gsm48_pdisc_msgtype_name;</span><br><span> gsm48_pdisc_msgtype_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+gsm48_pdisc_msgtype_name_c;</span><br><span> gsm48_reject_value_names;</span><br><span> </span><br><span> gsm_7bit_decode;</span><br><span>@@ -417,6 +432,7 @@</span><br><span> gsm_gsmtime2fn;</span><br><span> osmo_dump_gsmtime;</span><br><span> osmo_dump_gsmtime_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_dump_gsmtime_c;</span><br><span> </span><br><span> gsm_milenage;</span><br><span> gsm_septet_encode;</span><br><span>@@ -487,6 +503,7 @@</span><br><span> rsl_ccch_conf_to_bs_ccch_sdcch_comb;</span><br><span> rsl_chan_nr_str;</span><br><span> rsl_chan_nr_str_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+rsl_chan_nr_str_c;</span><br><span> rsl_dec_chan_nr;</span><br><span> rsl_enc_chan_nr;</span><br><span> rsl_err_name;</span><br><span>@@ -549,8 +566,10 @@</span><br><span> </span><br><span> osmo_apn_qualify;</span><br><span> osmo_apn_qualify_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_apn_qualify_c;</span><br><span> osmo_apn_qualify_from_imsi;</span><br><span> osmo_apn_qualify_from_imsi_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_apn_qualify_from_imsi_c;</span><br><span> osmo_apn_to_str;</span><br><span> osmo_apn_from_str;</span><br><span> </span><br><span>@@ -610,6 +629,7 @@</span><br><span> osmo_gsm48_classmark_supports_a5;</span><br><span> osmo_gsm48_classmark_a5_name;</span><br><span> osmo_gsm48_classmark_a5_name_buf;</span><br><span style="color: hsl(120, 100%, 40%);">+osmo_gsm48_classmark_a5_name_c;</span><br><span> osmo_gsm48_classmark_update;</span><br><span> </span><br><span> local: *;</span><br><span>diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c</span><br><span>index 7bc6002..1777479 100644</span><br><span>--- a/src/gsm/rsl.c</span><br><span>+++ b/src/gsm/rsl.c</span><br><span>@@ -258,6 +258,19 @@</span><br><span>        return rsl_chan_nr_str_buf(str, sizeof(str), chan_nr);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Get human-readable string for RSL channel number, in dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from which to allocate output buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] chan_nr channel number to be stringified</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns dynamically-allocated buffer with string representation</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *rsl_chan_nr_str_c(const void *ctx, uint8_t chan_nr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     char *str = talloc_size(ctx, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return rsl_chan_nr_str_buf(str, 20, chan_nr);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct value_string rsl_err_vals[] = {</span><br><span>    { RSL_ERR_RADIO_IF_FAIL,        "Radio Interface Failure" },</span><br><span>       { RSL_ERR_RADIO_LINK_FAIL,      "Radio Link Failure" },</span><br><span>diff --git a/src/msgb.c b/src/msgb.c</span><br><span>index b7596f6..b57a205 100644</span><br><span>--- a/src/msgb.c</span><br><span>+++ b/src/msgb.c</span><br><span>@@ -64,9 +64,8 @@</span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/logging.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void *tall_msgb_ctx = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! Allocate a new message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Allocate a new message buffer from given talloc cotext</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from which to allocate</span><br><span>  * \param[in] size Length in octets, including headroom</span><br><span>  * \param[in] name Human-readable name to be associated with msgb</span><br><span>  * \returns dynamically-allocated \ref msgb</span><br><span>@@ -75,11 +74,11 @@</span><br><span>  * memory buffer for the actual message data (size specified by \a size)</span><br><span>  * using the talloc memory context previously set by \ref msgb_set_talloc_ctx</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-struct msgb *msgb_alloc(uint16_t size, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *msgb_alloc_c(const void *ctx, uint16_t size, const char *name)</span><br><span> {</span><br><span>      struct msgb *msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   msg = talloc_named_const(tall_msgb_ctx, sizeof(*msg) + size, name);</span><br><span style="color: hsl(120, 100%, 40%);">+   msg = talloc_named_const(ctx, sizeof(*msg) + size, name);</span><br><span>    if (!msg) {</span><br><span>          LOGP(DLGLOBAL, LOGL_FATAL, "Unable to allocate a msgb: "</span><br><span>                   "name='%s', size=%u\n", name, size);</span><br><span>@@ -98,6 +97,24 @@</span><br><span>  return msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* default msgb allocation context for msgb_alloc() */</span><br><span style="color: hsl(120, 100%, 40%);">+void *tall_msgb_ctx = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Allocate a new message buffer from tall_msgb_ctx</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] size Length in octets, including headroom</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] name Human-readable name to be associated with msgb</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns dynamically-allocated \ref msgb</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function allocates a 'struct msgb' as well as the underlying</span><br><span style="color: hsl(120, 100%, 40%);">+ * memory buffer for the actual message data (size specified by \a size)</span><br><span style="color: hsl(120, 100%, 40%);">+ * using the talloc memory context previously set by \ref msgb_set_talloc_ctx</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *msgb_alloc(uint16_t size, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return msgb_alloc_c(tall_msgb_ctx, size, name);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Release given message buffer</span><br><span>  * \param[in] m Message buffer to be freed</span><br><span>  */</span><br><span>@@ -309,11 +326,11 @@</span><br><span>  *  \param[in] msg  The old msgb object</span><br><span>  *  \param[in] name Human-readable name to be associated with msgb</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-struct msgb *msgb_copy(const struct msgb *msg, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *msgb_copy_c(const void *ctx, const struct msgb *msg, const char *name)</span><br><span> {</span><br><span>    struct msgb *new_msg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       new_msg = msgb_alloc(msg->data_len, name);</span><br><span style="color: hsl(120, 100%, 40%);">+ new_msg = msgb_alloc_c(ctx, msg->data_len, name);</span><br><span>         if (!new_msg)</span><br><span>                return NULL;</span><br><span> </span><br><span>@@ -338,6 +355,19 @@</span><br><span>      return new_msg;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Copy an msgb.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This function allocates a new msgb, copies the data buffer of msg,</span><br><span style="color: hsl(120, 100%, 40%);">+ *  and adjusts the pointers (incl l1h-l4h) accordingly. The cb part</span><br><span style="color: hsl(120, 100%, 40%);">+ *  is not copied.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] msg  The old msgb object</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] name Human-readable name to be associated with msgb</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct msgb *msgb_copy(const struct msgb *msg, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      return msgb_copy_c(tall_msgb_ctx, msg, name);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Resize an area within an msgb</span><br><span>  *</span><br><span>  *  This resizes a sub area of the msgb data and adjusts the pointers (incl</span><br><span>@@ -485,6 +515,19 @@</span><br><span>  return msgb_hexdump_buf(buf, sizeof(buf), msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return a dynamically allocated buffer containing a hexdump of the msg</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx talloc context from where to allocate the output string</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] msg message buffer</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns a pointer to a static char array</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *msgb_hexdump_c(const void *ctx, const struct msgb *msg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, msgb_length(msg)*3 + 100);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return msgb_hexdump_buf(buf, sizeof(buf), msg);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Print a string to the end of message buffer.</span><br><span>  * \param[in] msg message buffer</span><br><span>  * \returns 0 on success, -EINVAL on error</span><br><span>diff --git a/src/sim/core.c b/src/sim/core.c</span><br><span>index 998e836..63b3000 100644</span><br><span>--- a/src/sim/core.c</span><br><span>+++ b/src/sim/core.c</span><br><span>@@ -305,6 +305,14 @@</span><br><span>       return osim_print_sw_buf(sw_print_buf, sizeof(sw_print_buf), ch, sw_in);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+char *osim_print_sw_c(const void *ctx, const struct osim_card_hdl *ch, uint16_t sw_in)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  char *buf = talloc_size(ctx, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osim_print_sw_buf(buf, 256, ch, sw_in);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> const struct osim_card_sw *osim_find_sw(const struct osim_card_profile *cp,</span><br><span>                                   uint16_t sw_in)</span><br><span> {</span><br><span>diff --git a/src/socket.c b/src/socket.c</span><br><span>index 6a3f254..eaa9fb5 100644</span><br><span>--- a/src/socket.c</span><br><span>+++ b/src/socket.c</span><br><span>@@ -827,6 +827,20 @@</span><br><span>     return str;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Get address/port information on socket in static string, like "r=1.2.3.4:5<->l=6.7.8.9:10".</span><br><span style="color: hsl(120, 100%, 40%);">+ * This does not include braces like osmo_sock_get_name().</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] fd  File descriptor of socket.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return Static string buffer containing the result.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_sock_get_name2_c(const void *ctx, int fd)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *str = talloc_size(ctx, OSMO_SOCK_NAME_MAXLEN);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!str)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_sock_get_name_buf(str, sizeof(str), fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return str;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int sock_get_domain(int fd)</span><br><span> {</span><br><span>  int domain;</span><br><span>diff --git a/src/utils.c b/src/utils.c</span><br><span>index ec22cee..91be3aa 100644</span><br><span>--- a/src/utils.c</span><br><span>+++ b/src/utils.c</span><br><span>@@ -338,6 +338,27 @@</span><br><span> }</span><br><span> </span><br><span> /*! Convert binary sequence to hexadecimal ASCII string</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from where to allocate the output string</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf pointer to sequence of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] len length of buf in number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns pointer to zero-terminated string</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function will print a sequence of bytes as hexadecimal numbers,</span><br><span style="color: hsl(120, 100%, 40%);">+ * adding one space character between each byte (e.g. "1a ef d9")</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The maximum size of the output buffer is 4096 bytes, i.e. the maximum</span><br><span style="color: hsl(120, 100%, 40%);">+ * number of input bytes that can be printed in one call is 1365!</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_hexdump_c(const void *ctx, const unsigned char *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *hexd_buff = talloc_size(ctx, len*3 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!hexd_buff)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, " ", true);</span><br><span style="color: hsl(120, 100%, 40%);">+        return hexd_buff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Convert binary sequence to hexadecimal ASCII string</span><br><span>  *  \param[in] buf pointer to sequence of bytes</span><br><span>  *  \param[in] len length of buf in number of bytes</span><br><span>  *  \returns pointer to zero-terminated string</span><br><span>@@ -354,6 +375,28 @@</span><br><span>   return hexd_buff;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Convert binary sequence to hexadecimal ASCII string</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ctx talloc context from where to allocate the output string</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] buf pointer to sequence of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] len length of buf in number of bytes</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns pointer to zero-terminated string</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function will print a sequence of bytes as hexadecimal numbers,</span><br><span style="color: hsl(120, 100%, 40%);">+ * without any space character between each byte (e.g. "1aefd9")</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The maximum size of the output buffer is 4096 bytes, i.e. the maximum</span><br><span style="color: hsl(120, 100%, 40%);">+ * number of input bytes that can be printed in one call is 2048!</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_hexdump_nospc_c(const void *ctx, const unsigned char *buf, int len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *hexd_buff = talloc_size(ctx, len*2 + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!hexd_buff)</span><br><span style="color: hsl(120, 100%, 40%);">+               return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, "", true);</span><br><span style="color: hsl(120, 100%, 40%);">+ return hexd_buff;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Compat with previous typo to preserve abi */</span><br><span> char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)</span><br><span> #if defined(__MACH__) && defined(__APPLE__)</span><br><span>@@ -638,6 +681,19 @@</span><br><span>        return osmo_escape_str_buf(str, in_len, namebuf, sizeof(namebuf));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Return the string with all non-printable characters escaped, in dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  A string that may contain any characters.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] len  Pass -1 to print until nul char, or >= 0 to force a length.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns dynamically-allocated output buffer, containing an escaped representation</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_escape_str_c(const void *ctx, const char *str, int in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = talloc_size(ctx, in_len+1);</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_escape_str_buf(str, in_len, buf, in_len+1);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Like osmo_escape_str(), but returns double-quotes around a string, or "NULL" for a NULL string.</span><br><span>  * This allows passing any char* value and get its C representation as string.</span><br><span>  * \param[in] str  A string that may contain any characters.</span><br><span>@@ -682,6 +738,20 @@</span><br><span>       return osmo_quote_str_buf(str, in_len, namebuf, sizeof(namebuf));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Like osmo_quote_str_buf() but returns the result in a dynamically-allocated buffer.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The static buffer is shared with get_value_string() and osmo_escape_str().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] str  A string that may contain any characters.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] in_len  Pass -1 to print until nul char, or >= 0 to force a length.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns dynamically-allocated buffer containing a quoted and escaped representation.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_quote_str_c(const void *ctx, const char *str, int in_len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *buf = talloc_size(ctx, OSMO_MAX(in_len, 32));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  return osmo_quote_str_buf(str, in_len, buf, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! perform an integer square root operation on unsigned 32bit integer.</span><br><span>  *  This implementation is taken from "Hacker's Delight" Figure 11-1 "Integer square root, Newton's</span><br><span>  *  method", which can also be found at http://www.hackersdelight.org/hdcodetxt/isqrt.c.txt */</span><br><span>@@ -765,6 +835,21 @@</span><br><span>         return buf;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Convert a string to lowercase, dynamically allocating the output from given talloc context</span><br><span style="color: hsl(120, 100%, 40%);">+ * See also osmo_str_tolower_buf().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx  talloc context from where to allocate the output string</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  String to convert to lowercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Resulting lowercase string in a dynamically allocated buffer, always nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_str_tolower_c(const void *ctx, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *buf = talloc_size(ctx, strlen(src)+1);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_str_tolower_buf(buf, sizeof(buf), src);</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Convert a string to uppercase, while checking buffer size boundaries.</span><br><span>  * The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.</span><br><span>  * If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters</span><br><span>@@ -808,6 +893,21 @@</span><br><span>         return buf;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Convert a string to uppercase, dynamically allocating the output from given talloc context</span><br><span style="color: hsl(120, 100%, 40%);">+ * See also osmo_str_tolower_buf().</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] ctx  talloc context from where to allocate the output string</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] src  String to convert to uppercase.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns Resulting uppercase string in a dynamically allocated buffer, always nul terminated.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+char *osmo_str_toupper_c(const void *ctx, const char *src)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       char *buf = talloc_size(ctx, strlen(src)+1);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!buf)</span><br><span style="color: hsl(120, 100%, 40%);">+             return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  osmo_str_toupper_buf(buf, sizeof(buf), src);</span><br><span style="color: hsl(120, 100%, 40%);">+  return buf;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Calculate the Luhn checksum (as used for IMEIs).</span><br><span>  * \param[in] in  Input digits in ASCII string representation.</span><br><span>  * \param[in] in_len  Count of digits to use for the input (14 for IMEI).</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13311">change 13311</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13311"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I8481c19b68ff67cfa22abb93c405ebcfcb0ab19b </div>
<div style="display:none"> Gerrit-Change-Number: 13311 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>