Add _c versions of functions that otherwise return static buffers

We have a habit of returning static buffers from some functions,
particularly when generating some kind of string values.  This is
convenient in terms of memory management, but it comes at the expense
of not being thread-safe, and not allowing for two calls of the
related function within one printf() statement.

Let's introduce _c suffix versions of those functions where the
caller passes in a talloc context from which the output buffer shall
be allocated.

Change-Id: I8481c19b68ff67cfa22abb93c405ebcfcb0ab19b
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index 0c51ce2..e05d37f 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -60,6 +60,7 @@
 	unsigned char _data[0]; /*!< optional immediate data array */
 };
 
+extern struct msgb *msgb_alloc_c(const void *ctx, uint16_t size, const char *name);
 extern struct msgb *msgb_alloc(uint16_t size, const char *name);
 extern void msgb_free(struct msgb *m);
 extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg);
@@ -68,9 +69,11 @@
 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);
+char *msgb_hexdump_c(const void *ctx, 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);
+extern struct msgb *msgb_copy_c(const void *ctx, const struct msgb *msg, const char *name);
 static int msgb_test_invariant(const struct msgb *msg) __attribute__((pure));
 
 /*! Free all msgbs from a queue built with msgb_enqueue().
@@ -501,6 +504,29 @@
 	return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
 }
 
+/*! Allocate message buffer with specified headroom from specified talloc context.
+ *  \param[in] ctx talloc context from which to allocate
+ *  \param[in] size size in bytes, including headroom
+ *  \param[in] headroom headroom in bytes
+ *  \param[in] name human-readable name
+ *  \returns allocated message buffer with specified headroom
+ *
+ * This function is a convenience wrapper around \ref msgb_alloc
+ * followed by \ref msgb_reserve in order to create a new \ref msgb with
+ * user-specified amount of headroom.
+ */
+static inline struct msgb *msgb_alloc_headroom_c(const void *ctx, int size, int headroom,
+						 const char *name)
+{
+	osmo_static_assert(size > headroom, headroom_bigger);
+
+	struct msgb *msg = msgb_alloc_c(ctx, size, name);
+	if (msg)
+		msgb_reserve(msg, headroom);
+	return msg;
+}
+
+
 /*! Allocate message buffer with specified headroom
  *  \param[in] size size in bytes, including headroom
  *  \param[in] headroom headroom in bytes
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index 4f6ed72..37b1eae 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -68,6 +68,7 @@
 
 char *osmo_sock_get_name(const void *ctx, int fd);
 const char *osmo_sock_get_name2(int fd);
+char *osmo_sock_get_name2_c(const void *ctx, int fd);
 int osmo_sock_get_name_buf(char *str, size_t str_len, int fd);
 int osmo_sock_get_ip_and_port(int fd, char *ip, size_t ip_len, char *port, size_t port_len, bool local);
 int osmo_sock_get_local_ip(int fd, char *host, size_t len);
diff --git a/include/osmocom/core/utils.h b/include/osmocom/core/utils.h
index 6a2b7d5..51e43ee 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -56,7 +56,9 @@
 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_c(const void *ctx, const unsigned char *buf, int len);
 char *osmo_hexdump_nospc(const unsigned char *buf, int len);
+char *osmo_hexdump_nospc_c(const void *ctx, const unsigned char *buf, int len);
 const char *osmo_hexdump_buf(char *out_buf, size_t out_buf_size, const unsigned char *buf, int len, const char *delim,
 			     bool delim_after_last);
 
@@ -73,9 +75,11 @@
 
 size_t osmo_str_tolower_buf(char *dest, size_t dest_len, const char *src);
 const char *osmo_str_tolower(const char *src);
+char *osmo_str_tolower_c(const void *ctx, const char *src);
 
 size_t osmo_str_toupper_buf(char *dest, size_t dest_len, const char *src);
 const char *osmo_str_toupper(const char *src);
+char *osmo_str_toupper_c(const void *ctx, const char *src);
 
 #define OSMO_SNPRINTF_RET(ret, rem, offset, len)		\
 do {								\
@@ -139,8 +143,10 @@
 
 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);
+char *osmo_escape_str_c(const void *ctx, const char *str, int in_len);
 const char *osmo_quote_str(const char *str, int in_len);
 char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize);
+char *osmo_quote_str_c(const void *ctx, const char *str, int in_len);
 
 uint32_t osmo_isqrt32(uint32_t x);
 
diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h
index ed155ff..02faa50 100644
--- a/include/osmocom/gprs/gprs_ns.h
+++ b/include/osmocom/gprs/gprs_ns.h
@@ -213,6 +213,7 @@
 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);
+char *gprs_ns_ll_str_c(const void *ctx, 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 788727c..ab5a5d5 100644
--- a/include/osmocom/gsm/abis_nm.h
+++ b/include/osmocom/gsm/abis_nm.h
@@ -43,6 +43,7 @@
 
 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);
+char *abis_nm_dump_foh_c(void *ctx, 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 7899bb2..ab5f493 100644
--- a/include/osmocom/gsm/apn.h
+++ b/include/osmocom/gsm/apn.h
@@ -12,6 +12,7 @@
 
 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);
+char *osmo_apn_qualify_c(const void *ctx, 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. */
@@ -19,6 +20,7 @@
 				 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);
