summaryrefslogtreecommitdiffstats
path: root/src/shared/libosmocore
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/libosmocore')
-rw-r--r--src/shared/libosmocore/.gitignore1
-rw-r--r--src/shared/libosmocore/configure.ac3
-rw-r--r--src/shared/libosmocore/include/osmocom/core/gsmtap.h12
-rw-r--r--src/shared/libosmocore/include/osmocom/core/msgb.h26
-rw-r--r--src/shared/libosmocore/include/osmocom/core/socket.h1
-rw-r--r--src/shared/libosmocore/include/osmocom/crypt/auth.h1
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm0808.h3
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h2
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h6
-rw-r--r--src/shared/libosmocore/include/osmocom/gsm/tlv.h42
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/misc.h3
-rw-r--r--src/shared/libosmocore/include/osmocom/vty/telnet_interface.h1
-rw-r--r--src/shared/libosmocore/src/gsm/a5.c8
-rw-r--r--src/shared/libosmocore/src/gsm/auth_milenage.c15
-rw-r--r--src/shared/libosmocore/src/gsm/gsm0808.c183
-rw-r--r--src/shared/libosmocore/src/gsm/lapd_core.c13
-rw-r--r--src/shared/libosmocore/src/gsm/lapdm.c8
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/milenage.c15
-rw-r--r--src/shared/libosmocore/src/gsm/milenage/milenage.h2
-rw-r--r--src/shared/libosmocore/src/vty/command.c176
-rw-r--r--src/shared/libosmocore/src/vty/telnet_interface.c57
-rw-r--r--src/shared/libosmocore/tests/Makefile.am2
-rw-r--r--src/shared/libosmocore/tests/auth/milenage_test.c20
-rw-r--r--src/shared/libosmocore/tests/auth/milenage_test.ok2
-rw-r--r--src/shared/libosmocore/tests/gsm0808/Makefile.am6
-rw-r--r--src/shared/libosmocore/tests/gsm0808/gsm0808_test.c269
-rw-r--r--src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok15
-rw-r--r--src/shared/libosmocore/tests/lapd/lapd_test.c31
-rw-r--r--src/shared/libosmocore/tests/lapd/lapd_test.ok4
-rw-r--r--src/shared/libosmocore/tests/testsuite.at6
-rw-r--r--src/shared/libosmocore/utils/osmo-auc-gen.c80
31 files changed, 754 insertions, 259 deletions
diff --git a/src/shared/libosmocore/.gitignore b/src/shared/libosmocore/.gitignore
index fe022875..82e43e3a 100644
--- a/src/shared/libosmocore/.gitignore
+++ b/src/shared/libosmocore/.gitignore
@@ -53,6 +53,7 @@ tests/a5/a5_test
tests/auth/milenage_test
tests/conv/conv_test
tests/lapd/lapd_test
+tests/gsm0808/gsm0808_test
utils/osmo-arfcn
utils/osmo-auc-gen
diff --git a/src/shared/libosmocore/configure.ac b/src/shared/libosmocore/configure.ac
index c38d82f4..0fea115f 100644
--- a/src/shared/libosmocore/configure.ac
+++ b/src/shared/libosmocore/configure.ac
@@ -1,6 +1,6 @@
AC_INIT([libosmocore],
m4_esyscmd([./git-version-gen .tarball-version]),
- [openbsc-devel@lists.openbsc.org])
+ [openbsc@lists.osmocom.org])
AM_INIT_AUTOMAKE([dist-bzip2])
AC_CONFIG_TESTDIR(tests)
@@ -168,6 +168,7 @@ AC_OUTPUT(
tests/auth/Makefile
tests/conv/Makefile
tests/lapd/Makefile
+ tests/gsm0808/Makefile
utils/Makefile
Doxyfile.core
Doxyfile.gsm
diff --git a/src/shared/libosmocore/include/osmocom/core/gsmtap.h b/src/shared/libosmocore/include/osmocom/core/gsmtap.h
index dbc3d314..a4e5d420 100644
--- a/src/shared/libosmocore/include/osmocom/core/gsmtap.h
+++ b/src/shared/libosmocore/include/osmocom/core/gsmtap.h
@@ -77,11 +77,19 @@
#define GSMTAP_CHANNEL_SDCCH8 0x08
#define GSMTAP_CHANNEL_TCH_F 0x09
#define GSMTAP_CHANNEL_TCH_H 0x0a
-#define GSMTAP_CHANNEL_CBCH51 0x0b
+#define GSMTAP_CHANNEL_PACCH 0x0b
#define GSMTAP_CHANNEL_CBCH52 0x0c
#define GSMTAP_CHANNEL_PDCH 0x0d
#define GSMTAP_CHANNEL_PTCCH 0x0e
-#define GSMTAP_CHANNEL_PACCH 0x0f
+#define GSMTAP_CHANNEL_CBCH51 0x0f
+
+/* GPRS Coding Scheme CS1..4 */
+#define GSMTAP_GPRS_CS_BASE 0x20
+#define GSMTAP_GPRS_CS(N) (GSMTAP_GPRS_CS_BASE + N)
+/* (E) GPRS Coding Scheme MCS0..9 */
+#define GSMTAP_GPRS_MCS_BASE 0x30
+#define GSMTAP_GPRS_MCS(N) (GSMTAP_GPRS_MCS_BASE + N)
+
#define GSMTAP_CHANNEL_ACCH 0x80
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
diff --git a/src/shared/libosmocore/include/osmocom/core/msgb.h b/src/shared/libosmocore/include/osmocom/core/msgb.h
index 9f46e6c6..e465ec2b 100644
--- a/src/shared/libosmocore/include/osmocom/core/msgb.h
+++ b/src/shared/libosmocore/include/osmocom/core/msgb.h
@@ -312,6 +312,32 @@ static inline void msgb_reserve(struct msgb *msg, int len)
msg->tail += len;
}
+/*! \brief Trim the msgb to a given absolute length
+ * \param[in] msg message buffer
+ * \param[in] len new total length of buffer
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_trim(struct msgb *msg, int len)
+{
+ if (len > msg->data_len)
+ return -1;
+
+ msg->len = len;
+ msg->tail = msg->data + len;
+
+ return 0;
+}
+
+/*! \brief Trim the msgb to a given layer3 length
+ * \pram[in] msg message buffer
+ * \param[in] l3len new layer3 length
+ * \returns 0 in case of success, negative in case of error
+ */
+static inline int msgb_l3trim(struct msgb *msg, int l3len)
+{
+ return msgb_trim(msg, (msg->l3h - msg->data) + l3len);
+}
+
/*! \brief Allocate message buffer with specified headroom
* \param[in] size size in bytes, including headroom
* \param[in] headroom headroom in bytes
diff --git a/src/shared/libosmocore/include/osmocom/core/socket.h b/src/shared/libosmocore/include/osmocom/core/socket.h
index c5288dfc..88214632 100644
--- a/src/shared/libosmocore/include/osmocom/core/socket.h
+++ b/src/shared/libosmocore/include/osmocom/core/socket.h
@@ -12,6 +12,7 @@
#include <stdint.h>
struct sockaddr;
+struct osmo_fd;
/* flags for osmo_sock_init. */
#define OSMO_SOCK_F_CONNECT (1 << 0)
diff --git a/src/shared/libosmocore/include/osmocom/crypt/auth.h b/src/shared/libosmocore/include/osmocom/crypt/auth.h
index 30e16e82..67b32009 100644
--- a/src/shared/libosmocore/include/osmocom/crypt/auth.h
+++ b/src/shared/libosmocore/include/osmocom/crypt/auth.h
@@ -33,6 +33,7 @@ struct osmo_sub_auth_data {
uint8_t k[16];
uint8_t amf[2];
uint64_t sqn;
+ int opc_is_op;
} umts;
struct {
uint8_t ki[16];
diff --git a/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h b/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
index 38d88ef9..5380dd9e 100644
--- a/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
+++ b/src/shared/libosmocore/include/osmocom/gsm/gsm0808.h
@@ -30,7 +30,8 @@ struct msgb *gsm0808_create_clear_command(uint8_t reason);
struct msgb *gsm0808_create_clear_complete(void);
struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
struct msgb *gsm0808_create_cipher_reject(uint8_t cause);
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length);
+struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len);
struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
uint8_t chosen_channel, uint8_t encr_alg_id,
diff --git a/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h b/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
index f4fce25c..2e576429 100644
--- a/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
+++ b/src/shared/libosmocore/include/osmocom/gsm/gsm48_ie.h
@@ -108,7 +108,7 @@ int gsm48_encode_more(struct msgb *msg);
struct gsm_sysinfo_freq {
/* if the frequency included in the sysinfo */
uint8_t mask;
-};
+} __attribute__ ((packed));
/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
diff --git a/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h b/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
index ce780926..eecc27ce 100644
--- a/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
+++ b/src/shared/libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -213,15 +213,15 @@ struct gsm48_chan_desc {
tsc:3;
uint8_t hsn:6,
maio_low:2;
- } h1;
+ } __attribute__ ((packed)) h1;
struct {
uint8_t arfcn_high:2,
spare:2,
h:1,
tsc:3;
uint8_t arfcn_low;
- } h0;
- };
+ } __attribute__ ((packed)) h0;
+ } __attribute__ ((packed));
} __attribute__ ((packed));
/* Chapter 10.5.2.20 */
diff --git a/src/shared/libosmocore/include/osmocom/gsm/tlv.h b/src/shared/libosmocore/include/osmocom/gsm/tlv.h
index 7b41d2d7..d2936d6d 100644
--- a/src/shared/libosmocore/include/osmocom/gsm/tlv.h
+++ b/src/shared/libosmocore/include/osmocom/gsm/tlv.h
@@ -178,28 +178,32 @@ static inline uint8_t *tv16_put(uint8_t *buf, uint8_t tag,
return buf;
}
-/*! \brief put (append) a LV field to a \ref msgb */
+/*! \brief put (append) a LV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_lv_put(struct msgb *msg, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, LV_GROSS_LEN(len));
return lv_put(buf, len, val);
}
-/*! \brief put (append) a TLV field to a \ref msgb */
+/*! \brief put (append) a TLV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tlv_put(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_put(msg, TLV_GROSS_LEN(len));
return tlv_put(buf, tag, len, val);
}
-/*! \brief put (append) a TV field to a \ref msgb */
+/*! \brief put (append) a TV field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv_put(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 2);
return tv_put(buf, tag, val);
}
-/*! \brief put (append) a TVfixed field to a \ref msgb */
+/*! \brief put (append) a TVfixed field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
unsigned int len, const uint8_t *val)
{
@@ -207,47 +211,57 @@ static inline uint8_t *msgb_tv_fixed_put(struct msgb *msg, uint8_t tag,
return tv_fixed_put(buf, tag, len, val);
}
-/*! \brief put (append) a V field to a \ref msgb */
+/*! \brief put (append) a V field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_v_put(struct msgb *msg, uint8_t val)
{
uint8_t *buf = msgb_put(msg, 1);
return v_put(buf, val);
}
-/*! \brief put (append) a TV16 field to a \ref msgb */
+/*! \brief put (append) a TV16 field to a \ref msgb
+ * \returns pointer to first byte after newly-put information */
static inline uint8_t *msgb_tv16_put(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_put(msg, 3);
return tv16_put(buf, tag, val);
}
-/*! \brief push (prepend) a TLV field to a \ref msgb */
+/*! \brief push (prepend) a TLV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tlv_push(struct msgb *msg, uint8_t tag, uint8_t len, const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, TLV_GROSS_LEN(len));
- return tlv_put(buf, tag, len, val);
+ tlv_put(buf, tag, len, val);
+ return buf;
}
-/*! \brief push (prepend) a TV field to a \ref msgb */
+/*! \brief push (prepend) a TV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tv_push(struct msgb *msg, uint8_t tag, uint8_t val)
{
uint8_t *buf = msgb_push(msg, 2);
- return tv_put(buf, tag, val);
+ tv_put(buf, tag, val);
+ return buf;
}
-/*! \brief push (prepend) a TV16 field to a \ref msgb */
+/*! \brief push (prepend) a TV16 field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tv16_push(struct msgb *msg, uint8_t tag, uint16_t val)
{
uint8_t *buf = msgb_push(msg, 3);
- return tv16_put(buf, tag, val);
+ tv16_put(buf, tag, val);
+ return buf;
}
-/*! \brief push (prepend) a TvLV field to a \ref msgb */
+/*! \brief push (prepend) a TvLV field to a \ref msgb
+ * \returns pointer to first byte of newly-pushed information */
static inline uint8_t *msgb_tvlv_push(struct msgb *msg, uint8_t tag, uint16_t len,
const uint8_t *val)
{
uint8_t *buf = msgb_push(msg, TVLV_GROSS_LEN(len));
- return tvlv_put(buf, tag, len, val);
+ tvlv_put(buf, tag, len, val);
+ return buf;
}
/* TLV parsing */
diff --git a/src/shared/libosmocore/include/osmocom/vty/misc.h b/src/shared/libosmocore/include/osmocom/vty/misc.h
index 707f82fa..89234733 100644
--- a/src/shared/libosmocore/include/osmocom/vty/misc.h
+++ b/src/shared/libosmocore/include/osmocom/vty/misc.h
@@ -7,4 +7,7 @@
void vty_out_rate_ctr_group(struct vty *vty, const char *prefix,
struct rate_ctr_group *ctrg);
+int osmo_vty_write_config_file(const char *filename);
+int osmo_vty_save_config_file(void);
+
#endif
diff --git a/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h b/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
index 2de4f192..65a1dd90 100644
--- a/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
+++ b/src/shared/libosmocore/include/osmocom/vty/telnet_interface.h
@@ -47,6 +47,7 @@ struct telnet_connection {
};
int telnet_init(void *tall_ctx, void *priv, int port);
+int telnet_init_dynif(void *tall_ctx, void *priv, const char *ip, int port);
void telnet_exit(void);
diff --git a/src/shared/libosmocore/src/gsm/a5.c b/src/shared/libosmocore/src/gsm/a5.c
index e330c759..34f271a8 100644
--- a/src/shared/libosmocore/src/gsm/a5.c
+++ b/src/shared/libosmocore/src/gsm/a5.c
@@ -89,10 +89,10 @@ osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
#define A5_R3_MASK ((1<<A5_R3_LEN)-1)
#define A5_R4_MASK ((1<<A5_R4_LEN)-1)
-#define A5_R1_TAPS 0x072000 /* x^19 + x^5 + x^2 + x + 1 */
-#define A5_R2_TAPS 0x300000 /* x^22 + x + 1 */
-#define A5_R3_TAPS 0x700080 /* x^23 + x^15 + x^2 + x + 1 */
-#define A5_R4_TAPS 0x010800 /* x^17 + x^5 + 1 */
+#define A5_R1_TAPS 0x072000 /* x^19 + x^18 + x^17 + x^14 + 1 */
+#define A5_R2_TAPS 0x300000 /* x^22 + x^21 + 1 */
+#define A5_R3_TAPS 0x700080 /* x^23 + x^22 + x^21 + x^8 + 1 */
+#define A5_R4_TAPS 0x010800 /* x^17 + x^12 + 1 */
/*! \brief Computes parity of a 32-bit word
* \param[in] x 32 bit word
diff --git a/src/shared/libosmocore/src/gsm/auth_milenage.c b/src/shared/libosmocore/src/gsm/auth_milenage.c
index 2a9ba334..5b2787dd 100644
--- a/src/shared/libosmocore/src/gsm/auth_milenage.c
+++ b/src/shared/libosmocore/src/gsm/auth_milenage.c
@@ -83,10 +83,21 @@ static int milenage_gen_vec_auts(struct osmo_auth_vector *vec,
const uint8_t *_rand)
{
uint8_t sqn_out[6];
+ uint8_t gen_opc[16];
+ uint8_t *opc;
int rc;
- rc = milenage_auts(aud->u.umts.opc, aud->u.umts.k,
- rand_auts, auts, sqn_out);
+ /* Check if we only know OP and compute OPC if required */
+ if (aud->type == OSMO_AUTH_TYPE_UMTS && aud->u.umts.opc_is_op) {
+ rc = milenage_opc_gen(gen_opc, aud->u.umts.k,
+ aud->u.umts.opc);
+ if (rc < 0)
+ return rc;
+ opc = gen_opc;
+ } else
+ opc = aud->u.umts.opc;
+
+ rc = milenage_auts(opc, aud->u.umts.k, rand_auts, auts, sqn_out);
if (rc < 0)
return rc;
diff --git a/src/shared/libosmocore/src/gsm/gsm0808.c b/src/shared/libosmocore/src/gsm/gsm0808.c
index 01221bd8..30098278 100644
--- a/src/shared/libosmocore/src/gsm/gsm0808.c
+++ b/src/shared/libosmocore/src/gsm/gsm0808.c
@@ -27,69 +27,52 @@
#define BSSMAP_MSG_SIZE 512
#define BSSMAP_MSG_HEADROOM 128
-static void put_data_16(uint8_t *data, const uint16_t val)
-{
- memcpy(data, &val, sizeof(val));
-}
-
struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, uint16_t _ci)
{
- uint8_t *data;
- uint8_t *ci;
struct msgb* msg;
- struct gsm48_loc_area_id *lai;
+ struct {
+ uint8_t ident;
+ struct gsm48_loc_area_id lai;
+ uint16_t ci;
+ } __attribute__ ((packed)) lai_ci;
msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap cmpl l3");
if (!msg)
return NULL;
- /* create the bssmap header */
- msg->l3h = msgb_put(msg, 2);
- msg->l3h[0] = 0x0;
-
/* create layer 3 header */
- data = msgb_put(msg, 1);
- data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3;
+ msgb_v_put(msg, BSS_MAP_MSG_COMPLETE_LAYER_3);
/* create the cell header */
- data = msgb_put(msg, 3);
- data[0] = GSM0808_IE_CELL_IDENTIFIER;
- data[1] = 1 + sizeof(*lai) + 2;
- data[2] = CELL_IDENT_WHOLE_GLOBAL;
-
- lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
- gsm48_generate_lai(lai, cc, nc, lac);
-
- ci = msgb_put(msg, 2);
- put_data_16(ci, htons(_ci));
+ lai_ci.ident = CELL_IDENT_WHOLE_GLOBAL;
+ gsm48_generate_lai(&lai_ci.lai, cc, nc, lac);
+ lai_ci.ci = htons(_ci);
+ msgb_tlv_put(msg, GSM0808_IE_CELL_IDENTIFIER, sizeof(lai_ci),
+ (uint8_t *) &lai_ci);
/* copy the layer3 data */
- data = msgb_put(msg, msgb_l3len(msg_l3) + 2);
- data[0] = GSM0808_IE_LAYER_3_INFORMATION;
- data[1] = msgb_l3len(msg_l3);
- memcpy(&data[2], msg_l3->l3h, data[1]);
+ msgb_tlv_put(msg, GSM0808_IE_LAYER_3_INFORMATION,
+ msgb_l3len(msg_l3), msg_l3->l3h);
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
+ /* push the bssmap header */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
struct msgb *gsm0808_create_reset(void)
{
+ uint8_t cause = GSM0808_CAUSE_EQUIPMENT_FAILURE;
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: reset");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0x04;
- msg->l3h[2] = 0x30;
- msg->l3h[3] = 0x04;
- msg->l3h[4] = 0x01;
- msg->l3h[5] = 0x20;
+ msgb_v_put(msg, BSS_MAP_MSG_RESET);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
+
return msg;
}
@@ -97,13 +80,12 @@ struct msgb *gsm0808_create_clear_complete(void)
{
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: clear complete");
+ uint8_t val = BSS_MAP_MSG_CLEAR_COMPLETE;
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 1;
- msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
+ msg->l3h = msg->data;
+ msgb_tlv_put(msg, BSSAP_MSG_BSS_MANAGEMENT, 1, &val);
return msg;
}
@@ -118,6 +100,7 @@ struct msgb *gsm0808_create_clear_command(uint8_t reason)
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, &reason);
+
return msg;
}
@@ -129,26 +112,20 @@ struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id)
return NULL;
/* send response with BSS override for A5/1... cheating */
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE;
+ msgb_v_put(msg, BSS_MAP_MSG_CIPHER_MODE_COMPLETE);
/* include layer3 in case we have at least two octets */
if (layer3 && msgb_l3len(layer3) > 2) {
- msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2);
- msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS;
- msg->l4h[1] = msgb_l3len(layer3);
- memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3));
+ msg->l4h = msgb_tlv_put(msg, GSM0808_IE_LAYER_3_MESSAGE_CONTENTS,
+ msgb_l3len(layer3), layer3->l3h);
}
/* and the optional BSS message */
- msg->l4h = msgb_put(msg, 2);
- msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- msg->l4h[1] = alg_id;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, alg_id);
+
+ /* pre-pend the header */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
@@ -159,32 +136,29 @@ struct msgb *gsm0808_create_cipher_reject(uint8_t cause)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 4);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 2;
- msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT;
- msg->l3h[3] = cause;
+ msgb_tv_put(msg, BSS_MAP_MSG_CIPHER_MODE_REJECT, cause);
+
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
-struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length)
+struct msgb *gsm0808_create_classmark_update(const uint8_t *cm2, uint8_t cm2_len,
+ const uint8_t *cm3, uint8_t cm3_len)
{
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"classmark-update");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE;
+ msgb_v_put(msg, BSS_MAP_MSG_CLASSMARK_UPDATE);
+ msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T2, cm2_len, cm2);
+ if (cm3)
+ msgb_tlv_put(msg, GSM0808_IE_CLASSMARK_INFORMATION_T3,
+ cm3_len, cm3);
- msg->l4h = msgb_put(msg, length);
- memcpy(msg->l4h, classmark_data, length);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
@@ -195,12 +169,11 @@ struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 5);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 3;
- msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT;
- msg->l3h[3] = link_id;
- msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED;
+ msgb_v_put(msg, BSS_MAP_MSG_SAPI_N_REJECT);
+ msgb_v_put(msg, link_id);
+ msgb_v_put(msg, GSM0808_CAUSE_BSS_NOT_EQUIPPED);
+
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
return msg;
}
@@ -209,78 +182,56 @@ struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
uint8_t chosen_channel, uint8_t encr_alg_id,
uint8_t speech_mode)
{
- uint8_t *data;
-
- struct msgb *msg = msgb_alloc(35, "bssmap: ass compl");
+ struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+ "bssmap: ass compl");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 3);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE;
+ msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_COMPLETE);
/* write 3.2.2.22 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = rr_cause;
+ msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, rr_cause);
/* write cirtcuit identity code 3.2.2.2 */
/* write cell identifier 3.2.2.17 */
/* write chosen channel 3.2.2.33 when BTS picked it */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_CHANNEL;
- data[1] = chosen_channel;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_CHANNEL, chosen_channel);
/* write chosen encryption algorithm 3.2.2.44 */
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
- data[1] = encr_alg_id;
+ msgb_tv_put(msg, GSM0808_IE_CHOSEN_ENCR_ALG, encr_alg_id);
/* write circuit pool 3.2.2.45 */
/* write speech version chosen: 3.2.2.51 when BTS picked it */
- if (speech_mode != 0) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_SPEECH_VERSION;
- data[1] = speech_mode;
- }
+ if (speech_mode != 0)
+ msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, speech_mode);
/* write LSA identifier 3.2.2.15 */
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- /* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause)
{
- uint8_t *data;
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
"bssmap: ass fail");
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 6);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 0xff;
- msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
- msg->l3h[3] = GSM0808_IE_CAUSE;
- msg->l3h[4] = 1;
- msg->l3h[5] = cause;
+ msgb_v_put(msg, BSS_MAP_MSG_ASSIGMENT_FAILURE);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
/* RR cause 3.2.2.22 */
- if (rr_cause) {
- data = msgb_put(msg, 2);
- data[0] = GSM0808_IE_RR_CAUSE;
- data[1] = *rr_cause;
- }
+ if (rr_cause)
+ msgb_tv_put(msg, GSM0808_IE_RR_CAUSE, *rr_cause);
/* Circuit pool 3.22.45 */
/* Circuit pool list 3.2.2.46 */
/* update the size */
- msg->l3h[1] = msgb_l3len(msg) - 2;
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
+
return msg;
}
@@ -293,14 +244,10 @@ struct msgb *gsm0808_create_clear_rqst(uint8_t cause)
if (!msg)
return NULL;
- msg->l3h = msgb_put(msg, 2 + 4);
- msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
- msg->l3h[1] = 4;
+ msgb_v_put(msg, BSS_MAP_MSG_CLEAR_RQST);
+ msgb_tlv_put(msg, GSM0808_IE_CAUSE, 1, &cause);
+ msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
- msg->l3h[2] = BSS_MAP_MSG_CLEAR_RQST;
- msg->l3h[3] = GSM0808_IE_CAUSE;
- msg->l3h[4] = 1;
- msg->l3h[5] = cause;
return msg;
}
diff --git a/src/shared/libosmocore/src/gsm/lapd_core.c b/src/shared/libosmocore/src/gsm/lapd_core.c
index b1b5a1ba..96099edb 100644
--- a/src/shared/libosmocore/src/gsm/lapd_core.c
+++ b/src/shared/libosmocore/src/gsm/lapd_core.c
@@ -707,7 +707,7 @@ static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
{
struct lapd_datalink *dl = lctx->dl;
uint8_t nr = lctx->n_recv;
- int s = 0, rej = 0, t200_reset = 0, t200_start = 0;
+ int s = 0, rej = 0, t200_reset = 0;
int i, h;
/* supervisory frame ? */
@@ -758,7 +758,6 @@ static void lapd_acknowledge(struct lapd_msg_ctx *lctx)
if (dl->tx_hist[sub_mod(dl->v_send, 1, dl->range_hist)].msg) {
LOGP(DLLAPD, LOGL_INFO, "start T200, due to unacked I "
"frame(s)\n");
- t200_start = 1;
lapd_start_t200(dl);
}
}
@@ -1731,7 +1730,15 @@ static int lapd_data_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx)
struct lapd_datalink *dl = lctx->dl;
struct msgb *msg = dp->oph.msg;
- LOGP(DLLAPD, LOGL_INFO, "writing message to send-queue\n");
+ if (msgb_l3len(msg) == 0) {
+ LOGP(DLLAPD, LOGL_ERROR,
+ "writing an empty message is not possible.\n");
+ msgb_free(msg);
+ return -1;
+ }
+
+ LOGP(DLLAPD, LOGL_INFO,
+ "writing message to send-queue: l3len: %d\n", msgb_l3len(msg));
/* Write data into the send queue */
msgb_enqueue(&dl->send_queue, msg);
diff --git a/src/shared/libosmocore/src/gsm/lapdm.c b/src/shared/libosmocore/src/gsm/lapdm.c
index 3d2f3d83..e9ce881b 100644
--- a/src/shared/libosmocore/src/gsm/lapdm.c
+++ b/src/shared/libosmocore/src/gsm/lapdm.c
@@ -792,7 +792,7 @@ static int rslms_rx_rll_est_req(struct msgb *msg, struct lapdm_datalink *dl)
/* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
msg->len = length;
- msg->tail = msg->data + length;
+ msg->tail = msg->l3h + length;
/* prepare prim */
osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg);
@@ -845,7 +845,7 @@ static int rslms_rx_rll_udata_req(struct msgb *msg, struct lapdm_datalink *dl)
/* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
msg->len = length;
- msg->tail = msg->data + length;
+ msg->tail = msg->l3h + length;
/* Push L1 + LAPDm header on msgb */
msg->l2h = msgb_push(msg, 4 + !ui_bts);
@@ -881,7 +881,7 @@ static int rslms_rx_rll_data_req(struct msgb *msg, struct lapdm_datalink *dl)
/* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
msg->len = length;
- msg->tail = msg->data + length;
+ msg->tail = msg->l3h + length;
/* prepare prim */
osmo_prim_init(&dp.oph, 0, PRIM_DL_DATA, PRIM_OP_REQUEST, msg);
@@ -938,7 +938,7 @@ static int rslms_rx_rll_res_req(struct msgb *msg, struct lapdm_datalink *dl)
/* Remove RLL header from msgb and set length to L3-info */
msgb_pull_l2h(msg);
msg->len = length;
- msg->tail = msg->data + length;
+ msg->tail = msg->l3h + length;
/* prepare prim */
osmo_prim_init(&dp.oph, 0, (msg_type == RSL_MT_RES_REQ) ? PRIM_DL_RES
diff --git a/src/shared/libosmocore/src/gsm/milenage/milenage.c b/src/shared/libosmocore/src/gsm/milenage/milenage.c
index cc4e95c5..b43f986a 100644
--- a/src/shared/libosmocore/src/gsm/milenage/milenage.c
+++ b/src/shared/libosmocore/src/gsm/milenage/milenage.c
@@ -327,3 +327,18 @@ int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
return 0;
}
+
+int milenage_opc_gen(u8 *opc, const u8 *k, const u8 *op)
+{
+ int i;
+
+ /* Encrypt OP using K */
+ if (aes_128_encrypt_block(k, op, opc))
+ return -1;
+
+ /* XOR the resulting Ek(OP) with OP */
+ for (i = 0; i < 16; i++)
+ opc[i] = opc[i] ^ op[i];
+
+ return 0;
+}
diff --git a/src/shared/libosmocore/src/gsm/milenage/milenage.h b/src/shared/libosmocore/src/gsm/milenage/milenage.h
index d5054d6d..a91e946a 100644
--- a/src/shared/libosmocore/src/gsm/milenage/milenage.h
+++ b/src/shared/libosmocore/src/gsm/milenage/milenage.h
@@ -30,4 +30,6 @@ int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar);
+int milenage_opc_gen(u8 *opc, const u8 *k, const u8 *op);
+
#endif /* MILENAGE_H */
diff --git a/src/shared/libosmocore/src/vty/command.c b/src/shared/libosmocore/src/vty/command.c
index ab1eacaa..fda2e17f 100644
--- a/src/shared/libosmocore/src/vty/command.c
+++ b/src/shared/libosmocore/src/vty/command.c
@@ -2268,31 +2268,19 @@ gDEFUN(config_list, config_list_cmd, "list", "Print command list\n")
return CMD_SUCCESS;
}
-/* Write current configuration into file. */
-DEFUN(config_write_file,
- config_write_file_cmd,
- "write file",
- "Write running configuration to memory, network, or terminal\n"
- "Write to configuration file\n")
+static int write_config_file(const char *config_file, char **outpath)
{
unsigned int i;
int fd;
struct cmd_node *node;
- char *config_file;
char *config_file_tmp = NULL;
char *config_file_sav = NULL;
struct vty *file_vty;
+ struct stat st;
- /* Check and see if we are operating under vtysh configuration */
- if (host.config == NULL) {
- vty_out(vty, "Can't save to configuration file, using vtysh.%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- /* Get filename. */
- config_file = host.config;
+ *outpath = NULL;
+ /* Check and see if we are operating under vtysh configuration */
config_file_sav =
_talloc_zero(tall_vty_cmd_ctx,
strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1,
@@ -2307,11 +2295,10 @@ DEFUN(config_write_file,
/* Open file to configuration write. */
fd = mkstemp(config_file_tmp);
if (fd < 0) {
- vty_out(vty, "Can't open configuration file %s.%s",
- config_file_tmp, VTY_NEWLINE);
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file_tmp);
talloc_free(config_file_tmp);
talloc_free(config_file_sav);
- return CMD_WARNING;
+ return -1;
}
/* Make vty for configuration file. */
@@ -2334,38 +2321,37 @@ DEFUN(config_write_file,
if (unlink(config_file_sav) != 0)
if (errno != ENOENT) {
- vty_out(vty,
- "Can't unlink backup configuration file %s.%s",
- config_file_sav, VTY_NEWLINE);
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file_sav);
talloc_free(config_file_sav);
talloc_free(config_file_tmp);
unlink(config_file_tmp);
- return CMD_WARNING;
+ return -2;
+ }
+
+ /* Only link the .sav file if the original file exists */
+ if (stat(config_file, &st) == 0) {
+ if (link(config_file, config_file_sav) != 0) {
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file_sav);
+ talloc_free(config_file_sav);
+ talloc_free(config_file_tmp);
+ unlink(config_file_tmp);
+ return -3;
+ }
+ sync();
+ if (unlink(config_file) != 0) {
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file);
+ talloc_free(config_file_sav);
+ talloc_free(config_file_tmp);
+ unlink(config_file_tmp);
+ return -4;
}
- if (link(config_file, config_file_sav) != 0) {
- vty_out(vty, "Can't backup old configuration file %s.%s",
- config_file_sav, VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
- }
- sync();
- if (unlink(config_file) != 0) {
- vty_out(vty, "Can't unlink configuration file %s.%s",
- config_file, VTY_NEWLINE);
- talloc_free(config_file_sav);
- talloc_free(config_file_tmp);
- unlink(config_file_tmp);
- return CMD_WARNING;
}
if (link(config_file_tmp, config_file) != 0) {
- vty_out(vty, "Can't save configuration file %s.%s", config_file,
- VTY_NEWLINE);
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file);
talloc_free(config_file_sav);
talloc_free(config_file_tmp);
unlink(config_file_tmp);
- return CMD_WARNING;
+ return -5;
}
unlink(config_file_tmp);
sync();
@@ -2374,13 +2360,70 @@ DEFUN(config_write_file,
talloc_free(config_file_tmp);
if (chmod(config_file, 0666 & ~CONFIGFILE_MASK) != 0) {
- vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
- config_file, strerror(errno), errno, VTY_NEWLINE);
+ *outpath = talloc_strdup(tall_vty_cmd_ctx, config_file);
+ return -6;
+ }
+
+ return 0;
+}
+
+
+/* Write current configuration into file. */
+DEFUN(config_write_file,
+ config_write_file_cmd,
+ "write file",
+ "Write running configuration to memory, network, or terminal\n"
+ "Write to configuration file\n")
+{
+ char *failed_file;
+ int rc;
+
+ if (host.config == NULL) {
+ vty_out(vty, "Can't save to configuration file, using vtysh.%s",
+ VTY_NEWLINE);
return CMD_WARNING;
}
- vty_out(vty, "Configuration saved to %s%s", config_file, VTY_NEWLINE);
- return CMD_SUCCESS;
+ rc = write_config_file(host.config, &failed_file);
+ switch (rc) {
+ case -1:
+ vty_out(vty, "Can't open configuration file %s.%s",
+ failed_file, VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ case -2:
+ vty_out(vty, "Can't unlink backup configuration file %s.%s",
+ failed_file, VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ case -3:
+ vty_out(vty, "Can't backup old configuration file %s.%s",
+ failed_file, VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ case -4:
+ vty_out(vty, "Can't unlink configuration file %s.%s",
+ failed_file, VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ case -5:
+ vty_out(vty, "Can't save configuration file %s.%s", failed_file,
+ VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ case -6:
+ vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
+ failed_file, strerror(errno), errno, VTY_NEWLINE);
+ rc = CMD_WARNING;
+ break;
+ default:
+ vty_out(vty, "Configuration saved to %s%s", host.config, VTY_NEWLINE);
+ rc = CMD_SUCCESS;
+ break;
+ }
+
+ talloc_free(failed_file);
+ return rc;
}
ALIAS(config_write_file,
@@ -3160,6 +3203,47 @@ void install_default(enum node_type node)
install_element(node, &show_running_config_cmd);
}
+/**
+ * \brief Write the current running config to a given file
+ * \param[in] vty the vty of the code
+ * \param[in] filename where to store the file
+ * \return 0 in case of success.
+ *
+ * If the filename already exists create a filename.sav
+ * version with the current code.
+ *
+ */
+int osmo_vty_write_config_file(const char *filename)
+{
+ char *failed_file;
+ int rc;
+
+ rc = write_config_file(filename, &failed_file);
+ talloc_free(failed_file);
+ return rc;
+}
+
+/**
+ * \brief Save the current state to the config file
+ * \return 0 in case of success.
+ *
+ * If the filename already exists create a filename.sav
+ * version with the current code.
+ *
+ */
+int osmo_vty_save_config_file(void)
+{
+ char *failed_file;
+ int rc;
+
+ if (host.config == NULL)
+ return -7;
+
+ rc = write_config_file(host.config, &failed_file);
+ talloc_free(failed_file);
+ return rc;
+}
+
/* Initialize command interface. Install basic nodes and commands. */
void cmd_init(int terminal)
{
diff --git a/src/shared/libosmocore/src/vty/telnet_interface.c b/src/shared/libosmocore/src/vty/telnet_interface.c
index 167acc18..001b016e 100644
--- a/src/shared/libosmocore/src/vty/telnet_interface.c
+++ b/src/shared/libosmocore/src/vty/telnet_interface.c
@@ -20,12 +20,14 @@
#include <sys/socket.h>
#include <netinet/in.h>
+#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/socket.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
@@ -52,53 +54,38 @@ static struct osmo_fd server_socket = {
.priv_nr = 0,
};
-/*! \brief Initialize telnet based VTY interface
+/*! \brief Initialize telnet based VTY interface listening to 127.0.0.1
* \param[in] tall_ctx \ref talloc context
* \param[in] priv private data to be passed to callback
* \param[in] port UDP port number
*/
int telnet_init(void *tall_ctx, void *priv, int port)
{
- struct sockaddr_in sock_addr;
- int fd, rc, on = 1;
-
- tall_telnet_ctx = talloc_named_const(tall_ctx, 1,
- "telnet_connection");
-
- /* FIXME: use new socket.c code of libosmocore */
- fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-
- if (fd < 0) {
- LOGP(0, LOGL_ERROR, "Telnet interface socket creation failed\n");
- return fd;
- }
-
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ return telnet_init_dynif(tall_ctx, priv, "127.0.0.1", port);
+}
- memset(&sock_addr, 0, sizeof(sock_addr));
- sock_addr.sin_family = AF_INET;
- sock_addr.sin_port = htons(port);
- sock_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+/*! \brief Initialize telnet based VTY interface
+ * \param[in] tall_ctx \ref talloc context
+ * \param[in] priv private data to be passed to callback
+ * \param[in] ip IP to listen to ('::1' for localhost, '::0' for all, ...)
+ * \param[in] port UDP port number
+ */
+int telnet_init_dynif(void *tall_ctx, void *priv, const char *ip, int port)
+{
+ int rc;
- rc = bind(fd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
- if (rc < 0) {
- LOGP(0, LOGL_ERROR, "Telnet interface failed to bind\n");
- close(fd);
- return rc;
- }
+ tall_telnet_ctx = talloc_named_const(tall_ctx, 1,
+ "telnet_connection");
- rc = listen(fd, 0);
- if (rc < 0) {
- LOGP(0, LOGL_ERROR, "Telnet interface failed to listen\n");
- close(fd);
- return rc;
- }
+ rc = osmo_sock_init_ofd(
+ &server_socket,
+ AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP,
+ ip, port, OSMO_SOCK_F_BIND
+ );
server_socket.data = priv;
- server_socket.fd = fd;
- osmo_fd_register(&server_socket);
- return 0;
+ return (rc < 0) ? -1 : 0;
}
extern struct host host;
diff --git a/src/shared/libosmocore/tests/Makefile.am b/src/shared/libosmocore/tests/Makefile.am
index 348355f2..eff1ac44 100644
--- a/src/shared/libosmocore/tests/Makefile.am
+++ b/src/shared/libosmocore/tests/Makefile.am
@@ -1,5 +1,5 @@
if ENABLE_TESTS
-SUBDIRS = timer sms ussd smscb bits a5 conv auth lapd
+SUBDIRS = timer sms ussd smscb bits a5 conv auth lapd gsm0808
if ENABLE_MSGFILE
SUBDIRS += msgfile
endif
diff --git a/src/shared/libosmocore/tests/auth/milenage_test.c b/src/shared/libosmocore/tests/auth/milenage_test.c
index da7c800a..7c996f02 100644
--- a/src/shared/libosmocore/tests/auth/milenage_test.c
+++ b/src/shared/libosmocore/tests/auth/milenage_test.c
@@ -37,6 +37,24 @@ static struct osmo_sub_auth_data test_aud = {
},
};
+static int opc_test(const struct osmo_sub_auth_data *aud)
+{
+ int rc;
+ uint8_t opc[16];
+#if 0
+ const uint8_t op[16] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+#else
+ const uint8_t op[16] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };
+#endif
+
+ rc = milenage_opc_gen(opc, aud->u.umts.k, op);
+
+ printf("OP:\t%s\n", osmo_hexdump(op, sizeof(op)));
+ printf("OPC:\t%s\n", osmo_hexdump(opc, sizeof(opc)));
+ return rc;
+}
+
int main(int argc, char **argv)
{
struct osmo_auth_vector _vec;
@@ -73,6 +91,8 @@ int main(int argc, char **argv)
printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn);
}
+ opc_test(&test_aud);
+
exit(0);
}
diff --git a/src/shared/libosmocore/tests/auth/milenage_test.ok b/src/shared/libosmocore/tests/auth/milenage_test.ok
index 66337ca9..00ffc222 100644
--- a/src/shared/libosmocore/tests/auth/milenage_test.ok
+++ b/src/shared/libosmocore/tests/auth/milenage_test.ok
@@ -6,3 +6,5 @@ RES: e9 fc 88 cc c8 a3 53 81
SRES: 21 5f db 4d
Kc: 6d e8 16 a7 59 a4 29 12
AUTS success: SEQ.MS = 33
+OP: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+OPC: c6 a1 3b 37 87 8f 5b 82 6f 4f 81 62 a1 c8 d8 79
diff --git a/src/shared/libosmocore/tests/gsm0808/Makefile.am b/src/shared/libosmocore/tests/gsm0808/Makefile.am
new file mode 100644
index 00000000..a238e7f3
--- /dev/null
+++ b/src/shared/libosmocore/tests/gsm0808/Makefile.am
@@ -0,0 +1,6 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include
+noinst_PROGRAMS = gsm0808_test
+EXTRA_DIST = gsm0808_test.ok
+
+gsm0808_test_SOURCES = gsm0808_test.c
+gsm0808_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
diff --git a/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c b/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c
new file mode 100644
index 00000000..7e5e97b5
--- /dev/null
+++ b/src/shared/libosmocore/tests/gsm0808/gsm0808_test.c
@@ -0,0 +1,269 @@
+/*
+ * (C) 2012 by Holger Hans Peter Freyther
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/gsm/gsm0808.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define VERIFY(msg, data, len) \
+ if (msgb_l3len(msg) != len) { \
+ printf("%s:%d Length don't match: %d vs. %d. %s\n", \
+ __func__, __LINE__, msgb_l3len(msg), len, \
+ osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
+ abort(); \
+ } else if (memcmp(msg->l3h, data, len) != 0) { \
+ printf("%s:%d didn't match: got: %s\n", \
+ __func__, __LINE__, \
+ osmo_hexdump(msg->l3h, msgb_l3len(msg))); \
+ abort(); \
+ }
+
+
+static void test_create_layer3(void)
+{
+ static const uint8_t res[] = {
+ 0x00, 0x0e, 0x57, 0x05, 0x08, 0x00, 0x77, 0x62,
+ 0x83, 0x33, 0x66, 0x44, 0x88, 0x17, 0x01, 0x23 };
+ struct msgb *msg, *in_msg;
+ printf("Testing creating Layer3\n");
+
+ in_msg = msgb_alloc_headroom(512, 128, "foo");
+ in_msg->l3h = in_msg->data;
+ msgb_v_put(in_msg, 0x23);
+
+ msg = gsm0808_create_layer3(in_msg, 0x1122, 0x2244, 0x3366, 0x4488);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+ msgb_free(in_msg);
+}
+
+static void test_create_reset()
+{
+ static const uint8_t res[] = { 0x00, 0x04, 0x30, 0x04, 0x01, 0x20 };
+ struct msgb *msg;
+
+ printf("Testing creating Reset\n");
+ msg = gsm0808_create_reset();
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_clear_command()
+{
+ static const uint8_t res[] = { 0x20, 0x04, 0x01, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Command\n");
+ msg = gsm0808_create_clear_command(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_clear_complete()
+{
+ static const uint8_t res[] = { 0x00, 0x01, 0x21 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Complete\n");
+ msg = gsm0808_create_clear_complete();
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_cipher_complete()
+{
+ static const uint8_t res1[] = {
+ 0x00, 0x08, 0x55, 0x20, 0x03, 0x23, 0x42, 0x21, 0x2c, 0x04 };
+ static const uint8_t res2[] = { 0x00, 0x03, 0x55, 0x2c, 0x04};
+ struct msgb *l3, *msg;
+
+ printf("Testing creating Cipher Complete\n");
+ l3 = msgb_alloc_headroom(512, 128, "l3h");
+ l3->l3h = l3->data;
+ msgb_v_put(l3, 0x23);
+ msgb_v_put(l3, 0x42);
+ msgb_v_put(l3, 0x21);
+
+ /* with l3 data */
+ msg = gsm0808_create_cipher_complete(l3, 4);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ /* with l3 data but short */
+ l3->len -= 1;
+ l3->tail -= 1;
+ msg = gsm0808_create_cipher_complete(l3, 4);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+
+ /* without l3 data */
+ msg = gsm0808_create_cipher_complete(NULL, 4);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+
+
+ msgb_free(l3);
+}
+
+static void test_create_cipher_reject()
+{
+ static const uint8_t res[] = { 0x00, 0x02, 0x59, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Cipher Reject\n");
+ msg = gsm0808_create_cipher_reject(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_cm_u()
+{
+ static const uint8_t res[] = {
+ 0x00, 0x07, 0x54, 0x12, 0x01, 0x23, 0x13, 0x01, 0x42 };
+ static const uint8_t res2o[] = {
+ 0x00, 0x04, 0x54, 0x12, 0x01, 0x23 };
+ struct msgb *msg;
+ const uint8_t cm2 = 0x23;
+ const uint8_t cm3 = 0x42;
+
+ printf("Testing creating CM U\n");
+ msg = gsm0808_create_classmark_update(&cm2, 1, &cm3, 1);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+
+ msg = gsm0808_create_classmark_update(&cm2, 1, NULL, 0);
+ VERIFY(msg, res2o, ARRAY_SIZE(res2o));
+
+ msgb_free(msg);
+}
+
+static void test_create_sapi_reject()
+{
+ static const uint8_t res[] = { 0x00, 0x03, 0x25, 0x03, 0x25 };
+ struct msgb *msg;
+
+ printf("Testing creating SAPI Reject\n");
+ msg = gsm0808_create_sapi_reject(3);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_ass_compl()
+{
+ static const uint8_t res1[] = {
+ 0x00, 0x09, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c,
+ 0x11, 0x40, 0x22 };
+ static const uint8_t res2[] = {
+ 0x00, 0x07, 0x02, 0x15, 0x23, 0x21, 0x42, 0x2c, 0x11};
+ struct msgb *msg;
+
+ printf("Testing creating Assignment Complete\n");
+ msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0x22);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ msg = gsm0808_create_assignment_completed(0x23, 0x42, 0x11, 0);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+}
+
+static void test_create_ass_fail()
+{
+ static const uint8_t res1[] = { 0x00, 0x04, 0x03, 0x04, 0x01, 0x23 };
+ static const uint8_t res2[] = {
+ 0x00, 0x06, 0x03, 0x04, 0x01, 0x23, 0x15, 0x02};
+ uint8_t rr_res = 2;
+ struct msgb *msg;
+
+ printf("Testing creating Assignment Failure\n");
+ msg = gsm0808_create_assignment_failure(0x23, NULL);
+ VERIFY(msg, res1, ARRAY_SIZE(res1));
+ msgb_free(msg);
+
+ msg = gsm0808_create_assignment_failure(0x23, &rr_res);
+ VERIFY(msg, res2, ARRAY_SIZE(res2));
+ msgb_free(msg);
+}
+
+static void test_create_clear_rqst()
+{
+ static const uint8_t res[] = { 0x00, 0x04, 0x22, 0x04, 0x01, 0x23 };
+ struct msgb *msg;
+
+ printf("Testing creating Clear Request\n");
+ msg = gsm0808_create_clear_rqst(0x23);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+}
+
+static void test_create_dtap()
+{
+ static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
+ struct msgb *msg, *l3;
+
+ printf("Testing creating DTAP\n");
+ l3 = msgb_alloc_headroom(512, 128, "test");
+ l3->l3h = l3->data;
+ msgb_v_put(l3, 0x23);
+ msgb_v_put(l3, 0x42);
+
+ msg = gsm0808_create_dtap(l3, 0x3);
+ VERIFY(msg, res, ARRAY_SIZE(res));
+ msgb_free(msg);
+ msgb_free(l3);
+}
+
+static void test_prepend_dtap()
+{
+ static const uint8_t res[] = { 0x01, 0x03, 0x02, 0x23, 0x42 };
+ struct msgb *in_msg;
+
+ printf("Testing prepend DTAP\n");
+
+ in_msg = msgb_alloc_headroom(512, 128, "test");
+ msgb_v_put(in_msg, 0x23);
+ msgb_v_put(in_msg, 0x42);
+
+ gsm0808_prepend_dtap_header(in_msg, 0x3);
+ in_msg->l3h = in_msg->data;
+ VERIFY(in_msg, res, ARRAY_SIZE(res));
+ msgb_free(in_msg);
+}
+
+int main(int argc, char **argv)
+{
+ printf("Testing generation of GSM0808 messages\n");
+ test_create_layer3();
+ test_create_reset();
+ test_create_clear_command();
+ test_create_clear_complete();
+ test_create_cipher_complete();
+ test_create_cipher_reject();
+ test_create_cm_u();
+ test_create_sapi_reject();
+ test_create_ass_compl();
+ test_create_ass_fail();
+ test_create_clear_rqst();
+ test_create_dtap();
+ test_prepend_dtap();
+
+ printf("Done\n");
+ return EXIT_SUCCESS;
+}
diff --git a/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok b/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok
new file mode 100644
index 00000000..eb431267
--- /dev/null
+++ b/src/shared/libosmocore/tests/gsm0808/gsm0808_test.ok
@@ -0,0 +1,15 @@
+Testing generation of GSM0808 messages
+Testing creating Layer3
+Testing creating Reset
+Testing creating Clear Command
+Testing creating Clear Complete
+Testing creating Cipher Complete
+Testing creating Cipher Reject
+Testing creating CM U
+Testing creating SAPI Reject
+Testing creating Assignment Complete
+Testing creating Assignment Failure
+Testing creating Clear Request
+Testing creating DTAP
+Testing prepend DTAP
+Done
diff --git a/src/shared/libosmocore/tests/lapd/lapd_test.c b/src/shared/libosmocore/tests/lapd/lapd_test.c
index 8c6b0df2..d58bec65 100644
--- a/src/shared/libosmocore/tests/lapd/lapd_test.c
+++ b/src/shared/libosmocore/tests/lapd/lapd_test.c
@@ -73,8 +73,8 @@ static const uint8_t cm_padded[] = {
};
static const uint8_t mm[] = {
- 0x05, 0x24, 0x31, 0x03, 0x50, 0x18, 0x93, 0x08,
- 0x29, 0x47, 0x80, 0x00,
+ 0x00, 0x0c, 0x00, 0x03, 0x01, 0x01, 0x20, 0x02,
+ 0x00, 0x0b, 0x00, 0x03, 0x05, 0x04, 0x0d
};
static const uint8_t dummy1[] = {
@@ -95,6 +95,20 @@ static struct msgb *create_mm_id_req(void)
struct msgb *msg;
msg = msgb_from_array(mm, sizeof(mm));
+ msg->l2h = msg->data + 3;
+ ASSERT(msgb_l2len(msg) == 12);
+ msg->l3h = msg->l2h + 6;
+ ASSERT(msgb_l3len(msg) == 6);
+
+ return msg;
+}
+
+static struct msgb *create_empty_msg(void)
+{
+ struct msgb *msg;
+
+ msg = msgb_from_array(NULL, 0);
+ ASSERT(msgb_l3len(msg) == 0);
rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
return msg;
}
@@ -194,9 +208,9 @@ static int ms_to_bts_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *_ctx
/* ASSERT(msg->data[7] == 0x0 && msg->data[8] == 0x9c); */
/* this should be 0x0 and 0x0... but we have a bug */
} else if (state->ms_read == 1) {
- printf("MS: Verifying incoming MM message.\n");
- ASSERT(msgb_l3len(msg) == ARRAY_SIZE(mm));
- ASSERT(memcmp(msg->l3h, mm, msgb_l3len(msg)) == 0);
+ printf("MS: Verifying incoming MM message: %d\n", msgb_l3len(msg));
+ ASSERT(msgb_l3len(msg) == 3);
+ ASSERT(memcmp(msg->l3h, &mm[12], msgb_l3len(msg)) == 0);
} else {
printf("MS: Do not know to verify: %d\n", state->ms_read);
}
@@ -271,7 +285,7 @@ static void test_lapdm_polling()
lapdm_rslms_recvmsg(create_dummy_data_req(), &ms_to_bts_channel);
- /* 4. And back to the MS */
+ /* 4. And back to the MS, but let's move data/l2h apart */
ASSERT(test_state.bts_read == 2)
ASSERT(test_state.ms_read == 2);
rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
@@ -284,6 +298,11 @@ static void test_lapdm_polling()
rc = lapdm_phsap_dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp);
ASSERT(rc < 0);
+ /* check sending an empty L3 message fails */
+ rc = lapdm_rslms_recvmsg(create_empty_msg(), &bts_to_ms_channel);
+ ASSERT(rc == -1);
+ ASSERT(test_state.ms_read == 2);
+
/* clean up */
lapdm_channel_exit(&bts_to_ms_channel);
lapdm_channel_exit(&ms_to_bts_channel);
diff --git a/src/shared/libosmocore/tests/lapd/lapd_test.ok b/src/shared/libosmocore/tests/lapd/lapd_test.ok
index 058ac3d7..d67a0a80 100644
--- a/src/shared/libosmocore/tests/lapd/lapd_test.ok
+++ b/src/shared/libosmocore/tests/lapd/lapd_test.ok
@@ -9,8 +9,8 @@ ms_to_bts_tx_cb: BTS->MS(us) message 9
MS: Verifying incoming primitive.
Sending back to MS
-ms_to_bts_tx_cb: BTS->MS(us) message 21
-MS: Verifying incoming MM message.
+ms_to_bts_tx_cb: BTS->MS(us) message 12
+MS: Verifying incoming MM message: 3
ms_to_bts_l1_cb: MS(us) -> BTS prim message
Sending back to BTS
diff --git a/src/shared/libosmocore/tests/testsuite.at b/src/shared/libosmocore/tests/testsuite.at
index 6aae04d4..69624c12 100644
--- a/src/shared/libosmocore/tests/testsuite.at
+++ b/src/shared/libosmocore/tests/testsuite.at
@@ -65,3 +65,9 @@ AT_KEYWORDS([lapd])
cat $abs_srcdir/lapd/lapd_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/lapd/lapd_test], [], [expout], [ignore])
AT_CLEANUP
+
+AT_SETUP([gsm0808])
+AT_KEYWORDS([gsm0808])
+cat $abs_srcdir/gsm0808/gsm0808_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gsm0808/gsm0808_test], [], [expout], [ignore])
+AT_CLEANUP
diff --git a/src/shared/libosmocore/utils/osmo-auc-gen.c b/src/shared/libosmocore/utils/osmo-auc-gen.c
index 62b51289..e3502b2c 100644
--- a/src/shared/libosmocore/utils/osmo-auc-gen.c
+++ b/src/shared/libosmocore/utils/osmo-auc-gen.c
@@ -1,6 +1,6 @@
/* GSM/GPRS/3G authentication testing tool */
-/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -52,17 +52,34 @@ static struct osmo_sub_auth_data test_aud = {
.algo = OSMO_AUTH_ALG_NONE,
};
+static void help()
+{
+ printf( "-2 --2g\tUse 2G (GSM) authentication\n"
+ "-3 --3g\tUse 3G (UMTS) authentication\n"
+ "-a --algorithm\tSpecify name of the algorithm\n"
+ "-k --key\tSpecify Ki / K\n"
+ "-o --opc\tSpecify OPC (only for 3G)\n"
+ "-O --op\tSpecify OP (only for 3G)\n"
+ "-a --amf\tSpecify AMF (only for 3G)\n"
+ "-s --sqn\tSpecify SQN (only for 3G)\n"
+ "-A --auts\tSpecify AUTS (only for 3G)\n"
+ "-r --rand\tSpecify random value\n");
+}
+
int main(int argc, char **argv)
{
struct osmo_auth_vector _vec;
struct osmo_auth_vector *vec = &_vec;
- uint8_t _rand[16];
+ uint8_t _rand[16], _auts[16];
int rc, option_index;
int rand_is_set = 0;
+ int auts_is_set = 0;
- printf("osmo-auc-gen (C) 2011 by Harald Welte\n");
+ printf("osmo-auc-gen (C) 2011-2012 by Harald Welte\n");
printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
+ memset(_auts, 0, sizeof(_auts));
+
while (1) {
int c;
unsigned long ul;
@@ -72,15 +89,18 @@ int main(int argc, char **argv)
{ "algorithm", 1, 0, 'a' },
{ "key", 1, 0, 'k' },
{ "opc", 1, 0, 'o' },
+ { "op", 1, 0, 'O' },
{ "amf", 1, 0, 'f' },
{ "sqn", 1, 0, 's' },
{ "rand", 1, 0, 'r' },
+ { "auts", 1, 0, 'A' },
+ { "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};
rc = 0;
- c = getopt_long(argc, argv, "23a:k:o:f:s:r:", long_options,
+ c = getopt_long(argc, argv, "23a:k:o:f:s:r:hO:A:", long_options,
&option_index);
if (c == -1)
@@ -120,6 +140,24 @@ int main(int argc, char **argv)
}
rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
sizeof(test_aud.u.umts.opc));
+ test_aud.u.umts.opc_is_op = 0;
+ break;
+ case 'O':
+ if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
+ fprintf(stderr, "Only UMTS has OP\n");
+ exit(2);
+ }
+ rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
+ sizeof(test_aud.u.umts.opc));
+ test_aud.u.umts.opc_is_op = 1;
+ break;
+ case 'A':
+ if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
+ fprintf(stderr, "Only UMTS has AUTS\n");
+ exit(2);
+ }
+ rc = osmo_hexparse(optarg, _auts, sizeof(_auts));
+ auts_is_set = 1;
break;
case 'f':
if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
@@ -141,6 +179,12 @@ int main(int argc, char **argv)
rc = osmo_hexparse(optarg, _rand, sizeof(_rand));
rand_is_set = 1;
break;
+ case 'h':
+ help();
+ exit(0);
+ default:
+ help();
+ exit(1);
}
if (rc < 0) {
@@ -158,26 +202,30 @@ int main(int argc, char **argv)
*(uint32_t *)(&_rand[12]) = rand();
}
+ if (test_aud.type == OSMO_AUTH_TYPE_NONE ||
+ test_aud.algo == OSMO_AUTH_ALG_NONE) {
+ help();
+ exit(2);
+ }
+
memset(vec, 0, sizeof(*vec));
- rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
+ if (!auts_is_set)
+ rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
+ else
+ rc = osmo_auth_gen_vec_auts(vec, &test_aud, _auts, _rand, _rand);
if (rc < 0) {
- fprintf(stderr, "error generating auth vector\n");
+ if (!auts_is_set)
+ fprintf(stderr, "error generating auth vector\n");
+ else
+ fprintf(stderr, "AUTS from MS seems incorrect\n");
exit(1);
}
dump_auth_vec(vec);
-#if 0
- const uint8_t auts[14] = { 0x87, 0x11, 0xa0, 0xec, 0x9e, 0x16, 0x37, 0xdf,
- 0x17, 0xf8, 0x0b, 0x38, 0x4e, 0xe4 };
- rc = osmo_auth_gen_vec_auts(vec, &test_aud, auts, _rand, _rand);
- if (rc < 0) {
- printf("AUTS failed\n");
- } else {
+ if (auts_is_set)
printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn);
- }
-#endif
- exit(0);
+ exit(0);
}