diff options
-rw-r--r-- | openbsc/include/openbsc/bsc_nat.h | 5 | ||||
-rw-r--r-- | openbsc/src/bsc_msc_ip.c | 37 | ||||
-rw-r--r-- | openbsc/src/nat/bsc_nat.c | 50 |
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; } |