Merge branch 'master' of git.osmocom.org:openbsc
This commit is contained in:
commit
901d57db07
|
@ -31,8 +31,8 @@ struct gsm_subscriber;
|
|||
|
||||
/* one time initialisation */
|
||||
int db_init(const char *name);
|
||||
int db_prepare();
|
||||
int db_fini();
|
||||
int db_prepare(void);
|
||||
int db_fini(void);
|
||||
|
||||
/* subscriber management */
|
||||
struct gsm_subscriber *db_create_subscriber(struct gsm_network *net,
|
||||
|
|
|
@ -35,6 +35,7 @@ enum {
|
|||
DLLC,
|
||||
DSNDCP,
|
||||
DNAT,
|
||||
DCTRL,
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ struct sgsn_mm_ctx {
|
|||
/* CKSN */
|
||||
enum gprs_ciph_algo ciph_algo;
|
||||
struct {
|
||||
uint8_t buf[14]; /* 10.5.5.12a */
|
||||
uint8_t buf[52]; /* 10.5.5.12a */
|
||||
uint8_t len;
|
||||
} ms_radio_access_capa;
|
||||
struct {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#ifndef _GSM_04_08_H
|
||||
#define _GSM_04_08_H
|
||||
|
||||
#include <openbsc/meas_rep.h>
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <openbsc/meas_rep.h>
|
||||
|
||||
struct msgb;
|
||||
struct gsm_bts;
|
||||
|
@ -31,7 +32,8 @@ int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
|||
int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);
|
||||
int gsm0408_new_conn(struct gsm_subscriber_connection *conn);
|
||||
enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra);
|
||||
enum gsm_chreq_reason_t get_reason_by_chreq(uint8_t ra, int neci);
|
||||
/* don't use "enum gsm_chreq_reason_t" to avoid circular dependency */
|
||||
int get_reason_by_chreq(uint8_t ra, int neci);
|
||||
void gsm_net_update_ctype(struct gsm_network *net);
|
||||
|
||||
int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
|
||||
|
|
|
@ -82,7 +82,7 @@ struct mgcp_trunk_config;
|
|||
typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
|
||||
typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
|
||||
typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
|
||||
typedef int (*mgcp_reset)(struct mgcp_config *cfg);
|
||||
typedef int (*mgcp_reset)(struct mgcp_trunk_config *cfg);
|
||||
|
||||
#define PORT_ALLOC_STATIC 0
|
||||
#define PORT_ALLOC_DYNAMIC 1
|
||||
|
|
|
@ -65,7 +65,7 @@ struct osmo_msc_data {
|
|||
char *mid_call_txt;
|
||||
int mid_call_timeout;
|
||||
char *rf_ctrl_name;
|
||||
struct osmo_bsc_rf *rf_ctl;
|
||||
struct osmo_bsc_rf *rf_ctrl;
|
||||
|
||||
/* ussd welcome text */
|
||||
char *ussd_welcome_txt;
|
||||
|
|
|
@ -68,4 +68,6 @@ void paging_update_buffer_space(struct gsm_bts *bts, uint16_t);
|
|||
/* pending paging requests */
|
||||
unsigned int paging_pending_requests_nr(struct gsm_bts *bts);
|
||||
|
||||
void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/process.h>
|
||||
|
||||
#include <openbsc/signal.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
|
|
@ -675,8 +675,9 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
|
|||
/* MS Radio Access Capability 10.5.5.12a */
|
||||
ms_ra_acc_cap_len = *cur++;
|
||||
ms_ra_acc_cap = cur;
|
||||
if (ms_ra_acc_cap_len > 51)
|
||||
if (ms_ra_acc_cap_len > 52)
|
||||
goto err_inval;
|
||||
cur += ms_ra_acc_cap_len;
|
||||
|
||||
/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
|
||||
|
||||
|
@ -735,8 +736,10 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
|
|||
ctx->cell_id = cid;
|
||||
/* Update MM Context with other data */
|
||||
ctx->drx_parms = drx_par;
|
||||
ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
|
||||
memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap, ms_ra_acc_cap_len);
|
||||
ctx->ms_radio_access_capa.len = OSMO_MIN(ms_ra_acc_cap_len,
|
||||
sizeof((ctx->ms_radio_access_capa.buf)));
|
||||
memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap,
|
||||
ctx->ms_radio_access_capa.len);
|
||||
ctx->ms_network_capa.len = msnc_len;
|
||||
memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
|
||||
|
||||
|
@ -754,7 +757,7 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
|
|||
GPRS_ALGO_GEA0, NULL);
|
||||
|
||||
DEBUGPC(DMM, "\n");
|
||||
return ctx ? gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT) : 0;
|
||||
return gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT);
|
||||
|
||||
err_inval:
|
||||
DEBUGPC(DMM, "\n");
|
||||
|
@ -910,6 +913,9 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
|
|||
/* MS Radio Access Capability 10.5.5.12a */
|
||||
ms_ra_acc_cap_len = *cur++;
|
||||
ms_ra_acc_cap = cur;
|
||||
if (ms_ra_acc_cap_len > 52)
|
||||
return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_PROTO_ERR_UNSPEC);
|
||||
cur += ms_ra_acc_cap_len;
|
||||
|
||||
/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
|
||||
* DRX parameter, MS network capability */
|
||||
|
|
|
@ -696,7 +696,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
|
|||
struct gprs_llc_llme *llme;
|
||||
/* FIXME: don't use the TLLI but the 0xFFFF unassigned? */
|
||||
llme = llme_alloc(msgb_tlli(msg));
|
||||
LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x08x, "
|
||||
LOGP(DLLC, LOGL_DEBUG, "LLC RX: unknown TLLI 0x%08x, "
|
||||
"creating LLME on the fly\n", msgb_tlli(msg));
|
||||
lle = &llme->lle[llhp.sapi];
|
||||
} else {
|
||||
|
|
|
@ -500,8 +500,6 @@ int sgsn_rx_sndcp_ud_ind(struct gprs_ra_id *ra_id, int32_t tlli, uint8_t nsapi,
|
|||
rate_ctr_add(&mmctx->ctrg->ctr[GMM_CTR_BYTES_UDATA_IN], npdu_len);
|
||||
|
||||
return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
|
||||
|
||||
return gtp_data_req(pdp->ggsn->gsn, pdp->lib, npdu, npdu_len);
|
||||
}
|
||||
|
||||
/* libgtp select loop integration */
|
||||
|
|
|
@ -281,5 +281,6 @@ int main(int argc, char **argv)
|
|||
exit(3);
|
||||
}
|
||||
|
||||
/* not reached */
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -59,9 +59,9 @@ int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned int
|
|||
}
|
||||
|
||||
if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) {
|
||||
fprintf(stderr, "Wrong more magic. Got: 0x%x %x %x %x\n",
|
||||
fprintf(stderr, "Wrong more magic. Got: 0x%x 0x%x vs. 0x%x 0x%x\n",
|
||||
firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff,
|
||||
firmware_header->more_magic[2] & 0xff, firmware_header->more_magic[3] & 0xff);
|
||||
more_magic[0], more_magic[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ struct ipa_bts_conn {
|
|||
uint16_t gprs_orig_port;
|
||||
uint32_t gprs_orig_ip;
|
||||
|
||||
char *id_tags[0xff];
|
||||
char *id_tags[256];
|
||||
uint8_t *id_resp;
|
||||
unsigned int id_resp_len;
|
||||
};
|
||||
|
@ -488,7 +488,7 @@ static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (trx_id > MAX_TRX) {
|
||||
if (trx_id >= MAX_TRX) {
|
||||
LOGP(DINP, LOGL_ERROR, "We don't support more "
|
||||
"than %u TRX\n", MAX_TRX);
|
||||
return -EINVAL;
|
||||
|
@ -1076,7 +1076,7 @@ static void signal_handler(int signal)
|
|||
}
|
||||
}
|
||||
|
||||
static void print_help()
|
||||
static void print_help(void)
|
||||
{
|
||||
printf(" ipaccess-proxy is a proxy BTS.\n");
|
||||
printf(" -h --help. This help text.\n");
|
||||
|
@ -1090,7 +1090,7 @@ static void print_help()
|
|||
printf(" -V --version. Print the version of OpenBSC.\n");
|
||||
}
|
||||
|
||||
static void print_usage()
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf("Usage: ipaccess-proxy [options]\n");
|
||||
}
|
||||
|
|
|
@ -776,7 +776,7 @@ static int sw_load_segment(struct abis_nm_sw *sw)
|
|||
char seg_buf[256];
|
||||
char *line_buf = seg_buf+2;
|
||||
unsigned char *tlv;
|
||||
uint8_t len;
|
||||
int len;
|
||||
|
||||
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
|
||||
|
||||
|
|
|
@ -427,7 +427,7 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
|
|||
*/
|
||||
msgb_v_put(msg, RSL_IE_CHAN_IDENT);
|
||||
len = msgb_put(msg, 1);
|
||||
msgb_tlv_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
|
||||
msgb_tv_fixed_put(msg, GSM48_IE_CHANDESC_2, sizeof(cd), (const uint8_t *) &cd);
|
||||
|
||||
if (lchan->ts->hopping.enabled)
|
||||
msgb_tlv_put(msg, GSM48_IE_MA_AFTER, lchan->ts->hopping.ma_len,
|
||||
|
|
|
@ -406,6 +406,9 @@ static int bootstrap_bts(struct gsm_bts *bts)
|
|||
|
||||
bts->si_common.ncc_permitted = 0xff;
|
||||
|
||||
/* Initialize the BTS state */
|
||||
gsm_bts_mo_reset(bts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -189,9 +189,9 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
|
|||
dump_pchan_load_vty(vty, " ", &pl);
|
||||
|
||||
/* show rf */
|
||||
if (net->msc_data && net->msc_data->rf_ctl)
|
||||
if (net->msc_data && net->msc_data->rf_ctrl)
|
||||
vty_out(vty, " Last RF Command: %s%s",
|
||||
net->msc_data->rf_ctl->last_state_command,
|
||||
net->msc_data->rf_ctrl->last_state_command,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
|
||||
|
@ -1055,11 +1055,14 @@ DEFUN(show_e1ts,
|
|||
}
|
||||
if (argc >= 1) {
|
||||
int num = atoi(argv[0]);
|
||||
llist_for_each_entry(line, &e1inp_line_list, list) {
|
||||
if (line->num == num)
|
||||
struct e1inp_line *l;
|
||||
llist_for_each_entry(l, &e1inp_line_list, list) {
|
||||
if (l->num == num) {
|
||||
line = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!line || line->num != num) {
|
||||
if (!line) {
|
||||
vty_out(vty, "E1 line %s is invalid%s",
|
||||
argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
|
@ -1067,7 +1070,7 @@ DEFUN(show_e1ts,
|
|||
}
|
||||
if (argc >= 2) {
|
||||
ts_nr = atoi(argv[1]);
|
||||
if (ts_nr > NUM_E1_TS) {
|
||||
if (ts_nr >= NUM_E1_TS) {
|
||||
vty_out(vty, "E1 timeslot %s is invalid%s",
|
||||
argv[1], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
|
@ -1157,7 +1160,7 @@ DEFUN(cfg_net_ncc,
|
|||
|
||||
DEFUN(cfg_net_mnc,
|
||||
cfg_net_mnc_cmd,
|
||||
"mobile network code <1-999>",
|
||||
"mobile network code <0-999>",
|
||||
"Set the GSM mobile network code")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
|
|
|
@ -190,7 +190,7 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, uint8_t ra)
|
|||
return GSM_LCHAN_SDCCH;
|
||||
}
|
||||
|
||||
enum gsm_chreq_reason_t get_reason_by_chreq(uint8_t ra, int neci)
|
||||
int get_reason_by_chreq(uint8_t ra, int neci)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
|
|
@ -405,3 +405,17 @@ unsigned int paging_pending_requests_nr(struct gsm_bts *bts)
|
|||
|
||||
return requests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find any paging data for the given subscriber at the given BTS.
|
||||
*/
|
||||
void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr)
|
||||
{
|
||||
struct gsm_paging_request *req;
|
||||
|
||||
llist_for_each_entry(req, &bts->paging.pending_requests, entry)
|
||||
if (req->subscr == subscr)
|
||||
return req->cbfn_param;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -175,6 +175,11 @@ static const struct log_info_cat default_categories[] = {
|
|||
.description = "GSM 08.08 NAT/Multipkexer",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
[DCTRL] = {
|
||||
.name = "DCTRL",
|
||||
.description = "Control interface",
|
||||
.enabled = 1, .loglevel = LOGL_NOTICE,
|
||||
},
|
||||
};
|
||||
|
||||
enum log_filter {
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
|
||||
{
|
||||
mo->nm_state.administrative = NM_STATE_NULL;
|
||||
mo->nm_state.operational = NM_OPSTATE_NULL;
|
||||
mo->nm_state.availability = NM_AVSTATE_POWER_OFF;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -365,7 +366,7 @@ static char *get_all_rate_ctr_in_group(const struct rate_ctr_group *ctrg, int in
|
|||
return NULL;
|
||||
|
||||
for (i=0;i<ctrg->desc->num_ctr;i++) {
|
||||
counters = talloc_asprintf_append(counters, "\n%s.%u.%s %lu",
|
||||
counters = talloc_asprintf_append(counters, "\n%s.%u.%s %"PRIu64,
|
||||
ctrg->desc->group_name_prefix, ctrg->idx,
|
||||
ctrg->desc->ctr_desc[i].name,
|
||||
get_rate_ctr_value(&ctrg->ctr[i], intv));
|
||||
|
|
|
@ -111,9 +111,8 @@ int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg)
|
|||
uint16_t _bvci = htons(*bvci);
|
||||
msgb_tvlv_put(msg, BSSGP_IE_BVCI, 2, (uint8_t *) &_bvci);
|
||||
}
|
||||
if (orig_msg)
|
||||
msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR,
|
||||
msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
|
||||
msgb_tvlv_put(msg, BSSGP_IE_PDU_IN_ERROR,
|
||||
msgb_bssgp_len(orig_msg), msgb_bssgph(orig_msg));
|
||||
|
||||
return gprs_ns_sendmsg(bssgp_nsi, msg);
|
||||
}
|
||||
|
|
|
@ -831,8 +831,20 @@ out_silent:
|
|||
|
||||
static struct msgb *handle_rsip(struct mgcp_config *cfg, struct msgb *msg)
|
||||
{
|
||||
struct mgcp_msg_ptr data_ptrs[6];
|
||||
const char *trans_id;
|
||||
struct mgcp_endpoint *endp;
|
||||
int found;
|
||||
|
||||
found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs),
|
||||
&trans_id, &endp);
|
||||
if (found != 0) {
|
||||
LOGP(DMGCP, LOGL_ERROR, "Failed to find the endpoint.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cfg->reset_cb)
|
||||
cfg->reset_cb(cfg);
|
||||
cfg->reset_cb(endp->tcfg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ out_err:
|
|||
}
|
||||
|
||||
|
||||
int db_prepare()
|
||||
int db_prepare(void)
|
||||
{
|
||||
dbi_result result;
|
||||
int i;
|
||||
|
@ -245,15 +245,13 @@ int db_prepare()
|
|||
return 0;
|
||||
}
|
||||
|
||||
int db_fini()
|
||||
int db_fini(void)
|
||||
{
|
||||
dbi_conn_close(conn);
|
||||
dbi_shutdown();
|
||||
|
||||
if (db_dirname)
|
||||
free(db_dirname);
|
||||
if (db_basename)
|
||||
free(db_basename);
|
||||
free(db_dirname);
|
||||
free(db_basename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -276,9 +274,9 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi)
|
|||
}
|
||||
|
||||
subscr = subscr_alloc();
|
||||
subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
|
||||
if (!subscr)
|
||||
return NULL;
|
||||
subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
|
||||
result = dbi_conn_queryf(conn,
|
||||
"INSERT INTO Subscriber "
|
||||
"(imsi, created, updated) "
|
||||
|
|
|
@ -554,7 +554,8 @@ static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *m
|
|||
{
|
||||
uint8_t *smsp = msgb_sms(msg);
|
||||
struct gsm_sms *gsms;
|
||||
uint8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
|
||||
unsigned int sms_alphabet;
|
||||
uint8_t sms_mti, sms_mms, sms_vpf, sms_rp;
|
||||
uint8_t *sms_vp;
|
||||
uint8_t da_len_bytes;
|
||||
uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
|
||||
|
|
|
@ -51,6 +51,8 @@ struct gsm_sms_pending {
|
|||
unsigned long long sms_id;
|
||||
int failed_attempts;
|
||||
int resend;
|
||||
|
||||
int no_detach;
|
||||
};
|
||||
|
||||
struct gsm_sms_queue {
|
||||
|
@ -86,17 +88,24 @@ static int sms_is_in_pending(struct gsm_sms_queue *smsq, struct gsm_sms *sms)
|
|||
return sms_find_pending(smsq, sms) != NULL;
|
||||
}
|
||||
|
||||
static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq,
|
||||
struct gsm_subscriber *subscr)
|
||||
static struct gsm_sms_pending *sms_subscriber_find_pending(
|
||||
struct gsm_sms_queue *smsq,
|
||||
struct gsm_subscriber *subscr)
|
||||
{
|
||||
struct gsm_sms_pending *pending;
|
||||
|
||||
llist_for_each_entry(pending, &smsq->pending_sms, entry) {
|
||||
if (pending->subscr == subscr)
|
||||
return 1;
|
||||
return pending;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sms_subscriber_is_pending(struct gsm_sms_queue *smsq,
|
||||
struct gsm_subscriber *subscr)
|
||||
{
|
||||
return sms_subscriber_find_pending(smsq, subscr) != NULL;
|
||||
}
|
||||
|
||||
static struct gsm_sms_pending *sms_pending_from(struct gsm_sms_queue *smsq,
|
||||
|
@ -146,7 +155,7 @@ static void sms_pending_failed(struct gsm_sms_pending *pending, int paging_error
|
|||
if (++pending->failed_attempts < smsq->max_fail)
|
||||
return sms_pending_resend(pending);
|
||||
|
||||
if (paging_error) {
|
||||
if (paging_error && !pending->no_detach) {
|
||||
LOGP(DSMS, LOGL_NOTICE,
|
||||
"Subscriber %llu is not reachable. Setting LAC=0.\n", pending->subscr->id);
|
||||
pending->subscr->lac = GSM_LAC_RESERVED_DETACHED;
|
||||
|
@ -321,16 +330,41 @@ int sms_queue_start(struct gsm_network *network, int max_pending)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sub_ready_for_sm(struct gsm_subscriber *subscr)
|
||||
static int sub_ready_for_sm(struct gsm_network *net, struct gsm_subscriber *subscr)
|
||||
{
|
||||
struct gsm_subscriber_connection *conn;
|
||||
struct gsm_sms *sms;
|
||||
struct gsm_sms_pending *pending;
|
||||
struct gsm_subscriber_connection *conn;
|
||||
|
||||
/*
|
||||
* The code used to be very clever and tried to submit
|
||||
* a SMS during the Location Updating Request. This has
|
||||
* two issues:
|
||||
* 1.) The Phone might not be ready yet, e.g. the C155
|
||||
* will not respond to the Submit when it is booting.
|
||||
* 2.) The queue is already trying to submit SMS to the
|
||||
* user and by not responding to the paging request
|
||||
* we will set the LAC back to 0. We would have to
|
||||
* stop the paging and move things over.
|
||||
*
|
||||
* We need to be careful in what we try here.
|
||||
*/
|
||||
|
||||
/* check if we have pending requests */
|
||||
pending = sms_subscriber_find_pending(net->sms_queue, subscr);
|
||||
if (pending) {
|
||||
LOGP(DMSC, LOGL_NOTICE,
|
||||
"Pending paging while subscriber %llu attached.\n",
|
||||
subscr->id);
|
||||
pending->no_detach = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A subscriber has attached. Check if there are
|
||||
* any pending SMS for him to be delivered */
|
||||
conn = connection_for_subscr(subscr);
|
||||
if (!conn)
|
||||
return -1;
|
||||
|
||||
/* Now try to deliver any pending SMS to this sub */
|
||||
sms = db_sms_get_unsent_for_subscr(subscr);
|
||||
if (!sms)
|
||||
return -1;
|
||||
|
@ -347,7 +381,7 @@ static int sms_subscr_cb(unsigned int subsys, unsigned int signal,
|
|||
return 0;
|
||||
|
||||
/* this is readyForSM */
|
||||
return sub_ready_for_sm(subscr);
|
||||
return sub_ready_for_sm(handler_data, subscr);
|
||||
}
|
||||
|
||||
static int sms_sms_cb(unsigned int subsys, unsigned int signal,
|
||||
|
|
|
@ -140,8 +140,14 @@ int trau_frame_up2down(struct decoded_trau_frame *fr)
|
|||
case TRAU_FT_EFR:
|
||||
/* clear time alignment */
|
||||
memset(fr->c_bits+5, 0, 6);
|
||||
/* FIXME: set UFE appropriately */
|
||||
/* FIXME: SP / BFI in case of DTx */
|
||||
/* set UFE appropriately */
|
||||
fr->c_bits[11] = 1; /* C12 (UFE), good frame (TODO) */
|
||||
/* C13 .. C15 are spare and coded as '1' */
|
||||
memset(fr->c_bits+12, 0x01, 3);
|
||||
/* SP / BFI in case of DTx */
|
||||
fr->c_bits[15] = 1; /* C16 (SP), no DTX (TODO) */
|
||||
/* C17 .. C21 are spare and coded as '1' */
|
||||
memset(fr->c_bits+16, 0x01, 5);
|
||||
break;
|
||||
case TRAU_FT_IDLE_UP:
|
||||
memcpy(fr->c_bits, ft_idle_down_bits, 5);
|
||||
|
@ -246,7 +252,7 @@ static struct decoded_trau_frame fr_idle_frame = {
|
|||
.t_bits = { 1, 1, 1, 1 },
|
||||
};
|
||||
static uint8_t encoded_idle_frame[TRAU_FRAME_BITS];
|
||||
static int dbits_initted;
|
||||
static int dbits_initted = 0;
|
||||
|
||||
uint8_t *trau_idle_frame(void)
|
||||
{
|
||||
|
@ -254,7 +260,27 @@ uint8_t *trau_idle_frame(void)
|
|||
if (!dbits_initted) {
|
||||
/* set all D-bits to 1 */
|
||||
memset(&fr_idle_frame.d_bits, 0x01, 260);
|
||||
|
||||
memset(&fr_idle_frame.c_bits, 0x01, 25); /* spare are set to 1 */
|
||||
/* set Downlink Idle Speech Frame pattern */
|
||||
fr_idle_frame.c_bits[0] = 0; /* C1 */
|
||||
fr_idle_frame.c_bits[1] = 1; /* C2 */
|
||||
fr_idle_frame.c_bits[2] = 1; /* C3 */
|
||||
fr_idle_frame.c_bits[3] = 1; /* C4 */
|
||||
fr_idle_frame.c_bits[4] = 0; /* C5 */
|
||||
/* set no Time Alignment pattern */
|
||||
fr_idle_frame.c_bits[5] = 0; /* C6 */
|
||||
fr_idle_frame.c_bits[6] = 0; /* C7 */
|
||||
fr_idle_frame.c_bits[7] = 0; /* C8 */
|
||||
fr_idle_frame.c_bits[8] = 0; /* C9 */
|
||||
fr_idle_frame.c_bits[9] = 0; /* C10 */
|
||||
fr_idle_frame.c_bits[10] = 0; /* C11 */
|
||||
/* already set to 1, but maybe we need to modify it in the future */
|
||||
fr_idle_frame.c_bits[11] = 1; /* C12 (UFE), good frame */
|
||||
fr_idle_frame.c_bits[15] = 1; /* C16 (SP), no DTX */
|
||||
|
||||
encode_fr(encoded_idle_frame, &fr_idle_frame);
|
||||
dbits_initted = 1; /* set it to 1 to not call it again */
|
||||
}
|
||||
return encoded_idle_frame;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <osmocom/gsm/protocol/gsm_08_08.h>
|
||||
#include <osmocom/gsm/gsm0808.h>
|
||||
|
||||
#include <osmocom/sccp/sccp.h>
|
||||
|
||||
#define return_when_not_connected(conn) \
|
||||
if (!conn->sccp_con) {\
|
||||
LOGP(DMSC, LOGL_ERROR, "MSC Connection not present.\n"); \
|
||||
|
@ -102,11 +104,13 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
|
|||
conn->bts->cell_identity);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
|
||||
sccp_connection_free(conn->sccp_con->sccp);
|
||||
bsc_delete_connection(conn->sccp_con);
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
}
|
||||
|
||||
if (bsc_open_connection(conn->sccp_con, resp) != 0) {
|
||||
sccp_connection_free(conn->sccp_con->sccp);
|
||||
bsc_delete_connection(conn->sccp_con);
|
||||
msgb_free(resp);
|
||||
return BSC_API_CONN_POL_REJECT;
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
|
||||
int bsc_grace_allow_new_connection(struct gsm_network *network)
|
||||
{
|
||||
if (!network->msc_data->rf_ctl)
|
||||
if (!network->msc_data->rf_ctrl)
|
||||
return 1;
|
||||
return network->msc_data->rf_ctl->policy == S_RF_ON;
|
||||
return network->msc_data->rf_ctrl->policy == S_RF_ON;
|
||||
}
|
||||
|
||||
static int handle_sub(struct gsm_lchan *lchan, const char *text)
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
#include <openbsc/ipaccess.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/process.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
|
||||
#include <osmocom/sccp/sccp.h>
|
||||
|
@ -49,7 +49,7 @@
|
|||
|
||||
struct gsm_network *bsc_gsmnet = 0;
|
||||
static const char *config_file = "openbsc.cfg";
|
||||
static const char *rf_ctl = NULL;
|
||||
static const char *rf_ctrl = NULL;
|
||||
extern const char *openbsc_copyright;
|
||||
static int daemonize = 0;
|
||||
|
||||
|
@ -120,7 +120,7 @@ static void handle_options(int argc, char **argv)
|
|||
log_set_log_level(osmo_stderr_target, atoi(optarg));
|
||||
break;
|
||||
case 'r':
|
||||
rf_ctl = optarg;
|
||||
rf_ctrl = optarg;
|
||||
break;
|
||||
default:
|
||||
/* ignore */
|
||||
|
@ -172,18 +172,57 @@ static void signal_handler(int signal)
|
|||
}
|
||||
|
||||
struct location {
|
||||
struct llist_head list;
|
||||
unsigned long age;
|
||||
int valid;
|
||||
double lat;
|
||||
double lon;
|
||||
double height;
|
||||
unsigned long age;
|
||||
};
|
||||
|
||||
static struct location myloc;
|
||||
static LLIST_HEAD(locations);
|
||||
|
||||
void cleanup_locations()
|
||||
{
|
||||
struct location *myloc, *tmp;
|
||||
int invalpos = 0, i = 0;
|
||||
|
||||
LOGP(DCTRL, LOGL_DEBUG, "Checking position list.\n");
|
||||
llist_for_each_entry_safe(myloc, tmp, &locations, list) {
|
||||
i++;
|
||||
if (i > 3) {
|
||||
LOGP(DCTRL, LOGL_DEBUG, "Deleting old position.\n");
|
||||
llist_del(&myloc->list);
|
||||
talloc_free(myloc);
|
||||
} else if (!myloc->valid) { /* Only capture the newest of subsequent invalid positions */
|
||||
invalpos++;
|
||||
if (invalpos > 1) {
|
||||
LOGP(DCTRL, LOGL_DEBUG, "Deleting subsequent invalid position.\n");
|
||||
invalpos--;
|
||||
i--;
|
||||
llist_del(&myloc->list);
|
||||
talloc_free(myloc);
|
||||
}
|
||||
} else {
|
||||
invalpos = 0;
|
||||
}
|
||||
}
|
||||
LOGP(DCTRL, LOGL_DEBUG, "Found %i positions.\n", i);
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE(net_loc, "location");
|
||||
int get_net_loc(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
cmd->reply = talloc_asprintf(cmd, "%lu,%f,%f,%f", myloc.age, myloc.lat, myloc.lon, myloc.height);
|
||||
struct location *myloc;
|
||||
|
||||
if (llist_empty(&locations)) {
|
||||
cmd->reply = talloc_asprintf(cmd, "0,0,0,0,0");
|
||||
return CTRL_CMD_REPLY;
|
||||
} else {
|
||||
myloc = llist_entry(locations.next, struct location, list);
|
||||
}
|
||||
|
||||
cmd->reply = talloc_asprintf(cmd, "%lu,%i,%f,%f,%f", myloc->age, myloc->valid, myloc->lat, myloc->lon, myloc->height);
|
||||
if (!cmd->reply) {
|
||||
cmd->reply = "OOM";
|
||||
return CTRL_CMD_ERROR;
|
||||
|
@ -194,24 +233,38 @@ int get_net_loc(struct ctrl_cmd *cmd, void *data)
|
|||
|
||||
int set_net_loc(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
char *saveptr, *lat, *lon, *height, *age, *tmp;
|
||||
char *saveptr, *lat, *lon, *height, *age, *valid, *tmp;
|
||||
struct location *myloc;
|
||||
|
||||
tmp = talloc_strdup(cmd, cmd->value);
|
||||
if (!tmp)
|
||||
goto oom;
|
||||
|
||||
myloc = talloc_zero(tall_bsc_ctx, struct location);
|
||||
if (!myloc) {
|
||||
talloc_free(tmp);
|
||||
goto oom;
|
||||
}
|
||||
INIT_LLIST_HEAD(&myloc->list);
|
||||
|
||||
|
||||
age = strtok_r(tmp, ",", &saveptr);
|
||||
valid = strtok_r(NULL, ",", &saveptr);
|
||||
lat = strtok_r(NULL, ",", &saveptr);
|
||||
lon = strtok_r(NULL, ",", &saveptr);
|
||||
height = strtok_r(NULL, "\0", &saveptr);
|
||||
|
||||
myloc.age = atol(age);
|
||||
myloc.lat = atof(lat);
|
||||
myloc.lon = atof(lon);
|
||||
myloc.height = atof(height);
|
||||
myloc->age = atol(age);
|
||||
myloc->valid = atoi(valid);
|
||||
myloc->lat = atof(lat);
|
||||
myloc->lon = atof(lon);
|
||||
myloc->height = atof(height);
|
||||
talloc_free(tmp);
|
||||
|
||||
/* Add location to the end of the list */
|
||||
llist_add(&myloc->list, &locations);
|
||||
cleanup_locations();
|
||||
|
||||
return get_net_loc(cmd, data);
|
||||
oom:
|
||||
cmd->reply = "OOM";
|
||||
|
@ -220,9 +273,9 @@ oom:
|
|||
|
||||
int verify_net_loc(struct ctrl_cmd *cmd, const char *value, void *data)
|
||||
{
|
||||
char *saveptr, *latstr, *lonstr, *heightstr, *agestr, *tmp;
|
||||
int ret = 0;
|
||||
char *saveptr, *latstr, *lonstr, *heightstr, *agestr, *validstr, *tmp;
|
||||
unsigned long age;
|
||||
int valid;
|
||||
double lat, lon, height;
|
||||
|
||||
tmp = talloc_strdup(cmd, value);
|
||||
|
@ -230,23 +283,27 @@ int verify_net_loc(struct ctrl_cmd *cmd, const char *value, void *data)
|
|||
return 1;
|
||||
|
||||
agestr = strtok_r(tmp, ",", &saveptr);
|
||||
validstr = strtok_r(NULL, ",", &saveptr);
|
||||
latstr = strtok_r(NULL, ",", &saveptr);
|
||||
lonstr = strtok_r(NULL, ",", &saveptr);
|
||||
heightstr = strtok_r(NULL, "\0", &saveptr);
|
||||
|
||||
if ((agestr == 0) || (latstr == 0) || (lonstr == 0) || (heightstr == 0))
|
||||
ret = 1;
|
||||
if ((agestr == NULL) || (validstr == NULL) || (latstr == NULL) ||
|
||||
(lonstr == NULL) || (heightstr == NULL))
|
||||
return 1;
|
||||
|
||||
age = atol(agestr);
|
||||
valid = atoi(validstr);
|
||||
lat = atof(latstr);
|
||||
lon = atof(lonstr);
|
||||
height = atof(heightstr);
|
||||
talloc_free(tmp);
|
||||
|
||||
if ((age == 0) || (lat < -90) || (lat > 90) || (lon < -180) || (lon > 180))
|
||||
if ((age == 0) || (lat < -90) || (lat > 90) || (lon < -180) ||
|
||||
(lon > 180) || (valid < 0) || (valid > 2))
|
||||
return 1;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE(trx_rf_lock, "rf_locked");
|
||||
|
@ -371,13 +428,13 @@ int main(int argc, char **argv)
|
|||
ctrl_cmd_install(CTRL_NODE_TRX, &cmd_trx_rf_lock);
|
||||
|
||||
data = bsc_gsmnet->msc_data;
|
||||
if (rf_ctl)
|
||||
bsc_replace_string(data, &data->rf_ctrl_name, rf_ctl);
|
||||
if (rf_ctrl)
|
||||
bsc_replace_string(data, &data->rf_ctrl_name, rf_ctrl);
|
||||
|
||||
if (data->rf_ctrl_name) {
|
||||
data->rf_ctl = osmo_bsc_rf_create(data->rf_ctrl_name,
|
||||
data->rf_ctrl = osmo_bsc_rf_create(data->rf_ctrl_name,
|
||||
bsc_gsmnet);
|
||||
if (!data->rf_ctl) {
|
||||
if (!data->rf_ctrl) {
|
||||
fprintf(stderr, "Failed to create the RF service.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ static int rf_write_cmd(struct osmo_fd *fd, struct msgb *msg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rf_ctl_accept(struct osmo_fd *bfd, unsigned int what)
|
||||
static int rf_ctrl_accept(struct osmo_fd *bfd, unsigned int what)
|
||||
{
|
||||
struct osmo_bsc_rf_conn *conn;
|
||||
struct osmo_bsc_rf *rf = bfd->data;
|
||||
|
@ -338,7 +338,7 @@ struct osmo_bsc_rf *osmo_bsc_rf_create(const char *path, struct gsm_network *net
|
|||
}
|
||||
|
||||
bfd->when = BSC_FD_READ;
|
||||
bfd->cb = rf_ctl_accept;
|
||||
bfd->cb = rf_ctrl_accept;
|
||||
bfd->data = rf;
|
||||
|
||||
if (osmo_fd_register(bfd) != 0) {
|
||||
|
|
|
@ -264,14 +264,14 @@ static void bsc_close_connections(struct bsc_msc_connection *msc_con)
|
|||
static int handle_msc_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
{
|
||||
struct osmo_msc_data *data;
|
||||
struct msc_signal_data *msc;
|
||||
|
||||
if (subsys != SS_MSC)
|
||||
return 0;
|
||||
|
||||
data = (struct osmo_msc_data *) signal_data;
|
||||
msc = signal_data;
|
||||
if (signal == S_MSC_LOST)
|
||||
bsc_close_connections(data->msc_con);
|
||||
bsc_close_connections(msc->data->msc_con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
/* The main method to drive it as a standalone process */
|
||||
|
||||
/*
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009 by On-Waves
|
||||
* (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2009-2011 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -40,7 +40,6 @@
|
|||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/process.h>
|
||||
#include <osmocom/core/select.h>
|
||||
|
||||
#include <osmocom/vty/telnet_interface.h>
|
||||
|
@ -59,6 +58,7 @@ void subscr_put() { abort(); }
|
|||
#warning "Make use of the rtp proxy code"
|
||||
|
||||
static struct mgcp_config *cfg;
|
||||
static struct mgcp_trunk_config *reset_trunk;
|
||||
static int reset_endpoints = 0;
|
||||
static int daemonize = 0;
|
||||
|
||||
|
@ -122,9 +122,10 @@ static void handle_options(int argc, char **argv)
|
|||
}
|
||||
|
||||
/* simply remember this */
|
||||
static int mgcp_rsip_cb(struct mgcp_config *cfg)
|
||||
static int mgcp_rsip_cb(struct mgcp_trunk_config *tcfg)
|
||||
{
|
||||
reset_endpoints = 1;
|
||||
reset_trunk = tcfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -171,12 +172,14 @@ static int read_call_agent(struct osmo_fd *fd, unsigned int what)
|
|||
}
|
||||
|
||||
if (reset_endpoints) {
|
||||
LOGP(DMGCP, LOGL_NOTICE, "Asked to reset endpoints.\n");
|
||||
LOGP(DMGCP, LOGL_NOTICE,
|
||||
"Asked to reset endpoints: %d/%d\n",
|
||||
reset_trunk->trunk_nr, reset_trunk->trunk_type);
|
||||
reset_endpoints = 0;
|
||||
|
||||
/* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */
|
||||
for (i = 1; i < cfg->trunk.number_endpoints; ++i)
|
||||
mgcp_free_endp(&cfg->trunk.endpoints[i]);
|
||||
for (i = 1; i < reset_trunk->number_endpoints; ++i)
|
||||
mgcp_free_endp(&reset_trunk->endpoints[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/process.h>
|
||||
|
||||
#include <osmocom/gsm/gsm0808.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_08.h>
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <openbsc/db.h>
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/process.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/e1_input.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/abis_nm.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <osmocom/core/select.h>
|
||||
|
@ -209,35 +210,31 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const char *bs11_link_state[] = {
|
||||
[0x00] = "Down",
|
||||
[0x01] = "Up",
|
||||
[0x02] = "Restoring",
|
||||
static const struct value_string bs11_linkst_names[] = {
|
||||
{ 0, "Down" },
|
||||
{ 1, "Up" },
|
||||
{ 2, "Restoring" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const char *linkstate_name(uint8_t linkstate)
|
||||
{
|
||||
if (linkstate > ARRAY_SIZE(bs11_link_state))
|
||||
return "Unknown";
|
||||
|
||||
return bs11_link_state[linkstate];
|
||||
return get_value_string(bs11_linkst_names, linkstate);
|
||||
}
|
||||
|
||||
static const char *mbccu_load[] = {
|
||||
[0] = "No Load",
|
||||
[1] = "Load BTSCAC",
|
||||
[2] = "Load BTSDRX",
|
||||
[3] = "Load BTSBBX",
|
||||
[4] = "Load BTSARC",
|
||||
[5] = "Load",
|
||||
static const struct value_string mbccu_load_names[] = {
|
||||
{ 0, "No Load" },
|
||||
{ 1, "Load BTSCAC" },
|
||||
{ 2, "Load BTSDRX" },
|
||||
{ 3, "Load BTSBBX" },
|
||||
{ 4, "Load BTSARC" },
|
||||
{ 5, "Load" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const char *mbccu_load_name(uint8_t linkstate)
|
||||
{
|
||||
if (linkstate > ARRAY_SIZE(mbccu_load))
|
||||
return "Unknown";
|
||||
|
||||
return mbccu_load[linkstate];
|
||||
return get_value_string(mbccu_load_names, linkstate);
|
||||
}
|
||||
|
||||
static const char *bts_phase_name(uint8_t phase)
|
||||
|
@ -899,7 +896,8 @@ int main(int argc, char **argv)
|
|||
status_timer.cb = status_timer_cb;
|
||||
|
||||
while (1) {
|
||||
osmo_select_main(0);
|
||||
if (osmo_select_main(0) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
abis_nm_bs11_factory_logon(g_bts, 0);
|
||||
|
|
Loading…
Reference in New Issue