aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-06-08 16:28:15 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-07-01 08:16:40 +0200
commit9705671025eba34b70d73e9d4e78813e4f2d31da (patch)
tree8bd643348c44f9d19f6e719b6197f33f121aa9a5
parentfce6971fe3673e8269414188fda0ce3b28b5cf03 (diff)
nat: Send 16 bytes of rand to the BSC and remember it
Generate 16 byte of random data to be used for A3A8 by the BSC in the response. We can't know which BSC it is at this point and I don't want to send another message once the token has been received so always send the data with an undefined code. The old BSCs don't parse the message and will happily ignore the RAND. /dev/urandom can give short reads on Linux so loop around it until the bytes have been read from the kernel.
-rw-r--r--openbsc/include/openbsc/bsc_nat.h1
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c40
2 files changed, 38 insertions, 3 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 103593780..c313e5244 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -84,6 +84,7 @@ struct bsc_connection {
/* do we know anything about this BSC? */
int authenticated;
+ uint8_t last_rand[16];
/* the fd we use to communicate */
struct osmo_wqueue write_queue;
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 82562ba17..254ea42f2 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -188,9 +188,9 @@ static void send_id_ack(struct bsc_connection *bsc)
bsc_send_data(bsc, id_ack, sizeof(id_ack), IPAC_PROTO_IPACCESS);
}
-static void send_id_req(struct bsc_connection *bsc)
+static void send_id_req(struct bsc_nat *nat, struct bsc_connection *bsc)
{
- static const uint8_t id_req[] = {
+ static const uint8_t s_id_req[] = {
IPAC_MSGT_ID_GET,
0x01, IPAC_IDTAG_UNIT,
0x01, IPAC_IDTAG_MACADDR,
@@ -202,7 +202,41 @@ static void send_id_req(struct bsc_connection *bsc)
0x01, IPAC_IDTAG_SERNR,
};
+ int toread, rounds;
+ uint8_t *mrand, *randoff;
+ uint8_t id_req[sizeof(s_id_req) + (2+16)];
+ uint8_t *buf = &id_req[sizeof(s_id_req)];
+
+ /* copy the static data */
+ memcpy(id_req, s_id_req, sizeof(s_id_req));
+
+ /* put the RAND with length, tag, value */
+ buf = v_put(buf, 0x11);
+ buf = v_put(buf, 0x23);
+ mrand = bsc->last_rand;
+ randoff = mrand;
+ memset(randoff, 0, 16);
+
+ for (toread = 16, rounds = 0; rounds < 5 && toread > 0; ++rounds) {
+ int rc = read(nat->random_fd, randoff, toread);
+ if (rc <= 0)
+ goto failed_random;
+ toread -= rc;
+ randoff += rc;
+ }
+
+ if (toread != 0)
+ goto failed_random;
+ memcpy(buf, mrand, 16);
+ buf += 16;
+
bsc_send_data(bsc, id_req, sizeof(id_req), IPAC_PROTO_IPACCESS);
+ return;
+
+failed_random:
+ /* the timeout will trigger and close this connection */
+ LOGP(DNAT, LOGL_ERROR, "Failed to read from urandom.\n");
+ return;
}
static struct msgb *nat_create_rlsd(struct nat_sccp_connection *conn)
@@ -1362,7 +1396,7 @@ static int ipaccess_listen_bsc_cb(struct osmo_fd *bfd, unsigned int what)
bsc->last_id = 0;
send_id_ack(bsc);
- send_id_req(bsc);
+ send_id_req(nat, bsc);
send_mgcp_reset(bsc);
/*