aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/bsc_nat.h5
-rw-r--r--openbsc/src/bsc_msc_ip.c37
-rw-r--r--openbsc/src/nat/bsc_nat.c50
3 files changed, 88 insertions, 4 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 66acde504..1da58bcba 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -32,6 +32,8 @@
#define DIR_BSC 1
#define DIR_MSC 2
+struct bsc_nat;
+
/*
* For the NAT we will need to analyze and later patch
* the received message. This would require us to parse
@@ -82,6 +84,9 @@ struct bsc_connection {
/* a timeout node */
struct timer_list id_timeout;
+
+ /* a back pointer */
+ struct bsc_nat *nat;
};
/*
diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c
index 54ed96b2a..518fbed26 100644
--- a/openbsc/src/bsc_msc_ip.c
+++ b/openbsc/src/bsc_msc_ip.c
@@ -610,6 +610,33 @@ static void initialize_if_needed(void)
}
}
+static void send_id_get_response(int fd)
+{
+ struct msgb *msg;
+ if (!bsc_gsmnet) {
+ LOGP(DMSC, LOGL_ERROR, "The network is not initialized yet.\n");
+ return;
+ }
+
+ if (!bsc_gsmnet->bsc_token) {
+ LOGP(DMSC, LOGL_ERROR, "The bsc token is not set.\n");
+ return;
+ }
+
+ msg = msgb_alloc_headroom(4096, 128, "id resp");
+
+ msg->l2h = msgb_v_put(msg, IPAC_MSGT_ID_RESP);
+ msgb_l16tv_put(msg, strlen(bsc_gsmnet->bsc_token) + 1,
+ IPAC_IDTAG_UNITNAME, (u_int8_t *) bsc_gsmnet->bsc_token);
+ ipaccess_prepend_header(msg, IPAC_PROTO_IPACCESS);
+
+ if (write(fd, msg->data, msg->len) != msg->len) {
+ LOGP(DMSC, LOGL_ERROR, "Short write.\n");
+ }
+
+ msgb_free(msg);
+}
+
/*
* callback with IP access data
*/
@@ -636,9 +663,13 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd, unsigned int what)
ipaccess_rcvmsg_base(msg, bfd);
/* initialize the networking. This includes sending a GSM08.08 message */
- if (hh->proto == IPAC_PROTO_IPACCESS && msg->l2h[0] == IPAC_MSGT_ID_ACK)
- initialize_if_needed();
- else if (hh->proto == IPAC_PROTO_SCCP)
+ if (hh->proto == IPAC_PROTO_IPACCESS) {
+ if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
+ initialize_if_needed();
+ else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
+ send_id_get_response(bfd->fd);
+ }
+ } else if (hh->proto == IPAC_PROTO_SCCP)
sccp_system_incoming(msg);
return 0;
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index aee009545..8466876bf 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -379,8 +379,12 @@ static void remove_bsc_connection(struct bsc_connection *connection)
{
struct sccp_connections *sccp_patch, *tmp;
bsc_unregister_fd(&connection->bsc_fd);
+ close(connection->bsc_fd.fd);
llist_del(&connection->list_entry);
+ /* stop the timeout timer */
+ bsc_del_timer(&connection->id_timeout);
+
/* remove all SCCP connections */
llist_for_each_entry_safe(sccp_patch, tmp, &nat->sccp_connections, list_entry) {
if (sccp_patch->bsc != connection)
@@ -393,6 +397,29 @@ static void remove_bsc_connection(struct bsc_connection *connection)
talloc_free(connection);
}
+static void ipaccess_close_bsc(void *data)
+{
+ struct bsc_connection *conn = data;
+
+ LOGP(DNAT, LOGL_ERROR, "BSC didn't respond to identity request. Closing.\n");
+ remove_bsc_connection(conn);
+}
+
+static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc)
+{
+ struct bsc_config *conf;
+ const char* token = (const char *) TLVP_VAL(tvp, IPAC_IDTAG_UNITNAME);
+
+ llist_for_each_entry(conf, &bsc->nat->bsc_configs, entry) {
+ if (strcmp(conf->token, token) == 0) {
+ bsc->authenticated = 1;
+ bsc->lac = conf->lac;
+ bsc_del_timer(&bsc->id_timeout);
+ break;
+ }
+ }
+}
+
static int forward_sccp_to_msc(struct bsc_fd *bfd, struct msgb *msg)
{
struct bsc_connection *bsc;
@@ -459,6 +486,18 @@ exit:
if (parsed->bssap == 0 && parsed->gsm_type == BSS_MAP_MSG_RESET) {
send_reset_ack(bfd);
send_reset_ack(bfd);
+ } else if (parsed->ipa_proto == IPAC_PROTO_IPACCESS) {
+ /* do we know who is handling this? */
+ if (msg->l2h[0] == IPAC_MSGT_ID_RESP) {
+ struct tlv_parsed tvp;
+ ipaccess_idtag_parse(&tvp,
+ (unsigned char *) msg->l2h + 2,
+ msgb_l2len(msg) - 2);
+ if (TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME))
+ ipaccess_auth_bsc(&tvp, bsc);
+ }
+
+ goto exit2;
}
exit2:
@@ -521,6 +560,7 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
return -1;
}
+ bsc->nat = nat;
bsc->bsc_fd.data = bsc;
bsc->bsc_fd.fd = ret;
bsc->bsc_fd.cb = ipaccess_bsc_cb;
@@ -534,7 +574,15 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
LOGP(DNAT, LOGL_INFO, "Registered new BSC\n");
llist_add(&bsc->list_entry, &nat->bsc_connections);
- ipaccess_send_id_ack(ret);
+ ipaccess_send_id_ack(bsc->bsc_fd.fd);
+ ipaccess_send_id_req(ret);
+
+ /*
+ * start the hangup timer
+ */
+ bsc->id_timeout.data = bsc;
+ bsc->id_timeout.cb = ipaccess_close_bsc;
+ bsc_schedule_timer(&bsc->id_timeout, 2, 0);
return 0;
}