Compare commits

...

46 Commits

Author SHA1 Message Date
Holger Hans Peter Freyther
fcb4468de4 A new day, a new tag 2010-05-14 00:49:14 +08:00
Holger Hans Peter Freyther
9e96b2df12 rach: Allow to set the emergency call bit
Add the rach emergency call allowed (0|1) setting and implement
it by directly manipulating the t2 value. It is the third bit which
is set to 0 when emergency calls are enabled and to one if it is
only enabled for access classes 11 to 15.
2010-05-14 00:39:19 +08:00
Holger Hans Peter Freyther
72952d854c [mgcp] Use tabs here.. 2010-05-14 00:20:32 +08:00
Holger Hans Peter Freyther
637dce99ba ipaccess: Move the RSL delay down to 0 milliseconds.
Set the delay to zero milliseconds to send RSL messages as fast
as possible.
2010-05-14 00:09:05 +08:00
Holger Hans Peter Freyther
641b07ab73 ipaccess: Make sure flashing of the secondary BTS is working
Use the TRX throughout the flash process.
2010-05-13 00:17:17 +08:00
Holger Hans Peter Freyther
6eae31e39f sw_load: Specify the trx_nr for the software load
For the multi TRX setup we will need to specify the right trx->nr
to be able to flash the BTS. For the BS11 case we are ignoring the
additional argument.
2010-05-13 00:17:17 +08:00
Holger Hans Peter Freyther
4647015f69 ipaccess: Send the reset to the BASEBAND_TRANSC and supply TRX
Send the IPA Restart to a given BTS/TRX, change the signal callbacks
to carry the trx instead of the BTS so we have an easy access to the
right TRX and change the ipaccess-config to use that TRX. This is
fixing the restart with a multi TRX setup.

Even if we have the msg->trx, use the gsm_bts_trx_by_nr and get
the TRX from the fom header. This is because the OpenBSC and the
BTS numbering might not match for the multi TRX case.
2010-05-13 00:16:15 +08:00
Holger Hans Peter Freyther
239f95467c ipaccess: Refactor... unite some code 2010-05-12 23:39:51 +08:00
Holger Hans Peter Freyther
cd80c73f37 ipaccess: Use the right trx when performing the test 2010-05-12 23:02:23 +08:00
Holger Hans Peter Freyther
d6f1c4afbb ipaccess: Use the current TRX to set the OML address. 2010-05-12 22:48:28 +08:00
Holger Hans Peter Freyther
0c8af75c94 Increase the version number. 2010-05-12 22:25:40 +08:00
Holger Hans Peter Freyther
e4b33be6fc chan: After sending the GSM04.08 RR Release, reset the subscriber and wait
After we send the SACH DEACTIVATE the BTS will get back to us with a
Release Indication which will trigger the RF Channel Release handling. This
is why we can return here, but we need to put the subscriber reference to
make sure to not end in a infinite loop.

This and the previous change fix the USSD issue for me.
2010-05-12 22:09:24 +08:00
Holger Hans Peter Freyther
cc7461cefc bsc_msc_ip: Assign a dummy gsm_subscriber to send a SACH DEACTIVATE
This is part of fixing USSD delivered to the MS. Currently only MT
services would end up with a GSM Subscriber assigned. The LCHAN code
is using the GSM Subscriber to figure out if a SACH DEACTIVATE should
be send to the MS. Add code to always assign a GSM Subscriber.
2010-05-12 22:09:16 +08:00
Holger Hans Peter Freyther
e174061d17 bssap: Use libosmocore for message creation. 2010-05-12 18:34:20 +08:00
Holger Hans Peter Freyther
6e1c3412ae bssap: Use libosmocore to create GSM0808 Reset 2010-05-12 18:33:15 +08:00
Holger Hans Peter Freyther
bff54b3e00 bssap: Start to libosmocore for gsm0808 message creation. 2010-05-12 18:31:13 +08:00
Holger Hans Peter Freyther
e75eb4ca25 ipaccess: Wait for the BASEBAND_TRANSCEIVER and then bootstrap OML
Currently we are connecting to the BTS and once the OML is established
we are bootstrapping the OML. This does not work for a multi TRX setup
as we will need to use a trx_nr != 0 for it.

Change the code to wait for a message (in this case NM OC_BASEBAND_TRANSC)
to detect the trx_nr used by the BTS and then use that TRX to bootstrap
the network.

I have tested setting the unit id on a single and multi trx system for
the first and second trx.
2010-05-12 17:16:18 +08:00
Holger Hans Peter Freyther
566737a4b8 abis: Pass the abis_om_obj_inst in the nm_state_event.. 2010-05-12 17:16:18 +08:00
Holger Hans Peter Freyther
2b7350240d nat: Have a recycle timer that removes unconfirmed SCCP connections.
The MSC does not respond to a SCCP CR with Paging Response as GSM
payload, when the response comes in 'too late'. Prevent the MUX having
stale connections and start removing old connections every 20 minutes.
2010-05-12 00:58:08 +08:00
Holger Hans Peter Freyther
d76b53c00e nat: When we fail to reallocate... also close down the MGCP part
Give the BSC a chanche to close down MGCP ports as well.
2010-05-12 00:35:07 +08:00
Holger Hans Peter Freyther
9c9ef7796a nat: Store the creation time of a sccp connection.
Generate it when creating the connection but also when
reusing an existing connection.
2010-05-12 00:33:38 +08:00
Holger Hans Peter Freyther
49fcc8fc90 bsc_msc_ip: Use constants for ?/0/1. 2010-05-11 22:54:29 +08:00
Holger Hans Peter Freyther
51a4bcc96a Increase the version... as we have new commands 2010-05-11 20:02:36 +08:00
Holger Hans Peter Freyther
d6238120dd bsc_msc_ip: Add an extra command to show the MSC status. 2010-05-11 20:00:22 +08:00
Holger Hans Peter Freyther
7407aec921 bsc_msc_ip: Move the MSC connection into the structure 2010-05-11 20:00:22 +08:00
Holger Hans Peter Freyther
e575ce69ce nat: Print the MSC status with a new vty command. 2010-05-11 20:00:16 +08:00
Holger Hans Peter Freyther
c1ca0ff091 misc: Make sure PACKAGE_VERSION is getting defined with a useful content.
PACKAGE_VERSION is used by the copyright message.
2010-05-11 19:08:10 +08:00
Holger Hans Peter Freyther
661e68b78f bsc_msc_ip: Add a test mode to send messages to the MSC.
Check if the MSC likes paging responses when it has not
recently send out a paging request.
2010-05-11 19:08:10 +08:00
Holger Hans Peter Freyther
376e146cfb gsm0408: Use counter_inc to increment the counter. 2010-05-11 19:08:10 +08:00
Holger Hans Peter Freyther
eb3ab2f85b bsc_msc: Add a connection timeout for the MSC.
When no one is listening our connection would get stuck
in the SYN_SENT state and we would be there forever.
2010-05-05 22:48:56 +08:00
Holger Hans Peter Freyther
ebc38e4f26 Version bump for testing it on the target 2010-05-05 20:43:11 +08:00
Holger Hans Peter Freyther
e2ab44a439 nat: Using the right fd can be a good idea as well 2010-05-05 20:42:14 +08:00
Holger Hans Peter Freyther
8b3cced773 Another version... another try 2010-05-05 20:37:10 +08:00
Holger Hans Peter Freyther
3d1b0770f4 nat: Fix bad bug, make sure the fd is not overwritten..
The adding of the innocent looking code was actually overwrote
the fd and then stupid things happened. Rename variables to avoid
that. rc,ret should be scratch variables...
2010-05-05 20:33:34 +08:00
Holger Hans Peter Freyther
99743fb7ec Bump the version for TCP_NODELAY. 2010-05-05 19:01:23 +08:00
Holger Hans Peter Freyther
a2a42a7561 bsc_msc_ip: Attempt to disable nagle
Use TCP_NODELAY on the connection to the MSC. We want small
messages to be send immediately.
2010-05-05 19:00:38 +08:00
Holger Hans Peter Freyther
ebd57da87d nat: Use TCP_NODELAY for the connection to the BSC.
We do not want to use NAGLE for the BSC connection.
2010-05-05 18:59:54 +08:00
Holger Hans Peter Freyther
b0ee082bb0 Bump version
Configurable timeout.
2010-05-05 17:52:40 +08:00
Holger Hans Peter Freyther
81f6a4c0bf bsc_msc_ip: Add VTY code for ping/pong timeout. 2010-05-05 17:46:08 +08:00
Holger Hans Peter Freyther
3978de52c1 bsc_msc_ip: Do not send a ping when the timeout is negative 2010-05-05 17:42:32 +08:00
Holger Hans Peter Freyther
7faf692cb7 bsc_msc_ip: Make the ping/pong timeouts configurable
Take the timeouts from the struct.
2010-05-05 17:39:22 +08:00
Holger Hans Peter Freyther
0cf25d5154 nat: Improve log messages. Refer to ip and fd. 2010-05-05 17:03:44 +08:00
Holger Hans Peter Freyther
08db178271 nat: Make ping/pong timeout configurable. 2010-05-05 16:57:38 +08:00
Holger Hans Peter Freyther
936d8c1b64 Work with later libosmocore. 2010-05-03 19:38:01 +08:00
Harald Welte
3170305e56 move gsm48_construct_ra() to libosmocore 2010-05-03 19:36:58 +08:00
Harald Welte
0f3490dd03 'struct gprs_ra_id' is now defined in libosmocore 2010-05-03 19:36:41 +08:00
26 changed files with 394 additions and 216 deletions

