aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm
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 /src/gsm
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
Diffstat (limited to 'src/gsm')
-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
8 files changed, 238 insertions, 4 deletions
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" },