diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/gb/gprs_ns.c | 16 | ||||
| -rw-r--r-- | src/gb/libosmogb.map | 1 | ||||
| -rw-r--r-- | src/gsm/abis_nm.c | 13 | ||||
| -rw-r--r-- | src/gsm/apn.c | 27 | ||||
| -rw-r--r-- | src/gsm/gsm0808_utils.c | 40 | ||||
| -rw-r--r-- | src/gsm/gsm23003.c | 101 | ||||
| -rw-r--r-- | src/gsm/gsm48.c | 92 | ||||
| -rw-r--r-- | src/gsm/gsm_utils.c | 13 | ||||
| -rw-r--r-- | src/gsm/libosmogsm.map | 18 | ||||
| -rw-r--r-- | src/gsm/rsl.c | 40 | ||||
| -rw-r--r-- | src/msgb.c | 38 | ||||
| -rw-r--r-- | src/sim/core.c | 24 | ||||
| -rw-r--r-- | src/utils.c | 31 | 
13 files changed, 337 insertions, 117 deletions
| diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c index c7ff78ed..fc120cec 100644 --- a/src/gb/gprs_ns.c +++ b/src/gb/gprs_ns.c @@ -1525,17 +1525,15 @@ int gprs_ns_rcvmsg(struct gprs_ns_inst *nsi, struct msgb *msg,  	return rc;  } -const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc) +char *gprs_ns_ll_str_buf(char *buf, size_t buf_len, const struct gprs_nsvc *nsvc)  { -	static char buf[80]; -  	switch(nsvc->ll) {  	case GPRS_NS_LL_UDP: -		snprintf(buf, sizeof(buf), "%s:%u", +		snprintf(buf, buf_len, "%s:%u",  			 inet_ntoa(nsvc->ip.bts_addr.sin_addr), osmo_ntohs(nsvc->ip.bts_addr.sin_port));  		break;  	case GPRS_NS_LL_FR_GRE: -		snprintf(buf, sizeof(buf), "%s:%u", +		snprintf(buf, buf_len, "%s:%u",  			 inet_ntoa(nsvc->frgre.bts_addr.sin_addr), osmo_ntohs(nsvc->frgre.bts_addr.sin_port));  		break;  	default: @@ -1543,11 +1541,17 @@ const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc)  		break;  	} -	buf[sizeof(buf) - 1] = '\0'; +	buf[buf_len - 1] = '\0';  	return buf;  } +const char *gprs_ns_ll_str(const struct gprs_nsvc *nsvc) +{ +	static char buf[80]; +	return gprs_ns_ll_str_buf(buf, sizeof(buf), nsvc); +} +  void gprs_ns_ll_copy(struct gprs_nsvc *nsvc, struct gprs_nsvc *other)  {  	nsvc->ll = other->ll; diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 2ad3ff71..21929da1 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -64,6 +64,7 @@ gprs_ns_tx_status;  gprs_ns_tx_unblock;  gprs_ns_vty_init;  gprs_ns_ll_str; +gprs_ns_ll_str_buf;  gprs_ns_ll_copy;  gprs_ns_ll_clear;  gprs_ns_msgb_alloc; diff --git a/src/gsm/abis_nm.c b/src/gsm/abis_nm.c index 49d05ba5..e25fdd03 100644 --- a/src/gsm/abis_nm.c +++ b/src/gsm/abis_nm.c @@ -928,14 +928,19 @@ enum gsm_phys_chan_config abis_nm_pchan4chcomb(uint8_t chcomb)  	return GSM_PCHAN_NONE;  } -const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh) +char *abis_nm_dump_foh_buf(char *buf, size_t buf_len, const struct abis_om_fom_hdr *foh)  { -	static char foh_buf[128]; -	snprintf(foh_buf, sizeof(foh_buf), "OC=%s(%02x) INST=(%02x,%02x,%02x)", +	snprintf(buf, buf_len, "OC=%s(%02x) INST=(%02x,%02x,%02x)",  		get_value_string(abis_nm_obj_class_names, foh->obj_class),  		foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr,  		foh->obj_inst.ts_nr); -	return foh_buf; +	return buf; +} + +const char *abis_nm_dump_foh(const struct abis_om_fom_hdr *foh) +{ +	static char foh_buf[128]; +	return abis_nm_dump_foh_buf(foh_buf, sizeof(foh_buf), foh);  }  /* this is just for compatibility reasons, it is now a macro */ diff --git a/src/gsm/apn.c b/src/gsm/apn.c index 26746631..4ab370c5 100644 --- a/src/gsm/apn.c +++ b/src/gsm/apn.c @@ -32,17 +32,22 @@  static char apn_strbuf[APN_MAXLEN+1]; -char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni) +char *osmo_apn_qualify_buf(char *buf, size_t buf_len, unsigned int mcc, unsigned int mnc, const char *ni)  { -	snprintf(apn_strbuf, sizeof(apn_strbuf)-1, APN_GPRS_FMT, -		ni, mnc, mcc); -	apn_strbuf[sizeof(apn_strbuf)-1] = '\0'; +	snprintf(buf, buf_len-1, APN_GPRS_FMT, ni, mnc, mcc); +	buf[buf_len-1] = '\0'; -	return apn_strbuf; +	return buf;  } -char *osmo_apn_qualify_from_imsi(const char *imsi, -				 const char *ni, int have_3dig_mnc) +char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni) +{ +	return osmo_apn_qualify_buf(apn_strbuf, sizeof(apn_strbuf), mcc, mnc, ni); +} + + +char *osmo_apn_qualify_from_imsi_buf(char *buf, size_t buf_len, const char *imsi, +				     const char *ni, int have_3dig_mnc)  {  	char cbuf[3+1], nbuf[3+1]; @@ -56,7 +61,13 @@ char *osmo_apn_qualify_from_imsi(const char *imsi,  		strncpy(nbuf, imsi+3, 2);  		nbuf[2] = '\0';  	} -	return osmo_apn_qualify(atoi(cbuf), atoi(nbuf), ni); +	return osmo_apn_qualify_buf(buf, buf_len, atoi(cbuf), atoi(nbuf), ni); +} + +char *osmo_apn_qualify_from_imsi(const char *imsi, +				 const char *ni, int have_3dig_mnc) +{ +	return osmo_apn_qualify_from_imsi_buf(apn_strbuf, sizeof(apn_strbuf), imsi, ni, have_3dig_mnc);  }  /** diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index e0cdaaf6..52e46743 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -595,11 +595,13 @@ int gsm0808_dec_lcls(struct osmo_lcls *lcls, const struct tlv_parsed *tp)  static char dbuf[256];  /*! Dump LCLS parameters (GCR excluded) into string for printing. + *  \param[out] buf caller-allocated output string buffer + *  \param[in] buf_len size of buf in bytes   *  \param[in] lcls pointer to the struct to print.   *  \returns string representation of LCLS or NULL on error. */ -char *osmo_lcls_dump(const struct osmo_lcls *lcls) +char *osmo_lcls_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls)  { -	struct osmo_strbuf s = { .buf = dbuf, .len = 256 }; +	struct osmo_strbuf s = { .buf = buf, .len = buf_len };  	if (!lcls)  		return NULL; @@ -612,12 +614,22 @@ char *osmo_lcls_dump(const struct osmo_lcls *lcls)  	return dbuf;  } +/*! Dump LCLS parameters (GCR excluded) into static string buffer for printing. + *  \param[in] lcls pointer to the struct to print. + *  \returns string representation of LCLS in static buffer or NULL on error. */ +char *osmo_lcls_dump(const struct osmo_lcls *lcls) +{ +	return osmo_lcls_dump_buf(dbuf, sizeof(dbuf), lcls); +} +  /*! Dump GCR struct into string for printing. + *  \param[out] buf caller-allocated output string buffer + *  \param[in] buf_len size of buf in bytes   *  \param[in] lcls pointer to the struct to print.   *  \returns string representation of GCR or NULL on error. */ -char *osmo_gcr_dump(const struct osmo_lcls *lcls) +char *osmo_gcr_dump_buf(char *buf, size_t buf_len, const struct osmo_lcls *lcls)  { -	struct osmo_strbuf s = { .buf = dbuf, .len = 256 }; +	struct osmo_strbuf s = { .buf = buf, .len = buf_len };  	if (!lcls)  		return NULL; @@ -631,6 +643,15 @@ char *osmo_gcr_dump(const struct osmo_lcls *lcls)  	return dbuf;  } +/*! Dump GCR struct into static string buffer for printing. + *  \param[in] lcls pointer to the struct to print. + *  \returns string representation of GCR in static buffer or NULL on error. */ +char *osmo_gcr_dump(const struct osmo_lcls *lcls) +{ +	return osmo_gcr_dump_buf(dbuf, sizeof(dbuf), lcls); +} + +  /*! Encode TS 08.08 Encryption Information IE   *  \param[out] msg Message Buffer to which IE is to be appended   *  \param[in] ei Encryption Information to be encoded @@ -1838,13 +1859,18 @@ const char *gsm0808_cell_id_list_name(const struct gsm0808_cell_id_list2 *cil)  #undef APPEND_STR  #undef APPEND_CELL_ID_U -const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct) +char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct)  { -	static char buf[128]; -	snprintf(buf, sizeof(buf), "ch_indctr=0x%x ch_rate_type=0x%x perm_spch=%s", +	snprintf(buf, buf_len, "ch_indctr=0x%x ch_rate_type=0x%x perm_spch=%s",  		 ct->ch_indctr, ct->ch_rate_type,  		 osmo_hexdump(ct->perm_spch, ct->perm_spch_len));  	return buf;  } +const char *gsm0808_channel_type_name(const struct gsm0808_channel_type *ct) +{ +	static char buf[128]; +	return gsm0808_channel_type_name_buf(buf, sizeof(buf), ct); +} +  /*! @} */ diff --git a/src/gsm/gsm23003.c b/src/gsm/gsm23003.c index 720c09b6..bbfe236a 100644 --- a/src/gsm/gsm23003.c +++ b/src/gsm/gsm23003.c @@ -90,13 +90,37 @@ bool osmo_imei_str_valid(const char *imei, bool with_15th_digit)  }  /*! Return MCC string as standardized 3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] mcc  MCC value. + * \returns string in user-supplied output buffer + */ +char *osmo_mcc_name_buf(char *buf, size_t buf_len, uint16_t mcc) +{ +	snprintf(buf, buf_len, "%03u", mcc); +	return buf; +} + +/*! Return MCC string as standardized 3-digit with leading zeros.   * \param[in] mcc  MCC value.   * \returns string in static buffer.   */  const char *osmo_mcc_name(uint16_t mcc)  {  	static char buf[8]; -	snprintf(buf, sizeof(buf), "%03u", mcc); +	return osmo_mcc_name_buf(buf, sizeof(buf), mcc); +} + +/*! Return MNC string as standardized 2- or 3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] mnc  MNC value. + * \param[in] mnc_3_digits  True if an MNC should fill three digits, only has an effect if MNC < 100. + * \returns string in static buffer. + */ +char *osmo_mnc_name_buf(char *buf, size_t buf_len, uint16_t mnc, bool mnc_3_digits) +{ +	snprintf(buf, buf_len, "%0*u", mnc_3_digits ? 3 : 2, mnc);  	return buf;  } @@ -108,14 +132,21 @@ const char *osmo_mcc_name(uint16_t mcc)  const char *osmo_mnc_name(uint16_t mnc, bool mnc_3_digits)  {  	static char buf[8]; -	snprintf(buf, sizeof(buf), "%0*u", mnc_3_digits ? 3 : 2, mnc); -	return buf; +	return osmo_mnc_name_buf(buf, sizeof(buf), mnc, mnc_3_digits);  } -static inline void plmn_name(char *buf, size_t buflen, const struct osmo_plmn_id *plmn) +/*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] plmn  MCC-MNC value. + * \returns string in static buffer. + */ +char *osmo_plmn_name_buf(char *buf, size_t buf_len, const struct osmo_plmn_id *plmn)  { -	snprintf(buf, buflen, "%s-%s", osmo_mcc_name(plmn->mcc), -		 osmo_mnc_name(plmn->mnc, plmn->mnc_3_digits)); +	char mcc[8], mnc[8]; +	snprintf(buf, buf_len, "%s-%s", osmo_mcc_name_buf(mcc, sizeof(mcc), plmn->mcc), +		 osmo_mnc_name_buf(mnc, sizeof(mnc), plmn->mnc, plmn->mnc_3_digits)); +	return buf;  }  /*! Return MCC-MNC string as standardized 3-digit-dash-2/3-digit with leading zeros. @@ -125,10 +156,10 @@ static inline void plmn_name(char *buf, size_t buflen, const struct osmo_plmn_id  const char *osmo_plmn_name(const struct osmo_plmn_id *plmn)  {  	static char buf[16]; -	plmn_name(buf, sizeof(buf), plmn); -	return buf; +	return osmo_plmn_name_buf(buf, sizeof(buf), plmn);  } +  /*! Same as osmo_plmn_name(), but returning in a different static buffer.   * \param[in] plmn  MCC-MNC value.   * \returns string in static buffer. @@ -136,7 +167,19 @@ const char *osmo_plmn_name(const struct osmo_plmn_id *plmn)  const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn)  {  	static char buf[16]; -	plmn_name(buf, sizeof(buf), plmn); +	return osmo_plmn_name_buf(buf, sizeof(buf), plmn); +} + +/*! Return MCC-MNC-LAC as string, in caller-provided output buffer. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] lai  LAI to encode, the rac member is ignored. + * \returns buf + */ +char *osmo_lai_name_buf(char *buf, size_t buf_len, const struct osmo_location_area_id *lai) +{ +	char plmn[16]; +	snprintf(buf, buf_len, "%s-%u", osmo_plmn_name_buf(plmn, sizeof(plmn), &lai->plmn), lai->lac);  	return buf;  } @@ -147,13 +190,18 @@ const char *osmo_plmn_name2(const struct osmo_plmn_id *plmn)  const char *osmo_lai_name(const struct osmo_location_area_id *lai)  {  	static char buf[32]; -	snprintf(buf, sizeof(buf), "%s-%u", osmo_plmn_name(&lai->plmn), lai->lac); -	return buf; +	return osmo_lai_name_buf(buf, sizeof(buf), lai);  } -static const char *_cgi_name(const struct osmo_cell_global_id *cgi, char *buf, size_t buflen) +/*! Return MCC-MNC-LAC-CI as string, in caller-provided output buffer. + * \param[out] buf caller-allocated output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] cgi  CGI to encode. + * \returns buf + */ +char *osmo_cgi_name_buf(char *buf, size_t buf_len, const struct osmo_cell_global_id *cgi)  { -	snprintf(buf, buflen, "%s-%u", osmo_lai_name(&cgi->lai), cgi->cell_identity); +	snprintf(buf, buf_len, "%s-%u", osmo_lai_name(&cgi->lai), cgi->cell_identity);  	return buf;  } @@ -164,7 +212,7 @@ static const char *_cgi_name(const struct osmo_cell_global_id *cgi, char *buf, s  const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi)  {  	static char buf[32]; -	return _cgi_name(cgi, buf, sizeof(buf)); +	return osmo_cgi_name_buf(buf, sizeof(buf), cgi);  }  /*! Same as osmo_cgi_name(), but uses a different static buffer. @@ -175,7 +223,7 @@ const char *osmo_cgi_name(const struct osmo_cell_global_id *cgi)  const char *osmo_cgi_name2(const struct osmo_cell_global_id *cgi)  {  	static char buf[32]; -	return _cgi_name(cgi, buf, sizeof(buf)); +	return osmo_cgi_name_buf(buf, sizeof(buf), cgi);  }  static void to_bcd(uint8_t *bcd, uint16_t val) @@ -187,14 +235,31 @@ static void to_bcd(uint8_t *bcd, uint16_t val)  	bcd[0] = val % 10;  } -const char *osmo_gummei_name(const struct osmo_gummei *gummei) +/*! Return string representation of GUMMEI in caller-provided output buffer. + * \param[out] buf pointer to caller-provided output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] gummei GUMMEI to be stringified + * \returns buf + */ +char *osmo_gummei_name_buf(char *buf, size_t buf_len, const struct osmo_gummei *gummei)  { -	static char buf[32]; -	snprintf(buf, sizeof(buf), "%s-%04x-%02x", osmo_plmn_name(&gummei->plmn), +	char plmn[16]; +	snprintf(buf, buf_len, "%s-%04x-%02x", osmo_plmn_name_buf(plmn, sizeof(plmn), &gummei->plmn),  		 gummei->mme.group_id, gummei->mme.code);  	return buf;  } +/*! Return string representation of GUMMEI in static output buffer. + * \param[in] gummei GUMMEI to be stringified + * \returns pointer to static output buffer + */ +const char *osmo_gummei_name(const struct osmo_gummei *gummei) +{ +	static char buf[32]; +	return osmo_gummei_name_buf(buf, sizeof(buf), gummei); +} + +  /* Convert MCC + MNC to BCD representation   * \param[out] bcd_dst caller-allocated memory for output   * \param[in] mcc Mobile Country Code diff --git a/src/gsm/gsm48.c b/src/gsm/gsm48.c index 5dc30ad0..a45d67bc 100644 --- a/src/gsm/gsm48.c +++ b/src/gsm/gsm48.c @@ -182,6 +182,20 @@ const char *rr_cause_name(uint8_t cause)  	return get_value_string(rr_cause_names, cause);  } +/*! Return MCC-MNC-LAC-RAC as string, in a caller-provided output buffer. + * \param[out] buf caller-provided output buffer + * \param[in] buf_len size of buf in bytes + * \param[in] rai  RAI to encode. + * \returns buf + */ +char *osmo_rai_name_buf(char *buf, size_t buf_len, const struct gprs_ra_id *rai) +{ +	snprintf(buf, buf_len, "%s-%s-%u-%u", +		 osmo_mcc_name(rai->mcc), osmo_mnc_name(rai->mnc, rai->mnc_3_digits), rai->lac, +		 rai->rac); +	return buf; +} +  /*! Return MCC-MNC-LAC-RAC as string, in a static buffer.   * \param[in] rai  RAI to encode.   * \returns Static string buffer. @@ -189,10 +203,7 @@ const char *rr_cause_name(uint8_t cause)  const char *osmo_rai_name(const struct gprs_ra_id *rai)  {  	static char buf[32]; -	snprintf(buf, sizeof(buf), "%s-%s-%u-%u", -		 osmo_mcc_name(rai->mcc), osmo_mnc_name(rai->mnc, rai->mnc_3_digits), rai->lac, -		 rai->rac); -	return buf; +	return osmo_rai_name_buf(buf, sizeof(buf), rai);  }  /* FIXME: convert to value_string */ @@ -433,14 +444,15 @@ const char *gsm48_mi_type_name(uint8_t mi)  	return get_value_string(mi_type_names, mi);  } -/*! Return a human readable representation of a Mobile Identity in static buffer. +/*! Return a human readable representation of a Mobile Identity in caller-provided buffer. + * \param[out] buf caller-provided output buffer + * \param[in] buf_len size of buf in bytes   * \param[in] mi  Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data.   * \param[in] mi_len  Length of mi. - * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid"... + * \return buf   */ -const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) +char *osmo_mi_name_buf(char *buf, size_t buf_len, const uint8_t *mi, uint8_t mi_len)  { -	static char mi_name[10 + GSM48_MI_SIZE + 1];  	uint8_t mi_type;  	uint32_t tmsi;  	char mi_string[GSM48_MI_SIZE]; @@ -452,8 +464,8 @@ const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len)  		/* Table 10.5.4.3, reverse generate_mid_from_tmsi */  		if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) {  			tmsi = osmo_load32be(&mi[1]); -			snprintf(mi_name, sizeof(mi_name), "TMSI-0x%08" PRIX32, tmsi); -			return mi_name; +			snprintf(buf, buf_len, "TMSI-0x%08" PRIX32, tmsi); +			return buf;  		}  		return "TMSI-invalid"; @@ -461,14 +473,25 @@ const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len)  	case GSM_MI_TYPE_IMEI:  	case GSM_MI_TYPE_IMEISV:  		osmo_bcd2str(mi_string, sizeof(mi_string), mi, 1, (mi_len * 2) - (mi[0] & GSM_MI_ODD ? 0 : 1), true); -		snprintf(mi_name, sizeof(mi_name), "%s-%s", gsm48_mi_type_name(mi_type), mi_string); -		return mi_name; +		snprintf(buf, buf_len, "%s-%s", gsm48_mi_type_name(mi_type), mi_string); +		return buf;  	default:  		return "unknown";  	}  } +/*! Return a human readable representation of a Mobile Identity in static buffer. + * \param[in] mi  Mobile Identity buffer containing 3GPP TS 04.08 style MI type and data. + * \param[in] mi_len  Length of mi. + * \return A string like "IMSI-1234567", "TMSI-0x1234ABCD" or "unknown", "TMSI-invalid"... + */ +const char *osmo_mi_name(const uint8_t *mi, uint8_t mi_len) +{ +	static char mi_name[10 + GSM48_MI_SIZE + 1]; +	return osmo_mi_name_buf(mi_name, sizeof(mi_name), mi, mi_len); +} +  /*! Checks is particular message is cipherable in A/Gb mode according to   *         3GPP TS 24.008 ยง 4.7.1.2   *  \param[in] hdr Message header @@ -1050,16 +1073,17 @@ const struct value_string gsm48_nc_ss_msgtype_names[] = {  	{ 0, NULL }  }; -/*! Compose a string naming the message type for given protocol. +/*! Compose a string naming the message type for given protocol, in a caller-provided buffer.   * If the message type string is known, return the message type name, otherwise   * return "<protocol discriminator name>:<message type in hex>". + * \param[out] buf caller-allcated output string buffer + * \param[in] buf_len size of buf in bytes   * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM   * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST - * \returns statically allocated string or string constant. + * \returns buf   */ -const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type) +char *gsm48_pdisc_msgtype_name_buf(char *buf, size_t buf_len, uint8_t pdisc, uint8_t msg_type)  { -	static char namebuf[64];  	const struct value_string *msgt_names;  	switch (pdisc) { @@ -1081,11 +1105,23 @@ const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type)  	}  	if (msgt_names) -		return get_value_string(msgt_names, msg_type); +		snprintf(buf, buf_len, "%s", get_value_string(msgt_names, msg_type)); +	else +		snprintf(buf, buf_len, "%s:0x%02x", gsm48_pdisc_name(pdisc), msg_type); +	return buf; +} -	snprintf(namebuf, sizeof(namebuf), "%s:0x%02x", -		 gsm48_pdisc_name(pdisc), msg_type); -	return namebuf; +/*! Compose a string naming the message type for given protocol, in a static buffer. + * If the message type string is known, return the message type name, otherwise + * return "<protocol discriminator name>:<message type in hex>". + * \param[in] pdisc protocol discriminator like GSM48_PDISC_MM + * \param[in] msg_type message type like GSM48_MT_MM_LOC_UPD_REQUEST + * \returns statically allocated string or string constant. + */ +const char *gsm48_pdisc_msgtype_name(uint8_t pdisc, uint8_t msg_type) +{ +	static char namebuf[64]; +	return gsm48_pdisc_msgtype_name_buf(namebuf, sizeof(namebuf), pdisc, msg_type);  }  const struct value_string gsm48_reject_value_names[] = { @@ -1187,9 +1223,8 @@ bool osmo_gsm48_classmark_is_r99(const struct osmo_gsm48_classmark *cm)   * \param[in] cm  Classmarks.   * \returns A statically allocated string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3"   */ -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)  { -	static char buf[128];  	char cm1[42] = "no-cm1";  	char cm2[42] = " no-cm2";  	char cm3[42] = " no-cm3"; @@ -1212,10 +1247,21 @@ const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm)  			 cm->classmark3[0] & (1 << 2) ? " A5/6" : "",  			 cm->classmark3[0] & (1 << 3) ? " A5/7" : ""); -	snprintf(buf, sizeof(buf), "%s%s%s", cm1, cm2, cm3); +	snprintf(buf, buf_len, "%s%s%s", cm1, cm2, cm3);  	return buf;  } +/*! Return a string representation of A5 cipher algorithms indicated by Classmark 1, 2 and 3. + * \param[in] cm  Classmarks. + * \returns A statically allocated string like "cm1{a5/1=supported} cm2{0x23= A5/2 A5/3} no-cm3" + */ +const char *osmo_gsm48_classmark_a5_name(const struct osmo_gsm48_classmark *cm) +{ +	static char buf[128]; +	return osmo_gsm48_classmark_a5_name_buf(buf, sizeof(buf), 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   * dst unchanged. (For Classmark 2 and 3, dst will exactly match any non-zero Classmark length from src, hence may end diff --git a/src/gsm/gsm_utils.c b/src/gsm/gsm_utils.c index c9c15d57..f34d9ea5 100644 --- a/src/gsm/gsm_utils.c +++ b/src/gsm/gsm_utils.c @@ -886,16 +886,21 @@ uint32_t gsm_gsmtime2fn(struct gsm_time *time)  	return (51 * ((time->t3 - time->t2 + 26) % 26) + time->t3 + (26 * 51 * time->t1));  } -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)  { -	static char buf[64]; - -	snprintf(buf, sizeof(buf), "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8, +	snprintf(buf, buf_len, "%06"PRIu32"/%02"PRIu16"/%02"PRIu8"/%02"PRIu8"/%02"PRIu8,  		 tm->fn, tm->t1, tm->t2, tm->t3, (uint8_t)tm->fn%52);  	buf[sizeof(buf)-1] = '\0';  	return buf;  } +char *osmo_dump_gsmtime(const struct gsm_time *tm) +{ +	static char buf[64]; +	return osmo_dump_gsmtime_buf(buf, sizeof(buf), tm); +} + +  /*! append range1024 encoded data to bit vector   *  \param[out] bv Caller-provided output bit-vector   *  \param[in] r Input Range1024 sructure */ diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 3fadc5a0..a69fb606 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -9,6 +9,7 @@ abis_nm_fail_evt_vrep;  abis_nm_chcomb4pchan;  abis_nm_debugp_foh;  abis_nm_dump_foh; +abis_nm_dump_foh_buf;  abis_nm_event_type_name;  abis_nm_nack_cause_name;  abis_nm_nack_name; @@ -225,6 +226,7 @@ gsm0808_speech_codec_type_names;  gsm0808_permitted_speech_names;  gsm0808_chosen_enc_alg_names;  gsm0808_channel_type_name; +gsm0808_channel_type_name_buf;  gsm0808_lcls_config_names;  gsm0808_lcls_control_names;  gsm0808_lcls_status_names; @@ -250,7 +252,9 @@ osmo_enc_gcr;  osmo_dec_gcr;  osmo_gcr_eq;  osmo_gcr_dump; +osmo_gcr_dump_buf;  osmo_lcls_dump; +osmo_lcls_dump_buf;  gsm0858_rsl_ul_meas_enc; @@ -345,6 +349,7 @@ gsm48_set_dtx;  gsm48_dtx_mode;  gsm48_mi_type_name;  osmo_mi_name; +osmo_mi_name_buf;  gsm48_mcc_mnc_to_bcd;  gsm48_mcc_mnc_from_bcd;  gsm48_generate_lai2; @@ -354,14 +359,21 @@ osmo_bts_feature_name;  osmo_plmn_to_bcd;  osmo_plmn_from_bcd;  osmo_mcc_name; +osmo_mcc_name_buf;  osmo_mnc_name; +osmo_mnc_name_buf;  osmo_plmn_name; +osmo_plmn_name_buf;  osmo_plmn_name2;  osmo_lai_name; +osmo_lai_name_buf;  osmo_rai_name; +osmo_rai_name_buf;  osmo_cgi_name; +osmo_cgi_name_buf;  osmo_cgi_name2;  osmo_gummei_name; +osmo_gummei_name_buf;  osmo_mnc_from_str;  osmo_mnc_cmp;  osmo_plmn_cmp; @@ -378,6 +390,7 @@ gsm48_mm_msgtype_names;  gsm48_cc_msgtype_names;  gsm48_cc_cause_names;  gsm48_pdisc_msgtype_name; +gsm48_pdisc_msgtype_name_buf;  gsm48_reject_value_names;  gsm_7bit_decode; @@ -403,6 +416,7 @@ gsm_fn_as_gsmtime_str;  gsm_get_octet_len;  gsm_gsmtime2fn;  osmo_dump_gsmtime; +osmo_dump_gsmtime_buf;  gsm_milenage;  gsm_septet_encode; @@ -472,6 +486,7 @@ rsl_ipac_eie_tlvdef;  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_dec_chan_nr;  rsl_enc_chan_nr;  rsl_err_name; @@ -533,7 +548,9 @@ ipa_prepend_header_ext;  ipa_send;  osmo_apn_qualify; +osmo_apn_qualify_buf;  osmo_apn_qualify_from_imsi; +osmo_apn_qualify_from_imsi_buf;  osmo_apn_to_str;  osmo_apn_from_str; @@ -592,6 +609,7 @@ osmo_gsm48_classmark1_is_r99;  osmo_gsm48_classmark2_is_r99;  osmo_gsm48_classmark_supports_a5;  osmo_gsm48_classmark_a5_name; +osmo_gsm48_classmark_a5_name_buf;  osmo_gsm48_classmark_update;  local: *; diff --git a/src/gsm/rsl.c b/src/gsm/rsl.c index e610ebf7..7bc60027 100644 --- a/src/gsm/rsl.c +++ b/src/gsm/rsl.c @@ -215,33 +215,47 @@ int rsl_dec_chan_nr(uint8_t chan_nr, uint8_t *type, uint8_t *subch, uint8_t *tim  	return 0;  } -/*! Get human-readable string for RSL channel number */ -const char *rsl_chan_nr_str(uint8_t chan_nr) +/*! Get human-readable string for RSL channel number, in caller-provided buffer. + *  \param[out] buf caller-provided output buffer + *  \param[in] buf_len size of buf in bytes + *  \param[in] chan_nr channel number to be stringified + *  \returns buf with string + */ +char *rsl_chan_nr_str_buf(char *buf, size_t buf_len, uint8_t chan_nr)  { -	static char str[20];  	int ts = chan_nr & 7;  	uint8_t cbits = chan_nr >> 3;  	if (cbits == 0x01) -		sprintf(str, "TCH/F on TS%d", ts); +		snprintf(buf, buf_len, "TCH/F on TS%d", ts);  	else if ((cbits & 0x1e) == 0x02) -		sprintf(str, "TCH/H(%u) on TS%d", cbits & 0x01, ts); +		snprintf(buf, buf_len, "TCH/H(%u) on TS%d", cbits & 0x01, ts);  	else if ((cbits & 0x1c) == 0x04) -		sprintf(str, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts); +		snprintf(buf, buf_len, "SDCCH/4(%u) on TS%d", cbits & 0x03, ts);  	else if ((cbits & 0x18) == 0x08) -		sprintf(str, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts); +		snprintf(buf, buf_len, "SDCCH/8(%u) on TS%d", cbits & 0x07, ts);  	else if (cbits == 0x10) -		sprintf(str, "BCCH on TS%d", ts); +		snprintf(buf, buf_len, "BCCH on TS%d", ts);  	else if (cbits == 0x11) -		sprintf(str, "RACH on TS%d", ts); +		snprintf(buf, buf_len, "RACH on TS%d", ts);  	else if (cbits == 0x12) -		sprintf(str, "PCH/AGCH on TS%d", ts); +		snprintf(buf, buf_len, "PCH/AGCH on TS%d", ts);  	else if (cbits == 0x18) -		sprintf(str, "PDCH on TS%d", ts); +		snprintf(buf, buf_len, "PDCH on TS%d", ts);  	else -		sprintf(str, "UNKNOWN on TS%d", ts); +		snprintf(buf, buf_len, "UNKNOWN on TS%d", ts); + +        return buf; +} -        return str; +/*! Get human-readable string for RSL channel number, in static buffer. + *  \param[in] chan_nr channel number to be stringified + *  \returns buf with string + */ +const char *rsl_chan_nr_str(uint8_t chan_nr) +{ +	static char str[20]; +	return rsl_chan_nr_str_buf(str, sizeof(str), chan_nr);  }  static const struct value_string rsl_err_vals[] = { @@ -392,13 +392,14 @@ int msgb_resize_area(struct msgb *msg, uint8_t *area,  } -/*! Return a (static) buffer containing a hexdump of the msg - * \param[in] msg message buffer - * \returns a pointer to a static char array +/*! fill user-provided buffer with hexdump of the msg. + * \param[out] buf caller-allocated buffer for output string + * \param[in] buf_len length of buf + * \param[in] msg message buffer to be dumped + * \returns buf   */ -const char *msgb_hexdump(const struct msgb *msg) +char *msgb_hexdump_buf(char *buf, size_t buf_len, const struct msgb *msg)  { -	static char buf[4100];  	int buf_offs = 0;  	int nchars;  	const unsigned char *start = msg->data; @@ -421,32 +422,32 @@ const char *msgb_hexdump(const struct msgb *msg)  		if (lxhs[i] > msg->tail)  			continue;  		if (lxhs[i] < msg->data || lxhs[i] > msg->tail) { -			nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +			nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  					  "(L%d=data%+" PRIdPTR ") ",  					  i+1, lxhs[i] - msg->data);  			buf_offs += nchars;  			continue;  		}  		if (lxhs[i] < start) { -			nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +			nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  					  "(L%d%+" PRIdPTR ") ", i+1,  					  start - lxhs[i]);  			buf_offs += nchars;  			continue;  		} -		nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +		nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  				  "%s[L%d]> ",  				  osmo_hexdump(start, lxhs[i] - start),  				  i+1); -		if (nchars < 0 || nchars + buf_offs >= sizeof(buf)) +		if (nchars < 0 || nchars + buf_offs >= buf_len)  			return "ERROR";  		buf_offs += nchars;  		start = lxhs[i];  	} -	nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +	nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  			  "%s", osmo_hexdump(start, msg->tail - start)); -	if (nchars < 0 || nchars + buf_offs >= sizeof(buf)) +	if (nchars < 0 || nchars + buf_offs >= buf_len)  		return "ERROR";  	buf_offs += nchars; @@ -456,17 +457,17 @@ const char *msgb_hexdump(const struct msgb *msg)  			continue;  		if (lxhs[i] < msg->head || lxhs[i] > msg->head + msg->data_len) { -			nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +			nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  					  "(L%d out of range) ", i+1);  		} else if (lxhs[i] <= msg->data + msg->data_len &&  			   lxhs[i] > msg->tail) { -			nchars = snprintf(buf + buf_offs, sizeof(buf) - buf_offs, +			nchars = snprintf(buf + buf_offs, buf_len - buf_offs,  					  "(L%d=tail%+" PRIdPTR ") ",  					  i+1, lxhs[i] - msg->tail);  		} else  			continue; -		if (nchars < 0 || nchars + buf_offs >= sizeof(buf)) +		if (nchars < 0 || nchars + buf_offs >= buf_len)  			return "ERROR";  		buf_offs += nchars;  	} @@ -474,6 +475,15 @@ const char *msgb_hexdump(const struct msgb *msg)  	return buf;  } +/*! Return a (static) buffer containing a hexdump of the msg. + * \param[in] msg message buffer + * \returns a pointer to a static char array + */ +const char *msgb_hexdump(const struct msgb *msg) +{ +	static char buf[4100]; +	return msgb_hexdump_buf(buf, sizeof(buf), msg); +}  /*! Print a string to the end of message buffer.   * \param[in] msgb message buffer. diff --git a/src/sim/core.c b/src/sim/core.c index a78cecc3..998e836b 100644 --- a/src/sim/core.c +++ b/src/sim/core.c @@ -267,10 +267,8 @@ struct msgb *osim_new_apdumsg(uint8_t cla, uint8_t ins, uint8_t p1,  	return msg;  } -/* FIXME: do we want to mark this as __thread? */ -static char sw_print_buf[256]; -char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in) +char *osim_print_sw_buf(char *buf, size_t buf_len, const struct osim_card_hdl *ch, uint16_t sw_in)  {  	const struct osim_card_sw *csw; @@ -283,25 +281,29 @@ char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in)  	switch (csw->type) {  	case SW_TYPE_STR: -		snprintf(sw_print_buf, sizeof(sw_print_buf), -			 "%04x (%s)", sw_in, csw->u.str); +		snprintf(buf, buf_len, "%04x (%s)", sw_in, csw->u.str);  		break;  	default:  		goto ret_def;  	} -	sw_print_buf[sizeof(sw_print_buf)-1] = '\0'; +	buf[buf_len-1] = '\0'; -	return sw_print_buf; +	return buf;  ret_def: -	snprintf(sw_print_buf, sizeof(sw_print_buf), -		 "%04x (Unknown)", sw_in); -	sw_print_buf[sizeof(sw_print_buf)-1] = '\0'; +	snprintf(buf, buf_len, "%04x (Unknown)", sw_in); +	buf[buf_len-1] = '\0'; -	return sw_print_buf; +	return buf;  } +char *osim_print_sw(const struct osim_card_hdl *ch, uint16_t sw_in) +{ +	/* FIXME: do we want to mark this as __thread? */ +	static char sw_print_buf[256]; +	return osim_print_sw_buf(sw_print_buf, sizeof(sw_print_buf), ch, sw_in); +}  const struct osim_card_sw *osim_find_sw(const struct osim_card_profile *cp,  					uint16_t sw_in) diff --git a | 