View File

@@ -1,7 +1,6 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT
AM_INIT_AUTOMAKE(openbsc, 0.3.99.3onwaves)
AC_INIT(openbsc, 0.3.99.11onwaves)
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

View File

@@ -92,7 +92,7 @@ int abis_nm_sw_act_req_ack(struct gsm_bts *bts, u_int8_t obj_class, u_int8_t i1,
int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg);
int abis_nm_event_reports(struct gsm_bts *bts, int on);
int abis_nm_reset_resource(struct gsm_bts *bts);
int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
u_int8_t win_size, int forced,
gsm_cbfn *cbfn, void *cb_data);
int abis_nm_software_load_status(struct gsm_bts *bts);
@@ -148,7 +148,7 @@ int abis_nm_ipaccess_msg(struct gsm_bts *bts, u_int8_t msg_type,
u_int8_t *attr, int attr_len);
int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr,
int attr_len);
int abis_nm_ipaccess_restart(struct gsm_bts *bts);
int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx);
int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, u_int8_t obj_class,
u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr,
u_int8_t *attr, u_int8_t attr_len);
@@ -164,7 +164,8 @@ enum nm_evt {
EVT_STATECHG_ADM,
};
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state);
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst);
const char *nm_opstate_name(u_int8_t os);
const char *nm_avail_name(u_int8_t avail);

View File

@@ -36,6 +36,7 @@ struct bsc_msc_connection {
void (*connection_loss) (struct bsc_msc_connection *);
void (*connected) (struct bsc_msc_connection *);
struct timer_list reconnect_timer;
struct timer_list timeout_timer;
};
struct bsc_msc_connection *bsc_msc_create(const char *ip, int port);

View File

@@ -120,6 +120,9 @@ struct sccp_connections {
int crcx;
int msc_timeslot;
int bsc_timeslot;
/* timeout handling */
struct timespec creation_time;
};
/**
@@ -213,6 +216,12 @@ struct bsc_nat {
char *msc_ip;
int msc_port;
int first_contact;
struct bsc_msc_connection *msc_con;
/* timeouts */
int auth_timeout;
int ping_timeout;
int pong_timeout;
struct bsc_endpoint *bsc_endpoints;

View File

@@ -3,6 +3,8 @@
#include <sys/types.h>
struct bsc_msc_connection;
enum gsm_phys_chan_config {
GSM_PCHAN_NONE,
GSM_PCHAN_CCCH,
@@ -673,6 +675,9 @@ struct gsm_network {
char *bsc_token;
char *msc_ip;
int msc_port;
struct bsc_msc_connection *msc_con;
int ping_timeout;
int pong_timeout;
};
#define SMS_HDR_SIZE 128
@@ -774,14 +779,6 @@ const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
/* A parsed GPRS routing area */
struct gprs_ra_id {
u_int16_t mnc;
u_int16_t mcc;
u_int16_t lac;
u_int8_t rac;
};
int gsm48_ra_id_by_bts(u_int8_t *buf, struct gsm_bts *bts);
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);

View File

@@ -133,7 +133,7 @@ struct scall_signal_data {
};
struct ipacc_ack_signal_data {
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
u_int8_t msg_type;
};

View File

@@ -56,4 +56,4 @@ bsc_nat_SOURCES = nat/bsc_nat.c nat/bsc_filter.c nat/bsc_sccp.c \
nat/bsc_nat_utils.c nat/bsc_nat_vty.c nat/bsc_mgcp_utils.c \
mgcp/mgcp_protocol.c mgcp/mgcp_network.c mgcp/mgcp_vty.c \
bsc_msc.c bssap.c
bsc_nat_LDADD = libvty.a libbsc.a libsccp.a
bsc_nat_LDADD = libvty.a libbsc.a libsccp.a -lrt

View File

