aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2011-04-23 23:55:14 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2011-04-26 09:33:47 +0200
commitde2b860dffd5e55b52ecf0db36b326f17cf70e10 (patch)
treef02645e5bfa2764133087453bc143911fc5efb19 /openbsc
parentc3f28320c24024e6e970735eef6f062821d588a2 (diff)
nat: Introduce a block on the NAT to slowly get rid of BSCs
For restarting the NAT we can now block it, it will not accept new connections and for existing connections it will attempt to drop them over time. A blocked NAT will end up with no BSC connections left and then can be safely restarted.
Diffstat (limited to 'openbsc')
-rw-r--r--openbsc/include/openbsc/bsc_nat.h3
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat.c35
-rw-r--r--openbsc/src/osmo-bsc_nat/bsc_nat_vty.c12
3 files changed, 50 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index e1848312d..8d552e254 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -264,6 +264,9 @@ struct bsc_nat {
struct bsc_fd ussd_listen;
struct bsc_nat_ussd_con *ussd_con;
+ /* for maintainenance */
+ int blocked;
+
/* statistics */
struct bsc_nat_statistics stats;
};
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 295074593..bbb2ae35c 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -847,6 +847,23 @@ void bsc_close_connection(struct bsc_connection *connection)
talloc_free(connection);
}
+static void bsc_maybe_close(struct bsc_connection *bsc)
+{
+ struct sccp_connections *sccp;
+ if (!bsc->nat->blocked)
+ return;
+
+ /* are there any connections left */
+ llist_for_each_entry(sccp, &bsc->nat->sccp_connections, list_entry)
+ if (sccp->bsc == bsc)
+ return;
+
+ /* nothing left, close the BSC */
+ LOGP(DNAT, LOGL_NOTICE, "Cleaning up BSC %d in blocking mode.\n",
+ bsc->cfg ? bsc->cfg->nr : -1);
+ bsc_close_connection(bsc);
+}
+
static void ipaccess_close_bsc(void *data)
{
struct sockaddr_in sock;
@@ -1008,6 +1025,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
con_filter = con->con_local;
}
remove_sccp_src_ref(bsc, msg, parsed);
+ bsc_maybe_close(bsc);
break;
case SCCP_MSG_TYPE_UDT:
/* simply forward everything */
@@ -1168,6 +1186,12 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
return 0;
}
+ if (nat->blocked) {
+ LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due NAT being blocked.\n");
+ close(fd);
+ return 0;
+ }
+
on = 1;
rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
if (rc != 0)
@@ -1302,6 +1326,8 @@ static void signal_handler(int signal)
static void sccp_close_unconfirmed(void *_data)
{
+ int destroyed = 0;
+ struct bsc_connection *bsc, *bsc_tmp;
struct sccp_connections *conn, *tmp1;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1318,8 +1344,17 @@ static void sccp_close_unconfirmed(void *_data)
sccp_src_ref_to_int(&conn->real_ref),
sccp_src_ref_to_int(&conn->patched_ref));
sccp_connection_destroy(conn);
+ destroyed = 1;
}
+ if (!destroyed)
+ goto out;
+
+ /* now close out any BSC */
+ llist_for_each_entry_safe(bsc, bsc_tmp, &nat->bsc_connections, list_entry)
+ bsc_maybe_close(bsc);
+
+out:
bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
}
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index da4815084..ef433caed 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -749,6 +749,17 @@ DEFUN(set_last_endp, set_last_endp_cmd,
return CMD_SUCCESS;
}
+DEFUN(block_new_conn, block_new_conn_cmd,
+ "nat-block (block|unblock)",
+ "Block the NAT for new connections\n"
+ "Block\n" "Unblock\n")
+{
+ _nat->blocked = argv[0][0] == 'b';
+ vty_out(vty, "%%Going to %s the NAT.%s",
+ _nat->blocked ? "block" : "unblock", VTY_NEWLINE);
+ return CMD_SUCCESS;
+}
+
int bsc_nat_vty_init(struct bsc_nat *nat)
{
_nat = nat;
@@ -766,6 +777,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element_ve(&show_acc_lst_cmd);
install_element(ENABLE_NODE, &set_last_endp_cmd);
+ install_element(ENABLE_NODE, &block_new_conn_cmd);
/* nat group */
install_element(CONFIG_NODE, &cfg_nat_cmd);