mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
synced 2025-11-02 04:53:24 +00:00
Compare commits
24 Commits
on-waves/0
...
on-waves/0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c8af75c94 | ||
|
|
e4b33be6fc | ||
|
|
cc7461cefc | ||
|
|
e174061d17 | ||
|
|
6e1c3412ae | ||
|
|
bff54b3e00 | ||
|
|
e75eb4ca25 | ||
|
|
566737a4b8 | ||
|
|
2b7350240d | ||
|
|
d76b53c00e | ||
|
|
9c9ef7796a | ||
|
|
49fcc8fc90 | ||
|
|
51a4bcc96a | ||
|
|
d6238120dd | ||
|
|
7407aec921 | ||
|
|
e575ce69ce | ||
|
|
c1ca0ff091 | ||
|
|
661e68b78f | ||
|
|
376e146cfb | ||
|
|
eb3ab2f85b | ||
|
|
ebc38e4f26 | ||
|
|
e2ab44a439 | ||
|
|
8b3cced773 | ||
|
|
3d1b0770f4 |
@@ -1,7 +1,6 @@
|
||||
dnl Process this file with autoconf to produce a configure script
|
||||
AC_INIT
|
||||
|
||||
AM_INIT_AUTOMAKE(openbsc, 0.3.99.6onwaves)
|
||||
AC_INIT(openbsc, 0.3.99.10onwaves)
|
||||
AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
|
||||
|
||||
dnl kernel style compile messages
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -120,6 +120,9 @@ struct sccp_connections {
|
||||
int crcx;
|
||||
int msc_timeslot;
|
||||
int bsc_timeslot;
|
||||
|
||||
/* timeout handling */
|
||||
struct timespec creation_time;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -213,6 +216,7 @@ struct bsc_nat {
|
||||
char *msc_ip;
|
||||
int msc_port;
|
||||
int first_contact;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
|
||||
/* timeouts */
|
||||
int auth_timeout;
|
||||
|
||||
@@ -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,7 @@ struct gsm_network {
|
||||
char *bsc_token;
|
||||
char *msc_ip;
|
||||
int msc_port;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
int ping_timeout;
|
||||
int pong_timeout;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -47,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>
|
||||
|
||||
@@ -65,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;
|
||||
@@ -270,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);
|
||||
@@ -314,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);
|
||||
@@ -421,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);
|
||||
@@ -636,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;
|
||||
@@ -652,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");
|
||||
|
||||
@@ -824,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;
|
||||
@@ -834,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,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.
|
||||
@@ -883,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)
|
||||
@@ -939,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;
|
||||
}
|
||||
|
||||
@@ -959,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);
|
||||
}
|
||||
@@ -984,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)
|
||||
@@ -1000,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;
|
||||
@@ -1040,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;
|
||||
@@ -1066,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;
|
||||
@@ -1183,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);
|
||||
|
||||
|
||||
|
||||
@@ -1204,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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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];
|
||||
@@ -299,13 +299,14 @@ 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;
|
||||
struct gsm_bts *bts = trx->bts;
|
||||
|
||||
printf("OML link established\n");
|
||||
printf("OML link established using TRX %d\n", trx->nr);
|
||||
|
||||
if (unit_id) {
|
||||
len = strlen(unit_id);
|
||||
@@ -317,8 +318,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;
|
||||
@@ -356,8 +356,7 @@ 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) {
|
||||
@@ -373,7 +372,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,9 +390,16 @@ 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;
|
||||
@@ -608,7 +613,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 +647,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 +692,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();
|
||||
|
||||
@@ -50,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;
|
||||
@@ -77,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;
|
||||
}
|
||||
@@ -92,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);
|
||||
}
|
||||
@@ -207,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,
|
||||
@@ -230,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)
|
||||
@@ -253,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -423,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");
|
||||
}
|
||||
@@ -440,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;
|
||||
}
|
||||
|
||||
@@ -627,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;
|
||||
|
||||
@@ -717,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, on;
|
||||
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 */
|
||||
@@ -736,15 +740,15 @@ 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;
|
||||
ret = setsockopt(bfd->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
|
||||
if (ret != 0)
|
||||
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 */
|
||||
@@ -756,24 +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, "BSC connection on %d with IP: %s\n",
|
||||
ret, inet_ntoa(sa.sin_addr));
|
||||
fd, inet_ntoa(sa.sin_addr));
|
||||
llist_add(&bsc->list_entry, &nat->bsc_connections);
|
||||
send_id_ack(bsc);
|
||||
send_id_req(bsc);
|
||||
@@ -905,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()
|
||||
@@ -961,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) {
|
||||
@@ -982,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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -181,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",
|
||||
@@ -406,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();
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user