diff options
| -rw-r--r-- | include/osmocom/gsm/gsm0808_utils.h | 1 | ||||
| -rw-r--r-- | src/gsm/gsm0808.c | 28 | ||||
| -rw-r--r-- | src/gsm/gsm0808_utils.c | 26 | ||||
| -rw-r--r-- | src/gsm/libosmogsm.map | 1 | ||||
| -rw-r--r-- | tests/gsm0808/gsm0808_test.c | 36 | ||||
| -rw-r--r-- | tests/gsm0808/gsm0808_test.ok | 2 | 
6 files changed, 75 insertions, 19 deletions
| diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index 097bd76b..90ff6771 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -77,6 +77,7 @@ int gsm0808_cell_id_list_name_buf(char *buf, size_t buflen, const struct gsm0808  int gsm0808_cell_id_u_name(char *buf, size_t buflen,  			   enum CELL_IDENT id_discr, const union gsm0808_cell_id_u *u); +uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause);  uint8_t gsm0808_enc_aoip_trasp_addr(struct msgb *msg,  				    const struct sockaddr_storage *ss);  int gsm0808_dec_aoip_trasp_addr(struct sockaddr_storage *ss, diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index c0d5f39d..e951ab1f 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -141,7 +141,7 @@ struct msgb *gsm0808_create_reset(void)  		return NULL;  	msgb_v_put(msg, BSS_MAP_MSG_RESET); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); +	gsm0808_enc_cause(msg, cause);  	msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));  	return msg; @@ -190,7 +190,7 @@ struct msgb *gsm0808_create_clear_command(uint8_t cause)  	msg->l3h = msgb_tv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 4);  	msgb_v_put(msg, BSS_MAP_MSG_CLEAR_CMD); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); +	gsm0808_enc_cause(msg, cause);  	return msg;  } @@ -273,7 +273,7 @@ struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause)  	msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, (const uint8_t *)&cause); +	gsm0808_enc_cause(msg, cause);  	msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); @@ -286,18 +286,22 @@ struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause)   *  \returns callee-allocated msgb with BSSMAP Cipher Mode Reject message */  struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext)  { -	uint8_t c[2]; +	uint16_t cause;  	struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,  					       "bssmap: cipher mode reject");  	if (!msg)  		return NULL; -	c[0] = 0x80 | (class << 4); /* set the high bit to indicate extended cause */ -	c[1] = ext; +	/* Set cause code class in the upper byte */ +	cause = 0x80 | (class << 4); +	cause = cause << 8; + +	/* Set cause code extension in the lower byte */ +	cause |= ext;  	msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 2, c); +	gsm0808_enc_cause(msg, cause);  	msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); @@ -572,7 +576,7 @@ struct msgb *gsm0808_create_ass_fail(uint8_t cause, const uint8_t *rr_cause,  		return NULL;  	msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_FAILURE); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); +	gsm0808_enc_cause(msg, cause);  	/* RR cause 3.2.2.22 */  	if (rr_cause) @@ -614,7 +618,7 @@ struct msgb *gsm0808_create_clear_rqst(uint8_t cause)  		return NULL;  	msgb_v_put(msg, BSS_MAP_MSG_CLEAR_RQST); -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause); +	gsm0808_enc_cause(msg, cause);  	msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));  	return msg; @@ -751,7 +755,7 @@ struct msgb *gsm0808_create_handover_required(const struct gsm0808_handover_requ  	msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_REQUIRED);  	/* Cause, 3.2.2.5 */ -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, params->cause & 0x80? 2 : 1, (const uint8_t*)¶ms->cause); +	gsm0808_enc_cause(msg, params->cause);  	/* Cell Identifier List, 3.2.2.27 */  	gsm0808_enc_cell_id_list2(msg, ¶ms->cil); @@ -876,7 +880,7 @@ struct msgb *gsm0808_create_handover_failure(const struct gsm0808_handover_failu  	msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_FAILURE);  	/* Cause, 3.2.2.5 */ -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, params->cause & 0x80? 2 : 1, (const uint8_t*)¶ms->cause); +	gsm0808_enc_cause(msg, params->cause);  	/* RR Cause, 3.2.2.22 */  	if (params->rr_cause_present) @@ -907,7 +911,7 @@ struct msgb *gsm0808_create_handover_performed(const struct gsm0808_handover_per  	msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_PERFORMED);  	/* Cause, 3.2.2.5 */ -	msgb_tlv_put(msg, GSM0808_IE_CAUSE, gsm0808_cause_ext(params->cause) ? 2 : 1, (const uint8_t *)¶ms->cause); +	gsm0808_enc_cause(msg, params->cause);  	/* Cell Identifier, 3.2.2.17 */  	gsm0808_enc_cell_id(msg, ¶ms->cell_id); diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index c58d8284..38a8664c 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -48,6 +48,32 @@   *  \file gsm0808_utils.c   */ +/*! Encode TS 08.08 AoIP Cause IE + *  \param[out] msg Message Buffer to which to append IE + *  \param[in] cause Cause code to be used in IE + *  \returns number of bytes added to \a msg */ +uint8_t gsm0808_enc_cause(struct msgb *msg, uint16_t cause) +{ +	/* See also 3GPP TS 48.008 3.2.2.5 Cause */ +	uint8_t *old_tail; +	bool extended; + +	old_tail = msg->tail; + +	extended = gsm0808_cause_ext(cause >> 8); + +	msgb_put_u8(msg, GSM0808_IE_CAUSE); +	if (extended) { +		msgb_put_u8(msg, 2); +		msgb_put_u16(msg, cause); +	} else { +		msgb_put_u8(msg, 1); +		msgb_put_u8(msg, (uint8_t) (cause & 0xFF)); +	} + +	return (uint8_t) (msg->tail - old_tail); +} +  /*! Encode TS 08.08 AoIP transport address IE   *  \param[out] msg Message Buffer to which to append IE   *  \param[in] ss Socket Address to be used in IE diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index e9a9e4f2..dc4e0a69 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -183,6 +183,7 @@ gsm0808_create_handover_complete;  gsm0808_create_handover_failure;  gsm0808_create_handover_performed;  gsm0808_prepend_dtap_header; +gsm0808_enc_cause;  gsm0808_enc_aoip_trasp_addr;  gsm0808_dec_aoip_trasp_addr;  gsm0808_enc_speech_codec; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 197ec06d..63b87200 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -30,6 +30,13 @@  #include <arpa/inet.h>  #include <errno.h> +#define EXPECT_ENCODED(hexstr) do { \ +		const char *enc_str = msgb_hexdump(msg); \ +		printf("%s: encoded: %s(rc = %u)\n", __func__, enc_str, rc_enc); \ +		OSMO_ASSERT(strcmp(enc_str, hexstr " ") == 0); \ +		OSMO_ASSERT(rc_enc == msg->len); \ +	} while(0) +  #define VERIFY(msg, data, len) 						\  	if (msgb_l3len(msg) != len) {					\  		printf("%s:%d Length don't match: %d vs. %d. %s\n", 	\ @@ -65,6 +72,27 @@ static void setup_codec_list(struct gsm0808_speech_codec_list *scl)  	scl->len = 3;  } +void test_gsm0808_enc_cause(void) +{ +	/* NOTE: This must be tested early because many of the following tests +	 * rely on the generation of a proper cause code. */ + +	uint8_t rc_enc; +	struct msgb *msg; + +	/* Test with a single byte cause code */ +	msg = msgb_alloc(1024, "output buffer"); +	rc_enc = gsm0808_enc_cause(msg, 0x41); +	EXPECT_ENCODED("04 01 41"); +	msgb_free(msg); + +	/* Test with an extended (two byte) cause code */ +	msg = msgb_alloc(1024, "output buffer"); +	rc_enc = gsm0808_enc_cause(msg, 0x8041); +	EXPECT_ENCODED("04 02 80 41"); +	msgb_free(msg); +} +  static void test_create_layer3(void)  {  	static const uint8_t res[] = { @@ -824,13 +852,6 @@ static void test_gsm0808_enc_dec_encrypt_info()  	msgb_free(msg);  } -#define EXPECT_ENCODED(hexstr) do { \ -		const char *enc_str = msgb_hexdump(msg); \ -		printf("%s: encoded: %s(rc = %u)\n", __func__, enc_str, rc_enc); \ -		OSMO_ASSERT(strcmp(enc_str, hexstr " ") == 0); \ -		OSMO_ASSERT(rc_enc == msg->len); \ -	} while(0) -  static void test_gsm0808_enc_dec_cell_id_list_lac()  {  	struct gsm0808_cell_id_list2 enc_cil; @@ -1770,6 +1791,7 @@ void test_gsm48_mr_cfg_from_gsm0808_sc_cfg()  int main(int argc, char **argv)  {  	printf("Testing generation of GSM0808 messages\n"); +	test_gsm0808_enc_cause();  	test_create_layer3();  	test_create_layer3_aoip();  	test_create_reset(); diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index a48cf1d5..e5833d01 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -1,4 +1,6 @@  Testing generation of GSM0808 messages +test_gsm0808_enc_cause: encoded: 04 01 41 (rc = 3) +test_gsm0808_enc_cause: encoded: 04 02 80 41 (rc = 4)  Testing creating Layer3  Testing creating Layer3 (AoIP)  Testing creating Reset | 
