aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Kluchnikov <kluchnikovi@gmail.com>2018-09-05 17:40:07 +0300
committerIvan Kluchnikov <kluchnikovi@gmail.com>2018-09-05 17:56:06 +0300
commit2458ccdec4ee59119afdb2ae5d13205788c42a6d (patch)
tree8ce73dd431d91a20ac7ed5a043cc8ab49de38d7a
parent246c2eece06e5248b58bec680de2e06606e32330 (diff)
hack: Send/receive data and control gb messages to/from different SGSN ports received during SNS configuration procedureuser/kluchnikov/gb-sns-hack
This patch is committed for historical purposes and it is required a significant rewrite. Data and control ports numbers are hardcoded, but they should be extracted from SNS-CONFIG message from SGSN. Changes to support both SNS and static configuration are required. Change-Id: I2494544e54c5af80ccea16c45c5f270835f8f346
-rw-r--r--include/osmocom/gprs/gprs_ns.h5
-rw-r--r--src/gb/gprs_bssgp_bss.c24
-rw-r--r--src/gb/gprs_ns.c106
-rw-r--r--src/gb/gprs_ns_sns.c6
4 files changed, 81 insertions, 60 deletions
diff --git a/include/osmocom/gprs/gprs_ns.h b/include/osmocom/gprs/gprs_ns.h
index febbde2..7698ca2 100644
--- a/include/osmocom/gprs/gprs_ns.h
+++ b/include/osmocom/gprs/gprs_ns.h
@@ -49,6 +49,9 @@ enum ns_timeout {
#define NS_DESC_A(st) ((st) & NSE_S_ALIVE ? "ALIVE" : "DEAD")
#define NS_DESC_R(st) ((st) & NSE_S_RESET ? "RESET" : "UNRESET")
+#define GB_SIGN_PORT 42000
+#define GB_DATA_PORT 2100
+
/*! Osmocom NS link layer types */
enum gprs_ns_ll {
GPRS_NS_LL_UDP, /*!< NS/UDP/IP */
@@ -181,6 +184,8 @@ struct sockaddr_in;
/* main function for higher layers (BSSGP) to send NS messages */
int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg);
+int gprs_ns_sendmsg_bss(struct gprs_ns_inst *nsi, struct msgb *msg, int port);
+
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause);
int gprs_ns_tx_block(struct gprs_nsvc *nsvc, uint8_t cause);
diff --git a/src/gb/gprs_bssgp_bss.c b/src/gb/gprs_bssgp_bss.c
index 487286c..eeaf919 100644
--- a/src/gb/gprs_bssgp_bss.c
+++ b/src/gb/gprs_bssgp_bss.c
@@ -69,7 +69,7 @@ int bssgp_tx_suspend(uint16_t nsei, uint32_t tlli,
bssgp_msgb_tlli_put(msg, tlli);
bssgp_msgb_ra_put(msg, ra_id);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/*! GMM-RESUME.req (Chapter 10.3.9) */
@@ -91,7 +91,7 @@ int bssgp_tx_resume(uint16_t nsei, uint32_t tlli,
msgb_tvlv_put(msg, BSSGP_IE_SUSPEND_REF_NR, 1, &suspend_ref);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/*! Transmit RA-CAPABILITY-UPDATE (10.3.3) */
@@ -113,7 +113,7 @@ int bssgp_tx_ra_capa_upd(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t tag)
msgb_tvlv_put(msg, BSSGP_IE_TAG, 1, &tag);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/* first common part of RADIO-STATUS */
@@ -141,7 +141,7 @@ static int common_tx_radio_status2(struct msgb *msg, uint8_t cause)
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
LOGPC(DBSSGP, LOGL_NOTICE, "CAUSE=%s\n", bssgp_cause_str(cause));
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/*! Transmit RADIO-STATUS for TLLI (10.3.5) */
@@ -213,7 +213,7 @@ int bssgp_tx_flush_ll_ack(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci_new);
msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, (uint8_t *) &_oct_aff);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT);
}
/*! Transmit LLC-DISCARDED (Chapter 10.4.3) */
@@ -239,7 +239,7 @@ int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
msgb_tvlv_put(msg, BSSGP_IE_NUM_OCT_AFF, 3, ((uint8_t *) &_oct_aff) + 1);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT);
}
/*! Transmit a BVC-BLOCK message (Chapter 10.4.8) */
@@ -260,7 +260,7 @@ int bssgp_tx_bvc_block(struct bssgp_bvc_ctx *bctx, uint8_t cause)
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
msgb_tvlv_put(msg, BSSGP_IE_CAUSE, 1, &cause);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT);
}
/*! Transmit a BVC-UNBLOCK message (Chapter 10.4.10) */
@@ -279,7 +279,7 @@ int bssgp_tx_bvc_unblock(struct bssgp_bvc_ctx *bctx)
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT);
}
/*! Transmit a BVC-RESET message (Chapter 10.4.12) */
@@ -306,7 +306,7 @@ int bssgp_tx_bvc_reset(struct bssgp_bvc_ctx *bctx, uint16_t bvci, uint8_t cause)
}
/* Optional: Feature Bitmap */
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_SIGN_PORT);
}
/*! Transmit a FLOW_CONTROL-BVC (Chapter 10.4.4)
@@ -378,7 +378,7 @@ int bssgp_tx_fc_bvc(struct bssgp_bvc_ctx *bctx, uint8_t tag,
sizeof(e_queue_delay),
(uint8_t *) &e_queue_delay);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/*! Transmit a FLOW_CONTROL-MS (Chapter 10.4.6)
@@ -421,7 +421,7 @@ int bssgp_tx_fc_ms(struct bssgp_bvc_ctx *bctx, uint32_t tlli, uint8_t tag,
msgb_tvlv_put(msg, BSSGP_IE_BUCKET_FULL_RATIO,
1, bucket_full_ratio);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/*! RL-UL-UNITDATA.req (Chapter 10.2.2)
@@ -467,7 +467,7 @@ int bssgp_tx_ul_ud(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
rate_ctr_inc(&bctx->ctrg->ctr[BSSGP_CTR_PKTS_OUT]);
rate_ctr_add(&bctx->ctrg->ctr[BSSGP_CTR_BYTES_OUT], msg->len);
- return gprs_ns_sendmsg(bssgp_nsi, msg);
+ return gprs_ns_sendmsg_bss(bssgp_nsi, msg, GB_DATA_PORT);
}
/* Parse a single GMM-PAGING.req to a given NSEI/NS-BVCI */
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c
index dc69302..c520243 100644
--- a/src/gb/gprs_ns.c
+++ b/src/gb/gprs_ns.c
@@ -259,8 +259,7 @@ static struct gprs_nsvc *nsvc_by_rem_addr(struct gprs_ns_inst *nsi,
struct gprs_nsvc *nsvc;
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
if (nsvc->ip.bts_addr.sin_addr.s_addr ==
- sin->sin_addr.s_addr &&
- nsvc->ip.bts_addr.sin_port == sin->sin_port)
+ sin->sin_addr.s_addr)
return nsvc;
}
return NULL;
@@ -444,29 +443,16 @@ static int gprs_ns_tx_simple(struct gprs_nsvc *nsvc, uint8_t pdu_type)
*/
int gprs_ns_tx_reset(struct gprs_nsvc *nsvc, uint8_t cause)
{
- struct msgb *msg = gprs_ns_msgb_alloc();
- struct gprs_ns_hdr *nsh;
- uint16_t nsvci = osmo_htons(nsvc->nsvci);
- uint16_t nsei = osmo_htons(nsvc->nsei);
-
- log_set_context(LOG_CTX_GB_NSVC, nsvc);
-
- if (!msg)
- return -ENOMEM;
-
- LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS RESET (NSVCI=%u, cause=%s)\n",
- nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause));
-
- msg->l2h = msgb_put(msg, sizeof(*nsh));
- nsh = (struct gprs_ns_hdr *) msg->l2h;
- nsh->pdu_type = NS_PDUT_RESET;
-
- msgb_tvlv_put(msg, NS_IE_CAUSE, 1, &cause);
- msgb_tvlv_put(msg, NS_IE_VCI, 2, (uint8_t *) &nsvci);
- msgb_tvlv_put(msg, NS_IE_NSEI, 2, (uint8_t *) &nsei);
-
- return gprs_ns_tx(nsvc, msg);
+ ns_set_state(nsvc, NSE_S_BLOCKED | NSE_S_ALIVE);
+ ns_set_remote_state(nsvc, NSE_S_BLOCKED | NSE_S_ALIVE);
+ rate_ctr_inc(&(nsvc)->ctrg->ctr[NS_CTR_BLOCKED]);
+ LOGP(DNS, LOGL_INFO, "NSEI=%u Rx NS UNBLOCK ACK\n", nsvc->nsei);
+ /* mark NS-VC as unblocked + active */
+ ns_set_state(nsvc, NSE_S_ALIVE);
+ ns_set_remote_state(nsvc, NSE_S_ALIVE);
+ ns_osmo_signal_dispatch(nsvc, S_NS_UNBLOCK, 0);
+ return 1;
}
/*! Transmit a NS-STATUS on a given NSVC
@@ -592,6 +578,8 @@ int gprs_ns_tx_alive_ack(struct gprs_nsvc *nsvc)
LOGP(DNS, LOGL_DEBUG, "NSEI=%u Tx NS ALIVE_ACK (NSVCI=%u)\n",
nsvc->nsei, nsvc->nsvci);
+ nsvc->ip.bts_addr.sin_port = htons(GB_SIGN_PORT);
+
return gprs_ns_tx_simple(nsvc, NS_PDUT_ALIVE_ACK);
}
@@ -887,6 +875,51 @@ int gprs_ns_sendmsg(struct gprs_ns_inst *nsi, struct msgb *msg)
return gprs_ns_tx(nsvc, msg);
}
+int gprs_ns_sendmsg_bss(struct gprs_ns_inst *nsi, struct msgb *msg, int port)
+{
+ struct gprs_nsvc *nsvc;
+ struct gprs_ns_hdr *nsh;
+ uint16_t bvci = msgb_bvci(msg);
+
+ nsvc = gprs_active_nsvc_by_nsei(nsi, msgb_nsei(msg));
+ if (!nsvc) {
+ int rc;
+ if (gprs_nsvc_by_nsei(nsi, msgb_nsei(msg))) {
+ LOGP(DNS, LOGL_ERROR,
+ "All NS-VCs for NSEI %u are either dead or blocked!\n",
+ msgb_nsei(msg));
+ rc = -EBUSY;
+ } else {
+ LOGP(DNS, LOGL_ERROR, "Unable to resolve NSEI %u "
+ "to NS-VC!\n", msgb_nsei(msg));
+ rc = -EINVAL;
+ }
+
+ msgb_free(msg);
+ return rc;
+ }
+ log_set_context(LOG_CTX_GB_NSVC, nsvc);
+
+ msg->l2h = msgb_push(msg, sizeof(*nsh) + 3);
+ nsh = (struct gprs_ns_hdr *) msg->l2h;
+ if (!nsh) {
+ LOGP(DNS, LOGL_ERROR, "Not enough headroom for NS header\n");
+ msgb_free(msg);
+ return -EIO;
+ }
+
+ nsh->pdu_type = NS_PDUT_UNITDATA;
+ /* spare octet in data[0] */
+ nsh->data[1] = bvci >> 8;
+ nsh->data[2] = bvci & 0xff;
+
+ //TX BSSGP
+ nsvc->ip.bts_addr.sin_port = htons(port);
+
+ return gprs_ns_tx(nsvc, msg);
+}
+
+
/* Section 9.2.10: receive side */
static int gprs_ns_rx_unitdata(struct gprs_nsvc *nsvc, struct msgb *msg)
{
@@ -1764,26 +1797,10 @@ int gprs_ns_nsip_listen(struct gprs_ns_inst *nsi)
nsi->nsip.fd.cb = nsip_fd_cb;
nsi->nsip.fd.data = nsi;
- if (nsi->nsip.remote_ip && nsi->nsip.remote_port) {
- /* connect to ensure only we only accept packets from the
- * configured remote end/peer */
- snprintf(remote_str, sizeof(remote_str), "%s", inet_ntoa(remote));
- ret =
- osmo_sock_init2_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM,
- IPPROTO_UDP, inet_ntoa(in),
- nsi->nsip.local_port, remote_str,
- nsi->nsip.remote_port, OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT);
-
- LOGP(DNS, LOGL_NOTICE,
- "Listening for nsip packets from %s:%u on %s:%u\n",
- remote_str, nsi->nsip.remote_port, inet_ntoa(in), nsi->nsip.local_port);
- } else {
- /* Accept UDP packets from any source IP/Port */
- ret = osmo_sock_init_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM,
- IPPROTO_UDP, inet_ntoa(in), nsi->nsip.local_port, OSMO_SOCK_F_BIND);
+ ret = osmo_sock_init_ofd(&nsi->nsip.fd, AF_INET, SOCK_DGRAM,
+ IPPROTO_UDP, inet_ntoa(in), nsi->nsip.local_port, OSMO_SOCK_F_BIND);
- LOGP(DNS, LOGL_NOTICE, "Listening for nsip packets on %s:%u\n", inet_ntoa(in), nsi->nsip.local_port);
- }
+ LOGP(DNS, LOGL_NOTICE, "Listening for nsip packets on %s:%u\n", inet_ntoa(in), nsi->nsip.local_port);
if (ret < 0)
return ret;
@@ -1824,9 +1841,6 @@ int gprs_nsvc_reset(struct gprs_nsvc *nsvc, uint8_t cause)
LOGP(DNS, LOGL_ERROR, "NSEI=%u, error resetting NS-VC\n",
nsvc->nsei);
}
- /* Start Tns-reset */
- nsvc_start_timer(nsvc, NSVC_TIMER_TNS_RESET);
-
return rc;
}
diff --git a/src/gb/gprs_ns_sns.c b/src/gb/gprs_ns_sns.c
index ddd641f..ebc6d41 100644
--- a/src/gb/gprs_ns_sns.c
+++ b/src/gb/gprs_ns_sns.c
@@ -178,11 +178,13 @@ static void gprs_sns_st_config_sgsn(struct osmo_fsm_inst *fi, uint32_t event, vo
}
LOGPFSML(fi, LOGL_INFO, "Rx SNS-CONFIG: Remote IPv4 list now %u entries\n",
gss->num_ip4_remote);
+ /* send CONFIG-ACK */
+ gprs_ns_tx_sns_config_ack(gss->nsvc_hack, NULL);
+
if (event == GPRS_SNS_EV_CONFIG_END) {
osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_CONFIGURED, 0, 0);
}
- /* send CONFIG-ACK */
- gprs_ns_tx_sns_config_ack(gss->nsvc_hack, NULL);
+
break;
default:
OSMO_ASSERT(0);