+char *osmo_apn_qualify_from_imsi_c(const void *ctx, 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 e246967..47c4e95 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -70,6 +70,7 @@
 
 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_lcls_dump_c(void *ctx, 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);
 
@@ -79,8 +80,11 @@
 
 const char *gsm0808_cell_id_name(const struct gsm0808_cell_id *cid);
 const char *gsm0808_cell_id_name2(const struct gsm0808_cell_id *cid);
+char *gsm0808_cell_id_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id *cid);
+char *gsm0808_cell_id_name_c(const void *ctx, const struct gsm0808_cell_id *cid);
 const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil);
 int gsm0808_cell_id_list_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id_list2 *cil);
+char *gsm0808_cell_id_list_name_c(const void *ctx, const struct gsm0808_cell_id_list2 *cil);
 int gsm0808_cell_id_u_name(char *buf, size_t buflen,
 			   enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u);
 bool gsm0808_cell_ids_match(const struct gsm0808_cell_id *id1, const struct gsm0808_cell_id *id2, bool exact_match);
@@ -254,5 +258,6 @@
 
 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);
+char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type *ct);
 
 /*! @} */
diff --git a/include/osmocom/gsm/gsm23003.h b/include/osmocom/gsm/gsm23003.h
index 88c4f3c..69f00f6 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -106,18 +106,24 @@
 
 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_mcc_name_c(const void *ctx, 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);
+char *osmo_mnc_name_c(const void *ctx, 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);
+char *osmo_plmn_name_c(const void *ctx, 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);
+char *osmo_lai_name_c(const void *ctx, 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);
+char *osmo_cgi_name_c(const void *ctx, 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);
+char *osmo_gummei_name_c(const void *ctx, 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 81b2bf0..786fbc9 100644
--- a/include/osmocom/gsm/gsm48.h
+++ b/include/osmocom/gsm/gsm48.h
@@ -36,6 +36,7 @@
 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);
+char *osmo_rai_name_c(const void *ctx, 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)
@@ -57,6 +58,7 @@
 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);
+char *osmo_mi_name_c(const void *ctx, 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 f48cc68..37df665 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -181,6 +181,7 @@
 /* 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);
+char *osmo_dump_gsmtime_c(const void *ctx, 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 c97df16..16910c3 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -71,6 +71,7 @@
 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);
+char *osmo_gsm48_classmark_a5_name_c(const void *ctx, 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 */
@@ -1645,6 +1646,7 @@
 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);
+char *gsm48_pdisc_msgtype_name_c(const void *ctx, 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 4a1da3a..285dbc2 100644
--- a/include/osmocom/gsm/rsl.h
+++ b/include/osmocom/gsm/rsl.h
@@ -32,6 +32,7 @@
 /* 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);
+char *rsl_chan_nr_str_c(const void *ctx, uint8_t chan_nr);
 
 
 const char *rsl_err_name(uint8_t err);
diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h
index 0490dcd..2bc4715 100644
--- a/include/osmocom/sim/sim.h
+++ b/include/osmocom/sim/sim.h
@@ -298,6 +298,7 @@
 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);
+char *osim_print_sw_c(const void *ctx, const struct osim_card_hdl *ch, uint16_t sw_in);
 
 extern const struct tlv_definition ts102221_fcp_tlv_def;
 extern const struct value_string ts102221_fcp_vals[14];