aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-05-16 20:43:52 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-05-16 20:45:16 +0800
commit4fcf80a59a58f920862eb6db5135e8d01e9b5e12 (patch)
tree6f9140741ebba659cb7ea59739b6764247f0f8d8
parent31e0bafa1063e83d2a78241f35ff56c7792096c6 (diff)
[nat] Make the refusal more complicated to support more MSCs
We will need to confirm the connection, then we can send the GSM48 message, then we need to close the connection... the embedding in the refusal method was way too easy..
-rw-r--r--openbsc/include/openbsc/bsc_nat.h1
-rw-r--r--openbsc/src/nat/bsc_nat.c58
-rw-r--r--openbsc/src/nat/bsc_nat_utils.c1
3 files changed, 53 insertions, 7 deletions
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 64be6b36..00d2cba1 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -47,6 +47,7 @@ enum {
NAT_CON_TYPE_LU,
NAT_CON_TYPE_CM_SERV_REQ,
NAT_CON_TYPE_PAG_RESP,
+ NAT_CON_TYPE_LOCAL_REJECT,
NAT_CON_TYPE_OTHER,
};
diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c
index a1192475..60af912b 100644
--- a/openbsc/src/nat/bsc_nat.c
+++ b/openbsc/src/nat/bsc_nat.c
@@ -301,22 +301,66 @@ static void bsc_send_con_refuse(struct bsc_connection *bsc,
struct msgb *payload;
struct msgb *refuse;
- if (con_type == NAT_CON_TYPE_LU) {
+ if (con_type == NAT_CON_TYPE_LU)
payload = gsm48_create_loc_upd_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
- gsm0808_prepend_dtap_header(payload, 0);
- } else if (con_type == NAT_CON_TYPE_CM_SERV_REQ) {
+ else if (con_type == NAT_CON_TYPE_CM_SERV_REQ)
payload = gsm48_create_mm_serv_rej(GSM48_REJECT_PLMN_NOT_ALLOWED);
+
+ /*
+ * Some BSCs do not handle the payload inside a SCCP CREF msg
+ * so we will need to:
+ * 1.) Allocate a local connection and mark it as local..
+ * 2.) queue data for downstream.. and the RLC should delete everything
+ */
+ if (payload) {
+ struct msgb *cc, *udt, *rlsd;
+ struct sccp_connections *con;
+ con = create_sccp_src_ref(bsc, parsed);
+ if (!con)
+ goto send_refuse;
+
+ /* declare it local and assign a unique remote_ref */
+ con->con_type = NAT_CON_TYPE_LOCAL_REJECT;
+ con->con_local = 1;
+ con->has_remote_ref = 1;
+ con->remote_ref = con->patched_ref;
+
+ /* 1. create a confirmation */
+ cc = sccp_create_cc(&con->remote_ref, &con->real_ref);
+ if (!cc)
+ goto send_refuse;
+
+ /* 2. create the DT1 */
gsm0808_prepend_dtap_header(payload, 0);
+ udt = sccp_create_dt1(&con->real_ref, payload->data, payload->len);
+ if (!udt) {
+ msgb_free(cc);
+ goto send_refuse;
+ }
+
+ /* 3. send a RLSD */
+ rlsd = sccp_create_rlsd(&con->remote_ref, &con->real_ref,
+ SCCP_RELEASE_CAUSE_END_USER_ORIGINATED);
+ if (!rlsd) {
+ msgb_free(cc);
+ msgb_free(udt);
+ goto send_refuse;
+ }
+
+ bsc_write(bsc, cc, IPAC_PROTO_SCCP);
+ bsc_write(bsc, udt, IPAC_PROTO_SCCP);
+ bsc_write(bsc, rlsd, IPAC_PROTO_SCCP);
+ msgb_free(payload);
+ return;
}
- refuse = sccp_create_refuse(parsed->src_local_ref,
- SCCP_REFUSAL_SCCP_FAILURE,
- payload ? payload->data : NULL,
- payload ? payload->len : 0);
+send_refuse:
if (payload)
msgb_free(payload);
+ refuse = sccp_create_refuse(parsed->src_local_ref,
+ SCCP_REFUSAL_SCCP_FAILURE, NULL, 0);
if (!refuse) {
LOGP(DNAT, LOGL_ERROR,
"Creating refuse msg failed for SCCP 0x%x on BSC Nr: %d.\n",
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index edc398ab..5890c07c 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -395,6 +395,7 @@ static const char *con_types [] = {
[NAT_CON_TYPE_LU] = "Location Update",
[NAT_CON_TYPE_CM_SERV_REQ] = "CM Serv Req",
[NAT_CON_TYPE_PAG_RESP] = "Paging Response",
+ [NAT_CON_TYPE_LOCAL_REJECT] = "Local Reject",
[NAT_CON_TYPE_OTHER] = "Other",
};