aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2019-03-18 18:38:47 +0100
committerHarald Welte <laforge@gnumonks.org>2019-04-10 22:42:32 +0000
commit179f35702ece13f4ab7fd1b331bef664834d8473 (patch)
tree9dad4da8eb773040ea8a2dc096190118f5d2abd6
parentd08e9866a5c3da6edda574bbe6d277047d10fded (diff)
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
-rw-r--r--include/osmocom/core/msgb.h26
-rw-r--r--include/osmocom/core/socket.h1
-rw-r--r--include/osmocom/core/utils.h6
-rw-r--r--include/osmocom/gprs/gprs_ns.h1
-rw-r--r--include/osmocom/gsm/abis_nm.h1
-rw-r--r--include/osmocom/gsm/apn.h2
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h5
-rw-r--r--include/osmocom/gsm/gsm23003.h6
-rw-r--r--include/osmocom/gsm/gsm48.h2
-rw-r--r--include/osmocom/gsm/gsm_utils.h1
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h2
-rw-r--r--include/osmocom/gsm/rsl.h1
-rw-r--r--include/osmocom/sim/sim.h1
-rw-r--r--src/gb/gprs_ns.c8
-rw-r--r--src/gb/libosmogb.map1
-rw-r--r--src/gsm/abis_nm.c9
-rw-r--r--src/gsm/apn.c16
-rw-r--r--src/gsm/gsm0808_utils.c40
-rw-r--r--src/gsm/gsm23003.c78
-rw-r--r--src/gsm/gsm48.c59
-rw-r--r--src/gsm/gsm_utils.c7
-rw-r--r--src/gsm/libosmogsm.map20
-rw-r--r--src/gsm/rsl.c13
-rw-r--r--src/msgb.c57
-rw-r--r--src/sim/core.c8
-rw-r--r--src/socket.c14
-rw-r--r--src/utils.c100
27 files changed, 474 insertions, 11 deletions
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index 0c51ce26..e05d37f0 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -60,6 +60,7 @@ struct msgb {
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 @@ extern void msgb_reset(struct msgb *m);
uint16_t msgb_length(const struct msgb *msg);
extern const char *msgb_hexdump(const struct msgb *msg);
char *msgb_hexdump_buf(char *buf, size_t buf_len, const struct msgb *msg);
+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 @@ static inline int msgb_l3trim(struct msgb *msg, int l3len)
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 4f6ed72b..37b1eaef 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -68,6 +68,7 @@ int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto,
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 6a2b7d5b..51e43ee5 100644
--- a/include/osmocom/core/utils.h
+++ b/include/osmocom/core/utils.h
@@ -56,7 +56,9 @@ int osmo_hexparse(const char *str, uint8_t *b, int max_len);
char *osmo_ubit_dump_buf(char *buf, size_t buf_len, const uint8_t *bits, unsigned int len);
char *osmo_ubit_dump(const uint8_t *bits, unsigned int len);
char *osmo_hexdump(const unsigned char *buf, int len);
+char *osmo_hexdump_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 @@ void osmo_str2upper(char *out, const char *in)
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 @@ bool osmo_separated_identifiers_valid(const char *str, const char *sep_chars);
const char *osmo_escape_str(const char *str, int len);
char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t bufsize);
+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 ed155ffe..02faa506 100644
--- a/include/osmocom/gprs/gprs_ns.h
+++ b/include/osmocom/gprs/gprs_ns.h
@@ -213,6 +213,7 @@ int gprs_ns_vty_init(struct gprs_ns_inst *nsi);
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 788727cd..ab5a5d5e 100644
--- a/include/osmocom/gsm/abis_nm.h
+++ b/include/osmocom/gsm/abis_nm.h
@@ -43,6 +43,7 @@ extern const struct tlv_definition abis_nm_att_tlvdef_ipa;
const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh);
char *abis_nm_dump_foh_buf(char *buf, size_t buf_len, const struct abis_om_fom_hdr *foh);
+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 7899bb28..ab5f4938 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 @@ char *osmo_apn_qualify_from_imsi(const char *imsi,
const char *ni, int have_3dig_mnc);
char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi,
const char *ni, int have_3dig_mnc);
+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 e2469670..47c4e95c 100644
--- a/include/osmocom/gsm/gsm0808_utils.h
+++ b/include/osmocom/gsm/gsm0808_utils.h
@@ -70,6 +70,7 @@ struct osmo_lcls {
char *osmo_lcls_dump(const struct osmo_lcls *lcls);
char *osmo_lcls_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls);
+char *osmo_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 @@ static inline const char *gsm0808_cell_id_discr_name(enum CELL_IDENT id_discr)
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 @@ static inline uint8_t gsm0808_chosen_channel(enum gsm_chan_t type, enum gsm48_ch
const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct);
char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct);
+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 88c4f3c2..69f00f68 100644
--- a/include/osmocom/gsm/gsm23003.h
+++ b/include/osmocom/gsm/gsm23003.h
@@ -106,18 +106,24 @@ bool osmo_imei_str_valid(const char *imei, bool with_15th_digit);
const char *osmo_mcc_name(uint16_t mcc);
char *osmo_mcc_name_buf(char *buf, size_t buf_len, uint16_t mcc);
+const char *osmo_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 81b2bf0d..786fbc9e 100644
--- a/include/osmocom/gsm/gsm48.h
+++ b/include/osmocom/gsm/gsm48.h
@@ -36,6 +36,7 @@ const char *gsm48_rr_msg_name(uint8_t msgtype);
const char *rr_cause_name(uint8_t cause);
const char *osmo_rai_name(const struct gprs_ra_id *rai);
char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai);
+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 @@ int gsm48_mi_to_string(char *string, const int str_len,
const char *gsm48_mi_type_name(uint8_t mi);
const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len);
char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len);
+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 f48cc68f..37df6656 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -181,6 +181,7 @@ uint32_t gsm_gsmtime2fn(struct gsm_time *time);
/* Returns static buffer with string representation of a GSM Time */
char *osmo_dump_gsmtime(const struct gsm_time *tm);
char *osmo_dump_gsmtime_buf(char *buf, size_t buf_len, const struct gsm_time *tm);
+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 c97df168..16910c35 100644
--- a/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -71,6 +71,7 @@ bool osmo_gsm48_classmark2_is_r99(const struct gsm48_classmark2 *cm2, uint8_t cm
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_mm_msgtype_names[];
extern const struct value_string gsm48_cc_msgtype_names[];
const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type);
char *gsm48_pdisc_msgtype_name_buf(char *buf, size_t buf_len, uint8_t pdisc, uint8_t msg_type);
+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 4a1da3a6..285dbc25 100644
--- a/include/osmocom/gsm/rsl.h
+++ b/include/osmocom/gsm/rsl.h
@@ -32,6 +32,7 @@ int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *tim
/* 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 0490dcd4..2bc47153 100644
--- a/include/osmocom/sim/sim.h
+++ b/include/osmocom/sim/sim.h
@@ -298,6 +298,7 @@ enum osim_card_sw_class osim_sw_class(const struct osim_card_profile *cp,
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];
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c
index fc120cec..d72003ed 100644
--- a/src/gb/gprs_ns.c
+++ b/src/gb/gprs_ns.c
@@ -1552,6 +1552,14 @@ const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc)
return gprs_ns_ll_str_buf(buf, sizeof(buf), nsvc);
}
+char *gprs_ns_ll_str_c(const void *ctx, const struct gprs_nsvc *nsvc)
+{
+ char *buf = talloc_size(ctx, INET6_ADDRSTRLEN+10);
+ if (!buf)
+ return buf;
+ return gprs_ns_ll_str_buf(buf, INET6_ADDRSTRLEN+10, nsvc);
+}
+
void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other)
{
nsvc->ll = other->ll;
diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map
index 21929da1..5e675a66 100644
--- a/src/gb/libosmogb.map
+++ b/src/gb/libosmogb.map
@@ -65,6 +65,7 @@ gprs_ns_tx_unblock;
gprs_ns_vty_init;
gprs_ns_ll_str;
gprs_ns_ll_str_buf;
+gprs_ns_ll_str_c;
gprs_ns_ll_copy;
gprs_ns_ll_clear;
gprs_ns_msgb_alloc;
diff --git a/src/gsm/abis_nm.c b/src/gsm/abis_nm.c
index e25fdd03..a4c0e41f 100644
--- a/src/gsm/abis_nm.c
+++ b/src/gsm/abis_nm.c
@@ -943,6 +943,15 @@ const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh)
return abis_nm_dump_foh_buf(foh_buf, sizeof(foh_buf), foh);
}
+char *abis_nm_dump_foh_c(void *ctx, const struct abis_om_fom_hdr *foh)
+{
+ size_t len = 15 /* format */ + 22 /* obj_class_name */+ 4*3 /* uint8 */ + 1 /*nul*/;
+ char *buf = talloc_size(ctx, len);
+ if (!buf)
+ return NULL;
+ return abis_nm_dump_foh_buf(buf, len, foh);
+}
+
/* this is just for compatibility reasons, it is now a macro */
#undef abis_nm_debugp_foh
OSMO_DEPRECATED("Use abis_nm_debugp_foh macro instead")
diff --git a/src/gsm/apn.c b/src/gsm/apn.c
index 4ab370c5..88b45a4b 100644
--- a/src/gsm/apn.c
+++ b/src/gsm/apn.c
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <talloc.h>
#include <osmocom/gsm/apn.h>
@@ -45,6 +46,13 @@ char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni)
return osmo_apn_qualify_buf(apn_strbuf, sizeof(apn_strbuf), mcc, mnc, ni);
}
+char *osmo_apn_qualify_c(const void *ctx, unsigned int mcc, unsigned int mnc, const char *ni)
+{
+ char *buf = talloc_size(ctx, APN_MAXLEN);
+ if (!buf)
+ return NULL;
+ return osmo_apn_qualify_buf(buf, APN_MAXLEN, mcc, mnc, ni);
+}
char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi,
const char *ni, int have_3dig_mnc)
@@ -70,6 +78,14 @@ char *osmo_apn_qualify_from_imsi(const char *imsi,
return osmo_apn_qualify_from_imsi_buf(apn_strbuf, sizeof(apn_strbuf), imsi, ni, have_3dig_mnc);
}
+char *osmo_apn_qualify_from_imsi_c(const void *ctx, const char *imsi, const char *ni, int have_3dig_mnc)
+{
+ char *buf = talloc_size(ctx, APN_MAXLEN);
+ if (!buf)
+ return NULL;
+ return osmo_apn_qualify_from_imsi_buf(buf, APN_MAXLEN, imsi, ni, have_3dig_mnc);
+}
+
/**
* Convert an encoded APN into a dot-separated string.
*
diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c
index 52e46743..99cf1881 100644
--- a/src/gsm/gsm0808_utils.c
+++ b/src/gsm/gsm0808_utils.c
@@ -622,6 +622,14 @@ char *osmo_lcls_dump(const struct osmo_lcls *lcls)
return osmo_lcls_dump_buf(dbuf, sizeof(dbuf), lcls);
}
+char *osmo_lcls_dump_c(void *ctx, const struct osmo_lcls *lcls)
+{
+ char *buf = talloc_size(ctx, 256);
+ if (!buf)
+ return NULL;
+ return osmo_lcls_dump_buf(buf, 256, lcls);
+}
+
/*! Dump GCR struct into string for printing.
* \param[out] buf caller-allocated output string buffer
* \param[in] buf_len size of buf in bytes
@@ -1775,8 +1783,7 @@ const struct value_string gsm0808_cell_id_discr_names[] = {
#define APPEND_STR(fmt, args...) APPEND_THING(snprintf, fmt, ##args)
#define APPEND_CELL_ID_U(DISCR, U) APPEND_THING(gsm0808_cell_id_u_name, DISCR, U)
-static const char *gsm0808_cell_id_name_buf(const struct gsm0808_cell_id *cid,
- char *buf, size_t buflen)
+char *gsm0808_cell_id_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id *cid)
{
char *pos = buf;
int total_len = 0;
@@ -1793,7 +1800,7 @@ static const char *gsm0808_cell_id_name_buf(const struct gsm0808_cell_id *cid,
const char *gsm0808_cell_id_name(const struct gsm0808_cell_id *cid)
{
static char buf[64];
- return gsm0808_cell_id_name_buf(cid, buf, sizeof(buf));
+ return gsm0808_cell_id_name_buf(buf, sizeof(buf), cid);
}
/*! Like gsm0808_cell_id_name() but uses a different static buffer.
@@ -1803,7 +1810,15 @@ const char *gsm0808_cell_id_name(const struct gsm0808_cell_id *cid)
const char *gsm0808_cell_id_name2(const struct gsm0808_cell_id *cid)
{
static char buf[64];
- return gsm0808_cell_id_name_buf(cid, buf, sizeof(buf));
+ return gsm0808_cell_id_name_buf(buf, sizeof(buf), cid);
+}
+
+char *gsm0808_cell_id_name_c(const void *ctx, const struct gsm0808_cell_id *cid)
+{
+ char *buf = talloc_size(ctx, 64);
+ if (!buf)
+ return NULL;
+ return gsm0808_cell_id_name_buf(buf, 64, cid);
}
/*! Return a human readable representation of the Cell Identifier List, like
@@ -1856,6 +1871,15 @@ const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil)
return buf;
}
+char *gsm0808_cell_id_list_name_c(const void *ctx, const struct gsm0808_cell_id_list2 *cil)
+{
+ char *buf = talloc_size(ctx, 1024);
+ if (!buf)
+ return NULL;
+ gsm0808_cell_id_list_name_buf(buf, 1024, cil);
+ return buf;
+}
+
#undef APPEND_STR
#undef APPEND_CELL_ID_U
@@ -1873,4 +1897,12 @@ const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct)
return gsm0808_channel_type_name_buf(buf, sizeof(buf), ct);
}
+char *gsm0808_channel_type_name_c(const void *ctx, const struct gsm0808_channel_type *ct)
+{
+ char *buf = talloc_size(ctx, 128);
+ if (!buf)
+ return NULL;
+ return gsm0808_channel_type_name_buf(buf, 128, ct);
+}
+
/*! @} */
diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c
index bbfe236a..2252f706 100644
--- a/src/gsm/gsm23003.c
+++ b/src/gsm/gsm23003.c
@@ -111,6 +111,19 @@ const char *osmo_mcc_name(uint16_t mcc)
return osmo_mcc_name_buf(buf, sizeof(buf), mcc);
}
+/*! Return MCC string as standardized 3-digit with leading zeros, into a talloc-allocated buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] mcc MCC value.
+ * \returns string in dynamically allocated buffer.
+ */
+const char *osmo_mcc_name_c(const void *ctx, uint16_t mcc)
+{
+ char *buf = talloc_size(ctx, 8);
+ if (!buf)
+ return NULL;
+ return osmo_mcc_name_buf(buf, 8, mcc);
+}
+
/*! Return MNC string as standardized 2- or 3-digit with leading zeros.
* \param[out] buf caller-allocated output buffer
* \param[in] buf_len size of buf in bytes
@@ -124,6 +137,20 @@ char *osmo_mnc_name_buf(char *buf, size_t buf_len, uint16_t mnc, bool mnc_3_digi
return buf;
}
+/*! Return MNC string as standardized 2- or 3-digit with leading zeros, into a talloc-allocated buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] mnc MNC value.
+ * \param[in] mnc_3_digits True if an MNC should fill three digits, only has an effect if MNC < 100.
+ * \returns string in dynamically allocated buffer.
+ */
+char *osmo_mnc_name_c(const void *ctx, uint16_t mnc, bool mnc_3_digits)
+{
+ char *buf = talloc_size(ctx, 8);
+ if (!buf)
+ return buf;
+ return osmo_mnc_name_buf(buf, 8, mnc, mnc_3_digits);
+}
+
/*! Return MNC string as standardized 2- or 3-digit with leading zeros.
* \param[in] mnc MNC value.
* \param[in] mnc_3_digits True if an MNC should fill three digits, only has an effect if MNC < 100.
@@ -170,6 +197,20 @@ const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn)
return osmo_plmn_name_buf(buf, sizeof(buf), plmn);
}
+/*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros, into
+ * a dynamically-allocated output buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] plmn MCC-MNC value.
+ * \returns string in dynamically allocated buffer.
+ */
+char *osmo_plmn_name_c(const void *ctx, const struct osmo_plmn_id *plmn)
+{
+ char *buf = talloc_size(ctx, 16);
+ if (!buf)
+ return NULL;
+ return osmo_plmn_name_buf(buf, 16, plmn);
+}
+
/*! Return MCC-MNC-LAC as string, in caller-provided output buffer.
* \param[out] buf caller-allocated output buffer
* \param[in] buf_len size of buf in bytes
@@ -193,6 +234,19 @@ const char *osmo_lai_name(const struct osmo_location_area_id *lai)
return osmo_lai_name_buf(buf, sizeof(buf), lai);
}
+/*! Return MCC-MNC-LAC as string, in a talloc-allocated output buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] lai LAI to encode, the rac member is ignored.
+ * \returns string representation of lai in dynamically allocated buffer.
+ */
+char *osmo_lai_name_c(const void *ctx, const struct osmo_location_area_id *lai)
+{
+ char *buf = talloc_size(ctx, 32);
+ if (!buf)
+ return NULL;
+ return osmo_lai_name_buf(buf, 32, lai);
+}
+
/*! Return MCC-MNC-LAC-CI as string, in caller-provided output buffer.
* \param[out] buf caller-allocated output buffer
* \param[in] buf_len size of buf in bytes
@@ -226,6 +280,17 @@ const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi)
return osmo_cgi_name_buf(buf, sizeof(buf), cgi);
}
+/*! Return MCC-MNC-LAC-CI as string, in a talloc-allocated output buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] cgi CGI to encode.
+ * \returns string representation of CGI in dynamically-allocated buffer.
+ */
+char *osmo_cgi_name_c(const void *ctx, const struct osmo_cell_global_id *cgi)
+{
+ char *buf = talloc_size(ctx, 32);
+ return osmo_cgi_name_buf(buf, 32, cgi);
+}
+
static void to_bcd(uint8_t *bcd, uint16_t val)
{
bcd[2] = val % 10;
@@ -259,6 +324,19 @@ const char *osmo_gummei_name(const struct osmo_gummei *gummei)
return osmo_gummei_name_buf(buf, sizeof(buf), gummei);
}
+/*! Return string representation of GUMMEI in static output buffer.
+ * \param[out] buf pointer to caller-provided output buffer
+ * \param[in] buf_len size of buf in bytes
+ * \param[in] gummei GUMMEI to be stringified
+ * \returns pointer to static output buffer
+ */
+char *osmo_gummei_name_c(const void *ctx, const struct osmo_gummei *gummei)
+{
+ char *buf = talloc_size(ctx, 32);
+ if (!buf)
+ return NULL;
+ return osmo_gummei_name_buf(buf, 32, gummei);
+}
/* Convert MCC + MNC to BCD representation
* \param[out] bcd_dst caller-allocated memory for output
diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c
index a45d67bc..c2c19cfe 100644
--- a/src/gsm/gsm48.c
+++ b/src/gsm/gsm48.c
@@ -36,6 +36,7 @@
#include <osmocom/core/byteswap.h>
#include <osmocom/core/bit16gen.h>
#include <osmocom/core/bit32gen.h>
+#include <osmocom/core/talloc.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gsm/gsm0502.h>
@@ -206,6 +207,19 @@ const char *osmo_rai_name(const struct gprs_ra_id *rai)
return osmo_rai_name_buf(buf, sizeof(buf), rai);
}
+/*! Return MCC-MNC-LAC-RAC as string, in dynamically-allocated output buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] rai RAI to encode.
+ * \returns string representation in dynamically-allocated output buffer.
+ */
+char *osmo_rai_name_c(const void *ctx, const struct gprs_ra_id *rai)
+{
+ char *buf = talloc_size(ctx, 32);
+ if (!buf)
+ return NULL;
+ return osmo_rai_name_buf(buf, 32, rai);
+}
+
/* FIXME: convert to value_string */
static const char *cc_state_names[32] = {
"NULL",
@@ -492,6 +506,22 @@ const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len)
return osmo_mi_name_buf(mi_name, sizeof(mi_name), mi, mi_len);
}
+/*! Return a human readable representation of a Mobile Identity in dynamically-allocated buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] mi Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data.
+ * \param[in] mi_len Length of mi.
+ * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid" in a
+ * dynamically-allocated output buffer.
+ */
+char *osmo_mi_name_c(const void *ctx, const uint8_t *mi, uint8_t mi_len)
+{
+ size_t buf_len = 10 + GSM48_MI_SIZE + 1;
+ char *mi_name = talloc_size(ctx, buf_len);
+ if (!mi_name)
+ return NULL;
+ return osmo_mi_name_buf(mi_name, buf_len, mi, mi_len);
+}
+
/*! Checks is particular message is cipherable in A/Gb mode according to
* 3GPP TS 24.008 ยง 4.7.1.2
* \param[in] hdr Message header
@@ -1124,6 +1154,22 @@ const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type)
return gsm48_pdisc_msgtype_name_buf(namebuf, sizeof(namebuf), pdisc, msg_type);
}
+/*! Compose a string naming the message type for given protocol, in a dynamically-allocated buffer.
+ * If the message type string is known, return the message type name, otherwise
+ * return "<protocol discriminator name>:<message type in hex>".
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM
+ * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST
+ * \returns string representation in dynamically allocated output buffer.
+ */
+char *gsm48_pdisc_msgtype_name_c(const void *ctx, uint8_t pdisc, uint8_t msg_type)
+{
+ char *namebuf = talloc_size(ctx, 64);
+ if (!namebuf)
+ return NULL;
+ return gsm48_pdisc_msgtype_name_buf(namebuf, 64, pdisc, msg_type);
+}
+
const struct value_string gsm48_reject_value_names[] = {
{ GSM48_REJECT_IMSI_UNKNOWN_IN_HLR, "IMSI_UNKNOWN_IN_HLR" },
{ GSM48_REJECT_ILLEGAL_MS, "ILLEGAL_MS" },
@@ -1261,6 +1307,19 @@ const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm)
return osmo_gsm48_classmark_a5_name_buf(buf, sizeof(buf), cm);
}
+/*! Return a string representation of A5 cipher algorithms indicated by Classmark 1, 2 and 3.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] cm Classmarks.
+ * \returns string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3" in dynamically-allocated
+ * output buffer.
+ */
+char *osmo_gsm48_classmark_a5_name_c(const void *ctx, const struct osmo_gsm48_classmark *cm)
+{
+ char *buf = talloc_size(ctx, 128);
+ if (!buf)
+ return NULL;
+ return osmo_gsm48_classmark_a5_name_buf(buf, 128, cm);
+}
/*! Overwrite dst with the Classmark information present in src.
* Add an new Classmark and overwrite in dst what src has to offer, but where src has no Classmark information, leave
diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c
index f2bf57bf..1450ed0b 100644
--- a/src/gsm/gsm_utils.c
+++ b/src/gsm/gsm_utils.c
@@ -900,6 +900,13 @@ char *osmo_dump_gsmtime(const struct gsm_time *tm)
return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm);
}
+char *osmo_dump_gsmtime_c(const void *ctx, const struct gsm_time *tm)
+{
+ char *buf = talloc_size(ctx, 64);
+ if (!buf)
+ return NULL;
+ return osmo_dump_gsmtime_buf(buf, 64, tm);
+}
/*! append range1024 encoded data to bit vector
* \param[out] bv Caller-provided output bit-vector
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index a69fb606..56481fdd 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -10,6 +10,7 @@ abis_nm_chcomb4pchan;
abis_nm_debugp_foh;
abis_nm_dump_foh;
abis_nm_dump_foh_buf;
+abis_nm_dump_foh_c;
abis_nm_event_type_name;
abis_nm_nack_cause_name;
abis_nm_nack_name;
@@ -212,8 +213,11 @@ gsm0808_enc_cell_id;
gsm0808_dec_cell_id;
gsm0808_cell_id_name;
gsm0808_cell_id_name2;
+gsm0808_cell_id_name_buf;
+gsm0808_cell_id_name_c;
gsm0808_cell_id_list_name;
gsm0808_cell_id_list_name_buf;
+gsm0808_cell_id_list_name_c;
gsm0808_cell_id_discr_names;
gsm0808_cell_id_u_name;
gsm0808_cell_ids_match;
@@ -227,6 +231,7 @@ gsm0808_permitted_speech_names;
gsm0808_chosen_enc_alg_names;
gsm0808_channel_type_name;
gsm0808_channel_type_name_buf;
+gsm0808_channel_type_name_c;
gsm0808_lcls_config_names;
gsm0808_lcls_control_names;
gsm0808_lcls_status_names;
@@ -255,6 +260,7 @@ osmo_gcr_dump;
osmo_gcr_dump_buf;
osmo_lcls_dump;
osmo_lcls_dump_buf;
+osmo_lcls_dump_c;
gsm0858_rsl_ul_meas_enc;
@@ -350,6 +356,7 @@ gsm48_dtx_mode;
gsm48_mi_type_name;
osmo_mi_name;
osmo_mi_name_buf;
+osmo_mi_name_c;
gsm48_mcc_mnc_to_bcd;
gsm48_mcc_mnc_from_bcd;
gsm48_generate_lai2;
@@ -360,20 +367,27 @@ osmo_plmn_to_bcd;
osmo_plmn_from_bcd;
osmo_mcc_name;
osmo_mcc_name_buf;
+osmo_mcc_name_c;
osmo_mnc_name;
osmo_mnc_name_buf;
+osmo_mnc_name_c;
osmo_plmn_name;
osmo_plmn_name_buf;
+osmo_plmn_name_c;
osmo_plmn_name2;
osmo_lai_name;
osmo_lai_name_buf;
+osmo_lai_name_c;
osmo_rai_name;
osmo_rai_name_buf;
+osmo_rai_name_c;
osmo_cgi_name;
osmo_cgi_name_buf;
+osmo_cgi_name_c;
osmo_cgi_name2;
osmo_gummei_name;
osmo_gummei_name_buf;
+osmo_gummei_name_c;
osmo_mnc_from_str;
osmo_mnc_cmp;
osmo_plmn_cmp;
@@ -391,6 +405,7 @@ gsm48_cc_msgtype_names;
gsm48_cc_cause_names;
gsm48_pdisc_msgtype_name;
gsm48_pdisc_msgtype_name_buf;
+gsm48_pdisc_msgtype_name_c;
gsm48_reject_value_names;
gsm_7bit_decode;
@@ -417,6 +432,7 @@ gsm_get_octet_len;
gsm_gsmtime2fn;
osmo_dump_gsmtime;
osmo_dump_gsmtime_buf;
+osmo_dump_gsmtime_c;
gsm_milenage;
gsm_septet_encode;
@@ -487,6 +503,7 @@ rsl_ccch_conf_to_bs_cc_chans;
rsl_ccch_conf_to_bs_ccch_sdcch_comb;
rsl_chan_nr_str;
rsl_chan_nr_str_buf;
+rsl_chan_nr_str_c;
rsl_dec_chan_nr;
rsl_enc_chan_nr;
rsl_err_name;
@@ -549,8 +566,10 @@ ipa_send;
osmo_apn_qualify;
osmo_apn_qualify_buf;
+osmo_apn_qualify_c;
osmo_apn_qualify_from_imsi;
osmo_apn_qualify_from_imsi_buf;
+osmo_apn_qualify_from_imsi_c;
osmo_apn_to_str;
osmo_apn_from_str;
@@ -610,6 +629,7 @@ osmo_gsm48_classmark2_is_r99;
osmo_gsm48_classmark_supports_a5;
osmo_gsm48_classmark_a5_name;
osmo_gsm48_classmark_a5_name_buf;
+osmo_gsm48_classmark_a5_name_c;
osmo_gsm48_classmark_update;
local: *;
diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c
index 7bc60027..17774799 100644
--- a/src/gsm/rsl.c
+++ b/src/gsm/rsl.c
@@ -258,6 +258,19 @@ const char *rsl_chan_nr_str(uint8_t chan_nr)
return rsl_chan_nr_str_buf(str, sizeof(str), chan_nr);
}
+/*! Get human-readable string for RSL channel number, in dynamically-allocated buffer.
+ * \param[in] ctx talloc context from which to allocate output buffer
+ * \param[in] chan_nr channel number to be stringified
+ * \returns dynamically-allocated buffer with string representation
+ */
+char *rsl_chan_nr_str_c(const void *ctx, uint8_t chan_nr)
+{
+ char *str = talloc_size(ctx, 20);
+ if (!str)
+ return NULL;
+ return rsl_chan_nr_str_buf(str, 20, chan_nr);
+}
+
static const struct value_string rsl_err_vals[] = {
{ RSL_ERR_RADIO_IF_FAIL, "Radio Interface Failure" },
{ RSL_ERR_RADIO_LINK_FAIL, "Radio Link Failure" },
diff --git a/src/msgb.c b/src/msgb.c
index 47b413b9..5a154e56 100644
--- a/src/msgb.c
+++ b/src/msgb.c
@@ -64,9 +64,8 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
-void *tall_msgb_ctx = NULL;
-
-/*! Allocate a new message buffer
+/*! Allocate a new message buffer from given talloc cotext
+ * \param[in] ctx talloc context from which to allocate
* \param[in] size Length in octets, including headroom
* \param[in] name Human-readable name to be associated with msgb
* \returns dynamically-allocated \ref msgb
@@ -75,11 +74,11 @@ void *tall_msgb_ctx = NULL;
* memory buffer for the actual message data (size specified by \a size)
* using the talloc memory context previously set by \ref msgb_set_talloc_ctx
*/
-struct msgb *msgb_alloc(uint16_t size, const char *name)
+struct msgb *msgb_alloc_c(const void *ctx, uint16_t size, const char *name)
{
struct msgb *msg;
- msg = talloc_named_const(tall_msgb_ctx, sizeof(*msg) + size, name);
+ msg = talloc_named_const(ctx, sizeof(*msg) + size, name);
if (!msg) {
LOGP(DLGLOBAL, LOGL_FATAL, "Unable to allocate a msgb: "
"name='%s', size=%u\n", name, size);
@@ -98,6 +97,24 @@ struct msgb *msgb_alloc(uint16_t size, const char *name)
return msg;
}
+/* default msgb allocation context for msgb_alloc() */
+void *tall_msgb_ctx = NULL;
+
+/*! Allocate a new message buffer from tall_msgb_ctx
+ * \param[in] size Length in octets, including headroom
+ * \param[in] name Human-readable name to be associated with msgb
+ * \returns dynamically-allocated \ref msgb
+ *
+ * This function allocates a 'struct msgb' as well as the underlying
+ * memory buffer for the actual message data (size specified by \a size)
+ * using the talloc memory context previously set by \ref msgb_set_talloc_ctx
+ */
+struct msgb *msgb_alloc(uint16_t size, const char *name)
+{
+ return msgb_alloc_c(tall_msgb_ctx, size, name);
+}
+
+
/*! Release given message buffer
* \param[in] m Message buffer to be freed
*/
@@ -309,11 +326,11 @@ void *msgb_talloc_ctx_init(void *root_ctx, unsigned int pool_size)
* \param[in] msg The old msgb object
* \param[in] name Human-readable name to be associated with msgb
*/
-struct msgb *msgb_copy(const struct msgb *msg, const char *name)
+struct msgb *msgb_copy_c(const void *ctx, const struct msgb *msg, const char *name)
{
struct msgb *new_msg;
- new_msg = msgb_alloc(msg->data_len, name);
+ new_msg = msgb_alloc_c(ctx, msg->data_len, name);
if (!new_msg)
return NULL;
@@ -338,6 +355,19 @@ struct msgb *msgb_copy(const struct msgb *msg, const char *name)
return new_msg;
}
+/*! Copy an msgb.
+ *
+ * This function allocates a new msgb, copies the data buffer of msg,
+ * and adjusts the pointers (incl l1h-l4h) accordingly. The cb part
+ * is not copied.
+ * \param[in] msg The old msgb object
+ * \param[in] name Human-readable name to be associated with msgb
+ */
+struct msgb *msgb_copy(const struct msgb *msg, const char *name)
+{
+ return msgb_copy_c(tall_msgb_ctx, msg, name);
+}
+
/*! Resize an area within an msgb
*
* This resizes a sub area of the msgb data and adjusts the pointers (incl
@@ -485,6 +515,19 @@ const char *msgb_hexdump(const struct msgb *msg)
return msgb_hexdump_buf(buf, sizeof(buf), msg);
}
+/*! Return a dynamically allocated buffer containing a hexdump of the msg
+ * \param[in] ctx talloc context from where to allocate the output string
+ * \param[in] msg message buffer
+ * \returns a pointer to a static char array
+ */
+char *msgb_hexdump_c(const void *ctx, const struct msgb *msg)
+{
+ char *buf = talloc_size(ctx, msgb_length(msg)*3 + 100);
+ if (!buf)
+ return NULL;
+ return msgb_hexdump_buf(buf, sizeof(buf), msg);
+}
+
/*! Print a string to the end of message buffer.
* \param[in] msgb message buffer.
* \param[in] format format string.
diff --git a/src/sim/core.c b/src/sim/core.c
index 998e836b..63b3000b 100644
--- a/src/sim/core.c
+++ b/src/sim/core.c
@@ -305,6 +305,14 @@ char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in)
return osim_print_sw_buf(sw_print_buf, sizeof(sw_print_buf), ch, sw_in);
}
+char *osim_print_sw_c(const void *ctx, const struct osim_card_hdl *ch, uint16_t sw_in)
+{
+ char *buf = talloc_size(ctx, 256);
+ if (!buf)
+ return NULL;
+ return osim_print_sw_buf(buf, 256, ch, sw_in);
+}
+
const struct osim_card_sw *osim_find_sw(const struct osim_card_profile *cp,
uint16_t sw_in)
{
diff --git a/src/socket.c b/src/socket.c
index 3a46ad02..c817e723 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -827,6 +827,20 @@ const char *osmo_sock_get_name2(int fd)
return str;
}
+/*! Get address/port information on socket in static string, like "r=1.2.3.4:5<->l=6.7.8.9:10".
+ * This does not include braces like osmo_sock_get_name().
+ * \param[in] fd File descriptor of socket.
+ * \return Static string buffer containing the result.
+ */
+char *osmo_sock_get_name2_c(const void *ctx, int fd)
+{
+ char *str = talloc_size(ctx, OSMO_SOCK_NAME_MAXLEN);
+ if (!str)
+ return NULL;
+ osmo_sock_get_name_buf(str, sizeof(str), fd);
+ return str;
+}
+
static int sock_get_domain(int fd)
{
int domain;
diff --git a/src/utils.c b/src/utils.c
index 47963650..b8b4ef56 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -338,6 +338,27 @@ char *osmo_hexdump(const unsigned char *buf, int len)
}
/*! Convert binary sequence to hexadecimal ASCII string
+ * \param[in] ctx talloc context from where to allocate the output string
+ * \param[in] buf pointer to sequence of bytes
+ * \param[in] len length of buf in number of bytes
+ * \returns pointer to zero-terminated string
+ *
+ * This function will print a sequence of bytes as hexadecimal numbers,
+ * adding one space character between each byte (e.g. "1a ef d9")
+ *
+ * The maximum size of the output buffer is 4096 bytes, i.e. the maximum
+ * number of input bytes that can be printed in one call is 1365!
+ */
+char *osmo_hexdump_c(const void *ctx, const unsigned char *buf, int len)
+{
+ char *hexd_buff = talloc_size(ctx, len*3 + 1);
+ if (!hexd_buff)
+ return NULL;
+ osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, " ", true);
+ return hexd_buff;
+}
+
+/*! Convert binary sequence to hexadecimal ASCII string
* \param[in] buf pointer to sequence of bytes
* \param[in] len length of buf in number of bytes
* \returns pointer to zero-terminated string
@@ -354,6 +375,28 @@ char *osmo_hexdump_nospc(const unsigned char *buf, int len)
return hexd_buff;
}
+/*! Convert binary sequence to hexadecimal ASCII string
+ * \param[in] ctx talloc context from where to allocate the output string
+ * \param[in] buf pointer to sequence of bytes
+ * \param[in] len length of buf in number of bytes
+ * \returns pointer to zero-terminated string
+ *
+ * This function will print a sequence of bytes as hexadecimal numbers,
+ * without any space character between each byte (e.g. "1aefd9")
+ *
+ * The maximum size of the output buffer is 4096 bytes, i.e. the maximum
+ * number of input bytes that can be printed in one call is 2048!
+ */
+char *osmo_hexdump_nospc_c(const void *ctx, const unsigned char *buf, int len)
+{
+ char *hexd_buff = talloc_size(ctx, len*2 + 1);
+ if (!hexd_buff)
+ return NULL;
+ osmo_hexdump_buf(hexd_buff, sizeof(hexd_buff), buf, len, "", true);
+ return hexd_buff;
+}
+
+
/* Compat with previous typo to preserve abi */
char *osmo_osmo_hexdump_nospc(const unsigned char *buf, int len)
#if defined(__MACH__) && defined(__APPLE__)
@@ -639,6 +682,19 @@ const char *osmo_escape_str(const char *str, int in_len)
return osmo_escape_str_buf(str, in_len, namebuf, sizeof(namebuf));
}
+/*! Return the string with all non-printable characters escaped, in dynamically-allocated buffer.
+ * \param[in] str A string that may contain any characters.
+ * \param[in] len Pass -1 to print until nul char, or >= 0 to force a length.
+ * \returns dynamically-allocated output buffer, containing an escaped representation
+ */
+char *osmo_escape_str_c(const void *ctx, const char *str, int in_len)
+{
+ char *buf = talloc_size(ctx, in_len+1);
+ if (!buf)
+ return NULL;
+ return osmo_escape_str_buf(str, in_len, buf, in_len+1);
+}
+
/*! Like osmo_escape_str(), but returns double-quotes around a string, or "NULL" for a NULL string.
* This allows passing any char* value and get its C representation as string.
* \param[in] str A string that may contain any characters.
@@ -671,6 +727,20 @@ const char *osmo_quote_str(const char *str, int in_len)
return osmo_quote_str_buf(str, in_len, namebuf, sizeof(namebuf));
}
+/*! Like osmo_quote_str_buf() but returns the result in a dynamically-allocated buffer.
+ * The static buffer is shared with get_value_string() and osmo_escape_str().
+ * \param[in] str A string that may contain any characters.
+ * \param[in] in_len Pass -1 to print until nul char, or >= 0 to force a length.
+ * \returns dynamically-allocated buffer containing a quoted and escaped representation.
+ */
+char *osmo_quote_str_c(const void *ctx, const char *str, int in_len)
+{
+ char *buf = talloc_size(ctx, OSMO_MAX(in_len+2, 32));
+ if (!buf)
+ return NULL;
+ return osmo_quote_str_buf(str, in_len, buf, 32);
+}
+
/*! perform an integer square root operation on unsigned 32bit integer.
* This implementation is taken from "Hacker's Delight" Figure 11-1 "Integer square root, Newton's
* method", which can also be found at http://www.hackersdelight.org/hdcodetxt/isqrt.c.txt */
@@ -754,6 +824,21 @@ const char *osmo_str_tolower(const char *src)
return buf;
}
+/*! Convert a string to lowercase, dynamically allocating the output from given talloc context
+ * See also osmo_str_tolower_buf().
+ * \param[in] ctx talloc context from where to allocate the output string
+ * \param[in] src String to convert to lowercase.
+ * \returns Resulting lowercase string in a dynamically allocated buffer, always nul terminated.
+ */
+char *osmo_str_tolower_c(const void *ctx, const char *src)
+{
+ char *buf = talloc_size(ctx, strlen(src)+1);
+ if (!buf)
+ return NULL;
+ osmo_str_tolower_buf(buf, sizeof(buf), src);
+ return buf;
+}
+
/*! Convert a string to uppercase, while checking buffer size boundaries.
* The result written to \a dest is guaranteed to be nul terminated if \a dest_len > 0.
* If dest == src, the string is converted in-place, if necessary truncated at dest_len - 1 characters
@@ -797,6 +882,21 @@ const char *osmo_str_toupper(const char *src)
return buf;
}
+/*! Convert a string to uppercase, dynamically allocating the output from given talloc context
+ * See also osmo_str_tolower_buf().
+ * \param[in] ctx talloc context from where to allocate the output string
+ * \param[in] src String to convert to uppercase.
+ * \returns Resulting uppercase string in a dynamically allocated buffer, always nul terminated.
+ */
+char *osmo_str_toupper_c(const void *ctx, const char *src)
+{
+ char *buf = talloc_size(ctx, strlen(src)+1);
+ if (!buf)
+ return NULL;
+ osmo_str_toupper_buf(buf, sizeof(buf), src);
+ return buf;
+}
+
/*! Calculate the Luhn checksum (as used for IMEIs).
* \param[in] in Input digits in ASCII string representation.
* \param[in] in_len Count of digits to use for the input (14 for IMEI).