aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/Makefile.am3
-rw-r--r--openbsc/src/abis_nm.c13
-rw-r--r--openbsc/src/abis_rsl.c163
-rw-r--r--openbsc/src/bsc_hack.c141
-rw-r--r--openbsc/src/db.c14
-rw-r--r--openbsc/src/e1_input.c10
-rw-r--r--openbsc/src/gsm_04_08.c435
-rw-r--r--openbsc/src/gsm_04_11.c17
-rw-r--r--openbsc/src/gsm_subscriber.c32
-rw-r--r--openbsc/src/mncc.c11
-rw-r--r--openbsc/src/msgb.c8
-rw-r--r--openbsc/src/paging.c8
-rw-r--r--openbsc/src/select.c9
-rw-r--r--openbsc/src/signal.c8
-rw-r--r--openbsc/src/subchan_demux.c9
-rw-r--r--openbsc/src/transaction.c144
-rw-r--r--openbsc/src/trau_mux.c17
-rw-r--r--openbsc/src/vty_interface.c4
18 files changed, 645 insertions, 401 deletions
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index 18555aa86..df34eb5eb 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -11,7 +11,8 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_04_08.c gsm_data.c mncc.c \
gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c db.c \
gsm_04_11.c telnet_interface.c subchan_demux.c \
trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
- input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c
+ input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
+ transaction.c
libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index f2383e2fa..dec4b2957 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -1643,7 +1643,7 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
msgb_tv_put(msg, NM_ATT_HSN, 0x00);
msgb_tv_put(msg, NM_ATT_MAIO, 0x00);
}
- msgb_tv_put(msg, NM_ATT_TSC, 0x07); /* training sequence */
+ msgb_tv_put(msg, NM_ATT_TSC, bts->tsc); /* training sequence */
if (bts->type == GSM_BTS_TYPE_BS11)
msgb_tlv_put(msg, 0x59, 1, &zero);
@@ -2056,10 +2056,6 @@ static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw)
FILE *swl;
int rc = 0;
- if (!tall_fle_ctx)
- tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "bs11_file_list_entry");
-
swl = fopen(bs11_sw->swl_fname, "r");
if (!swl)
return -ENODEV;
@@ -2373,3 +2369,10 @@ int abis_nm_ipaccess_restart(struct gsm_bts *bts)
{
return __simple_cmd(bts, NM_MT_IPACC_RESTART);
}
+
+
+static __attribute__((constructor)) void on_dso_load_abis_nm(void)
+{
+ tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "bs11_file_list_entry");
+}
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index df95e7979..56c3f711b 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -314,18 +314,55 @@ static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
memset(out+len, 0x2b, MACBLOCK_SIZE-len);
}
-static void print_rsl_cause(u_int8_t *cause_tlv)
+static const char *rsl_err_vals[0xff] = {
+ [RSL_ERR_RADIO_IF_FAIL] = "Radio Interface Failure",
+ [RSL_ERR_RADIO_LINK_FAIL] = "Radio Link Failure",
+ [RSL_ERR_HANDOVER_ACC_FAIL] = "Handover Access Failure",
+ [RSL_ERR_TALKER_ACC_FAIL] = "Talker Access Failure",
+ [RSL_ERR_OM_INTERVENTION] = "O&M Intervention",
+ [RSL_ERR_NORMAL_UNSPEC] = "Normal event, unspecified",
+ [RSL_ERR_EQUIPMENT_FAIL] = "Equipment Failure",
+ [RSL_ERR_RR_UNAVAIL] = "Radio Resource not available",
+ [RSL_ERR_TERR_CH_FAIL] = "Terrestrial Channel Failure",
+ [RSL_ERR_CCCH_OVERLOAD] = "CCCH Overload",
+ [RSL_ERR_ACCH_OVERLOAD] = "ACCH Overload",
+ [RSL_ERR_PROCESSOR_OVERLOAD] = "Processor Overload",
+ [RSL_ERR_RES_UNAVAIL] = "Resource not available, unspecified",
+ [RSL_ERR_TRANSC_UNAVAIL] = "Transcoding not available",
+ [RSL_ERR_SERV_OPT_UNAVAIL] = "Service or Option not available",
+ [RSL_ERR_ENCR_UNIMPL] = "Encryption algorithm not implemented",
+ [RSL_ERR_SERV_OPT_UNIMPL] = "Service or Option not implemented",
+ [RSL_ERR_RCH_ALR_ACTV_ALLOC] = "Radio channel already activated",
+ [RSL_ERR_INVALID_MESSAGE] = "Invalid Message, unspecified",
+ [RSL_ERR_MSG_DISCR] = "Message Discriminator Error",
+ [RSL_ERR_MSG_TYPE] = "Message Type Error",
+ [RSL_ERR_MSG_SEQ] = "Message Sequence Error",
+ [RSL_ERR_IE_ERROR] = "General IE error",
+ [RSL_ERR_MAND_IE_ERROR] = "Mandatory IE error",
+ [RSL_ERR_OPT_IE_ERROR] = "Optional IE error",
+ [RSL_ERR_IE_NONEXIST] = "IE non-existent",
+ [RSL_ERR_IE_LENGTH] = "IE length error",
+ [RSL_ERR_IE_CONTENT] = "IE content error",
+ [RSL_ERR_PROTO] = "Protocol error, unspecified",
+ [RSL_ERR_INTERWORKING] = "Interworking error, unspecified",
+};
+
+static const char *rsl_err_name(u_int8_t err)
{
- u_int8_t cause_len;
- int i;
+ if (rsl_err_vals[err])
+ return rsl_err_vals[err];
+ else
+ return "unknown";
+}
- if (cause_tlv[0] != RSL_IE_CAUSE)
- return;
+static void print_rsl_cause(const u_int8_t *cause_v, u_int8_t cause_len)
+{
+ int i;
- cause_len = cause_tlv[1];
- DEBUGPC(DRSL, "CAUSE: ");
- for (i = 0; i < cause_len; i++)
- DEBUGPC(DRSL, "%02x ", cause_tlv[2+i]);
+ DEBUGPC(DRSL, "CAUSE=0x%02x(%s) ",
+ cause_v[0], rsl_err_name(cause_v[0]));
+ for (i = 1; i < cause_len-1; i++)
+ DEBUGPC(DRSL, "%02x ", cause_v[i]);
}
/* Send a BCCH_INFO message as per Chapter 8.5.1 */
@@ -652,6 +689,25 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
return abis_rsl_sendmsg(msg);
}
+/* Chapter 8.4.5 */
+int rsl_deact_sacch(struct gsm_lchan *lchan)
+{
+ struct abis_rsl_dchan_hdr *dh;
+ struct msgb *msg = rsl_msgb_alloc();
+
+ dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
+ init_dchan_hdr(dh, RSL_MT_DEACTIVATE_SACCH);
+ dh->chan_nr = lchan2chan_nr(lchan);
+
+ msg->lchan = lchan;
+ msg->trx = lchan->ts->trx;
+
+ DEBUGP(DRSL, "DEACTivate SACCH CMD channel=%s chan_nr=0x%02x\n",
+ gsm_ts_name(lchan->ts), dh->chan_nr);
+
+ return abis_rsl_sendmsg(msg);
+}
+
/* Chapter 9.1.7 of 04.08 */
int rsl_chan_release(struct gsm_lchan *lchan)
{
@@ -798,8 +854,9 @@ static int rsl_rx_chan_act_nack(struct msgb *msg)
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
- DEBUGPC(DRSL, "CAUSE=0x%02x ", *TLVP_VAL(&tp, RSL_IE_CAUSE));
-
+ print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ TLVP_LEN(&tp, RSL_IE_CAUSE));
+
return 0;
}
@@ -810,10 +867,13 @@ static int rsl_rx_conn_fail(struct msgb *msg)
struct tlv_parsed tp;
DEBUGPC(DRSL, "CONNECTION FAIL: ");
- print_rsl_cause(dh->data);
rsl_tlv_parse(&tp, dh->data, msgb_l2len(msg)-sizeof(*dh));
+ if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
+ print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ TLVP_LEN(&tp, RSL_IE_CAUSE));
+
if (msg->trx->bts->type == GSM_BTS_TYPE_BS11) {
/* FIXME: we have no idea what cause 0x18 is !!! */
if (TLVP_PRESENT(&tp, RSL_IE_CAUSE) &&
@@ -935,9 +995,16 @@ static int abis_rsl_rx_dchan(struct msgb *msg)
static int rsl_rx_error_rep(struct msgb *msg)
{
struct abis_rsl_common_hdr *rslh = msgb_l2(msg);
+ struct tlv_parsed tp;
DEBUGP(DRSL, "ERROR REPORT ");
- print_rsl_cause(rslh->data);
+
+ rsl_tlv_parse(&tp, rslh->data, msgb_l2len(msg)-sizeof(*rslh));
+
+ if (TLVP_PRESENT(&tp, RSL_IE_CAUSE))
+ print_rsl_cause(TLVP_VAL(&tp, RSL_IE_CAUSE),
+ TLVP_LEN(&tp, RSL_IE_CAUSE));
+
DEBUGPC(DRSL, "\n");
return 0;
@@ -1025,7 +1092,7 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
ia.chan_desc.h0.h = 0;
ia.chan_desc.h0.arfcn_high = arfcn >> 8;
ia.chan_desc.h0.arfcn_low = arfcn & 0xff;
- ia.chan_desc.h0.tsc = 7;
+ ia.chan_desc.h0.tsc = bts->tsc;
/* use request reference extracted from CHAN_RQD */
memcpy(&ia.req_ref, rqd_ref, sizeof(ia.req_ref));
ia.timing_advance = rqd_ta;
@@ -1175,17 +1242,45 @@ static int abis_rsl_rx_rll(struct msgb *msg)
return rc;
}
+static u_int8_t ipa_smod_s_for_tch_mode(u_int8_t tch_mode)
+{
+#if 0
+ switch (tch_mode) {
+ case GSM48_CMODE_SPEECH_V1:
+ return 0x00;
+ case GSM48_CMODE_SPEECH_EFR:
+ return 0x01;
+ case GSM48_CMODE_SPEECH_AMR:
+ return 0x02;
+ /* FIXME: Type1 half-rate and type3 half-rate */
+ }
+ return 0;
+#else
+ /* hard-code EFR for now, since tch_mode is not correct at this
+ * point in time */
+ return 0x01;
+#endif
+}
+
/* ip.access specific RSL extensions */
int rsl_ipacc_bind(struct gsm_lchan *lchan)
{
struct msgb *msg = rsl_msgb_alloc();
struct abis_rsl_dchan_hdr *dh;
+ u_int8_t speech_mode_s;
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_IPAC_BIND);
dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
dh->chan_nr = lchan2chan_nr(lchan);
+ speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
+ /* 0x1- == receive-only, 0x-1 == EFR codec */
+ msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x10 | speech_mode_s);
+
+ DEBUGPC(DRSL, "channel=%s chan_nr=0x%02x IPAC_BIND\n",
+ gsm_ts_name(lchan->ts), dh->chan_nr);
+
msg->trx = lchan->ts->trx;
return abis_rsl_sendmsg(msg);
@@ -1197,12 +1292,20 @@ int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
struct msgb *msg = rsl_msgb_alloc();
struct abis_rsl_dchan_hdr *dh;
u_int8_t *att_f8, *att_ip, *att_port;
+ u_int8_t speech_mode_s;
+ struct in_addr ia;
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, RSL_MT_IPAC_CONNECT);
dh->c.msg_discr = ABIS_RSL_MDISC_IPACCESS;
dh->chan_nr = lchan2chan_nr(lchan);
+ ia.s_addr = htonl(ip);
+ DEBUGP(DRSL, "IPAC_CONNECT channel=%s chan_nr=0x%02x "
+ "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d\n",
+ gsm_ts_name(lchan->ts), dh->chan_nr,
+ inet_ntoa(ia), port, rtp_payload2, conn_id);
+
att_f8 = msgb_put(msg, sizeof(conn_id)+1);
att_f8[0] = RSL_IE_IPAC_CONN_ID;
att_f8[1] = conn_id >> 8;
@@ -1221,8 +1324,12 @@ int rsl_ipacc_connect(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port,
att_port[1] = port >> 8;
att_port[2] = port & 0xff;
- msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 1); /* F4 01 */
- msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2); /* FC 7F */
+ speech_mode_s = ipa_smod_s_for_tch_mode(lchan->tch_mode);
+ /* 0x0- == both directions, 0x-1 == EFR codec */
+ msgb_tv_put(msg, RSL_IE_IPAC_SPEECH_MODE, 0x00 | speech_mode_s);
+ if (rtp_payload2)
+ msgb_tv_put(msg, RSL_IE_IPAC_RTP_PAYLOAD2, rtp_payload2);
+
msg->trx = lchan->ts->trx;
return abis_rsl_sendmsg(msg);
@@ -1243,7 +1350,6 @@ static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
if (!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_PORT) ||
!TLVP_PRESENT(&tv, RSL_IE_IPAC_LOCAL_IP) ||
- !TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2) ||
!TLVP_PRESENT(&tv, RSL_IE_IPAC_CONN_ID)) {
DEBUGPC(DRSL, "mandatory IE missing");
return -EINVAL;
@@ -1252,15 +1358,20 @@ static int abis_rsl_rx_ipacc_bindack(struct msgb *msg)
port = *((u_int16_t *) TLVP_VAL(&tv, RSL_IE_IPAC_LOCAL_PORT));
attr_f8 = *((u_int16_t *) TLVP_VAL(&tv, 0xf8));
- DEBUGPC(DRSL, "IP=%s PORT=%d RTP_PAYLOAD2=%d CONN_ID=%d",
- inet_ntoa(ip), ntohs(port), *TLVP_VAL(&tv, 0xfc),
- ntohs(attr_f8));
+ DEBUGPC(DRSL, "IP=%s PORT=%d CONN_ID=%d ",
+ inet_ntoa(ip), ntohs(port), ntohs(attr_f8));
+
+ if (TLVP_PRESENT(&tv, RSL_IE_IPAC_RTP_PAYLOAD2)) {
+ ts->abis_ip.rtp_payload2 =
+ *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
+ DEBUGPC(DRSL, "RTP_PAYLOAD2=0x%02x ",
+ ts->abis_ip.rtp_payload2);
+ }
/* update our local information about this TS */
ts->abis_ip.bound_ip = ntohl(ip.s_addr);
ts->abis_ip.bound_port = ntohs(port);
ts->abis_ip.conn_id = ntohs(attr_f8);
- ts->abis_ip.rtp_payload2 = *TLVP_VAL(&tv, RSL_IE_IPAC_RTP_PAYLOAD2);
dispatch_signal(SS_ABISIP, S_ABISIP_BIND_ACK, msg->lchan);
@@ -1273,12 +1384,12 @@ static int abis_rsl_rx_ipacc_disc_ind(struct msgb *msg)
struct tlv_parsed tv;
rsl_tlv_parse(&tv, dh->data, msgb_l2len(msg)-sizeof(*dh));
- if (!TLVP_PRESENT(&tv, RSL_IE_CAUSE)) {
- DEBUGPC(DRSL, "mandatory IE missing! ");
- return -EINVAL;
- }
- DEBUGPC(DRSL, "cause=0x%02x ", *TLVP_VAL(&tv, RSL_IE_CAUSE));
+ if (TLVP_PRESENT(&tv, RSL_IE_CAUSE))
+ print_rsl_cause(TLVP_VAL(&tv, RSL_IE_CAUSE),
+ TLVP_LEN(&tv, RSL_IE_CAUSE));
+
+ dispatch_signal(SS_ABISIP, S_ABISIP_DISC_IND, msg->lchan);
return 0;
}
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index 688ee9fbc..1bfb7068b 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -56,6 +56,8 @@ static struct gsm_network *gsmnet;
static int MCC = 1;
static int MNC = 1;
static int LAC = 1;
+static int TSC = HARDCODED_TSC;
+static int BSIC = HARDCODED_BSIC;
static int ARFCN = HARDCODED_ARFCN;
static int cardnr = 0;
static int release_l2 = 0;
@@ -63,6 +65,15 @@ static enum gsm_bts_type BTS_TYPE = GSM_BTS_TYPE_BS11;
static enum gsm_band BAND = GSM_BAND_900;
static const char *database_name = "hlr.sqlite3";
+struct nano_bts_id {
+ struct llist_head entry;
+ int site_id;
+ int bts_id;
+};
+
+static LLIST_HEAD(nanobts_ids);
+
+
/* The following definitions are for OM and NM packets that we cannot yet
* generate by code but we just pass on */
@@ -219,26 +230,27 @@ SET ATTRIBUTES
unsigned char msg_3[] =
{
NM_MT_BS11_SET_ATTR, NM_OC_BS11_HANDOVER, 0x00, 0xFF, 0xFF,
- 0xD0, 0x00,
- 0x64, 0x00,
- 0x67, 0x00,
- 0x68, 0x00,
- 0x6A, 0x00,
- 0x6C, 0x00,
- 0x6D, 0x00,
- 0x6F, 0x08,
- 0x70, 0x08, 0x01,
+ 0xD0, 0x00, /* enableDelayPowerBudgetHO */
+ 0x64, 0x00, /* enableDistanceHO */
+ 0x67, 0x00, /* enableInternalInterCellHandover */
+ 0x68, 0x00, /* enableInternalInterCellHandover */
+ 0x6A, 0x00, /* enablePowerBudgetHO */
+ 0x6C, 0x00, /* enableRXLEVHO */
+ 0x6D, 0x00, /* enableRXQUALHO */
+ 0x6F, 0x08, /* hoAveragingDistance */
+ 0x70, 0x08, 0x01, /* hoAveragingLev */
0x71, 0x10, 0x10, 0x10,
- 0x72, 0x08, 0x02,
- 0x73, 0x0A,
- 0x74, 0x05,
- 0x75, 0x06,
- 0x76, 0x06,
- 0x78, 0x14,
- 0x79, 0x14,
- 0x7A, 0x14,
- 0x7D, 0x06,
- 0x92, 0x03, 0x20, 0x01, 0x00,
+ 0x72, 0x08, 0x02, /* hoAveragingQual */
+ 0x73, 0x0A, /* hoLowerThresholdLevDL */
+ 0x74, 0x05, /* hoLowerThresholdLevUL */
+ 0x75, 0x06, /* hoLowerThresholdQualDL */
+ 0x76, 0x06, /* hoLowerThresholdQualUL */
+ 0x78, 0x14, /* hoThresholdLevDLintra */
+ 0x79, 0x14, /* hoThresholdLevULintra */
+ 0x7A, 0x14, /* hoThresholdMsRangeMax */
+ 0x7D, 0x06, /* nCell */
+ NM_ATT_BS11_TIMER_HO_REQUEST, 0x03,
+ 0x20, 0x01, 0x00,
0x45, 0x01, 0x00,
0x48, 0x01, 0x00,
0x5A, 0x01, 0x00,
@@ -291,22 +303,22 @@ unsigned char msg_4[] =
NM_MT_BS11_SET_ATTR, NM_OC_BS11_PWR_CTRL, 0x00, 0xFF, 0xFF,
NM_ATT_BS11_ENA_MS_PWR_CTRL, 0x00,
NM_ATT_BS11_ENA_PWR_CTRL_RLFW, 0x00,
- 0x7E, 0x04, 0x01,
- 0x7F, 0x04, 0x02,
- 0x80, 0x0F,
- 0x81, 0x0A,
- 0x82, 0x05,
- 0x83, 0x05,
- 0x84, 0x0C,
- 0x85, 0x14,
- 0x86, 0x0F,
- 0x87, 0x04,
- 0x88, 0x04,
- 0x89, 0x02,
- 0x8A, 0x02,
- 0x8B, 0x02,
- 0x8C, 0x01,
- 0x8D, 0x40,
+ 0x7E, 0x04, 0x01, /* pcAveragingLev */
+ 0x7F, 0x04, 0x02, /* pcAveragingQual */
+ 0x80, 0x0F, /* pcLowerThresholdLevDL */
+ 0x81, 0x0A, /* pcLowerThresholdLevUL */
+ 0x82, 0x05, /* pcLowerThresholdQualDL */
+ 0x83, 0x05, /* pcLowerThresholdQualUL */
+ 0x84, 0x0C, /* pcRLFThreshold */
+ 0x85, 0x14, /* pcUpperThresholdLevDL */
+ 0x86, 0x0F, /* pcUpperThresholdLevUL */
+ 0x87, 0x04, /* pcUpperThresholdQualDL */
+ 0x88, 0x04, /* pcUpperThresholdQualUL */
+ 0x89, 0x02, /* powerConfirm */
+ 0x8A, 0x02, /* powerConfirmInterval */
+ 0x8B, 0x02, /* powerIncrStepSize */
+ 0x8C, 0x01, /* powerRedStepSize */
+ 0x8D, 0x40, /* radioLinkTimeoutBs */
0x65, 0x01, 0x00 // set to 0x01 to enable BSPowerControl
};
@@ -883,13 +895,18 @@ static void patch_tables(struct gsm_bts *bts)
/* patch BSIC */
bs11_attr_bts[1] = bts->bsic;
nanobts_attr_bts[sizeof(nanobts_attr_bts)-1] = bts->bsic;
+
+ /* patch TSC */
+ si4[15] &= ~0xe0;
+ si4[15] |= (bts->tsc & 7) << 5;
}
static void bootstrap_rsl(struct gsm_bts_trx *trx)
{
fprintf(stdout, "bootstrapping RSL for BTS/TRX (%u/%u) "
- "using MCC=%u MNC=%u\n", trx->nr, trx->bts->nr, MCC, MNC);
+ "using MCC=%u MNC=%u BSIC=%u TSC=%u\n",
+ trx->nr, trx->bts->nr, MCC, MNC, BSIC, TSC);
set_system_infos(trx);
}
@@ -963,8 +980,6 @@ static int bootstrap_bts(struct gsm_bts *bts)
static int bootstrap_network(void)
{
- struct gsm_bts *bts;
-
switch(BTS_TYPE) {
case GSM_BTS_TYPE_NANOBTS_1800:
if (ARFCN < 512 || ARFCN > 885) {
@@ -993,9 +1008,6 @@ static int bootstrap_network(void)
gsmnet->name_long = "OpenBSC";
gsmnet->name_short = "OpenBSC";
- bts = gsm_bts_alloc(gsmnet, BTS_TYPE, HARDCODED_TSC, HARDCODED_BSIC);
- bootstrap_bts(bts);
-
if (db_init(database_name)) {
printf("DB: Failed to init database. Please check the option settings.\n");
return -1;
@@ -1014,17 +1026,27 @@ static int bootstrap_network(void)
/* E1 mISDN input setup */
if (BTS_TYPE == GSM_BTS_TYPE_BS11) {
+ struct gsm_bts *bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
+ bootstrap_bts(bts);
+
gsmnet->num_bts = 1;
return e1_config(bts, cardnr, release_l2);
} else {
- /* FIXME: do this dynamic */
- bts->ip_access.site_id = 1801;
- bts->ip_access.bts_id = 0;
+ struct nano_bts_id *bts_id;
+ struct gsm_bts *bts;
+
+ if (llist_empty(&nanobts_ids)) {
+ fprintf(stderr, "You need to specify -i DEVICE_1 -i DEVICE_2 for nanoBTS.\n");
+ return -EINVAL;
+ }
+
+ llist_for_each_entry(bts_id, &nanobts_ids, entry) {
+ bts = gsm_bts_alloc(gsmnet, BTS_TYPE, TSC, BSIC);
+ bootstrap_bts(bts);
+ bts->ip_access.site_id = bts_id->site_id;
+ bts->ip_access.bts_id = 0;
+ }
- bts = gsm_bts_alloc(gsmnet, BTS_TYPE, HARDCODED_TSC, HARDCODED_BSIC);
- bootstrap_bts(bts);
- bts->ip_access.site_id = 1800;
- bts->ip_access.bts_id = 0;
return ipaccess_setup(gsmnet);
}
}
@@ -1061,6 +1083,7 @@ static void print_help()
printf(" -r --reject-cause number The reject cause for LOCATION UPDATING REJECT.\n");
printf(" -p --pcap file The filename of the pcap file\n");
printf(" -t --bts-type type The BTS type (bs11, nanobts900, nanobts1800)\n");
+ printf(" -i --bts-id=NUMBER The known nanoBTS device numbers. Can be specified multiple times.\n");
printf(" -C --cardnr number For bs11 select E1 card number other than 0\n");
printf(" -R --release-l2 Releases mISDN layer 2 after exit, to unload driver.\n");
printf(" -h --help this text\n");
@@ -1087,10 +1110,13 @@ static void handle_options(int argc, char** argv)
{"release-l2", 0, 0, 'R'},
{"timestamp", 0, 0, 'T'},
{"band", 0, 0, 'b'},
+ {"bts-id", 1, 0, 'i'},
+ {"tsc", 1, 0, 'S'},
+ {"bsic", 1, 0, 'B'},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:",
+ c = getopt_long(argc, argv, "hc:n:d:sar:p:f:t:C:RL:l:Tb:i:S:B:",
long_options, &option_index);
if (c == -1)
break;
@@ -1145,6 +1171,23 @@ static void handle_options(int argc, char** argv)
case 'b':
BAND = gsm_band_parse(atoi(optarg));
break;
+ case 'i': {
+ struct nano_bts_id *bts_id = talloc_zero(tall_bsc_ctx, struct nano_bts_id);
+ if (!bts_id) {
+ fprintf(stderr, "Failed to allocate bts id\n");
+ exit(-1);
+ }
+
+ bts_id->site_id = atoi(optarg);
+ llist_add(&bts_id->entry, &nanobts_ids);
+ break;
+ case 'S':
+ TSC = atoi(optarg);
+ break;
+ case 'B':
+ BSIC = atoi(optarg);
+ break;
+ }
default:
/* ignore */
break;
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index 543f44ce2..fc2950a36 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -158,12 +158,13 @@ int db_fini() {
return 0;
}
-struct gsm_subscriber* db_create_subscriber(char *imsi) {
+struct gsm_subscriber* db_create_subscriber(struct gsm_network *net, char *imsi)
+{
dbi_result result;
struct gsm_subscriber* subscr;
/* Is this subscriber known in the db? */
- subscr = db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
+ subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi);
if (subscr) {
result = dbi_conn_queryf(conn,
"UPDATE Subscriber set updated = datetime('now') "
@@ -189,6 +190,7 @@ struct gsm_subscriber* db_create_subscriber(char *imsi) {
if (result==NULL) {
printf("DB: Failed to create Subscriber by IMSI.\n");
}
+ subscr->net = net;
subscr->id = dbi_conn_sequence_last(conn, NULL);
strncpy(subscr->imsi, imsi, GSM_IMSI_LENGTH-1);
dbi_result_free(result);
@@ -196,7 +198,10 @@ struct gsm_subscriber* db_create_subscriber(char *imsi) {
return subscr;
}
-struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, const char *id) {
+struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
+ enum gsm_subscriber_field field,
+ const char *id)
+{
dbi_result result;
const char *string;
char *quoted;
@@ -246,6 +251,7 @@ struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, const
}
subscr = subscr_alloc();
+ subscr->net = net;
subscr->id = dbi_result_get_ulonglong(result, "id");
string = dbi_result_get_string(result, "imsi");
if (string)
@@ -459,7 +465,7 @@ int db_sms_store(struct gsm_sms *sms)
}
/* retrieve the next unsent SMS with ID >= min_id */
-struct gsm_sms *db_sms_get_unsent(int min_id)
+struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id)
{
dbi_result result;
struct gsm_sms *sms = malloc(sizeof(*sms));
diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c
index 2d0c1340f..7531755c2 100644
--- a/openbsc/src/e1_input.c
+++ b/openbsc/src/e1_input.c
@@ -370,10 +370,6 @@ e1inp_sign_link_create(struct e1inp_ts *ts, enum e1inp_sign_type type,
if (ts->type != E1INP_TS_TYPE_SIGN)
return NULL;
- if (!tall_sigl_ctx)
- tall_sigl_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "e1inp_sign_link");
-
link = talloc_zero(tall_sigl_ctx, struct e1inp_sign_link);
if (!link)
return NULL;
@@ -505,3 +501,9 @@ int e1inp_line_register(struct e1inp_line *line)
return 0;
}
+
+static __attribute__((constructor)) void on_dso_load_e1_inp(void)
+{
+ tall_sigl_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "e1inp_sign_link");
+}
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 9e0427e05..a9f2ebd8e 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -45,6 +45,7 @@
#include <openbsc/trau_frame.h>
#include <openbsc/trau_mux.h>
#include <openbsc/talloc.h>
+#include <openbsc/transaction.h>
#define GSM48_ALLOC_SIZE 1024
#define GSM48_ALLOC_HEADROOM 128
@@ -54,7 +55,6 @@
#define GSM_MAX_USERUSER 128
static void *tall_locop_ctx;
-static void *tall_trans_ctx;
static const struct tlv_definition rsl_att_tlvdef = {
.def = {
@@ -292,7 +292,6 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi);
static int gsm48_tx_simple(struct gsm_lchan *lchan,
u_int8_t pdisc, u_int8_t msg_type);
static void schedule_reject(struct gsm_lchan *lchan);
-void free_trans(struct gsm_trans *trans);
struct gsm_lai {
u_int16_t mcc;
@@ -351,9 +350,6 @@ static void allocate_loc_updating_req(struct gsm_lchan *lchan)
use_lchan(lchan);
release_loc_updating_req(lchan);
- if (!tall_locop_ctx)
- tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "loc_updating_oper");
lchan->loc_operation = talloc_zero(tall_locop_ctx,
struct gsm_loc_updating_operation);
}
@@ -392,9 +388,12 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
release_loc_updating_req(lchan);
/* Free all transactions that are associated with the released lchan */
+ /* FIXME: this is not neccessarily the right thing to do, we should
+ * only set trans->lchan to NULL and wait for another lchan to be
+ * established to the same MM entity (phone/subscriber) */
llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) {
if (trans->lchan == lchan)
- free_trans(trans);
+ trans_free(trans);
}
return 0;
@@ -406,6 +405,8 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal,
*/
static __attribute__((constructor)) void on_dso_load_0408(void)
{
+ tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "loc_updating_oper");
register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
}
@@ -981,10 +982,18 @@ struct msgb *gsm48_msgb_alloc(void)
"GSM 04.08");
}
-int gsm48_sendmsg(struct msgb *msg)
+int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans)
{
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
+
+ /* if we get passed a transaction reference, do some common
+ * work that the caller no longer has to do */
+ if (trans) {
+ gh->proto_discr = trans->protocol | (trans->transaction_id << 4);
+ msg->lchan = trans->lchan;
+ }
+
if (msg->lchan) {
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msg->data;
msg->trx = msg->lchan->ts->trx;
if ((gh->proto_discr & GSM48_PDISC_MASK) == GSM48_PDISC_CC)
@@ -1020,7 +1029,7 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
DEBUGP(DMM, "-> LOCATION UPDATING REJECT on channel: %d\n", lchan->nr);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
/* Chapter 9.2.13 : Send LOCATION UPDATE ACCEPT */
@@ -1048,7 +1057,7 @@ int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi)
DEBUGP(DMM, "-> LOCATION UPDATE ACCEPT\n");
- ret = gsm48_sendmsg(msg);
+ ret = gsm48_sendmsg(msg, NULL);
ret = gsm48_tx_mm_info(lchan);
@@ -1119,7 +1128,7 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type)
gh->msg_type = GSM48_MT_MM_ID_REQ;
gh->data[0] = id_type;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
#define MI_SIZE 32
@@ -1129,6 +1138,8 @@ static int mm_rx_id_resp(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm_lchan *lchan = msg->lchan;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_network *net = bts->network;
u_int8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
char mi_string[MI_SIZE];
@@ -1139,7 +1150,7 @@ static int mm_rx_id_resp(struct msgb *msg)
switch (mi_type) {
case GSM_MI_TYPE_IMSI:
if (!lchan->subscr)
- lchan->subscr = db_create_subscriber(mi_string);
+ lchan->subscr = db_create_subscriber(net, mi_string);
if (lchan->loc_operation)
lchan->loc_operation->waiting_for_imsi = 0;
break;
@@ -1196,6 +1207,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
struct gsm48_loc_upd_req *lu;
struct gsm_subscriber *subscr = NULL;
struct gsm_lchan *lchan = msg->lchan;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
u_int8_t mi_type;
char mi_string[MI_SIZE];
int rc;
@@ -1230,7 +1242,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
lchan->loc_operation->waiting_for_imei = 1;
/* look up subscriber based on IMSI */
- subscr = db_create_subscriber(mi_string);
+ subscr = db_create_subscriber(bts->network, mi_string);
break;
case GSM_MI_TYPE_TMSI:
DEBUGPC(DMM, "\n");
@@ -1239,7 +1251,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg)
lchan->loc_operation->waiting_for_imei = 1;
/* look up the subscriber based on TMSI, request IMSI if it fails */
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
if (!subscr) {
/* send IDENTITY REQUEST message to get IMSI */
rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI);
@@ -1297,7 +1309,7 @@ int gsm48_tx_chan_mode_modify(struct gsm_lchan *lchan, u_int8_t mode)
cmm->chan_desc.h0.arfcn_low = arfcn & 0xff;
cmm->mode = mode;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
#if 0
@@ -1349,7 +1361,7 @@ int gsm48_tx_mm_info(struct gsm_lchan *lchan)
name_len = strlen(net->name_short);
/* 10.5.3.5a */
ptr8 = (u_int8_t *) msgb_put(msg, 3);
- ptr8[0] = GSM48_IE_NAME_LONG;
+ ptr8[0] = GSM48_IE_NAME_SHORT;
ptr8[1] = name_len*2 + 1;
ptr8[2] = 0x90; /* UCS2, no spare bits, no CI */
@@ -1377,7 +1389,7 @@ int gsm48_tx_mm_info(struct gsm_lchan *lchan)
ptr8[7] |= 0x80;
#endif
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan)
@@ -1403,7 +1415,7 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan,
gh->data[0] = value;
DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
@@ -1421,6 +1433,7 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
u_int8_t mi_type;
char mi_string[MI_SIZE];
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm_subscriber *subscr;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_service_request *req =
@@ -1455,7 +1468,7 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
DEBUGPC(DMM, "serv_type=0x%02x mi_type=0x%02x M(%s)\n",
req->cm_service_type, mi_type, mi_string);
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
/* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */
if (!subscr)
@@ -1478,6 +1491,7 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg)
static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_imsi_detach_ind *idi =
(struct gsm48_imsi_detach_ind *) gh->data;
@@ -1491,10 +1505,10 @@ static int gsm48_rx_mm_imsi_detach_ind(struct msgb *msg)
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMSI:
- subscr = subscr_get_by_imsi(mi_string);
+ subscr = subscr_get_by_imsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMEI:
case GSM_MI_TYPE_IMEISV:
@@ -1574,6 +1588,7 @@ static int gsm0408_rcv_mm(struct msgb *msg)
/* Receive a PAGING RESPONSE message from the MS */
static int gsm48_rr_rx_pag_resp(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t *classmark2_lv = gh->data + 1;
u_int8_t *mi_lv = gh->data + 2 + *classmark2_lv;
@@ -1588,10 +1603,10 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg)
mi_type, mi_string);
switch (mi_type) {
case GSM_MI_TYPE_TMSI:
- subscr = subscr_get_by_tmsi(mi_string);
+ subscr = subscr_get_by_tmsi(bts->network, mi_string);
break;
case GSM_MI_TYPE_IMSI:
- subscr = subscr_get_by_imsi(mi_string);
+ subscr = subscr_get_by_imsi(bts->network, mi_string);
break;
}
@@ -1769,7 +1784,11 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan)
DEBUGP(DRR, "Sending Channel Release: Chan: Number: %d Type: %d\n",
lchan->nr, lchan->type);
- return gsm48_sendmsg(msg);
+ /* Send actual release request to MS */
+ gsm48_sendmsg(msg, NULL);
+
+ /* Deactivate the SACCH on the BTS side */
+ return rsl_deact_sacch(lchan);
}
/* Call Control */
@@ -1785,9 +1804,9 @@ static void new_cc_state(struct gsm_trans *trans, int state)
return;
DEBUGP(DCC, "new state %s -> %s\n",
- cc_state_names[trans->state], cc_state_names[state]);
+ cc_state_names[trans->cc.state], cc_state_names[state]);
- trans->state = state;
+ trans->cc.state = state;
}
static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
@@ -1796,8 +1815,6 @@ static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
u_int8_t *cause, *call_state;
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_STATUS;
cause = msgb_put(msg, 3);
@@ -1808,7 +1825,7 @@ static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
call_state = msgb_put(msg, 1);
call_state[0] = 0xc0 | 0x00;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_tx_simple(struct gsm_lchan *lchan,
@@ -1822,15 +1839,15 @@ static int gsm48_tx_simple(struct gsm_lchan *lchan,
gh->proto_discr = pdisc;
gh->msg_type = msg_type;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, NULL);
}
static void gsm48_stop_cc_timer(struct gsm_trans *trans)
{
- if (bsc_timer_pending(&trans->cc_timer)) {
- DEBUGP(DCC, "stopping pending timer T%x\n", trans->Tcurrent);
- bsc_del_timer(&trans->cc_timer);
- trans->Tcurrent = 0;
+ if (bsc_timer_pending(&trans->cc.timer)) {
+ DEBUGP(DCC, "stopping pending timer T%x\n", trans->cc.Tcurrent);
+ bsc_del_timer(&trans->cc.timer);
+ trans->cc.Tcurrent = 0;
}
}
@@ -1841,7 +1858,7 @@ static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans,
if (trans)
if (trans->lchan)
- DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
+ DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
"Sending '%s' to MNCC.\n",
trans->lchan->ts->trx->bts->nr,
trans->lchan->ts->trx->nr,
@@ -1879,49 +1896,23 @@ int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
return mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
}
-void free_trans(struct gsm_trans *trans)
+/* Call Control Specific transaction release.
+ * gets called by trans_free, DO NOT CALL YOURSELF! */
+void _gsm48_cc_trans_free(struct gsm_trans *trans)
{
- struct gsm_bts *bts;
-
gsm48_stop_cc_timer(trans);
/* send release to L4, if callref still exists */
if (trans->callref) {
/* Ressource unavailable */
- mncc_release_ind(trans->network, trans, trans->callref,
+ mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
- if (trans->state != GSM_CSTATE_NULL)
- new_cc_state(trans, GSM_CSTATE_NULL);
- }
-
- if (!trans->lchan && trans->subscr && trans->subscr->net) {
- /* Stop paging on all bts' */
- bts = NULL;
- do {
- bts = gsm_bts_by_lac(trans->subscr->net,
- trans->subscr->lac, bts);
- if (!bts)
- break;
- /* Stop paging */
- paging_request_stop(bts, trans->subscr, NULL);
- } while (1);
- }
-
- if (trans->lchan) {
- trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
- put_lchan(trans->lchan);
}
-
- if (trans->subscr)
- subscr_put(trans->subscr);
-
- if (trans->state != GSM_CSTATE_NULL)
+ if (trans->cc.state != GSM_CSTATE_NULL)
new_cc_state(trans, GSM_CSTATE_NULL);
-
- llist_del(&trans->entry);
-
- talloc_free(trans);
+ if (trans->lchan)
+ trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref);
}
static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg);
@@ -1962,7 +1953,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
use_lchan(lchan);
}
/* send SETUP request to called party */
- gsm48_cc_tx_setup(transt, &transt->cc_msg);
+ gsm48_cc_tx_setup(transt, &transt->cc.msg);
if (is_ipaccess_bts(lchan->ts->trx->bts))
rsl_ipacc_bind(lchan);
break;
@@ -1970,11 +1961,12 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event,
DEBUGP(DCC, "Paging subscr %s expired!\n",
subscr->extension);
/* Temporarily out of order */
- mncc_release_ind(transt->network, transt, transt->callref,
+ mncc_release_ind(transt->subscr->net, transt,
+ transt->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_DEST_OOO);
transt->callref = 0;
- free_trans(transt);
+ trans_free(transt);
break;
}
}
@@ -2023,21 +2015,11 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan)
return 0;
}
-static struct gsm_trans *get_trans_ref(struct gsm_network *net, u_int32_t callref)
-{
- struct gsm_trans *trans;
- llist_for_each_entry(trans, &net->trans_list, entry) {
- if (trans->callref == callref)
- return trans;
- }
- return NULL;
-}
-
/* bridge channels of two transactions */
static int tch_bridge(struct gsm_network *net, u_int32_t *refs)
{
- struct gsm_trans *trans1 = get_trans_ref(net, refs[0]);
- struct gsm_trans *trans2 = get_trans_ref(net, refs[1]);
+ struct gsm_trans *trans1 = trans_find_by_callref(net, refs[0]);
+ struct gsm_trans *trans2 = trans_find_by_callref(net, refs[1]);
if (!trans1 || !trans2)
return -EIO;
@@ -2055,7 +2037,7 @@ static int tch_recv(struct gsm_network *net, struct gsm_mncc *data, int enable)
struct gsm_trans *trans;
/* Find callref */
- trans = get_trans_ref(net, data->callref);
+ trans = trans_find_by_callref(net, data->callref);
if (!trans)
return -EIO;
if (!trans->lchan)
@@ -2073,7 +2055,7 @@ static int tch_frame(struct gsm_network *net, struct gsm_trau_frame *frame)
struct gsm_trans *trans;
/* Find callref */
- trans = get_trans_ref(net, frame->callref);
+ trans = trans_find_by_callref(net, frame->callref);
if (!trans)
return -EIO;
if (!trans->lchan)
@@ -2112,7 +2094,7 @@ static void gsm48_cc_timeout(void *arg)
memset(&l4_rel, 0, sizeof(struct gsm_mncc));
l4_rel.callref = trans->callref;
- switch(trans->Tcurrent) {
+ switch(trans->cc.Tcurrent) {
case 0x303:
release = 1;
l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
@@ -2130,21 +2112,21 @@ static void gsm48_cc_timeout(void *arg)
l4_cause = GSM48_CC_CAUSE_USER_NOTRESPOND;
break;
case 0x308:
- if (!trans->T308_second) {
+ if (!trans->cc.T308_second) {
/* restart T308 a second time */
- gsm48_cc_tx_release(trans, &trans->cc_msg);
- trans->T308_second = 1;
+ gsm48_cc_tx_release(trans, &trans->cc.msg);
+ trans->cc.T308_second = 1;
break; /* stay in release state */
}
- free_trans(trans);
+ trans_free(trans);
return;
// release = 1;
// l4_cause = 14;
// break;
case 0x306:
release = 1;
- mo_cause = trans->cc_msg.cause.value;
- mo_location = trans->cc_msg.cause.location;
+ mo_cause = trans->cc.msg.cause.value;
+ mo_location = trans->cc.msg.cause.location;
break;
case 0x323:
disconnect = 1;
@@ -2155,7 +2137,7 @@ static void gsm48_cc_timeout(void *arg)
if (release && trans->callref) {
/* process release towards layer 4 */
- mncc_release_ind(trans->network, trans, trans->callref,
+ mncc_release_ind(trans->subscr->net, trans, trans->callref,
l4_location, l4_cause);
trans->callref = 0;
}
@@ -2163,15 +2145,15 @@ static void gsm48_cc_timeout(void *arg)
if (disconnect && trans->callref) {
/* process disconnect towards layer 4 */
mncc_set_cause(&l4_rel, l4_location, l4_cause);
- mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &l4_rel);
+ mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &l4_rel);
}
/* process disconnect towards mobile station */
if (disconnect || release) {
mncc_set_cause(&mo_rel, mo_location, mo_cause);
- mo_rel.cause.diag[0] = ((trans->Tcurrent & 0xf00) >> 8) + '0';
- mo_rel.cause.diag[1] = ((trans->Tcurrent & 0x0f0) >> 4) + '0';
- mo_rel.cause.diag[2] = (trans->Tcurrent & 0x00f) + '0';
+ mo_rel.cause.diag[0] = ((trans->cc.Tcurrent & 0xf00) >> 8) + '0';
+ mo_rel.cause.diag[1] = ((trans->cc.Tcurrent & 0x0f0) >> 4) + '0';
+ mo_rel.cause.diag[2] = (trans->cc.Tcurrent & 0x00f) + '0';
mo_rel.cause.diag_len = 3;
if (disconnect)
@@ -2186,10 +2168,10 @@ static void gsm48_start_cc_timer(struct gsm_trans *trans, int current,
int sec, int micro)
{
DEBUGP(DCC, "starting timer T%x with %d seconds\n", current, sec);
- trans->cc_timer.cb = gsm48_cc_timeout;
- trans->cc_timer.data = trans;
- bsc_schedule_timer(&trans->cc_timer, sec, micro);
- trans->Tcurrent = current;
+ trans->cc.timer.cb = gsm48_cc_timeout;
+ trans->cc.timer.data = trans;
+ bsc_schedule_timer(&trans->cc.timer, sec, micro);
+ trans->cc.Tcurrent = current;
}
static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
@@ -2264,7 +2246,7 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_INITIATED);
/* indicate setup to MNCC */
- mncc_recvmsg(trans->network, trans, MNCC_SETUP_IND, &setup);
+ mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_IND, &setup);
return 0;
}
@@ -2274,9 +2256,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
struct gsm_mncc *setup = arg;
- struct gsm_trans *transt;
- u_int16_t trans_id_mask = 0;
- int rc, i;
+ int rc, trans_id;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
@@ -2285,40 +2265,27 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
DEBUGP(DCC, "TX Setup with assigned transaction. "
"This is not allowed!\n");
/* Temporarily out of order */
- rc = mncc_release_ind(trans->network, trans, trans->callref,
+ rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
/* Get free transaction_id */
- llist_for_each_entry(transt, &trans->network->trans_list, entry) {
- /* Transaction of our lchan? */
- if (transt->lchan == trans->lchan &&
- transt->transaction_id != 0xff)
- trans_id_mask |= (1 << (transt->transaction_id >> 4));
- }
- /* Assign free transaction ID */
- if ((trans_id_mask & 0x007f) == 0x7f) {
+ trans_id = trans_assign_trans_id(trans->subscr, GSM48_PDISC_CC, 0);
+ if (trans_id < 0) {
/* no free transaction ID */
- rc = mncc_release_ind(trans->network, trans, trans->callref,
+ rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
GSM48_CAUSE_LOC_PRN_S_LU,
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
- for (i = 0; i < 7; i++) {
- if ((trans_id_mask & (1 << i)) == 0) {
- trans->transaction_id = i << 4; /* flag = 0 */
- break;
- }
- }
+ trans->transaction_id = trans_id;
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_SETUP;
gsm48_start_cc_timer(trans, 0x303, GSM48_T303);
@@ -2350,7 +2317,7 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_CALL_PRESENT);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
@@ -2394,7 +2361,8 @@ static int gsm48_cc_rx_call_conf(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_MO_TERM_CALL_CONF);
- return mncc_recvmsg(trans->network, trans, MNCC_CALL_CONF_IND, &call_conf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_CALL_CONF_IND,
+ &call_conf);
}
static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
@@ -2403,8 +2371,6 @@ static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_CALL_PROC;
new_cc_state(trans, GSM_CSTATE_MO_CALL_PROC);
@@ -2419,7 +2385,7 @@ static int gsm48_cc_tx_call_proc(struct gsm_trans *trans, void *arg)
if (proceeding->fields & MNCC_F_PROGRESS)
encode_progress(msg, 0, &proceeding->progress);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
@@ -2457,7 +2423,8 @@ static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
- return mncc_recvmsg(trans->network, trans, MNCC_ALERT_IND, &alerting);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_ALERT_IND,
+ &alerting);
}
static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
@@ -2466,8 +2433,6 @@ static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_ALERTING;
/* facility */
@@ -2482,7 +2447,7 @@ static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_CALL_DELIVERED);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
@@ -2491,8 +2456,6 @@ static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_PROGRESS;
/* progress */
@@ -2501,7 +2464,7 @@ static int gsm48_cc_tx_progress(struct gsm_trans *trans, void *arg)
if (progress->fields & MNCC_F_USERUSER)
encode_useruser(msg, 0, &progress->useruser);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
@@ -2510,8 +2473,6 @@ static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_CONNECT;
gsm48_stop_cc_timer(trans);
@@ -2532,7 +2493,7 @@ static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_CONNECT_IND);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
@@ -2576,7 +2537,7 @@ static int gsm48_cc_rx_connect(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
- return mncc_recvmsg(trans->network, trans, MNCC_SETUP_CNF, &connect);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_CNF, &connect);
}
@@ -2590,7 +2551,7 @@ static int gsm48_cc_rx_connect_ack(struct gsm_trans *trans, struct msgb *msg)
memset(&connect_ack, 0, sizeof(struct gsm_mncc));
connect_ack.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_SETUP_COMPL_IND,
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_SETUP_COMPL_IND,
&connect_ack);
}
@@ -2599,13 +2560,11 @@ static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
@@ -2647,7 +2606,7 @@ static int gsm48_cc_rx_disconnect(struct gsm_trans *trans, struct msgb *msg)
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_DISC_IND, &disc);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_DISC_IND, &disc);
}
@@ -2667,8 +2626,6 @@ static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_DISCONNECT;
gsm48_stop_cc_timer(trans);
@@ -2691,11 +2648,11 @@ static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
encode_useruser(msg, 0, &disc->useruser);
/* store disconnect cause for T306 expiry */
- memcpy(&trans->cc_msg, disc, sizeof(struct gsm_mncc));
+ memcpy(&trans->cc.msg, disc, sizeof(struct gsm_mncc));
new_cc_state(trans, GSM_CSTATE_DISCONNECT_IND);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
@@ -2736,19 +2693,20 @@ static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- if (trans->state == GSM_CSTATE_RELEASE_REQ) {
+ if (trans->cc.state == GSM_CSTATE_RELEASE_REQ) {
/* release collision 5.4.5 */
- rc = mncc_recvmsg(trans->network, trans, MNCC_REL_CNF, &rel);
+ rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_CNF, &rel);
} else {
- rc = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC | trans->transaction_id,
- GSM48_MT_CC_RELEASE_COMPL);
- rc = mncc_recvmsg(trans->network, trans, MNCC_REL_IND, &rel);
+ rc = gsm48_tx_simple(msg->lchan,
+ GSM48_PDISC_CC | (trans->transaction_id << 4),
+ GSM48_MT_CC_RELEASE_COMPL);
+ rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
}
new_cc_state(trans, GSM_CSTATE_NULL);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -2759,8 +2717,6 @@ static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_RELEASE;
trans->callref = 0;
@@ -2778,13 +2734,13 @@ static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
if (rel->fields & MNCC_F_USERUSER)
encode_useruser(msg, 0, &rel->useruser);
- trans->T308_second = 0;
- memcpy(&trans->cc_msg, rel, sizeof(struct gsm_mncc));
+ trans->cc.T308_second = 0;
+ memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
- if (trans->state != GSM_CSTATE_RELEASE_REQ)
+ if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
@@ -2826,23 +2782,23 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
}
if (trans->callref) {
- switch (trans->state) {
+ switch (trans->cc.state) {
case GSM_CSTATE_CALL_PRESENT:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REJ_IND, &rel);
break;
case GSM_CSTATE_RELEASE_REQ:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REL_CNF, &rel);
break;
default:
- rc = mncc_recvmsg(trans->network, trans,
+ rc = mncc_recvmsg(trans->subscr->net, trans,
MNCC_REL_IND, &rel);
}
}
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -2853,8 +2809,6 @@ static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
trans->callref = 0;
@@ -2871,9 +2825,9 @@ static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
if (rel->fields & MNCC_F_USERUSER)
encode_useruser(msg, 0, &rel->useruser);
- free_trans(trans);
+ trans_free(trans);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
@@ -2899,7 +2853,7 @@ static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
TLVP_VAL(&tp, GSM48_IE_SS_VERS)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_FACILITY_IND, &fac);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
}
static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
@@ -2908,14 +2862,12 @@ static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_FACILITY;
/* facility */
encode_facility(msg, 1, &fac->facility);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
@@ -2924,7 +2876,7 @@ static int gsm48_cc_rx_hold(struct gsm_trans *trans, struct msgb *msg)
memset(&hold, 0, sizeof(struct gsm_mncc));
hold.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_HOLD_IND, &hold);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_HOLD_IND, &hold);
}
static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
@@ -2932,11 +2884,9 @@ static int gsm48_cc_tx_hold_ack(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_HOLD_ACK;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
@@ -2945,8 +2895,6 @@ static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_HOLD_REJ;
/* cause */
@@ -2955,7 +2903,7 @@ static int gsm48_cc_tx_hold_rej(struct gsm_trans *trans, void *arg)
else
encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
@@ -2964,7 +2912,8 @@ static int gsm48_cc_rx_retrieve(struct gsm_trans *trans, struct msgb *msg)
memset(&retrieve, 0, sizeof(struct gsm_mncc));
retrieve.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_RETRIEVE_IND, &retrieve);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_RETRIEVE_IND,
+ &retrieve);
}
static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
@@ -2972,11 +2921,9 @@ static int gsm48_cc_tx_retrieve_ack(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_RETR_ACK;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
@@ -2985,8 +2932,6 @@ static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_RETR_REJ;
/* cause */
@@ -2995,7 +2940,7 @@ static int gsm48_cc_tx_retrieve_rej(struct gsm_trans *trans, void *arg)
else
encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
@@ -3015,7 +2960,7 @@ static int gsm48_cc_rx_start_dtmf(struct gsm_trans *trans, struct msgb *msg)
TLVP_VAL(&tp, GSM48_IE_KPD_FACILITY)-1);
}
- return mncc_recvmsg(trans->network, trans, MNCC_START_DTMF_IND, &dtmf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_START_DTMF_IND, &dtmf);
}
static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
@@ -3024,15 +2969,13 @@ static int gsm48_cc_tx_start_dtmf_ack(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_START_DTMF_ACK;
/* keypad */
if (dtmf->fields & MNCC_F_KEYPAD)
encode_keypad(msg, dtmf->keypad);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
@@ -3041,8 +2984,6 @@ static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_START_DTMF_REJ;
/* cause */
@@ -3051,7 +2992,7 @@ static int gsm48_cc_tx_start_dtmf_rej(struct gsm_trans *trans, void *arg)
else
encode_cause(msg, 1, &default_cause);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
@@ -3059,11 +3000,9 @@ static int gsm48_cc_tx_stop_dtmf_ack(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_STOP_DTMF_ACK;
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
@@ -3073,7 +3012,7 @@ static int gsm48_cc_rx_stop_dtmf(struct gsm_trans *trans, struct msgb *msg)
memset(&dtmf, 0, sizeof(struct gsm_mncc));
dtmf.callref = trans->callref;
- return mncc_recvmsg(trans->network, trans, MNCC_STOP_DTMF_IND, &dtmf);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_STOP_DTMF_IND, &dtmf);
}
static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
@@ -3095,7 +3034,7 @@ static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_IND, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_IND, &modify);
}
static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
@@ -3104,8 +3043,6 @@ static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_MODIFY;
gsm48_start_cc_timer(trans, 0x323, GSM48_T323);
@@ -3115,7 +3052,7 @@ static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg)
@@ -3139,7 +3076,7 @@ static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_CNF, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_CNF, &modify);
}
static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
@@ -3148,8 +3085,6 @@ static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
/* bearer capability */
@@ -3157,7 +3092,7 @@ static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
@@ -3187,7 +3122,7 @@ static int gsm48_cc_rx_modify_reject(struct gsm_trans *trans, struct msgb *msg)
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return mncc_recvmsg(trans->network, trans, MNCC_MODIFY_REJ, &modify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_MODIFY_REJ, &modify);
}
static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
@@ -3196,8 +3131,6 @@ static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
/* bearer capability */
@@ -3207,7 +3140,7 @@ static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
new_cc_state(trans, GSM_CSTATE_ACTIVE);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
@@ -3216,14 +3149,12 @@ static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_NOTIFY;
/* notify */
encode_notify(msg, notify->notify);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
@@ -3239,7 +3170,7 @@ static int gsm48_cc_rx_notify(struct gsm_trans *trans, struct msgb *msg)
if (payload_len >= 1)
decode_notify(&notify.notify, gh->data);
- return mncc_recvmsg(trans->network, trans, MNCC_NOTIFY_IND, &notify);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_NOTIFY_IND, &notify);
}
static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
@@ -3248,8 +3179,6 @@ static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- gh->proto_discr = GSM48_PDISC_CC | trans->transaction_id;
- msg->lchan = trans->lchan;
gh->msg_type = GSM48_MT_CC_USER_INFO;
/* user-user */
@@ -3259,7 +3188,7 @@ static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
if (user->more)
encode_more(msg);
- return gsm48_sendmsg(msg);
+ return gsm48_sendmsg(msg, trans);
}
static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
@@ -3282,7 +3211,7 @@ static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, struct msgb *msg)
if (TLVP_PRESENT(&tp, GSM48_IE_MORE_DATA))
user.more = 1;
- return mncc_recvmsg(trans->network, trans, MNCC_USERINFO_IND, &user);
+ return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &user);
}
static int gsm48_lchan_modify(struct gsm_trans *trans, void *arg)
@@ -3381,7 +3310,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
rel.callref = data->callref;
/* Find callref */
- trans = get_trans_ref(net, data->callref);
+ trans = trans_find_by_callref(net, data->callref);
/* Callref unknown */
if (!trans) {
@@ -3406,9 +3335,10 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
}
/* New transaction due to setup, find subscriber */
if (data->called.number[0])
- subscr = subscr_get_by_extension(data->called.number);
+ subscr = subscr_get_by_extension(net,
+ data->called.number);
else
- subscr = subscr_get_by_imsi(data->imsi);
+ subscr = subscr_get_by_imsi(net, data->imsi);
/* If subscriber is not found */
if (!subscr) {
DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) "
@@ -3433,7 +3363,8 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
GSM48_CC_CAUSE_DEST_OOO);
}
/* Create transaction */
- if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
+ trans = trans_alloc(subscr, GSM48_PDISC_CC, 0xff, data->callref);
+ if (!trans) {
DEBUGP(DCC, "No memory for trans.\n");
subscr_put(subscr);
/* Ressource unavailable */
@@ -3442,12 +3373,6 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
return -ENOMEM;
}
- trans->callref = data->callref;
- trans->network = net;
- trans->transaction_id = 0xff; /* unassigned */
- llist_add_tail(&trans->entry, &net->trans_list);
- /* Assign subscriber to transaction */
- trans->subscr = subscr;
/* Find lchan */
for (i = 0; i < net->num_bts; i++) {
bts = gsm_bts_num(net, i);
@@ -3483,7 +3408,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
return 0;
}
/* store setup informations until paging was successfull */
- memcpy(&trans->cc_msg, data, sizeof(struct gsm_mncc));
+ memcpy(&trans->cc.msg, data, sizeof(struct gsm_mncc));
/* start paging subscriber on all BTS with her location */
subscr->net = net;
bts = NULL;
@@ -3521,7 +3446,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
else
rc = mncc_recvmsg(net, trans, MNCC_REL_IND, &rel);
trans->callref = 0;
- free_trans(trans);
+ trans_free(trans);
return rc;
}
@@ -3530,13 +3455,13 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg)
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
trans->transaction_id,
(lchan->subscr)?(lchan->subscr->extension):"-",
- get_mncc_name(msg_type), trans->state,
- cc_state_names[trans->state]);
+ get_mncc_name(msg_type), trans->cc.state,
+ cc_state_names[trans->cc.state]);
/* Find function for current state and message */
for (i = 0; i < DOWNSLLEN; i++)
if ((msg_type == downstatelist[i].type)
- && ((1 << trans->state) & downstatelist[i].states))
+ && ((1 << trans->cc.state) & downstatelist[i].states))
break;
if (i == DOWNSLLEN) {
DEBUGP(DCC, "Message unhandled at this state.\n");
@@ -3607,10 +3532,9 @@ static int gsm0408_rcv_cc(struct msgb *msg)
{
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t msg_type = gh->msg_type & 0xbf;
- u_int8_t transaction_id = (gh->proto_discr & 0xf0) ^ 0x80; /* flip */
+ u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */
struct gsm_lchan *lchan = msg->lchan;
- struct gsm_trans *trans = NULL, *transt;
- struct gsm_network *net = lchan->ts->trx->bts->network;
+ struct gsm_trans *trans = NULL;
int i, rc = 0;
if (msg_type & 0x80) {
@@ -3619,50 +3543,38 @@ static int gsm0408_rcv_cc(struct msgb *msg)
}
/* Find transaction */
- llist_for_each_entry(transt, &net->trans_list, entry) {
- /* Transaction of our lchan? */
- if (transt->lchan == lchan
- && transt->transaction_id == transaction_id) {
- trans = transt;
- }
- }
-
- DEBUGP(DCC, "(bts %d trx %d ts %d ti %02x sub %s) "
+ trans = trans_find_by_id(lchan, transaction_id);
+
+ DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) "
"Received '%s' from MS in state %d (%s)\n",
lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr,
transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-",
- cc_msg_names[msg_type], trans?(trans->state):0,
- cc_state_names[trans?(trans->state):0]);
+ cc_msg_names[msg_type], trans?(trans->cc.state):0,
+ cc_state_names[trans?(trans->cc.state):0]);
/* Create transaction */
if (!trans) {
- DEBUGP(DCC, "Unknown transaction ID %02x, "
+ DEBUGP(DCC, "Unknown transaction ID %x, "
"creating new trans.\n", transaction_id);
/* Create transaction */
- if (!(trans = talloc_zero(tall_trans_ctx, struct gsm_trans))) {
+ trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC,
+ transaction_id, new_callref++);
+ if (!trans) {
DEBUGP(DCC, "No memory for trans.\n");
rc = gsm48_tx_simple(msg->lchan,
- GSM48_PDISC_CC | transaction_id,
+ GSM48_PDISC_CC | (transaction_id << 4),
GSM48_MT_CC_RELEASE_COMPL);
return -ENOMEM;
}
- llist_add_tail(&trans->entry, &net->trans_list);
/* Assign transaction */
- trans->callref = new_callref++;
- trans->network = net;
- trans->transaction_id = transaction_id;
trans->lchan = lchan;
use_lchan(lchan);
- if (lchan->subscr) {
- trans->subscr = lchan->subscr;
- subscr_get(trans->subscr);
- }
}
/* find function for current state and message */
for (i = 0; i < DATASLLEN; i++)
if ((msg_type == datastatelist[i].type)
- && ((1 << trans->state) & datastatelist[i].states))
+ && ((1 << trans->cc.state) & datastatelist[i].states))
break;
if (i == DATASLLEN) {
DEBUGP(DCC, "Message unhandled at this state.\n");
@@ -3819,3 +3731,4 @@ int bsc_upqueue(struct gsm_network *net)
return work;
}
+
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 1b622b12b..9218783ff 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -154,6 +154,7 @@ static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
/* process an incoming TPDU (called from RP-DATA) */
static int gsm340_rx_tpdu(struct msgb *msg)
{
+ struct gsm_bts *bts = msg->lchan->ts->trx->bts;
u_int8_t *smsp = msgb_sms(msg);
struct sms_submit *sms;
struct gsm_sms *gsms;
@@ -161,19 +162,11 @@ static int gsm340_rx_tpdu(struct msgb *msg)
u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
int rc = 0;
- if (!tall_sms_ctx)
- tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "sms_submit");
-
sms = talloc(tall_sms_ctx, struct sms_submit);
if (!sms)
return -ENOMEM;
memset(sms, 0, sizeof(*sms));
- if (!tall_gsms_ctx)
- tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "sms");
-
gsms = talloc(tall_gsms_ctx, struct gsm_sms);
if (!gsms) {
talloc_free(sms);
@@ -257,7 +250,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
/* FIXME: sender refcount */
/* determine gsms->receiver based on dialled number */
- gsms->receiver = subscr_get_by_extension(sms->dest_addr);
+ gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
if (!gsms->receiver) {
rc = 1; /* cause 1: unknown subscriber */
goto out;
@@ -512,3 +505,9 @@ int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
return gsm0411_sendmsg(msg);
}
+
+static __attribute__((constructor)) void on_dso_load_sms(void)
+{
+ tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms_submit");
+ tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
+}
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index a323d4e87..748015693 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -103,10 +103,6 @@ struct gsm_subscriber *subscr_alloc(void)
{
struct gsm_subscriber *s;
- if (!tall_subscr_ctx)
- tall_subscr_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "subscriber");
-
s = talloc(tall_subscr_ctx, struct gsm_subscriber);
if (!s)
return NULL;
@@ -126,7 +122,8 @@ static void subscr_free(struct gsm_subscriber *subscr)
talloc_free(subscr);
}
-struct gsm_subscriber *subscr_get_by_tmsi(const char *tmsi)
+struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_network *net,
+ const char *tmsi)
{
struct gsm_subscriber *subscr;
@@ -136,10 +133,11 @@ struct gsm_subscriber *subscr_get_by_tmsi(const char *tmsi)
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_TMSI, tmsi);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_TMSI, tmsi);
}
-struct gsm_subscriber *subscr_get_by_imsi(const char *imsi)
+struct gsm_subscriber *subscr_get_by_imsi(struct gsm_network *net,
+ const char *imsi)
{
struct gsm_subscriber *subscr;
@@ -148,10 +146,11 @@ struct gsm_subscriber *subscr_get_by_imsi(const char *imsi)
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_IMSI, imsi);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi);
}
-struct gsm_subscriber *subscr_get_by_extension(const char *ext)
+struct gsm_subscriber *subscr_get_by_extension(struct gsm_network *net,
+ const char *ext)
{
struct gsm_subscriber *subscr;
@@ -160,7 +159,7 @@ struct gsm_subscriber *subscr_get_by_extension(const char *ext)
return subscr_get(subscr);
}
- return db_get_subscriber(GSM_SUBSCRIBER_EXTENSION, ext);
+ return db_get_subscriber(net, GSM_SUBSCRIBER_EXTENSION, ext);
}
int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
@@ -168,6 +167,7 @@ int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason)
/* FIXME: Migrate pending requests from one BSC to another */
switch (reason) {
case GSM_SUBSCRIBER_UPDATE_ATTACHED:
+ s->net = bts->network;
/* Indicate "attached to LAC" */
s->lac = bts->location_area_code;
break;
@@ -209,10 +209,6 @@ void subscr_get_channel(struct gsm_subscriber *subscr,
{
struct subscr_request *request;
- if (!tall_sub_req_ctx)
- tall_sub_req_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "subscr_request");
-
request = talloc(tall_sub_req_ctx, struct subscr_request);
if (!request) {
if (cbfn)
@@ -269,3 +265,11 @@ void subscr_put_channel(struct gsm_lchan *lchan)
subscr_send_paging_request(lchan->subscr);
}
+
+static __attribute__((constructor)) void on_dso_load_subscr(void)
+{
+ tall_subscr_ctx = talloc_named_const(tall_bsc_ctx, 1, "subscriber");
+
+ tall_sub_req_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "subscr_request");
+}
diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c
index b2dab078e..8cd62f6ce 100644
--- a/openbsc/src/mncc.c
+++ b/openbsc/src/mncc.c
@@ -140,9 +140,6 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type,
if (call->remote_ref)
return 0;
- if (!tall_call_ctx)
- tall_call_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "gsm_call");
/* create remote call */
if (!(remote = talloc(tall_call_ctx, struct gsm_call))) {
memset(&mncc, 0, sizeof(struct gsm_mncc));
@@ -306,9 +303,6 @@ int mncc_recv(struct gsm_network *net, int msg_type, void *arg)
if (!call) {
if (msg_type != MNCC_SETUP_IND)
return 0; /* drop */
- if (!tall_call_ctx)
- tall_call_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "gsm_call");
/* create call */
if (!(call = talloc_zero(tall_call_ctx, struct gsm_call))) {
struct gsm_mncc rel;
@@ -395,3 +389,8 @@ int mncc_recv(struct gsm_network *net, int msg_type, void *arg)
return rc;
}
+
+static __attribute__((constructor)) void on_dso_load_trau_mncc(void)
+{
+ tall_call_ctx = talloc_named_const(tall_bsc_ctx, 1, "gsm_call");
+}
diff --git a/openbsc/src/msgb.c b/openbsc/src/msgb.c
index ae1334614..52edf2dcd 100644
--- a/openbsc/src/msgb.c
+++ b/openbsc/src/msgb.c
@@ -33,9 +33,6 @@ struct msgb *msgb_alloc(u_int16_t size, const char *name)
{
struct msgb *msg;
- if (!tall_msgb_ctx)
- tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 1, "msgb");
-
msg = _talloc_zero(tall_msgb_ctx, sizeof(*msg) + size, name);
if (!msg)
@@ -76,3 +73,8 @@ struct msgb *msgb_dequeue(struct llist_head *queue)
return llist_entry(lh, struct msgb, list);
}
+
+static __attribute__((constructor)) void on_dso_load_trau_msgb(void)
+{
+ tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 1, "msgb");
+}
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index 0703e932f..b63a717b0 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -219,9 +219,6 @@ static void _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr,
struct gsm_bts_paging_state *bts_entry = &bts->paging;
struct gsm_paging_request *req;
- if (!tall_paging_ctx)
- tall_paging_ctx = talloc_named_const(NULL, 1, "paging_request");
-
if (paging_pending_request(bts_entry, subscr)) {
DEBUGP(DPAG, "Paging request already pending\n");
return;
@@ -310,3 +307,8 @@ void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots)
{
bts->paging.available_slots = free_slots;
}
+
+static __attribute__((constructor)) void on_dso_load_paging(void)
+{
+ tall_paging_ctx = talloc_named_const(NULL, 1, "paging_request");
+}
diff --git a/openbsc/src/select.c b/openbsc/src/select.c
index 11b7e6b49..7f45426d0 100644
--- a/openbsc/src/select.c
+++ b/openbsc/src/select.c
@@ -25,6 +25,7 @@
static int maxfd = 0;
static LLIST_HEAD(bsc_fds);
+static int unregistered_count;
int bsc_register_fd(struct bsc_fd *fd)
{
@@ -50,6 +51,7 @@ int bsc_register_fd(struct bsc_fd *fd)
void bsc_unregister_fd(struct bsc_fd *fd)
{
+ unregistered_count++;
llist_del(&fd->list);
}
@@ -86,6 +88,8 @@ int bsc_select_main(int polling)
bsc_update_timers();
/* call registered callback functions */
+restart:
+ unregistered_count = 0;
llist_for_each_entry_safe(ufd, tmp, &bsc_fds, list) {
int flags = 0;
@@ -102,6 +106,11 @@ int bsc_select_main(int polling)
work = 1;
ufd->cb(ufd, flags);
}
+ /* ugly, ugly hack. If more than one filedescriptors were
+ * unregistered, they might have been consecutive and
+ * llist_for_each_entry_safe() is no longer safe */
+ if (unregistered_count > 1)
+ goto restart;
}
return work;
}
diff --git a/openbsc/src/signal.c b/openbsc/src/signal.c
index 41352fb1a..bf5671ee1 100644
--- a/openbsc/src/signal.c
+++ b/openbsc/src/signal.c
@@ -39,9 +39,6 @@ int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data)
{
struct signal_handler *sig_data;
- if (!tall_sigh_ctx)
- tall_sigh_ctx = talloc_named_const(NULL, 1, "signal_handler");
-
sig_data = talloc(tall_sigh_ctx, struct signal_handler);
if (!sig_data)
return -ENOMEM;
@@ -84,3 +81,8 @@ void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data
(*handler->cbfn)(subsys, signal, handler->data, signal_data);
}
}
+
+static __attribute__((constructor)) void on_dso_load_signal(void)
+{
+ tall_sigh_ctx = talloc_named_const(NULL, 1, "signal_handler");
+}
diff --git a/openbsc/src/subchan_demux.c b/openbsc/src/subchan_demux.c
index ccd4fadc6..368b9853c 100644
--- a/openbsc/src/subchan_demux.c
+++ b/openbsc/src/subchan_demux.c
@@ -312,9 +312,6 @@ int subchan_mux_init(struct subch_mux *mx)
{
int i;
- if (!tall_tqe_ctx)
- tall_tqe_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "subch_txq_entry");
memset(mx, 0, sizeof(*mx));
for (i = 0; i < NR_SUBCH; i++) {
struct mux_subch *sch = &mx->subch[i];
@@ -323,3 +320,9 @@ int subchan_mux_init(struct subch_mux *mx)
return 0;
}
+
+static __attribute__((constructor)) void on_dso_load_ss_demux(void)
+{
+ tall_tqe_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "subch_txq_entry");
+}
diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c
new file mode 100644
index 000000000..f4cef28d2
--- /dev/null
+++ b/openbsc/src/transaction.c
@@ -0,0 +1,144 @@
+/* GSM 04.07 Transaction handling */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <openbsc/transaction.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/mncc.h>
+#include <openbsc/debug.h>
+#include <openbsc/talloc.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/mncc.h>
+#include <openbsc/paging.h>
+
+static void *tall_trans_ctx;
+
+struct gsm_trans *trans_find_by_id(struct gsm_lchan *lchan, u_int8_t trans_id)
+{
+ struct gsm_trans *trans;
+ struct gsm_network *net = lchan->ts->trx->bts->network;
+
+ llist_for_each_entry(trans, &net->trans_list, entry) {
+ if (trans->lchan == lchan && trans->transaction_id == trans_id)
+ return trans;
+ }
+ return NULL;
+}
+
+struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
+ u_int32_t callref)
+{
+ struct gsm_trans *trans;
+
+ llist_for_each_entry(trans, &net->trans_list, entry) {
+ if (trans->callref == callref)
+ return trans;
+ }
+ return NULL;
+}
+
+struct gsm_trans *trans_alloc(struct gsm_subscriber *subscr,
+ u_int8_t protocol, u_int8_t trans_id,
+ u_int32_t callref)
+{
+ struct gsm_trans *trans;
+
+ DEBUGP(DCC, "subscr=%p, subscr->net=%p\n", subscr, subscr->net);
+
+ trans = talloc_zero(tall_trans_ctx, struct gsm_trans);
+ if (!trans)
+ return NULL;
+
+ trans->subscr = subscr;
+ subscr_get(trans->subscr);
+
+ trans->protocol = protocol;
+ trans->transaction_id = trans_id;
+ trans->callref = callref;
+
+ llist_add_tail(&trans->entry, &subscr->net->trans_list);
+
+ return trans;
+}
+
+void trans_free(struct gsm_trans *trans)
+{
+ struct gsm_bts *bts;
+
+ switch (trans->protocol) {
+ case GSM48_PDISC_CC:
+ _gsm48_cc_trans_free(trans);
+ break;
+ }
+
+ if (trans->lchan)
+ put_lchan(trans->lchan);
+
+ if (!trans->lchan && trans->subscr && trans->subscr->net) {
+ /* Stop paging on all bts' */
+ bts = NULL;
+ do {
+ bts = gsm_bts_by_lac(trans->subscr->net,
+ trans->subscr->lac, bts);
+ if (!bts)
+ break;
+ /* Stop paging */
+ paging_request_stop(bts, trans->subscr, NULL);
+ } while (1);
+ }
+
+ if (trans->subscr)
+ subscr_put(trans->subscr);
+
+ llist_del(&trans->entry);
+
+ talloc_free(trans);
+}
+
+/* allocate an unused transaction ID for the given subscriber
+ * in the given protocol using the ti_flag specified */
+int trans_assign_trans_id(struct gsm_subscriber *subscr,
+ u_int8_t protocol, u_int8_t ti_flag)
+{
+ struct gsm_network *net = subscr->net;
+ struct gsm_trans *trans;
+ unsigned int used_tid_bitmask = 0;
+ int i;
+
+ if (ti_flag)
+ ti_flag = 0x8;
+
+ /* generate bitmask of already-used TIDs for this (subscr,proto) */
+ llist_for_each_entry(trans, &net->trans_list, entry) {
+ if (trans->subscr != subscr ||
+ trans->protocol != protocol ||
+ trans->transaction_id == 0xff)
+ continue;
+ used_tid_bitmask |= (1 << trans->transaction_id);
+ }
+
+ for (i = 0; i <= 7; i++) {
+ if ((used_tid_bitmask & (1 << (i | ti_flag))) == 0)
+ return i | ti_flag;
+ }
+
+ return -1;
+}
diff --git a/openbsc/src/trau_mux.c b/openbsc/src/trau_mux.c
index 04febbd63..9ff7001d3 100644
--- a/openbsc/src/trau_mux.c
+++ b/openbsc/src/trau_mux.c
@@ -55,10 +55,6 @@ int trau_mux_map(const struct gsm_e1_subslot *src,
{
struct map_entry *me;
- if (!tall_map_ctx)
- tall_map_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "trau_map_entry");
-
me = talloc(tall_map_ctx, struct map_entry);
if (!me)
return -ENOMEM;
@@ -201,10 +197,6 @@ int trau_recv_lchan(struct gsm_lchan *lchan, u_int32_t callref)
struct gsm_e1_subslot *src_ss;
struct upqueue_entry *ue;
- if (!tall_upq_ctx)
- tall_upq_ctx = talloc_named_const(tall_bsc_ctx, 1,
- "trau_upq_entry");
-
ue = talloc(tall_upq_ctx, struct upqueue_entry);
if (!ue)
return -ENOMEM;
@@ -243,3 +235,12 @@ int trau_send_lchan(struct gsm_lchan *lchan, struct decoded_trau_frame *tf)
return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
TRAU_FRAME_BITS);
}
+
+static __attribute__((constructor)) void on_dso_load_trau_mux(void)
+{
+ tall_map_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "trau_map_entry");
+
+ tall_upq_ctx = talloc_named_const(tall_bsc_ctx, 1,
+ "trau_upq_entry");
+}
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index 462689098..11b2ff60b 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -589,7 +589,7 @@ DEFUN(cfg_subscr,
const char *imsi = argv[0];
struct gsm_subscriber *subscr;
- subscr = subscr_get_by_imsi(imsi);
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
if (!subscr) {
vty_out(vty, "%% No subscriber for IMSI %s%s",
imsi, VTY_NEWLINE);
@@ -855,7 +855,7 @@ DEFUN(show_subscr,
if (argc >= 1) {
imsi = argv[0];
- subscr = subscr_get_by_imsi(imsi);
+ subscr = subscr_get_by_imsi(gsmnet, imsi);
if (!subscr) {
vty_out(vty, "%% unknown subscriber%s",
VTY_NEWLINE);