summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/gsm/gsm0808.h1
-rw-r--r--include/osmocom/gsm/gsm0808_utils.h2
-rw-r--r--src/gsm/gsm0808.c24
-rw-r--r--src/gsm/gsm0808_utils.c16
-rw-r--r--src/gsm/libosmogsm.map2
-rw-r--r--tests/gsm0808/gsm0808_test.c44
-rw-r--r--tests/gsm0808/gsm0808_test.ok1
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