diff options
58 files changed, 1167 insertions, 916 deletions
diff --git a/libosmocore/include/osmocore/Makefile.am b/libosmocore/include/osmocore/Makefile.am index fb4f089b7..1c3a33f33 100644 --- a/libosmocore/include/osmocore/Makefile.am +++ b/libosmocore/include/osmocore/Makefile.am @@ -1,7 +1,7 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \ tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \ gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \ - gsm48_ie.h + gsm48_ie.h logging.h if ENABLE_TALLOC osmocore_HEADERS += talloc.h diff --git a/libosmocore/include/osmocore/logging.h b/libosmocore/include/osmocore/logging.h new file mode 100644 index 000000000..93f18a07b --- /dev/null +++ b/libosmocore/include/osmocore/logging.h @@ -0,0 +1,130 @@ +#ifndef _OSMOCORE_LOGGING_H +#define _OSMOCORE_LOGGING_H + +#include <stdio.h> +#include <stdint.h> +#include <osmocore/linuxlist.h> + +#define LOG_MAX_CATEGORY 32 +#define LOG_MAX_CTX 8 +#define LOG_MAX_FILTERS 8 + +#define DEBUG + +#ifdef DEBUG +#define DEBUGP(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 0, fmt, ## args) +#define DEBUGPC(ss, fmt, args...) logp(ss, __FILE__, __LINE__, 1, fmt, ## args) +#else +#define DEBUGP(xss, fmt, args...) +#define DEBUGPC(ss, fmt, args...) +#endif + +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + +char *hexdump(const unsigned char *buf, int len); +void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); + +/* new logging interface */ +#define LOGP(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) +#define LOGPC(ss, level, fmt, args...) \ + logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) + +/* different levels */ +#define LOGL_DEBUG 1 /* debugging information */ +#define LOGL_INFO 3 +#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ +#define LOGL_ERROR 7 /* error condition, requires user action */ +#define LOGL_FATAL 8 /* fatal, program aborted */ + +#define LOG_FILTER_ALL 0x0001 + +struct log_category { + uint8_t loglevel; + uint8_t enabled; +}; + +struct log_info_cat { + const char *name; + const char *color; + const char *description; + uint8_t loglevel; + uint8_t enabled; +}; + +/* log context information, passed to filter */ +struct log_context { + void *ctx[LOG_MAX_CTX+1]; +}; + +struct log_target; + +typedef int log_filter(const struct log_context *ctx, + struct log_target *target); + +struct log_info { + /* filter callback function */ + log_filter *filter_fn; + + /* per-category information */ + const struct log_info_cat *cat; + unsigned int num_cat; +}; + +struct log_target { + struct llist_head entry; + + int filter_map; + void *filter_data[LOG_MAX_FILTERS+1]; + + struct log_category categories[LOG_MAX_CATEGORY+1]; + uint8_t loglevel; + int use_color:1; + int print_timestamp:1; + + union { + struct { + FILE *out; + } tgt_stdout; + + struct { + int priority; + } tgt_syslog; + + struct { + void *vty; + } tgt_vty; + }; + + void (*output) (struct log_target *target, const char *string); +}; + +/* use the above macros */ +void logp2(unsigned int subsys, unsigned int level, char *file, + int line, int cont, const char *format, ...) + __attribute__ ((format (printf, 6, 7))); +void log_init(const struct log_info *cat); + +/* context management */ +void log_reset_context(void); +int log_set_context(uint8_t ctx, void *value); + +/* filter on the targets */ +void log_set_all_filter(struct log_target *target, int); + +void log_set_use_color(struct log_target *target, int); +void log_set_print_timestamp(struct log_target *target, int); +void log_set_log_level(struct log_target *target, int log_level); +void log_parse_category_mask(struct log_target *target, const char* mask); +int log_parse_level(const char *lvl); +int log_parse_category(const char *category); +void log_set_category_filter(struct log_target *target, int category, + int enable, int level); + +/* management of the targets */ +struct log_target *log_target_create(void); +struct log_target *log_target_create_stderr(void); +void log_add_target(struct log_target *target); +void log_del_target(struct log_target *target); + +#endif /* _OSMOCORE_LOGGING_H */ diff --git a/libosmocore/include/osmocore/write_queue.h b/libosmocore/include/osmocore/write_queue.h index c84000c1e..64d4159a0 100644 --- a/libosmocore/include/osmocore/write_queue.h +++ b/libosmocore/include/osmocore/write_queue.h @@ -38,6 +38,7 @@ struct write_queue { }; void write_queue_init(struct write_queue *queue, int max_length); +void write_queue_clear(struct write_queue *queue); int write_queue_enqueue(struct write_queue *queue, struct msgb *data); int write_queue_bfd_cb(struct bsc_fd *fd, unsigned int what); diff --git a/libosmocore/src/Makefile.am b/libosmocore/src/Makefile.am index f0effa2ea..16978074a 100644 --- a/libosmocore/src/Makefile.am +++ b/libosmocore/src/Makefile.am @@ -9,7 +9,8 @@ lib_LTLIBRARIES = libosmocore.la libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \ tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \ - write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c + write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \ + logging.c if ENABLE_TALLOC libosmocore_la_SOURCES += talloc.c diff --git a/libosmocore/src/logging.c b/libosmocore/src/logging.c new file mode 100644 index 000000000..508ccfd3e --- /dev/null +++ b/libosmocore/src/logging.c @@ -0,0 +1,345 @@ +/* Debugging/Logging support code */ + +/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org> + * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org> + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <errno.h> + +#include <osmocore/talloc.h> +#include <osmocore/utils.h> +#include <osmocore/logging.h> + +static const struct log_info *log_info; + +static struct log_context log_context; +static void *tall_log_ctx = NULL; +static LLIST_HEAD(target_list); + +static const struct value_string loglevel_strs[] = { + { 0, "EVERYTHING" }, + { LOGL_DEBUG, "DEBUG" }, + { LOGL_INFO, "INFO" }, + { LOGL_NOTICE, "NOTICE" }, + { LOGL_ERROR, "ERROR" }, + { LOGL_FATAL, "FATAL" }, + { 0, NULL }, +}; + +int log_parse_level(const char *lvl) +{ + return get_string_value(loglevel_strs, lvl); +} + +int log_parse_category(const char *category) +{ + int i; + + for (i = 0; i < log_info->num_cat; ++i) { + if (!strcasecmp(log_info->cat[i].name+1, category)) + return i; + } + + return -EINVAL; +} + +/* + * Parse the category mask. + * The format can be this: category1:category2:category3 + * or category1,2:category2,3:... + */ +void log_parse_category_mask(struct log_target* target, const char *_mask) +{ + int i = 0; + char *mask = strdup(_mask); + char *category_token = NULL; + + /* Disable everything to enable it afterwards */ + for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + target->categories[i].enabled = 0; + + category_token = strtok(mask, ":"); + do { + for (i = 0; i < log_info->num_cat; ++i) { + char* colon = strstr(category_token, ","); + int length = strlen(category_token); + + if (colon) + length = colon - category_token; + + if (strncasecmp(log_info->cat[i].name, category_token, + length) == 0) { + int level = 0; + + if (colon) + level = atoi(colon+1); + + target->categories[i].enabled = 1; + target->categories[i].loglevel = level; + } + } + } while ((category_token = strtok(NULL, ":"))); + + free(mask); +} + +static const char* color(int subsys) +{ + if (subsys < log_info->num_cat) + return log_info->cat[subsys].color; + + return NULL; +} + +static void _output(struct log_target *target, unsigned int subsys, + char *file, int line, int cont, const char *format, + va_list ap) +{ + char col[30]; + char sub[30]; + char tim[30]; + char buf[4096]; + char final[4096]; + + /* prepare the data */ + col[0] = '\0'; + sub[0] = '\0'; + tim[0] = '\0'; + buf[0] = '\0'; + + /* are we using color */ + if (target->use_color) { + const char *c = color(subsys); + if (c) { + snprintf(col, sizeof(col), "%s", color(subsys)); + col[sizeof(col)-1] = '\0'; + } + } + vsnprintf(buf, sizeof(buf), format, ap); + buf[sizeof(buf)-1] = '\0'; + + if (!cont) { + if (target->print_timestamp) { + char *timestr; + time_t tm; + tm = time(NULL); + timestr = ctime(&tm); + timestr[strlen(timestr)-1] = '\0'; + snprintf(tim, sizeof(tim), "%s ", timestr); + tim[sizeof(tim)-1] = '\0'; + } + snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); + sub[sizeof(sub)-1] = '\0'; + } + + snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); + final[sizeof(final)-1] = '\0'; + target->output(target, final); +} + + +static void _logp(unsigned int subsys, int level, char *file, int line, + int cont, const char *format, va_list ap) +{ + struct log_target *tar; + + llist_for_each_entry(tar, &target_list, entry) { + struct log_category *category; + int output = 0; + + category = &tar->categories[subsys]; + /* subsystem is not supposed to be logged */ + if (!category->enabled) + continue; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + continue; + + /* Check the category log level */ + if (tar->loglevel == 0 && category->loglevel != 0 && + level < category->loglevel) + continue; + + /* Apply filters here... if that becomes messy we will + * need to put filters in a list and each filter will + * say stop, continue, output */ + if ((tar->filter_map & LOG_FILTER_ALL) != 0) + output = 1; + else if (log_info->filter_fn) + output = log_info->filter_fn(&log_context, + tar); + + if (output) { + /* FIXME: copying the va_list is an ugly + * workaround against a bug hidden somewhere in + * _output. If we do not copy here, the first + * call to _output() will corrupt the va_list + * contents, and any further _output() calls + * with the same va_list will segfault */ + va_list bp; + va_copy(bp, ap); + _output(tar, subsys, file, line, cont, format, bp); + va_end(bp); + } + } +} + +void logp(unsigned int subsys, char *file, int line, int cont, + const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _logp(subsys, LOGL_DEBUG, file, line, cont, format, ap); + va_end(ap); +} + +void logp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _logp(subsys, level, file, line, cont, format, ap); + va_end(ap); +} + +static char hexd_buff[4096]; + +char *hexdump(const unsigned char *buf, int len) +{ + int i; + char *cur = hexd_buff; + + hexd_buff[0] = 0; + for (i = 0; i < len; i++) { + int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); + int rc = snprintf(cur, len_remain, "%02x ", buf[i]); + if (rc <= 0) + break; + cur += rc; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + +void log_add_target(struct log_target *target) +{ + llist_add_tail(&target->entry, &target_list); +} + +void log_del_target(struct log_target *target) +{ + llist_del(&target->entry); +} + +void log_reset_context(void) +{ + memset(&log_context, 0, sizeof(log_context)); +} + +int log_set_context(uint8_t ctx_nr, void *value) +{ + if (ctx_nr > LOG_MAX_CTX) + return -EINVAL; + + log_context.ctx[ctx_nr] = value; + + return 0; +} + +void log_set_all_filter(struct log_target *target, int all) +{ + if (all) + target->filter_map |= LOG_FILTER_ALL; + else + target->filter_map &= ~LOG_FILTER_ALL; +} + +void log_set_use_color(struct log_target *target, int use_color) +{ + target->use_color = use_color; +} + +void log_set_print_timestamp(struct log_target *target, int print_timestamp) +{ + target->print_timestamp = print_timestamp; +} + +void log_set_log_level(struct log_target *target, int log_level) +{ + target->loglevel = log_level; +} + +void log_set_category_filter(struct log_target *target, int category, + int enable, int level) +{ + if (category >= log_info->num_cat) + return; + target->categories[category].enabled = !!enable; + target->categories[category].loglevel = level; +} + +static void _stderr_output(struct log_target *target, const char *log) +{ + fprintf(target->tgt_stdout.out, "%s", log); + fflush(target->tgt_stdout.out); +} + +struct log_target *log_target_create(void) +{ + struct log_target *target; + + target = talloc_zero(tall_log_ctx, struct log_target); + if (!target) + return NULL; + + INIT_LLIST_HEAD(&target->entry); + memcpy(target->categories, log_info->cat, + sizeof(struct log_category)*log_info->num_cat); + target->use_color = 1; + target->print_timestamp = 0; + target->loglevel = 0; + return target; +} + +struct log_target *log_target_create_stderr(void) +{ + struct log_target *target; + + target = log_target_create(); + if (!target) + return NULL; + + target->tgt_stdout.out = stderr; + target->output = _stderr_output; + return target; +} + +void log_init(const struct log_info *cat) +{ + tall_log_ctx = talloc_named_const(NULL, 1, "logging"); + log_info = cat; +} diff --git a/libosmocore/src/write_queue.c b/libosmocore/src/write_queue.c index 7d908b4ca..a0ac2d6fd 100644 --- a/libosmocore/src/write_queue.c +++ b/libosmocore/src/write_queue.c @@ -72,3 +72,14 @@ int write_queue_enqueue(struct write_queue *queue, struct msgb *data) return 0; } + +void write_queue_clear(struct write_queue *queue) +{ + while (!llist_empty(&queue->msg_queue)) { + struct msgb *msg = msgb_dequeue(&queue->msg_queue); + msgb_free(msg); + } + + queue->current_length = 0; + queue->bfd.when &= ~BSC_FD_WRITE; +} diff --git a/openbsc/configure.in b/openbsc/configure.in index 6119847bf..9db2e2458 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -16,7 +16,7 @@ dnl checks for libraries AC_SEARCH_LIBS(crypt, crypt, [LIBCRYPT="-lcrypt"; AC_DEFINE([VTY_CRYPT_PW], [], [Use crypt functionality of vty.])]) -PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.1) +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.1.3) dnl checks for header files AC_HEADER_STDC diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 731bc76c4..25e3f4dd9 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -6,7 +6,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ bsc_rll.h mncc.h transaction.h ussd.h gsm_04_80.h \ silent_call.h mgcp.h meas_rep.h rest_octets.h \ system_information.h handover.h mgcp_internal.h \ - bssap.h bsc_msc.h bsc_nat.h vty.h + vty.h bssap.h bsc_msc.h bsc_nat.h -openbsc_HEADERS = gsm_04_08.h meas_rep.h +openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 532382ead..c8ac1dead 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -59,7 +59,7 @@ int rsl_ipacc_crcx(struct gsm_lchan *lchan); int rsl_ipacc_mdcx(struct gsm_lchan *lchan, u_int32_t ip, u_int16_t port, u_int8_t rtp_payload2); int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan); -int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan); +int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act); int abis_rsl_rcvmsg(struct msgb *msg); diff --git a/openbsc/include/openbsc/bsc_api.h b/openbsc/include/openbsc/bsc_api.h new file mode 100644 index 000000000..51e344f5a --- /dev/null +++ b/openbsc/include/openbsc/bsc_api.h @@ -0,0 +1,6 @@ +/* GSM 08.08 like API for OpenBSC */ + +#include "gsm_data.h" + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id); diff --git a/openbsc/include/openbsc/chan_alloc.h b/openbsc/include/openbsc/chan_alloc.h index c2e05d6a7..2cf447c7f 100644 --- a/openbsc/include/openbsc/chan_alloc.h +++ b/openbsc/include/openbsc/chan_alloc.h @@ -27,20 +27,20 @@ * Refcounting for the lchan. If the refcount drops to zero * the channel will send a RSL release request. */ -#define use_lchan(lchan) \ - do { lchan->use_count++; \ - DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \ - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \ - lchan->nr, lchan->use_count); \ +#define use_subscr_con(con) \ + do { (con)->use_count++; \ + DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) increases usage to: %d\n", \ + (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ + (con)->lchan->nr, (con)->use_count); \ } while(0); -#define put_lchan(lchan, reason) \ - do { lchan->use_count--; \ - DEBUGP(DCC, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \ - lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, \ - lchan->nr, lchan->use_count); \ - if (lchan->use_count <= 0) \ - _lchan_release(lchan, reason); \ +#define put_subscr_con(con, reason) \ + do { (con)->use_count--; \ + DEBUGP(DREF, "lchan (bts=%d,trx=%d,ts=%d,ch=%d) decreases usage to: %d\n", \ + (con)->lchan->ts->trx->bts->nr, (con)->lchan->ts->trx->nr, (con)->lchan->ts->nr, \ + (con)->lchan->nr, (con)->use_count); \ + if ((con)->use_count <= 0) \ + _lchan_release((con)->lchan, reason); \ } while(0); diff --git a/openbsc/include/openbsc/db.h b/openbsc/include/openbsc/db.h index df664dbc1..d0a1278ef 100644 --- a/openbsc/include/openbsc/db.h +++ b/openbsc/include/openbsc/db.h @@ -55,8 +55,8 @@ int set_authtuple_for_subscr(struct gsm_auth_tuple *atuple, /* SMS store-and-forward */ int db_sms_store(struct gsm_sms *sms); -struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id); -struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id); +struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id); +struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id); struct gsm_sms *db_sms_get_unsent_for_subscr(struct gsm_subscriber *subscr); int db_sms_mark_sent(struct gsm_sms *sms); diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 31e404d6c..c96d58922 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -5,6 +5,7 @@ #include <osmocore/linuxlist.h> #define DEBUG +#include <osmocore/logging.h> /* Debug Areas of the code */ enum { @@ -32,31 +33,6 @@ enum { Debug_LastEntry, }; -#ifdef DEBUG -#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args) -#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args) -#else -#define DEBUGP(xss, fmt, args...) -#define DEBUGPC(ss, fmt, args...) -#endif - - -#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; - -char *hexdump(const unsigned char *buf, int len); -void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); - -/* new logging interface */ -#define LOGP(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) -#define LOGPC(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) - -/* different levels */ -#define LOGL_DEBUG 1 /* debugging information */ -#define LOGL_INFO 3 -#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ -#define LOGL_ERROR 7 /* error condition, requires user action */ -#define LOGL_FATAL 8 /* fatal, program aborted */ - /* context */ #define BSC_CTX_LCHAN 0 #define BSC_CTX_SUBSCR 1 @@ -66,67 +42,12 @@ void debugp(unsigned int subsys, char *file, int line, int cont, const char *for /* target */ enum { - DEBUG_FILTER_IMSI = 1 << 0, - DEBUG_FILTER_ALL = 1 << 1, -}; - -struct debug_category { - int enabled; - int loglevel; + //DEBUG_FILTER_ALL = 1 << 0, + LOG_FILTER_IMSI = 1 << 1, }; -struct debug_target { - int filter_map; - char *imsi_filter; - - - struct debug_category categories[Debug_LastEntry]; - int use_color; - int print_timestamp; - int loglevel; - - union { - struct { - FILE *out; - } tgt_stdout; - - struct { - int priority; - } tgt_syslog; - - struct { - void *vty; - } tgt_vty; - }; - - void (*output) (struct debug_target *target, const char *string); - - struct llist_head entry; -}; - -/* use the above macros */ -void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 6, 7))); -void debug_init(void); - -/* context management */ -void debug_reset_context(void); -void debug_set_context(int ctx, void *value); - -/* filter on the targets */ -void debug_set_imsi_filter(struct debug_target *target, const char *imsi); -void debug_set_all_filter(struct debug_target *target, int); -void debug_set_use_color(struct debug_target *target, int); -void debug_set_print_timestamp(struct debug_target *target, int); -void debug_set_log_level(struct debug_target *target, int log_level); -void debug_parse_category_mask(struct debug_target *target, const char* mask); -int debug_parse_level(const char *lvl); -int debug_parse_category(const char *category); -void debug_set_category_filter(struct debug_target *target, int category, int enable, int level); +void log_set_imsi_filter(struct log_target *target, const char *imsi); +extern const struct log_info log_info; -/* management of the targets */ -struct debug_target *debug_target_create(void); -struct debug_target *debug_target_create_stderr(void); -void debug_add_target(struct debug_target *target); -void debug_del_target(struct debug_target *target); #endif /* _DEBUG_H */ diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 602658331..eb445d11a 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -25,7 +25,6 @@ int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq); int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan); struct msgb *gsm48_msgb_alloc(void); int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans); -int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len); int gsm48_send_rr_release(struct gsm_lchan *lchan); int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); diff --git a/openbsc/include/openbsc/gsm_04_11.h b/openbsc/include/openbsc/gsm_04_11.h index 9badd3659..8127af1ea 100644 --- a/openbsc/include/openbsc/gsm_04_11.h +++ b/openbsc/include/openbsc/gsm_04_11.h @@ -25,7 +25,7 @@ struct msgb; int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id); -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms); +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms); struct gsm_sms *sms_alloc(void); void sms_free(struct gsm_sms *sms); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 6005dee6a..303663f41 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -201,6 +201,27 @@ enum gsm_lchan_state { LCHAN_S_INACTIVE, /* channel is set inactive */ }; +/* the per subscriber data for lchan */ +struct gsm_subscriber_connection { + /* To whom we are allocated at the moment */ + struct gsm_subscriber *subscr; + + /* + * Operations that have a state and might be pending + */ + struct gsm_loc_updating_operation *loc_operation; + + /* use count. how many users use this channel */ + unsigned int use_count; + + /* Are we part of a special "silent" call */ + int silent_call; + + /* back pointers */ + struct gsm_lchan *lchan; + struct gsm_bts *bts; +}; + struct gsm_lchan { /* The TS that we're part of */ struct gsm_bts_trx_ts *ts; @@ -223,34 +244,21 @@ struct gsm_lchan { u_int8_t key_len; u_int8_t key[MAX_A5_KEY_LEN]; } encr; - /* Are we part of a special "silent" call */ - int silent_call; + + struct timer_list T3101; /* AMR bits */ struct gsm48_multi_rate_conf mr_conf; - /* To whom we are allocated at the moment */ - struct gsm_subscriber *subscr; - - struct timer_list T3101; - /* Established data link layer services */ u_int8_t sapis[8]; /* - * Operations that have a state and might be pending - */ - struct gsm_loc_updating_operation *loc_operation; - - /* * MSC handling... */ struct bss_sccp_connection_data *msc_data; - /* use count. how many users use this channel */ - unsigned int use_count; - /* cache of last measurement reports on this lchan */ struct gsm_meas_rep meas_rep[6]; int meas_rep_idx; @@ -268,6 +276,8 @@ struct gsm_lchan { u_int8_t speech_mode; struct rtp_socket *rtp_socket; } abis_ip; + + struct gsm_subscriber_connection conn; }; struct gsm_e1_subslot { @@ -279,7 +289,7 @@ struct gsm_e1_subslot { u_int8_t e1_ts_ss; }; -#define BTS_TRX_F_ACTIVATED 0x0001 +#define TS_F_PDCH_MODE 0x1000 /* One Timeslot in a TRX */ struct gsm_bts_trx_ts { struct gsm_bts_trx *trx; diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 0c22869f6..1b974e288 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -42,6 +42,7 @@ enum signal_subsystems { SS_SUBSCR, SS_SCALL, SS_GLOBAL, + SS_CHALLOC, }; /* SS_PAGING signals */ @@ -93,6 +94,12 @@ enum signal_lchan { S_LCHAN_MEAS_REP, /* 08.58 Measurement Report */ }; +/* SS_CHALLOC signals */ +enum signal_challoc { + S_CHALLOC_ALLOC_FAIL, /* allocation of lchan has failed */ + S_CHALLOC_FREED, /* lchan has been successfully freed */ +}; + /* SS_SUBSCR signals */ enum signal_subscr { S_SUBSCR_ATTACHED, @@ -130,4 +137,10 @@ struct ipacc_ack_signal_data { u_int8_t msg_type; }; +struct challoc_signal_data { + struct gsm_bts *bts; + struct gsm_lchan *lchan; + enum gsm_chan_t type; +}; + #endif diff --git a/openbsc/include/openbsc/telnet_interface.h b/openbsc/include/openbsc/telnet_interface.h index 20e794b49..b8c36b6a1 100644 --- a/openbsc/include/openbsc/telnet_interface.h +++ b/openbsc/include/openbsc/telnet_interface.h @@ -22,7 +22,7 @@ #define TELNET_INTERFACE_H #include "gsm_data.h" -#include "debug.h" +#include <openbsc/debug.h> #include <osmocore/select.h> #include <vty/vty.h> @@ -32,7 +32,7 @@ struct telnet_connection { struct gsm_network *network; struct bsc_fd fd; struct vty *vty; - struct debug_target *dbg; + struct log_target *dbg; }; diff --git a/openbsc/include/openbsc/transaction.h b/openbsc/include/openbsc/transaction.h index 50c3cc5da..90a008bdc 100644 --- a/openbsc/include/openbsc/transaction.h +++ b/openbsc/include/openbsc/transaction.h @@ -20,8 +20,8 @@ struct gsm_trans { /* To whom we belong, unique identifier of remote MM entity */ struct gsm_subscriber *subscr; - /* The LCHAN that we're currently using to transmit messages */ - struct gsm_lchan *lchan; + /* The associated connection we are using to transmit messages */ + struct gsm_subscriber_connection *conn; /* reference from MNCC or other application */ u_int32_t callref; @@ -71,6 +71,6 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new); +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new); #endif diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am index d9ffa8d0f..c749ed94a 100644 --- a/openbsc/src/Makefile.am +++ b/openbsc/src/Makefile.am @@ -18,7 +18,7 @@ libbsc_a_SOURCES = abis_rsl.c abis_nm.c gsm_data.c gsm_04_08_utils.c \ input/misdn.c input/ipaccess.c \ talloc_ctx.c system_information.c rest_octets.c \ rtp_proxy.c bts_siemens_bs11.c bts_ipaccess_nanobts.c \ - bts_unknown.c telnet_interface.c meas_rep.c bsc_version.c vty_interface_cmds.c + bts_unknown.c meas_rep.c telnet_interface.c bsc_version.c bsc_api.c vty_interface_cmds.c libmsc_a_SOURCES = gsm_subscriber.c db.c \ mncc.c gsm_04_08.c gsm_04_11.c transaction.c \ diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index c9852bf82..5e6e8196c 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -1,4 +1,4 @@ -/* GSM Network Management (OML) messages on the A-bis interface +/* GSM Network Management (OML) messages on the A-bis interface * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */ /* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org> @@ -514,7 +514,7 @@ int nm_is_running(struct gsm_nm_state *s) { static void debugp_foh(struct abis_om_fom_hdr *foh) { DEBUGP(DNM, "OC=%s(%02x) INST=(%02x,%02x,%02x) ", - obj_class_name(foh->obj_class), foh->obj_class, + obj_class_name(foh->obj_class), foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr, foh->obj_inst.ts_nr); } @@ -938,7 +938,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh)); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, "CAUSE=%s\n", + DEBUGPC(DNM, "CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else DEBUGPC(DNM, "\n"); @@ -1349,7 +1349,7 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname) return -1; } /* read first line and parse file ID and VERSION */ - rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n", + rc = fscanf(sw->stream, "@(#)%12s:%80s\r\n", file_id, file_version); if (rc != 2) { perror("parsing header line of software file"); @@ -2233,7 +2233,7 @@ int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts) } /* like abis_nm_conn_terr_traf + set_tei */ -int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port, +int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot, u_int8_t tei) { @@ -2595,7 +2595,7 @@ static u_int8_t req_attr_btsm[] = { NM_ATT_SW_DESCR, NM_ATT_GET_ARI }; #endif -static u_int8_t req_attr[] = { +static u_int8_t req_attr[] = { NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xa8, NM_ATT_OPER_STATE, 0xd5, 0xa1, NM_ATT_BS11_ESN_FW_CODE_NO, NM_ATT_BS11_ESN_HW_CODE_NO, 0x42, NM_ATT_BS11_ESN_PCB_SERIAL, NM_ATT_BS11_PLL }; @@ -2674,11 +2674,11 @@ static int abis_nm_rx_ipacc(struct msgb *msg) DEBUGPC(DNM, "RSL CONNECT ACK "); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP)) DEBUGPC(DNM, "IP=%s ", - inet_ntoa(*((struct in_addr *) + inet_ntoa(*((struct in_addr *) TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP)))); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_DST_IP_PORT)) DEBUGPC(DNM, "PORT=%u ", - ntohs(*((u_int16_t *) + ntohs(*((u_int16_t *) TLVP_VAL(&tp, NM_ATT_IPACC_DST_IP_PORT)))); if (TLVP_PRESENT(&tp, NM_ATT_IPACC_STREAM_ID)) DEBUGPC(DNM, "STREAM=0x%02x ", @@ -2688,7 +2688,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_RSL_CONNECT_NACK: LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - DEBUGPC(DNM, " CAUSE=%s\n", + DEBUGPC(DNM, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else DEBUGPC(DNM, "\n"); @@ -2700,7 +2700,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_SET_NVATTR_NACK: LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2712,7 +2712,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_GET_NVATTR_NACK: LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2723,7 +2723,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg) case NM_MT_IPACC_SET_ATTR_NACK: LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK "); if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES)) - LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", + LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n", nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else LOGPC(DNM, LOGL_ERROR, "\n"); @@ -2800,7 +2800,7 @@ int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr, attr_len); } -int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, +int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, u_int32_t ip, u_int16_t port, u_int8_t stream) { struct in_addr ia; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 96a5ab896..939143f2e 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -1,4 +1,4 @@ -/* GSM Radio Signalling Link messages on the A-bis interface +/* GSM Radio Signalling Link messages on the A-bis interface * 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */ /* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org> @@ -118,8 +118,8 @@ struct gsm_lchan *lchan_lookup(struct gsm_bts_trx *trx, u_int8_t chan_nr) } lchan = &ts->lchan[lch_idx]; - debug_set_context(BSC_CTX_LCHAN, lchan); - debug_set_context(BSC_CTX_SUBSCR, lchan->subscr); + log_set_context(BSC_CTX_LCHAN, lchan); + log_set_context(BSC_CTX_SUBSCR, lchan->conn.subscr); return lchan; } @@ -222,7 +222,7 @@ static void print_rsl_cause(int lvl, const u_int8_t *cause_v, u_int8_t cause_len LOGPC(DRSL, lvl, "CAUSE=0x%02x(%s) ", cause_v[0], rsl_err_name(cause_v[0])); - for (i = 1; i < cause_len-1; i++) + for (i = 1; i < cause_len-1; i++) LOGPC(DRSL, lvl, "%02x ", cause_v[i]); } @@ -245,7 +245,7 @@ int rsl_bcch_info(struct gsm_bts_trx *trx, u_int8_t type, return abis_rsl_sendmsg(msg); } -int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, +int rsl_sacch_filling(struct gsm_bts_trx *trx, u_int8_t type, const u_int8_t *data, int len) { struct abis_rsl_common_hdr *ch; @@ -416,7 +416,7 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr, } #endif -int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, +int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type, u_int8_t ta, u_int8_t ho_ref) { struct abis_rsl_dchan_hdr *dh; @@ -779,7 +779,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) msg->lchan->state = LCHAN_S_NONE; } else msg->lchan->state = LCHAN_S_NONE; - + LOGPC(DRSL, LOGL_ERROR, "\n"); dispatch_signal(SS_LCHAN, S_LCHAN_ACTIVATE_NACK, msg->lchan); @@ -993,12 +993,14 @@ static int abis_rsl_rx_dchan(struct msgb *msg) break; case RSL_MT_IPAC_PDCH_ACT_ACK: DEBUGPC(DRSL, "%s IPAC PDCH ACT ACK\n", ts_name); + msg->lchan->ts->flags |= TS_F_PDCH_MODE; break; case RSL_MT_IPAC_PDCH_ACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH ACT NACK\n", ts_name); break; case RSL_MT_IPAC_PDCH_DEACT_ACK: DEBUGP(DRSL, "%s IPAC PDCH DEACT ACK\n", ts_name); + msg->lchan->ts->flags &= ~TS_F_PDCH_MODE; break; case RSL_MT_IPAC_PDCH_DEACT_NACK: LOGP(DRSL, LOGL_ERROR, "%s IPAC PDCH DEACT NACK\n", ts_name); @@ -1055,7 +1057,7 @@ static int abis_rsl_rx_trx(struct msgb *msg) //DEBUGP(DRSL, "%s RF Resource Indication\n", gsm_trx_name(msg->trx)); break; case RSL_MT_OVERLOAD: - /* indicate CCCH / ACCH / processor overload */ + /* indicate CCCH / ACCH / processor overload */ LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n", gsm_trx_name(msg->trx)); break; @@ -1245,7 +1247,7 @@ static int rsl_rx_rll_err_ind(struct msgb *msg) return 0; } -/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST +/* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST 0x02, 0x06, 0x01, 0x20, 0x02, 0x00, @@ -1265,7 +1267,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) switch (rllh->c.msg_type) { case RSL_MT_DATA_IND: DEBUGPC(DRLL, "DATA INDICATION\n"); - if (msgb_l2len(msg) > + if (msgb_l2len(msg) > sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) && rllh->data[0] == RSL_IE_L3_INFO) { msg->l3h = &rllh->data[3]; @@ -1277,7 +1279,7 @@ static int abis_rsl_rx_rll(struct msgb *msg) /* lchan is established, stop T3101 */ msg->lchan->sapis[rllh->link_id & 0x7] = LCHAN_SAPI_MS; bsc_del_timer(&msg->lchan->T3101); - if (msgb_l2len(msg) > + if (msgb_l2len(msg) > sizeof(struct abis_rsl_common_hdr) + sizeof(*rllh) && rllh->data[0] == RSL_IE_L3_INFO) { msg->l3h = &rllh->data[3]; @@ -1472,17 +1474,24 @@ int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan) return rc; } -int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan) +int rsl_ipacc_pdch_activate(struct gsm_lchan *lchan, int act) { struct msgb *msg = rsl_msgb_alloc(); struct abis_rsl_dchan_hdr *dh; + u_int8_t msg_type; + + if (act) + msg_type = RSL_MT_IPAC_PDCH_ACT; + else + msg_type = RSL_MT_IPAC_PDCH_DEACT; dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh)); - init_dchan_hdr(dh, RSL_MT_IPAC_PDCH_ACT); + init_dchan_hdr(dh, msg_type); dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN; dh->chan_nr = lchan2chan_nr(lchan); - DEBUGP(DRSL, "%s IPAC_PDCH_ACT\n", gsm_lchan_name(lchan)); + DEBUGP(DRSL, "%s IPAC_PDCH_%sACT\n", gsm_lchan_name(lchan), + act ? "" : "DE"); msg->trx = lchan->ts->trx; diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c index de426aa9c..8193ecd34 100644 --- a/openbsc/src/bs11_config.c +++ b/openbsc/src/bs11_config.c @@ -3,7 +3,7 @@ /* (C) 2009 by Harald Welte <laforge@gnumonks.org> * All Rights Reserved * - * This software is based on ideas (but not code) of BS11Config + * This software is based on ideas (but not code) of BS11Config * (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de> * * This program is free software; you can redistribute it and/or modify @@ -54,9 +54,9 @@ static enum bs11cfg_state bs11cfg_state = STATE_NONE; static char *command, *value; struct timer_list status_timer; -static const u_int8_t obj_li_attr[] = { +static const u_int8_t obj_li_attr[] = { NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00, - NM_ATT_BS11_L1_PROT_TYPE, 0x00, + NM_ATT_BS11_L1_PROT_TYPE, 0x00, NM_ATT_BS11_LINE_CFG, 0x00, }; static const u_int8_t obj_bbsig0_attr[] = { @@ -71,7 +71,7 @@ static const char *trx1_password = "1111111111"; static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 }; -static struct debug_target *stderr_target; +static struct log_target *stderr_target; /* dummy function to keep gsm_data.c happy */ struct counter *counter_alloc(const char *name) @@ -778,7 +778,7 @@ static void handle_options(int argc, char **argv) serial_port = optarg; break; case 'b': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 's': fname_software = optarg; @@ -834,10 +834,10 @@ int main(int argc, char **argv) struct gsm_network *gsmnet; int rc; - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); handle_options(argc, argv); bts_model_bs11_init(); diff --git a/openbsc/src/bsc_api.c b/openbsc/src/bsc_api.c new file mode 100644 index 000000000..b504752e1 --- /dev/null +++ b/openbsc/src/bsc_api.c @@ -0,0 +1,33 @@ +/* GSM 08.08 like API for OpenBSC. The bridge from MSC to BSC */ + +/* (C) 2010 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <openbsc/bsc_api.h> +#include <openbsc/abis_rsl.h> + + +int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, + struct msgb *msg, int link_id) +{ + msg->lchan = conn->lchan; + msg->trx = msg->lchan->ts->trx; + return rsl_data_request(msg, link_id); +} diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 4cde4ddec..a50d4ab0b 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -38,7 +38,7 @@ #include <openbsc/signal.h> /* MCC and MNC for the Location Area Identifier */ -static struct debug_target *stderr_target; +static struct log_target *stderr_target; struct gsm_network *bsc_gsmnet = 0; static const char *database_name = "hlr.sqlite3"; static const char *config_file = "openbsc.cfg"; @@ -127,10 +127,10 @@ static void handle_options(int argc, char** argv) print_help(); exit(0); case 's': - debug_set_use_color(stderr_target, 0); + log_set_use_color(stderr_target, 0); break; case 'd': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 'l': database_name = strdup(optarg); @@ -142,13 +142,13 @@ static void handle_options(int argc, char** argv) create_pcap_file(optarg); break; case 'T': - debug_set_print_timestamp(stderr_target, 1); + log_set_print_timestamp(stderr_target, 1); break; case 'P': ipacc_rtp_direct = 0; break; case 'e': - debug_set_log_level(stderr_target, atoi(optarg)); + log_set_log_level(stderr_target, atoi(optarg)); break; case 'V': print_version(); @@ -211,21 +211,21 @@ int main(int argc, char **argv) { int rc; - debug_init(); + log_init(&log_info); tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc"); talloc_ctx_init(); on_dso_load_token(); on_dso_load_rrlp(); on_dso_load_ho_dec(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); bts_model_unknown_init(); bts_model_bs11_init(); bts_model_nanobts_init(); /* enable filters */ - debug_set_all_filter(stderr_target, 1); + log_set_all_filter(stderr_target, 1); /* parse options */ handle_options(argc, argv); @@ -262,7 +262,7 @@ int main(int argc, char **argv) while (1) { bsc_upqueue(bsc_gsmnet); - debug_reset_context(); + log_reset_context(); bsc_select_main(0); } } diff --git a/openbsc/src/bsc_msc_ip.c b/openbsc/src/bsc_msc_ip.c index 4b7af742e..862bac02e 100644 --- a/openbsc/src/bsc_msc_ip.c +++ b/openbsc/src/bsc_msc_ip.c @@ -55,7 +55,7 @@ #define SCCP_IT_TIMER 60 /* MCC and MNC for the Location Area Identifier */ -static struct debug_target *stderr_target; +static struct log_target *stderr_target; struct gsm_network *bsc_gsmnet = 0; static const char *config_file = "openbsc.cfg"; static char *msc_address = "127.0.0.1"; @@ -167,7 +167,7 @@ void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state) DEBUGP(DMSC, "ERROR: The lchan is still associated\n."); lchan->msc_data = NULL; - put_lchan(lchan, 0); + put_subscr_con(&lchan->conn, 0); } bss_sccp_free_data((struct bss_sccp_connection_data *)conn->data_ctx); @@ -205,8 +205,8 @@ static int open_sccp_connection(struct msgb *layer3) /* When not connected to a MSC. We will simply close things down. */ if (!msc_con->is_connected) { LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n"); - use_lchan(layer3->lchan); - put_lchan(layer3->lchan, 0); + use_subscr_con(&layer3->lchan->conn); + put_subscr_con(&layer3->lchan->conn, 0); return -1; } @@ -242,7 +242,7 @@ static int open_sccp_connection(struct msgb *layer3) layer3->lchan->msc_data = con_data; /* FIXME: Use transaction for this */ - use_lchan(layer3->lchan); + use_subscr_con(&layer3->lchan->conn); sccp_connection_connect(sccp_connection, &sccp_ssn_bssap, data); msgb_free(data); @@ -326,20 +326,20 @@ static int handle_ass_compl(struct msgb *msg) if (!msg->lchan->msc_data) { LOGP(DMSC, LOGL_ERROR, "No MSC data\n"); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } if (msgb_l3len(msg) - sizeof(*gh) != 1) { DEBUGP(DMSC, "assignment failure invalid: %d\n", msgb_l3len(msg) - sizeof(*gh)); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } @@ -350,9 +350,9 @@ static int handle_ass_compl(struct msgb *msg) old_chan->msc_data = NULL; /* give up the old channel to not do a SACCH deactivate */ - subscr_put(old_chan->subscr); - old_chan->subscr = NULL; - put_lchan(old_chan, 1); + subscr_put(old_chan->conn.subscr); + old_chan->conn.subscr = NULL; + put_subscr_con(&old_chan->conn, 1); /* activate audio on it... */ if (is_ipaccess_bts(msg->lchan->ts->trx->bts) && msg->lchan->tch_mode != GSM48_CMODE_SIGN) @@ -373,20 +373,20 @@ static int handle_ass_fail(struct msgb *msg) DEBUGP(DMSC, "ASSIGNMENT FAILURE from MS, forwarding to MSC\n"); if (!msg->lchan->msc_data) { LOGP(DMSC, LOGL_ERROR, "No MSC data\n"); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } if (msg->lchan->msc_data->secondary_lchan != msg->lchan) { LOGP(DMSC, LOGL_NOTICE, "Wrong assignment complete.\n"); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } if (msgb_l3len(msg) - sizeof(*gh) != 1) { DEBUGP(DMSC, "assignment failure invalid: %d\n", msgb_l3len(msg) - sizeof(*gh)); - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); return -1; } @@ -806,13 +806,13 @@ static void msc_connection_was_lost(struct bsc_msc_connection *msc) llist_for_each_entry_safe(bss, tmp, &active_connections, active_connections) { if (bss->lchan) { bss->lchan->msc_data = NULL; - put_lchan(bss->lchan, 0); + put_subscr_con(&bss->lchan->conn, 0); bss->lchan = NULL; } if (bss->secondary_lchan) { bss->secondary_lchan->msc_data = NULL; - put_lchan(bss->secondary_lchan, 0); + put_subscr_con(&bss->secondary_lchan->conn, 0); bss->secondary_lchan = NULL; } @@ -911,16 +911,16 @@ static void handle_options(int argc, char** argv) print_help(); exit(0); case 's': - debug_set_use_color(stderr_target, 0); + log_set_use_color(stderr_target, 0); break; case 'd': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 'c': config_file = strdup(optarg); break; case 'T': - debug_set_print_timestamp(stderr_target, 1); + log_set_print_timestamp(stderr_target, 1); break; case 'P': ipacc_rtp_direct = 0; @@ -932,7 +932,7 @@ static void handle_options(int argc, char** argv) inet_aton(optarg, &local_addr); break; case 'e': - debug_set_log_level(stderr_target, atoi(optarg)); + log_set_log_level(stderr_target, atoi(optarg)); break; default: /* ignore */ @@ -1013,17 +1013,17 @@ extern int bts_model_nanobts_init(void); int main(int argc, char **argv) { - debug_init(); + log_init(&log_info); tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc"); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); bts_model_unknown_init(); bts_model_bs11_init(); bts_model_nanobts_init(); /* enable filters */ - debug_set_all_filter(stderr_target, 1); + log_set_all_filter(stderr_target, 1); /* parse options */ handle_options(argc, argv); diff --git a/openbsc/src/bsc_rll.c b/openbsc/src/bsc_rll.c index 5c849271b..368c2665b 100644 --- a/openbsc/src/bsc_rll.c +++ b/openbsc/src/bsc_rll.c @@ -51,8 +51,11 @@ static LLIST_HEAD(bsc_rll_reqs); static void complete_rllr(struct bsc_rll_req *rllr, enum bsc_rllr_ind type) { + struct gsm_subscriber_connection *conn; + + conn = &rllr->lchan->conn; llist_del(&rllr->list); - put_lchan(rllr->lchan, 0); + put_subscr_con(conn, 0); rllr->cb(rllr->lchan, rllr->link_id, rllr->data, type); talloc_free(rllr); } @@ -70,6 +73,7 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi, enum bsc_rllr_ind), void *data) { + struct gsm_subscriber_connection *conn; struct bsc_rll_req *rllr = talloc_zero(tall_bsc_ctx, struct bsc_rll_req); u_int8_t link_id; if (!rllr) @@ -83,7 +87,8 @@ int rll_establish(struct gsm_lchan *lchan, u_int8_t sapi, lchan->type == GSM_LCHAN_TCH_H) && sapi != 0) link_id |= 0x40; - use_lchan(lchan); + conn = &lchan->conn; + use_subscr_con(conn); rllr->lchan = lchan; rllr->link_id = link_id; rllr->cb = cb; diff --git a/openbsc/src/bssap.c b/openbsc/src/bssap.c index cdee92bc9..ec20341aa 100644 --- a/openbsc/src/bssap.c +++ b/openbsc/src/bssap.c @@ -191,10 +191,10 @@ static int bssmap_handle_clear_command(struct sccp_connection *conn, /* we might got killed during an assignment */ if (msg->lchan->msc_data->secondary_lchan) - put_lchan(msg->lchan->msc_data->secondary_lchan, 0); + put_subscr_con(&msg->lchan->msc_data->secondary_lchan->conn, 0); msg->lchan->msc_data = NULL; - put_lchan(msg->lchan, 0); + put_subscr_con(&msg->lchan->conn, 0); } /* send the clear complete message */ @@ -407,10 +407,10 @@ static int handle_new_assignment(struct msgb *msg, int full_rate, int chan_mode) memcpy(&new_lchan->encr, &msg->lchan->encr, sizeof(new_lchan->encr)); new_lchan->ms_power = msg->lchan->ms_power; new_lchan->bs_power = msg->lchan->bs_power; - new_lchan->subscr = subscr_get(msg->lchan->subscr); + new_lchan->conn.subscr = subscr_get(msg->lchan->conn.subscr); /* copy new data to it */ - use_lchan(new_lchan); + use_subscr_con(&new_lchan->conn); new_lchan->tch_mode = chan_mode; new_lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH; @@ -439,13 +439,13 @@ static void continue_new_assignment(struct gsm_lchan *new_lchan) { if (!new_lchan->msc_data) { LOGP(DMSC, LOGL_ERROR, "No BSS data found.\n"); - put_lchan(new_lchan, 0); + put_subscr_con(&new_lchan->conn, 0); return; } if (new_lchan->msc_data->secondary_lchan != new_lchan) { LOGP(DMSC, LOGL_ERROR, "This is not the secondary channel?\n"); - put_lchan(new_lchan, 0); + put_subscr_con(&new_lchan->conn, 0); return; } diff --git a/openbsc/src/chan_alloc.c b/openbsc/src/chan_alloc.c index 4274697e8..5ca47f909 100644 --- a/openbsc/src/chan_alloc.c +++ b/openbsc/src/chan_alloc.c @@ -150,6 +150,7 @@ static const u_int8_t subslots_per_pchan[] = { [GSM_PCHAN_TCH_H] = 2, [GSM_PCHAN_SDCCH8_SACCH8C] = 8, /* FIXME: what about dynamic TCH_F_TCH_H ? */ + [GSM_PCHAN_TCH_F_PDCH] = 1, }; static struct gsm_lchan * @@ -165,7 +166,14 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) ts = &trx->ts[j]; if (!ts_is_usable(ts)) continue; - if (ts->pchan != pchan) + /* ip.access dynamic TCH/F + PDCH combination */ + if (ts->pchan == GSM_PCHAN_TCH_F_PDCH && + pchan == GSM_PCHAN_TCH_F) { + /* we can only consider such a dynamic channel + * if the PDCH is currently inactive */ + if (ts->flags & TS_F_PDCH_MODE) + continue; + } else if (ts->pchan != pchan) continue; /* check if all sub-slots are allocated yet */ for (ss = 0; ss < subslots_per_pchan[pchan]; ss++) { @@ -175,6 +183,7 @@ _lc_find_trx(struct gsm_bts_trx *trx, enum gsm_phys_chan_config pchan) return lc; } } + return NULL; } @@ -250,7 +259,6 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) if (lchan) { lchan->type = type; - lchan->use_count = 0; /* clear sapis */ memset(lchan->sapis, 0, ARRAY_SIZE(lchan->sapis)); @@ -261,6 +269,15 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* clear any msc reference */ lchan->msc_data = NULL; + /* clear per MSC/BSC data */ + memset(&lchan->conn, 0, sizeof(lchan->conn)); + lchan->conn.lchan = lchan; + lchan->conn.bts = lchan->ts->trx->bts; + } else { + struct challoc_signal_data sig; + sig.bts = bts; + sig.type = type; + dispatch_signal(SS_CHALLOC, S_CHALLOC_ALLOC_FAIL, &sig); } return lchan; @@ -269,18 +286,20 @@ struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type) /* Free a logical channel */ void lchan_free(struct gsm_lchan *lchan) { + struct challoc_signal_data sig; int i; + sig.type = lchan->type; lchan->type = GSM_LCHAN_NONE; - if (lchan->subscr) { - subscr_put(lchan->subscr); - lchan->subscr = NULL; + if (lchan->conn.subscr) { + subscr_put(lchan->conn.subscr); + lchan->conn.subscr = NULL; } /* We might kill an active channel... */ - if (lchan->use_count != 0) { + if (lchan->conn.use_count != 0) { dispatch_signal(SS_LCHAN, S_LCHAN_UNEXPECTED_RELEASE, lchan); - lchan->use_count = 0; + lchan->conn.use_count = 0; } bsc_del_timer(&lchan->T3101); @@ -293,7 +312,11 @@ void lchan_free(struct gsm_lchan *lchan) } for (i = 0; i < ARRAY_SIZE(lchan->neigh_meas); i++) lchan->neigh_meas[i].arfcn = 0; - lchan->silent_call = 0; + lchan->conn.silent_call = 0; + + sig.lchan = lchan; + sig.bts = lchan->ts->trx->bts; + dispatch_signal(SS_CHALLOC, S_CHALLOC_FREED, &sig); /* FIXME: ts_free() the timeslot, if we're the last logical * channel using it */ @@ -302,22 +325,22 @@ void lchan_free(struct gsm_lchan *lchan) /* Consider releasing the channel now */ int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) { - if (lchan->use_count > 0) { + if (lchan->conn.use_count > 0) { DEBUGP(DRLL, "BUG: _lchan_release called without zero use_count.\n"); return 0; } /* Assume we have GSM04.08 running and send a release */ - if (lchan->subscr) { - ++lchan->use_count; + if (lchan->conn.subscr) { + ++lchan->conn.use_count; gsm48_send_rr_release(lchan); - --lchan->use_count; + --lchan->conn.use_count; } /* spoofed? message */ - if (lchan->use_count < 0) + if (lchan->conn.use_count < 0) LOGP(DRLL, LOGL_ERROR, "Channel count is negative: %d\n", - lchan->use_count); + lchan->conn.use_count); DEBUGP(DRLL, "%s Recycling Channel\n", gsm_lchan_name(lchan)); rsl_release_request(lchan, 0, release_reason); @@ -326,14 +349,14 @@ int _lchan_release(struct gsm_lchan *lchan, u_int8_t release_reason) struct gsm_lchan* lchan_find(struct gsm_bts *bts, struct gsm_subscriber *subscr) { struct gsm_bts_trx *trx; - int ts_no, lchan_no; + int ts_no, lchan_no; llist_for_each_entry(trx, &bts->trx_list, list) { for (ts_no = 0; ts_no < 8; ++ts_no) { for (lchan_no = 0; lchan_no < TS_MAX_LCHAN; ++lchan_no) { struct gsm_lchan *lchan = &trx->ts[ts_no].lchan[lchan_no]; - if (subscr == lchan->subscr) + if (subscr == lchan->conn.subscr) return lchan; } } diff --git a/openbsc/src/db.c b/openbsc/src/db.c index 10c1d6d4c..8bf47ab38 100644 --- a/openbsc/src/db.c +++ b/openbsc/src/db.c @@ -254,7 +254,7 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) struct gsm_subscriber *subscr; /* Is this subscriber known in the db? */ - subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); + subscr = db_get_subscriber(net, GSM_SUBSCRIBER_IMSI, imsi); if (subscr) { result = dbi_conn_queryf(conn, "UPDATE Subscriber set updated = datetime('now') " @@ -288,6 +288,8 @@ struct gsm_subscriber *db_create_subscriber(struct gsm_network *net, char *imsi) return subscr; } +static_assert(sizeof(unsigned char) == sizeof(struct gsm48_classmark1), classmark1_size); + static int get_equipment_by_subscr(struct gsm_subscriber *subscr) { dbi_result result; @@ -316,9 +318,10 @@ static int get_equipment_by_subscr(struct gsm_subscriber *subscr) strncpy(equip->imei, string, sizeof(equip->imei)); string = dbi_result_get_string(result, "classmark1"); - if (string) - cm1 = atoi(string) & 0xff; - equip->classmark1 = *((struct gsm48_classmark1 *) &cm1); + if (string) { + cm1 = atoi(string) & 0xff; + memcpy(&equip->classmark1, &cm1, sizeof(equip->classmark1)); + } equip->classmark2_len = dbi_result_get_field_length(result, "classmark2"); cm2 = dbi_result_get_binary(result, "classmark2"); @@ -1014,7 +1017,7 @@ static struct gsm_sms *sms_from_result(struct gsm_network *net, dbi_result resul } /* retrieve the next unsent SMS with ID >= min_id */ -struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id) +struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, unsigned long long min_id) { dbi_result result; struct gsm_sms *sms; @@ -1041,7 +1044,7 @@ struct gsm_sms *db_sms_get_unsent(struct gsm_network *net, int min_id) return sms; } -struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_subscr_id) +struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, unsigned long long min_subscr_id) { dbi_result result; struct gsm_sms *sms; @@ -1049,7 +1052,7 @@ struct gsm_sms *db_sms_get_unsent_by_subscr(struct gsm_network *net, int min_sub result = dbi_conn_queryf(conn, "SELECT * FROM SMS,Subscriber " "WHERE sms.receiver_id >= %llu AND sms.sent is NULL " - "AND sms.receiver_id = subscriber.id " + "AND sms.receiver_id = subscriber.id " "AND subscriber.lac > 0 " "ORDER BY sms.receiver_id, id LIMIT 1", min_subscr_id); @@ -1133,7 +1136,7 @@ int db_sms_inc_deliver_attempts(struct gsm_sms *sms) return 0; } -int db_apdu_blob_store(struct gsm_subscriber *subscr, +int db_apdu_blob_store(struct gsm_subscriber *subscr, u_int8_t apdu_id_flags, u_int8_t len, u_int8_t *apdu) { diff --git a/openbsc/src/debug.c b/openbsc/src/debug.c index 5ffd5546f..aaf8f88fc 100644 --- a/openbsc/src/debug.c +++ b/openbsc/src/debug.c @@ -1,5 +1,6 @@ -/* Debugging/Logging support code */ -/* (C) 2008 by Harald Welte <laforge@gnumonks.org> +/* OpenBSC Debugging/Logging support code */ + +/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org> * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org> * All Rights Reserved * @@ -27,403 +28,166 @@ #include <time.h> #include <errno.h> -#include <openbsc/debug.h> #include <osmocore/talloc.h> #include <osmocore/utils.h> +#include <osmocore/logging.h> #include <openbsc/gsm_data.h> #include <openbsc/gsm_subscriber.h> +#include <openbsc/debug.h> /* default categories */ -static struct debug_category default_categories[Debug_LastEntry] = { - [DRLL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DNM] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DRR] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DRSL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMM] = { .enabled = 1, .loglevel = LOGL_INFO }, - [DMNCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DSMS] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DPAG] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMEAS] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMI] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMIB] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DMUX] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DINP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DSCCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMSC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DMGCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DHO] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DDB] = { .enabled = 1, .loglevel = LOGL_NOTICE }, - [DREF] = { .enabled = 0, .loglevel = LOGL_NOTICE }, - [DNAT] = { .enabled = 1, .loglevel = LOGL_NOTICE }, -}; - -struct debug_info { - const char *name; - const char *color; - const char *description; - int number; - int position; -}; - -struct debug_context { - struct gsm_lchan *lchan; - struct gsm_subscriber *subscr; - struct gsm_bts *bts; +static const struct log_info_cat default_categories[] = { + [DRLL] = { + .name = "DRLL", + .description = "Radio Link Layer", + .color = "\033[1;31m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DCC] = { + .name = "DCC", + .description = "Call Control", + .color = "\033[1;32m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMM] = { + .name = "DMM", + .description = "Mobility Management", + .color = "\033[1;33m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DRR] = { + .name = "DRR", + .description = "Radio Resource", + .color = "\033[1;34m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DRSL] = { + .name = "DRSL", + .description = "Radio Siganlling Link", + .color = "\033[1;35m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DNM] = { + .name = "DNM", + .description = "Network Management (OML)", + .color = "\033[1;36m", + .enabled = 1, .loglevel = LOGL_INFO, + }, + [DMNCC] = { + .name = "DMNCC", + .description = "BSC<->MSC interface", + .color = "\033[1;39m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DSMS] = { + .name = "DSMS", + .description = "Short Message Service", + .color = "\033[1;37m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DPAG] = { + .name = "DPAG", + .description = "Paging", + .color = "\033[1;38m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMEAS] = { + .name = "DMEAS", + .description = "Measurement Processing", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMI] = { + .name = "DMI", + .description = "mISDN Input Driver", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMIB] = { + .name = "DMIB", + .description = "mISDN B-Channels", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DMUX] = { + .name = "DMUX", + .description = "TRAU Frame Multiplex", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DINP] = { + .name = "DINP", + .description = "Input Driver", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DSCCP] = { + .name = "DSCCP", + .description = "SCCP Protocol", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMSC] = { + .name = "DMSC", + .description = "Mobile Switching Center", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DMGCP] = { + .name = "DMGCP", + .description = "Media Gateway Control Protocol", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DHO] = { + .name = "DHO", + .description = "Hand-Over", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DDB] = { + .name = "DDB", + .description = "Database", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DREF] = { + .name = "DREF", + .description = "Reference Counting", + .enabled = 0, .loglevel = LOGL_NOTICE, + }, + [DNAT] = { + .name = "DNAT", + .description = "BSC MUX/NAT", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, }; -static struct debug_context debug_context; -static void *tall_dbg_ctx = NULL; -static LLIST_HEAD(target_list); - -#define DEBUG_CATEGORY(NUMBER, NAME, COLOR, DESCRIPTION) \ - { .name = NAME, .color = COLOR, .description = DESCRIPTION, .number = NUMBER }, - -static const struct debug_info debug_info[] = { - DEBUG_CATEGORY(DRLL, "DRLL", "\033[1;31m", "") - DEBUG_CATEGORY(DCC, "DCC", "\033[1;32m", "") - DEBUG_CATEGORY(DMM, "DMM", "\033[1;33m", "") - DEBUG_CATEGORY(DRR, "DRR", "\033[1;34m", "") - DEBUG_CATEGORY(DRSL, "DRSL", "\033[1;35m", "") - DEBUG_CATEGORY(DNM, "DNM", "\033[1;36m", "") - DEBUG_CATEGORY(DSMS, "DSMS", "\033[1;37m", "") - DEBUG_CATEGORY(DPAG, "DPAG", "\033[1;38m", "") - DEBUG_CATEGORY(DMNCC, "DMNCC","\033[1;39m", "") - DEBUG_CATEGORY(DINP, "DINP", "", "") - DEBUG_CATEGORY(DMI, "DMI", "", "") - DEBUG_CATEGORY(DMIB, "DMIB", "", "") - DEBUG_CATEGORY(DMUX, "DMUX", "", "") - DEBUG_CATEGORY(DMEAS, "DMEAS", "", "") - DEBUG_CATEGORY(DSCCP, "DSCCP", "", "") - DEBUG_CATEGORY(DMSC, "DMSC", "", "") - DEBUG_CATEGORY(DMGCP, "DMGCP", "", "") - DEBUG_CATEGORY(DHO, "DHO", "", "") - DEBUG_CATEGORY(DNAT, "DNAT", "", "") - DEBUG_CATEGORY(DDB, "DDB", "", "") - DEBUG_CATEGORY(DREF, "DREF", "", "") +enum log_ctxt { + CTX_SUBSCRIBER, }; -static const struct value_string loglevel_strs[] = { - { 0, "EVERYTHING" }, - { 1, "DEBUG" }, - { 3, "INFO" }, - { 5, "NOTICE" }, - { 7, "ERROR" }, - { 8, "FATAL" }, - { 0, NULL }, +enum log_filter { + _FLT_ALL = LOG_FILTER_ALL, /* libosmocore */ + FLT_IMSI = 1, }; -int debug_parse_level(const char *lvl) -{ - return get_string_value(loglevel_strs, lvl); -} - -int debug_parse_category(const char *category) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { - if (!strcasecmp(debug_info[i].name+1, category)) - return debug_info[i].number; - } - - return -EINVAL; -} - -/* - * Parse the category mask. - * The format can be this: category1:category2:category3 - * or category1,2:category2,3:... - */ -void debug_parse_category_mask(struct debug_target* target, const char *_mask) -{ - int i = 0; - char *mask = strdup(_mask); - char *category_token = NULL; - - /* Disable everything to enable it afterwards */ - for (i = 0; i < ARRAY_SIZE(target->categories); ++i) - target->categories[i].enabled = 0; - - category_token = strtok(mask, ":"); - do { - for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { - char* colon = strstr(category_token, ","); - int length = strlen(category_token); - - if (colon) - length = colon - category_token; - - if (strncasecmp(debug_info[i].name, category_token, length) == 0) { - int number = debug_info[i].number; - int level = 0; - - if (colon) - level = atoi(colon+1); - - target->categories[number].enabled = 1; - target->categories[number].loglevel = level; - } - } - } while ((category_token = strtok(NULL, ":"))); - - free(mask); -} - -static const char* color(int subsys) -{ - int i = 0; - - for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { - if (debug_info[i].number == subsys) - return debug_info[i].color; - } - - return ""; -} - -static void _output(struct debug_target *target, unsigned int subsys, char *file, int line, - int cont, const char *format, va_list ap) -{ - char col[30]; - char sub[30]; - char tim[30]; - char buf[4096]; - char final[4096]; - - /* prepare the data */ - col[0] = '\0'; - sub[0] = '\0'; - tim[0] = '\0'; - buf[0] = '\0'; - - /* are we using color */ - if (target->use_color) { - snprintf(col, sizeof(col), "%s", color(subsys)); - col[sizeof(col)-1] = '\0'; - } - vsnprintf(buf, sizeof(buf), format, ap); - buf[sizeof(buf)-1] = '\0'; - - if (!cont) { - if (target->print_timestamp) { - char *timestr; - time_t tm; - tm = time(NULL); - timestr = ctime(&tm); - timestr[strlen(timestr)-1] = '\0'; - snprintf(tim, sizeof(tim), "%s ", timestr); - tim[sizeof(tim)-1] = '\0'; - } - snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); - sub[sizeof(sub)-1] = '\0'; - } - - snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); - final[sizeof(final)-1] = '\0'; - target->output(target, final); -} - - -static void _debugp(unsigned int subsys, int level, char *file, int line, - int cont, const char *format, va_list ap) -{ - struct debug_target *tar; - - llist_for_each_entry(tar, &target_list, entry) { - struct debug_category *category; - int output = 0; - - category = &tar->categories[subsys]; - /* subsystem is not supposed to be debugged */ - if (!category->enabled) - continue; - - /* Check the global log level */ - if (tar->loglevel != 0 && level < tar->loglevel) - continue; - - /* Check the category log level */ - if (tar->loglevel == 0 && category->loglevel != 0 && level < category->loglevel) - continue; - - /* - * Apply filters here... if that becomes messy we will need to put - * filters in a list and each filter will say stop, continue, output - */ - if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) { - output = 1; - } else if ((tar->filter_map & DEBUG_FILTER_IMSI) != 0 - && debug_context.subscr && strcmp(debug_context.subscr->imsi, tar->imsi_filter) == 0) { - output = 1; - } - - if (output) { - /* FIXME: copying the va_list is an ugly workaround against a bug - * hidden somewhere in _output. If we do not copy here, the first - * call to _output() will corrupt the va_list contents, and any - * further _output() calls with the same va_list will segfault */ - va_list bp; - va_copy(bp, ap); - _output(tar, subsys, file, line, cont, format, bp); - va_end(bp); - } - } -} - -void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) +static int filter_fn(const struct log_context *ctx, + struct log_target *tar) { - va_list ap; + struct gsm_subscriber *subscr = ctx->ctx[CTX_SUBSCRIBER]; - va_start(ap, format); - _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap); - va_end(ap); -} - -void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - _debugp(subsys, level, file, line, cont, format, ap); - va_end(ap); -} - -static char hexd_buff[4096]; - -char *hexdump(const unsigned char *buf, int len) -{ - int i; - char *cur = hexd_buff; - - hexd_buff[0] = 0; - for (i = 0; i < len; i++) { - int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); - int rc = snprintf(cur, len_remain, "%02x ", buf[i]); - if (rc <= 0) - break; - cur += rc; - } - hexd_buff[sizeof(hexd_buff)-1] = 0; - return hexd_buff; -} - - - -void debug_add_target(struct debug_target *target) -{ - llist_add_tail(&target->entry, &target_list); -} + if ((tar->filter_map & (1 << FLT_IMSI)) != 0 + && subscr && strcmp(subscr->imsi, tar->filter_data[FLT_IMSI]) == 0) + return 1; -void debug_del_target(struct debug_target *target) -{ - llist_del(&target->entry); + return 0; } -void debug_reset_context(void) -{ - memset(&debug_context, 0, sizeof(debug_context)); -} - -/* currently we are not reffing these */ -void debug_set_context(int ctx, void *value) -{ - switch (ctx) { - case BSC_CTX_LCHAN: - debug_context.lchan = (struct gsm_lchan *) value; - break; - case BSC_CTX_SUBSCR: - debug_context.subscr = (struct gsm_subscriber *) value; - break; - case BSC_CTX_BTS: - debug_context.bts = (struct gsm_bts *) value; - break; - case BSC_CTX_SCCP: - break; - default: - break; - } -} +const struct log_info log_info = { + .filter_fn = filter_fn, + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; -void debug_set_imsi_filter(struct debug_target *target, const char *imsi) +void log_set_imsi_filter(struct log_target *target, const char *imsi) { if (imsi) { - target->filter_map |= DEBUG_FILTER_IMSI; - target->imsi_filter = talloc_strdup(target, imsi); - } else if (target->imsi_filter) { - target->filter_map &= ~DEBUG_FILTER_IMSI; - talloc_free(target->imsi_filter); - target->imsi_filter = NULL; + target->filter_map |= (1 << FLT_IMSI); + target->filter_data[FLT_IMSI] = talloc_strdup(target, imsi); + } else if (target->filter_data[FLT_IMSI]) { + target->filter_map &= ~(1 << FLT_IMSI); + talloc_free(target->filter_data[FLT_IMSI]); + target->filter_data[FLT_IMSI] = NULL; } } - -void debug_set_all_filter(struct debug_target *target, int all) -{ - if (all) - target->filter_map |= DEBUG_FILTER_ALL; - else - target->filter_map &= ~DEBUG_FILTER_ALL; -} - -void debug_set_use_color(struct debug_target *target, int use_color) -{ - target->use_color = use_color; -} - -void debug_set_print_timestamp(struct debug_target *target, int print_timestamp) -{ - target->print_timestamp = print_timestamp; -} - -void debug_set_log_level(struct debug_target *target, int log_level) -{ - target->loglevel = log_level; -} - -void debug_set_category_filter(struct debug_target *target, int category, int enable, int level) -{ - if (category >= Debug_LastEntry) - return; - target->categories[category].enabled = !!enable; - target->categories[category].loglevel = level; -} - -static void _stderr_output(struct debug_target *target, const char *log) -{ - fprintf(target->tgt_stdout.out, "%s", log); - fflush(target->tgt_stdout.out); -} - -struct debug_target *debug_target_create(void) -{ - struct debug_target *target; - - target = talloc_zero(tall_dbg_ctx, struct debug_target); - if (!target) - return NULL; - - INIT_LLIST_HEAD(&target->entry); - memcpy(target->categories, default_categories, sizeof(default_categories)); - target->use_color = 1; - target->print_timestamp = 0; - target->loglevel = 0; - return target; -} - -struct debug_target *debug_target_create_stderr(void) -{ - struct debug_target *target; - - target = debug_target_create(); - if (!target) - return NULL; - - target->tgt_stdout.out = stderr; - target->output = _stderr_output; - return target; -} - -void debug_init(void) -{ - tall_dbg_ctx = talloc_named_const(NULL, 1, "debug"); -} diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c index c20359c09..fba59a784 100644 --- a/openbsc/src/e1_input.c +++ b/openbsc/src/e1_input.c @@ -442,7 +442,7 @@ int e1inp_rx_ts(struct e1inp_ts *ts, struct msgb *msg, return -EINVAL; } - debug_set_context(BSC_CTX_BTS, link->trx->bts); + log_set_context(BSC_CTX_BTS, link->trx->bts); switch (link->type) { case E1INP_SIGN_OML: msg->trx = link->trx; diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 5c0bc8be9..f8602a330 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1,4 +1,4 @@ -/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface +/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */ /* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org> @@ -58,7 +58,7 @@ void *tall_locop_ctx; int gsm0408_loc_upd_acc(struct gsm_lchan *lchan, u_int32_t tmsi); static int gsm48_tx_simple(struct gsm_lchan *lchan, u_int8_t pdisc, u_int8_t msg_type); -static void schedule_reject(struct gsm_lchan *lchan); +static void schedule_reject(struct gsm_subscriber_connection *conn); struct gsm_lai { u_int16_t mcc; @@ -96,34 +96,34 @@ static int authorize_subscriber(struct gsm_loc_updating_operation *loc, } } -static void release_loc_updating_req(struct gsm_lchan *lchan) +static void release_loc_updating_req(struct gsm_subscriber_connection *conn) { - if (!lchan->loc_operation) + if (!conn->loc_operation) return; - bsc_del_timer(&lchan->loc_operation->updating_timer); - talloc_free(lchan->loc_operation); - lchan->loc_operation = 0; - put_lchan(lchan, 0); + bsc_del_timer(&conn->loc_operation->updating_timer); + talloc_free(conn->loc_operation); + conn->loc_operation = 0; + put_subscr_con(conn, 0); } -static void allocate_loc_updating_req(struct gsm_lchan *lchan) +static void allocate_loc_updating_req(struct gsm_subscriber_connection *conn) { - use_lchan(lchan); - release_loc_updating_req(lchan); + use_subscr_con(conn); + release_loc_updating_req(conn); - lchan->loc_operation = talloc_zero(tall_locop_ctx, + conn->loc_operation = talloc_zero(tall_locop_ctx, struct gsm_loc_updating_operation); } -static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg) +static int gsm0408_authorize(struct gsm_subscriber_connection *conn, struct msgb *msg) { - if (authorize_subscriber(lchan->loc_operation, lchan->subscr)) { + if (authorize_subscriber(conn->loc_operation, conn->subscr)) { int rc; - db_subscriber_alloc_tmsi(lchan->subscr); - rc = gsm0408_loc_upd_acc(msg->lchan, lchan->subscr->tmsi); - if (lchan->ts->trx->bts->network->send_mm_info) { + db_subscriber_alloc_tmsi(conn->subscr); + rc = gsm0408_loc_upd_acc(msg->lchan, conn->subscr->tmsi); + if (msg->lchan->ts->trx->bts->network->send_mm_info) { /* send MM INFO with network name */ rc = gsm48_tx_mm_info(msg->lchan); } @@ -131,9 +131,9 @@ static int gsm0408_authorize(struct gsm_lchan *lchan, struct msgb *msg) /* call subscr_update after putting the loc_upd_acc * in the transmit queue, since S_SUBSCR_ATTACHED might * trigger further action like SMS delivery */ - subscr_update(lchan->subscr, msg->trx->bts, + subscr_update(conn->subscr, msg->trx->bts, GSM_SUBSCRIBER_UPDATE_ATTACHED); - release_loc_updating_req(lchan); + release_loc_updating_req(conn); return rc; } @@ -156,14 +156,14 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, if (!lchan) return 0; - release_loc_updating_req(lchan); + release_loc_updating_req(&lchan->conn); /* Free all transactions that are associated with the released lchan */ /* FIXME: this is not neccessarily the right thing to do, we should * only set trans->lchan to NULL and wait for another lchan to be * established to the same MM entity (phone/subscriber) */ llist_for_each_entry_safe(trans, temp, &lchan->ts->trx->bts->network->trans_list, entry) { - if (trans->lchan == lchan) + if (trans->conn && trans->conn->lchan == lchan) trans_free(trans); } @@ -173,11 +173,13 @@ static int gsm0408_handle_lchan_signal(unsigned int subsys, unsigned int signal, /* Chapter 9.2.14 : Send LOCATION UPDATING REJECT */ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) { + struct gsm_subscriber_connection *conn; struct gsm_bts *bts = lchan->ts->trx->bts; struct msgb *msg = gsm48_msgb_alloc(); struct gsm48_hdr *gh; msg->lchan = lchan; + conn = &lchan->conn; gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); gh->proto_discr = GSM48_PDISC_MM; @@ -185,8 +187,8 @@ int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause) gh->data[0] = cause; LOGP(DMM, LOGL_INFO, "Subscriber %s: LOCATION UPDATING REJECT " - "LAC=%u BTS=%u\n", lchan->subscr ? - subscr_name(lchan->subscr) : "unknown", + "LAC=%u BTS=%u\n", conn->subscr ? + subscr_name(conn->subscr) : "unknown", lchan->ts->trx->bts->location_area_code, lchan->ts->trx->bts->nr); counter_inc(bts->network->stats.loc_upd_resp.reject); @@ -243,6 +245,7 @@ static int mm_tx_identity_req(struct gsm_lchan *lchan, u_int8_t id_type) /* Parse Chapter 9.2.11 Identity Response */ static int mm_rx_id_resp(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm_lchan *lchan = msg->lchan; struct gsm_bts *bts = lchan->ts->trx->bts; @@ -254,50 +257,53 @@ static int mm_rx_id_resp(struct msgb *msg) DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n", mi_type, mi_string); + conn = &lchan->conn; + dispatch_signal(SS_SUBSCR, S_SUBSCR_IDENTITY, gh->data); switch (mi_type) { case GSM_MI_TYPE_IMSI: /* look up subscriber based on IMSI, create if not found */ - if (!lchan->subscr) { - lchan->subscr = subscr_get_by_imsi(net, mi_string); - if (!lchan->subscr) - lchan->subscr = db_create_subscriber(net, mi_string); + if (!conn->subscr) { + conn->subscr = subscr_get_by_imsi(net, mi_string); + if (!conn->subscr) + conn->subscr = db_create_subscriber(net, mi_string); } - if (lchan->loc_operation) - lchan->loc_operation->waiting_for_imsi = 0; + if (conn->loc_operation) + conn->loc_operation->waiting_for_imsi = 0; break; case GSM_MI_TYPE_IMEI: case GSM_MI_TYPE_IMEISV: /* update subscribe <-> IMEI mapping */ - if (lchan->subscr) { - db_subscriber_assoc_imei(lchan->subscr, mi_string); - db_sync_equipment(&lchan->subscr->equipment); + if (conn->subscr) { + db_subscriber_assoc_imei(conn->subscr, mi_string); + db_sync_equipment(&conn->subscr->equipment); } - if (lchan->loc_operation) - lchan->loc_operation->waiting_for_imei = 0; + if (conn->loc_operation) + conn->loc_operation->waiting_for_imei = 0; break; } /* Check if we can let the mobile station enter */ - return gsm0408_authorize(lchan, msg); + return gsm0408_authorize(conn, msg); } static void loc_upd_rej_cb(void *data) { - struct gsm_lchan *lchan = data; + struct gsm_subscriber_connection *conn = data; + struct gsm_lchan *lchan = conn->lchan; struct gsm_bts *bts = lchan->ts->trx->bts; gsm0408_loc_upd_rej(lchan, bts->network->reject_cause); - release_loc_updating_req(lchan); + release_loc_updating_req(conn); } -static void schedule_reject(struct gsm_lchan *lchan) +static void schedule_reject(struct gsm_subscriber_connection *conn) { - lchan->loc_operation->updating_timer.cb = loc_upd_rej_cb; - lchan->loc_operation->updating_timer.data = lchan; - bsc_schedule_timer(&lchan->loc_operation->updating_timer, 5, 0); + conn->loc_operation->updating_timer.cb = loc_upd_rej_cb; + conn->loc_operation->updating_timer.data = conn; + bsc_schedule_timer(&conn->loc_operation->updating_timer, 5, 0); } static const char *lupd_name(u_int8_t type) @@ -317,6 +323,7 @@ static const char *lupd_name(u_int8_t type) /* Chapter 9.2.15: Receive Location Updating Request */ static int mm_rx_loc_upd_req(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_loc_upd_req *lu; struct gsm_subscriber *subscr = NULL; @@ -327,6 +334,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) int rc; lu = (struct gsm48_loc_upd_req *) gh->data; + conn = &lchan->conn; mi_type = lu->mi[0] & GSM_MI_TYPE_MASK; @@ -353,21 +361,21 @@ static int mm_rx_loc_upd_req(struct msgb *msg) * Pseudo Spoof detection: Just drop a second/concurrent * location updating request. */ - if (lchan->loc_operation) { + if (conn->loc_operation) { DEBUGPC(DMM, "ignoring request due an existing one: %p.\n", - lchan->loc_operation); + conn->loc_operation); gsm0408_loc_upd_rej(lchan, GSM48_REJECT_PROTOCOL_ERROR); return 0; } - allocate_loc_updating_req(lchan); + allocate_loc_updating_req(&lchan->conn); switch (mi_type) { case GSM_MI_TYPE_IMSI: DEBUGPC(DMM, "\n"); /* we always want the IMEI, too */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); - lchan->loc_operation->waiting_for_imei = 1; + conn->loc_operation->waiting_for_imei = 1; /* look up subscriber based on IMSI, create if not found */ subscr = subscr_get_by_imsi(bts->network, mi_string); @@ -379,7 +387,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) DEBUGPC(DMM, "\n"); /* we always want the IMEI, too */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); - lchan->loc_operation->waiting_for_imei = 1; + conn->loc_operation->waiting_for_imei = 1; /* look up the subscriber based on TMSI, request IMSI if it fails */ subscr = subscr_get_by_tmsi(bts->network, @@ -387,7 +395,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI); - lchan->loc_operation->waiting_for_imsi = 1; + conn->loc_operation->waiting_for_imsi = 1; } break; case GSM_MI_TYPE_IMEI: @@ -401,7 +409,7 @@ static int mm_rx_loc_upd_req(struct msgb *msg) } /* schedule the reject timer */ - schedule_reject(lchan); + schedule_reject(conn); if (!subscr) { DEBUGPC(DRR, "<- Can't find any subscriber for this ID\n"); @@ -409,12 +417,12 @@ static int mm_rx_loc_upd_req(struct msgb *msg) return -EINVAL; } - lchan->subscr = subscr; - lchan->subscr->equipment.classmark1 = lu->classmark1; + conn->subscr = subscr; + conn->subscr->equipment.classmark1 = lu->classmark1; /* check if we can let the subscriber into our network immediately * or if we need to wait for identity responses. */ - return gsm0408_authorize(lchan, msg); + return gsm0408_authorize(conn, msg); } #if 0 @@ -563,7 +571,7 @@ static int gsm48_tx_mm_serv_ack(struct gsm_lchan *lchan) } /* 9.2.6 CM service reject */ -static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan, +static int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn, enum gsm48_reject_value value) { struct msgb *msg = gsm48_msgb_alloc(); @@ -571,8 +579,8 @@ static int gsm48_tx_mm_serv_rej(struct gsm_lchan *lchan, gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1); - msg->lchan = lchan; - use_lchan(lchan); + msg->lchan = conn->lchan; + use_subscr_con(conn); gh->proto_discr = GSM48_PDISC_MM; gh->msg_type = GSM48_MT_MM_CM_SERV_REJ; @@ -610,20 +618,20 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) DEBUGP(DMM, "<- CM SERVICE REQUEST "); if (msg->data_len < sizeof(struct gsm48_service_request*)) { DEBUGPC(DMM, "wrong sized message\n"); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } if (msg->data_len < req->mi_len + 6) { DEBUGPC(DMM, "does not fit in packet\n"); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } mi_type = mi[0] & GSM_MI_TYPE_MASK; if (mi_type != GSM_MI_TYPE_TMSI) { DEBUGPC(DMM, "mi_type is not TMSI: %d\n", mi_type); - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_INCORRECT_MESSAGE); } @@ -641,12 +649,12 @@ static int gsm48_rx_mm_serv_req(struct msgb *msg) /* FIXME: if we don't know the TMSI, inquire abit IMSI and allocate new TMSI */ if (!subscr) - return gsm48_tx_mm_serv_rej(msg->lchan, + return gsm48_tx_mm_serv_rej(&msg->lchan->conn, GSM48_REJECT_IMSI_UNKNOWN_IN_HLR); - if (!msg->lchan->subscr) - msg->lchan->subscr = subscr; - else if (msg->lchan->subscr == subscr) + if (!msg->lchan->conn.subscr) + msg->lchan->conn.subscr = subscr; + else if (msg->lchan->conn.subscr == subscr) subscr_put(subscr); /* lchan already has a ref, don't need another one */ else { DEBUGP(DMM, "<- CM Channel already owned by someone else?\n"); @@ -744,8 +752,8 @@ static int gsm0408_rcv_mm(struct msgb *msg) break; case GSM48_MT_MM_TMSI_REALL_COMPL: DEBUGP(DMM, "TMSI Reallocation Completed. Subscriber: %s\n", - msg->lchan->subscr ? - subscr_name(msg->lchan->subscr) : + msg->lchan->conn.subscr ? + subscr_name(msg->lchan->conn.subscr) : "unknown subscriber"); break; case GSM48_MT_MM_IMSI_DETACH_IND: @@ -810,7 +818,7 @@ static int gsm48_rx_rr_pag_resp(struct msgb *msg) static int gsm48_rx_rr_classmark(struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); - struct gsm_subscriber *subscr = msg->lchan->subscr; + struct gsm_subscriber *subscr = msg->lchan->conn.subscr; unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh); u_int8_t cm2_len, cm3_len = 0; u_int8_t *cm2, *cm3 = NULL; @@ -858,7 +866,7 @@ static int gsm48_rx_rr_status(struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); - DEBUGP(DRR, "STATUS rr_cause = %s\n", + DEBUGP(DRR, "STATUS rr_cause = %s\n", rr_cause_name(gh->data[0])); return 0; @@ -891,7 +899,7 @@ static int gsm48_rx_rr_app_info(struct msgb *msg) DEBUGP(DNM, "RX APPLICATION INFO id/flags=0x%02x apdu_len=%u apdu=%s", apdu_id_flags, apdu_len, hexdump(apdu_data, apdu_len)); - return db_apdu_blob_store(msg->lchan->subscr, apdu_id_flags, apdu_len, apdu_data); + return db_apdu_blob_store(msg->lchan->conn.subscr, apdu_id_flags, apdu_len, apdu_data); } /* Chapter 9.1.16 Handover complete */ @@ -1050,19 +1058,19 @@ static void gsm48_stop_cc_timer(struct gsm_trans *trans) trans->cc.Tcurrent = 0; } } - + static int mncc_recvmsg(struct gsm_network *net, struct gsm_trans *trans, int msg_type, struct gsm_mncc *mncc) { struct msgb *msg; if (trans) - if (trans->lchan) + if (trans->conn) DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Sending '%s' to MNCC.\n", - trans->lchan->ts->trx->bts->nr, - trans->lchan->ts->trx->nr, - trans->lchan->ts->nr, trans->transaction_id, + trans->conn->lchan->ts->trx->bts->nr, + trans->conn->lchan->ts->trx->nr, + trans->conn->lchan->ts->nr, trans->transaction_id, (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); else @@ -1111,12 +1119,12 @@ void _gsm48_cc_trans_free(struct gsm_trans *trans) } if (trans->cc.state != GSM_CSTATE_NULL) new_cc_state(trans, GSM_CSTATE_NULL); - if (trans->lchan) - trau_mux_unmap(&trans->lchan->ts->e1_link, trans->callref); + if (trans->conn) + trau_mux_unmap(&trans->conn->lchan->ts->e1_link, trans->callref); } static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg); - + /* call-back from paging the B-end of the connection */ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, struct msgb *msg, void *_lchan, void *param) @@ -1128,7 +1136,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, if (hooknum != GSM_HOOK_RR_PAGING) return -EINVAL; - + if (!subscr) return -EINVAL; net = subscr->net; @@ -1139,7 +1147,7 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, /* check all tranactions (without lchan) for subscriber */ llist_for_each_entry_safe(transt, tmp, &net->trans_list, entry) { - if (transt->subscr != subscr || transt->lchan) + if (transt->subscr != subscr || transt->conn) continue; switch (event) { case GSM_PAGING_SUCCEEDED: @@ -1148,9 +1156,9 @@ static int setup_trig_pag_evt(unsigned int hooknum, unsigned int event, DEBUGP(DCC, "Paging subscr %s succeeded!\n", subscr->extension); /* Assign lchan */ - if (!transt->lchan) { - transt->lchan = lchan; - use_lchan(lchan); + if (!transt->conn) { + transt->conn = &lchan->conn; + use_subscr_con(transt->conn); } /* send SETUP request to called party */ gsm48_cc_tx_setup(transt, &transt->cc.msg); @@ -1195,7 +1203,7 @@ static int handle_abisip_signal(unsigned int subsys, unsigned int signal, * a tch_recv_mncc request pending */ net = lchan->ts->trx->bts->network; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan && trans->tch_recv) { + if (trans->conn && trans->conn->lchan == lchan && trans->tch_recv) { DEBUGP(DCC, "pending tch_recv_mncc request\n"); tch_recv_mncc(net, trans->callref, 1); } @@ -1268,11 +1276,11 @@ static int tch_bridge(struct gsm_network *net, u_int32_t *refs) if (!trans1 || !trans2) return -EIO; - if (!trans1->lchan || !trans2->lchan) + if (!trans1->conn || !trans2->conn) return -EIO; /* through-connect channel */ - return tch_map(trans1->lchan, trans2->lchan); + return tch_map(trans1->conn->lchan, trans2->conn->lchan); } /* enable receive of channels to MNCC upqueue */ @@ -1287,9 +1295,9 @@ static int tch_recv_mncc(struct gsm_network *net, u_int32_t callref, int enable) trans = trans_find_by_callref(net, callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - lchan = trans->lchan; + lchan = trans->conn->lchan; bts = lchan->ts->trx->bts; switch (bts->type) { @@ -2484,7 +2492,7 @@ static int _gsm48_lchan_modify(struct gsm_trans *trans, void *arg) { struct gsm_mncc *mode = arg; - return gsm48_lchan_modify(trans->lchan, mode->lchan_mode); + return gsm48_lchan_modify(trans->conn->lchan, mode->lchan_mode); } static struct downstate { @@ -2570,18 +2578,18 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) trans = trans_find_by_callref(net, data->callref); if (!trans) return -EIO; - if (!trans->lchan) + if (!trans->conn) return 0; - if (trans->lchan->type != GSM_LCHAN_TCH_F) + if (trans->conn->lchan->type != GSM_LCHAN_TCH_F) return 0; - bts = trans->lchan->ts->trx->bts; + bts = trans->conn->lchan->ts->trx->bts; switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: - if (!trans->lchan->abis_ip.rtp_socket) + if (!trans->conn->lchan->abis_ip.rtp_socket) return 0; - return rtp_send_frame(trans->lchan->abis_ip.rtp_socket, arg); + return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg); case GSM_BTS_TYPE_BS11: - return trau_send_frame(trans->lchan, arg); + return trau_send_frame(trans->conn->lchan, arg); default: DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); } @@ -2659,6 +2667,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) } /* Find lchan */ lchan = lchan_for_subscr(subscr); + /* If subscriber has no lchan */ if (!lchan) { /* find transaction with this subscriber already paging */ @@ -2686,16 +2695,18 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) return 0; } /* Assign lchan */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); subscr_put(subscr); } - lchan = trans->lchan; + + if (trans->conn) + lchan = trans->conn->lchan; /* if paging did not respond yet */ if (!lchan) { DEBUGP(DCC, "(bts - trx - ts - ti -- sub %s) " - "Received '%s' from MNCC in paging state\n", + "Received '%s' from MNCC in paging state\n", (trans->subscr)?(trans->subscr->extension):"-", get_mncc_name(msg_type)); mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU, @@ -2713,7 +2724,7 @@ int mncc_send(struct gsm_network *net, int msg_type, void *arg) "Received '%s' from MNCC in state %d (%s)\n", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, trans->transaction_id, - (lchan->subscr)?(lchan->subscr->extension):"-", + (trans->conn->subscr)?(trans->conn->subscr->extension):"-", get_mncc_name(msg_type), trans->cc.state, gsm48_cc_state_name(trans->cc.state)); @@ -2750,7 +2761,7 @@ static struct datastate { GSM48_MT_CC_CALL_CONF, gsm48_cc_rx_call_conf}, {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF), /* ???? | 5.2.2.3.2 */ GSM48_MT_CC_ALERTING, gsm48_cc_rx_alerting}, - {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */ + {SBIT(GSM_CSTATE_CALL_PRESENT) | SBIT(GSM_CSTATE_MO_TERM_CALL_CONF) | SBIT(GSM_CSTATE_CALL_RECEIVED), /* (5.2.2.6) | 5.2.2.6 | 5.2.2.6 */ GSM48_MT_CC_CONNECT, gsm48_cc_rx_connect}, /* signalling during call */ {ALL_STATES - SBIT(GSM_CSTATE_NULL), @@ -2789,6 +2800,7 @@ static struct datastate { static int gsm0408_rcv_cc(struct msgb *msg) { + struct gsm_subscriber_connection *conn; struct gsm48_hdr *gh = msgb_l3(msg); u_int8_t msg_type = gh->msg_type & 0xbf; u_int8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */ @@ -2800,14 +2812,16 @@ static int gsm0408_rcv_cc(struct msgb *msg) DEBUGP(DCC, "MSG 0x%2x not defined for PD error\n", msg_type); return -EINVAL; } - + + conn = &lchan->conn; + /* Find transaction */ - trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_CC, transaction_id); + trans = trans_find_by_id(conn->subscr, GSM48_PDISC_CC, transaction_id); DEBUGP(DCC, "(bts %d trx %d ts %d ti %x sub %s) " "Received '%s' from MS in state %d (%s)\n", lchan->ts->trx->bts->nr, lchan->ts->trx->nr, lchan->ts->nr, - transaction_id, (lchan->subscr)?(lchan->subscr->extension):"-", + transaction_id, (conn->subscr)?(conn->subscr->extension):"-", gsm48_cc_msg_name(msg_type), trans?(trans->cc.state):0, gsm48_cc_state_name(trans?(trans->cc.state):0)); @@ -2816,7 +2830,7 @@ static int gsm0408_rcv_cc(struct msgb *msg) DEBUGP(DCC, "Unknown transaction ID %x, " "creating new trans.\n", transaction_id); /* Create transaction */ - trans = trans_alloc(lchan->subscr, GSM48_PDISC_CC, + trans = trans_alloc(conn->subscr, GSM48_PDISC_CC, transaction_id, new_callref++); if (!trans) { DEBUGP(DCC, "No memory for trans.\n"); @@ -2826,8 +2840,8 @@ static int gsm0408_rcv_cc(struct msgb *msg) return -ENOMEM; } /* Assign transaction */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } /* find function for current state and message */ diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c index 2d957cae3..dbbc7fbb2 100644 --- a/openbsc/src/gsm_04_08_utils.c +++ b/openbsc/src/gsm_04_08_utils.c @@ -57,7 +57,7 @@ int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans) * work that the caller no longer has to do */ if (trans) { gh->proto_discr = trans->protocol | (trans->transaction_id << 4); - msg->lchan = trans->lchan; + msg->lchan = trans->conn->lchan; } if (msg->lchan) { @@ -269,50 +269,6 @@ int gsm48_send_rr_release(struct gsm_lchan *lchan) return rsl_deact_sacch(lchan); } -/* Convert Mobile Identity (10.5.1.4) to string */ -int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len) -{ - int i; - u_int8_t mi_type; - char *str_cur = string; - u_int32_t tmsi; - - mi_type = mi[0] & GSM_MI_TYPE_MASK; - - switch (mi_type) { - case GSM_MI_TYPE_NONE: - break; - case GSM_MI_TYPE_TMSI: - /* Table 10.5.4.3, reverse generate_mid_from_tmsi */ - if (mi_len == GSM48_TMSI_LEN && mi[0] == (0xf0 | GSM_MI_TYPE_TMSI)) { - memcpy(&tmsi, &mi[1], 4); - tmsi = ntohl(tmsi); - return snprintf(string, str_len, "%u", tmsi); - } - break; - case GSM_MI_TYPE_IMSI: - case GSM_MI_TYPE_IMEI: - case GSM_MI_TYPE_IMEISV: - *str_cur++ = bcd2char(mi[0] >> 4); - - for (i = 1; i < mi_len; i++) { - if (str_cur + 2 >= string + str_len) - return str_cur - string; - *str_cur++ = bcd2char(mi[i] & 0xf); - /* skip last nibble in last input byte when GSM_EVEN */ - if( (i != mi_len-1) || (mi[0] & GSM_MI_ODD)) - *str_cur++ = bcd2char(mi[i] >> 4); - } - break; - default: - break; - } - *str_cur++ = '\0'; - - return str_cur - string; -} - - int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv) { @@ -349,16 +305,16 @@ int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr) if (is_siemens_bts(bts)) send_siemens_mrpci(msg->lchan, classmark2_lv); - if (!msg->lchan->subscr) { - msg->lchan->subscr = subscr; - } else if (msg->lchan->subscr != subscr) { + if (!msg->lchan->conn.subscr) { + msg->lchan->conn.subscr = subscr; + } else if (msg->lchan->conn.subscr != subscr) { LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n"); subscr_put(subscr); return -EINVAL; } else { DEBUGP(DRR, "<- Channel already owned by us\n"); subscr_put(subscr); - subscr = msg->lchan->subscr; + subscr = msg->lchan->conn.subscr; } sig_data.subscr = subscr; @@ -659,4 +615,3 @@ int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg) return 0; } - diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c index f12e05b1f..0c12f15f5 100644 --- a/openbsc/src/gsm_04_11.c +++ b/openbsc/src/gsm_04_11.c @@ -24,6 +24,7 @@ */ +#include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -63,7 +64,7 @@ static const struct value_string cp_cause_strs[] = { { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" }, { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" }, { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" }, - { GSM411_CP_CAUSE_MSG_INCOMP_STATE, + { GSM411_CP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" }, { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" }, { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" }, @@ -121,16 +122,11 @@ struct msgb *gsm411_msgb_alloc(void) "GSM 04.11"); } -static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id) +static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id) { - if (msg->lchan) - msg->trx = msg->lchan->ts->trx; - - msg->l3h = msg->data; - DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len)); - - return rsl_data_request(msg, link_id); + msg->l3h = msg->data; + return gsm0808_submit_dtap(conn, msg, link_id); } /* SMC TC1* is expired */ @@ -154,9 +150,6 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, gh->proto_discr = trans->protocol | (trans->transaction_id<<4); gh->msg_type = msg_type; - /* assign the outgoing lchan */ - msg->lchan = trans->lchan; - /* mobile originating */ switch (gh->msg_type) { case GSM411_MT_CP_DATA: @@ -179,7 +172,7 @@ static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans, DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id); - return gsm411_sendmsg(msg, trans->sms.link_id); + return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id); } /* Prefix msg with a RP-DATA header and send as CP-DATA */ @@ -215,7 +208,7 @@ static u_int8_t unbcdify(u_int8_t value) u_int8_t ret; if ((value & 0x0F) > 9 || (value >> 4) > 9) - LOGP(DSMS, LOGL_ERROR, + LOGP(DSMS, LOGL_ERROR, "unbcdify got too big nibble: 0x%02X\n", value); ret = (value&0x0F)*10; @@ -509,11 +502,10 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms) return msg->len - old_msg_len; } -/* process an incoming TPDU (called from RP-DATA) - * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ -static int gsm340_rx_tpdu(struct msgb *msg) +/* process an incoming TPDU (called from RP-DATA) + * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */ +static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_bts *bts = msg->lchan->ts->trx->bts; u_int8_t *smsp = msgb_sms(msg); struct gsm_sms *gsms; u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp; @@ -522,7 +514,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */ int rc = 0; - counter_inc(bts->network->stats.sms.submitted); + counter_inc(conn->bts->network->stats.sms.submitted); gsms = sms_alloc(); if (!gsms) @@ -575,7 +567,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) sms_vp = 0; break; default: - LOGP(DSMS, LOGL_NOTICE, + LOGP(DSMS, LOGL_NOTICE, "SMS Validity period not implemented: 0x%02x\n", sms_vpf); return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER; } @@ -594,7 +586,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) } } - gsms->sender = subscr_get(msg->lchan->subscr); + gsms->sender = subscr_get(msg->lchan->conn.subscr); LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, " "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, " @@ -602,7 +594,7 @@ static int gsm340_rx_tpdu(struct msgb *msg) subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref, gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr, gsms->user_data_len, - sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : + sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text : hexdump(gsms->user_data, gsms->user_data_len)); gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp); @@ -610,10 +602,10 @@ static int gsm340_rx_tpdu(struct msgb *msg) dispatch_signal(SS_SMS, 0, gsms); /* determine gsms->receiver based on dialled number */ - gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr); + gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr); if (!gsms->receiver) { rc = 1; /* cause 1: unknown subscriber */ - counter_inc(bts->network->stats.sms.no_receiver); + counter_inc(conn->bts->network->stats.sms.no_receiver); goto out; } @@ -687,7 +679,7 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans, DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len)); - rc = gsm340_rx_tpdu(msg); + rc = gsm340_rx_tpdu(trans->conn, msg); if (rc == 0) return gsm411_send_rp_ack(trans, rph->msg_ref); else if (rc > 0) @@ -753,14 +745,17 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, trans->sms.sms = NULL; /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr); + assert(msg->lchan->conn.subscr == trans->subscr); + + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); /* free the transaction here */ trans_free(trans); /* release channel if done */ +#warning "BROKEN. The SAPI will be released automatically by the BSC" if (!sms) rsl_release_request(msg->lchan, trans->sms.link_id, 0); @@ -770,7 +765,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans, static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, struct gsm411_rp_hdr *rph) { - struct gsm_network *net = trans->lchan->ts->trx->bts->network; + struct gsm_network *net = trans->conn->bts->network; struct gsm_sms *sms = trans->sms.sms; u_int8_t cause_len = rph->data[0]; u_int8_t cause = rph->data[1]; @@ -780,7 +775,7 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans, * the cause and take action depending on it */ LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n", - subscr_name(msg->lchan->subscr), cause_len, cause, + subscr_name(trans->conn->subscr), cause_len, cause, get_value_string(rp_cause_strs, cause)); if (!trans->sms.is_mt) { @@ -833,11 +828,13 @@ static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans, dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr); /* check for more messages for this subscriber */ - sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr); + assert(msg->lchan->conn.subscr == trans->subscr); + sms = db_sms_get_unsent_for_subscr(trans->subscr); if (sms) - gsm411_send_sms_lchan(msg->lchan, sms); + gsm411_send_sms_lchan(trans->conn, sms); else rsl_release_request(msg->lchan, trans->sms.link_id, 0); +#warning "BROKEN: The SAPI=3 will be released automatically by the BSC" return rc; } @@ -920,16 +917,16 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) struct gsm_trans *trans; int rc = 0; - if (!lchan->subscr) + if (!lchan->conn.subscr) return -EIO; /* FIXME: send some error message */ DEBUGP(DSMS, "trans_id=%x ", transaction_id); - trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS, transaction_id); if (!trans) { DEBUGPC(DSMS, "(new) "); - trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { DEBUGPC(DSMS, "No memory for trans\n"); @@ -941,8 +938,8 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) trans->sms.is_mt = 0; trans->sms.link_id = link_id; - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = &lchan->conn; + use_subscr_con(trans->conn); } switch(msg_type) { @@ -961,7 +958,7 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id) if (i == transaction_id) continue; - ptrans = trans_find_by_id(lchan->subscr, + ptrans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS, i); if (!ptrans) continue; @@ -1041,7 +1038,7 @@ static u_int8_t tpdu_test[] = { /* Take a SMS in gsm_sms structure and send it through an already * existing lchan. We also assume that the caller ensured this lchan already * has a SAPI3 RLL connection! */ -int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) +int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms) { struct msgb *msg = gsm411_msgb_alloc(); struct gsm_trans *trans; @@ -1050,18 +1047,16 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) int transaction_id; int rc; - transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0); + transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0); if (transaction_id == -1) { LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n"); return -EBUSY; } - msg->lchan = lchan; - DEBUGP(DSMS, "send_sms_lchan()\n"); /* FIXME: allocate transaction with message reference */ - trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS, + trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS, transaction_id, new_callref++); if (!trans) { LOGP(DSMS, LOGL_ERROR, "No memory for trans\n"); @@ -1074,8 +1069,8 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) trans->sms.sms = sms; trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */ - trans->lchan = lchan; - use_lchan(lchan); + trans->conn = conn; + use_subscr_con(trans->conn); /* Hardcode SMSC Originating Address for now */ data = (u_int8_t *)msgb_put(msg, 8); @@ -1112,7 +1107,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms) DEBUGP(DSMS, "TX: SMS DELIVER\n"); - counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered); + counter_inc(conn->bts->network->stats.sms.delivered); return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref); /* FIXME: enter 'wait for RP-ACK' state, start TR1N */ @@ -1130,11 +1125,13 @@ static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id, switch (type) { case BSC_RLLR_IND_EST_CONF: - gsm411_send_sms_lchan(lchan, sms); +#warning "BROKEN: The BSC will establish this transparently" + gsm411_send_sms_lchan(&lchan->conn, sms); break; case BSC_RLLR_IND_REL_IND: case BSC_RLLR_IND_ERR_IND: case BSC_RLLR_IND_TIMEOUT: +#warning "BROKEN: We will need to handle SAPI n Reject" sms_free(sms); break; } diff --git a/openbsc/src/gsm_04_80.c b/openbsc/src/gsm_04_80.c index 8271274f1..2112e3f99 100644 --- a/openbsc/src/gsm_04_80.c +++ b/openbsc/src/gsm_04_80.c @@ -236,7 +236,7 @@ static int parse_process_uss_req(u_int8_t *uss_req_data, u_int8_t length, gsm_7bit_decode(req->text, &(uss_req_data[7]), num_chars); /* append null-terminator */ - req->text[num_chars+1] = 0; + req->text[num_chars+1] = 0; rc = 1; } } diff --git a/openbsc/src/gsm_subscriber_base.c b/openbsc/src/gsm_subscriber_base.c index e53488a84..13cdfbe08 100644 --- a/openbsc/src/gsm_subscriber_base.c +++ b/openbsc/src/gsm_subscriber_base.c @@ -189,6 +189,7 @@ void subscr_get_channel(struct gsm_subscriber *subscr, void subscr_put_channel(struct gsm_lchan *lchan) { + struct gsm_subscriber_connection *conn = &lchan->conn; /* * FIXME: Continue with other requests now... by checking * the gsm_subscriber inside the gsm_lchan. Drop the ref count @@ -207,10 +208,10 @@ void subscr_put_channel(struct gsm_lchan *lchan) * will listen to the paging requests before we timeout */ - put_lchan(lchan, 0); + put_subscr_con(conn, 0); - if (lchan->subscr && !llist_empty(&lchan->subscr->requests)) - subscr_send_paging_request(lchan->subscr); + if (lchan->conn.subscr && !llist_empty(&lchan->conn.subscr->requests)) + subscr_send_paging_request(lchan->conn.subscr); } struct gsm_subscriber *subscr_get_or_create(struct gsm_network *net, diff --git a/openbsc/src/handover_logic.c b/openbsc/src/handover_logic.c index 33fafaec1..2d857f43e 100644 --- a/openbsc/src/handover_logic.c +++ b/openbsc/src/handover_logic.c @@ -122,7 +122,7 @@ int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts) new_lchan->bs_power = old_lchan->bs_power; new_lchan->rsl_cmode = old_lchan->rsl_cmode; new_lchan->tch_mode = old_lchan->tch_mode; - new_lchan->subscr = subscr_get(old_lchan->subscr); + new_lchan->conn.subscr = subscr_get(old_lchan->conn.subscr); /* FIXME: do we have a better idea of the timing advance? */ rc = rsl_chan_activate_lchan(new_lchan, RSL_ACT_INTER_ASYNC, 0, @@ -218,7 +218,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) } LOGP(DHO, LOGL_INFO, "Subscriber %s HO from BTS %u->%u on ARFCN " - "%u->%u\n", subscr_name(ho->old_lchan->subscr), + "%u->%u\n", subscr_name(ho->old_lchan->conn.subscr), ho->old_lchan->ts->trx->bts->nr, new_lchan->ts->trx->bts->nr, ho->old_lchan->ts->trx->arfcn, new_lchan->ts->trx->arfcn); @@ -227,7 +227,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) bsc_del_timer(&ho->T3103); /* update lchan pointer of transaction */ - trans_lchan_change(ho->old_lchan, new_lchan); + trans_lchan_change(&ho->old_lchan->conn, &new_lchan->conn); ho->old_lchan->state = LCHAN_S_INACTIVE; @@ -242,6 +242,7 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan) /* GSM 04.08 HANDOVER FAIL has been received */ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) { + struct gsm_subscriber_connection *conn; struct gsm_network *net = old_lchan->ts->trx->bts->network; struct bsc_handover *ho; @@ -255,7 +256,8 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan) bsc_del_timer(&ho->T3103); llist_del(&ho->list); - put_lchan(ho->new_lchan, 0); + conn = &ho->new_lchan->conn; + put_subscr_con(conn, 0); talloc_free(ho); return 0; diff --git a/openbsc/src/input/ipaccess.c b/openbsc/src/input/ipaccess.c index 387c5bac3..2449e261d 100644 --- a/openbsc/src/input/ipaccess.c +++ b/openbsc/src/input/ipaccess.c @@ -62,7 +62,7 @@ static struct ia_e1_handle *e1h; static const u_int8_t pong[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_PONG }; static const u_int8_t id_ack[] = { 0, 1, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_ACK }; static const u_int8_t id_req[] = { 0, 17, IPAC_PROTO_IPACCESS, IPAC_MSGT_ID_GET, - 0x01, IPAC_IDTAG_UNIT, + 0x01, IPAC_IDTAG_UNIT, 0x01, IPAC_IDTAG_MACADDR, 0x01, IPAC_IDTAG_LOCATION1, 0x01, IPAC_IDTAG_LOCATION2, diff --git a/openbsc/src/input/misdn.c b/openbsc/src/input/misdn.c index 56930d498..83b01f2ca 100644 --- a/openbsc/src/input/misdn.c +++ b/openbsc/src/input/misdn.c @@ -262,7 +262,7 @@ static int handle_tsX_write(struct bsc_fd *bfd) ret = send(bfd->fd, tx_buf, sizeof(*hh) + BCHAN_TX_GRAN, 0); if (ret < sizeof(*hh) + BCHAN_TX_GRAN) - DEBUGP(DMIB, "send returns %d instead of %lu\n", ret, + DEBUGP(DMIB, "send returns %d instead of %zu\n", ret, sizeof(*hh) + BCHAN_TX_GRAN); return ret; diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index 870950d0e..670e3f11a 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -612,14 +612,14 @@ int main(int argc, char **argv) struct gsm_bts *bts; struct sockaddr_in sin; int rc, option_index = 0, stream_id = 0xff; - struct debug_target *stderr_target; - - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); - debug_set_log_level(stderr_target, 0); - debug_parse_category_mask(stderr_target, "DNM,0"); + struct log_target *stderr_target; + + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); + log_set_log_level(stderr_target, 0); + log_parse_category_mask(stderr_target, "DNM,0"); bts_model_nanobts_init(); printf("ipaccess-config (C) 2009 by Harald Welte\n"); diff --git a/openbsc/src/ipaccess/ipaccess-find.c b/openbsc/src/ipaccess/ipaccess-find.c index 01f8a2d8d..ec4a0b778 100644 --- a/openbsc/src/ipaccess/ipaccess-find.c +++ b/openbsc/src/ipaccess/ipaccess-find.c @@ -71,7 +71,7 @@ static int udp_sock(const char *ifname) rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa)); if (rc < 0) goto err; -#endif +#endif return fd; err: @@ -79,7 +79,7 @@ err: return rc; } -const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00, +const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00, IPAC_MSGT_ID_GET, 0x01, IPAC_IDTAG_MACADDR, 0x01, IPAC_IDTAG_IPADDR, diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c index 217e0bdf1..386081349 100644 --- a/openbsc/src/ipaccess/ipaccess-proxy.c +++ b/openbsc/src/ipaccess/ipaccess-proxy.c @@ -42,7 +42,7 @@ #include <openbsc/ipaccess.h> #include <osmocore/talloc.h> -static struct debug_target *stderr_target; +static struct log_target *stderr_target; /* one instance of an ip.access protocol proxy */ struct ipa_proxy { @@ -265,10 +265,10 @@ static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int li struct ipa_bts_conn *ipbc, u_int8_t trx_id) { if (ipbc) - debugp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id, + logp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id, ipbc->unit_id.bts_id, trx_id); else - debugp2(ss, lvl, file, line, 0, "unknown "); + logp2(ss, lvl, file, line, 0, "unknown "); } /* UDP socket handling */ @@ -550,6 +550,7 @@ static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg, } /* lookup BTS, create sign_link, ... */ + site_id = bts_id = trx_id = 0; parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT), &site_id, &bts_id, &trx_id); ipbc = find_bts_by_unitid(ipp, site_id, bts_id); @@ -946,7 +947,7 @@ static int listen_fd_cb(struct bsc_fd *listen_bfd, unsigned int what) perror("accept"); return ret; } - DEBUGP(DINP, "accept()ed new %s link from %s\n", + DEBUGP(DINP, "accept()ed new %s link from %s\n", (listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL", inet_ntoa(sa.sin_addr)); @@ -1108,11 +1109,11 @@ int main(int argc, char **argv) tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy"); - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); - debug_parse_category_mask(stderr_target, "DINP:DMI"); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); + log_parse_category_mask(stderr_target, "DINP:DMI"); rc = ipaccess_proxy_setup(); if (rc < 0) diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c index 802e16e21..80b7b543c 100644 --- a/openbsc/src/mgcp/mgcp_main.c +++ b/openbsc/src/mgcp/mgcp_main.c @@ -59,7 +59,7 @@ static struct mgcp_config *cfg; static int reset_endpoints = 0; const char *openbsc_version = "OpenBSC MGCP " PACKAGE_VERSION; -const char *openbsc_copyright = +const char *openbsc_copyright = "Copyright (C) 2009-2010 Holger Freyther and On-Waves\n" "Contributions by Daniel Willmann, Jan Lübbe,Stefan Schmidt\n" "Dieter Spaar, Andreas Eversberg, Harald Welte\n\n" @@ -178,14 +178,14 @@ int main(int argc, char** argv) struct gsm_network dummy_network; struct sockaddr_in addr; int on = 1, rc; - struct debug_target *stderr_target; + struct log_target *stderr_target; tall_bsc_ctx = talloc_named_const(NULL, 1, "mgcp-callagent"); - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); cfg = mgcp_config_alloc(); if (!cfg) diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c index 01d59aad1..afd53644e 100644 --- a/openbsc/src/mncc.c +++ b/openbsc/src/mncc.c @@ -332,16 +332,16 @@ static int mncc_rcv_tchf(struct gsm_call *call, int msg_type, remote_trans = trans_find_by_callref(call->net, call->remote_ref); /* this shouldn't really happen */ - if (!remote_trans || !remote_trans->lchan) { + if (!remote_trans || !remote_trans->conn) { LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without lchan?!?\n"); return -EIO; } /* RTP socket of remote end has meanwhile died */ - if (!remote_trans->lchan->abis_ip.rtp_socket) + if (!remote_trans->conn->lchan->abis_ip.rtp_socket) return -EIO; - return rtp_send_frame(remote_trans->lchan->abis_ip.rtp_socket, dfr); + return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, dfr); } diff --git a/openbsc/src/nat/bsc_nat.c b/openbsc/src/nat/bsc_nat.c index 500809c63..631d89994 100644 --- a/openbsc/src/nat/bsc_nat.c +++ b/openbsc/src/nat/bsc_nat.c @@ -49,7 +49,7 @@ #include <sccp/sccp.h> -struct debug_target *stderr_target; +struct log_target *stderr_target; static const char *config_file = "bsc-nat.cfg"; static char *msc_address = "127.0.0.1"; static struct in_addr local_addr; @@ -700,16 +700,16 @@ static void handle_options(int argc, char** argv) print_help(); exit(0); case 's': - debug_set_use_color(stderr_target, 0); + log_set_use_color(stderr_target, 0); break; case 'd': - debug_parse_category_mask(stderr_target, optarg); + log_parse_category_mask(stderr_target, optarg); break; case 'c': config_file = strdup(optarg); break; case 'T': - debug_set_print_timestamp(stderr_target, 1); + log_set_print_timestamp(stderr_target, 1); break; case 'm': msc_address = strdup(optarg); @@ -740,10 +740,10 @@ static void signal_handler(int signal) int main(int argc, char** argv) { - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); /* parse options */ local_addr.s_addr = INADDR_ANY; diff --git a/openbsc/src/rs232.c b/openbsc/src/rs232.c index 36af59cbf..22adf56c8 100644 --- a/openbsc/src/rs232.c +++ b/openbsc/src/rs232.c @@ -156,7 +156,7 @@ static int handle_ser_read(struct bsc_fd *bfd) fprintf(stderr, "Invalid length in hdr: %u\n", sh->rxmsg_bytes_missing); } - } else { + } else { /* try to read as many of the missing bytes as are available */ rc = read(sh->fd.fd, msg->tail, sh->rxmsg_bytes_missing); if (rc < 0) { diff --git a/openbsc/src/rtp_proxy.c b/openbsc/src/rtp_proxy.c index 9f2e2fd76..375204e97 100644 --- a/openbsc/src/rtp_proxy.c +++ b/openbsc/src/rtp_proxy.c @@ -504,7 +504,7 @@ static int rtp_bfd_cb(struct bsc_fd *bfd, unsigned int flags) return 0; } -static void init_rss(struct rtp_sub_socket *rss, +static void init_rss(struct rtp_sub_socket *rss, struct rtp_socket *rs, int fd, int priv_nr) { /* initialize bfd */ diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c index f81bdc51e..85c7f8987 100644 --- a/openbsc/src/silent_call.c +++ b/openbsc/src/silent_call.c @@ -38,6 +38,7 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, struct msgb *msg, void *_lchan, void *_data) { + struct gsm_subscriber_connection *conn; struct gsm_lchan *lchan = _lchan; struct scall_signal_data sigdata; int rc; @@ -47,6 +48,8 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, DEBUGP(DSMS, "paging_cb_silent: "); + conn = &lchan->conn; + sigdata.lchan = lchan; sigdata.data = _data; @@ -54,10 +57,10 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event, case GSM_PAGING_SUCCEEDED: DEBUGPC(DSMS, "success, using Timeslot %u on ARFCN %u\n", lchan->ts->nr, lchan->ts->trx->arfcn); - lchan->silent_call = 1; + conn->silent_call = 1; /* increment lchan reference count */ dispatch_signal(SS_SCALL, S_SCALL_SUCCESS, &sigdata); - use_lchan(lchan); + use_subscr_con(conn); break; case GSM_PAGING_EXPIRED: DEBUGP(DSMS, "expired\n"); @@ -97,7 +100,7 @@ int silent_call_reroute(struct msgb *msg) int i; /* if we're not part of a silent call, never reroute */ - if (!msg->lchan->silent_call) + if (!msg->lchan->conn.silent_call) return 0; /* check if we are a special message that is handled in openbsc */ @@ -126,16 +129,18 @@ int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data, int type) int gsm_silent_call_stop(struct gsm_subscriber *subscr) { struct gsm_lchan *lchan; + struct gsm_subscriber_connection *conn; lchan = lchan_for_subscr(subscr); if (!lchan) return -EINVAL; /* did we actually establish a silent call for this guy? */ - if (!lchan->silent_call) + conn = &lchan->conn; + if (!conn->silent_call) return -EINVAL; - put_lchan(lchan, 0); + put_subscr_con(conn, 0); return 0; } diff --git a/openbsc/src/talloc_ctx.c b/openbsc/src/talloc_ctx.c index 6379e13db..4b373b4ae 100644 --- a/openbsc/src/talloc_ctx.c +++ b/openbsc/src/talloc_ctx.c @@ -19,7 +19,7 @@ extern void *tall_ctr_ctx; void talloc_ctx_init(void) { tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb"); - tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0, + tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0, "bs11_file_list_entry"); tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 0, "loc_updating_oper"); tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 0, "sms"); diff --git a/openbsc/src/telnet_interface.c b/openbsc/src/telnet_interface.c index aa119b464..c7de026d1 100644 --- a/openbsc/src/telnet_interface.c +++ b/openbsc/src/telnet_interface.c @@ -117,7 +117,7 @@ int telnet_close_client(struct bsc_fd *fd) { bsc_unregister_fd(fd); if (conn->dbg) { - debug_del_target(conn->dbg); + log_del_target(conn->dbg); talloc_free(conn->dbg); } diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c index 4b586a637..bd2761b5f 100644 --- a/openbsc/src/transaction.c +++ b/openbsc/src/transaction.c @@ -96,13 +96,13 @@ void trans_free(struct gsm_trans *trans) break; } - if (!trans->lchan && trans->subscr && trans->subscr->net) { + if (!trans->conn && trans->subscr && trans->subscr->net) { /* Stop paging on all bts' */ paging_request_stop(NULL, trans->subscr, NULL); } - if (trans->lchan) - put_lchan(trans->lchan, 0); + if (trans->conn) + put_subscr_con(trans->conn, 0); if (trans->subscr) subscr_put(trans->subscr); @@ -149,21 +149,22 @@ int trans_assign_trans_id(struct gsm_subscriber *subscr, /* update all transactions to use a different LCHAN, e.g. * after handover has succeeded */ -int trans_lchan_change(struct gsm_lchan *lchan_old, - struct gsm_lchan *lchan_new) +int trans_lchan_change(struct gsm_subscriber_connection *conn_old, + struct gsm_subscriber_connection *conn_new) { - struct gsm_network *net = lchan_old->ts->trx->bts->network; + struct gsm_network *net = conn_old->lchan->ts->trx->bts->network; struct gsm_trans *trans; int num = 0; llist_for_each_entry(trans, &net->trans_list, entry) { - if (trans->lchan == lchan_old) { - /* drop old channel use cound */ - put_lchan(trans->lchan, 0); + if (trans->conn == conn_old) { + + /* drop old channel use count */ + put_subscr_con(conn_old, 0); /* assign new channel */ - trans->lchan = lchan_new; + trans->conn = conn_new; /* bump new channel use count */ - use_lchan(trans->lchan); + use_subscr_con(conn_new); num++; } } diff --git a/openbsc/src/ussd.c b/openbsc/src/ussd.c index a3d11f080..547691965 100644 --- a/openbsc/src/ussd.c +++ b/openbsc/src/ussd.c @@ -62,7 +62,7 @@ int handle_rcv_ussd(struct msgb *msg) /* A network-specific handler function */ static int send_own_number(const struct msgb *msg, const struct ussd_request *req) { - char *own_number = msg->lchan->subscr->extension; + char *own_number = msg->lchan->conn.subscr->extension; char response_string[GSM_EXTENSION_LENGTH + 20]; /* Need trailing CR as EOT character */ diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c index 1260f38c5..0ac9530f5 100644 --- a/openbsc/src/vty/vty.c +++ b/openbsc/src/vty/vty.c @@ -526,7 +526,7 @@ vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes) vty->iac_sb_in_progress = 1; return 0; break; - case SE: + case SE: { if (!vty->iac_sb_in_progress) return 0; diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c index 5754d1e23..94b177ef3 100644 --- a/openbsc/src/vty_interface.c +++ b/openbsc/src/vty_interface.c @@ -38,6 +38,7 @@ #include <openbsc/db.h> #include <osmocore/talloc.h> #include <openbsc/telnet_interface.h> +#include <openbsc/vty.h> static struct gsm_network *gsmnet; @@ -171,7 +172,7 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) "BSIC %u, TSC %u and %u TRX%s", bts->nr, btstype2str(bts->type), gsm_band_name(bts->band), bts->cell_identity, - bts->location_area_code, bts->bsic, bts->tsc, + bts->location_area_code, bts->bsic, bts->tsc, bts->num_trx, VTY_NEWLINE); vty_out(vty, "MS Max power: %u dBm%s", bts->ms_max_power, VTY_NEWLINE); vty_out(vty, "Minimum Rx Level for Access: %i dBm%s", @@ -634,19 +635,19 @@ static void lchan_dump_vty(struct vty *vty, struct gsm_lchan *lchan) int idx; vty_out(vty, "Lchan %u in Timeslot %u of TRX %u in BTS %u, Type %s%s", - lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, + lchan->nr, lchan->ts->nr, lchan->ts->trx->nr, lchan->ts->trx->bts->nr, gsm_lchant_name(lchan->type), VTY_NEWLINE); - vty_out(vty, " Use Count: %u, State: %s%s", lchan->use_count, + vty_out(vty, " Use Count: %u, State: %s%s", lchan->conn.use_count, gsm_lchans_name(lchan->state), VTY_NEWLINE); vty_out(vty, " BS Power: %u dBm, MS Power: %u dBm%s", lchan->ts->trx->nominal_power - lchan->ts->trx->max_power_red - lchan->bs_power*2, ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power), VTY_NEWLINE); - if (lchan->subscr) { + if (lchan->conn.subscr) { vty_out(vty, " Subscriber:%s", VTY_NEWLINE); - subscr_dump_vty(vty, lchan->subscr); + subscr_dump_vty(vty, lchan->conn.subscr); } else vty_out(vty, " No Subscriber%s", VTY_NEWLINE); if (is_ipaccess_bts(lchan->ts->trx->bts)) { @@ -1310,7 +1311,7 @@ DEFUN(cfg_bts, /* allocate a new one */ bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_UNKNOWN, HARDCODED_TSC, HARDCODED_BSIC); - } else + } else bts = gsm_bts_num(gsmnet, bts_nr); if (!bts) { @@ -1741,9 +1742,9 @@ DEFUN(cfg_trx, } else if (trx_nr == bts->num_trx) { /* we need to allocate a new one */ trx = gsm_bts_trx_alloc(bts); - } else + } else trx = gsm_bts_trx_num(bts, trx_nr); - + if (!trx) return CMD_WARNING; diff --git a/openbsc/src/vty_interface_cmds.c b/openbsc/src/vty_interface_cmds.c index 167b9542c..d4945840e 100644 --- a/openbsc/src/vty_interface_cmds.c +++ b/openbsc/src/vty_interface_cmds.c @@ -30,7 +30,7 @@ #include <stdlib.h> -static void _vty_output(struct debug_target *tgt, const char *line) +static void _vty_output(struct log_target *tgt, const char *line) { struct vty *vty = tgt->tgt_vty.vty; vty_out(vty, "%s", line); @@ -39,11 +39,11 @@ static void _vty_output(struct debug_target *tgt, const char *line) vty_out(vty, "\r"); } -struct debug_target *debug_target_create_vty(struct vty *vty) +struct log_target *log_target_create_vty(struct vty *vty) { - struct debug_target *target; + struct log_target *target; - target = debug_target_create(); + target = log_target_create(); if (!target) return NULL; @@ -65,11 +65,11 @@ DEFUN(enable_logging, return CMD_WARNING; } - conn->dbg = debug_target_create_vty(vty); + conn->dbg = log_target_create_vty(vty); if (!conn->dbg) return CMD_WARNING; - debug_add_target(conn->dbg); + log_add_target(conn->dbg); return CMD_SUCCESS; } @@ -86,7 +86,7 @@ DEFUN(logging_fltr_imsi, return CMD_WARNING; } - debug_set_imsi_filter(conn->dbg, argv[0]); + log_set_imsi_filter(conn->dbg, argv[0]); return CMD_SUCCESS; } @@ -103,7 +103,7 @@ DEFUN(logging_fltr_all, return CMD_WARNING; } - debug_set_all_filter(conn->dbg, atoi(argv[0])); + log_set_all_filter(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -120,7 +120,7 @@ DEFUN(logging_use_clr, return CMD_WARNING; } - debug_set_use_color(conn->dbg, atoi(argv[0])); + log_set_use_color(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -137,12 +137,12 @@ DEFUN(logging_prnt_timestamp, return CMD_WARNING; } - debug_set_print_timestamp(conn->dbg, atoi(argv[0])); + log_set_print_timestamp(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } /* FIXME: those have to be kept in sync with the log levels and categories */ -#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|nat)" +#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref)" #define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" DEFUN(logging_level, logging_level_cmd, @@ -150,8 +150,8 @@ DEFUN(logging_level, "Set the log level for a specified category\n") { struct telnet_connection *conn; - int category = debug_parse_category(argv[0]); - int level = debug_parse_level(argv[1]); + int category = log_parse_category(argv[0]); + int level = log_parse_level(argv[1]); conn = (struct telnet_connection *) vty->priv; if (!conn->dbg) { @@ -177,7 +177,7 @@ DEFUN(logging_level, DEFUN(logging_set_category_mask, logging_set_category_mask_cmd, - "logging set debug mask MASK", + "logging set log mask MASK", "Decide which categories to output.\n") { struct telnet_connection *conn; @@ -188,7 +188,7 @@ DEFUN(logging_set_category_mask, return CMD_WARNING; } - debug_parse_category_mask(conn->dbg, argv[0]); + log_parse_category_mask(conn->dbg, argv[0]); return CMD_SUCCESS; } @@ -205,7 +205,7 @@ DEFUN(logging_set_log_level, return CMD_WARNING; } - debug_set_log_level(conn->dbg, atoi(argv[0])); + log_set_log_level(conn->dbg, atoi(argv[0])); return CMD_SUCCESS; } @@ -222,13 +222,12 @@ DEFUN(diable_logging, return CMD_WARNING; } - debug_del_target(conn->dbg); + log_del_target(conn->dbg); talloc_free(conn->dbg); conn->dbg = NULL; return CMD_SUCCESS; } - void openbsc_vty_add_cmds() { install_element(VIEW_NODE, &enable_logging_cmd); diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c index 40e2475ba..4780a7a88 100644 --- a/openbsc/tests/bsc-nat/bsc_nat_test.c +++ b/openbsc/tests/bsc-nat/bsc_nat_test.c @@ -509,11 +509,12 @@ static void test_mgcp_parse(void) int main(int argc, char **argv) { - struct debug_target *stderr_target; + struct log_target *stderr_target; - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); test_filter(); test_contrack(); diff --git a/openbsc/tests/debug/debug_test.c b/openbsc/tests/debug/debug_test.c index 0f0c284ab..695d65c0b 100644 --- a/openbsc/tests/debug/debug_test.c +++ b/openbsc/tests/debug/debug_test.c @@ -24,17 +24,17 @@ int main(int argc, char** argv) { - struct debug_target *stderr_target; + struct log_target *stderr_target; - debug_init(); - stderr_target = debug_target_create_stderr(); - debug_add_target(stderr_target); - debug_set_all_filter(stderr_target, 1); + log_init(&log_info); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); - debug_parse_category_mask(stderr_target, "DRLL"); + log_parse_category_mask(stderr_target, "DRLL"); DEBUGP(DCC, "You should not see this\n"); - debug_parse_category_mask(stderr_target, "DRLL:DCC"); + log_parse_category_mask(stderr_target, "DRLL:DCC"); DEBUGP(DRLL, "You should see this\n"); DEBUGP(DCC, "You should see this\n"); DEBUGP(DMM, "You should not see this\n"); |