aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2015-09-11 01:34:45 +0200
committerHarald Welte <laforge@gnumonks.org>2015-09-11 01:36:44 +0200
commit10dfc5a97daae6bbd16a10d5d2fd39e2ef77fb34 (patch)
treeec8625da7bbda59261ae53c788a5ea61d02d2d8d
parent256c67ad81eae9bdcd8e49dd6f9133cf64d27c88 (diff)
respond to HNBAP UE REGISTER REQ withe correspnding ACCEPT
The Accept incudes the IMSI that the phone presented, but somehow we fail to encode the Context ID as bitstring, see ../pcap/20150911-hnbap-ue_register.pcap
-rw-r--r--pcap/20150911-hnbap-ue_register.pcapbin0 -> 6712 bytes
-rw-r--r--src/hnbgw.c2
-rw-r--r--src/hnbgw_hnbap.c83
3 files changed, 78 insertions, 7 deletions
diff --git a/pcap/20150911-hnbap-ue_register.pcap b/pcap/20150911-hnbap-ue_register.pcap
new file mode 100644
index 0000000..9874af9
--- /dev/null
+++ b/pcap/20150911-hnbap-ue_register.pcap
Binary files differ
diff --git a/src/hnbgw.c b/src/hnbgw.c
index ac0d03c..b50cd9d 100644
--- a/src/hnbgw.c
+++ b/src/hnbgw.c
@@ -9,6 +9,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/sctp.h>
+//#include <arpa/inet.h>
#include <osmocom/core/application.h>
#include <osmocom/core/talloc.h>
@@ -245,6 +246,7 @@ int main(int argc, char **argv)
g_hnb_gw.listen_fd.cb = listen_fd_cb;
g_hnb_gw.listen_fd.when = BSC_FD_READ;
g_hnb_gw.listen_fd.data = &g_hnb_gw;
+ g_hnb_gw.next_ue_ctx_id = 23;
INIT_LLIST_HEAD(&g_hnb_gw.hnb_list);
INIT_LLIST_HEAD(&g_hnb_gw.ue_list);
diff --git a/src/hnbgw_hnbap.c b/src/hnbgw_hnbap.c
index d00d59e..7810573 100644
--- a/src/hnbgw_hnbap.c
+++ b/src/hnbgw_hnbap.c
@@ -1,5 +1,6 @@
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
+#include <osmocom/gsm/gsm48.h>
#include <unistd.h>
#include <errno.h>
@@ -23,6 +24,51 @@ static int hnbgw_hnbap_tx(struct hnb_context *ctx, struct msgb *msg)
return osmo_wqueue_enqueue(&ctx->wqueue, msg);
}
+int decode_iu_bcd(char *out, size_t out_len, const uint8_t *in, size_t in_len)
+{
+ const uint8_t *ch;
+ char *outch = out;
+
+ for (ch = in; ch < in + in_len; ch++) {
+ char c = osmo_bcd2char(*ch & 0xF);
+ *outch++ = c;
+ if (outch + 1 >= out + out_len)
+ break;
+ c = osmo_bcd2char(*ch >> 4);
+ /* skip padding nibble at end */
+ if (c == 'F')
+ break;
+ *outch++ = c;
+ }
+ *outch++ = '\0';
+ return outch - out;
+}
+
+int encode_iu_imsi(uint8_t *out, size_t out_len,
+ const char *in)
+{
+ unsigned int len = strlen(in);
+ uint8_t odd = (len & 0x01) == 1;
+ unsigned int off = 0;
+ unsigned int i;
+
+ len /= 2;
+ if (odd)
+ len++;
+
+ for (i = 0; i < len; i++) {
+ uint8_t lower, upper;
+
+ lower = osmo_char2bcd(in[++off]) & 0x0f;
+ if (!odd && off + 1 == len)
+ upper = 0x0f;
+ else
+ upper = osmo_char2bcd(in[++off]) & 0x0f;
+
+ out[i] = (upper << 4) | lower;
+ }
+ return i;
+}
static int hnbgw_tx_hnb_register_acc(struct hnb_context *ctx)
{
@@ -57,10 +103,15 @@ static int hnbgw_tx_ue_register_acc(struct ue_context *ue)
UERegisterAccept_t accept_out;
UERegisterAcceptIEs_t accept;
struct msgb *msg;
+ uint8_t encoded_imsi[10];
+ size_t encoded_imsi_len;
int rc;
- /* FIXME accept.uE_Identity; */
+ encoded_imsi_len = encode_iu_imsi(encoded_imsi, sizeof(encoded_imsi), ue->imsi);
+
memset(&accept, 0, sizeof(accept));
+ accept.uE_Identity.present = UE_Identity_PR_iMSI;
+ OCTET_STRING_fromBuf(&accept.uE_Identity.choice.iMSI, (const char *)encoded_imsi, encoded_imsi_len);
asn1_u32_to_bitstring(&accept.context_ID, &ue->context_id);
memset(&accept_out, 0, sizeof(accept_out));
@@ -105,19 +156,37 @@ static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, ANY_t *in)
{
UERegisterRequestIEs_t ies;
struct ue_context *ue;
+ char imsi[16];
int rc;
rc = hnbap_decode_ueregisterrequesties(&ies, in);
if (rc < 0)
return rc;
- /* FIXME: convert UE identity into a more palatable format */
- ue = ue_context_by_imsi("123");
- if (!ue)
- ue = ue_context_alloc(ctx, "123");
+ switch (ies.uE_Identity.present) {
+ case UE_Identity_PR_iMSI:
+ decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSI.buf,
+ ies.uE_Identity.choice.iMSI.size);
+ break;
+ case UE_Identity_PR_iMSIDS41:
+ decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIDS41.buf,
+ ies.uE_Identity.choice.iMSIDS41.size);
+ break;
+ case UE_Identity_PR_iMSIESN:
+ decode_iu_bcd(imsi, sizeof(imsi), ies.uE_Identity.choice.iMSIESN.iMSIDS41.buf,
+ ies.uE_Identity.choice.iMSIESN.iMSIDS41.size);
+ break;
+ default:
+ DEBUGP(DMAIN, "UE-REGISTER-REQ without IMSI?!?\n");
+ return -1;
+ }
- DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d cause=%ld\n",
- ies.uE_Identity.present, ies.registration_Cause);
+ DEBUGP(DMAIN, "UE-REGSITER-REQ ID_type=%d imsi=%s cause=%ld\n",
+ ies.uE_Identity.present, imsi, ies.registration_Cause);
+
+ ue = ue_context_by_imsi(imsi);
+ if (!ue)
+ ue = ue_context_alloc(ctx, imsi);
/* Send UERegisterAccept */
return hnbgw_tx_ue_register_acc(ue);