@@ -678,7 +678,7 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class,
new_state = *nm_state;
new_state.administrative = adm_state;
rc = nm_state_event(EVT_STATECHG_ADM, obj_class, obj, nm_state, &new_state);
rc = nm_state_event(EVT_STATECHG_ADM, obj_class, obj, nm_state, &new_state, obj_inst);
nm_state->administrative = adm_state;
@@ -732,7 +732,7 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
/* Update the operational state of a given object in our in-memory data
* structures and send an event to the higher layer */
void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state);
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state, &foh->obj_inst);
nm_state->operational = new_state.operational;
nm_state->availability = new_state.availability;
if (nm_state->administrative == 0)
@@ -1139,6 +1139,7 @@ enum sw_state {
struct abis_nm_sw {
struct gsm_bts *bts;
int trx_nr;
gsm_cbfn *cbfn;
void *cb_data;
int forced;
@@ -1592,7 +1593,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
}
/* Load the specified software into the BTS */
int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
u_int8_t win_size, int forced,
gsm_cbfn *cbfn, void *cb_data)
{
@@ -1606,6 +1607,7 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
return -EBUSY;
sw->bts = bts;
sw->trx_nr = trx_nr;
switch (bts->type) {
case GSM_BTS_TYPE_BS11:
@@ -1616,8 +1618,8 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
break;
case GSM_BTS_TYPE_NANOBTS:
sw->obj_class = NM_OC_BASEB_TRANSC;
sw->obj_instance[0] = 0x00;
sw->obj_instance[1] = 0x00;
sw->obj_instance[0] = sw->bts->nr;
sw->obj_instance[1] = sw->trx_nr;
sw->obj_instance[2] = 0xff;
break;
case GSM_BTS_TYPE_UNKNOWN:
@@ -2551,7 +2553,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event,
fle = fl_dequeue(&bs11_sw->file_list);
if (fle) {
/* start download the next file of our file list */
rc = abis_nm_software_load(bs11_sw->bts, fle->fname,
rc = abis_nm_software_load(bs11_sw->bts, 0xff, fle->fname,
bs11_sw->win_size,
bs11_sw->forced,
&bs11_swload_cbfn, bs11_sw);
@@ -2607,7 +2609,7 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
return -EINVAL;
/* start download the next file of our file list */
rc = abis_nm_software_load(bts, fle->fname, win_size, forced,
rc = abis_nm_software_load(bts, 0xff, fle->fname, win_size, forced,
bs11_swload_cbfn, bs11_sw);
talloc_free(fle);
return rc;
@@ -2775,12 +2777,12 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
case NM_MT_IPACC_RSL_CONNECT_NACK:
case NM_MT_IPACC_SET_NVATTR_NACK:
case NM_MT_IPACC_GET_NVATTR_NACK:
signal.bts = msg->trx->bts;
signal.trx = gsm_bts_trx_by_nr(msg->trx->bts, foh->obj_inst.trx_nr);
signal.msg_type = foh->msg_type;
dispatch_signal(SS_NM, S_NM_IPACC_NACK, &signal);
break;
case NM_MT_IPACC_SET_NVATTR_ACK:
signal.bts = msg->trx->bts;
signal.trx = gsm_bts_trx_by_nr(msg->trx->bts, foh->obj_inst.trx_nr);
signal.msg_type = foh->msg_type;
dispatch_signal(SS_NM, S_NM_IPACC_ACK, &signal);
break;
@@ -2866,9 +2868,16 @@ int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
}
/* restart / reboot an ip.access nanoBTS */
int abis_nm_ipaccess_restart(struct gsm_bts *bts)
int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx)
{
return __simple_cmd(bts, NM_MT_IPACC_RESTART);
struct abis_om_hdr *oh;
struct msgb *msg = nm_msgb_alloc();
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
fill_om_fom_hdr(oh, 0, NM_MT_IPACC_RESTART, NM_OC_BASEB_TRANSC,
trx->bts->nr, trx->nr, 0xff);
return abis_nm_sendmsg(trx->bts, msg);
}
int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, u_int8_t obj_class,

View File

@@ -481,7 +481,7 @@ static int handle_state_resp(enum abis_bs11_phase state)
* argument, so our swload_cbfn can distinguish
* a safety load from a regular software */
if (file_is_readable(fname_safety))
rc = abis_nm_software_load(g_bts, fname_safety,
rc = abis_nm_software_load(g_bts, 0xff, fname_safety,
win_size, param_forced,
swload_cbfn, g_bts);
else
@@ -697,7 +697,8 @@ int handle_serial_msg(struct msgb *rx_msg)
}
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_ins)
{
return 0;
}

View File

@@ -401,7 +401,8 @@ static unsigned char nanobts_attr_nsvc0[] = {
/* Callback function to be called whenever we get a GSM 12.21 state change event */
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst)
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;

View File

@@ -49,6 +49,14 @@ static void connection_loss(struct bsc_msc_connection *con)
con->connection_loss(con);
}
static void msc_con_timeout(void *_con)
{
struct bsc_msc_connection *con = _con;
LOGP(DMSC, LOGL_ERROR, "MSC Connection timeout.\n");
bsc_msc_lost(con);
}
static int bsc_msc_except(struct bsc_fd *bfd)
{
struct write_queue *wrt;
@@ -98,6 +106,7 @@ static int msc_connection_connect(struct bsc_fd *fd, unsigned int what)
fd->when = BSC_FD_READ | BSC_FD_EXCEPT;
con->is_connected = 1;
bsc_del_timer(&con->timeout_timer);
LOGP(DMSC, LOGL_NOTICE, "(Re)Connected to the MSC.\n");
if (con->connected)
con->connected(con);
@@ -165,6 +174,9 @@ int bsc_msc_connect(struct bsc_msc_connection *con)
LOGP(DMSC, LOGL_ERROR, "MSC Connection in progress\n");
fd->when = BSC_FD_WRITE;
fd->cb = msc_connection_connect;
con->timeout_timer.cb = msc_con_timeout;
con->timeout_timer.data = con;
bsc_schedule_timer(&con->timeout_timer, 20, 0);
} else if (ret < 0) {
perror("Connection failed");
connection_loss(con);

View File

@@ -30,6 +30,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#define _GNU_SOURCE
@@ -46,9 +47,12 @@
#include <openbsc/bsc_nat.h>
#include <openbsc/bsc_msc_rf.h>
#include <vty/command.h>
#include <osmocore/select.h>
#include <osmocore/talloc.h>
#include <osmocore/write_queue.h>
#include <osmocore/gsm0808.h>
#include <sccp/sccp.h>
@@ -64,22 +68,37 @@ static struct in_addr local_addr;
static LLIST_HEAD(active_connections);
static struct write_queue mgcp_agent;
static const char *rf_ctl = NULL;
static int testmode = 0;
extern int ipacc_rtp_direct;
/* msc handling */
static struct bsc_msc_connection *msc_con;
static struct timer_list msc_ping_timeout;
static struct timer_list msc_pong_timeout;
extern int bsc_bootstrap_network(int (*layer4)(struct gsm_network *, int, void *), const char *cfg_file);
extern int bsc_shutdown_net(struct gsm_network *net);
static void install_extra_commands();
struct llist_head *bsc_sccp_connections()
{
return &active_connections;
}
/*
* Having a subscriber in the lchan is used to indicate that a SACH DEACTIVATE
* should be send. We will just introduce a fake subscriber and bind it to the
* lchan.
*/
static void assign_dummy_subscr(struct gsm_lchan *lchan)
{
if (!lchan->conn.subscr) {
lchan->conn.subscr = subscr_get_or_create(bsc_gsmnet, "2323");
lchan->conn.subscr->lac = 2323;
}
}
struct bss_sccp_connection_data *bss_sccp_create_data()
{
struct bss_sccp_connection_data *data;
@@ -269,7 +288,7 @@ static int open_sccp_connection(struct msgb *layer3)
struct msgb *data;
/* When not connected to a MSC. We will simply close things down. */
if (!msc_con->is_authenticated) {
if (!bsc_gsmnet->msc_con->is_authenticated) {
LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
use_subscr_con(&layer3->lchan->conn);
put_subscr_con(&layer3->lchan->conn, 0);
@@ -313,6 +332,8 @@ static int open_sccp_connection(struct msgb *layer3)
bsc_schedule_timer(&con_data->sccp_cc_timeout, 10, 0);
/* FIXME: Use transaction for this */
/* assign a dummy subscriber */
assign_dummy_subscr(layer3->lchan);
use_subscr_con(&layer3->lchan->conn);
sccp_connection_connect(sccp_connection, &sccp_ssn_bssap, data);
msgb_free(data);
@@ -420,6 +441,9 @@ static int handle_ass_compl(struct msgb *msg)
msg->lchan->msc_data->secondary_lchan = NULL;
old_chan->msc_data = NULL;
/* assign a dummy subscriber */
assign_dummy_subscr(msg->lchan);
/* give up the old channel to not do a SACCH deactivate */
if (old_chan->conn.subscr)
subscr_put(old_chan->conn.subscr);
@@ -635,7 +659,7 @@ static void print_usage()
static int msc_queue_write(struct msgb *msg, int proto)
{
ipaccess_prepend_header(msg, proto);
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
if (write_queue_enqueue(&bsc_gsmnet->msc_con->write_queue, msg) != 0) {
LOGP(DMSC, LOGL_FATAL, "Failed to queue IPA/%d\n", proto);
msgb_free(msg);
return -1;
@@ -651,7 +675,7 @@ static int msc_sccp_do_write(struct bsc_fd *fd, struct msgb *msg)
LOGP(DMSC, LOGL_DEBUG, "Sending SCCP to MSC: %u\n", msgb_l2len(msg));
LOGP(DMI, LOGL_DEBUG, "MSC TX %s\n", hexdump(msg->l2h, msgb_l2len(msg)));
ret = write(msc_con->write_queue.bfd.fd, msg->data, msg->len);
ret = write(bsc_gsmnet->msc_con->write_queue.bfd.fd, msg->data, msg->len);
if (ret < msg->len)
perror("MSC: Failed to send SCCP");
@@ -823,9 +847,9 @@ static void initialize_if_needed(void)
struct msgb *msg;
if (!msc_con->is_authenticated) {
if (!bsc_gsmnet->msc_con->is_authenticated) {
/* send a gsm 08.08 reset message from here */
msg = bssmap_create_reset();
msg = gsm0808_create_reset();
if (!msg) {
LOGP(DMSC, LOGL_ERROR, "Failed to create the reset message.\n");
return;
@@ -833,7 +857,7 @@ static void initialize_if_needed(void)
sccp_write(msg, &sccp_ssn_bssap, &sccp_ssn_bssap, 0);
msgb_free(msg);
msc_con->is_authenticated = 1;
bsc_gsmnet->msc_con->is_authenticated = 1;
}
}
@@ -858,6 +882,32 @@ static void send_id_get_response(int fd)
msc_queue_write(msg, IPAC_PROTO_IPACCESS);
}
/*
* Send some packets to test the MSC.
*/
static void test_msc()
{
struct msgb *msg;
if (!testmode)
return;
static const uint8_t pag_resp[] = {
0x01, 0xf3, 0x26, 0x09, 0x02, 0x02, 0x04, 0x02, 0x42,
0xfe, 0x0f, 0x1f, 0x00, 0x1d, 0x57, 0x05, 0x08, 0x00,
0x72, 0xf4, 0x80, 0x10, 0x1c, 0x9c, 0x40, 0x17, 0x10,
0x06, 0x27, 0x02, 0x03, 0x30, 0x18, 0xa0, 0x08, 0x59,
0x51, 0x30, 0x10, 0x30, 0x32, 0x80, 0x06, 0x00
};
msg = msgb_alloc_headroom(4096, 128, "paging response");
if (!msg)
return;
msg->l2h = msgb_put(msg, sizeof(pag_resp));
memcpy(msg->l2h, pag_resp, sizeof(pag_resp));
msc_queue_write(msg, IPAC_PROTO_SCCP);
}
/*
* The connection to the MSC was lost and we will need to free all
* resources and then attempt to reconnect.
@@ -882,7 +932,7 @@ static void msc_connection_was_lost(struct bsc_msc_connection *msc)
static void msc_pong_timeout_cb(void *data)
{
LOGP(DMSC, LOGL_ERROR, "MSC didn't answer PING. Closing connection.\n");
bsc_msc_lost(msc_con);
bsc_msc_lost(bsc_gsmnet->msc_con);
}
static void send_ping(void)
@@ -903,17 +953,26 @@ static void send_ping(void)
static void msc_ping_timeout_cb(void *data)
{
if (bsc_gsmnet->ping_timeout < 0)
return;
send_ping();
/* send another ping in 20 seconds */
bsc_schedule_timer(&msc_ping_timeout, 20, 0);
bsc_schedule_timer(&msc_ping_timeout, bsc_gsmnet->ping_timeout, 0);
/* also start a pong timer */
bsc_schedule_timer(&msc_pong_timeout, 5, 0);
bsc_schedule_timer(&msc_pong_timeout, bsc_gsmnet->pong_timeout, 0);
}
static void msc_connection_connected(struct bsc_msc_connection *con)
{
int ret, on;
on = 1;
ret = setsockopt(con->write_queue.bfd.fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
if (ret != 0)
LOGP(DMSC, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
msc_ping_timeout_cb(con);
}
@@ -929,7 +988,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
if (!msg) {
if (error == 0) {
LOGP(DMSC, LOGL_ERROR, "The connection to the MSC was lost.\n");
bsc_msc_lost(msc_con);
bsc_msc_lost(bsc_gsmnet->msc_con);
return -1;
}
@@ -949,6 +1008,7 @@ static int ipaccess_a_fd_cb(struct bsc_fd *bfd)
initialize_if_needed();
else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
send_id_get_response(bfd->fd);
test_msc();
} else if (msg->l2h[0] == IPAC_MSGT_PONG) {
bsc_del_timer(&msc_pong_timeout);
}
@@ -974,6 +1034,7 @@ static void print_help()
printf(" -l --local=IP. The local address of the MGCP.\n");
printf(" -e --log-level number. Set a global loglevel.\n");
printf(" -r --rf-ctl NAME. A unix domain socket to listen for cmds.\n");
printf(" -t --testmode. A special mode to provoke failures at the MSC.\n");
}
static void handle_options(int argc, char** argv)
@@ -990,10 +1051,11 @@ static void handle_options(int argc, char** argv)
{"local", 1, 0, 'l'},
{"log-level", 1, 0, 'e'},
{"rf-ctl", 1, 0, 'r'},
{"testmode", 0, 0, 't'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hd:sTc:m:l:e:r:",
c = getopt_long(argc, argv, "hd:sTc:m:l:e:r:t",
long_options, &option_index);
if (c == -1)
break;
@@ -1030,6 +1092,9 @@ static void handle_options(int argc, char** argv)
case 'r':
rf_ctl = optarg;
break;
case 't':
testmode = 1;
break;
default:
/* ignore */
break;
@@ -1056,9 +1121,9 @@ static void signal_handler(int signal)
talloc_report_full(tall_bsc_ctx, stderr);
break;
case SIGUSR2:
if (!msc_con || !msc_con->is_connected)
if (!bsc_gsmnet->msc_con || !bsc_gsmnet->msc_con->is_connected)
return;
bsc_msc_lost(msc_con);
bsc_msc_lost(bsc_gsmnet->msc_con);
break;
default:
break;
@@ -1173,20 +1238,22 @@ int main(int argc, char **argv)
if (msc_address)
msc = msc_address;
msc_con = bsc_msc_create(msc, bsc_gsmnet->msc_port);
if (!msc_con) {
bsc_gsmnet->msc_con = bsc_msc_create(msc, bsc_gsmnet->msc_port);
if (!bsc_gsmnet->msc_con) {
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);
}
install_extra_commands();
msc_ping_timeout.cb = msc_ping_timeout_cb;
msc_pong_timeout.cb = msc_pong_timeout_cb;
msc_con->connection_loss = msc_connection_was_lost;
msc_con->connected = msc_connection_connected;
msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
msc_con->write_queue.write_cb = msc_sccp_do_write;
bsc_msc_connect(msc_con);
bsc_gsmnet->msc_con->connection_loss = msc_connection_was_lost;
bsc_gsmnet->msc_con->connected = msc_connection_connected;
bsc_gsmnet->msc_con->write_queue.read_cb = ipaccess_a_fd_cb;
bsc_gsmnet->msc_con->write_queue.write_cb = msc_sccp_do_write;
bsc_msc_connect(bsc_gsmnet->msc_con);
@@ -1194,3 +1261,25 @@ int main(int argc, char **argv)
bsc_select_main(0);
}
}
DEFUN(show_msc,
show_msc_cmd,
"show msc connection",
SHOW_STR "Show the status of the MSC connection.")
{
if (!bsc_gsmnet->msc_con) {
vty_out(vty, "The MSC is not yet configured.\n");
return CMD_WARNING;
}
vty_out(vty, "MSC on %s:%d is connected: %d%s\n",
bsc_gsmnet->msc_con->ip, bsc_gsmnet->msc_con->port,
bsc_gsmnet->msc_con->is_connected, VTY_NEWLINE);
return CMD_SUCCESS;
}
static void install_extra_commands()
{
install_element(VIEW_NODE, &show_msc_cmd);
}

View File

@@ -59,14 +59,14 @@ static void handle_query(struct bsc_msc_rf_conn *conn)
{
struct msgb *msg;
struct gsm_bts *bts;
char send = '0';
char send = RF_CMD_OFF;
llist_for_each_entry(bts, &conn->gsm_network->bts_list, list) {
struct gsm_bts_trx *trx;
llist_for_each_entry(trx, &bts->trx_list, list) {
if (trx->nm_state.availability == NM_AVSTATE_OK &&
trx->nm_state.operational != NM_STATE_LOCKED) {
send = '1';
send = RF_CMD_ON;
break;
}
}

View File

@@ -174,7 +174,7 @@ static int bssmap_handle_clear_command(struct sccp_connection *conn,
}
/* send the clear complete message */
resp = bssmap_create_clear_complete();
resp = gsm0808_create_clear_complete();
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Sending clear complete failed.\n");
return -1;
@@ -312,7 +312,7 @@ static void bssmap_t10_fired(void *_conn)
msc_data = conn->data_ctx;
bssmap_free_secondary(msc_data);
resp = bssmap_create_assignment_failure(
resp = gsm0808_create_assignment_failure(
GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Allocation failure: %p\n", conn);
@@ -765,36 +765,6 @@ struct msgb *bssmap_create_layer3(struct msgb *msg_l3)
return msg;
}
struct msgb *bssmap_create_reset(void)
{
struct msgb *msg = msgb_alloc(30, "bssmap: reset");
if (!msg)
return NULL;
msg->l3h = msgb_put(msg, 6);
msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
msg->l3h[1] = 0x04;
msg->l3h[2] = 0x30;
msg->l3h[3] = 0x04;
msg->l3h[4] = 0x01;
msg->l3h[5] = 0x20;
return msg;
}
struct msgb *bssmap_create_clear_complete(void)
{
struct msgb *msg = msgb_alloc(30, "bssmap: clear complete");
if (!msg)
return NULL;
msg->l3h = msgb_put(msg, 3);
msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
msg->l3h[1] = 1;
msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
return msg;
}
struct msgb *bssmap_create_cipher_complete(struct msgb *layer3)
{
struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
@@ -1005,36 +975,6 @@ struct msgb *bssmap_create_assignment_completed(struct gsm_lchan *lchan, u_int8_
return msg;
}
struct msgb *bssmap_create_assignment_failure(u_int8_t cause, u_int8_t *rr_cause)
{
u_int8_t *data;
struct msgb *msg = msgb_alloc(35, "bssmap: ass fail");
if (!msg)
return NULL;
msg->l3h = msgb_put(msg, 6);
msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
msg->l3h[1] = 0xff;
msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
msg->l3h[3] = GSM0808_IE_CAUSE;
msg->l3h[4] = 1;
msg->l3h[5] = cause;
/* RR cause 3.2.2.22 */
if (rr_cause) {
data = msgb_put(msg, 2);
data[0] = GSM0808_IE_RR_CAUSE;
data[1] = *rr_cause;
}
/* Circuit pool 3.22.45 */
/* Circuit pool list 3.2.2.46 */
/* update the size */
msg->l3h[1] = msgb_l3len(msg) - 2;
return msg;
}
struct msgb *dtap_create_msg(struct msgb *msg_l3, u_int8_t link_id)
{
struct dtap_header *header;
@@ -1312,7 +1252,7 @@ void gsm0808_send_assignment_failure(struct gsm_lchan *lchan, u_int8_t cause, u_
bsc_del_timer(&lchan->msc_data->T10);
bssmap_free_secondary(lchan->msc_data);
resp = bssmap_create_assignment_failure(cause, rr_value);
resp = gsm0808_create_assignment_failure(cause, rr_value);
if (!resp) {
LOGP(DMSC, LOGL_ERROR, "Allocation failure: %p\n", lchan_get_sccp(lchan));
return;

View File

@@ -381,6 +381,11 @@ static void _lchan_handle_release(struct gsm_lchan *lchan)
++lchan->conn.use_count;
gsm48_send_rr_release(lchan);
--lchan->conn.use_count;
/* avoid reentrancy */
subscr_put(lchan->conn.subscr);
lchan->conn.subscr = NULL;
return;
}
/* spoofed? message */

View File

@@ -321,7 +321,7 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr)
sig_data.bts = msg->lchan->ts->trx->bts;
sig_data.lchan = msg->lchan;
bts->network->stats.paging.completed++;
counter_inc(bts->network->stats.paging.completed);
dispatch_signal(SS_PAGING, S_PAGING_SUCCEEDED, &sig_data);

View File

@@ -300,6 +300,8 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->msc_ip = talloc_strdup(net, "127.0.0.1");
net->msc_port = 5000;
net->ping_timeout = 20;
net->pong_timeout = 5;
return net;
}
@@ -454,33 +456,6 @@ const char *gsm_auth_policy_name(enum gsm_auth_policy policy)
return get_value_string(auth_policy_names, policy);
}
/* this should not be here but in gsm_04_08... but that creates
in turn a dependency nightmare (abis_nm depending on 04_08, ...) */
static int gsm48_construct_ra(u_int8_t *buf, const struct gprs_ra_id *raid)
{
u_int16_t mcc = raid->mcc;
u_int16_t mnc = raid->mnc;
buf[0] = ((mcc / 100) % 10) | (((mcc / 10) % 10) << 4);
buf[1] = (mcc % 10);
/* I wonder who came up with the stupidity of encoding the MNC
* differently depending on how many digits its decimal number has! */
if (mnc < 100) {
buf[1] |= 0xf0;
buf[2] = ((mnc / 10) % 10) | ((mnc % 10) << 4);
} else {
buf[1] |= (mnc % 10) << 4;
buf[2] = ((mnc / 100) % 10) | (((mcc / 10) % 10) << 4);
}
*(u_int16_t *)(buf+3) = htons(raid->lac);
buf[5] = raid->rac;
return 6;
}
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
{
raid->mcc = bts->network->country_code;

View File

@@ -265,7 +265,7 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct msgb *msg,
trx->rsl_link = e1inp_sign_link_create(e1i_ts,
E1INP_SIGN_RSL, trx,
trx->rsl_tei, 0);
trx->rsl_link->ts->sign.delay = 10;
trx->rsl_link->ts->sign.delay = 0;
/* get rid of our old temporary bfd */
memcpy(newbfd, bfd, sizeof(*newbfd));

View File

@@ -1,8 +1,8 @@
/* ip.access nanoBTS configuration tool */
/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
* (C) 2009 by Holger Hans Peter Freyther
* (C) 2009 by On Waves
* (C) 2009,2010 by Holger Hans Peter Freyther
* (C) 2009,2010 by On Waves
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
@@ -59,7 +59,7 @@ static int sw_load_state = 0;
static int oml_state = 0;
static int dump_files = 0;
static char *firmware_analysis = NULL;
static int trx_nr = 0;
static int found_trx = 0;
struct sw_load {
u_int8_t file_id[255];
@@ -92,23 +92,23 @@ static int ipacc_msg_nack(u_int8_t mt)
return 0;
}
static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts *bts)
static void check_restart_or_exit(struct gsm_bts_trx *trx)
{
if (restart) {
abis_nm_ipaccess_restart(trx);
} else {
exit(0);
}
}
static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts_trx *trx)
{
if (sw_load_state == 1) {
fprintf(stderr, "The new software is activaed.\n");
if (restart) {
abis_nm_ipaccess_restart(bts);
} else {
exit(0);
}
check_restart_or_exit(trx);
} else if (oml_state == 1) {
fprintf(stderr, "Set the primary OML IP.\n");
if (restart) {
abis_nm_ipaccess_restart(bts);
} else {
exit(0);
}
check_restart_or_exit(trx);
}
return 0;
@@ -203,7 +203,7 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal,
return ipacc_msg_nack(ipacc_data->msg_type);
case S_NM_IPACC_ACK:
ipacc_data = signal_data;
return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->bts);
return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx);
case S_NM_TEST_REP:
return test_rep(signal_data);
case S_NM_IPACC_RESTART_ACK:
@@ -228,12 +228,12 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
void *data, void *param)
{
struct msgb *msg;
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
if (hook != GSM_HOOK_NM_SWLOAD)
return 0;
bts = (struct gsm_bts *) data;
trx = (struct gsm_bts_trx *) data;
switch (event) {
case NM_MT_LOAD_INIT_ACK:
@@ -272,7 +272,7 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
msg->l2h[1] = msgb_l3len(msg) >> 8;
msg->l2h[2] = msgb_l3len(msg) & 0xff;
printf("Foo l2h: %p l3h: %p... length l2: %u l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg));
abis_nm_ipaccess_set_nvattr(bts->c0, msg->l2h, msgb_l2len(msg));
abis_nm_ipaccess_set_nvattr(trx, msg->l2h, msgb_l2len(msg));
msgb_free(msg);
break;
case NM_MT_LOAD_END_NACK:
@@ -286,7 +286,7 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
case NM_MT_ACTIVATE_SW_ACK:
break;
case NM_MT_LOAD_SEG_ACK:
percent = abis_nm_software_load_status(bts);
percent = abis_nm_software_load_status(trx->bts);
if (percent > percent_old)
printf("Software Download Progress: %d%%\n", percent);
percent_old = percent;
@@ -299,13 +299,13 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
return 0;
}
static void bootstrap_om(struct gsm_bts *bts)
static void bootstrap_om(struct gsm_bts_trx *trx)
{
int len;
static u_int8_t buf[1024];
u_int8_t *cur = buf;
printf("OML link established\n");
printf("OML link established using TRX %d\n", trx->nr);
if (unit_id) {
len = strlen(unit_id);
@@ -317,8 +317,7 @@ static void bootstrap_om(struct gsm_bts *bts)
memcpy(buf+3, unit_id, len);
buf[3+len] = 0;
printf("setting Unit ID to '%s'\n", unit_id);
abis_nm_ipaccess_set_nvattr(gsm_bts_trx_by_nr(bts, trx_nr),
buf, 3+len+1);
abis_nm_ipaccess_set_nvattr(trx, buf, 3+len+1);
}
if (prim_oml_ip) {
struct in_addr ia;
@@ -342,7 +341,7 @@ static void bootstrap_om(struct gsm_bts *bts)
*cur++ = 0;
printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
oml_state = 1;
abis_nm_ipaccess_set_nvattr(bts->c0, buf, 3+len);
abis_nm_ipaccess_set_nvattr(trx, buf, 3+len);
}
if (nv_mask) {
len = 4;
@@ -356,13 +355,12 @@ static void bootstrap_om(struct gsm_bts *bts)
*cur++ = nv_mask >> 8;
printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
nv_flags, nv_mask);
abis_nm_ipaccess_set_nvattr(gsm_bts_trx_by_nr(bts, trx_nr),
buf, 3+len);
abis_nm_ipaccess_set_nvattr(trx, buf, 3+len);
}
if (restart && !prim_oml_ip && !software) {
printf("restarting BTS\n");
abis_nm_ipaccess_restart(bts);
abis_nm_ipaccess_restart(trx);
}
}
@@ -373,7 +371,6 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
case EVT_E1_TEI_UP:
switch (type) {
case E1INP_SIGN_OML:
bootstrap_om(trx->bts);
break;
case E1INP_SIGN_RSL:
/* FIXME */
@@ -392,22 +389,29 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
}
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_inst)
{
if (evt == EVT_STATECHG_OPER &&
if (obj_class == NM_OC_BASEB_TRANSC) {
if (!found_trx && obj_inst->trx_nr != 0xff) {
struct gsm_bts_trx *trx = container_of(obj, struct gsm_bts_trx, bb_transc);
bootstrap_om(trx);
found_trx = 1;
}
} else if (evt == EVT_STATECHG_OPER &&
obj_class == NM_OC_RADIO_CARRIER &&
new_state->availability == 3) {
struct gsm_bts_trx *trx = obj;
if (net_listen_testnr) {
u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
abis_nm_perform_test(trx->bts, 2, 0, trx->nr, 0xff,
net_listen_testnr, 1,
phys_config, sizeof(phys_config));
} else if (software) {
int rc;
printf("Attempting software upload with '%s'\n", software);
rc = abis_nm_software_load(trx->bts, software, 19, 0, swload_cbfn, trx->bts);
rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx);
if (rc < 0) {
fprintf(stderr, "Failed to start software load\n");
exit(-3);
@@ -608,7 +612,6 @@ static void print_help(void)
printf(" -d --software firmware\n");
printf(" -f --firmware firmware Provide firmware information\n");
printf(" -w --write-firmware. This will dump the firmware parts to the filesystem. Use with -f.\n");
printf(" -t --trx NR. The TRX to use for the Unit ID and NVRAM attributes.\n");
}
int main(int argc, char **argv)
@@ -643,11 +646,10 @@ int main(int argc, char **argv)
{ "software", 1, 0, 'd' },
{ "firmware", 1, 0, 'f' },
{ "write-firmware", 0, 0, 'w' },
{ "trx", 1, 0, 't' },
{ 0, 0, 0, 0 },
};
c = getopt_long(argc, argv, "u:o:rn:l:hs:d:f:wt:", long_options,
c = getopt_long(argc, argv, "u:o:rn:l:hs:d:f:w", long_options,
&option_index);
if (c == -1)
@@ -689,9 +691,6 @@ int main(int argc, char **argv)
case 'w':
dump_files = 1;
break;
case 't':
trx_nr = atoi(optarg);
break;
case 'h':
print_usage();
print_help();

View File

@@ -135,7 +135,7 @@ static struct msgb *mgcp_msgb_alloc(void)
struct msgb *msg;
msg = msgb_alloc_headroom(4096, 128, "MGCP msg");
if (!msg)
LOGP(DMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
LOGP(DMGCP, LOGL_ERROR, "Failed to msgb for MGCP data.\n");
return msg;
}

View File

@@ -23,6 +23,7 @@
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
@@ -49,12 +50,15 @@
#include <sccp/sccp.h>
#define SCCP_CLOSE_TIME 20
#define SCCP_CLOSE_TIME_TIMEOUT 19
struct log_target *stderr_target;
static const char *config_file = "bsc-nat.cfg";
static struct in_addr local_addr;
static struct bsc_msc_connection *msc_con;
static struct bsc_fd bsc_listen;
static const char *msc_ip = NULL;
static struct timer_list sccp_close;
static struct bsc_nat *nat;
@@ -76,7 +80,8 @@ struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num)
* below are stubs we need to link
*/
int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state)
struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
struct abis_om_obj_inst *obj_ins)
{
return -1;
}
@@ -91,7 +96,7 @@ int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
static void queue_for_msc(struct bsc_msc_connection *con, struct msgb *msg)
{
if (write_queue_enqueue(&msc_con->write_queue, msg) != 0) {
if (write_queue_enqueue(&nat->msc_con->write_queue, msg) != 0) {
LOGP(DINP, LOGL_ERROR, "Failed to enqueue the write.\n");
msgb_free(msg);
}
@@ -138,13 +143,16 @@ static void bsc_ping_timeout(void *_bsc)
{
struct bsc_connection *bsc = _bsc;
if (bsc->nat->ping_timeout < 0)
return;
send_ping(bsc);
/* send another ping in 20 seconds */
bsc_schedule_timer(&bsc->ping_timeout, 20, 0);
bsc_schedule_timer(&bsc->ping_timeout, bsc->nat->ping_timeout, 0);
/* also start a pong timer */
bsc_schedule_timer(&bsc->pong_timeout, 5, 0);
bsc_schedule_timer(&bsc->pong_timeout, bsc->nat->pong_timeout, 0);
}
static void start_ping_pong(struct bsc_connection *bsc)
@@ -203,7 +211,7 @@ static void nat_send_rlsd(struct sccp_connections *conn)
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
queue_for_msc(msc_con, msg);
queue_for_msc(nat->msc_con, msg);
}
static void nat_send_rlc(struct sccp_source_reference *src,
@@ -226,7 +234,7 @@ static void nat_send_rlc(struct sccp_source_reference *src,
ipaccess_prepend_header(msg, IPAC_PROTO_SCCP);
queue_for_msc(msc_con, msg);
queue_for_msc(nat->msc_con, msg);
}
static void send_mgcp_reset(struct bsc_connection *bsc)
@@ -249,7 +257,7 @@ static void initialize_msc_if_needed()
return;
nat->first_contact = 1;
msc_send_reset(msc_con);
msc_send_reset(nat->msc_con);
}
/*
@@ -419,7 +427,7 @@ static void msc_send_reset(struct bsc_msc_connection *msc_con)
msg->l2h = msgb_put(msg, sizeof(reset));
memcpy(msg->l2h, reset, msgb_l2len(msg));
queue_for_msc(msc_con, msg);
queue_for_msc(nat->msc_con, msg);
LOGP(DMSC, LOGL_NOTICE, "Scheduled GSM0808 reset msg for the MSC.\n");
}
@@ -436,7 +444,7 @@ static int ipaccess_msc_read_cb(struct bsc_fd *bfd)
else
LOGP(DNAT, LOGL_ERROR, "Failed to parse ip access message: %d\n", error);
bsc_msc_lost(msc_con);
bsc_msc_lost(nat->msc_con);
return -1;
}
@@ -540,13 +548,15 @@ static void ipaccess_auth_bsc(struct tlv_parsed *tvp, struct bsc_connection *bsc
bsc->authenticated = 1;
bsc->cfg = conf;
bsc_del_timer(&bsc->id_timeout);
LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d\n", conf->nr, conf->lac);
LOGP(DNAT, LOGL_NOTICE, "Authenticated bsc nr: %d lac: %d on fd %d\n",
conf->nr, conf->lac, bsc->write_queue.bfd.fd);
start_ping_pong(bsc);
return;
}
}
LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s.\n", token);
LOGP(DNAT, LOGL_ERROR, "No bsc found for token %s on fd: %d.\n", token,
bsc->write_queue.bfd.fd);
}
static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
@@ -621,7 +631,7 @@ static int forward_sccp_to_msc(struct bsc_connection *bsc, struct msgb *msg)
}
/* send the non-filtered but maybe modified msg */
queue_for_msc(msc_con, msg);
queue_for_msc(nat->msc_con, msg);
talloc_free(parsed);
return 0;
@@ -711,17 +721,17 @@ static int ipaccess_bsc_write_cb(struct bsc_fd *bfd, struct msgb *msg)
static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
{
struct bsc_connection *bsc;
int ret;
int fd, rc, on;
struct sockaddr_in sa;
socklen_t sa_len = sizeof(sa);
if (!(what & BSC_FD_READ))
return 0;
ret = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
if (ret < 0) {
fd = accept(bfd->fd, (struct sockaddr *) &sa, &sa_len);
if (fd < 0) {
perror("accept");
return ret;
return fd;
}
/* count the reconnect */
@@ -730,12 +740,17 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
/*
* if we are not connected to a msc... just close the socket
*/
if (!msc_con->is_connected) {
if (!nat->msc_con->is_connected) {
LOGP(DNAT, LOGL_NOTICE, "Disconnecting BSC due lack of MSC connection.\n");
close(ret);
close(fd);
return 0;
}
on = 1;
rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
if (rc != 0)
LOGP(DNAT, LOGL_ERROR, "Failed to set TCP_NODELAY: %s\n", strerror(errno));
/* todo... do something with the connection */
/* todo... use GNUtls to see if we want to trust this as a BTS */
@@ -745,23 +760,24 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
bsc = bsc_connection_alloc(nat);
if (!bsc) {
LOGP(DNAT, LOGL_ERROR, "Failed to allocate BSC struct.\n");
close(ret);
close(fd);
return -1;
}
bsc->write_queue.bfd.data = bsc;
bsc->write_queue.bfd.fd = ret;
bsc->write_queue.bfd.fd = fd;
bsc->write_queue.read_cb = ipaccess_bsc_read_cb;
bsc->write_queue.write_cb = ipaccess_bsc_write_cb;
bsc->write_queue.bfd.when = BSC_FD_READ;
if (bsc_register_fd(&bsc->write_queue.bfd) < 0) {
LOGP(DNAT, LOGL_ERROR, "Failed to register BSC fd.\n");
close(ret);
close(fd);
talloc_free(bsc);
return -2;
}
LOGP(DNAT, LOGL_NOTICE, "Registered new BSC\n");
LOGP(DNAT, LOGL_NOTICE, "BSC connection on %d with IP: %s\n",
fd, inet_ntoa(sa.sin_addr));
llist_add(&bsc->list_entry, &nat->bsc_connections);
send_id_ack(bsc);
send_id_req(bsc);
@@ -772,7 +788,7 @@ static int ipaccess_listen_bsc_cb(struct bsc_fd *bfd, unsigned int what)
*/
bsc->id_timeout.data = bsc;
bsc->id_timeout.cb = ipaccess_close_bsc;
bsc_schedule_timer(&bsc->id_timeout, 2, 0);
bsc_schedule_timer(&bsc->id_timeout, nat->auth_timeout, 0);
return 0;
}
@@ -893,6 +909,29 @@ static void signal_handler(int signal)
}
}
static void sccp_close_unconfirmed(void *_data)
{
struct sccp_connections *conn, *tmp1;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
llist_for_each_entry_safe(conn, tmp1, &nat->sccp_connections, list_entry) {
if (conn->has_remote_ref)
continue;
int diff = (now.tv_sec - conn->creation_time.tv_sec) / 60;
if (diff < SCCP_CLOSE_TIME_TIMEOUT)
continue;
LOGP(DNAT, LOGL_ERROR, "SCCP connection 0x%x/0x%x was never confirmed.\n",
sccp_src_ref_to_int(&conn->real_ref),
sccp_src_ref_to_int(&conn->patched_ref));
sccp_connection_destroy(conn);
}
bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
}
extern void *tall_msgb_ctx;
extern void *tall_ctr_ctx;
static void talloc_init_ctx()
@@ -949,16 +988,16 @@ int main(int argc, char** argv)
return -4;
/* connect to the MSC */
msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port);
if (!msc_con) {
nat->msc_con = bsc_msc_create(nat->msc_ip, nat->msc_port);
if (!nat->msc_con) {
fprintf(stderr, "Creating a bsc_msc_connection failed.\n");
exit(1);
}
msc_con->connection_loss = msc_connection_was_lost;
msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
bsc_msc_connect(msc_con);
nat->msc_con->connection_loss = msc_connection_was_lost;
nat->msc_con->write_queue.read_cb = ipaccess_msc_read_cb;
nat->msc_con->write_queue.write_cb = ipaccess_msc_write_cb;;
bsc_msc_connect(nat->msc_con);
/* wait for the BSC */
if (listen_for_bsc(&bsc_listen, &local_addr, 5000) < 0) {
@@ -970,6 +1009,11 @@ int main(int argc, char** argv)
signal(SIGUSR1, &signal_handler);
signal(SIGPIPE, SIG_IGN);
/* recycle timer */
sccp_close.cb = sccp_close_unconfirmed;
sccp_close.data = NULL;
bsc_schedule_timer(&sccp_close, SCCP_CLOSE_TIME, 0);
while (1) {
bsc_select_main(0);
}

View File

@@ -53,6 +53,9 @@ struct bsc_nat *bsc_nat_alloc(void)
nat->stats.msc.reconn = counter_alloc("nat.msc.conn");
nat->msc_ip = talloc_strdup(nat, "127.0.0.1");
nat->msc_port = 5000;
nat->auth_timeout = 2;
nat->ping_timeout = 20;
nat->pong_timeout = 5;
return nat;
}

View File

@@ -24,6 +24,7 @@
#include <vty/vty.h>
#include <openbsc/bsc_nat.h>
#include <openbsc/bsc_msc.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/mgcp.h>
#include <openbsc/vty.h>
@@ -57,6 +58,9 @@ static int config_write_nat(struct vty *vty)
vty_out(vty, " insi deny %s%s", _nat->imsi_deny, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", _nat->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", _nat->msc_port, VTY_NEWLINE);
vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -178,6 +182,22 @@ DEFUN(show_stats,
return CMD_SUCCESS;
}
DEFUN(show_msc,
show_msc_cmd,
"show msc connection",
SHOW_STR "Show the status of the MSC connection.")
{
if (!_nat->msc_con) {
vty_out(vty, "The MSC is not yet configured.\n");
return CMD_WARNING;
}
vty_out(vty, "MSC on %s:%d is connected: %d%s\n",
_nat->msc_con->ip, _nat->msc_con->port,
_nat->msc_con->is_connected, VTY_NEWLINE);
return CMD_SUCCESS;
}
DEFUN(close_bsc,
close_bsc_cmd,
"close bsc connection BSC_NR",
@@ -256,6 +276,33 @@ DEFUN(cfg_nat_msc_port,
return CMD_SUCCESS;
}
DEFUN(cfg_nat_auth_time,
cfg_nat_auth_time_cmd,
"timeout auth <1-256>",
"The time to wait for an auth response.")
{
_nat->auth_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_ping_time,
cfg_nat_ping_time_cmd,
"timeout ping NR",
"Send a ping every NR seconds. Negative to disable.")
{
_nat->ping_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_nat_pong_time,
cfg_nat_pong_time_cmd,
"timeout pong NR",
"Wait NR seconds for the PONG response. Should be smaller than ping.")
{
_nat->pong_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
/* per BSC configuration */
DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
{
@@ -376,6 +423,7 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(VIEW_NODE, &show_bsc_cfg_cmd);
install_element(VIEW_NODE, &show_stats_cmd);
install_element(VIEW_NODE, &close_bsc_cmd);
install_element(VIEW_NODE, &show_msc_cmd);
openbsc_vty_add_cmds();
@@ -387,6 +435,9 @@ int bsc_nat_vty_init(struct bsc_nat *nat)
install_element(NAT_NODE, &cfg_nat_imsi_deny_cmd);
install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
install_element(NAT_NODE, &cfg_nat_ping_time_cmd);
install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
/* BSC subgroups */
install_element(NAT_NODE, &cfg_bsc_cmd);

View File

@@ -28,6 +28,7 @@
#include <osmocore/talloc.h>
#include <string.h>
#include <time.h>
static int equal(struct sccp_source_reference *ref1, struct sccp_source_reference *ref2)
{
@@ -97,10 +98,12 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
LOGP(DNAT, LOGL_ERROR, "BSC %d reused src ref: %d and we failed to generate a new id.\n",
bsc->cfg->nr, sccp_src_ref_to_int(parsed->src_local_ref));
bsc_mgcp_dlcx(conn);
llist_del(&conn->list_entry);
talloc_free(conn);
return -1;
} else {
clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
bsc_mgcp_dlcx(conn);
return 0;
}
@@ -114,6 +117,7 @@ int create_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc
}
conn->bsc = bsc;
clock_gettime(CLOCK_MONOTONIC, &conn->creation_time);
conn->real_ref = *parsed->src_local_ref;
if (assign_src_local_reference(&conn->patched_ref, bsc->nat) != 0) {
LOGP(DNAT, LOGL_ERROR, "Failed to assign a ref.\n");

View File

@@ -359,6 +359,8 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
bts->rach_ldavg_slots, VTY_NEWLINE);
if (bts->si_common.rach_control.cell_bar)
vty_out(vty, " cell barred 1%s", VTY_NEWLINE);
if ((bts->si_common.rach_control.t2 & 0x4) == 0)
vty_out(vty, " rach emergency call allowed 1%s", VTY_NEWLINE);
if (is_ipaccess_bts(bts)) {
vty_out(vty, " ip.access unit_id %u %u%s",
bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE);
@@ -480,6 +482,8 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " bsc_token %s%s", gsmnet->bsc_token, VTY_NEWLINE);
vty_out(vty, " msc ip %s%s", gsmnet->msc_ip, VTY_NEWLINE);
vty_out(vty, " msc port %d%s", gsmnet->msc_port, VTY_NEWLINE);
vty_out(vty, " timeout ping %d%s", gsmnet->ping_timeout, VTY_NEWLINE);
vty_out(vty, " timeout pong %d%s", gsmnet->pong_timeout, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -1335,6 +1339,23 @@ DEFUN(cfg_net_msc_port,
return CMD_SUCCESS;
}
DEFUN(cfg_net_ping_time,
cfg_net_ping_time_cmd,
"timeout ping NR",
"Set the PING interval, negative for not sending PING")
{
gsmnet->ping_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
DEFUN(cfg_net_pong_time,
cfg_net_pong_time_cmd,
"timeout pong NR",
"Set the time to wait for a PONG.")
{
gsmnet->pong_timeout = atoi(argv[0]);
return CMD_SUCCESS;
}
#define DECLARE_TIMER(number, doc) \
DEFUN(cfg_net_T##number, \
@@ -1642,6 +1663,20 @@ DEFUN(cfg_bts_cell_barred, cfg_bts_cell_barred_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_rach_ec_allowed, cfg_bts_rach_ec_allowed_cmd,
"rach emergency call allowed (0|1)",
"Should this cell allow emergency calls?")
{
struct gsm_bts *bts = vty->index;
if (atoi(argv[0]) == 0)
bts->si_common.rach_control.t2 |= 0x4;
else
bts->si_common.rach_control.t2 &= ~0x4;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_ms_max_power, cfg_bts_ms_max_power_cmd,
"ms max power <0-40>",
"Maximum transmit power of the MS")
@@ -2070,6 +2105,8 @@ int bsc_vty_init(struct gsm_network *net)
install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd);
install_element(GSMNET_NODE, &cfg_net_msc_ip_cmd);
install_element(GSMNET_NODE, &cfg_net_msc_port_cmd);
install_element(GSMNET_NODE, &cfg_net_ping_time_cmd);
install_element(GSMNET_NODE, &cfg_net_pong_time_cmd);
install_element(GSMNET_NODE, &cfg_bts_cmd);
install_node(&bts_node, config_write_bts);
@@ -2090,6 +2127,7 @@ int bsc_vty_init(struct gsm_network *net)
install_element(BTS_NODE, &cfg_bts_rach_nm_b_thresh_cmd);
install_element(BTS_NODE, &cfg_bts_rach_nm_ldavg_cmd);
install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
install_element(BTS_NODE, &cfg_bts_rach_ec_allowed_cmd);
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);

View File

@@ -13,5 +13,5 @@ bsc_nat_test_SOURCES = bsc_nat_test.c \
$(top_srcdir)/src/mgcp/mgcp_protocol.c \
$(top_srcdir)/src/mgcp/mgcp_network.c \
$(top_srcdir)/src/bssap.c
bsc_nat_test_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libsccp.a $(LIBOSMOCORE_LIBS)
bsc_nat_test_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libsccp.a $(LIBOSMOCORE_LIBS) -lrt