mirror of https://gerrit.osmocom.org/libosmocore
Merge remote-tracking branch 'origin/master' into daniel/onwaves
Change-Id: Iaba2f4312f251e8324409bdb230df86ab2c2438e
This commit is contained in:
commit
e373a09bec
|
@ -7,6 +7,6 @@
|
|||
# If any interfaces have been added since the last public release: c:r:a + 1.
|
||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
||||
#library what description / commit summary line
|
||||
gsup gsup.h the 'osmo_gsup_message' struct extended with
|
||||
session information => ABI changed
|
||||
SS/USSD information => ABI changed
|
||||
libosmogsm gsm0480_l3hdr_push() removed from gsm/gsm0480.h (was not exposed)
|
||||
libosmogsm gsm48_push_l3hdr() (re)introduced in gsm/gsm48.h (GSM 04.08 API)
|
||||
libosmogsm gsm48_push_l3hdr_tid() a wrapper around gsm48_push_l3hdr()
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
. $(dirname "$0")/jenkins_common.sh
|
||||
|
||||
|
||||
# from ../configure.ac
|
||||
WERROR_FLAGS="-Werror -Wno-error=deprecated -Wno-error=deprecated-declarations -Wno-error=cpp"
|
||||
|
||||
src_dir="$PWD"
|
||||
build() {
|
||||
build_dir="$1"
|
||||
|
@ -14,7 +18,7 @@ build() {
|
|||
--enable-embedded \
|
||||
--disable-doxygen \
|
||||
--disable-shared \
|
||||
CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs -Werror"
|
||||
CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs $WERROR_FLAGS"
|
||||
|
||||
$MAKE $PARALLEL_MAKE
|
||||
}
|
||||
|
|
|
@ -1,3 +1,120 @@
|
|||
libosmocore (0.12.0) unstable; urgency=medium
|
||||
|
||||
[ Pau Espin Pedrol ]
|
||||
* control_if: Avoid heap-use-after-free in osmo_wqueue_bfd_cb
|
||||
* configure: Check separately for lib implementing dlopen and dlsym
|
||||
* tests: bitrev_test: Fix dynamic-stack-buffer-overflow
|
||||
* tests: gea_test: Use correct max size for key in buffer
|
||||
* tests: a5_test: Print wrong buffer correctly on error
|
||||
* gsm: kasumi: Fix dynamic-stack-buffer-overflow on out buffers not multiple of 64 bits
|
||||
* gsm: lapdm.c: Add missing new line char in notice log string
|
||||
* ctrl: Log CMD TYPE on invalid ID number
|
||||
* ctrl: Fix parsing of ERROR recvd msgs with id=err
|
||||
* gsm0808: Add value_string for encryption algorithms
|
||||
* ctrl: Introduce ctrl_cmd_parse3 API
|
||||
* ctrl: ctrl_handle_msg: Avoid sending back received ERROR msgs
|
||||
* tests: ctrl: Test received ERROR messages are handled correctly
|
||||
* libosmocoding: clarify return values for TCH decoding functions
|
||||
* libosmocodec: FR err concealment: Fix too many silent frames generated
|
||||
* tests: codec: ecu_fr: Print XMAXC fields
|
||||
* tests: codec: ecu_fr: Add buffer with unequal XMAXC values
|
||||
* rate_ctr: Improve logging
|
||||
* logging: log_vty_command_string: Fix undercount of buf alloc size
|
||||
* logging_vty: Simplify code in config_write_log_single
|
||||
* logging.c: Fix whitespace typo
|
||||
|
||||
[ Harald Welte ]
|
||||
* lapdm: Fix back-pointer from lapdm_entity to lapdm_channel
|
||||
* lapdm: Implement SABM related constraints
|
||||
* lapdm: cleanup: send_rslms_rll_l3_ui(): Use msgb_tv_push()
|
||||
* lapdm: send_rslms_rll_l3_ui(): Don't include B4/SACCH IE unless needed
|
||||
* lapdm: don't enforce contention resolution on SAPI0/DCCH
|
||||
* Add osmo_timerfd_* functions for osmo_fd-wrapped timerfd
|
||||
* import isdn4linux HDLC code from linux kernel
|
||||
* isdnhdlc: Port from kernel to userspace
|
||||
* mncc: properly export osmo_mncc_name()
|
||||
* cosmetic: Whitespace fixes in control_if.c
|
||||
* ctrl: Introduce libosmoctrl.map to avoid unintended exports
|
||||
* ctrl: Add doxygen API documentation; generate html from it
|
||||
* debian: Add libosmoctrl-doc sub-package
|
||||
* gsm_08_08.h: Add enum for LCLS config, control and status
|
||||
* gsm0808: Add encoding functions for LCLS BSSMAP messages
|
||||
* gsm0808: Add value_string for LCLS related IEs
|
||||
* tlv: Add TLVP_VAL_MINLEN() to obtain value _if_ length is >= minimum
|
||||
* Add osmo_isqrt32() to compute 32bit integer square root
|
||||
* fsm: Change semantics of LOGPFSML() log-level
|
||||
* vty: Don't dump deprecated commands in XML export
|
||||
* vty: Add logging_vty_add_deprecated_subsys
|
||||
* gsup: Add osmo_gsup_get_err_msg_type() function
|
||||
* gsup: Add value_string for Session State IE
|
||||
* gsm 04.80: Add value_string for component type and op code
|
||||
* Fix embedded (arm-none-eabi) builds
|
||||
* jenkins_arm.sh: Don't run 'make check' on embedded builds
|
||||
* jenkins_arch.sh: Accept "arm-none-eabi" as alias for "arm"
|
||||
* jenkins_arch.sh: Exit with error on unknown architecture
|
||||
* Don't call abort() directly, always use osmo_panic()
|
||||
* osmo_panic(): Annotate as __attribute__ ((noreturn))
|
||||
* gprs_ns.h: Declare gprs_ns_cause_str() which already existed in c file
|
||||
|
||||
[ Stefan Sperling ]
|
||||
* define a constant for the max length of called party BCD IE
|
||||
* introduce vty_out_rate_ctr_group_fmt() function
|
||||
* Add a 'show rate-counters' VTY command.
|
||||
* remove unused argument from pad_append_ctr() helper function
|
||||
* check bssgp_tlv_parse() return code in bssgp_rcvmsg()
|
||||
* return error to sender upon bssgp_tlv_parse() failure
|
||||
|
||||
[ Neels Hofmeyr ]
|
||||
* add gsm0808 channel enum to IE val conversion functions
|
||||
* add gsm0808_cell_id_to_list()
|
||||
* add support for gsm0808 HANDOVER REQUIRED message
|
||||
* add gsm0808_create_handover_request_ack()
|
||||
* add osmo_fsm_inst_state_chg_keep_timer()
|
||||
* fix gsm0808_permitted_speech(): don't return HR3 for TCH_F + AMR
|
||||
* add and tweak inter-BSC HO API
|
||||
* vty/command.c: talloc from tall_vty_cmd_ctx, not NULL
|
||||
* vty: cosmetic: cmd_deopt(): use talloc_strndup(), not memcpy()
|
||||
* vty: fix use-after-free and memleaks in is_cmd_ambiguous()
|
||||
* utils_test: fix isqrt_test calculation range
|
||||
* utils_test: check stderr to catch sanitizer issues
|
||||
* add osmo_sockaddr_to_str_and_uint()
|
||||
|
||||
[ Philipp Maier ]
|
||||
* fsm: guard action callback
|
||||
* gsm_04_08: add function to get value string
|
||||
* gsm_08_08: gsm0808_permitted_speech does not have value strings
|
||||
|
||||
[ Thorsten Alteholz ]
|
||||
* fix spelling
|
||||
|
||||
[ Keith ]
|
||||
* Add enum gsm48_cause_coding from GSM 04.08 Section 10.5.4.11
|
||||
* Add enum gsm48_progress_desc
|
||||
|
||||
[ Daniel Willmann ]
|
||||
* ports.h: Add ctrl port for osmo-gbproxy
|
||||
* Add function gprs_nsvc_state_append
|
||||
* stats_vty: Add asciidoc sections between the different counters
|
||||
|
||||
[ Vadim Yanitskiy ]
|
||||
* gsm0480: fix: don't overwrite the data of RELEASE_COMPLETE
|
||||
* GSUP: implement TCAP-like session management
|
||||
* GSUP: introduce new messages for SS/USSD payloads
|
||||
* Doxygen: gitignore generated files for libosmoctrl
|
||||
* gsm/gsm0480.c: introduce gsm0480_extract_ie_by_tag()
|
||||
* gsm/gsm0480: refactor and expose gsm0480_parse_facility_ie()
|
||||
* Don't enforce Python 2 for utilities
|
||||
|
||||
[ Alexander Chemeris ]
|
||||
* coding: Fix (E)GPRS BER calculation to correctly account for puncturing.
|
||||
* coding: Documentation typo fix.
|
||||
|
||||
[ Alexander Couzens ]
|
||||
* vty: initialize termios before using it
|
||||
* stats_statsd: sanitize statsd name
|
||||
|
||||
-- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 27 Jul 2018 17:31:46 +0200
|
||||
|
||||
libosmocore (0.11.0+ow2) unstable; urgency=medium
|
||||
|
||||
* Release version for On-Waves
|
||||
|
|
|
@ -27,9 +27,9 @@ Architecture: any
|
|||
Multi-Arch: foreign
|
||||
Depends: libosmocodec0 (= ${binary:Version}),
|
||||
libosmocoding0 (= ${binary:Version}),
|
||||
libosmocore10 (= ${binary:Version}),
|
||||
libosmocore11 (= ${binary:Version}),
|
||||
libosmogb6 (= ${binary:Version}),
|
||||
libosmogsm9 (= ${binary:Version}),
|
||||
libosmogsm10 (= ${binary:Version}),
|
||||
libosmovty4 (= ${binary:Version}),
|
||||
libosmoctrl0 (= ${binary:Version}),
|
||||
libosmosim0 (= ${binary:Version}),
|
||||
|
@ -110,7 +110,7 @@ Description: Documentation for the osmo coding library
|
|||
.
|
||||
This package contains the documentation for the libosmocoding library.
|
||||
|
||||
Package: libosmocore10
|
||||
Package: libosmocore11
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
|
@ -124,14 +124,14 @@ Description: Osmo Core library
|
|||
(at least) other programs that are developed in the sphere of Free Software /
|
||||
Open Source mobile communication.
|
||||
.
|
||||
The libosmocore10 library in particular is a collection of common code used in
|
||||
The libosmocore11 library in particular is a collection of common code used in
|
||||
various sub-projects inside the Osmocom family of projects.
|
||||
|
||||
Package: libosmocore-doc
|
||||
Architecture: all
|
||||
Section: doc
|
||||
Depends: ${misc:Depends},
|
||||
libosmocore10,
|
||||
libosmocore11,
|
||||
libjs-jquery,
|
||||
libosmocodec-doc,
|
||||
libosmocoding-doc,
|
||||
|
@ -178,7 +178,7 @@ Description: Documentation for the Osmo GPRS Gb library
|
|||
.
|
||||
This package contains the documentation for the libosmogb library.
|
||||
|
||||
Package: libosmogsm9
|
||||
Package: libosmogsm10
|
||||
Section: libs
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
|
@ -202,7 +202,7 @@ Package: libosmogsm-doc
|
|||
Architecture: all
|
||||
Section: doc
|
||||
Depends: ${misc:Depends},
|
||||
libosmogsm9,
|
||||
libosmogsm10,
|
||||
libjs-jquery
|
||||
Description: Documentation for the Osmo GSM utility library
|
||||
This is part of the libosmocore "meta"-library. The libosmocore library
|
||||
|
|
|
@ -25,10 +25,6 @@ override_dh_install:
|
|||
override_dh_auto_test:
|
||||
dh_auto_test || (find . -name testsuite.log -exec cat {} \; ; false)
|
||||
|
||||
override_dh_autoreconf:
|
||||
echo $(VERSION) > .tarball-version
|
||||
dh_autoreconf
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- --enable-static
|
||||
|
||||
|
|
|
@ -100,6 +100,7 @@ nobase_include_HEADERS = \
|
|||
osmocom/gsm/prim.h \
|
||||
osmocom/gsm/l1sap.h \
|
||||
osmocom/gsm/oap.h \
|
||||
osmocom/gsm/oap_client.h \
|
||||
osmocom/gsm/protocol/gsm_03_40.h \
|
||||
osmocom/gsm/protocol/gsm_03_41.h \
|
||||
osmocom/gsm/protocol/gsm_04_08.h \
|
||||
|
|
|
@ -178,7 +178,7 @@ static inline const char *osmo_fsm_inst_state_name(struct osmo_fsm_inst *fi)
|
|||
*/
|
||||
#define osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T) \
|
||||
_osmo_fsm_inst_state_chg(fi, new_state, timeout_secs, T, \
|
||||
__BASE_FILE__, __LINE__)
|
||||
__FILE__, __LINE__)
|
||||
int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state,
|
||||
unsigned long timeout_secs, int T,
|
||||
const char *file, int line);
|
||||
|
@ -194,7 +194,7 @@ int _osmo_fsm_inst_state_chg(struct osmo_fsm_inst *fi, uint32_t new_state,
|
|||
*/
|
||||
#define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \
|
||||
_osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \
|
||||
__BASE_FILE__, __LINE__)
|
||||
__FILE__, __LINE__)
|
||||
int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state,
|
||||
const char *file, int line);
|
||||
|
||||
|
@ -205,7 +205,7 @@ int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_s
|
|||
* purposes. See there for documentation.
|
||||
*/
|
||||
#define osmo_fsm_inst_dispatch(fi, event, data) \
|
||||
_osmo_fsm_inst_dispatch(fi, event, data, __BASE_FILE__, __LINE__)
|
||||
_osmo_fsm_inst_dispatch(fi, event, data, __FILE__, __LINE__)
|
||||
int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data,
|
||||
const char *file, int line);
|
||||
|
||||
|
@ -216,7 +216,7 @@ int _osmo_fsm_inst_dispatch(struct osmo_fsm_inst *fi, uint32_t event, void *data
|
|||
* See there for documentation.
|
||||
*/
|
||||
#define osmo_fsm_inst_term(fi, cause, data) \
|
||||
_osmo_fsm_inst_term(fi, cause, data, __BASE_FILE__, __LINE__)
|
||||
_osmo_fsm_inst_term(fi, cause, data, __FILE__, __LINE__)
|
||||
void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi,
|
||||
enum osmo_fsm_term_cause cause, void *data,
|
||||
const char *file, int line);
|
||||
|
@ -228,7 +228,7 @@ void _osmo_fsm_inst_term(struct osmo_fsm_inst *fi,
|
|||
* purposes. See there for documentation.
|
||||
*/
|
||||
#define osmo_fsm_inst_term_children(fi, cause, data) \
|
||||
_osmo_fsm_inst_term_children(fi, cause, data, __BASE_FILE__, __LINE__)
|
||||
_osmo_fsm_inst_term_children(fi, cause, data, __FILE__, __LINE__)
|
||||
void _osmo_fsm_inst_term_children(struct osmo_fsm_inst *fi,
|
||||
enum osmo_fsm_term_cause cause,
|
||||
void *data,
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#define GSMTAP_TYPE_UM 0x01
|
||||
#define GSMTAP_TYPE_ABIS 0x02
|
||||
#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
|
||||
#define GSMTAP_TYPE_SIM 0x04
|
||||
#define GSMTAP_TYPE_SIM 0x04 /* ISO 7816 smart card interface */
|
||||
#define GSMTAP_TYPE_TETRA_I1 0x05 /* tetra air interface */
|
||||
#define GSMTAP_TYPE_TETRA_I1_BURST 0x06 /* tetra air interface */
|
||||
#define GSMTAP_TYPE_WMX_BURST 0x07 /* WiMAX burst */
|
||||
|
@ -103,6 +103,18 @@
|
|||
|
||||
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
|
||||
|
||||
/* sub-types for GSMTAP_TYPE_SIM */
|
||||
#define GSMTAP_SIM_APDU 0x00 /* APDU data (complete APDU) */
|
||||
#define GSMTAP_SIM_ATR 0x01 /* card ATR data */
|
||||
#define GSMTAP_SIM_PPS_REQ 0x02 /* PPS request data */
|
||||
#define GSMTAP_SIM_PPS_RSP 0x03 /* PPS response data */
|
||||
#define GSMTAP_SIM_TPDU_HDR 0x04 /* TPDU command header */
|
||||
#define GSMTAP_SIM_TPDU_CMD 0x05 /* TPDU command body */
|
||||
#define GSMTAP_SIM_TPDU_RSP 0x06 /* TPDU response body */
|
||||
#define GSMTAP_SIM_TPDU_SW 0x07 /* TPDU response trailer */
|
||||
|
||||
/* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */
|
||||
|
||||
/* sub-types for TYPE_TETRA_AIR */
|
||||
#define GSMTAP_TETRA_BSCH 0x01
|
||||
#define GSMTAP_TETRA_AACH 0x02
|
||||
|
|
|
@ -55,17 +55,17 @@ void logp(int subsys, const char *file, int line, int cont, const char *format,
|
|||
#define LOGPC(ss, level, fmt, args...) \
|
||||
do { \
|
||||
if (log_check_level(ss, level)) \
|
||||
logp2(ss, level, __BASE_FILE__, __LINE__, 1, fmt, ##args); \
|
||||
logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args); \
|
||||
} while(0)
|
||||
|
||||
/*! Log through the Osmocom logging framework with explicit source.
|
||||
* If caller_file is passed as NULL, __BASE_FILE__ and __LINE__ are used
|
||||
* If caller_file is passed as NULL, __FILE__ and __LINE__ are used
|
||||
* instead of caller_file and caller_line (so that this macro here defines
|
||||
* both cases in the same place, and to catch cases where callers fail to pass
|
||||
* a non-null filename string).
|
||||
* \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
|
||||
* \param[in] level logging level (e.g. \ref LOGL_NOTICE)
|
||||
* \param[in] caller_file caller's source file string (e.g. __BASE_FILE__)
|
||||
* \param[in] caller_file caller's source file string (e.g. __FILE__)
|
||||
* \param[in] caller_line caller's source line nr (e.g. __LINE__)
|
||||
* \param[in] fmt format string
|
||||
* \param[in] args variable argument list
|
||||
|
@ -74,13 +74,13 @@ void logp(int subsys, const char *file, int line, int cont, const char *format,
|
|||
LOGPSRCC(ss, level, caller_file, caller_line, 0, fmt, ##args)
|
||||
|
||||
/*! Log through the Osmocom logging framework with explicit source.
|
||||
* If caller_file is passed as NULL, __BASE_FILE__ and __LINE__ are used
|
||||
* If caller_file is passed as NULL, __FILE__ and __LINE__ are used
|
||||
* instead of caller_file and caller_line (so that this macro here defines
|
||||
* both cases in the same place, and to catch cases where callers fail to pass
|
||||
* a non-null filename string).
|
||||
* \param[in] ss logging subsystem (e.g. \ref DLGLOBAL)
|
||||
* \param[in] level logging level (e.g. \ref LOGL_NOTICE)
|
||||
* \param[in] caller_file caller's source file string (e.g. __BASE_FILE__)
|
||||
* \param[in] caller_file caller's source file string (e.g. __FILE__)
|
||||
* \param[in] caller_line caller's source line nr (e.g. __LINE__)
|
||||
* \param[in] cont continuation (1) or new line (0)
|
||||
* \param[in] fmt format string
|
||||
|
@ -92,7 +92,7 @@ void logp(int subsys, const char *file, int line, int cont, const char *format,
|
|||
if (caller_file) \
|
||||
logp2(ss, level, caller_file, caller_line, cont, fmt, ##args); \
|
||||
else \
|
||||
logp2(ss, level, __BASE_FILE__, __LINE__, cont, fmt, ##args); \
|
||||
logp2(ss, level, __FILE__, __LINE__, cont, fmt, ##args); \
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
|
@ -228,6 +228,12 @@ enum log_filename_type {
|
|||
LOG_FILENAME_BASENAME,
|
||||
};
|
||||
|
||||
/*! Where on a log line source file and line should be logged. */
|
||||
enum log_filename_pos {
|
||||
LOG_FILENAME_POS_HEADER_END,
|
||||
LOG_FILENAME_POS_LINE_END,
|
||||
};
|
||||
|
||||
/*! structure representing a logging target */
|
||||
struct log_target {
|
||||
struct llist_head entry; /*!< linked list */
|
||||
|
@ -313,6 +319,8 @@ struct log_target {
|
|||
bool print_category_hex;
|
||||
/* Should we print the source file and line, and in which way? */
|
||||
enum log_filename_type print_filename2;
|
||||
/* Where on a log line to put the source file info. */
|
||||
enum log_filename_pos print_filename_pos;
|
||||
};
|
||||
|
||||
/* use the above macros */
|
||||
|
@ -335,6 +343,7 @@ void log_set_print_extended_timestamp(struct log_target *target, int);
|
|||
void log_set_print_timestamp(struct log_target *target, int);
|
||||
void log_set_print_filename(struct log_target *target, int);
|
||||
void log_set_print_filename2(struct log_target *target, enum log_filename_type lft);
|
||||
void log_set_print_filename_pos(struct log_target *target, enum log_filename_pos pos);
|
||||
void log_set_print_category(struct log_target *target, int);
|
||||
void log_set_print_category_hex(struct log_target *target, int);
|
||||
void log_set_print_level(struct log_target *target, int);
|
||||
|
|
|
@ -81,6 +81,40 @@ static inline void msgb_queue_free(struct llist_head *queue)
|
|||
while ((msg = msgb_dequeue(queue))) msgb_free(msg);
|
||||
}
|
||||
|
||||
/*! Enqueue message buffer to tail of a queue and increment queue size counter
|
||||
* \param[in] queue linked list header of queue
|
||||
* \param[in] msg message buffer to be added to the queue
|
||||
* \param[in] count pointer to variable holding size of the queue
|
||||
*
|
||||
* The function will append the specified message buffer \a msg to the queue
|
||||
* implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count,
|
||||
* then increment \a count
|
||||
*/
|
||||
static inline void msgb_enqueue_count(struct llist_head *queue, struct msgb *msg,
|
||||
unsigned int *count)
|
||||
{
|
||||
msgb_enqueue(queue, msg);
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
/*! Dequeue message buffer from head of queue and decrement queue size counter
|
||||
* \param[in] queue linked list header of queue
|
||||
* \param[in] count pointer to variable holding size of the queue
|
||||
* \returns message buffer (if any) or NULL if queue empty
|
||||
*
|
||||
* The function will remove the first message buffer from the queue
|
||||
* implemented by \ref llist_head \a queue using function \ref msgb_enqueue_count,
|
||||
* and decrement \a count, all if queue is not empty.
|
||||
*/
|
||||
static inline struct msgb *msgb_dequeue_count(struct llist_head *queue,
|
||||
unsigned int *count)
|
||||
{
|
||||
struct msgb *msg = msgb_dequeue(queue);
|
||||
if (msg)
|
||||
(*count)--;
|
||||
return msg;
|
||||
}
|
||||
|
||||
#ifdef MSGB_DEBUG
|
||||
#include <osmocom/core/panic.h>
|
||||
#define MSGB_ABORT(msg, fmt, args ...) do { \
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef int osmo_signal_cbfn(unsigned int subsys, unsigned int signal, void *han
|
|||
|
||||
|
||||
/* Management */
|
||||
void *osmo_signal_talloc_ctx_init(void *root_ctx);
|
||||
int osmo_signal_register_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data);
|
||||
void osmo_signal_unregister_handler(unsigned int subsys, osmo_signal_cbfn *cbfn, void *data);
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ struct osmo_fd;
|
|||
#define OSMO_SOCK_F_NO_MCAST_LOOP (1 << 3)
|
||||
/*! disable receiving all multiast even for non-subscribed groups */
|
||||
#define OSMO_SOCK_F_NO_MCAST_ALL (1 << 4)
|
||||
/*! use SO_REUSEADDR on UDP ports (required for multicast) */
|
||||
#define OSMO_SOCK_F_UDP_REUSEADDR (1 << 5)
|
||||
|
||||
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||
const char *host, uint16_t port, unsigned int flags);
|
||||
|
|
|
@ -78,7 +78,7 @@ do { \
|
|||
*/
|
||||
#define OSMO_ASSERT(exp) \
|
||||
if (!(exp)) { \
|
||||
osmo_panic("Assert failed %s %s:%d\n", #exp, __BASE_FILE__, __LINE__); \
|
||||
osmo_panic("Assert failed %s %s:%d\n", #exp, __FILE__, __LINE__); \
|
||||
}
|
||||
|
||||
/*! duplicate a string using talloc and release its prior content (if any)
|
||||
|
|
|
@ -207,6 +207,9 @@ int bssgp_fc_in(struct bssgp_flow_control *fc, struct msgb *msg,
|
|||
int bssgp_fc_ms_init(struct bssgp_flow_control *fc_ms, uint16_t bvci,
|
||||
uint16_t nsei, uint32_t max_queue_depth);
|
||||
|
||||
void bssgp_flush_all_queues();
|
||||
void bssgp_fc_flush_queue(struct bssgp_flow_control *fc);
|
||||
|
||||
/* gprs_bssgp_vty.c */
|
||||
int bssgp_vty_init(void);
|
||||
void bssgp_set_log_ss(int ss);
|
||||
|
|
|
@ -108,6 +108,11 @@ int gsm0480_parse_facility_ie(const uint8_t *facility_ie, uint16_t length,
|
|||
int gsm0480_decode_ss_request(const struct gsm48_hdr *hdr, uint16_t len,
|
||||
struct ss_request *request);
|
||||
|
||||
struct msgb *gsm0480_msgb_alloc_name(const char *name);
|
||||
struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text);
|
||||
struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code);
|
||||
struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t problem_code);
|
||||
|
||||
struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text);
|
||||
struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text);
|
||||
struct msgb *gsm0480_create_notifySS(const char *text);
|
||||
|
@ -116,6 +121,3 @@ struct msgb *gsm0480_create_ussd_release_complete(void);
|
|||
|
||||
int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id);
|
||||
int gsm0480_wrap_facility(struct msgb *msg);
|
||||
|
||||
struct gsm48_hdr *gsm0480_l3hdr_push(struct msgb *msg, uint8_t proto_discr,
|
||||
uint8_t msg_type);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
#include <osmocom/gsm/gsm48_ie.h>
|
||||
|
@ -63,3 +65,9 @@ void gsm48_mcc_mnc_to_bcd(uint8_t *bcd_dst, uint16_t mcc, uint16_t mnc)
|
|||
OSMO_DEPRECATED("Use osmo_plmn_to_bcd() instead, to not lose leading zeros in the MNC");
|
||||
void gsm48_mcc_mnc_from_bcd(uint8_t *bcd_src, uint16_t *mcc, uint16_t *mnc)
|
||||
OSMO_DEPRECATED("Use osmo_plmn_from_bcd() instead, to not lose leading zeros in the MNC");
|
||||
|
||||
struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg,
|
||||
uint8_t pdisc, uint8_t msg_type);
|
||||
|
||||
#define gsm48_push_l3hdr_tid(msg, pdisc, tid, msg_type) \
|
||||
gsm48_push_l3hdr(msg, (pdisc & 0x0f) | (tid << 4), msg_type)
|
||||
|
|
|
@ -26,11 +26,16 @@ struct ipaccess_unit {
|
|||
/* obtain the human-readable name of an IPA CCM ID TAG */
|
||||
const char *ipa_ccm_idtag_name(uint8_t tag);
|
||||
|
||||
/* parse a buffer of ID tags into a osmocom TLV style representation */
|
||||
int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len);
|
||||
int ipa_ccm_idtag_parse(struct tlv_parsed *dec, unsigned char *buf, int len)
|
||||
OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead");
|
||||
int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset)
|
||||
OSMO_DEPRECATED("Use ipa_ccm_id_{get,resp}_parse instead");
|
||||
|
||||
/* Is the TAG included in the length field? */
|
||||
int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len, const int len_offset);
|
||||
/* parse payload of IPA CCM ID GET into a osmocom TLV style representation */
|
||||
int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len);
|
||||
|
||||
/* parse payload of IPA CCM ID RESP into a osmocom TLV style representation */
|
||||
int ipa_ccm_id_resp_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len);
|
||||
|
||||
/* parse an Unit ID in string format into the 'ipaccess_unit' data structure */
|
||||
int ipa_parse_unitid(const char *str, struct ipaccess_unit *unit_data);
|
||||
|
|
|
@ -90,7 +90,7 @@ void _osmo_mncc_log(int subsys, int level, const char *file, int line, const cha
|
|||
const uint8_t *msg, unsigned int len);
|
||||
|
||||
#define osmo_mncc_log(ss, level, prefix, msg, len) \
|
||||
_osmo_mncc_log(ss, level, __BASE_FILE__, __LINE__, prefix, msg, len);
|
||||
_osmo_mncc_log(ss, level, __FILE__, __LINE__, prefix, msg, len);
|
||||
|
||||
extern const struct value_string osmo_mncc_names[];
|
||||
static inline const char *osmo_mncc_name(uint32_t msg_type) {
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* Osmocom Authentication Protocol API */
|
||||
|
||||
/* (C) 2015 by Sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Hofmeyr
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct msgb;
|
||||
struct osmo_oap_message;
|
||||
|
||||
/* This is the config part for vty. It is essentially copied in
|
||||
* oap_client_state, where values are copied over once the config is
|
||||
* considered valid. */
|
||||
struct osmo_oap_client_config {
|
||||
uint16_t client_id;
|
||||
int secret_k_present;
|
||||
uint8_t secret_k[16];
|
||||
int secret_opc_present;
|
||||
uint8_t secret_opc[16];
|
||||
};
|
||||
|
||||
/* The runtime state of the OAP client. client_id and the secrets are in fact
|
||||
* duplicated from oap_client_config, so that a separate validation of the
|
||||
* config data is possible, and so that only a struct oap_client_state* is
|
||||
* passed around. */
|
||||
struct osmo_oap_client_state {
|
||||
enum {
|
||||
OSMO_OAP_UNINITIALIZED = 0, /* just allocated. */
|
||||
OSMO_OAP_DISABLED, /* disabled by config. */
|
||||
OSMO_OAP_INITIALIZED, /* enabled, config is valid. */
|
||||
OSMO_OAP_REQUESTED_CHALLENGE,
|
||||
OSMO_OAP_SENT_CHALLENGE_RESULT,
|
||||
OSMO_OAP_REGISTERED
|
||||
} state;
|
||||
uint16_t client_id;
|
||||
uint8_t secret_k[16];
|
||||
uint8_t secret_opc[16];
|
||||
int registration_failures;
|
||||
};
|
||||
|
||||
/* From config, initialize state. Return 0 on success. */
|
||||
int osmo_oap_client_init(struct osmo_oap_client_config *config,
|
||||
struct osmo_oap_client_state *state);
|
||||
|
||||
/* Construct an OAP registration message and return in *msg_tx. Use
|
||||
* state->client_id and update state->state.
|
||||
* Return 0 on success, or a negative value on error.
|
||||
* If an error is returned, *msg_tx is guaranteed to be NULL. */
|
||||
int osmo_oap_client_register(struct osmo_oap_client_state *state, struct msgb **msg_tx);
|
||||
|
||||
/* Decode and act on a received OAP message msg_rx. Update state->state. If a
|
||||
* non-NULL pointer is returned in *msg_tx, that msgb should be sent to the OAP
|
||||
* server (and freed) by the caller. The received msg_rx is not freed.
|
||||
* Return 0 on success, or a negative value on error.
|
||||
* If an error is returned, *msg_tx is guaranteed to be NULL. */
|
||||
int osmo_oap_client_handle(struct osmo_oap_client_state *state,
|
||||
const struct msgb *msg_rx, struct msgb **msg_tx);
|
||||
|
||||
/* Allocate a msgb and in it, return the encoded oap_client_msg. Return
|
||||
* NULL on error. (Like oap_client_encode(), but also allocates a msgb.)
|
||||
* About the name: the idea is do_something(oap_client_encoded(my_struct))
|
||||
*/
|
||||
struct msgb *osmo_oap_client_encoded(const struct osmo_oap_message *oap_client_msg);
|
|
@ -4,11 +4,23 @@ REL=$2
|
|||
|
||||
if [ "z$REL" = "z" ]; then
|
||||
echo "No REL value specified, defaulting to 'patch' release"
|
||||
REL=patch
|
||||
REL="patch"
|
||||
fi
|
||||
|
||||
BUMPVER=`command -v bumpversion`
|
||||
ALLOW_NO_LIBVERSION_CHANGE="${ALLOW_NO_LIBVERSION_CHANGE:-0}"
|
||||
ALLOW_NO_LIBVERSION_DEB_MATCH="${ALLOW_NO_LIBVERSION_DEB_MATCH:-0}"
|
||||
|
||||
libversion_to_deb_major() {
|
||||
libversion="$1"
|
||||
current="$(echo "$libversion" | cut -d ":" -f 1)"
|
||||
#revision="$(echo "$libversion" | cut -d ":" -f 2)"
|
||||
age="$(echo "$libversion" | cut -d ":" -f 3)"
|
||||
major="$(expr "$current" - "$age")"
|
||||
echo "$major"
|
||||
}
|
||||
|
||||
BUMPVER=`command -v bumpversion`
|
||||
GIT_TOPDIR="$(git rev-parse --show-toplevel)"
|
||||
NEW_VER=`bumpversion --list --current-version $VERSION $REL --allow-dirty | awk -F '=' '{ print $2 }'`
|
||||
LIBVERS=`git grep -n LIBVERSION | grep '=' | grep am | grep -v LDFLAGS`
|
||||
MAKEMOD=`git diff --cached -GLIBVERSION --stat | grep Makefile.am`
|
||||
|
@ -27,12 +39,40 @@ fi
|
|||
echo "Releasing $VERSION -> $NEW_VER..."
|
||||
|
||||
if [ "z$LIBVERS" != "z" ]; then
|
||||
if [ "z$MAKEMOD" = "z" ]; then
|
||||
echo "Before releasing, please modify some of the libversions: $LIBVERS"
|
||||
if [ "z$MAKEMOD" = "z" ] && [ "z$ALLOW_NO_LIBVERSION_CHANGE" = "z0" ]; then
|
||||
echo "ERROR: Before releasing, please modify some of the libversions: $LIBVERS"
|
||||
echo "You should NOT be doing this unless you've read and understood following article:"
|
||||
echo "https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info"
|
||||
exit 1
|
||||
fi
|
||||
if [ "z$ALLOW_NO_LIBVERSION_DEB_MATCH" = "z0" ]; then
|
||||
echo "$LIBVERS" | while read -r line; do
|
||||
libversion=$(echo "$line" | cut -d "=" -f 2)
|
||||
major="$(libversion_to_deb_major "$libversion")"
|
||||
file_matches="$(find "${GIT_TOPDIR}/debian" -name "lib*${major}.install" | wc -l)"
|
||||
if [ "z$file_matches" = "z0" ]; then
|
||||
echo "ERROR: Found no matching debian/lib*$major.install file for LIBVERSION=$libversion"
|
||||
exit 1
|
||||
elif [ "z$file_matches" = "z1" ]; then
|
||||
echo "OK: Found matching debian/lib*$major.install for LIBVERSION=$libversion"
|
||||
else
|
||||
echo "WARN: Found $file_matches files matching debian/lib*$major.install for LIBVERSION=$libversion, manual check required!"
|
||||
fi
|
||||
control_matches="$(grep -e "Package" "${GIT_TOPDIR}/debian/control" | grep "lib" | grep "$major$" | wc -l)"
|
||||
if [ "z$control_matches" = "z0" ]; then
|
||||
echo "ERROR: Found no matching Package lib*$major in debian/control for LIBVERSION=$libversion"
|
||||
exit 1
|
||||
elif [ "z$control_matches" = "z1" ]; then
|
||||
echo "OK: Found 'Package: lib*$major' in debian/control for LIBVERSION=$libversion"
|
||||
else
|
||||
echo "WARN: Found $file_matches files matching 'Package: lib*$major' in debian/control for LIBVERSION=$libversion, manual check required!"
|
||||
fi
|
||||
done
|
||||
# catch and forward exit from pipe subshell "while read":
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -f "TODO-RELEASE" ]; then
|
||||
grep '#' TODO-RELEASE > TODO-RELEASE.clean
|
||||
mv TODO-RELEASE.clean TODO-RELEASE
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=10:0:0
|
||||
LIBVERSION=11:0:0
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=1:0:1
|
||||
LIBVERSION=1:1:1
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include $(TALLOC_CFLAGS)
|
||||
AM_CFLAGS = -Wall
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read Chapter 6 "Library interface versions" of the libtool
|
||||
# documentation before making any modification
|
||||
LIBVERSION = 1:0:1
|
||||
LIBVERSION = 1:1:1
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I"$(top_srcdir)/include" \
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=2:0:2
|
||||
LIBVERSION=3:0:3
|
||||
|
||||
AM_CFLAGS = -Wall $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS)
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ static int get_fsm_inst_dump(struct ctrl_cmd *cmd, void *data)
|
|||
if (fi->proc.parent)
|
||||
cmd->reply = talloc_asprintf_append(cmd->reply, ",parent='%s'", fi->proc.parent->name);
|
||||
|
||||
llist_for_each_entry(child, &fi->proc.children, list) {
|
||||
llist_for_each_entry(child, &fi->proc.children, proc.child) {
|
||||
cmd->reply = talloc_asprintf_append(cmd->reply, ",child='%s'", child->name);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification
|
||||
LIBVERSION=6:0:0
|
||||
LIBVERSION=7:0:1
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN} -fno-strict-aliasing $(TALLOC_CFLAGS)
|
||||
|
@ -23,4 +23,3 @@ libosmogb_la_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c \
|
|||
endif
|
||||
|
||||
EXTRA_DIST = libosmogb.map
|
||||
|
||||
|
|
|
@ -1263,3 +1263,31 @@ void bssgp_set_log_ss(int ss)
|
|||
{
|
||||
DBSSGP = ss;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Flush the queue of the bssgp_flow_control
|
||||
* \param[in] The flow control object which holds the queue.
|
||||
*/
|
||||
void bssgp_fc_flush_queue(struct bssgp_flow_control *fc)
|
||||
{
|
||||
struct bssgp_fc_queue_element *element, *tmp;
|
||||
|
||||
llist_for_each_entry_safe(element, tmp, &fc->queue, list) {
|
||||
msgb_free(element->msg);
|
||||
llist_del(&element->list);
|
||||
talloc_free(element);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Flush the queues of all BSSGP contexts.
|
||||
*/
|
||||
void bssgp_flush_all_queues()
|
||||
{
|
||||
struct bssgp_bvc_ctx *bctx;
|
||||
|
||||
llist_for_each_entry(bctx, &bssgp_bvc_ctxts, list) {
|
||||
if (bctx->fc)
|
||||
bssgp_fc_flush_queue(bctx->fc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,8 +87,8 @@
|
|||
|
||||
#include "common_vty.h"
|
||||
|
||||
#define ns_set_state(ns_, st_) ns_set_state_with_log(ns_, st_, false, __BASE_FILE__, __LINE__)
|
||||
#define ns_set_remote_state(ns_, st_) ns_set_state_with_log(ns_, st_, true, __BASE_FILE__, __LINE__)
|
||||
#define ns_set_state(ns_, st_) ns_set_state_with_log(ns_, st_, false, __FILE__, __LINE__)
|
||||
#define ns_set_remote_state(ns_, st_) ns_set_state_with_log(ns_, st_, true, __FILE__, __LINE__)
|
||||
#define ns_mark_blocked(ns_) ns_set_state(ns_, (ns_)->state | NSE_S_BLOCKED)
|
||||
#define ns_mark_unblocked(ns_) ns_set_state(ns_, (ns_)->state & (~NSE_S_BLOCKED));
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ bssgp_pdu_str;
|
|||
bssgp_fc_in;
|
||||
bssgp_fc_init;
|
||||
bssgp_fc_ms_init;
|
||||
bssgp_fc_flush_queue;
|
||||
bssgp_flush_all_queues;
|
||||
bssgp_msgb_alloc;
|
||||
bssgp_msgb_copy;
|
||||
bssgp_msgb_tlli_put;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=9:0:0
|
||||
LIBVERSION=10:0:0
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include $(TALLOC_CFLAGS)
|
||||
AM_CFLAGS = -Wall ${GCC_FVISIBILITY_HIDDEN}
|
||||
|
@ -30,7 +30,7 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \
|
|||
milenage/aes-internal.c milenage/aes-internal-enc.c \
|
||||
milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \
|
||||
gsup.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \
|
||||
gsm23003.c mncc.c bts_features.c
|
||||
gsm23003.c mncc.c bts_features.c oap_client.c
|
||||
libgsmint_la_LDFLAGS = -no-undefined
|
||||
libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
/*! \file comp128v23.c
|
||||
* COMP128 version 2 and 3 implementation, common algorithm used for GSM Authentication (A3/A8).
|
||||
*
|
||||
* This code is a C conversion of the original code from
|
||||
* http://www.hackingprojects.net/
|
||||
* This code is a C conversion of the original code by Tamas Jos <info@skelsec.com> from:
|
||||
* - original (out of service): http://www.hackingprojects.net/
|
||||
* - original (archive): https://web.archive.org/web/20130730113347/http://www.hackingprojects.net/
|
||||
* - new site: https://github.com/skelsec/COMP128
|
||||
*/
|
||||
/*
|
||||
* (C) 2013 by Kévin Redon <kevredon@mail.tsaitgaist.info>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <osmocom/core/logging.h>
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/gsm0480.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/protocol/gsm_03_40.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
||||
|
@ -354,7 +353,7 @@ int gsm411_push_cp_header(struct msgb *msg, uint8_t proto, uint8_t trans,
|
|||
uint8_t msg_type)
|
||||
{
|
||||
/* Outgoing proto_discr needs the highest bit set */
|
||||
gsm0480_l3hdr_push(msg, proto | (trans << 4), msg_type);
|
||||
gsm48_push_l3hdr_tid(msg, proto, trans, msg_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/gsm0480.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
|
@ -87,6 +88,15 @@ static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
|
|||
return data;
|
||||
}
|
||||
|
||||
static inline unsigned char *msgb_push_NULL(struct msgb *msgb)
|
||||
{
|
||||
uint8_t *data = msgb_push(msgb, 2);
|
||||
|
||||
data[0] = ASN1_NULL_TYPE_TAG;
|
||||
data[1] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
/* wrap an invoke around it... the other way around
|
||||
*
|
||||
* 1.) Invoke Component tag
|
||||
|
@ -122,7 +132,7 @@ struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *
|
|||
uint8_t *seq_len_ptr, *ussd_len_ptr, *data;
|
||||
int len;
|
||||
|
||||
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 USSD Notify");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
|
@ -168,7 +178,7 @@ struct msgb *gsm0480_create_notifySS(const char *text)
|
|||
if (len < 1 || len > 160)
|
||||
return NULL;
|
||||
|
||||
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 NotifySS");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
|
@ -787,13 +797,22 @@ static int parse_ss_for_bs_req(const uint8_t *ss_req_data,
|
|||
return rc;
|
||||
}
|
||||
|
||||
struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text)
|
||||
struct msgb *gsm0480_msgb_alloc_name(const char *name)
|
||||
{
|
||||
return msgb_alloc_headroom(1024, 128, name);
|
||||
}
|
||||
|
||||
/*! Generate a USSD ReturnResult component containing a string in default GSM alphabet.
|
||||
* \param[in] invoke_id InvokeID of the request to which we respond
|
||||
* \param[in] text USSD text in ASCII; to be encoded as GSM 7-but alphabet
|
||||
*/
|
||||
struct msgb *gsm0480_gen_ussd_resp_7bit(uint8_t invoke_id, const char *text)
|
||||
{
|
||||
struct msgb *msg;
|
||||
uint8_t *ptr8;
|
||||
int response_len;
|
||||
|
||||
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 USSD Resp");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
|
@ -824,25 +843,95 @@ struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const
|
|||
/* Wrap this up as a Return Result component */
|
||||
msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_RESULT);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*! Legacy helper: Generate USSD response including FACILITY IE + L3 header.
|
||||
*
|
||||
* This function is just like \ref gsm0480_gen_ussd_resp_7bit, but it generates
|
||||
* not only the FACILITY value, but the full L3 message including message header
|
||||
* and FACILITY IE Tag+Length.
|
||||
*/
|
||||
struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
msg = gsm0480_gen_ussd_resp_7bit(invoke_id, text);
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
/* Wrap the component in a Facility message */
|
||||
msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
|
||||
|
||||
/* And finally pre-pend the L3 header */
|
||||
gsm0480_l3hdr_push(msg,
|
||||
GSM48_PDISC_NC_SS | trans_id
|
||||
| (1<<7) /* TI direction = 1 */,
|
||||
GSM0480_MTYPE_RELEASE_COMPLETE);
|
||||
gsm48_push_l3hdr_tid(msg, GSM48_PDISC_NC_SS,
|
||||
/* FIXME: TI direction is always 1 ?!? */
|
||||
trans_id | (1 << 7),
|
||||
GSM0480_MTYPE_RELEASE_COMPLETE);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct gsm48_hdr *gsm0480_l3hdr_push(struct msgb *msg, uint8_t proto_discr,
|
||||
uint8_t msg_type)
|
||||
/*! Generate a ReturnError component (see section 3.6.1) and given error code (see section 3.6.6).
|
||||
* \param[in] invoke_id InvokeID of the request
|
||||
* \param[in] error_code Error code (section 4.5)
|
||||
* \return message buffer containing the Reject component
|
||||
*
|
||||
* Note: if InvokeID is not available, e.g. when message parsing failed, any incorrect vlue
|
||||
* can be passed (0x00 > x > 0xff), so the universal NULL-tag (see table 3.6) will be used instead.
|
||||
*/
|
||||
struct msgb *gsm0480_gen_return_error(uint8_t invoke_id, uint8_t error_code)
|
||||
{
|
||||
struct gsm48_hdr *gh;
|
||||
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
|
||||
gh->proto_discr = proto_discr;
|
||||
gh->msg_type = msg_type;
|
||||
return gh;
|
||||
struct msgb *msg;
|
||||
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 ReturnError");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
/* First insert the problem code */
|
||||
msgb_push_TLV1(msg, GSM_0480_ERROR_CODE_TAG, error_code);
|
||||
|
||||
/* Before it, insert the invoke ID */
|
||||
msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
|
||||
|
||||
/* Wrap this up as a Reject component */
|
||||
msgb_wrap_with_TL(msg, GSM0480_CTYPE_RETURN_ERROR);
|
||||
|
||||
/* FIXME: Wrap in Facility + L3? */
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*! Generate a Reject component (see section 3.6.1) and given error code (see section 3.6.7).
|
||||
* \param[in] invoke_id InvokeID of the request
|
||||
* \param[in] problem_tag Problem code tag (table 3.13)
|
||||
* \param[in] problem_code Problem code (table 3.14-3.17)
|
||||
* \return message buffer containing the Reject component
|
||||
*
|
||||
* Note: if InvokeID is not available, e.g. when message parsing failed, any incorrect vlue
|
||||
* can be passed (0x00 > x > 0xff), so the universal NULL-tag (see table 3.6) will be used instead.
|
||||
*/
|
||||
struct msgb *gsm0480_gen_reject(int invoke_id, uint8_t problem_tag, uint8_t problem_code)
|
||||
{
|
||||
struct msgb *msg;
|
||||
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 Reject");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
/* First insert the problem code */
|
||||
msgb_push_TLV1(msg, problem_tag, problem_code);
|
||||
|
||||
/* If the Invoke ID is not available, Universal NULL (table 3.9) with length=0 shall be used */
|
||||
if (invoke_id < 0 || invoke_id > 255)
|
||||
msgb_push_NULL(msg);
|
||||
else
|
||||
msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, invoke_id);
|
||||
|
||||
/* Wrap this up as a Reject component */
|
||||
msgb_wrap_with_TL(msg, GSM0480_CTYPE_REJECT);
|
||||
|
||||
/* FIXME: Wrap in Facility + L3? */
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct msgb *gsm0480_create_ussd_notify(int level, const char *text)
|
||||
|
@ -856,7 +945,11 @@ struct msgb *gsm0480_create_ussd_notify(int level, const char *text)
|
|||
gsm0480_wrap_invoke(msg, GSM0480_OP_CODE_USS_NOTIFY, 0);
|
||||
gsm0480_wrap_facility(msg);
|
||||
|
||||
gsm0480_l3hdr_push(msg, GSM48_PDISC_NC_SS, GSM0480_MTYPE_REGISTER);
|
||||
/* And finally pre-pend the L3 header */
|
||||
gsm48_push_l3hdr(msg, GSM48_PDISC_NC_SS,
|
||||
/* FIXME: no transactionID?!? */
|
||||
GSM0480_MTYPE_REGISTER);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -864,12 +957,14 @@ struct msgb *gsm0480_create_ussd_release_complete(void)
|
|||
{
|
||||
struct msgb *msg;
|
||||
|
||||
msg = msgb_alloc_headroom(1024, 128, "GSM 04.80 USSD REL COMPL");
|
||||
msg = gsm0480_msgb_alloc_name("TS 04.80 USSD REL COMPL");
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
/* FIXME: should this set trans_id and TI direction flag? */
|
||||
gsm0480_l3hdr_push(msg, GSM48_PDISC_NC_SS,
|
||||
GSM0480_MTYPE_RELEASE_COMPLETE);
|
||||
/* And finally pre-pend the L3 header */
|
||||
gsm48_push_l3hdr(msg, GSM48_PDISC_NC_SS,
|
||||
/* FIXME: no transactionID?!? */
|
||||
GSM0480_MTYPE_RELEASE_COMPLETE);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
|
|
@ -588,7 +588,7 @@ struct msgb *gsm0808_create_clear_rqst(uint8_t cause)
|
|||
/*! Create BSSMAP PAGING message
|
||||
* \param[in] imsi Mandatory paged IMSI in string representation
|
||||
* \param[in] tmsi Optional paged TMSI
|
||||
* \param[in] cil Cell Identity List (where to page)
|
||||
* \param[in] cil Mandatory Cell Identity List (where to page)
|
||||
* \param[in] chan_needed Channel Type needed
|
||||
* \returns callee-allocated msgb with BSSMAP PAGING message */
|
||||
struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi,
|
||||
|
@ -615,7 +615,7 @@ struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi,
|
|||
/* Message Type 3.2.2.1 */
|
||||
msgb_v_put(msg, BSS_MAP_MSG_PAGING);
|
||||
|
||||
/* IMSI 3.2.2.6 */
|
||||
/* mandatory IMSI 3.2.2.6 */
|
||||
mid_len = gsm48_generate_mid_from_imsi(mid_buf, imsi);
|
||||
msgb_tlv_put(msg, GSM0808_IE_IMSI, mid_len - 2, mid_buf + 2);
|
||||
|
||||
|
@ -626,9 +626,8 @@ struct msgb *gsm0808_create_paging2(const char *imsi, const uint32_t *tmsi,
|
|||
(uint8_t *) & tmsi_sw);
|
||||
}
|
||||
|
||||
/* Cell Identifier List 3.2.2.27 */
|
||||
if (cil)
|
||||
gsm0808_enc_cell_id_list2(msg, cil);
|
||||
/* mandatory Cell Identifier List 3.2.2.27 */
|
||||
gsm0808_enc_cell_id_list2(msg, cil);
|
||||
|
||||
/* Channel Needed 3.2.2.36 */
|
||||
if (chan_needed) {
|
||||
|
@ -763,6 +762,9 @@ struct msgb *gsm0808_create_handover_request_ack(const uint8_t *l3_info, uint8_t
|
|||
if (chosen_speech_version != 0)
|
||||
msgb_tv_put(msg, GSM0808_IE_SPEECH_VERSION, chosen_speech_version);
|
||||
|
||||
/* prepend header with final length */
|
||||
msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -780,6 +782,9 @@ struct msgb *gsm0808_create_handover_detect()
|
|||
/* Message Type, 3.2.2.1 */
|
||||
msgb_v_put(msg, BSS_MAP_MSG_HANDOVER_DETECT);
|
||||
|
||||
/* prepend header with final length */
|
||||
msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -816,6 +821,9 @@ struct msgb *gsm0808_create_handover_complete(const struct gsm0808_handover_comp
|
|||
if (params->lcls_bss_status_present)
|
||||
msgb_tv_put(msg, GSM0808_IE_LCLS_BSS_STATUS, params->lcls_bss_status);
|
||||
|
||||
/* prepend header with final length */
|
||||
msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
@ -843,6 +851,9 @@ struct msgb *gsm0808_create_handover_failure(const struct gsm0808_handover_failu
|
|||
if (params->codec_list_bss_supported.len)
|
||||
gsm0808_enc_speech_codec_list(msg, ¶ms->codec_list_bss_supported);
|
||||
|
||||
/* prepend header with final length */
|
||||
msg->l3h = msgb_tv_push(msg, BSSAP_MSG_BSS_MANAGEMENT, msgb_length(msg));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
|
@ -1024,4 +1024,24 @@ const struct value_string gsm48_reject_value_names[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*! Wrap a given \ref msg with \ref gsm48_hdr structure
|
||||
* \param[out] msg A message to be wrapped
|
||||
* \param[in] pdisc GSM TS 04.07 protocol discriminator 1/2,
|
||||
* sub-pdisc, trans_id or skip_ind 1/2,
|
||||
* see section 11.2.3.1 for details
|
||||
* \param[in] msg_type GSM TS 04.08 message type
|
||||
* @return pointer to pushed header within \ref msg
|
||||
*/
|
||||
struct gsm48_hdr *gsm48_push_l3hdr(struct msgb *msg,
|
||||
uint8_t pdisc, uint8_t msg_type)
|
||||
{
|
||||
struct gsm48_hdr *gh;
|
||||
|
||||
gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
|
||||
gh->proto_discr = pdisc;
|
||||
gh->msg_type = msg_type;
|
||||
|
||||
return gh;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
112
src/gsm/ipa.c
112
src/gsm/ipa.c
|
@ -137,6 +137,83 @@ int ipa_ccm_idtag_parse_off(struct tlv_parsed *dec, unsigned char *buf, int len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Parse the payload part of an IPA CCM ID GET, return \ref tlv_parsed format.
|
||||
* The odd payload format of those messages is structured as follows:
|
||||
* * 8bit length value (length of payload *and tag*)
|
||||
* * 8bit tag value
|
||||
* * optional, variable-length payload
|
||||
* \param[out] dec Caller-provided/allocated output structure for parsed payload
|
||||
* \param[in] buf Buffer containing the payload (excluding 1 byte msg_type) of the message
|
||||
* \param[in] len Length of \a buf in octets
|
||||
* \returns 0 on success; negative on error */
|
||||
int ipa_ccm_id_get_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len)
|
||||
{
|
||||
uint8_t t_len;
|
||||
uint8_t t_tag;
|
||||
const uint8_t *cur = buf;
|
||||
|
||||
memset(dec, 0, sizeof(*dec));
|
||||
|
||||
while (len >= 2) {
|
||||
len -= 2;
|
||||
t_len = *cur++;
|
||||
t_tag = *cur++;
|
||||
|
||||
if (t_len > len + 1) {
|
||||
LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur);
|
||||
|
||||
dec->lv[t_tag].len = t_len-1;
|
||||
dec->lv[t_tag].val = cur;
|
||||
|
||||
cur += t_len-1;
|
||||
len -= t_len-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Parse the payload part of an IPA CCM ID RESP, return \ref tlv_parsed format.
|
||||
* The odd payload format of those messages is structured as follows:
|
||||
* * 16bit length value (length of payload *and tag*)
|
||||
* * 8bit tag value
|
||||
* * optional, variable-length payload
|
||||
* \param[out] dec Caller-provided/allocated output structure for parsed payload
|
||||
* \param[in] buf Buffer containing the payload (excluding 1 byte msg_type) of the message
|
||||
* \param[in] len Length of \a buf in octets
|
||||
* \returns 0 on success; negative on error */
|
||||
int ipa_ccm_id_resp_parse(struct tlv_parsed *dec, const uint8_t *buf, unsigned int len)
|
||||
{
|
||||
uint8_t t_len;
|
||||
uint8_t t_tag;
|
||||
const uint8_t *cur = buf;
|
||||
|
||||
memset(dec, 0, sizeof(*dec));
|
||||
|
||||
while (len >= 3) {
|
||||
len -= 3;
|
||||
t_len = *cur++ << 8;
|
||||
t_len += *cur++;
|
||||
t_tag = *cur++;
|
||||
|
||||
if (t_len > len + 1) {
|
||||
LOGP(DLMI, LOGL_ERROR, "The tag does not fit: %d > %d\n", t_len, len + 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DEBUGPC(DLMI, "%s='%s' ", ipa_ccm_idtag_name(t_tag), cur);
|
||||
|
||||
dec->lv[t_tag].len = t_len-1;
|
||||
dec->lv[t_tag].val = cur;
|
||||
|
||||
cur += t_len-1;
|
||||
len -= t_len-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipa_parse_unitid(const char *str, struct ipaccess_unit *unit_data)
|
||||
{
|
||||
unsigned long ul;
|
||||
|
@ -251,23 +328,23 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev,
|
|||
break;
|
||||
case IPAC_IDTAG_LOCATION1:
|
||||
if (dev->location1)
|
||||
strncpy(str, dev->location1, IPA_STRING_MAX);
|
||||
osmo_strlcpy(str, dev->location1, sizeof(str));
|
||||
break;
|
||||
case IPAC_IDTAG_LOCATION2:
|
||||
if (dev->location2)
|
||||
strncpy(str, dev->location2, IPA_STRING_MAX);
|
||||
osmo_strlcpy(str, dev->location2, sizeof(str));
|
||||
break;
|
||||
case IPAC_IDTAG_EQUIPVERS:
|
||||
if (dev->equipvers)
|
||||
strncpy(str, dev->equipvers, IPA_STRING_MAX);
|
||||
osmo_strlcpy(str, dev->equipvers, sizeof(str));
|
||||
break;
|
||||
case IPAC_IDTAG_SWVERSION:
|
||||
if (dev->swversion)
|
||||
strncpy(str, dev->swversion, IPA_STRING_MAX);
|
||||
osmo_strlcpy(str, dev->swversion, sizeof(str));
|
||||
break;
|
||||
case IPAC_IDTAG_UNITNAME:
|
||||
if (dev->unit_name) {
|
||||
snprintf(str, sizeof(str), dev->unit_name, IPA_STRING_MAX);
|
||||
snprintf(str, sizeof(str), "%s", dev->unit_name);
|
||||
} else {
|
||||
snprintf(str, sizeof(str),
|
||||
"%02x-%02x-%02x-%02x-%02x-%02x",
|
||||
|
@ -278,7 +355,7 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev,
|
|||
break;
|
||||
case IPAC_IDTAG_SERNR:
|
||||
if (dev->serno)
|
||||
strncpy(str, dev->serno, IPA_STRING_MAX);
|
||||
osmo_strlcpy(str, dev->serno, sizeof(str));
|
||||
break;
|
||||
default:
|
||||
LOGP(DLINP, LOGL_NOTICE,
|
||||
|
@ -286,7 +363,6 @@ struct msgb *ipa_ccm_make_id_resp(const struct ipaccess_unit *dev,
|
|||
msgb_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
str[IPA_STRING_MAX-1] = '\0';
|
||||
|
||||
LOGP(DLINP, LOGL_INFO, " tag %d: %s\n", ies_req[i], str);
|
||||
tag = msgb_put(msg, 3 + strlen(str) + 1);
|
||||
|
@ -452,6 +528,9 @@ void ipa_prepend_header(struct msgb *msg, int proto)
|
|||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
|
||||
/*! Read one ipa message from socket fd without caching not fully received
|
||||
* messages. See \ref ipa_msg_recv_buffered for further information.
|
||||
*/
|
||||
int ipa_msg_recv(int fd, struct msgb **rmsg)
|
||||
{
|
||||
int rc = ipa_msg_recv_buffered(fd, rmsg, NULL);
|
||||
|
@ -462,6 +541,25 @@ int ipa_msg_recv(int fd, struct msgb **rmsg)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*! Read one ipa message from socket fd or store part if still not fully received.
|
||||
* \param[in] fd The fd for the socket to read from.
|
||||
* \param[out] rmsg internally allocated msgb containing a fully received ipa message.
|
||||
* \param[inout] tmp_msg internally allocated msgb caching data for not yet fully received message.
|
||||
*
|
||||
* As ipa can run on top of stream based protocols such as TCP, there's the
|
||||
* possibility that such lower layers split ipa messages in several low level
|
||||
* packets. If a low layer packet is received containing several ipa frames,
|
||||
* this function will pull from the socket and return only the first one
|
||||
* available in the stream. As the socket will remain with data, it will
|
||||
* trigger again during next select() and then this function will fetch the
|
||||
* next ipa message, and so on.
|
||||
*
|
||||
* \returns -EAGAIN and allocated tmp_msg if message was not yet fully
|
||||
* received. Other negative values indicate an error and cached msgb will be
|
||||
* freed. 0 if socket is found dead. Positive value indicating l2 msgb len and
|
||||
* rmsg pointing to internally allocated msgb containing the ipa frame on
|
||||
* scucess.
|
||||
*/
|
||||
int ipa_msg_recv_buffered(int fd, struct msgb **rmsg, struct msgb **tmp_msg)
|
||||
{
|
||||
struct msgb *msg = tmp_msg ? *tmp_msg : NULL;
|
||||
|
|
|
@ -97,6 +97,10 @@ gsm0480_wrap_facility;
|
|||
gsm0480_wrap_invoke;
|
||||
gsm0480_comp_type_names;
|
||||
gsm0480_op_code_names;
|
||||
gsm0480_msgb_alloc_name;
|
||||
gsm0480_gen_ussd_resp_7bit;
|
||||
gsm0480_gen_return_error;
|
||||
gsm0480_gen_reject;
|
||||
|
||||
gsm0502_calc_paging_group;
|
||||
|
||||
|
@ -237,6 +241,7 @@ gsm411_rp_state_names;
|
|||
|
||||
gsm414_msgt_names;
|
||||
|
||||
gsm48_push_l3hdr;
|
||||
gsm48_att_tlvdef;
|
||||
gsm48_cc_msg_name;
|
||||
gsm48_rr_msg_name;
|
||||
|
@ -458,6 +463,8 @@ ipa_ccm_tlv_to_unitdata;
|
|||
ipa_ccm_idtag_name;
|
||||
ipa_ccm_idtag_parse;
|
||||
ipa_ccm_idtag_parse_off;
|
||||
ipa_ccm_id_get_parse;
|
||||
ipa_ccm_id_resp_parse;
|
||||
ipa_ccm_make_id_resp;
|
||||
ipa_ccm_make_id_resp_from_req;
|
||||
ipa_msg_alloc;
|
||||
|
@ -489,5 +496,10 @@ osmo_mncc_stringify;
|
|||
osmo_mncc_names;
|
||||
_osmo_mncc_log;
|
||||
|
||||
osmo_oap_client_encoded;
|
||||
osmo_oap_client_handle;
|
||||
osmo_oap_client_init;
|
||||
osmo_oap_client_register;
|
||||
|
||||
local: *;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
/* Osmocom Authentication Protocol API */
|
||||
|
||||
/* (C) 2015 by Sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Hofmeyr
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/crypt/auth.h>
|
||||
#include <osmocom/gsm/oap.h>
|
||||
|
||||
#include <osmocom/gsm/oap_client.h>
|
||||
|
||||
int osmo_oap_client_init(struct osmo_oap_client_config *config,
|
||||
struct osmo_oap_client_state *state)
|
||||
{
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED);
|
||||
|
||||
if (!config)
|
||||
goto disable;
|
||||
|
||||
if (config->client_id == 0)
|
||||
goto disable;
|
||||
|
||||
if (config->secret_k_present == 0) {
|
||||
LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret K missing.\n");
|
||||
goto disable;
|
||||
}
|
||||
|
||||
if (config->secret_opc_present == 0) {
|
||||
LOGP(DLOAP, LOGL_NOTICE, "OAP: client ID set, but secret OPC missing.\n");
|
||||
goto disable;
|
||||
}
|
||||
|
||||
state->client_id = config->client_id;
|
||||
memcpy(state->secret_k, config->secret_k, sizeof(state->secret_k));
|
||||
memcpy(state->secret_opc, config->secret_opc, sizeof(state->secret_opc));
|
||||
state->state = OSMO_OAP_INITIALIZED;
|
||||
return 0;
|
||||
|
||||
disable:
|
||||
state->state = OSMO_OAP_DISABLED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* From the given state and received RAND and AUTN octets, validate the
|
||||
* server's authenticity and formulate the matching milenage reply octets in
|
||||
* *tx_xres. The state is not modified.
|
||||
* On success, and if tx_res is not NULL, exactly 8 octets will be written to
|
||||
* *tx_res. If not NULL, tx_res must point at allocated memory of at least 8
|
||||
* octets. The caller will want to send XRES back to the server in a challenge
|
||||
* response message and update the state.
|
||||
* Return 0 on success; -1 if OAP is disabled; -2 if rx_random and rx_autn fail
|
||||
* the authentication check; -3 for any other errors. */
|
||||
static int oap_evaluate_challenge(const struct osmo_oap_client_state *state,
|
||||
const uint8_t *rx_random,
|
||||
const uint8_t *rx_autn,
|
||||
uint8_t *tx_xres)
|
||||
{
|
||||
struct osmo_auth_vector vec;
|
||||
|
||||
struct osmo_sub_auth_data auth = {
|
||||
.type = OSMO_AUTH_TYPE_UMTS,
|
||||
.algo = OSMO_AUTH_ALG_MILENAGE,
|
||||
};
|
||||
|
||||
osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.k)
|
||||
== sizeof(state->secret_k), _secret_k_size_match);
|
||||
osmo_static_assert(sizeof(((struct osmo_sub_auth_data*)0)->u.umts.opc)
|
||||
== sizeof(state->secret_opc), _secret_opc_size_match);
|
||||
|
||||
switch (state->state) {
|
||||
case OSMO_OAP_UNINITIALIZED:
|
||||
case OSMO_OAP_DISABLED:
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(auth.u.umts.k, state->secret_k, sizeof(auth.u.umts.k));
|
||||
memcpy(auth.u.umts.opc, state->secret_opc, sizeof(auth.u.umts.opc));
|
||||
memset(auth.u.umts.amf, '\0', sizeof(auth.u.umts.amf));
|
||||
auth.u.umts.sqn = 41; /* TODO use incrementing sequence nr */
|
||||
|
||||
memset(&vec, 0, sizeof(vec));
|
||||
osmo_auth_gen_vec(&vec, &auth, rx_random);
|
||||
|
||||
if (vec.res_len != 8) {
|
||||
LOGP(DLOAP, LOGL_ERROR, "OAP: Expected XRES to be 8 octets, got %d\n",
|
||||
vec.res_len);
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (osmo_constant_time_cmp(vec.autn, rx_autn, sizeof(vec.autn)) != 0) {
|
||||
LOGP(DLOAP, LOGL_ERROR, "OAP: AUTN mismatch!\n");
|
||||
LOGP(DLOAP, LOGL_INFO, "OAP: AUTN from server: %s\n",
|
||||
osmo_hexdump_nospc(rx_autn, sizeof(vec.autn)));
|
||||
LOGP(DLOAP, LOGL_INFO, "OAP: AUTN expected: %s\n",
|
||||
osmo_hexdump_nospc(vec.autn, sizeof(vec.autn)));
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (tx_xres != NULL)
|
||||
memcpy(tx_xres, vec.res, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct msgb *osmo_oap_client_encoded(const struct osmo_oap_message *oap_msg)
|
||||
{
|
||||
struct msgb *msg = msgb_alloc_headroom(1000, 64, __func__);
|
||||
OSMO_ASSERT(msg);
|
||||
osmo_oap_encode(msg, oap_msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* Create a new msgb containing an OAP registration message.
|
||||
* On error, return NULL. */
|
||||
static struct msgb* oap_msg_register(uint16_t client_id)
|
||||
{
|
||||
struct osmo_oap_message oap_msg = {0};
|
||||
|
||||
if (client_id < 1) {
|
||||
LOGP(DLOAP, LOGL_ERROR, "OAP: Invalid client ID: %d\n", client_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
oap_msg.message_type = OAP_MSGT_REGISTER_REQUEST;
|
||||
oap_msg.client_id = client_id;
|
||||
return osmo_oap_client_encoded(&oap_msg);
|
||||
}
|
||||
|
||||
int osmo_oap_client_register(struct osmo_oap_client_state *state, struct msgb **msg_tx)
|
||||
{
|
||||
*msg_tx = oap_msg_register(state->client_id);
|
||||
if (!(*msg_tx))
|
||||
return -1;
|
||||
|
||||
state->state = OSMO_OAP_REQUESTED_CHALLENGE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a new msgb containing an OAP challenge response message.
|
||||
* xres must point at 8 octets to return as challenge response.
|
||||
* On error, return NULL. */
|
||||
static struct msgb* oap_msg_challenge_response(uint8_t *xres)
|
||||
{
|
||||
struct osmo_oap_message oap_reply = {0};
|
||||
|
||||
oap_reply.message_type = OAP_MSGT_CHALLENGE_RESULT;
|
||||
memcpy(oap_reply.xres, xres, sizeof(oap_reply.xres));
|
||||
oap_reply.xres_present = 1;
|
||||
return osmo_oap_client_encoded(&oap_reply);
|
||||
}
|
||||
|
||||
static int handle_challenge(struct osmo_oap_client_state *state,
|
||||
struct osmo_oap_message *oap_rx,
|
||||
struct msgb **msg_tx)
|
||||
{
|
||||
int rc;
|
||||
uint8_t xres[8];
|
||||
|
||||
if (!(oap_rx->rand_present && oap_rx->autn_present)) {
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"OAP challenge incomplete (rand_present: %d, autn_present: %d)\n",
|
||||
oap_rx->rand_present, oap_rx->autn_present);
|
||||
rc = -2;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
rc = oap_evaluate_challenge(state,
|
||||
oap_rx->rand,
|
||||
oap_rx->autn,
|
||||
xres);
|
||||
if (rc < 0)
|
||||
goto failure;
|
||||
|
||||
*msg_tx = oap_msg_challenge_response(xres);
|
||||
if ((*msg_tx) == NULL) {
|
||||
rc = -1;
|
||||
goto failure;
|
||||
}
|
||||
|
||||
state->state = OSMO_OAP_SENT_CHALLENGE_RESULT;
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
OSMO_ASSERT(rc < 0);
|
||||
state->state = OSMO_OAP_INITIALIZED;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int osmo_oap_client_handle(struct osmo_oap_client_state *state,
|
||||
const struct msgb *msg_rx, struct msgb **msg_tx)
|
||||
{
|
||||
uint8_t *data = msgb_l2(msg_rx);
|
||||
size_t data_len = msgb_l2len(msg_rx);
|
||||
struct osmo_oap_message oap_msg = {0};
|
||||
int rc = 0;
|
||||
|
||||
*msg_tx = NULL;
|
||||
|
||||
OSMO_ASSERT(data);
|
||||
|
||||
rc = osmo_oap_decode(&oap_msg, data, data_len);
|
||||
if (rc < 0) {
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"Decoding OAP message failed with error '%s' (%d)\n",
|
||||
get_value_string(gsm48_gmm_cause_names, -rc), -rc);
|
||||
return -10;
|
||||
}
|
||||
|
||||
switch (state->state) {
|
||||
case OSMO_OAP_UNINITIALIZED:
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"Received OAP message %d, but the OAP client is"
|
||||
" not initialized\n", oap_msg.message_type);
|
||||
return -ENOTCONN;
|
||||
case OSMO_OAP_DISABLED:
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"Received OAP message %d, but the OAP client is"
|
||||
" disabled\n", oap_msg.message_type);
|
||||
return -ENOTCONN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (oap_msg.message_type) {
|
||||
case OAP_MSGT_CHALLENGE_REQUEST:
|
||||
return handle_challenge(state, &oap_msg, msg_tx);
|
||||
|
||||
case OAP_MSGT_REGISTER_RESULT:
|
||||
/* successfully registered */
|
||||
state->state = OSMO_OAP_REGISTERED;
|
||||
break;
|
||||
|
||||
case OAP_MSGT_REGISTER_ERROR:
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"OAP registration failed\n");
|
||||
state->state = OSMO_OAP_INITIALIZED;
|
||||
if (state->registration_failures < 3) {
|
||||
state->registration_failures++;
|
||||
return osmo_oap_client_register(state, msg_tx);
|
||||
}
|
||||
return -11;
|
||||
|
||||
case OAP_MSGT_REGISTER_REQUEST:
|
||||
case OAP_MSGT_CHALLENGE_RESULT:
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"Received invalid OAP message type for OAP client side: %d\n",
|
||||
(int)oap_msg.message_type);
|
||||
return -12;
|
||||
|
||||
default:
|
||||
LOGP(DLOAP, LOGL_ERROR,
|
||||
"Unknown OAP message type: %d\n",
|
||||
(int)oap_msg.message_type);
|
||||
return -13;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -254,7 +254,9 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd)
|
|||
|
||||
if (osmo_sockaddr_is_local((struct sockaddr *)&ss, ss_len) == 1) {
|
||||
rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM,
|
||||
IPPROTO_UDP, OSMO_SOCK_F_BIND);
|
||||
IPPROTO_UDP,
|
||||
OSMO_SOCK_F_BIND |
|
||||
OSMO_SOCK_F_UDP_REUSEADDR);
|
||||
if (rc >= 0)
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -406,21 +406,24 @@ static void _output(struct log_target *target, unsigned int subsys,
|
|||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
}
|
||||
switch (target->print_filename2) {
|
||||
case LOG_FILENAME_NONE:
|
||||
break;
|
||||
case LOG_FILENAME_PATH:
|
||||
ret = snprintf(buf + offset, rem, "%s:%d ", file, line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
case LOG_FILENAME_BASENAME:
|
||||
ret = snprintf(buf + offset, rem, "%s:%d ", const_basename(file), line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
|
||||
if (target->print_filename_pos == LOG_FILENAME_POS_HEADER_END) {
|
||||
switch (target->print_filename2) {
|
||||
case LOG_FILENAME_NONE:
|
||||
break;
|
||||
case LOG_FILENAME_PATH:
|
||||
ret = snprintf(buf + offset, rem, "%s:%d ", file, line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
case LOG_FILENAME_BASENAME:
|
||||
ret = snprintf(buf + offset, rem, "%s:%d ", const_basename(file), line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = vsnprintf(buf + offset, rem, format, ap);
|
||||
|
@ -428,6 +431,31 @@ static void _output(struct log_target *target, unsigned int subsys,
|
|||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
|
||||
/* For LOG_FILENAME_POS_LAST, print the source file info only when the caller ended the log
|
||||
* message in '\n'. If so, nip the last '\n' away, insert the source file info and re-append an
|
||||
* '\n'. All this to allow LOGP("start..."); LOGPC("...end\n") constructs. */
|
||||
if (target->print_filename_pos == LOG_FILENAME_POS_LINE_END
|
||||
&& offset > 0 && buf[offset-1] == '\n') {
|
||||
switch (target->print_filename2) {
|
||||
case LOG_FILENAME_NONE:
|
||||
break;
|
||||
case LOG_FILENAME_PATH:
|
||||
offset --;
|
||||
ret = snprintf(buf + offset, rem, " (%s:%d)\n", file, line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
case LOG_FILENAME_BASENAME:
|
||||
offset --;
|
||||
ret = snprintf(buf + offset, rem, " (%s:%d)\n", const_basename(file), line);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
OSMO_SNPRINTF_RET(ret, rem, offset, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target->use_color) {
|
||||
ret = snprintf(buf + offset, rem, "\033[0;m");
|
||||
if (ret < 0)
|
||||
|
@ -677,6 +705,17 @@ void log_set_print_filename2(struct log_target *target, enum log_filename_type l
|
|||
target->print_filename2 = lft;
|
||||
}
|
||||
|
||||
/*! Set the position where on a log line the source file info should be logged.
|
||||
* \param[in] target Log target to be affected.
|
||||
* \param[in] pos A LOG_FILENAME_POS_* enum value.
|
||||
* LOG_FILENAME_POS_DEFAULT logs just before the caller supplied log message.
|
||||
* LOG_FILENAME_POS_LAST logs only at the end of a log line, where the caller issued an '\n' to end the
|
||||
*/
|
||||
void log_set_print_filename_pos(struct log_target *target, enum log_filename_pos pos)
|
||||
{
|
||||
target->print_filename_pos = pos;
|
||||
}
|
||||
|
||||
/*! Enable or disable printing of the category name
|
||||
* \param[in] target Log target to be affected
|
||||
* \param[in] print_catname Enable (1) or disable (0) filenames
|
||||
|
@ -759,7 +798,7 @@ struct log_target *log_target_create(void)
|
|||
if (!target)
|
||||
return NULL;
|
||||
|
||||
target->categories = talloc_zero_array(target,
|
||||
target->categories = talloc_zero_array(target,
|
||||
struct log_category,
|
||||
osmo_log_info->num_cat);
|
||||
if (!target->categories) {
|
||||
|
@ -932,7 +971,7 @@ const char *log_vty_command_string()
|
|||
{
|
||||
struct log_info *info = osmo_log_info;
|
||||
int len = 0, offset = 0, ret, i, rem;
|
||||
int size = strlen("logging level () ()") + 1;
|
||||
int size = strlen("logging level (all|) ()") + 1;
|
||||
char *str;
|
||||
|
||||
assert_loginfo(__func__);
|
||||
|
|
|
@ -46,6 +46,15 @@ struct signal_handler {
|
|||
void *data;
|
||||
};
|
||||
|
||||
/*! Initialize a signal_handler talloc context for \ref osmo_signal_register_handler.
|
||||
* Create a talloc context called "osmo_signal".
|
||||
* \param[in] root_ctx talloc context used as parent for the new "osmo_signal" ctx.
|
||||
* \returns the new osmo_signal talloc context, e.g. for reporting
|
||||
*/
|
||||
void *osmo_signal_talloc_ctx_init(void *root_ctx) {
|
||||
tall_sigh_ctx = talloc_named_const(tall_sigh_ctx, 0, "osmo_signal");
|
||||
return tall_sigh_ctx;
|
||||
}
|
||||
|
||||
/*! Register a new signal handler
|
||||
* \param[in] subsys Subsystem number
|
||||
|
|
69
src/socket.c
69
src/socket.c
|
@ -209,16 +209,20 @@ int osmo_sock_init2(uint16_t family, uint16_t type, uint8_t proto,
|
|||
if (sfd < 0)
|
||||
continue;
|
||||
|
||||
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&on, sizeof(on));
|
||||
if (rc < 0) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR,
|
||||
"cannot setsockopt socket:"
|
||||
" %s:%u: %s\n",
|
||||
local_host, local_port, strerror(errno));
|
||||
close(sfd);
|
||||
continue;
|
||||
if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) {
|
||||
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&on, sizeof(on));
|
||||
if (rc < 0) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR,
|
||||
"cannot setsockopt socket:"
|
||||
" %s:%u: %s\n",
|
||||
local_host, local_port,
|
||||
strerror(errno));
|
||||
close(sfd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == -1) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket: %s:%u: %s\n",
|
||||
local_host, local_port, strerror(errno));
|
||||
|
@ -345,15 +349,17 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
|||
continue;
|
||||
}
|
||||
} else {
|
||||
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&on, sizeof(on));
|
||||
if (rc < 0) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR,
|
||||
"cannot setsockopt socket:"
|
||||
" %s:%u: %s\n",
|
||||
host, port, strerror(errno));
|
||||
close(sfd);
|
||||
continue;
|
||||
if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) {
|
||||
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
&on, sizeof(on));
|
||||
if (rc < 0) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR,
|
||||
"cannot setsockopt socket:"
|
||||
" %s:%u: %s\n",
|
||||
host, port, strerror(errno));
|
||||
close(sfd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == -1) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "unable to bind socket:"
|
||||
|
@ -373,7 +379,16 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR) {
|
||||
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (rc < 0) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR,
|
||||
"cannot setsockopt socket: %s:%u: %s\n", host,
|
||||
port, strerror(errno));
|
||||
close(sfd);
|
||||
sfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = osmo_sock_init_tail(sfd, type, flags);
|
||||
if (rc < 0) {
|
||||
|
@ -590,23 +605,29 @@ int osmo_sock_unix_init(uint16_t type, uint8_t proto,
|
|||
struct sockaddr_un local;
|
||||
int sfd, rc, on = 1;
|
||||
unsigned int namelen;
|
||||
const size_t socket_path_len = strlen(socket_path);
|
||||
|
||||
if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) ==
|
||||
(OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT))
|
||||
return -EINVAL;
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strncpy(local.sun_path, socket_path, sizeof(local.sun_path));
|
||||
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
|
||||
if (socket_path_len == sizeof(local.sun_path)) {
|
||||
/* Handle corner-case where sun_path is not NUL-terminated. See the unix(7) man page. */
|
||||
memcpy(local.sun_path, socket_path, sizeof(local.sun_path));
|
||||
} else if (osmo_strlcpy(local.sun_path, socket_path, sizeof(local.sun_path)) >= sizeof(local.sun_path)) {
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "Socket path exceeds maximum length of %zd bytes: %s\n",
|
||||
sizeof(local.sun_path), socket_path);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
|
||||
local.sun_len = strlen(local.sun_path);
|
||||
local.sun_len = socket_path_len;
|
||||
#endif
|
||||
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
|
||||
namelen = SUN_LEN(&local);
|
||||
#else
|
||||
namelen = strlen(local.sun_path) +
|
||||
offsetof(struct sockaddr_un, sun_path);
|
||||
namelen = socket_path_len + offsetof(struct sockaddr_un, sun_path);
|
||||
#endif
|
||||
|
||||
sfd = socket(AF_UNIX, type, proto);
|
||||
|
|
|
@ -68,6 +68,25 @@ struct osmo_stats_reporter *osmo_stats_reporter_create_statsd(const char *name)
|
|||
return srep;
|
||||
}
|
||||
|
||||
/*! Replace all illegal ':' in the stats name, but not when used as value seperator.
|
||||
* ':' is used as seperator between the name and the value in the statsd protocol.
|
||||
* \param[inout] buf is a null terminated string containing name, value, unit. */
|
||||
static void osmo_stats_reporter_sanitize_name(char *buf)
|
||||
{
|
||||
/* e.g. msc.loc_update_type:normal:1|c -> msc.loc_update_type.normal:1|c
|
||||
* last is the seperator between name and value */
|
||||
char *last = strrchr(buf, ':');
|
||||
char *tmp = strchr(buf, ':');
|
||||
|
||||
if (!last)
|
||||
return;
|
||||
|
||||
while (tmp < last) {
|
||||
*tmp = '.';
|
||||
tmp = strchr(buf, ':');
|
||||
}
|
||||
}
|
||||
|
||||
static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep,
|
||||
const char *name1, unsigned int index1, const char *name2, int64_t value,
|
||||
const char *unit)
|
||||
|
@ -134,8 +153,10 @@ static int osmo_stats_reporter_statsd_send(struct osmo_stats_reporter *srep,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (nchars > 0)
|
||||
if (nchars > 0) {
|
||||
osmo_stats_reporter_sanitize_name(buf);
|
||||
msgb_trim(srep->buffer, msgb_length(srep->buffer) + nchars);
|
||||
}
|
||||
|
||||
if (!srep->agg_enabled)
|
||||
rc = osmo_stats_reporter_send_buffer(srep);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# This is _NOT_ the library release version, it's an API version.
|
||||
# Please read chapter "Library interface versions" of the libtool documentation
|
||||
# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html
|
||||
LIBVERSION=4:1:0
|
||||
LIBVERSION=5:0:1
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
|
||||
AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
|
||||
|
|
|
@ -102,7 +102,7 @@ void vty_out_fsm_inst(struct vty *vty, struct osmo_fsm_inst *fsmi)
|
|||
fsmi->proc.parent_term_event),
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
llist_for_each_entry(child, &fsmi->proc.children, list) {
|
||||
llist_for_each_entry(child, &fsmi->proc.children, proc.child) {
|
||||
vty_out(vty, " Child: '%s'%s", child->name, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,12 +246,14 @@ static const struct value_string logging_print_file_args[] = {
|
|||
|
||||
DEFUN(logging_prnt_file,
|
||||
logging_prnt_file_cmd,
|
||||
"logging print file (0|1|basename)",
|
||||
"logging print file (0|1|basename) [last]",
|
||||
LOGGING_STR "Log output settings\n"
|
||||
"Configure log message\n"
|
||||
"Don't prefix each log message\n"
|
||||
"Prefix each log message with the source file and line\n"
|
||||
"Prefix each log message with the source file's basename (strip leading paths) and line\n")
|
||||
"Prefix each log message with the source file's basename (strip leading paths) and line\n"
|
||||
"Log source file info at the end of a log line. If omitted, log source file info just"
|
||||
" before the log text.\n")
|
||||
{
|
||||
struct log_target *tgt = osmo_log_vty2tgt(vty);
|
||||
|
||||
|
@ -259,6 +261,10 @@ DEFUN(logging_prnt_file,
|
|||
return CMD_WARNING;
|
||||
|
||||
log_set_print_filename2(tgt, get_string_value(logging_print_file_args, argv[0]));
|
||||
if (argc > 1)
|
||||
log_set_print_filename_pos(tgt, LOG_FILENAME_POS_LINE_END);
|
||||
else
|
||||
log_set_print_filename_pos(tgt, LOG_FILENAME_POS_HEADER_END);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -814,15 +820,9 @@ static int config_write_log_single(struct vty *vty, struct log_target *tgt)
|
|||
/* stupid old osmo logging API uses uppercase strings... */
|
||||
osmo_str2lower(cat_lower, osmo_log_info->cat[i].name+1);
|
||||
osmo_str2lower(level_lower, log_level_str(cat->loglevel));
|
||||
|
||||
if (strcmp(level_lower, "everything") != 0) /* FIXME: remove this check once 'everything' is phased out */
|
||||
vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE);
|
||||
else
|
||||
LOGP(DLSTATS, LOGL_ERROR, "logging level everything is deprecated and should not be used\n");
|
||||
vty_out(vty, " logging level %s %s%s", cat_lower, level_lower, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
/* FIXME: levels */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -516,12 +516,15 @@ DEFUN(show_stats_asciidoc_table,
|
|||
host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE);
|
||||
/* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table header
|
||||
* as usual text*/
|
||||
vty_out(vty, "=== Rate Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
|
||||
vty_out(vty, "// generating tables for rate_ctr_group%s", VTY_NEWLINE);
|
||||
rate_ctr_for_each_group(asciidoc_rate_ctr_group_handler, vty);
|
||||
|
||||
vty_out(vty, "== Osmo Stat Items%s%s", VTY_NEWLINE, VTY_NEWLINE);
|
||||
vty_out(vty, "// generating tables for osmo_stat_items%s", VTY_NEWLINE);
|
||||
osmo_stat_item_for_each_group(asciidoc_osmo_stat_item_group_handler, vty);
|
||||
|
||||
vty_out(vty, "== Osmo Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
|
||||
vty_out(vty, "// generating tables for osmo_counters%s", VTY_NEWLINE);
|
||||
asciidoc_counter_generate(vty);
|
||||
return CMD_SUCCESS;
|
||||
|
|
|
@ -1694,6 +1694,8 @@ static int vty_config_write(struct vty *vty)
|
|||
/* login */
|
||||
if (!password_check)
|
||||
vty_out(vty, " no login%s", VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " login%s", VTY_NEWLINE);
|
||||
|
||||
/* bind */
|
||||
if (vty_bind_addr && (strcmp(vty_bind_addr, VTY_BIND_ADDR_DEFAULT) != 0))
|
||||
|
@ -1766,8 +1768,6 @@ void vty_init_vtysh(void)
|
|||
vtyvec = vector_init(VECTOR_MIN_SIZE);
|
||||
}
|
||||
|
||||
extern void *tall_bsc_ctx;
|
||||
|
||||
/*! Initialize VTY layer
|
||||
* \param[in] app_info application information
|
||||
*/
|
||||
|
|
|
@ -23,7 +23,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
|
|||
coding/coding_test conv/conv_gsm0503_test \
|
||||
abis/abis_test endian/endian_test sercomm/sercomm_test \
|
||||
prbs/prbs_test gsm23003/gsm23003_test \
|
||||
codec/codec_ecu_fr_test timer/clk_override_test
|
||||
codec/codec_ecu_fr_test timer/clk_override_test \
|
||||
oap/oap_client_test
|
||||
|
||||
if ENABLE_MSGFILE
|
||||
check_PROGRAMS += msgfile/msgfile_test
|
||||
|
@ -172,6 +173,9 @@ gsup_gsup_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
|||
oap_oap_test_SOURCES = oap/oap_test.c
|
||||
oap_oap_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
||||
|
||||
oap_oap_client_test_SOURCES = oap/oap_client_test.c
|
||||
oap_oap_client_test_LDADD = $(LDADD) $(top_builddir)/src/gsm/libosmogsm.la
|
||||
|
||||
fsm_fsm_test_SOURCES = fsm/fsm_test.c
|
||||
fsm_fsm_test_LDADD = $(LDADD) $(top_builddir)/src/ctrl/libosmoctrl.la
|
||||
|
||||
|
@ -253,7 +257,8 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
|
|||
conv/conv_gsm0503_test.ok endian/endian_test.ok \
|
||||
sercomm/sercomm_test.ok prbs/prbs_test.ok \
|
||||
gsm23003/gsm23003_test.ok \
|
||||
timer/clk_override_test.ok
|
||||
timer/clk_override_test.ok \
|
||||
oap/oap_client_test.ok oap/oap_client_test.err
|
||||
|
||||
DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c
|
||||
BUILT_SOURCES = conv/gsm0503_test_vectors.c
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
AM_CPPFLAGS = \
|
||||
$(all_includes) \
|
||||
-I$(top_srcdir)/include \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
-Wall \
|
||||
-ggdb3 \
|
||||
$(LIBOSMOCORE_CFLAGS) \
|
||||
$(LIBOSMOGSM_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
oap_test.ok \
|
||||
$(NULL)
|
||||
|
||||
if HAVE_LIBGTP
|
||||
if HAVE_LIBCARES
|
||||
noinst_PROGRAMS = \
|
||||
oap_test \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
||||
oap_test_SOURCES = \
|
||||
oap_test.c \
|
||||
$(NULL)
|
||||
|
||||
oap_test_LDADD = \
|
||||
$(top_builddir)/src/gprs/oap.o \
|
||||
$(top_builddir)/src/gprs/oap_messages.o \
|
||||
$(top_builddir)/src/gprs/gprs_utils.o \
|
||||
$(top_builddir)/src/libcommon/libcommon.a \
|
||||
$(LIBOSMOCORE_LIBS) \
|
||||
$(LIBOSMOGSM_LIBS) \
|
||||
-lrt
|
||||
|
|
@ -0,0 +1,271 @@
|
|||
/* Test Osmocom Authentication Protocol */
|
||||
/*
|
||||
* (C) 2015 by sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation; either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/gsm/oap.h>
|
||||
|
||||
#include <osmocom/gsm/oap_client.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void test_oap_api(void)
|
||||
{
|
||||
printf("Testing OAP API\n");
|
||||
|
||||
struct osmo_oap_client_config _config;
|
||||
struct osmo_oap_client_config *config = &_config;
|
||||
|
||||
struct osmo_oap_client_state _state;
|
||||
struct osmo_oap_client_state *state = &_state;
|
||||
|
||||
struct osmo_oap_message oap_rx;
|
||||
struct msgb *msg_rx;
|
||||
|
||||
struct osmo_oap_message oap_tx;
|
||||
struct msgb *msg_tx;
|
||||
|
||||
memset(config, 0, sizeof(*config));
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16);
|
||||
OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16);
|
||||
|
||||
fprintf(stderr, "- make sure filling with zeros means uninitialized\n");
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED);
|
||||
|
||||
fprintf(stderr, "- reject messages in uninitialized state\n");
|
||||
memset(&oap_rx, 0, sizeof(oap_rx));
|
||||
state->client_id = 1;
|
||||
oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_UNINITIALIZED);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- NULL config should disable\n");
|
||||
OSMO_ASSERT( osmo_oap_client_init(NULL, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
|
||||
fprintf(stderr, "- reject messages in disabled state\n");
|
||||
memset(state, 0, sizeof(*state));
|
||||
memset(&oap_rx, 0, sizeof(oap_rx));
|
||||
state->state = OSMO_OAP_DISABLED;
|
||||
state->client_id = 1;
|
||||
oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- invalid client_id and shared secret\n");
|
||||
memset(state, 0, sizeof(*state));
|
||||
config->client_id = 0;
|
||||
config->secret_k_present = 0;
|
||||
config->secret_opc_present = 0;
|
||||
OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
|
||||
fprintf(stderr, "- reset state\n");
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
fprintf(stderr, "- only client_id is invalid\n");
|
||||
config->client_id = 0;
|
||||
config->secret_k_present = 1;
|
||||
config->secret_opc_present = 1;
|
||||
OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
fprintf(stderr, "- valid id, but omitted shared_secret (1/2)\n");
|
||||
config->client_id = 12345;
|
||||
config->secret_k_present = 0;
|
||||
config->secret_opc_present = 1;
|
||||
OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
fprintf(stderr, "- valid id, but omitted shared_secret (2/2)\n");
|
||||
config->client_id = 12345;
|
||||
config->secret_k_present = 1;
|
||||
config->secret_opc_present = 0;
|
||||
OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_DISABLED);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
|
||||
fprintf(stderr, "- mint configuration\n");
|
||||
config->client_id = 12345;
|
||||
config->secret_k_present = 1;
|
||||
config->secret_opc_present = 1;
|
||||
/*config->secret_* buffers are still set from the top */
|
||||
OSMO_ASSERT( osmo_oap_client_init(config, state) == 0 );
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED);
|
||||
|
||||
|
||||
fprintf(stderr, "- Missing challenge data\n");
|
||||
memset(&oap_rx, 0, sizeof(oap_rx));
|
||||
oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST;
|
||||
oap_rx.rand_present = 0;
|
||||
oap_rx.autn_present = 0;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- AUTN missing\n");
|
||||
osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
|
||||
oap_rx.rand, 16);
|
||||
oap_rx.rand_present = 1;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- RAND missing\n");
|
||||
oap_rx.rand_present = 0;
|
||||
osmo_hexparse("cec4e3848a33000086781158ca40f136",
|
||||
oap_rx.autn, 16);
|
||||
oap_rx.autn_present = 1;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- wrong autn (by one bit)\n");
|
||||
osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
|
||||
oap_rx.rand, 16);
|
||||
osmo_hexparse("dec4e3848a33000086781158ca40f136",
|
||||
oap_rx.autn, 16);
|
||||
oap_rx.rand_present = 1;
|
||||
oap_rx.autn_present = 1;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -2);
|
||||
msgb_free(msg_rx);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
fprintf(stderr, "- all data correct\n");
|
||||
osmo_hexparse("cec4e3848a33000086781158ca40f136",
|
||||
oap_rx.autn, 16);
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
|
||||
fprintf(stderr, "- but refuse to evaluate in uninitialized state\n");
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED);
|
||||
|
||||
state->state = OSMO_OAP_UNINITIALIZED;
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
state->state = OSMO_OAP_DISABLED;
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) < 0);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
|
||||
state->state = OSMO_OAP_INITIALIZED;
|
||||
|
||||
fprintf(stderr, "- now everything is correct\n");
|
||||
/* a successful return value here indicates correct autn */
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0);
|
||||
msgb_free(msg_rx);
|
||||
|
||||
fprintf(stderr, "- Expect the challenge response in msg_tx\n");
|
||||
OSMO_ASSERT(msg_tx);
|
||||
OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0);
|
||||
OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT);
|
||||
OSMO_ASSERT(strcmp("e2d05b598c61d9ba",
|
||||
osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres)))
|
||||
== 0);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_SENT_CHALLENGE_RESULT);
|
||||
msgb_free(msg_tx);
|
||||
msg_tx = 0;
|
||||
|
||||
struct osmo_oap_client_state saved_state = _state;
|
||||
|
||||
fprintf(stderr, "- Receive registration error for the first time.\n");
|
||||
|
||||
memset(&oap_rx, 0, sizeof(oap_rx));
|
||||
oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
|
||||
oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
|
||||
OSMO_ASSERT(state->registration_failures == 0);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0);
|
||||
OSMO_ASSERT(state->registration_failures == 1);
|
||||
OSMO_ASSERT(msg_tx);
|
||||
OSMO_ASSERT(osmo_oap_decode(&oap_tx, msg_tx->data, msg_tx->len) == 0);
|
||||
OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_REQUESTED_CHALLENGE);
|
||||
msgb_free(msg_tx);
|
||||
msg_tx = 0;
|
||||
|
||||
fprintf(stderr, "- Receive registration error for the Nth time.\n");
|
||||
state->registration_failures = 999;
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == -11);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_INITIALIZED);
|
||||
msgb_free(msg_tx);
|
||||
msg_tx = 0;
|
||||
|
||||
msgb_free(msg_rx);
|
||||
|
||||
fprintf(stderr, "- Registration success\n");
|
||||
|
||||
_state = saved_state;
|
||||
memset(&oap_rx, 0, sizeof(oap_rx));
|
||||
oap_rx.message_type = OAP_MSGT_REGISTER_RESULT;
|
||||
msg_rx = osmo_oap_client_encoded(&oap_rx);
|
||||
OSMO_ASSERT(osmo_oap_client_handle(state, msg_rx, &msg_tx) == 0);
|
||||
OSMO_ASSERT(!msg_tx);
|
||||
OSMO_ASSERT(state->state == OSMO_OAP_REGISTERED);
|
||||
msgb_free(msg_rx);
|
||||
}
|
||||
|
||||
static struct log_info_cat oap_client_test_categories[] = {
|
||||
};
|
||||
|
||||
static struct log_info info = {
|
||||
.cat = oap_client_test_categories,
|
||||
.num_cat = ARRAY_SIZE(oap_client_test_categories),
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *ctx = talloc_named_const(NULL, 0, "oap_client_test");
|
||||
msgb_talloc_ctx_init(ctx, 0);
|
||||
osmo_init_logging2(ctx, &info);
|
||||
|
||||
OSMO_ASSERT(osmo_stderr_target);
|
||||
log_set_use_color(osmo_stderr_target, 0);
|
||||
log_set_print_timestamp(osmo_stderr_target, 0);
|
||||
log_set_print_filename(osmo_stderr_target, 0);
|
||||
log_set_print_category(osmo_stderr_target, 1);
|
||||
log_parse_category_mask(osmo_stderr_target, "DLOAP,1");
|
||||
|
||||
test_oap_api();
|
||||
printf("Done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
- make sure filling with zeros means uninitialized
|
||||
- reject messages in uninitialized state
|
||||
DLOAP Received OAP message 5, but the OAP client is not initialized
|
||||
- NULL config should disable
|
||||
- reject messages in disabled state
|
||||
DLOAP Received OAP message 5, but the OAP client is disabled
|
||||
- invalid client_id and shared secret
|
||||
- reset state
|
||||
- only client_id is invalid
|
||||
- valid id, but omitted shared_secret (1/2)
|
||||
DLOAP OAP: client ID set, but secret K missing.
|
||||
- valid id, but omitted shared_secret (2/2)
|
||||
DLOAP OAP: client ID set, but secret OPC missing.
|
||||
- mint configuration
|
||||
- Missing challenge data
|
||||
DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 0)
|
||||
- AUTN missing
|
||||
DLOAP OAP challenge incomplete (rand_present: 1, autn_present: 0)
|
||||
- RAND missing
|
||||
DLOAP OAP challenge incomplete (rand_present: 0, autn_present: 1)
|
||||
- wrong autn (by one bit)
|
||||
DLOAP OAP: AUTN mismatch!
|
||||
DLOAP OAP: AUTN from server: dec4e3848a33000086781158ca40f136
|
||||
DLOAP OAP: AUTN expected: cec4e3848a33000086781158ca40f136
|
||||
- all data correct
|
||||
- but refuse to evaluate in uninitialized state
|
||||
DLOAP Received OAP message 8, but the OAP client is not initialized
|
||||
DLOAP Received OAP message 8, but the OAP client is disabled
|
||||
- now everything is correct
|
||||
- Expect the challenge response in msg_tx
|
||||
- Receive registration error for the first time.
|
||||
DLOAP OAP registration failed
|
||||
- Receive registration error for the Nth time.
|
||||
DLOAP OAP registration failed
|
||||
- Registration success
|
|
@ -0,0 +1,2 @@
|
|||
Testing OAP API
|
||||
Done
|
|
@ -274,6 +274,13 @@ touch experr
|
|||
AT_CHECK([$abs_top_builddir/tests/oap/oap_test], [0], [expout], [experr])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([oap_client])
|
||||
AT_KEYWORDS([oap_client])
|
||||
cat $abs_srcdir/oap/oap_client_test.ok > expout
|
||||
cat $abs_srcdir/oap/oap_client_test.err > experr
|
||||
AT_CHECK([$abs_top_builddir/tests/oap/oap_client_test], [0], [expout], [experr])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([socket])
|
||||
AT_KEYWORDS([socket])
|
||||
cat $abs_srcdir/socket/socket_test.ok > expout
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#include <osmocom/gsm/ipa.h>
|
||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||
|
||||
#include <osmocom/core/logging.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
@ -170,12 +171,65 @@ static void hexparse_test(void)
|
|||
printf("rc = %d\n", rc);
|
||||
}
|
||||
|
||||
static void test_idtag_parsing(void)
|
||||
static void test_ipa_ccm_id_resp_parsing(void)
|
||||
{
|
||||
struct tlv_parsed tvp;
|
||||
int rc;
|
||||
|
||||
static uint8_t data[] = {
|
||||
static const uint8_t id_resp_data[] = {
|
||||
0x00, 0x13, IPAC_IDTAG_MACADDR,
|
||||
'0','0',':','0','2',':','9','5',':','0','0',':','6','2',':','9','e','\0',
|
||||
0x00, 0x11, IPAC_IDTAG_IPADDR,
|
||||
'1','9','2','.','1','6','8','.','1','0','0','.','1','9','0','\0',
|
||||
0x00, 0x0a, IPAC_IDTAG_UNIT,
|
||||
'1','2','3','4','/','0','/','0','\0',
|
||||
0x00, 0x02, IPAC_IDTAG_LOCATION1,
|
||||
'\0',
|
||||
0x00, 0x0d, IPAC_IDTAG_LOCATION2,
|
||||
'B','T','S','_','N','B','T','1','3','1','G','\0',
|
||||
0x00, 0x0c, IPAC_IDTAG_EQUIPVERS,
|
||||
'1','6','5','a','0','2','9','_','5','5','\0',
|
||||
0x00, 0x14, IPAC_IDTAG_SWVERSION,
|
||||
'1','6','8','d','4','7','2','_','v','2','0','0','b','4','1','1','d','0','\0',
|
||||
0x00, 0x18, IPAC_IDTAG_UNITNAME,
|
||||
'n','b','t','s','-','0','0','-','0','2','-','9','5','-','0','0','-','6','2','-','9','E','\0',
|
||||
0x00, 0x0a, IPAC_IDTAG_SERNR,
|
||||
'0','0','1','1','0','7','8','1','\0'
|
||||
};
|
||||
|
||||
printf("\nTesting IPA CCM ID RESP parsing\n");
|
||||
|
||||
rc = ipa_ccm_id_resp_parse(&tvp, (uint8_t *) id_resp_data, sizeof(id_resp_data));
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_MACADDR));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_MACADDR) == 0x12);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_IPADDR));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_IPADDR) == 0x10);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNIT));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNIT) == 0x09);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION1));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION1) == 0x01);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_LOCATION2));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_LOCATION2) == 0x0c);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_EQUIPVERS));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SWVERSION));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_EQUIPVERS) == 0x0b);
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SWVERSION) == 0x13);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_UNITNAME));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_UNITNAME) == 0x17);
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, IPAC_IDTAG_SERNR));
|
||||
OSMO_ASSERT(TLVP_LEN(&tvp, IPAC_IDTAG_SERNR) == 0x09);
|
||||
}
|
||||
|
||||
static void test_ipa_ccm_id_get_parsing(void)
|
||||
{
|
||||
struct tlv_parsed tvp;
|
||||
int rc;
|
||||
|
||||
/* IPA CCM IDENTITY REQUEST message: 8bit length followed by respective value */
|
||||
static const uint8_t id_get_data[] = {
|
||||
0x01, 0x08,
|
||||
0x01, 0x07,
|
||||
0x01, 0x02,
|
||||
|
@ -188,7 +242,9 @@ static void test_idtag_parsing(void)
|
|||
0x11, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
rc = ipa_ccm_idtag_parse_off(&tvp, data, sizeof(data), 1);
|
||||
printf("\nTesting IPA CCM ID GET parsing\n");
|
||||
|
||||
rc = ipa_ccm_id_get_parse(&tvp, id_get_data, sizeof(id_get_data));
|
||||
OSMO_ASSERT(rc == 0);
|
||||
|
||||
OSMO_ASSERT(TLVP_PRESENT(&tvp, 8));
|
||||
|
@ -567,7 +623,8 @@ int main(int argc, char **argv)
|
|||
|
||||
hexdump_test();
|
||||
hexparse_test();
|
||||
test_idtag_parsing();
|
||||
test_ipa_ccm_id_get_parsing();
|
||||
test_ipa_ccm_id_resp_parsing();
|
||||
test_is_hexstr();
|
||||
bcd_test();
|
||||
str_escape_test();
|
||||
|
|
|
@ -27,6 +27,10 @@ rc = -1
|
|||
Hexparse with invalid char
|
||||
rc = -1
|
||||
|
||||
Testing IPA CCM ID GET parsing
|
||||
|
||||
Testing IPA CCM ID RESP parsing
|
||||
|
||||
----- test_is_hexstr
|
||||
0: pass str='(null)' min=0 max=10 even=0 expect=valid
|
||||
1: pass str='(null)' min=1 max=10 even=0 expect=invalid
|
||||
|
|
|
@ -74,7 +74,8 @@ static int verify_pin(struct osim_chan_hdl *st, uint8_t pin_nr, char *pin)
|
|||
msg = osim_new_apdumsg(0x00, 0x20, 0x00, pin_nr, 8, 0);
|
||||
pindst = (char *) msgb_put(msg, 8);
|
||||
memset(pindst, 0xFF, 8);
|
||||
strncpy(pindst, pin, strlen(pin));
|
||||
/* Do not copy the terminating \0 */
|
||||
memcpy(pindst, pin, strlen(pin));
|
||||
|
||||
return osim_transceive_apdu(st, msg);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue