diff options
| -rw-r--r-- | include/osmocom/gsm/gsm0808.h | 1 | ||||
| -rw-r--r-- | include/osmocom/gsm/gsm0808_utils.h | 2 | ||||
| -rw-r--r-- | src/gsm/gsm0808.c | 24 | ||||
| -rw-r--r-- | src/gsm/gsm0808_utils.c | 16 | ||||
| -rw-r--r-- | src/gsm/libosmogsm.map | 2 | ||||
| -rw-r--r-- | tests/gsm0808/gsm0808_test.c | 44 | ||||
| -rw-r--r-- | tests/gsm0808/gsm0808_test.ok | 1 | 
7 files changed, 89 insertions, 1 deletions
| diff --git a/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h index 66f7c277..9b19d691 100644 --- a/include/osmocom/gsm/gsm0808.h +++ b/include/osmocom/gsm/gsm0808.h @@ -51,6 +51,7 @@ struct msgb *gsm0808_create_cipher(const struct gsm0808_encrypt_info *ei,  				   const uint8_t *cipher_response_mode);  struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);  struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause); +struct msgb *gsm0808_create_cipher_reject_ext(enum gsm0808_cause_class class, uint8_t ext);  struct msgb *gsm0808_create_classmark_request();  struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,  					     const uint8_t *cm3, uint8_t cm3_len); diff --git a/include/osmocom/gsm/gsm0808_utils.h b/include/osmocom/gsm/gsm0808_utils.h index b56e2635..c22d0a9b 100644 --- a/include/osmocom/gsm/gsm0808_utils.h +++ b/include/osmocom/gsm/gsm0808_utils.h @@ -120,6 +120,8 @@ static inline bool gsm0808_cause_ext(enum gsm0808_cause cause)  	return (cause & 0x80) && !(cause & 0x0F);  } +int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp); +  /*! \returns 3GPP TS 48.008 3.2.2.49 Current Channel Type 1 from enum gsm_chan_t. */  static inline uint8_t gsm0808_current_channel_type_1(enum gsm_chan_t type)  { diff --git a/src/gsm/gsm0808.c b/src/gsm/gsm0808.c index c413688c..a84e717d 100644 --- a/src/gsm/gsm0808.c +++ b/src/gsm/gsm0808.c @@ -283,6 +283,30 @@ struct msgb *gsm0808_create_cipher_reject(enum gsm0808_cause cause)  	return msg;  } +/*! Create BSSMAP Cipher Mode Reject message + *  \param[in] class 3GPP TS 08.08 §3.2.2.5 cause's class + *  \param[in] ext 3GPP TS 08.08 §3.2.2.5 cause value (national application extension) + *  \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]; +	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; + +	msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT); + +	msgb_tlv_put(msg, GSM0808_IE_CAUSE, 2, c); + +	msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg)); + +	return msg; +} +  /*! Create BSSMAP LCLS CONNECT CONTROL message (TS 48.008 3.2.1.91).   *  \param[in] config LCLS Configuration   *  \param[in] control LCLS Connection Status Control diff --git a/src/gsm/gsm0808_utils.c b/src/gsm/gsm0808_utils.c index 2348105d..c58d8284 100644 --- a/src/gsm/gsm0808_utils.c +++ b/src/gsm/gsm0808_utils.c @@ -1235,6 +1235,22 @@ void gsm48_mr_cfg_from_gsm0808_sc_cfg(struct gsm48_multi_rate_conf *cfg,  	cfg->icmi = 1;  } +int gsm0808_get_cipher_reject_cause(const struct tlv_parsed *tp) +{ +	const uint8_t *buf = TLVP_VAL_MINLEN(tp, GSM0808_IE_CAUSE, 1); + +	if (!buf) +		return -EBADMSG; + +	if (TLVP_LEN(tp, GSM0808_IE_CAUSE) > 1) { +		if (!gsm0808_cause_ext(buf[0])) +			return -EINVAL; +		return buf[1]; +	} + +	return buf[0]; +} +  /*! Print a human readable name of the cell identifier to the char buffer.   * This is useful both for struct gsm0808_cell_id and struct gsm0808_cell_id_list2.   * See also gsm0808_cell_id_name() and gsm0808_cell_id_list_name(). diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index 32e4ce95..217dcc39 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -157,6 +157,8 @@ gsm0808_create_ass_fail;  gsm0808_create_cipher;  gsm0808_create_cipher_complete;  gsm0808_create_cipher_reject; +gsm0808_create_cipher_reject_ext; +gsm0808_get_cipher_reject_cause;  gsm0808_create_classmark_request;  gsm0808_create_classmark_update;  gsm0808_create_clear_command; diff --git a/tests/gsm0808/gsm0808_test.c b/tests/gsm0808/gsm0808_test.c index 671b8399..197ec06d 100644 --- a/tests/gsm0808/gsm0808_test.c +++ b/tests/gsm0808/gsm0808_test.c @@ -250,14 +250,55 @@ static void test_create_cipher_complete()  	msgb_free(l3);  } +static inline void parse_cipher_reject(struct msgb *msg, uint8_t exp) +{ +	struct tlv_parsed tp; +	int rc; + +	/* skip header and message type so we can parse Cause IE directly */ +	msg->l2h = msgb_data(msg) + sizeof(struct bssmap_header) + 1; + +	rc = osmo_bssap_tlv_parse(&tp, msg->l2h, msgb_l2len(msg)); +	if (rc < 0) +		printf("FIXME: failed (%d) to parse created message %s\n", rc, msgb_hexdump(msg)); + +	rc = gsm0808_get_cipher_reject_cause(&tp); +	if (rc < 0) +		printf("FIXME: failed (%s) to extract Cause from created message %s\n", +		       strerror(-rc), msgb_hexdump(msg)); + +	if (exp != (enum gsm0808_cause)rc) +		printf("FIXME: wrong Cause %d != %u (" OSMO_BIN_SPEC ") extracted from created message %s\n", +		       rc, exp, OSMO_BIT_PRINT(exp), msgb_hexdump(msg)); +} +  static void test_create_cipher_reject()  {  	static const uint8_t res[] = { 0x00, 0x04, 0x59, 0x04, 0x01, 0x23 }; +	enum gsm0808_cause cause = GSM0808_CAUSE_CCCH_OVERLOAD;  	struct msgb *msg;  	printf("Testing creating Cipher Reject\n"); -	msg = gsm0808_create_cipher_reject(GSM0808_CAUSE_CCCH_OVERLOAD); +	msg = gsm0808_create_cipher_reject(cause); +	VERIFY(msg, res, ARRAY_SIZE(res)); + +	parse_cipher_reject(msg, cause); + +	msgb_free(msg); +} + +static void test_create_cipher_reject_ext() +{ +	static const uint8_t res[] = { 0x00, 0x05, 0x59, 0x04, 0x02, 0xd0, 0xFA }; +	uint8_t cause = 0xFA; +	struct msgb *msg; + +	printf("Testing creating Cipher Reject (extended)\n"); +	msg = gsm0808_create_cipher_reject_ext(GSM0808_CAUSE_CLASS_INVAL, cause);  	VERIFY(msg, res, ARRAY_SIZE(res)); + +	parse_cipher_reject(msg, cause); +  	msgb_free(msg);  } @@ -1738,6 +1779,7 @@ int main(int argc, char **argv)  	test_create_cipher();  	test_create_cipher_complete();  	test_create_cipher_reject(); +	test_create_cipher_reject_ext();  	test_create_cm_u();  	test_create_sapi_reject();  	test_create_ass(); diff --git a/tests/gsm0808/gsm0808_test.ok b/tests/gsm0808/gsm0808_test.ok index 58bc5099..a48cf1d5 100644 --- a/tests/gsm0808/gsm0808_test.ok +++ b/tests/gsm0808/gsm0808_test.ok @@ -8,6 +8,7 @@ Testing creating Clear Complete  Testing creating Chipher Mode Command  Testing creating Cipher Complete  Testing creating Cipher Reject +Testing creating Cipher Reject (extended)  Testing creating CM U  Testing creating SAPI Reject  Testing creating Assignment Request | 
